deelan / webgl-loader

Automatically exported from code.google.com/p/webgl-loader
0 stars 0 forks source link

MTL Support Not Complete #32

Open GoogleCodeExporter opened 8 years ago

GoogleCodeExporter commented 8 years ago
Not much of the MTL file is used. Only newmtl, Kd, and map_Kd are supported.

There are numerous other things that can be used in MTL files:

Ka / map_Ka   - ambient color
Ks / map_Ks   - specular color
Ns            - specular color weighting (0 to 1000)
d / Tr        - transparency (0.0 to 1.0)
illum         - illumination model
map_bump / bump
disp
decal
refl

Additionally, the commands that load files (map_*, disp, ...) can take extra 
arguments modifying how those files are used (e.g. -o moves the origin of the 
map).

Original issue reported on code.google.com by j...@coderforlife.com on 1 Mar 2012 at 3:31

GoogleCodeExporter commented 8 years ago
A first step would just to include some of the information in the JSON output 
so that a custom loader could use it. The following code adds support for 
outputting Ka, Ks, Ns, and d (and their maps) which are probably the most 
common. Like your original map code, it will copy the map arguments into the 
output (for the JS library to deal with). The code supports having both Kd and 
map_Kd (which is allowed).

The Material and WavefrontMtlFile classes in mesh.h are the only things that 
need updating:

struct Material {
  std::string name;
  float Ka[3], Kd[3], Ks[3], Ns, d;
  std::string map_Ka, map_Kd, map_Ks, map_Ns, map_d;

  Material() : Ns(HUGE_VALF), d(HUGE_VALF) {
    Ka[0] = HUGE_VALF; Ka[1] = HUGE_VALF; Ka[2] = HUGE_VALF;
    Kd[0] = HUGE_VALF; Kd[1] = HUGE_VALF; Kd[2] = HUGE_VALF;
    Ks[0] = HUGE_VALF; Ks[1] = HUGE_VALF; Ks[2] = HUGE_VALF;
  }

  void DumpJson() const {
    printf("    \'%s\': {\n", name.c_str());
    if (Ka[0] != HUGE_VALF && Ka[1] != HUGE_VALF && Ka[2] != HUGE_VALF) { printf("      Ka: [%hu, %hu, %hu],\n", Quantize(Ka[0], 0, 1, 255), Quantize(Ka[1], 0, 1, 255), Quantize(Ka[2], 0, 1, 255)); }
    if (Kd[0] != HUGE_VALF && Kd[1] != HUGE_VALF && Kd[2] != HUGE_VALF) { printf("      Kd: [%hu, %hu, %hu],\n", Quantize(Kd[0], 0, 1, 255), Quantize(Kd[1], 0, 1, 255), Quantize(Kd[2], 0, 1, 255)); }
    if (Ks[0] != HUGE_VALF && Ks[1] != HUGE_VALF && Ks[2] != HUGE_VALF) { printf("      Ks: [%hu, %hu, %hu],\n", Quantize(Ks[0], 0, 1, 255), Quantize(Ks[1], 0, 1, 255), Quantize(Ks[2], 0, 1, 255)); }
    if (Ns != HUGE_VALF) { printf("      Ns: %f,\n", Ns); }
    if (d  != HUGE_VALF) { printf("      d: %hu,\n", Quantize(d, 0, 1, 255)); }
    if (!map_Ka.empty()) { printf("      map_Ka: \'%s\',\n", map_Ka.c_str()); }
    if (!map_Kd.empty()) { printf("      map_Kd: \'%s\',\n", map_Kd.c_str()); }
    if (!map_Ks.empty()) { printf("      map_Ks: \'%s\',\n", map_Ks.c_str()); }
    if (!map_Ns.empty()) { printf("      map_Ns: \'%s\',\n", map_Ns.c_str()); }
    if (!map_d.empty())  { printf("      map_d: \'%s\',\n",  map_d.c_str()); }
    puts("    },");  // TODO: JSON serialization needs to be better!
  }
};

class WavefrontMtlFile {
 public:
  explicit WavefrontMtlFile(FILE* fp) { ... }
  const MaterialList& materials() const { ... }
 private:
  void ParseFile(FILE* fp) { .. }

  void ParseLine(const char* line, unsigned int line_num) {
    switch (*line) {
      case 'K': ParseColor(line + 1, line_num); break;
      case 'N': if (line[1] == 's') { current_->Ns = strtof(line + 2, NULL); } break;
      case 'd': current_->d = strtof(line + 1, NULL); break;
      case 'T': if (line[1] == 'r') { current_->d = strtof(line + 2, NULL); } break;
      case 'm': if (0 == strncmp(line + 1, "ap_", 3)) { ParseMap(line + 4, line_num); } break;
      case 'n': if (0 == strncmp(line + 1, "ewmtl", 5)) { ParseNewmtl(line + 6, line_num); } 
      default: break;
    }
  }

  void ParseColor(const char* line, unsigned int line_num) {
    float* out = NULL;
    switch (*line) {
      case 'a': out = current_->Ka; break;
      case 'd': out = current_->Kd; break;
      case 's': out = current_->Ks; break;
      default: break;
    }
    if (out) {
        ShortFloatList floats;
        floats.ParseLine(line + 1);
        out[0] = floats[0];
        out[1] = floats[1];
        out[2] = floats[2];
    }
  }

  void ParseMap(const char* line, unsigned int line_num) {
    std::string* out = NULL;
    switch (*line) {
      case 'K':
        switch (line[1]) {
          case 'a': out = ¤t_->map_Ka; break;
          case 'd': out = ¤t_->map_Kd; break;
          case 's': out = ¤t_->map_Ks; break;
          default: break;
        }
        break;
      case 'N': if (line[1] == 's') { out = ¤t_->map_Ns; } break;
      case 'd': line -= 1; out = ¤t_->map_d; break;
      case 'T': if (line[1] == 'r') { out = ¤t_->map_d; } break;
      default: break;
    }
    if (out) {
        *out = StripLeadingWhitespace(line + 1);
    }
  }

  void ParseNewmtl(const char* line, unsigned int line_num) { ... }
  Material* current_;
  MaterialList materials_;
};

Original comment by j...@coderforlife.com on 1 Mar 2012 at 10:35

GoogleCodeExporter commented 8 years ago
Awesome! I'll definitely take a look at this change and fold it into some 
planned improvements.

Original comment by wonchun on 4 Apr 2012 at 2:35

GoogleCodeExporter commented 8 years ago
Is this added? I need it badly, thanks.

Original comment by DakeF...@gmail.com on 5 Aug 2012 at 5:06