Added multiple materials per shape/object

This commit is contained in:
Mykhailo Parfeniuk
2014-09-07 14:19:22 +03:00
parent 8f7712c382
commit 33cd9a4768
2 changed files with 63 additions and 52 deletions

View File

@@ -224,24 +224,22 @@ void InitMaterial(material_t& material) {
static bool
exportFaceGroupToShape(
shape_t& shape,
std::map<vertex_index, unsigned int> vertexCache,
const std::vector<float> &in_positions,
const std::vector<float> &in_normals,
const std::vector<float> &in_texcoords,
const std::vector<std::vector<vertex_index> >& faceGroup,
const material_t &material,
const int material,
const std::string &name,
const bool is_material_seted)
bool clearCache)
{
if (faceGroup.empty()) {
return false;
}
// Flattened version of vertex data
std::vector<float> positions;
std::vector<float> normals;
std::vector<float> texcoords;
std::map<vertex_index, unsigned int> vertexCache;
std::vector<unsigned int> indices;
size_t offset;
offset = shape.mesh.indices.size();
// Flatten vertices and indices
for (size_t i = 0; i < faceGroup.size(); i++) {
@@ -258,13 +256,13 @@ exportFaceGroupToShape(
i1 = i2;
i2 = face[k];
unsigned int v0 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i0);
unsigned int v1 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i1);
unsigned int v2 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i2);
unsigned int v0 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i0);
unsigned int v1 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i1);
unsigned int v2 = updateVertex(vertexCache, shape.mesh.positions, shape.mesh.normals, shape.mesh.texcoords, in_positions, in_normals, in_texcoords, i2);
indices.push_back(v0);
indices.push_back(v1);
indices.push_back(v2);
shape.mesh.indices.push_back(v0);
shape.mesh.indices.push_back(v1);
shape.mesh.indices.push_back(v2);
}
}
@@ -272,27 +270,22 @@ exportFaceGroupToShape(
//
// Construct shape.
//
shape.name = name;
shape.mesh.positions.swap(positions);
shape.mesh.normals.swap(normals);
shape.mesh.texcoords.swap(texcoords);
shape.mesh.indices.swap(indices);
shape.submeshes.push_back(std::pair<int, int>(offset, shape.mesh.indices.size()-offset));
if(is_material_seted) {
shape.material = material;
} else {
InitMaterial(shape.material);
shape.material.diffuse[0] = 1.f;
shape.material.diffuse[1] = 1.f;
shape.material.diffuse[2] = 1.f;
}
shape.name = name;
shape.materials.push_back(material);
if (clearCache)
vertexCache.clear();
return true;
}
std::string LoadMtl (
std::map<std::string, material_t>& material_map,
std::map<std::string, int>& material_map,
std::vector<material_t>& materials,
std::istream& inStream)
{
material_map.clear();
@@ -332,7 +325,11 @@ std::string LoadMtl (
// new mtl
if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) {
// flush previous material.
material_map.insert(std::pair<std::string, material_t>(material.name, material));
if (!material.name.empty())
{
material_map.insert(std::pair<std::string, int>(material.name, materials.size()));
materials.push_back(material);
}
// initial temporary material
InitMaterial(material);
@@ -474,14 +471,16 @@ std::string LoadMtl (
}
}
// flush last material.
material_map.insert(std::pair<std::string, material_t>(material.name, material));
material_map.insert(std::pair<std::string, int>(material.name, materials.size()));
materials.push_back(material);
return err.str();
}
std::string MaterialFileReader::operator() (
const std::string& matId,
std::map<std::string, material_t>& matMap)
std::vector<material_t>& materials,
std::map<std::string, int>& matMap)
{
std::string filepath;
@@ -492,12 +491,13 @@ std::string MaterialFileReader::operator() (
}
std::ifstream matIStream(filepath.c_str());
return LoadMtl(matMap, matIStream);
return LoadMtl(matMap, materials, matIStream);
}
std::string
LoadObj(
std::vector<shape_t>& shapes,
std::vector<material_t>& materials, // [output]
const char* filename,
const char* mtl_basepath)
{
@@ -518,11 +518,12 @@ LoadObj(
}
MaterialFileReader matFileReader( basePath );
return LoadObj(shapes, ifs, matFileReader);
return LoadObj(shapes, materials, ifs, matFileReader);
}
std::string LoadObj(
std::vector<shape_t>& shapes,
std::vector<material_t>& materials, // [output]
std::istream& inStream,
MaterialReader& readMatFn)
{
@@ -535,9 +536,11 @@ std::string LoadObj(
std::string name;
// material
std::map<std::string, material_t> material_map;
material_t material;
bool is_material_seted = false;
std::map<std::string, int> material_map;
std::map<vertex_index, unsigned int> vertexCache;
int material = -1;
shape_t shape;
int maxchars = 8192; // Alloc enough size.
std::vector<char> buf(maxchars); // Alloc enough size.
@@ -625,13 +628,16 @@ std::string LoadObj(
token += 7;
sscanf(token, "%s", namebuf);
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, false);
faceGroup.clear();
if (material_map.find(namebuf) != material_map.end()) {
material = material_map[namebuf];
is_material_seted = true;
} else {
// { error!! material not found }
InitMaterial(material);
material = -1;
}
continue;
}
@@ -642,7 +648,7 @@ std::string LoadObj(
token += 7;
sscanf(token, "%s", namebuf);
std::string err_mtl = readMatFn(namebuf, material_map);
std::string err_mtl = readMatFn(namebuf, materials, material_map);
if (!err_mtl.empty()) {
faceGroup.clear(); // for safety
return err_mtl;
@@ -655,13 +661,14 @@ std::string LoadObj(
if (token[0] == 'g' && isSpace((token[1]))) {
// flush previous face group.
shape_t shape;
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, is_material_seted);
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true);
if (ret) {
shapes.push_back(shape);
}
is_material_seted = false;
shape = shape_t();
material = -1;
faceGroup.clear();
std::vector<std::string> names;
@@ -687,14 +694,14 @@ std::string LoadObj(
if (token[0] == 'o' && isSpace((token[1]))) {
// flush previous face group.
shape_t shape;
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, is_material_seted);
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true);
if (ret) {
shapes.push_back(shape);
}
is_material_seted = false;
material = -1;
faceGroup.clear();
shape = shape_t();
// @todo { multiple object name? }
char namebuf[4096];
@@ -709,12 +716,10 @@ std::string LoadObj(
// Ignore unknown command.
}
shape_t shape;
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, is_material_seted);
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true);
if (ret) {
shapes.push_back(shape);
}
is_material_seted = false; // for safety
faceGroup.clear(); // for safety
return err.str();