11 Commits

Author SHA1 Message Date
Syoyo Fujita
a957ebe002 Fix some coments.
Bump version 1.4.0
2018-12-01 13:32:05 +09:00
Syoyo Fujita
d793bfb405 Merge pull request #191 from sinisterchipmunk/initialize_unparsed_texopts
Properly initialize all texture_option_t's, not just parsed ones
2018-12-01 13:25:41 +09:00
Colin MacKenzie IV
0ab0146296 Update function declaration 2018-11-30 15:27:38 -05:00
Colin MacKenzie IV
20d122f305 Properly initialize all texture_option_t's, not just parsed ones 2018-11-30 15:14:07 -05:00
Syoyo Fujita
850d0ffdfa Merge pull request #190 from ukabuer/patch-1
Update README.md
2018-11-30 21:29:21 +09:00
UKABUER
80058fdcb0 Update README.md 2018-11-30 20:24:14 +08:00
Syoyo Fujita
1a7aea4ac1 Merge pull request #189 from mathue/patch-1
Fix of important memory leak in Python module
2018-11-29 01:31:03 +09:00
Martin Thümmel
178ef391c7 Fix of important memory leak in Python module
Dear all,
As described in the issue https://github.com/syoyo/tinyobjloader/issues/188#issue-385341218 there is a memory leak in the function pyLoadObj(). The reference count for all created Python objects must be decreased after they are fed into the lists and dictionaries. The only  exception from this is the function PyTuple_SetItem() in pyTupleFromfloat3(), which decreases the reference counter of the Python object *tuple automatically by calling this function. In all other cases like PyList_Insert(), the references are only borrowed and not decreased. Therefore, each created Python object will remain in the heap, since there is one reference to it left in the counter.

These facts are explained in https://docs.python.org/2/c-api/intro.html#reference-counts in detail.

Best regards
Martin.
P.S. sorry, that i did not put that much effort into a more readable code and just inserted the Py_DECREF() function at every necessary position.
2018-11-28 17:16:12 +01:00
Syoyo Fujita
59b4d7ccef Merge pull request #187 from Neptilo/master
Fix parsing double with negative exponent
2018-11-06 00:28:10 +09:00
Victor Ripplinger
6f990e2b6c Fix parsing double with negative exponent 2018-11-05 15:17:34 +01:00
Syoyo Fujita
7fb5056a53 Make ParseTextureNameAndOption function public. 2018-10-19 15:29:31 +09:00
5 changed files with 214 additions and 158 deletions

View File

