obj loader work

This commit is contained in:
yangxiao 2014-08-17 22:49:53 +08:00
parent 05b13b8c38
commit 1e961e00b7
4 changed files with 145 additions and 37 deletions

View File

@ -23,6 +23,7 @@
****************************************************************************/ ****************************************************************************/
#include "3d/CCBundle3D.h" #include "3d/CCBundle3D.h"
#include "3d/CCObjLoader.h"
#include "base/ccMacros.h" #include "base/ccMacros.h"
#include "platform/CCFileUtils.h" #include "platform/CCFileUtils.h"
@ -213,6 +214,100 @@ bool Bundle3D::load(const std::string& path)
return ret; return ret;
} }
bool Bundle3D::loadObj(MeshDatas& meshdatas, MaterialDatas& materialdatas, NodeDatas& nodedatas, const std::string& fullPath, const char* mtl_basepath)
{
meshdatas.resetData();
materialdatas.resetData();
nodedatas.resetData();
ObjLoader::shapes_t shapes;
auto ret = ObjLoader::LoadObj(shapes, fullPath.c_str(), mtl_basepath);
if (ret.empty())
{
//fill data
MeshData* meshdata = new MeshData();
MeshVertexAttrib attrib;
attrib.size = 3;
attrib.type = GL_FLOAT;
if (shapes.positions.size())
{
attrib.vertexAttrib = GLProgram::VERTEX_ATTRIB_POSITION;
attrib.attribSizeBytes = attrib.size * sizeof(float);
meshdata->attribs.push_back(attrib);
}
bool hasnormal = false, hastex = false;
if (shapes.normals.size())
{
hasnormal = true;
attrib.vertexAttrib = GLProgram::VERTEX_ATTRIB_NORMAL;
attrib.attribSizeBytes = attrib.size * sizeof(float);;
meshdata->attribs.push_back(attrib);
}
if (shapes.texcoords.size())
{
hastex = true;
attrib.size = 2;
attrib.vertexAttrib = GLProgram::VERTEX_ATTRIB_TEX_COORD;
attrib.attribSizeBytes = attrib.size * sizeof(float);
meshdata->attribs.push_back(attrib);
}
auto vertexNum = shapes.positions.size() / 3;
for(auto i = 0; i < vertexNum; i++)
{
meshdata->vertex.push_back(shapes.positions[i * 3]);
meshdata->vertex.push_back(shapes.positions[i * 3 + 1]);
meshdata->vertex.push_back(shapes.positions[i * 3 + 2]);
if (hasnormal)
{
meshdata->vertex.push_back(shapes.normals[i * 3]);
meshdata->vertex.push_back(shapes.normals[i * 3 + 1]);
meshdata->vertex.push_back(shapes.normals[i * 3 + 2]);
}
if (hastex)
{
meshdata->vertex.push_back(shapes.texcoords[i * 2]);
meshdata->vertex.push_back(shapes.texcoords[i * 2 + 1]);
}
}
meshdatas.meshDatas.push_back(meshdata);
NMaterialData materialdata;
int i = 0;
char str[20];
std::string dir = "";
auto last = fullPath.rfind("/");
if (last != -1)
dir = fullPath.substr(0, last + 1);
for (const auto& it : shapes.shapes)
{
NTextureData tex;
tex.filename = dir + it.material.diffuse_texname;
tex.type = NTextureData::Usage::Diffuse;
sprintf(str, "%d", i++);
materialdata.textures.push_back(tex);
materialdata.id = str;
materialdatas.materials.push_back(materialdata);
meshdata->subMeshIndices.push_back(it.mesh.indices);
meshdata->subMeshIds.push_back(str);
auto modelnode = new ModelNodeData();
modelnode->matrialId = str;
modelnode->subMeshId = str;
modelnode->id = it.name;
nodedatas.nodes.push_back(modelnode);
}
return true;
}
CCLOG("load %s file error: %s", fullPath.c_str(), ret.c_str());
return false;
}
bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata) bool Bundle3D::loadMeshData(const std::string& id, MeshData* meshdata)
{ {

View File

@ -102,6 +102,9 @@ public:
virtual bool loadNodes(NodeDatas& nodedatas); virtual bool loadNodes(NodeDatas& nodedatas);
//since 3.3, to support reskin //since 3.3, to support reskin
virtual bool loadMaterials(MaterialDatas& materialdatas); virtual bool loadMaterials(MaterialDatas& materialdatas);
//load .obj file
static bool loadObj(MeshDatas& meshdatas, MaterialDatas& materialdatas, NodeDatas& nodedatas, const std::string& fullPath, const char* mtl_basepath = nullptr);
protected: protected:

View File

@ -105,6 +105,20 @@ struct NodeDatas
{ {
std::vector<NodeData*> skeleton; //skeleton std::vector<NodeData*> skeleton; //skeleton
std::vector<NodeData*> nodes; // nodes, CCNode, Sprite3D or part of Sprite3D std::vector<NodeData*> nodes; // nodes, CCNode, Sprite3D or part of Sprite3D
void resetData()
{
for(auto& it : skeleton)
{
delete it;
}
skeleton.clear();
for(auto& it : nodes)
{
delete it;
}
nodes.clear();
}
}; };
/**mesh data*/ /**mesh data*/

View File

@ -114,40 +114,33 @@ bool Sprite3D::loadFromObj(const std::string& path)
std::string fullPath = FileUtils::getInstance()->fullPathForFilename(path); std::string fullPath = FileUtils::getInstance()->fullPathForFilename(path);
std::string key = fullPath + "#"; std::string key = fullPath + "#";
//.mtl file directory MeshDatas meshdatas;
std::string dir = ""; MaterialDatas materialdatas;
auto last = fullPath.rfind("/"); NodeDatas nodeDatas;
if (last != -1) bool ret = Bundle3D::loadObj(meshdatas, materialdatas, nodeDatas, fullPath);
dir = fullPath.substr(0, last + 1); if (ret)
ObjLoader::shapes_t shapes;
std::string errstr = ObjLoader::LoadObj(shapes, fullPath.c_str(), dir.c_str());
if (!errstr.empty())
return false;
//convert to mesh and material
std::vector<std::vector<unsigned short> > submeshIndices;
std::vector<std::string> matnames;
std::string texname;
for (auto it = shapes.shapes.begin(); it != shapes.shapes.end(); it++)
{ {
submeshIndices.push_back((*it).mesh.indices); for( int i = 0 ; i < meshdatas.meshDatas.size() ; i++ )
{
texname = (*it).material.diffuse_texname; MeshData* meshData= meshdatas.meshDatas[i];
if (!texname.empty()) if(meshData)
texname = dir + (*it).material.diffuse_texname; {
matnames.push_back(texname); Mesh* mesh = Mesh::create(*meshData);
_meshes.pushBack(mesh);
}
}
for(int i = 0; i < nodeDatas.nodes.size(); i++ )
{
NodeData* nodeData= nodeDatas.nodes[i];
if(nodeData)
{
createNode(nodeData, this, materialdatas);
}
}
} }
// //add mesh to cache
_mesh = Mesh::create(shapes.positions, shapes.normals, shapes.texcoords, submeshIndices); // MeshCache::getInstance()->addMesh(key, _mesh);
_mesh->retain();
if (_mesh == nullptr)
return false;
//add mesh to cache
MeshCache::getInstance()->addMesh(key, _mesh);
genMaterials(key, matnames);
genGLProgramState(); genGLProgramState();
return true; return true;
@ -356,8 +349,11 @@ void Sprite3D::createNode(NodeData* nodedata, Node* root, const MaterialDatas& m
{ {
_subMeshStates.pushBack(subMeshState); _subMeshStates.pushBack(subMeshState);
subMeshState->setSubMesh(getSubMesh(modelNodeData->subMeshId)); subMeshState->setSubMesh(getSubMesh(modelNodeData->subMeshId));
auto skin = MeshSkin::create(_skeleton, modelNodeData->bones, modelNodeData->invBindPose); if (_skeleton && modelNodeData->bones.size())
subMeshState->setSkin(skin); {
auto skin = MeshSkin::create(_skeleton, modelNodeData->bones, modelNodeData->invBindPose);
subMeshState->setSkin(skin);
}
if (modelNodeData->matrialId == "" && matrialdatas.materials.size()) if (modelNodeData->matrialId == "" && matrialdatas.materials.size())
{ {
@ -434,10 +430,10 @@ void Sprite3D::genMaterials(const std::string& keyprefix, const std::vector<std:
subMeshState->setTexture(tex); subMeshState->setTexture(tex);
_subMeshStates.pushBack(subMeshState); _subMeshStates.pushBack(subMeshState);
//add to cache // //add to cache
sprintf(str, "submesh%d", index); // sprintf(str, "submesh%d", index);
std::string submeshkey = keyprefix + std::string(str); // std::string submeshkey = keyprefix + std::string(str);
Sprite3DMaterialCache::getInstance()->addSprite3DMaterial(submeshkey, tex); // Sprite3DMaterialCache::getInstance()->addSprite3DMaterial(submeshkey, tex);
index++; index++;
} }
} }