Skip to content

Commit 582eb2b

Browse files
committed
Initial support of texture options.
1 parent c2474e2 commit 582eb2b

File tree

4 files changed

+237
-17
lines changed

4 files changed

+237
-17
lines changed

loader_example.cc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@ static void PrintInfo(const tinyobj::attrib_t& attrib,
233233
printf(" material.map_Ns = %s\n",
234234
materials[i].specular_highlight_texname.c_str());
235235
printf(" material.map_bump = %s\n", materials[i].bump_texname.c_str());
236+
printf(" bump_multiplier = %f\n", static_cast<const double>(materials[i].bump_texopt.bump_multiplier));
236237
printf(" material.map_d = %s\n", materials[i].alpha_texname.c_str());
237238
printf(" material.disp = %s\n", materials[i].displacement_texname.c_str());
238239
printf(" <<PBR>>\n");
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
newmtl default
2+
Ka 0 0 0
3+
Kd 0 0 0
4+
Ks 0 0 0
5+
Kt 0.1 0.2 0.3
6+
map_Kd -o 0.1 diffuse.jpg
7+
map_Ks -o 0.1 0.2 specular.jpg
8+
map_Ns -o 0.1 0.2 0.3 specular_highlight.jpg
9+
map_bump -bm 3 bumpmap.jpg
10+
11+
newmtl bm2
12+
Ka 0 0 0
13+
Kd 0 0 0
14+
Ks 0 0 0
15+
Kt 0.1 0.2 0.3
16+
# blendu
17+
map_Kd -blendu on diffuse.jpg
18+
map_Ks -blendv off specular.jpg
19+
# -bm after filename
20+
map_bump bumpmap2.jpg -bm 1.5
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
mtllib texture-options-issue-85.mtl
2+
o Test
3+
v 1.864151 -1.219172 -5.532511
4+
v 0.575869 -0.666304 5.896140
5+
v 0.940448 1.000000 -1.971128
6+
usemtl default
7+
f 1 2 3

tiny_obj_loader.h

Lines changed: 209 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,64 @@ THE SOFTWARE.
4343

4444
namespace 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+
46104
typedef 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+
514606
static 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+
604795
static 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

Comments
 (0)