@@ -205,8 +205,9 @@ tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials; std::vector<tinyobj::material_t> materials;
std::string warn;
std::string err; std::string err;
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &err, inputfile.c_str()); bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, inputfile.c_str());
if (!err.empty()) { // `err` may contain warning message. if (!err.empty()) { // `err` may contain warning message.
std::cerr << err << std::endl; std::cerr << err << std::endl;

View File

@@ -605,19 +605,9 @@ static bool tryParseDouble(const char *s, const char *s_end, double *result) {
} }
assemble : assemble :
*result = (sign == '+' ? 1 : -1) *
{ (exponent ? std::ldexp(mantissa * std::pow(5.0, exponent), exponent)
// = pow(5.0, exponent); : mantissa);
double a = 1.0;
for (int i = 0; i < exponent; i++) {
a = a * 5.0;
}
*result =
//(sign == '+' ? 1 : -1) * ldexp(mantissa * pow(5.0, exponent), exponent);
(sign == '+' ? 1 : -1) * (mantissa * a) *
static_cast<double>(1ULL << exponent); // 5.0^exponent * 2^exponent
}
return true; return true;
fail: fail:
return false; return false;

View File

@@ -18,11 +18,9 @@ typedef std::vector<int> vecti;
PyObject* pyTupleFromfloat3(float array[3]) { PyObject* pyTupleFromfloat3(float array[3]) {
int i; int i;
PyObject* tuple = PyTuple_New(3); PyObject* tuple = PyTuple_New(3);
for (i = 0; i <= 2; i++) { for (i = 0; i <= 2; i++) {
PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i])); PyTuple_SetItem(tuple, i, PyFloat_FromDouble(array[i]));
} }
return tuple; return tuple;
} }
@@ -30,32 +28,27 @@ extern "C" {
static PyObject* pyLoadObj(PyObject* self, PyObject* args) { static PyObject* pyLoadObj(PyObject* self, PyObject* args) {
PyObject *rtndict, *pyshapes, *pymaterials, *pymaterial_indices, *attribobj, *current, *meshobj; PyObject *rtndict, *pyshapes, *pymaterials, *pymaterial_indices, *attribobj, *current, *meshobj;
char const* current_name; char const* current_name;
char const* filename; char const* filename;
vectd vect; vectd vect;
std::vector<tinyobj::index_t> indices; std::vector<tinyobj::index_t> indices;
std::vector<unsigned char> face_verts; std::vector<unsigned char> face_verts;
tinyobj::attrib_t attrib; tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials; std::vector<tinyobj::material_t> materials;
if (!PyArg_ParseTuple(args, "s", &filename)) return NULL; if (!PyArg_ParseTuple(args, "s", &filename)) return NULL;
std::string err; std::string err, warn;
tinyobj::LoadObj(&attrib, &shapes, &materials, &err, filename); tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err, filename);
pyshapes = PyDict_New(); pyshapes = PyDict_New();
pymaterials = PyDict_New(); pymaterials = PyDict_New();
pymaterial_indices = PyList_New(0); pymaterial_indices = PyList_New(0);
rtndict = PyDict_New(); rtndict = PyDict_New();
attribobj = PyDict_New(); attribobj = PyDict_New();
for (int i = 0; i <= 2; i++) { for (int i = 0; i <= 2; i++) {
current = PyList_New(0); current = PyList_New(0);
switch (i) { switch (i) {
case 0: case 0:
current_name = "vertices"; current_name = "vertices";
@@ -72,124 +65,137 @@ static PyObject* pyLoadObj(PyObject* self, PyObject* args) {
} }
for (vectd::iterator it = vect.begin(); it != vect.end(); it++) { for (vectd::iterator it = vect.begin(); it != vect.end(); it++) {
PyList_Insert(current, it - vect.begin(), PyFloat_FromDouble(*it)); PyObject* value = PyFloat_FromDouble(*it);
PyList_Insert(current, it - vect.begin(), value);
Py_DECREF(value);
} }
PyDict_SetItemString(attribobj, current_name, current); PyDict_SetItemString(attribobj, current_name, current);
Py_DECREF(current);
} }
for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin(); for (std::vector<tinyobj::shape_t>::iterator shape = shapes.begin(); shape != shapes.end(); shape++) {
shape != shapes.end(); shape++) {
meshobj = PyDict_New(); meshobj = PyDict_New();
tinyobj::mesh_t cm = (*shape).mesh; tinyobj::mesh_t cm = (*shape).mesh;
{ {
current = PyList_New(0); current = PyList_New(0);
for (size_t i = 0; i < cm.indices.size(); i++) { for (size_t i = 0; i < cm.indices.size(); i++) {
// Flatten index array: v_idx, vn_idx, vt_idx, v_idx, vn_idx, vt_idx, // Flatten index array: v_idx, vn_idx, vt_idx, v_idx, vn_idx, vt_idx,
// ... PyObject* value = PyLong_FromLong(cm.indices[i].vertex_index);
PyList_Insert(current, 3 * i + 0, PyList_Insert(current, 3 * i + 0, value);
PyLong_FromLong(cm.indices[i].vertex_index)); Py_DECREF(value);
PyList_Insert(current, 3 * i + 1, value = PyLong_FromLong(cm.indices[i].normal_index);
PyLong_FromLong(cm.indices[i].normal_index)); PyList_Insert(current, 3 * i + 1, value);
PyList_Insert(current, 3 * i + 2, Py_DECREF(value);
PyLong_FromLong(cm.indices[i].texcoord_index)); value = PyLong_FromLong(cm.indices[i].texcoord_index);
PyList_Insert(current, 3 * i + 2, value);
Py_DECREF(value);
} }
PyDict_SetItemString(meshobj, "indices", current); PyDict_SetItemString(meshobj, "indices", current);
Py_DECREF(current);
} }
{ {
current = PyList_New(0); current = PyList_New(0);
for (size_t i = 0; i < cm.num_face_vertices.size(); i++) { for (size_t i = 0; i < cm.num_face_vertices.size(); i++) {
// Widen data type to long. // Widen data type to long.
PyList_Insert(current, i, PyLong_FromLong(cm.num_face_vertices[i])); PyObject* value = PyLong_FromLong(cm.num_face_vertices[i]);
PyList_Insert(current, i, value);
Py_DECREF(value);
} }
PyDict_SetItemString(meshobj, "num_face_vertices", current); PyDict_SetItemString(meshobj, "num_face_vertices", current);
Py_DECREF(current);
} }
{ {
current = PyList_New(0); current = PyList_New(0);
for (size_t i = 0; i < cm.material_ids.size(); i++) { for (size_t i = 0; i < cm.material_ids.size(); i++) {
PyList_Insert(current, i, PyLong_FromLong(cm.material_ids[i])); PyObject* value = PyLong_FromLong(cm.material_ids[i]);
PyList_Insert(current, i, value);
Py_DECREF(value);
} }
PyDict_SetItemString(meshobj, "material_ids", current); PyDict_SetItemString(meshobj, "material_ids", current);
Py_DECREF(current);
} }
PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj); PyDict_SetItemString(pyshapes, (*shape).name.c_str(), meshobj);
Py_DECREF(meshobj);
} }
for (std::vector<tinyobj::material_t>::iterator mat = materials.begin(); for (std::vector<tinyobj::material_t>::iterator mat = materials.begin(); mat != materials.end(); mat++) {
mat != materials.end(); mat++) {
PyObject* matobj = PyDict_New(); PyObject* matobj = PyDict_New();
PyObject* unknown_parameter = PyDict_New(); PyObject* unknown_parameter = PyDict_New();
for (std::map<std::string, std::string>::iterator p = for (std::map<std::string, std::string>::iterator p = mat->unknown_parameter.begin(); p != mat->unknown_parameter.end(); ++p) {
mat->unknown_parameter.begin(); PyObject* value = PyUnicode_FromString(p->second.c_str());
p != mat->unknown_parameter.end(); ++p) { PyDict_SetItemString(unknown_parameter, p->first.c_str(), value);
PyDict_SetItemString(unknown_parameter, p->first.c_str(), Py_DECREF(value);
PyUnicode_FromString(p->second.c_str()));
} }
PyDict_SetItemString(matobj, "shininess", PyObject* value = PyFloat_FromDouble(mat->shininess);
PyFloat_FromDouble(mat->shininess)); PyDict_SetItemString(matobj, "shininess", value);
PyDict_SetItemString(matobj, "ior", PyFloat_FromDouble(mat->ior)); Py_DECREF(value);
PyDict_SetItemString(matobj, "dissolve", value = PyFloat_FromDouble(mat->ior);
PyFloat_FromDouble(mat->dissolve)); PyDict_SetItemString(matobj, "ior", value);
PyDict_SetItemString(matobj, "illum", PyLong_FromLong(mat->illum)); Py_DECREF(value);
PyDict_SetItemString(matobj, "ambient_texname", value = PyFloat_FromDouble(mat->dissolve);
PyUnicode_FromString(mat->ambient_texname.c_str())); PyDict_SetItemString(matobj, "dissolve", value);
PyDict_SetItemString(matobj, "diffuse_texname", Py_DECREF(value);
PyUnicode_FromString(mat->diffuse_texname.c_str())); value = PyLong_FromLong(mat->illum);
PyDict_SetItemString(matobj, "specular_texname", PyDict_SetItemString(matobj, "illum", value);
PyUnicode_FromString(mat->specular_texname.c_str())); Py_DECREF(value);
PyDict_SetItemString( value = PyUnicode_FromString(mat->ambient_texname.c_str());
matobj, "specular_highlight_texname", PyDict_SetItemString(matobj, "ambient_texname", value);
PyUnicode_FromString(mat->specular_highlight_texname.c_str())); Py_DECREF(value);
PyDict_SetItemString(matobj, "bump_texname", value = PyUnicode_FromString(mat->diffuse_texname.c_str());
PyUnicode_FromString(mat->bump_texname.c_str())); PyDict_SetItemString(matobj, "diffuse_texname", value);
PyDict_SetItemString( Py_DECREF(value);
matobj, "displacement_texname", value = PyUnicode_FromString(mat->specular_texname.c_str());
PyUnicode_FromString(mat->displacement_texname.c_str())); PyDict_SetItemString(matobj, "specular_texname", value);
PyDict_SetItemString(matobj, "alpha_texname", Py_DECREF(value);
PyUnicode_FromString(mat->alpha_texname.c_str())); value = PyUnicode_FromString(mat->specular_highlight_texname.c_str());
PyDict_SetItemString(matobj, "specular_highlight_texname", value);
Py_DECREF(value);
value = PyUnicode_FromString(mat->bump_texname.c_str());
PyDict_SetItemString(matobj, "bump_texname", value);
Py_DECREF(value);
value = PyUnicode_FromString(mat->displacement_texname.c_str());
PyDict_SetItemString(matobj, "displacement_texname", value);
Py_DECREF(value);
value = PyUnicode_FromString(mat->alpha_texname.c_str());
PyDict_SetItemString(matobj, "alpha_texname", value);
Py_DECREF(value);
PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3(mat->ambient)); PyDict_SetItemString(matobj, "ambient", pyTupleFromfloat3(mat->ambient));
PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3(mat->diffuse)); PyDict_SetItemString(matobj, "diffuse", pyTupleFromfloat3(mat->diffuse));
PyDict_SetItemString(matobj, "specular", PyDict_SetItemString(matobj, "specular", pyTupleFromfloat3(mat->specular));
pyTupleFromfloat3(mat->specular)); PyDict_SetItemString(matobj, "transmittance", pyTupleFromfloat3(mat->transmittance));
PyDict_SetItemString(matobj, "transmittance", PyDict_SetItemString(matobj, "emission", pyTupleFromfloat3(mat->emission));
pyTupleFromfloat3(mat->transmittance));
PyDict_SetItemString(matobj, "emission",
pyTupleFromfloat3(mat->emission));
PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter); PyDict_SetItemString(matobj, "unknown_parameter", unknown_parameter);
Py_DECREF(unknown_parameter);
PyDict_SetItemString(pymaterials, mat->name.c_str(), matobj); PyDict_SetItemString(pymaterials, mat->name.c_str(), matobj);
PyList_Append(pymaterial_indices, PyUnicode_FromString(mat->name.c_str())); Py_DECREF(matobj);
value = PyUnicode_FromString(mat->name.c_str());
PyList_Append(pymaterial_indices, value);
Py_DECREF(value);
} }
PyDict_SetItemString(rtndict, "shapes", pyshapes); PyDict_SetItemString(rtndict, "shapes", pyshapes);
Py_DECREF(pyshapes);
PyDict_SetItemString(rtndict, "materials", pymaterials); PyDict_SetItemString(rtndict, "materials", pymaterials);
Py_DECREF(pymaterials);
PyDict_SetItemString(rtndict, "material_indices", pymaterial_indices); PyDict_SetItemString(rtndict, "material_indices", pymaterial_indices);
Py_DECREF(pymaterial_indices);
PyDict_SetItemString(rtndict, "attribs", attribobj); PyDict_SetItemString(rtndict, "attribs", attribobj);
Py_DECREF(attribobj);
return rtndict; return rtndict;
} }
static PyMethodDef mMethods[] = { static PyMethodDef mMethods[] = {
{"LoadObj", pyLoadObj, METH_VARARGS}, {NULL, NULL, 0, NULL} {"LoadObj", pyLoadObj, METH_VARARGS}, {NULL, NULL, 0, NULL}
}; };
#if PY_MAJOR_VERSION >= 3 #if PY_MAJOR_VERSION >= 3
static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader", static struct PyModuleDef moduledef = {PyModuleDef_HEAD_INIT, "tinyobjloader", NULL, -1, mMethods};
NULL, -1, mMethods};
PyMODINIT_FUNC PyInit_tinyobjloader(void) { PyMODINIT_FUNC PyInit_tinyobjloader(void) {
return PyModule_Create(&moduledef); return PyModule_Create(&moduledef);

View File

@@ -986,6 +986,49 @@ TEST_CASE("multiple-group-names", "[group]") {
// single white space. // single white space.
} }
TEST_CASE("initialize_all_texopts", "[ensure unparsed texopts are initialized to defaults]") {
tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes;
std::vector<tinyobj::material_t> materials;
std::string warn;
std::string err;
bool ret = tinyobj::LoadObj(&attrib, &shapes, &materials, &warn, &err,
"../models/cornell_box.obj", gMtlBasePath, false);
REQUIRE(0 < materials.size());
#define REQUIRE_DEFAULT_TEXOPT(texopt) \
REQUIRE(tinyobj::TEXTURE_TYPE_NONE == texopt.type); \
REQUIRE(0.0 == texopt.brightness); \
REQUIRE(1.0 == texopt.contrast); \
REQUIRE(false == texopt.clamp); \
REQUIRE(true == texopt.blendu); \
REQUIRE(true == texopt.blendv); \
REQUIRE(1.0 == texopt.bump_multiplier); \
for (int j = 0; j < 3; j++) { \
REQUIRE(0.0 == texopt.origin_offset[j]); \
REQUIRE(1.0 == texopt.scale[j]); \
REQUIRE(0.0 == texopt.turbulence[j]); \
}
for (size_t i = 0; i < materials.size(); i++) {
REQUIRE_DEFAULT_TEXOPT(materials[i].ambient_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].diffuse_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].specular_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].specular_highlight_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].bump_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].displacement_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].alpha_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].reflection_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].roughness_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].metallic_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].sheen_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].emissive_texopt);
REQUIRE_DEFAULT_TEXOPT(materials[i].normal_texopt);
}
#undef REQUIRE_DEFAULT_TEXOPT
}
TEST_CASE("colorspace", "[Issue184]") { TEST_CASE("colorspace", "[Issue184]") {
tinyobj::attrib_t attrib; tinyobj::attrib_t attrib;
std::vector<tinyobj::shape_t> shapes; std::vector<tinyobj::shape_t> shapes;

View File

@@ -23,6 +23,8 @@ THE SOFTWARE.
*/ */
// //
// version 1.4.0 : Modifed ParseTextureNameAndOption API
// version 1.3.1 : Make ParseTextureNameAndOption API public
// version 1.3.0 : Separate warning and error message(breaking API of LoadObj) // version 1.3.0 : Separate warning and error message(breaking API of LoadObj)
// version 1.2.3 : Added color space extension('-colorspace') to tex opts. // version 1.2.3 : Added color space extension('-colorspace') to tex opts.
// version 1.2.2 : Parse multiple group names. // version 1.2.2 : Parse multiple group names.
@@ -157,8 +159,8 @@ typedef struct {
real_t bump_multiplier; // -bm (for bump maps only, default 1.0) real_t bump_multiplier; // -bm (for bump maps only, default 1.0)
// extension // extension
std::string colorspace; // Explicitly specify color space of stored value. std::string colorspace; // Explicitly specify color space of stored texel
// Usually `sRGB` or `linear` (default empty). // value. Usually `sRGB` or `linear` (default empty).
} texture_option_t; } texture_option_t;
typedef struct { typedef struct {
@@ -386,6 +388,16 @@ void LoadMtl(std::map<std::string, int> *material_map,
std::vector<material_t> *materials, std::istream *inStream, std::vector<material_t> *materials, std::istream *inStream,
std::string *warning, std::string *err); std::string *warning, std::string *err);
///
/// Parse texture name and texture option for custom texture parameter through
/// material::unknown_parameter
///
/// @param[out] texname Parsed texture name
/// @param[out] texopt Parsed texopt
/// @param[in] linebuf Input string
///
bool ParseTextureNameAndOption(std::string *texname, texture_option_t *texopt,
const char *linebuf);
} // namespace tinyobj } // namespace tinyobj
#endif // TINY_OBJ_LOADER_H_ #endif // TINY_OBJ_LOADER_H_
@@ -891,37 +903,12 @@ static vertex_index_t parseRawTriple(const char **token) {
return vi; return vi;
} }
static bool ParseTextureNameAndOption(std::string *texname, bool ParseTextureNameAndOption(std::string *texname, texture_option_t *texopt,
texture_option_t *texopt, const char *linebuf) {
const char *linebuf, const bool is_bump) {
// @todo { write more robust lexer and parser. } // @todo { write more robust lexer and parser. }
bool found_texname = false; bool found_texname = false;
std::string texture_name; std::string texture_name;
// Fill with default value for texopt.
if (is_bump) {
texopt->imfchan = 'l';
} else {
texopt->imfchan = 'm';
}
texopt->bump_multiplier = static_cast<real_t>(1.0);
texopt->clamp = false;
texopt->blendu = true;
texopt->blendv = true;
texopt->sharpness = static_cast<real_t>(1.0);
texopt->brightness = static_cast<real_t>(0.0);
texopt->contrast = static_cast<real_t>(1.0);
texopt->origin_offset[0] = static_cast<real_t>(0.0);
texopt->origin_offset[1] = static_cast<real_t>(0.0);
texopt->origin_offset[2] = static_cast<real_t>(0.0);
texopt->scale[0] = static_cast<real_t>(1.0);
texopt->scale[1] = static_cast<real_t>(1.0);
texopt->scale[2] = static_cast<real_t>(1.0);
texopt->turbulence[0] = static_cast<real_t>(0.0);
texopt->turbulence[1] = static_cast<real_t>(0.0);
texopt->turbulence[2] = static_cast<real_t>(0.0);
texopt->type = TEXTURE_TYPE_NONE;
const char *token = linebuf; // Assume line ends with NULL const char *token = linebuf; // Assume line ends with NULL
while (!IS_NEW_LINE((*token))) { while (!IS_NEW_LINE((*token))) {
@@ -998,7 +985,46 @@ static bool ParseTextureNameAndOption(std::string *texname,
} }
} }
static void InitTexOpt(texture_option_t *texopt, const bool is_bump) {
if (is_bump) {
texopt->imfchan = 'l';
} else {
texopt->imfchan = 'm';
}
texopt->bump_multiplier = static_cast<real_t>(1.0);
texopt->clamp = false;
texopt->blendu = true;
texopt->blendv = true;
texopt->sharpness = static_cast<real_t>(1.0);
texopt->brightness = static_cast<real_t>(0.0);
texopt->contrast = static_cast<real_t>(1.0);
texopt->origin_offset[0] = static_cast<real_t>(0.0);
texopt->origin_offset[1] = static_cast<real_t>(0.0);
texopt->origin_offset[2] = static_cast<real_t>(0.0);
texopt->scale[0] = static_cast<real_t>(1.0);
texopt->scale[1] = static_cast<real_t>(1.0);
texopt->scale[2] = static_cast<real_t>(1.0);
texopt->turbulence[0] = static_cast<real_t>(0.0);
texopt->turbulence[1] = static_cast<real_t>(0.0);
texopt->turbulence[2] = static_cast<real_t>(0.0);
texopt->type = TEXTURE_TYPE_NONE;
}
static void InitMaterial(material_t *material) { static void InitMaterial(material_t *material) {
InitTexOpt(&material->ambient_texopt, /* is_bump */ false);
InitTexOpt(&material->diffuse_texopt, /* is_bump */ false);
InitTexOpt(&material->specular_texopt, /* is_bump */ false);
InitTexOpt(&material->specular_highlight_texopt, /* is_bump */ false);
InitTexOpt(&material->bump_texopt, /* is_bump */ true);
InitTexOpt(&material->displacement_texopt, /* is_bump */ false);
InitTexOpt(&material->alpha_texopt, /* is_bump */ false);
InitTexOpt(&material->reflection_texopt, /* is_bump */ false);
InitTexOpt(&material->roughness_texopt, /* is_bump */ false);
InitTexOpt(&material->metallic_texopt, /* is_bump */ false);
InitTexOpt(&material->sheen_texopt, /* is_bump */ false);
InitTexOpt(&material->emissive_texopt, /* is_bump */ false);
InitTexOpt(&material->normal_texopt,
/* is_bump */ false); // @fixme { is_bump will be true? }
material->name = ""; material->name = "";
material->ambient_texname = ""; material->ambient_texname = "";
material->diffuse_texname = ""; material->diffuse_texname = "";
@@ -1329,7 +1355,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
std::string linebuf; std::string linebuf;
while (inStream->peek() != -1) { while (inStream->peek() != -1) {
safeGetline(*inStream, linebuf); safeGetline(*inStream, linebuf);
line_no++; line_no++;
// Trim trailing whitespace. // Trim trailing whitespace.
if (linebuf.size() > 0) { if (linebuf.size() > 0) {
@@ -1469,9 +1495,9 @@ void LoadMtl(std::map<std::string, int> *material_map,
if (has_tr) { if (has_tr) {
warn_ss << "Both `d` and `Tr` parameters defined for \"" warn_ss << "Both `d` and `Tr` parameters defined for \""
<< material.name << "\". Use the value of `d` for dissolve (line " << material.name
<< line_no << " in .mtl.)" << "\". Use the value of `d` for dissolve (line " << line_no
<< std::endl; << " in .mtl.)" << std::endl;
} }
has_d = true; has_d = true;
continue; continue;
@@ -1481,9 +1507,9 @@ void LoadMtl(std::map<std::string, int> *material_map,
if (has_d) { if (has_d) {
// `d` wins. Ignore `Tr` value. // `d` wins. Ignore `Tr` value.
warn_ss << "Both `d` and `Tr` parameters defined for \"" warn_ss << "Both `d` and `Tr` parameters defined for \""
<< material.name << "\". Use the value of `d` for dissolve (line " << material.name
<< line_no << " in .mtl.)" << "\". Use the value of `d` for dissolve (line " << line_no
<< std::endl; << " in .mtl.)" << std::endl;
} else { } else {
// We invert value of Tr(assume Tr is in range [0, 1]) // We invert value of Tr(assume Tr is in range [0, 1])
// NOTE: Interpretation of Tr is application(exporter) dependent. For // NOTE: Interpretation of Tr is application(exporter) dependent. For
@@ -1547,8 +1573,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) { if ((0 == strncmp(token, "map_Ka", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
ParseTextureNameAndOption(&(material.ambient_texname), ParseTextureNameAndOption(&(material.ambient_texname),
&(material.ambient_texopt), token, &(material.ambient_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1556,8 +1581,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) { if ((0 == strncmp(token, "map_Kd", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
ParseTextureNameAndOption(&(material.diffuse_texname), ParseTextureNameAndOption(&(material.diffuse_texname),
&(material.diffuse_texopt), token, &(material.diffuse_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1565,8 +1589,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) { if ((0 == strncmp(token, "map_Ks", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
ParseTextureNameAndOption(&(material.specular_texname), ParseTextureNameAndOption(&(material.specular_texname),
&(material.specular_texopt), token, &(material.specular_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1574,8 +1597,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) { if ((0 == strncmp(token, "map_Ns", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
ParseTextureNameAndOption(&(material.specular_highlight_texname), ParseTextureNameAndOption(&(material.specular_highlight_texname),
&(material.specular_highlight_texopt), token, &(material.specular_highlight_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1583,8 +1605,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) { if ((0 == strncmp(token, "map_bump", 8)) && IS_SPACE(token[8])) {
token += 9; token += 9;
ParseTextureNameAndOption(&(material.bump_texname), ParseTextureNameAndOption(&(material.bump_texname),
&(material.bump_texopt), token, &(material.bump_texopt), token);
/* is_bump */ true);
continue; continue;
} }
@@ -1592,8 +1613,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_Bump", 8)) && IS_SPACE(token[8])) { if ((0 == strncmp(token, "map_Bump", 8)) && IS_SPACE(token[8])) {
token += 9; token += 9;
ParseTextureNameAndOption(&(material.bump_texname), ParseTextureNameAndOption(&(material.bump_texname),
&(material.bump_texopt), token, &(material.bump_texopt), token);
/* is_bump */ true);
continue; continue;
} }
@@ -1601,8 +1621,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) { if ((0 == strncmp(token, "bump", 4)) && IS_SPACE(token[4])) {
token += 5; token += 5;
ParseTextureNameAndOption(&(material.bump_texname), ParseTextureNameAndOption(&(material.bump_texname),
&(material.bump_texopt), token, &(material.bump_texopt), token);
/* is_bump */ true);
continue; continue;
} }
@@ -1611,8 +1630,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
token += 6; token += 6;
material.alpha_texname = token; material.alpha_texname = token;
ParseTextureNameAndOption(&(material.alpha_texname), ParseTextureNameAndOption(&(material.alpha_texname),
&(material.alpha_texopt), token, &(material.alpha_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1620,8 +1638,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) { if ((0 == strncmp(token, "disp", 4)) && IS_SPACE(token[4])) {
token += 5; token += 5;
ParseTextureNameAndOption(&(material.displacement_texname), ParseTextureNameAndOption(&(material.displacement_texname),
&(material.displacement_texopt), token, &(material.displacement_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1629,8 +1646,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "refl", 4)) && IS_SPACE(token[4])) { if ((0 == strncmp(token, "refl", 4)) && IS_SPACE(token[4])) {
token += 5; token += 5;
ParseTextureNameAndOption(&(material.reflection_texname), ParseTextureNameAndOption(&(material.reflection_texname),
&(material.reflection_texopt), token, &(material.reflection_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1638,8 +1654,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) { if ((0 == strncmp(token, "map_Pr", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
ParseTextureNameAndOption(&(material.roughness_texname), ParseTextureNameAndOption(&(material.roughness_texname),
&(material.roughness_texopt), token, &(material.roughness_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1647,8 +1662,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) { if ((0 == strncmp(token, "map_Pm", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
ParseTextureNameAndOption(&(material.metallic_texname), ParseTextureNameAndOption(&(material.metallic_texname),
&(material.metallic_texopt), token, &(material.metallic_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1656,8 +1670,7 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) { if ((0 == strncmp(token, "map_Ps", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
ParseTextureNameAndOption(&(material.sheen_texname), ParseTextureNameAndOption(&(material.sheen_texname),
&(material.sheen_texopt), token, &(material.sheen_texopt), token);
/* is_bump */ false);
continue; continue;
} }
@@ -1665,17 +1678,15 @@ void LoadMtl(std::map<std::string, int> *material_map,
if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) { if ((0 == strncmp(token, "map_Ke", 6)) && IS_SPACE(token[6])) {
token += 7; token += 7;
ParseTextureNameAndOption(&(material.emissive_texname), ParseTextureNameAndOption(&(material.emissive_texname),
&(material.emissive_texopt), token, &(material.emissive_texopt), token);
/* is_bump */ false);
continue; continue;
} }
// PBR: normal map texture // PBR: normal map texture
if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) { if ((0 == strncmp(token, "norm", 4)) && IS_SPACE(token[4])) {
token += 5; token += 5;
ParseTextureNameAndOption( ParseTextureNameAndOption(&(material.normal_texname),
&(material.normal_texname), &(material.normal_texopt), token, &(material.normal_texopt), token);
/* is_bump */ false); // @fixme { is_bump will be true? }
continue; continue;
} }
@@ -1934,7 +1945,8 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
static_cast<int>(vt.size() / 2), &vi)) { static_cast<int>(vt.size() / 2), &vi)) {
if (err) { if (err) {
std::stringstream ss; std::stringstream ss;
ss << "Failed parse `f' line(e.g. zero value for face index. line " << line_num << ".)\n"; ss << "Failed parse `f' line(e.g. zero value for face index. line "
<< line_num << ".)\n";
(*err) += ss.str(); (*err) += ss.str();
} }
return false; return false;
@@ -1996,7 +2008,8 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
if (warn) { if (warn) {
std::stringstream ss; std::stringstream ss;
ss << "Looks like empty filename for mtllib. Use default " ss << "Looks like empty filename for mtllib. Use default "
"material (line " << line_num << ".)\n"; "material (line "
<< line_num << ".)\n";
(*warn) += ss.str(); (*warn) += ss.str();
} }
@@ -2205,21 +2218,24 @@ bool LoadObj(attrib_t *attrib, std::vector<shape_t> *shapes,
if (greatest_v_idx >= static_cast<int>(v.size() / 3)) { if (greatest_v_idx >= static_cast<int>(v.size() / 3)) {
if (warn) { if (warn) {
std::stringstream ss; std::stringstream ss;
ss << "Vertex indices out of bounds (line " << line_num << ".)\n" << std::endl; ss << "Vertex indices out of bounds (line " << line_num << ".)\n"
<< std::endl;
(*warn) += ss.str(); (*warn) += ss.str();
} }
} }
if (greatest_vn_idx >= static_cast<int>(vn.size() / 3)) { if (greatest_vn_idx >= static_cast<int>(vn.size() / 3)) {
if (warn) { if (warn) {
std::stringstream ss; std::stringstream ss;
ss << "Vertex normal indices out of bounds (line " << line_num << ".)\n" << std::endl; ss << "Vertex normal indices out of bounds (line " << line_num << ".)\n"
<< std::endl;
(*warn) += ss.str(); (*warn) += ss.str();
} }
} }
if (greatest_vt_idx >= static_cast<int>(vt.size() / 2)) { if (greatest_vt_idx >= static_cast<int>(vt.size() / 2)) {
if (warn) { if (warn) {
std::stringstream ss; std::stringstream ss;
ss << "Vertex texcoord indices out of bounds (line " << line_num << ".)\n" << std::endl; ss << "Vertex texcoord indices out of bounds (line " << line_num << ".)\n"
<< std::endl;
(*warn) += ss.str(); (*warn) += ss.str();
} }
} }