From 1e961e00b7d48c8b969485ae42dc8fc991da25d1 Mon Sep 17 00:00:00 2001 From: yangxiao Date: Sun, 17 Aug 2014 22:49:53 +0800 Subject: [PATCH] obj loader work --- cocos/3d/CCBundle3D.cpp | 95 +++++++++++++++++++++++++++++++++++++++ cocos/3d/CCBundle3D.h | 3 ++ cocos/3d/CCBundle3DData.h | 14 ++++++ cocos/3d/CCSprite3D.cpp | 70 ++++++++++++++--------------- 4 files changed, 145 insertions(+), 37 deletions(-) diff --git a/cocos/3d/CCBundle3D.cpp b/cocos/3d/CCBundle3D.cpp index 1899935436..7b089daf6f 100644 --- a/cocos/3d/CCBundle3D.cpp +++ b/cocos/3d/CCBundle3D.cpp @@ -23,6 +23,7 @@ ****************************************************************************/ #include "3d/CCBundle3D.h" +#include "3d/CCObjLoader.h" #include "base/ccMacros.h" #include "platform/CCFileUtils.h" @@ -213,6 +214,100 @@ bool Bundle3D::load(const std::string& path) 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) { diff --git a/cocos/3d/CCBundle3D.h b/cocos/3d/CCBundle3D.h index ea6164ac68..2fc9bf02e5 100644 --- a/cocos/3d/CCBundle3D.h +++ b/cocos/3d/CCBundle3D.h @@ -102,6 +102,9 @@ public: virtual bool loadNodes(NodeDatas& nodedatas); //since 3.3, to support reskin 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: diff --git a/cocos/3d/CCBundle3DData.h b/cocos/3d/CCBundle3DData.h index 2d2edc511a..d179a7bb6b 100644 --- a/cocos/3d/CCBundle3DData.h +++ b/cocos/3d/CCBundle3DData.h @@ -105,6 +105,20 @@ struct NodeDatas { std::vector skeleton; //skeleton std::vector 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*/ diff --git a/cocos/3d/CCSprite3D.cpp b/cocos/3d/CCSprite3D.cpp index 3220a3d10c..9b852a036d 100644 --- a/cocos/3d/CCSprite3D.cpp +++ b/cocos/3d/CCSprite3D.cpp @@ -114,40 +114,33 @@ bool Sprite3D::loadFromObj(const std::string& path) std::string fullPath = FileUtils::getInstance()->fullPathForFilename(path); std::string key = fullPath + "#"; - //.mtl file directory - std::string dir = ""; - auto last = fullPath.rfind("/"); - if (last != -1) - dir = fullPath.substr(0, last + 1); - - 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 > submeshIndices; - std::vector matnames; - std::string texname; - for (auto it = shapes.shapes.begin(); it != shapes.shapes.end(); it++) + MeshDatas meshdatas; + MaterialDatas materialdatas; + NodeDatas nodeDatas; + bool ret = Bundle3D::loadObj(meshdatas, materialdatas, nodeDatas, fullPath); + if (ret) { - submeshIndices.push_back((*it).mesh.indices); - - texname = (*it).material.diffuse_texname; - if (!texname.empty()) - texname = dir + (*it).material.diffuse_texname; - matnames.push_back(texname); + for( int i = 0 ; i < meshdatas.meshDatas.size() ; i++ ) + { + MeshData* meshData= meshdatas.meshDatas[i]; + if(meshData) + { + 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); + } + } } - - _mesh = Mesh::create(shapes.positions, shapes.normals, shapes.texcoords, submeshIndices); - _mesh->retain(); - if (_mesh == nullptr) - return false; - //add mesh to cache - MeshCache::getInstance()->addMesh(key, _mesh); +// //add mesh to cache +// MeshCache::getInstance()->addMesh(key, _mesh); - genMaterials(key, matnames); - genGLProgramState(); return true; @@ -356,8 +349,11 @@ void Sprite3D::createNode(NodeData* nodedata, Node* root, const MaterialDatas& m { _subMeshStates.pushBack(subMeshState); subMeshState->setSubMesh(getSubMesh(modelNodeData->subMeshId)); - auto skin = MeshSkin::create(_skeleton, modelNodeData->bones, modelNodeData->invBindPose); - subMeshState->setSkin(skin); + if (_skeleton && modelNodeData->bones.size()) + { + auto skin = MeshSkin::create(_skeleton, modelNodeData->bones, modelNodeData->invBindPose); + subMeshState->setSkin(skin); + } if (modelNodeData->matrialId == "" && matrialdatas.materials.size()) { @@ -434,10 +430,10 @@ void Sprite3D::genMaterials(const std::string& keyprefix, const std::vectorsetTexture(tex); _subMeshStates.pushBack(subMeshState); - //add to cache - sprintf(str, "submesh%d", index); - std::string submeshkey = keyprefix + std::string(str); - Sprite3DMaterialCache::getInstance()->addSprite3DMaterial(submeshkey, tex); +// //add to cache +// sprintf(str, "submesh%d", index); +// std::string submeshkey = keyprefix + std::string(str); +// Sprite3DMaterialCache::getInstance()->addSprite3DMaterial(submeshkey, tex); index++; } }