@@ -43,6 +43,64 @@ THE SOFTWARE.
4343
4444namespace tinyobj {
4545
46+ // https://en.wikipedia.org/wiki/Wavefront_.obj_file says ...
47+ //
48+ // -blendu on | off # set horizontal texture blending (default on)
49+ // -blendv on | off # set vertical texture blending (default on)
50+ // -boost float_value # boost mip-map sharpness
51+ // -mm base_value gain_value # modify texture map values (default 0 1)
52+ // # base_value = brightness, gain_value = contrast
53+ // -o u [v [w]] # Origin offset (default 0 0 0)
54+ // -s u [v [w]] # Scale (default 1 1 1)
55+ // -t u [v [w]] # Turbulence (default 0 0 0)
56+ // -texres resolution # texture resolution to create
57+ // -clamp on | off # only render texels in the clamped 0-1 range (default off)
58+ // # When unclamped, textures are repeated across a surface,
59+ // # when clamped, only texels which fall within the 0-1
60+ // # range are rendered.
61+ // -bm mult_value # bump multiplier (for bump maps only)
62+ //
63+ // -imfchan r | g | b | m | l | z # specifies which channel of the file is used to
64+ // # create a scalar or bump texture. r:red, g:green,
65+ // # b:blue, m:matte, l:luminance, z:z-depth..
66+ // # (the default for bump is 'l' and for decal is 'm')
67+ // bump -imfchan r bumpmap.tga # says to use the red channel of bumpmap.tga as the bumpmap
68+ //
69+ // For reflection maps...
70+ //
71+ // -type sphere # specifies a sphere for a "refl" reflection map
72+ // -type cube_top | cube_bottom | # when using a cube map, the texture file for each
73+ // cube_front | cube_back | # side of the cube is specified separately
74+ // cube_left | cube_right
75+
76+
77+ typedef enum {
78+ TEXTURE_TYPE_NONE, // default
79+ TEXTURE_TYPE_SPHERE,
80+ TEXTURE_TYPE_CUBE_TOP,
81+ TEXTURE_TYPE_CUBE_BOTTOM,
82+ TEXTURE_TYPE_CUBE_FRONT,
83+ TEXTURE_TYPE_CUBE_BACK,
84+ TEXTURE_TYPE_CUBE_LEFT,
85+ TEXTURE_TYPE_CUBE_RIGHT
86+ } texture_type_t ;
87+
88+ typedef struct {
89+ texture_type_t type; // -type (default TEXTURE_TYPE_NONE)
90+ float sharpness; // -boost (default 1.0?)
91+ float brightness; // base_value in -mm option (default 0)
92+ float contrast; // gain_value in -mm option (default 1)
93+ float origin_offset[3 ]; // -o u [v [w]] (default 0 0 0)
94+ float scale[3 ]; // -s u [v [w]] (default 1 1 1)
95+ float turbulence[3 ]; // -t u [v [w]] (default 0 0 0)
96+ // int texture_resolution; // -texres resolution (default = ?) TODO
97+ bool clamp; // -clamp (default false)
98+ char imfchan; // -imfchan (the default for bump is 'l' and for decal is 'm')
99+ bool blendu; // -blendu (default on)
100+ bool blendv; // -blendv (default on)
101+ float bump_multiplier; // -bm (for bump maps only, default 1.0)
102+ } texture_option_t ;
103+
46104typedef struct {
47105 std::string name;
48106
@@ -67,6 +125,14 @@ typedef struct {
67125 std::string displacement_texname; // disp
68126 std::string alpha_texname; // map_d
69127
128+ texture_option_t ambient_texopt;
129+ texture_option_t diffuse_texopt;
130+ texture_option_t specular_texopt;
131+ texture_option_t specular_highlight_texopt;
132+ texture_option_t bump_texopt;
133+ texture_option_t displacement_texopt;
134+ texture_option_t alpha_texopt;
135+
70136 // PBR extension
71137 // http://exocortex.com/blog/extending_wavefront_mtl_to_support_pbr
72138 float roughness; // [0, 1] default 0
@@ -77,12 +143,21 @@ typedef struct {
77143 float anisotropy; // aniso. [0, 1] default 0
78144 float anisotropy_rotation; // anisor. [0, 1] default 0
79145 float pad0;
146+ float pad1;
80147 std::string roughness_texname; // map_Pr
81148 std::string metallic_texname; // map_Pm
82149 std::string sheen_texname; // map_Ps
83150 std::string emissive_texname; // map_Ke
84151 std::string normal_texname; // norm. For normal mapping.
85152
153+ texture_option_t roughness_texopt;
154+ texture_option_t metallic_texopt;
155+ texture_option_t sheen_texopt;
156+ texture_option_t emissive_texopt;
157+ texture_option_t normal_texopt;
158+
159+ int pad2;
160+
86161 std::map<std::string, std::string> unknown_parameter;
87162} material_t ;
88163
@@ -511,6 +586,23 @@ static inline void parseV(float *x, float *y, float *z, float *w,
511586 (*w) = parseFloat (token, 1.0 );
512587}
513588
589+ static inline bool parseOnOff (const char **token, bool default_value = true ) {
590+ (*token) += strspn ((*token), " \t " );
591+ const char *end = (*token) + strcspn ((*token), " \t\r " );
592+
593+ printf (" token = %s\n " , (*token));
594+ bool ret = default_value;
595+ if ((0 == strncmp ((*token), " on" , 2 ))) {
596+ ret = true ;
597+ } else if ((0 == strncmp ((*token), " off" , 3 ))) {
598+ printf (" off\n " );
599+ ret = false ;
600+ }
601+
602+ (*token) = end;
603+ return ret;
604+ }
605+
514606static tag_sizes parseTagTriple (const char **token) {
515607 tag_sizes ts;
516608
@@ -601,6 +693,105 @@ static vertex_index parseRawTriple(const char **token) {
601693 return vi;
602694}
603695
696+ static bool ParseTextureNameAndOption (std::string* texname, texture_option_t *texopt, const char * linebuf, const bool is_bump)
697+ {
698+ // @todo { write more robust lexer and parser. }
699+ bool found_texname = false ;
700+ std::string texture_name;
701+
702+ // Fill with default value for texopt.
703+ if (is_bump) {
704+ texopt->imfchan = ' l' ;
705+ } else {
706+ texopt->imfchan = ' m' ;
707+ }
708+ texopt->bump_multiplier = 1 .0f ;
709+ texopt->clamp = false ;
710+ texopt->blendu = true ;
711+ texopt->blendv = true ;
712+ texopt->sharpness = 1 .0f ;
713+ texopt->brightness = 0 .0f ;
714+ texopt->contrast = 1 .0f ;
715+ texopt->origin_offset [0 ] = 0 .0f ;
716+ texopt->origin_offset [1 ] = 0 .0f ;
717+ texopt->origin_offset [2 ] = 0 .0f ;
718+ texopt->scale [0 ] = 1 .0f ;
719+ texopt->scale [1 ] = 1 .0f ;
720+ texopt->scale [2 ] = 1 .0f ;
721+ texopt->turbulence [0 ] = 0 .0f ;
722+ texopt->turbulence [1 ] = 0 .0f ;
723+ texopt->turbulence [2 ] = 0 .0f ;
724+ texopt->type = TEXTURE_TYPE_NONE;
725+
726+ const char *token = linebuf; // Assume line ends with NULL
727+
728+ // @todo { -mm, -type, -imfchan }
729+ while (!IS_NEW_LINE ((*token))) {
730+ if ((0 == strncmp (token, " -blendu" , 7 )) && IS_SPACE ((token[7 ]))) {
731+ token += 8 ;
732+ texopt->blendu = parseOnOff (&token, /* default */ true );
733+ printf (" blendu = %d\n " , texopt->blendu );
734+ } else if ((0 == strncmp (token, " -blendv" , 7 )) && IS_SPACE ((token[7 ]))) {
735+ token += 8 ;
736+ texopt->blendv = parseOnOff (&token, /* default */ true );
737+ printf (" blendv = %d\n " , texopt->blendv );
738+ } else if ((0 == strncmp (token, " -clamp" , 6 )) && IS_SPACE ((token[6 ]))) {
739+ token += 7 ;
740+ texopt->clamp = parseOnOff (&token, /* default */ true );
741+ printf (" clamp= %d\n " , texopt->clamp );
742+ } else if ((0 == strncmp (token, " -boost" , 6 )) && IS_SPACE ((token[6 ]))) {
743+ token += 7 ;
744+ texopt->sharpness = parseFloat (&token, 1.0 );
745+ printf (" boost = %f\n " , static_cast <double >(texopt->sharpness ));
746+ } else if ((0 == strncmp (token, " -bm" , 3 )) && IS_SPACE ((token[3 ]))) {
747+ token += 4 ;
748+ texopt->bump_multiplier = parseFloat (&token, 1.0 );
749+ printf (" bm %f\n " , static_cast <double >(texopt->bump_multiplier ));
750+ } else if ((0 == strncmp (token, " -o" , 2 )) && IS_SPACE ((token[2 ]))) {
751+ token += 3 ;
752+ parseFloat3 (&(texopt->origin_offset [0 ]), &(texopt->origin_offset [1 ]), &(texopt->origin_offset [2 ]), &token);
753+ printf (" o %f, %f, %f\n " ,
754+ static_cast <double >(texopt->origin_offset [0 ]),
755+ static_cast <double >(texopt->origin_offset [1 ]),
756+ static_cast <double >(texopt->origin_offset [2 ]));
757+ } else if ((0 == strncmp (token, " -s" , 2 )) && IS_SPACE ((token[2 ]))) {
758+ token += 3 ;
759+ parseFloat3 (&(texopt->scale [0 ]), &(texopt->scale [1 ]), &(texopt->scale [2 ]), &token);
760+ printf (" s %f, %f, %f\n " ,
761+ static_cast <double >(texopt->scale [0 ]),
762+ static_cast <double >(texopt->scale [1 ]),
763+ static_cast <double >(texopt->scale [2 ]));
764+ } else if ((0 == strncmp (token, " -t" , 2 )) && IS_SPACE ((token[2 ]))) {
765+ token += 3 ;
766+ parseFloat3 (&(texopt->turbulence [0 ]), &(texopt->turbulence [1 ]), &(texopt->turbulence [2 ]), &token);
767+ printf (" t %f, %f, %f\n " ,
768+ static_cast <double >(texopt->turbulence [0 ]),
769+ static_cast <double >(texopt->turbulence [1 ]),
770+ static_cast <double >(texopt->turbulence [2 ]));
771+ } else {
772+ // Assume texture filename
773+ token += strspn (token, " \t " ); // skip space
774+ size_t len = strcspn (token, " \t\r " ); // untile next space
775+ texture_name = std::string (token, token + len);
776+ printf (" texname = [%s]\n " , texture_name.c_str ());
777+ token += len;
778+
779+ token += strspn (token, " \t " ); // skip space
780+
781+ found_texname = true ;
782+ }
783+ }
784+
785+ if (found_texname) {
786+ (*texname) = texture_name;
787+ return true ;
788+ } else {
789+ return false ;
790+ }
791+ }
792+
793+
794+
604795static void InitMaterial (material_t *material) {
605796 material->name = " " ;
606797 material->ambient_texname = " " ;
@@ -913,84 +1104,85 @@ void LoadMtl(std::map<std::string, int> *material_map,
9131104 // diffuse texture
9141105 if ((0 == strncmp (token, " map_Kd" , 6 )) && IS_SPACE (token[6 ])) {
9151106 token += 7 ;
916- material.diffuse_texname = token;
1107+ ParseTextureNameAndOption (&( material.diffuse_texname ), &(material. diffuse_texopt ), token, /* is_bump */ false ) ;
9171108 continue ;
9181109 }
9191110
9201111 // specular texture
9211112 if ((0 == strncmp (token, " map_Ks" , 6 )) && IS_SPACE (token[6 ])) {
9221113 token += 7 ;
923- material.specular_texname = token;
1114+ ParseTextureNameAndOption (&( material.specular_texname ), &(material. specular_texopt ), token, /* is_bump */ false ) ;
9241115 continue ;
9251116 }
9261117
9271118 // specular highlight texture
9281119 if ((0 == strncmp (token, " map_Ns" , 6 )) && IS_SPACE (token[6 ])) {
9291120 token += 7 ;
930- material.specular_highlight_texname = token;
1121+ ParseTextureNameAndOption (&( material.specular_highlight_texname ), &(material. specular_highlight_texopt ), token, /* is_bump */ false ) ;
9311122 continue ;
9321123 }
9331124
9341125 // bump texture
9351126 if ((0 == strncmp (token, " map_bump" , 8 )) && IS_SPACE (token[8 ])) {
9361127 token += 9 ;
937- material.bump_texname = token;
1128+ ParseTextureNameAndOption (&(material.bump_texname ), &(material.bump_texopt ), token, /* is_bump */ true );
1129+ continue ;
1130+ }
1131+
1132+ // bump texture
1133+ if ((0 == strncmp (token, " bump" , 4 )) && IS_SPACE (token[4 ])) {
1134+ token += 5 ;
1135+ ParseTextureNameAndOption (&(material.bump_texname ), &(material.bump_texopt ), token, /* is_bump */ true );
9381136 continue ;
9391137 }
9401138
9411139 // alpha texture
9421140 if ((0 == strncmp (token, " map_d" , 5 )) && IS_SPACE (token[5 ])) {
9431141 token += 6 ;
9441142 material.alpha_texname = token;
945- continue ;
946- }
947-
948- // bump texture
949- if ((0 == strncmp (token, " bump" , 4 )) && IS_SPACE (token[4 ])) {
950- token += 5 ;
951- material.bump_texname = token;
1143+ ParseTextureNameAndOption (&(material.alpha_texname ), &(material.alpha_texopt ), token, /* is_bump */ false );
9521144 continue ;
9531145 }
9541146
9551147 // displacement texture
9561148 if ((0 == strncmp (token, " disp" , 4 )) && IS_SPACE (token[4 ])) {
9571149 token += 5 ;
958- material.displacement_texname = token;
1150+ ParseTextureNameAndOption (&( material.displacement_texname ), &(material. displacement_texopt ), token, /* is_bump */ false ) ;
9591151 continue ;
9601152 }
9611153
9621154 // PBR: roughness texture
9631155 if ((0 == strncmp (token, " map_Pr" , 6 )) && IS_SPACE (token[6 ])) {
9641156 token += 7 ;
965- material.roughness_texname = token;
1157+ ParseTextureNameAndOption (&( material.roughness_texname ), &(material. roughness_texopt ), token, /* is_bump */ false ) ;
9661158 continue ;
9671159 }
9681160
9691161 // PBR: metallic texture
9701162 if ((0 == strncmp (token, " map_Pm" , 6 )) && IS_SPACE (token[6 ])) {
9711163 token += 7 ;
972- material.metallic_texname = token;
1164+ ParseTextureNameAndOption (&( material.metallic_texname ), &(material. metallic_texopt ), token, /* is_bump */ false ) ;
9731165 continue ;
9741166 }
9751167
9761168 // PBR: sheen texture
9771169 if ((0 == strncmp (token, " map_Ps" , 6 )) && IS_SPACE (token[6 ])) {
9781170 token += 7 ;
979- material.sheen_texname = token;
1171+ ParseTextureNameAndOption (&( material.sheen_texname ), &(material. sheen_texopt ), token, /* is_bump */ false ) ;
9801172 continue ;
9811173 }
9821174
9831175 // PBR: emissive texture
9841176 if ((0 == strncmp (token, " map_Ke" , 6 )) && IS_SPACE (token[6 ])) {
9851177 token += 7 ;
986- material.emissive_texname = token;
1178+ ParseTextureNameAndOption (&( material.emissive_texname ), &(material. emissive_texopt ), token, /* is_bump */ false ) ;
9871179 continue ;
9881180 }
9891181
9901182 // PBR: normal map texture
9911183 if ((0 == strncmp (token, " norm" , 4 )) && IS_SPACE (token[4 ])) {
9921184 token += 5 ;
993- material.normal_texname = token;
1185+ ParseTextureNameAndOption (&( material.normal_texname ), &(material. normal_texopt ), token, /* is_bump */ false ); // @fixme { is_bump will be true? }
9941186 continue ;
9951187 }
9961188
0 commit comments