Added multiple materials per shape/object
This commit is contained in:
@@ -224,24 +224,22 @@ void InitMaterial(material_t& material) {
|
|||||||
static bool
|
static bool
|
||||||
exportFaceGroupToShape(
|
exportFaceGroupToShape(
|
||||||
shape_t& shape,
|
shape_t& shape,
|
||||||
|
std::map<vertex_index, unsigned int> vertexCache,
|
||||||
const std::vector<float> &in_positions,
|
const std::vector<float> &in_positions,
|
||||||
const std::vector<float> &in_normals,
|
const std::vector<float> &in_normals,
|
||||||
const std::vector<float> &in_texcoords,
|
const std::vector<float> &in_texcoords,
|
||||||
const std::vector<std::vector<vertex_index> >& faceGroup,
|
const std::vector<std::vector<vertex_index> >& faceGroup,
|
||||||
const material_t &material,
|
const int material,
|
||||||
const std::string &name,
|
const std::string &name,
|
||||||
const bool is_material_seted)
|
bool clearCache)
|
||||||
{
|
{
|
||||||
if (faceGroup.empty()) {
|
if (faceGroup.empty()) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Flattened version of vertex data
|
size_t offset;
|
||||||
std::vector<float> positions;
|
|
||||||
std::vector<float> normals;
|
offset = shape.mesh.indices.size();
|
||||||
std::vector<float> texcoords;
|
|
||||||
std::map<vertex_index, unsigned int> vertexCache;
|
|
||||||
std::vector<unsigned int> indices;
|
|
||||||
|
|
||||||
// Flatten vertices and indices
|
// Flatten vertices and indices
|
||||||
for (size_t i = 0; i < faceGroup.size(); i++) {
|
for (size_t i = 0; i < faceGroup.size(); i++) {
|
||||||
@@ -258,13 +256,13 @@ exportFaceGroupToShape(
|
|||||||
i1 = i2;
|
i1 = i2;
|
||||||
i2 = face[k];
|
i2 = face[k];
|
||||||
|
|
||||||
unsigned int v0 = updateVertex(vertexCache, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i0);
|
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, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i1);
|
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, positions, normals, texcoords, in_positions, in_normals, in_texcoords, i2);
|
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);
|
shape.mesh.indices.push_back(v0);
|
||||||
indices.push_back(v1);
|
shape.mesh.indices.push_back(v1);
|
||||||
indices.push_back(v2);
|
shape.mesh.indices.push_back(v2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -272,27 +270,22 @@ exportFaceGroupToShape(
|
|||||||
//
|
//
|
||||||
// Construct shape.
|
// Construct shape.
|
||||||
//
|
//
|
||||||
shape.name = name;
|
shape.submeshes.push_back(std::pair<int, int>(offset, shape.mesh.indices.size()-offset));
|
||||||
shape.mesh.positions.swap(positions);
|
|
||||||
shape.mesh.normals.swap(normals);
|
|
||||||
shape.mesh.texcoords.swap(texcoords);
|
|
||||||
shape.mesh.indices.swap(indices);
|
|
||||||
|
|
||||||
if(is_material_seted) {
|
shape.name = name;
|
||||||
shape.material = material;
|
|
||||||
} else {
|
shape.materials.push_back(material);
|
||||||
InitMaterial(shape.material);
|
|
||||||
shape.material.diffuse[0] = 1.f;
|
if (clearCache)
|
||||||
shape.material.diffuse[1] = 1.f;
|
vertexCache.clear();
|
||||||
shape.material.diffuse[2] = 1.f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LoadMtl (
|
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)
|
std::istream& inStream)
|
||||||
{
|
{
|
||||||
material_map.clear();
|
material_map.clear();
|
||||||
@@ -332,7 +325,11 @@ std::string LoadMtl (
|
|||||||
// new mtl
|
// new mtl
|
||||||
if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) {
|
if ((0 == strncmp(token, "newmtl", 6)) && isSpace((token[6]))) {
|
||||||
// flush previous material.
|
// 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
|
// initial temporary material
|
||||||
InitMaterial(material);
|
InitMaterial(material);
|
||||||
@@ -474,14 +471,16 @@ std::string LoadMtl (
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// flush last material.
|
// 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();
|
return err.str();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string MaterialFileReader::operator() (
|
std::string MaterialFileReader::operator() (
|
||||||
const std::string& matId,
|
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;
|
std::string filepath;
|
||||||
|
|
||||||
@@ -492,12 +491,13 @@ std::string MaterialFileReader::operator() (
|
|||||||
}
|
}
|
||||||
|
|
||||||
std::ifstream matIStream(filepath.c_str());
|
std::ifstream matIStream(filepath.c_str());
|
||||||
return LoadMtl(matMap, matIStream);
|
return LoadMtl(matMap, materials, matIStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string
|
std::string
|
||||||
LoadObj(
|
LoadObj(
|
||||||
std::vector<shape_t>& shapes,
|
std::vector<shape_t>& shapes,
|
||||||
|
std::vector<material_t>& materials, // [output]
|
||||||
const char* filename,
|
const char* filename,
|
||||||
const char* mtl_basepath)
|
const char* mtl_basepath)
|
||||||
{
|
{
|
||||||
@@ -518,11 +518,12 @@ LoadObj(
|
|||||||
}
|
}
|
||||||
MaterialFileReader matFileReader( basePath );
|
MaterialFileReader matFileReader( basePath );
|
||||||
|
|
||||||
return LoadObj(shapes, ifs, matFileReader);
|
return LoadObj(shapes, materials, ifs, matFileReader);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string LoadObj(
|
std::string LoadObj(
|
||||||
std::vector<shape_t>& shapes,
|
std::vector<shape_t>& shapes,
|
||||||
|
std::vector<material_t>& materials, // [output]
|
||||||
std::istream& inStream,
|
std::istream& inStream,
|
||||||
MaterialReader& readMatFn)
|
MaterialReader& readMatFn)
|
||||||
{
|
{
|
||||||
@@ -535,9 +536,11 @@ std::string LoadObj(
|
|||||||
std::string name;
|
std::string name;
|
||||||
|
|
||||||
// material
|
// material
|
||||||
std::map<std::string, material_t> material_map;
|
std::map<std::string, int> material_map;
|
||||||
material_t material;
|
std::map<vertex_index, unsigned int> vertexCache;
|
||||||
bool is_material_seted = false;
|
int material = -1;
|
||||||
|
|
||||||
|
shape_t shape;
|
||||||
|
|
||||||
int maxchars = 8192; // Alloc enough size.
|
int maxchars = 8192; // Alloc enough size.
|
||||||
std::vector<char> buf(maxchars); // Alloc enough size.
|
std::vector<char> buf(maxchars); // Alloc enough size.
|
||||||
@@ -625,13 +628,16 @@ std::string LoadObj(
|
|||||||
token += 7;
|
token += 7;
|
||||||
sscanf(token, "%s", namebuf);
|
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()) {
|
if (material_map.find(namebuf) != material_map.end()) {
|
||||||
material = material_map[namebuf];
|
material = material_map[namebuf];
|
||||||
is_material_seted = true;
|
|
||||||
} else {
|
} else {
|
||||||
// { error!! material not found }
|
// { error!! material not found }
|
||||||
InitMaterial(material);
|
material = -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -642,7 +648,7 @@ std::string LoadObj(
|
|||||||
token += 7;
|
token += 7;
|
||||||
sscanf(token, "%s", namebuf);
|
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()) {
|
if (!err_mtl.empty()) {
|
||||||
faceGroup.clear(); // for safety
|
faceGroup.clear(); // for safety
|
||||||
return err_mtl;
|
return err_mtl;
|
||||||
@@ -655,13 +661,14 @@ std::string LoadObj(
|
|||||||
if (token[0] == 'g' && isSpace((token[1]))) {
|
if (token[0] == 'g' && isSpace((token[1]))) {
|
||||||
|
|
||||||
// flush previous face group.
|
// flush previous face group.
|
||||||
shape_t shape;
|
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true);
|
||||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, is_material_seted);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
shapes.push_back(shape);
|
shapes.push_back(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
is_material_seted = false;
|
shape = shape_t();
|
||||||
|
|
||||||
|
material = -1;
|
||||||
faceGroup.clear();
|
faceGroup.clear();
|
||||||
|
|
||||||
std::vector<std::string> names;
|
std::vector<std::string> names;
|
||||||
@@ -687,14 +694,14 @@ std::string LoadObj(
|
|||||||
if (token[0] == 'o' && isSpace((token[1]))) {
|
if (token[0] == 'o' && isSpace((token[1]))) {
|
||||||
|
|
||||||
// flush previous face group.
|
// flush previous face group.
|
||||||
shape_t shape;
|
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true);
|
||||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, is_material_seted);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
shapes.push_back(shape);
|
shapes.push_back(shape);
|
||||||
}
|
}
|
||||||
|
|
||||||
is_material_seted = false;
|
material = -1;
|
||||||
faceGroup.clear();
|
faceGroup.clear();
|
||||||
|
shape = shape_t();
|
||||||
|
|
||||||
// @todo { multiple object name? }
|
// @todo { multiple object name? }
|
||||||
char namebuf[4096];
|
char namebuf[4096];
|
||||||
@@ -709,12 +716,10 @@ std::string LoadObj(
|
|||||||
// Ignore unknown command.
|
// Ignore unknown command.
|
||||||
}
|
}
|
||||||
|
|
||||||
shape_t shape;
|
bool ret = exportFaceGroupToShape(shape, vertexCache, v, vn, vt, faceGroup, material, name, true);
|
||||||
bool ret = exportFaceGroupToShape(shape, v, vn, vt, faceGroup, material, name, is_material_seted);
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
shapes.push_back(shape);
|
shapes.push_back(shape);
|
||||||
}
|
}
|
||||||
is_material_seted = false; // for safety
|
|
||||||
faceGroup.clear(); // for safety
|
faceGroup.clear(); // for safety
|
||||||
|
|
||||||
return err.str();
|
return err.str();
|
||||||
|
|||||||
@@ -45,8 +45,9 @@ typedef struct
|
|||||||
typedef struct
|
typedef struct
|
||||||
{
|
{
|
||||||
std::string name;
|
std::string name;
|
||||||
material_t material;
|
|
||||||
mesh_t mesh;
|
mesh_t mesh;
|
||||||
|
std::vector< std::pair<int, int> > submeshes;
|
||||||
|
std::vector< int > materials;
|
||||||
} shape_t;
|
} shape_t;
|
||||||
|
|
||||||
class MaterialReader
|
class MaterialReader
|
||||||
@@ -57,7 +58,8 @@ public:
|
|||||||
|
|
||||||
virtual std::string operator() (
|
virtual std::string operator() (
|
||||||
const std::string& matId,
|
const std::string& matId,
|
||||||
std::map<std::string, material_t>& matMap) = 0;
|
std::vector<material_t>& materials,
|
||||||
|
std::map<std::string, int>& matMap) = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
class MaterialFileReader:
|
class MaterialFileReader:
|
||||||
@@ -68,7 +70,8 @@ class MaterialFileReader:
|
|||||||
virtual ~MaterialFileReader() {}
|
virtual ~MaterialFileReader() {}
|
||||||
virtual std::string operator() (
|
virtual std::string operator() (
|
||||||
const std::string& matId,
|
const std::string& matId,
|
||||||
std::map<std::string, material_t>& matMap);
|
std::vector<material_t>& materials,
|
||||||
|
std::map<std::string, int>& matMap);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string m_mtlBasePath;
|
std::string m_mtlBasePath;
|
||||||
@@ -81,6 +84,7 @@ class MaterialFileReader:
|
|||||||
/// 'mtl_basepath' is optional, and used for base path for .mtl file.
|
/// 'mtl_basepath' is optional, and used for base path for .mtl file.
|
||||||
std::string LoadObj(
|
std::string LoadObj(
|
||||||
std::vector<shape_t>& shapes, // [output]
|
std::vector<shape_t>& shapes, // [output]
|
||||||
|
std::vector<material_t>& materials, // [output]
|
||||||
const char* filename,
|
const char* filename,
|
||||||
const char* mtl_basepath = NULL);
|
const char* mtl_basepath = NULL);
|
||||||
|
|
||||||
@@ -89,13 +93,15 @@ std::string LoadObj(
|
|||||||
/// Returns empty string when loading .obj success.
|
/// Returns empty string when loading .obj success.
|
||||||
std::string LoadObj(
|
std::string LoadObj(
|
||||||
std::vector<shape_t>& shapes, // [output]
|
std::vector<shape_t>& shapes, // [output]
|
||||||
|
std::vector<material_t>& materials, // [output]
|
||||||
std::istream& inStream,
|
std::istream& inStream,
|
||||||
MaterialReader& readMatFn);
|
MaterialReader& readMatFn);
|
||||||
|
|
||||||
/// Loads materials into std::map
|
/// Loads materials into std::map
|
||||||
/// Returns an empty string if successful
|
/// Returns an empty string if successful
|
||||||
std::string LoadMtl (
|
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);
|
std::istream& inStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user