Dictionary Curve3D::_get_data() const { Dictionary dc; Vector3Array d; d.resize(points.size()*3); Vector3Array::Write w = d.write(); RealArray t; t.resize(points.size()); RealArray::Write wt = t.write(); for(int i=0;i<points.size();i++) { w[i*3+0]=points[i].in; w[i*3+1]=points[i].out; w[i*3+2]=points[i].pos; wt[i]=points[i].tilt; } w=Vector3Array::Write(); wt=RealArray::Write(); dc["points"]=d; dc["tilts"]=t; return dc; }
void RasterizerDummy::mesh_add_surface(RID p_mesh,VS::PrimitiveType p_primitive,const Array& p_arrays,const Array& p_blend_shapes,bool p_alpha_sort) { Mesh *mesh = mesh_owner.get( p_mesh ); ERR_FAIL_COND(!mesh); ERR_FAIL_INDEX( p_primitive, VS::PRIMITIVE_MAX ); ERR_FAIL_COND(p_arrays.size()!=VS::ARRAY_MAX); Surface s; s.format=0; for(int i=0;i<p_arrays.size();i++) { if (p_arrays[i].get_type()==Variant::NIL) continue; s.format|=(1<<i); if (i==VS::ARRAY_VERTEX) { Vector3Array v = p_arrays[i]; int len = v.size(); ERR_FAIL_COND(len==0); Vector3Array::Read r = v.read(); for(int i=0;i<len;i++) { if (i==0) s.aabb.pos=r[0]; else s.aabb.expand_to(r[i]); } } } ERR_FAIL_COND((s.format&VS::ARRAY_FORMAT_VERTEX)==0); // mandatory s.data=p_arrays; s.morph_data=p_blend_shapes; s.primitive=p_primitive; s.alpha_sort=p_alpha_sort; s.morph_target_count=mesh->morph_target_count; s.morph_format=s.format; Surface *surface = memnew( Surface ); *surface=s; mesh->surfaces.push_back(surface); }
int RasterizerDummy::mesh_surface_get_array_len(RID p_mesh, int p_surface) const { Mesh *mesh = mesh_owner.get( p_mesh ); ERR_FAIL_COND_V(!mesh,-1); ERR_FAIL_INDEX_V(p_surface, mesh->surfaces.size(), -1 ); Surface *surface = mesh->surfaces[p_surface]; ERR_FAIL_COND_V( !surface, -1 ); Vector3Array arr = surface->data[VS::ARRAY_VERTEX]; return arr.size(); }
//------------------------------------------------------------------------------------------------ bool AnimatedMeshToShapeConverter::getBoneVertices(unsigned char bone, unsigned int &vertex_count, Ogre::Vector3 *&vertices, const Ogre::Vector3 &bonePosition) { BoneIndex::iterator i = mBoneIndex->find(bone); if (i == mBoneIndex->end()) { return false; } Vector3Array *array = i->second; const Vector3Array::size_type size = array->size(); if (size == 0) { return false; } vertex_count = size + 1; if (vertex_count > mTransformedVerticesTempSize) { if (mTransformedVerticesTemp) { delete[] mTransformedVerticesTemp; } mTransformedVerticesTemp = new Ogre::Vector3[vertex_count]; } vertices = mTransformedVerticesTemp; vertices[0] = bonePosition; //mEntity->_getParentNodeFullTransform() * // mEntity->getSkeleton()->getBone(bone)->_getDerivedPosition(); //mEntity->getSkeleton()->getBone(bone)->_getDerivedOrientation() unsigned int currBoneVertex = 1; Vector3Array::iterator j = array->begin(); while (j != array->end()) { vertices[currBoneVertex] = (*j); ++j; ++currBoneVertex; } return true; }
void PhysicsShapeMesh::addMesh(const Vector3Array& vertices, const UintArray& face) noexcept { btIndexedMesh mesh; mesh.m_vertexType = PHY_FLOAT; mesh.m_numVertices = vertices.size(); mesh.m_vertexStride = sizeof(Vector3); mesh.m_vertexBase = (unsigned char*)vertices.data(); mesh.m_indexType = PHY_INTEGER; mesh.m_numTriangles = face.size() / 3; mesh.m_triangleIndexStride = sizeof(std::uint32_t) * 3; mesh.m_triangleIndexBase = (unsigned char*)face.data(); if (face.empty()) { auto array = new btTriangleMesh; for (int i = 0; i < mesh.m_numVertices; i += 3) { btVector3 v1; v1.setX(vertices[i].x); v1.setY(vertices[i].y); v1.setZ(vertices[i].z); btVector3 v2; v2.setX(vertices[i + 1].x); v2.setY(vertices[i + 1].y); v2.setZ(vertices[i + 1].z); btVector3 v3; v3.setX(vertices[i + 2].x); v3.setY(vertices[i + 2].y); v3.setZ(vertices[i + 2].z); array->addTriangle(v1, v2, v3); } _array = array; } else { auto array = new btTriangleIndexVertexArray; array->addIndexedMesh(mesh); _array = array; } }
Vector3Array Curve3D::tesselate(int p_max_stages,float p_tolerance) const { Vector3Array tess; if (points.size()==0) { return tess; } Vector< Map<float,Vector3> > midpoints; midpoints.resize(points.size()-1); int pc=1; for(int i=0;i<points.size()-1;i++) { _bake_segment3d(midpoints[i],0,1,points[i].pos,points[i].out,points[i+1].pos,points[i+1].in,0,p_max_stages,p_tolerance); pc++; pc+=midpoints[i].size(); } tess.resize(pc); Vector3Array::Write bpw=tess.write(); bpw[0]=points[0].pos; int pidx=0; for(int i=0;i<points.size()-1;i++) { for(Map<float,Vector3>::Element *E=midpoints[i].front();E;E=E->next()) { pidx++; bpw[pidx] = E->get(); } pidx++; bpw[pidx] = points[i+1].pos; } bpw=Vector3Array::Write (); return tess; }
////////////////////////////////////////////////////////////////////// // Read a mesh ////////////////////////////////////////////////////////////////////// Mesh *MeshReader::BuildMesh( const string &inputFile ) { // Open the input file ifstream f( inputFile.c_str() ); Real E, v, density; int numGaussPoints; int elementType; int numVertices, numElements, numConstrained; Tuple3i divisions; f >> E; f >> v; f >> density; f >> numGaussPoints; f >> elementType; f >> numVertices; f >> numElements; f >> numConstrained; f >> divisions[ 0 ]; f >> divisions[ 1 ]; f >> divisions[ 2 ]; Vector3Array vertices; for ( int i = 0; i < numVertices; i++ ) { VEC3F p; f >> p[0]; f >> p[1]; f >> p[2]; vertices.push_back( p ); } // Read in elements if ( elementType < 0 || elementType >= Mesh::NUM_ELEMENT_TYPES ) { cout << "Invalid element type!" << endl; return NULL; } IntArray connectivity; if ( elementType == Mesh::ISO_8_NODE ) { for ( int i = 0; i < numElements; i++ ) { for ( int j = 0; j < 8; j++ ) { int nodeNum; f >> nodeNum; connectivity.push_back( nodeNum ); } } } vector<bool> constrained(vertices.size()); for (int i = 0; i < constrained.size(); i++) { constrained.at(i) = false; } // Read in constrained nodes for ( int i = 0; i < numConstrained; i++ ) { int nodeNum; f >> nodeNum; constrained.at(nodeNum) = true; } f.close(); // Finish building the mesh return new Mesh( vertices, (Mesh::ElementType)elementType, connectivity, constrained, E, v, density, numGaussPoints, divisions ); }
//------------------------------------------------------------------------------------------------ void VertexIndexToShape::addAnimatedVertexData(const Ogre::VertexData *vertex_data, const Ogre::VertexData *blend_data, const Ogre::Mesh::IndexMap *indexMap) { // Get the bone index element assert(vertex_data); const Ogre::VertexData *data = blend_data; const unsigned int prev_size = mVertexCount; mVertexCount += (unsigned int)data->vertexCount; Ogre::Vector3 *tmp_vert = new Ogre::Vector3[mVertexCount]; if (mVertexBuffer) { memcpy(tmp_vert, mVertexBuffer, sizeof(Ogre::Vector3) * prev_size); delete[] mVertexBuffer; } mVertexBuffer = tmp_vert; // Get the positional buffer element { const Ogre::VertexElement *posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); assert(posElem); Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); unsigned char *vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); float *pReal; Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; const unsigned int vertexCount = (unsigned int)data->vertexCount; for (unsigned int j = 0; j < vertexCount; ++j) { posElem->baseVertexPointerToElement(vertex, &pReal); vertex += vSize; curVertices->x = (*pReal++); curVertices->y = (*pReal++); curVertices->z = (*pReal++); *curVertices = mTransform * (*curVertices); curVertices++; } vbuf->unlock(); } { const Ogre::VertexElement *bneElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_BLEND_INDICES); assert(bneElem); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(bneElem->getSource()); const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); unsigned char *vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned char *pBone = NULL; if (!mBoneIndex) { mBoneIndex = new BoneIndex(); } Ogre::Vector3 *curVertices = &mVertexBuffer[prev_size]; const unsigned int vertexCount = (unsigned int)vertex_data->vertexCount; for (unsigned int j = 0; j < vertexCount; ++j) { bneElem->baseVertexPointerToElement(vertex, &pBone); vertex += vSize; const unsigned char currBone = (indexMap) ? (*indexMap)[*pBone] : *pBone; const BoneIndex::iterator i = mBoneIndex->find(currBone); Vector3Array *l = NULL; if (i == mBoneIndex->end()) { l = new Vector3Array; mBoneIndex->insert(BoneKeyIndex(currBone, l)); } else { l = i->second; } l->push_back(*curVertices); curVertices++; } vbuf->unlock(); } }
int main(int _argc, const char* _argv[]) { bx::CommandLine cmdLine(_argc, _argv); const char* filePath = cmdLine.findOption('f'); if (NULL == filePath) { help("Input file name must be specified."); return EXIT_FAILURE; } const char* outFilePath = cmdLine.findOption('o'); if (NULL == outFilePath) { help("Output file name must be specified."); return EXIT_FAILURE; } float scale = 1.0f; const char* scaleArg = cmdLine.findOption('s', "scale"); if (NULL != scaleArg) { scale = (float)atof(scaleArg); } cmdLine.hasArg(s_obbSteps, '\0', "obb"); s_obbSteps = bx::uint32_min(bx::uint32_max(s_obbSteps, 1), 90); uint32_t packNormal = 0; cmdLine.hasArg(packNormal, '\0', "packnormal"); uint32_t packUv = 0; cmdLine.hasArg(packUv, '\0', "packuv"); bool ccw = cmdLine.hasArg("ccw"); bool flipV = cmdLine.hasArg("flipv"); bool hasTangent = cmdLine.hasArg("tangent"); FILE* file = fopen(filePath, "r"); if (NULL == file) { printf("Unable to open input file '%s'.", filePath); exit(EXIT_FAILURE); } int64_t parseElapsed = -bx::getHPCounter(); int64_t triReorderElapsed = 0; uint32_t size = (uint32_t)fsize(file); char* data = new char[size+1]; size = (uint32_t)fread(data, 1, size, file); data[size] = '\0'; fclose(file); // https://en.wikipedia.org/wiki/Wavefront_.obj_file Vector3Array positions; Vector3Array normals; Vector3Array texcoords; Index3Map indexMap; TriangleArray triangles; GroupArray groups; uint32_t num = 0; Group group; group.m_startTriangle = 0; group.m_numTriangles = 0; char commandLine[2048]; uint32_t len = sizeof(commandLine); int argc; char* argv[64]; const char* next = data; do { next = bx::tokenizeCommandLine(next, commandLine, len, argc, argv, BX_COUNTOF(argv), '\n'); if (0 < argc) { if (0 == strcmp(argv[0], "#") ) { if (2 < argc && 0 == strcmp(argv[2], "polygons") ) { } } else if (0 == strcmp(argv[0], "f") ) { Triangle triangle; memset(&triangle, 0, sizeof(Triangle) ); for (uint32_t edge = 0, numEdges = argc-1; edge < numEdges; ++edge) { Index3 index; index.m_texcoord = -1; index.m_normal = -1; index.m_vertexIndex = -1; char* vertex = argv[edge+1]; char* texcoord = strchr(vertex, '/'); if (NULL != texcoord) { *texcoord++ = '\0'; char* normal = strchr(texcoord, '/'); if (NULL != normal) { *normal++ = '\0'; index.m_normal = atoi(normal)-1; } index.m_texcoord = atoi(texcoord)-1; } index.m_position = atoi(vertex)-1; uint64_t hash0 = index.m_position; uint64_t hash1 = uint64_t(index.m_texcoord)<<20; uint64_t hash2 = uint64_t(index.m_normal)<<40; uint64_t hash = hash0^hash1^hash2; stl::pair<Index3Map::iterator, bool> result = indexMap.insert(stl::make_pair(hash, index) ); if (!result.second) { Index3& oldIndex = result.first->second; BX_UNUSED(oldIndex); BX_CHECK(oldIndex.m_position == index.m_position && oldIndex.m_texcoord == index.m_texcoord && oldIndex.m_normal == index.m_normal , "Hash collision!" ); } switch (edge) { case 0: case 1: case 2: triangle.m_index[edge] = hash; if (2 == edge) { if (ccw) { std::swap(triangle.m_index[1], triangle.m_index[2]); } triangles.push_back(triangle); } break; default: if (ccw) { triangle.m_index[2] = triangle.m_index[1]; triangle.m_index[1] = hash; } else { triangle.m_index[1] = triangle.m_index[2]; triangle.m_index[2] = hash; } triangles.push_back(triangle); break; } } } else if (0 == strcmp(argv[0], "g") ) { EXPECT(1 < argc); group.m_name = argv[1]; } else if (*argv[0] == 'v') { group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { groups.push_back(group); group.m_startTriangle = (uint32_t)(triangles.size() ); group.m_numTriangles = 0; } if (0 == strcmp(argv[0], "vn") ) { Vector3 normal; normal.x = (float)atof(argv[1]); normal.y = (float)atof(argv[2]); normal.z = (float)atof(argv[3]); normals.push_back(normal); } else if (0 == strcmp(argv[0], "vp") ) { static bool once = true; if (once) { once = false; printf("warning: 'parameter space vertices' are unsupported.\n"); } } else if (0 == strcmp(argv[0], "vt") ) { Vector3 texcoord; texcoord.x = (float)atof(argv[1]); texcoord.y = 0.0f; texcoord.z = 0.0f; switch (argc) { case 4: texcoord.z = (float)atof(argv[3]); // fallthrough case 3: texcoord.y = (float)atof(argv[2]); break; default: break; } texcoords.push_back(texcoord); } else { float px = (float)atof(argv[1]); float py = (float)atof(argv[2]); float pz = (float)atof(argv[3]); float pw = 1.0f; if (argc > 4) { pw = (float)atof(argv[4]); } float invW = scale/pw; px *= invW; py *= invW; pz *= invW; Vector3 pos; pos.x = px; pos.y = py; pos.z = pz; positions.push_back(pos); } } else if (0 == strcmp(argv[0], "usemtl") ) { std::string material(argv[1]); if (material != group.m_material) { group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { groups.push_back(group); group.m_startTriangle = (uint32_t)(triangles.size() ); group.m_numTriangles = 0; } } group.m_material = material; } // unsupported tags // else if (0 == strcmp(argv[0], "mtllib") ) // { // } // else if (0 == strcmp(argv[0], "o") ) // { // } // else if (0 == strcmp(argv[0], "s") ) // { // } } ++num; } while ('\0' != *next); group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { groups.push_back(group); group.m_startTriangle = (uint32_t)(triangles.size() ); group.m_numTriangles = 0; } delete [] data; int64_t now = bx::getHPCounter(); parseElapsed += now; int64_t convertElapsed = -now; std::sort(groups.begin(), groups.end(), GroupSortByMaterial() ); bool hasColor = false; bool hasNormal; bool hasTexcoord; { Index3Map::const_iterator it = indexMap.begin(); hasNormal = -1 != it->second.m_normal; hasTexcoord = -1 != it->second.m_texcoord; if (!hasTexcoord && texcoords.size() == positions.size() ) { hasTexcoord = true; for (Index3Map::iterator it = indexMap.begin(), itEnd = indexMap.end(); it != itEnd; ++it) { it->second.m_texcoord = it->second.m_position; } } if (!hasNormal && normals.size() == positions.size() ) { hasNormal = true; for (Index3Map::iterator it = indexMap.begin(), itEnd = indexMap.end(); it != itEnd; ++it) { it->second.m_normal = it->second.m_position; } } } bgfx::VertexDecl decl; decl.begin(); decl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float); if (hasColor) { decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true); } if (hasTexcoord) { switch (packUv) { default: case 0: decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float); break; case 1: decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Half); break; } } if (hasNormal) { hasTangent &= hasTexcoord; switch (packNormal) { default: case 0: decl.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float); if (hasTangent) { decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Float); } break; case 1: decl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true); if (hasTangent) { decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true); } break; } } decl.end(); uint32_t stride = decl.getStride(); uint8_t* vertexData = new uint8_t[triangles.size() * 3 * stride]; uint16_t* indexData = new uint16_t[triangles.size() * 3]; int32_t numVertices = 0; int32_t numIndices = 0; int32_t numPrimitives = 0; uint8_t* vertices = vertexData; uint16_t* indices = indexData; std::string material = groups.begin()->m_material; PrimitiveArray primitives; bx::CrtFileWriter writer; if (0 != writer.open(outFilePath) ) { printf("Unable to open output file '%s'.", outFilePath); exit(EXIT_FAILURE); } Primitive prim; prim.m_startVertex = 0; prim.m_startIndex = 0; uint32_t positionOffset = decl.getOffset(bgfx::Attrib::Position); uint32_t color0Offset = decl.getOffset(bgfx::Attrib::Color0); uint32_t ii = 0; for (GroupArray::const_iterator groupIt = groups.begin(); groupIt != groups.end(); ++groupIt, ++ii) { for (uint32_t tri = groupIt->m_startTriangle, end = tri + groupIt->m_numTriangles; tri < end; ++tri) { if (material != groupIt->m_material || 65533 < numVertices) { prim.m_numVertices = numVertices - prim.m_startVertex; prim.m_numIndices = numIndices - prim.m_startIndex; if (0 < prim.m_numVertices) { primitives.push_back(prim); } triReorderElapsed -= bx::getHPCounter(); for (PrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt) { const Primitive& prim = *primIt; triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32); } triReorderElapsed += bx::getHPCounter(); if (hasTangent) { calcTangents(vertexData, numVertices, decl, indexData, numIndices); } write(&writer, vertexData, numVertices, decl, indexData, numIndices, material, primitives); primitives.clear(); for (Index3Map::iterator indexIt = indexMap.begin(); indexIt != indexMap.end(); ++indexIt) { indexIt->second.m_vertexIndex = -1; } vertices = vertexData; indices = indexData; numVertices = 0; numIndices = 0; prim.m_startVertex = 0; prim.m_startIndex = 0; ++numPrimitives; material = groupIt->m_material; } Triangle& triangle = triangles[tri]; for (uint32_t edge = 0; edge < 3; ++edge) { uint64_t hash = triangle.m_index[edge]; Index3& index = indexMap[hash]; if (index.m_vertexIndex == -1) { index.m_vertexIndex = numVertices++; float* position = (float*)(vertices + positionOffset); memcpy(position, &positions[index.m_position], 3*sizeof(float) ); if (hasColor) { uint32_t* color0 = (uint32_t*)(vertices + color0Offset); *color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff); } if (hasTexcoord) { float uv[2]; memcpy(uv, &texcoords[index.m_texcoord], 2*sizeof(float) ); if (flipV) { uv[1] = -uv[1]; } bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, decl, vertices); } if (hasNormal) { float normal[4]; bx::vec3Norm(normal, (float*)&normals[index.m_normal]); bgfx::vertexPack(normal, true, bgfx::Attrib::Normal, decl, vertices); } vertices += stride; } *indices++ = (uint16_t)index.m_vertexIndex; ++numIndices; } } if (0 < numVertices) { prim.m_numVertices = numVertices - prim.m_startVertex; prim.m_numIndices = numIndices - prim.m_startIndex; prim.m_name = groupIt->m_name; primitives.push_back(prim); prim.m_startVertex = numVertices; prim.m_startIndex = numIndices; } BX_TRACE("%3d: s %5d, n %5d, %s\n" , ii , groupIt->m_startTriangle , groupIt->m_numTriangles , groupIt->m_material.c_str() ); } if (0 < primitives.size() ) { triReorderElapsed -= bx::getHPCounter(); for (PrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt) { const Primitive& prim = *primIt; triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32); } triReorderElapsed += bx::getHPCounter(); if (hasTangent) { calcTangents(vertexData, numVertices, decl, indexData, numIndices); } write(&writer, vertexData, numVertices, decl, indexData, numIndices, material, primitives); } printf("size: %d\n", uint32_t(writer.seek() ) ); writer.close(); delete [] indexData; delete [] vertexData; now = bx::getHPCounter(); convertElapsed += now; printf("parse %f [s]\ntri reorder %f [s]\nconvert %f [s]\n# %d, g %d, p %d, v %d, i %d\n" , double(parseElapsed)/bx::getHPFrequency() , double(triReorderElapsed)/bx::getHPFrequency() , double(convertElapsed)/bx::getHPFrequency() , num , uint32_t(groups.size() ) , numPrimitives , numVertices , numIndices ); return EXIT_SUCCESS; }
uint32_t objToBin(const uint8_t* _objData , bx::WriterSeekerI* _writer , uint32_t _packUv , uint32_t _packNormal , bool _ccw , bool _flipV , bool _hasTangent , float _scale ) { int64_t parseElapsed = -bx::getHPCounter(); int64_t triReorderElapsed = 0; const int64_t begin = _writer->seek(); Vector3Array positions; Vector3Array normals; Vector3Array texcoords; Index3Map indexMap; TriangleArray triangles; BgfxGroupArray groups; uint32_t num = 0; MeshGroup group; group.m_startTriangle = 0; group.m_numTriangles = 0; group.m_name = ""; group.m_material = ""; char commandLine[2048]; uint32_t len = sizeof(commandLine); int argc; char* argv[64]; const char* next = (const char*)_objData; do { next = bx::tokenizeCommandLine(next, commandLine, len, argc, argv, BX_COUNTOF(argv), '\n'); if (0 < argc) { if (0 == strcmp(argv[0], "#") ) { if (2 < argc && 0 == strcmp(argv[2], "polygons") ) { } } else if (0 == strcmp(argv[0], "f") ) { Triangle triangle; memset(&triangle, 0, sizeof(Triangle) ); const int numNormals = (int)normals.size(); const int numTexcoords = (int)texcoords.size(); const int numPositions = (int)positions.size(); for (uint32_t edge = 0, numEdges = argc-1; edge < numEdges; ++edge) { Index3 index; index.m_texcoord = 0; index.m_normal = 0; index.m_vertexIndex = -1; char* vertex = argv[edge+1]; char* texcoord = strchr(vertex, '/'); if (NULL != texcoord) { *texcoord++ = '\0'; char* normal = strchr(texcoord, '/'); if (NULL != normal) { *normal++ = '\0'; const int nn = atoi(normal); index.m_normal = (nn < 0) ? nn+numNormals : nn-1; } const int tex = atoi(texcoord); index.m_texcoord = (tex < 0) ? tex+numTexcoords : tex-1; } const int pos = atoi(vertex); index.m_position = (pos < 0) ? pos+numPositions : pos-1; uint64_t hash0 = index.m_position; uint64_t hash1 = uint64_t(index.m_texcoord)<<20; uint64_t hash2 = uint64_t(index.m_normal)<<40; uint64_t hash = hash0^hash1^hash2; CS_STL::pair<Index3Map::iterator, bool> result = indexMap.insert(CS_STL::make_pair(hash, index) ); if (!result.second) { Index3& oldIndex = result.first->second; BX_UNUSED(oldIndex); BX_CHECK(oldIndex.m_position == index.m_position && oldIndex.m_texcoord == index.m_texcoord && oldIndex.m_normal == index.m_normal , "Hash collision!" ); } switch (edge) { case 0: case 1: case 2: triangle.m_index[edge] = hash; if (2 == edge) { if (_ccw) { std::swap(triangle.m_index[1], triangle.m_index[2]); } triangles.push_back(triangle); } break; default: if (_ccw) { triangle.m_index[2] = triangle.m_index[1]; triangle.m_index[1] = hash; } else { triangle.m_index[1] = triangle.m_index[2]; triangle.m_index[2] = hash; } triangles.push_back(triangle); break; } } } else if (0 == strcmp(argv[0], "g") ) { if (1 >= argc) { CS_PRINT("Error parsing *.obj file.\n"); return 0; } group.m_name = argv[1]; } else if (*argv[0] == 'v') { group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { groups.push_back(group); group.m_startTriangle = (uint32_t)(triangles.size() ); group.m_numTriangles = 0; } if (0 == strcmp(argv[0], "vn") ) { Vector3 normal; normal.x = (float)atof(argv[1]); normal.y = (float)atof(argv[2]); normal.z = (float)atof(argv[3]); normals.push_back(normal); } else if (0 == strcmp(argv[0], "vp") ) { static bool once = true; if (once) { once = false; CS_PRINT("warning: 'parameter space vertices' are unsupported.\n"); } } else if (0 == strcmp(argv[0], "vt") ) { Vector3 texcoord; texcoord.x = (float)atof(argv[1]); texcoord.y = 0.0f; texcoord.z = 0.0f; switch (argc) { case 4: texcoord.z = (float)atof(argv[3]); // fallthrough case 3: texcoord.y = (float)atof(argv[2]); break; default: break; } texcoords.push_back(texcoord); } else { float px = (float)atof(argv[1]); float py = (float)atof(argv[2]); float pz = (float)atof(argv[3]); float pw = 1.0f; if (argc > 4) { pw = (float)atof(argv[4]); } float invW = _scale/pw; px *= invW; py *= invW; pz *= invW; Vector3 pos; pos.x = px; pos.y = py; pos.z = pz; positions.push_back(pos); } } else if (0 == strcmp(argv[0], "usemtl") ) { std::string material(argv[1]); if (material != group.m_material) { group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { groups.push_back(group); group.m_startTriangle = (uint32_t)(triangles.size() ); group.m_numTriangles = 0; } } group.m_material = material; } // unsupported tags // else if (0 == strcmp(argv[0], "mtllib") ) // { // } // else if (0 == strcmp(argv[0], "o") ) // { // } // else if (0 == strcmp(argv[0], "s") ) // { // } } ++num; } while ('\0' != *next); group.m_numTriangles = (uint32_t)(triangles.size() ) - group.m_startTriangle; if (0 < group.m_numTriangles) { groups.push_back(group); group.m_startTriangle = (uint32_t)(triangles.size() ); group.m_numTriangles = 0; } int64_t now = bx::getHPCounter(); parseElapsed += now; int64_t convertElapsed = -now; std::sort(groups.begin(), groups.end(), GroupSortByMaterial() ); bool hasColor = false; bool hasNormal; bool hasTexcoord; { Index3Map::const_iterator it = indexMap.begin(); hasNormal = 0 != it->second.m_normal; hasTexcoord = 0 != it->second.m_texcoord; if (!hasTexcoord && texcoords.size() == positions.size() ) { hasTexcoord = true; for (Index3Map::iterator it = indexMap.begin(), itEnd = indexMap.end(); it != itEnd; ++it) { it->second.m_texcoord = it->second.m_position; } } if (!hasNormal && normals.size() == positions.size() ) { hasNormal = true; for (Index3Map::iterator it = indexMap.begin(), itEnd = indexMap.end(); it != itEnd; ++it) { it->second.m_normal = it->second.m_position; } } } bgfx::VertexDecl decl; decl.begin(); decl.add(bgfx::Attrib::Position, 3, bgfx::AttribType::Float); if (hasColor) { decl.add(bgfx::Attrib::Color0, 4, bgfx::AttribType::Uint8, true); } if (hasTexcoord) { switch (_packUv) { default: case 0: decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Float); break; case 1: decl.add(bgfx::Attrib::TexCoord0, 2, bgfx::AttribType::Half); break; } } if (hasNormal) { _hasTangent &= hasTexcoord; switch (_packNormal) { default: case 0: decl.add(bgfx::Attrib::Normal, 3, bgfx::AttribType::Float); if (_hasTangent) { decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Float); } break; case 1: decl.add(bgfx::Attrib::Normal, 4, bgfx::AttribType::Uint8, true, true); if (_hasTangent) { decl.add(bgfx::Attrib::Tangent, 4, bgfx::AttribType::Uint8, true, true); } break; } } decl.end(); uint32_t stride = decl.getStride(); uint8_t* vertexData = new uint8_t[triangles.size() * 3 * stride]; uint16_t* indexData = new uint16_t[triangles.size() * 3]; int32_t numVertices = 0; int32_t numIndices = 0; int32_t numPrimitives = 0; uint8_t* vertices = vertexData; uint16_t* indices = indexData; std::string material = groups.begin()->m_material; BgfxPrimitiveArray primitives; Primitive prim; prim.m_startVertex = 0; prim.m_startIndex = 0; uint32_t positionOffset = decl.getOffset(bgfx::Attrib::Position); uint32_t color0Offset = decl.getOffset(bgfx::Attrib::Color0); uint32_t ii = 0; for (BgfxGroupArray::const_iterator groupIt = groups.begin(); groupIt != groups.end(); ++groupIt, ++ii) { for (uint32_t tri = groupIt->m_startTriangle, end = tri + groupIt->m_numTriangles; tri < end; ++tri) { if (material != groupIt->m_material || 65533 < numVertices) { prim.m_numVertices = numVertices - prim.m_startVertex; prim.m_numIndices = numIndices - prim.m_startIndex; if (0 < prim.m_numVertices) { primitives.push_back(prim); } triReorderElapsed -= bx::getHPCounter(); for (BgfxPrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt) { const Primitive& prim = *primIt; triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32); } triReorderElapsed += bx::getHPCounter(); if (_hasTangent) { calculateTangents(vertexData, numVertices, decl, indexData, numIndices); } write(_writer , vertexData , numVertices , decl , indexData , numIndices , material.c_str() , primitives.data() , (uint32_t)primitives.size() ); primitives.clear(); for (Index3Map::iterator indexIt = indexMap.begin(); indexIt != indexMap.end(); ++indexIt) { indexIt->second.m_vertexIndex = -1; } vertices = vertexData; indices = indexData; numVertices = 0; numIndices = 0; prim.m_startVertex = 0; prim.m_startIndex = 0; ++numPrimitives; material = groupIt->m_material; } Triangle& triangle = triangles[tri]; for (uint32_t edge = 0; edge < 3; ++edge) { uint64_t hash = triangle.m_index[edge]; Index3& index = indexMap[hash]; if (index.m_vertexIndex == -1) { index.m_vertexIndex = numVertices++; float* position = (float*)(vertices + positionOffset); memcpy(position, &positions[index.m_position], 3*sizeof(float) ); if (hasColor) { uint32_t* color0 = (uint32_t*)(vertices + color0Offset); *color0 = rgbaToAbgr(numVertices%255, numIndices%255, 0, 0xff); } if (hasTexcoord) { float uv[2]; memcpy(uv, &texcoords[index.m_texcoord], 2*sizeof(float) ); if (_flipV) { uv[1] = -uv[1]; } bgfx::vertexPack(uv, true, bgfx::Attrib::TexCoord0, decl, vertices); } if (hasNormal) { float normal[4]; bx::vec3Norm(normal, (float*)&normals[index.m_normal]); bgfx::vertexPack(normal, true, bgfx::Attrib::Normal, decl, vertices); } vertices += stride; } *indices++ = (uint16_t)index.m_vertexIndex; ++numIndices; } } if (0 < numVertices) { prim.m_numVertices = numVertices - prim.m_startVertex; prim.m_numIndices = numIndices - prim.m_startIndex; bx::strlcpy(prim.m_name, groupIt->m_name.c_str(), 128); primitives.push_back(prim); prim.m_startVertex = numVertices; prim.m_startIndex = numIndices; } //CS_PRINT("%3d: s %5d, n %5d, %s\n" // , ii // , groupIt->m_startTriangle // , groupIt->m_numTriangles // , groupIt->m_material.c_str() // ); } if (0 < primitives.size() ) { triReorderElapsed -= bx::getHPCounter(); for (BgfxPrimitiveArray::const_iterator primIt = primitives.begin(); primIt != primitives.end(); ++primIt) { const Primitive& prim = *primIt; triangleReorder(indexData + prim.m_startIndex, prim.m_numIndices, numVertices, 32); } triReorderElapsed += bx::getHPCounter(); if (_hasTangent) { calculateTangents(vertexData, numVertices, decl, indexData, numIndices); } write(_writer, vertexData, numVertices, decl, indexData, numIndices, material.c_str(), primitives.data(), (uint32_t)primitives.size()); } delete [] indexData; delete [] vertexData; now = bx::getHPCounter(); convertElapsed += now; const int64_t end = _writer->seek(); const uint32_t dataSize = uint32_t(end-begin); CS_PRINT("size: %u\n", dataSize); CS_PRINT("parse %f [s]\ntri reorder %f [s]\nconvert %f [s]\n# %d, g %d, p %d, v %d, i %d\n" , double(parseElapsed)/bx::getHPFrequency() , double(triReorderElapsed)/bx::getHPFrequency() , double(convertElapsed)/bx::getHPFrequency() , num , uint32_t(groups.size() ) , numPrimitives , numVertices , numIndices ); return dataSize; }
bool PMDHandler::doLoad(Model& model, istream& stream) noexcept { PMD _pmd; if (!stream.read((char*)&_pmd.Header, sizeof(_pmd.Header))) return false; // vertex if (!stream.read((char*)&_pmd.VertexCount, sizeof(_pmd.VertexCount))) return false; if (_pmd.VertexCount > 0) { _pmd.VertexList.resize(_pmd.VertexCount); if (!stream.read((char*)&_pmd.VertexList[0], (std::streamsize)(sizeof(PMD_Vertex)* _pmd.VertexCount))) return false; } // index if (!stream.read((char*)&_pmd.IndexCount, sizeof(_pmd.IndexCount))) return false; if (_pmd.IndexCount > 0) { _pmd.IndexList.resize(_pmd.IndexCount); if (!stream.read((char*)&_pmd.IndexList[0], (std::streamsize)(sizeof(PMD_Index)* _pmd.IndexCount))) return false; } // materal if (!stream.read((char*)&_pmd.MaterialCount, sizeof(_pmd.MaterialCount))) return false; if (_pmd.MaterialCount > 0) { _pmd.MaterialList.resize(_pmd.MaterialCount); if (!stream.read((char*)&_pmd.MaterialList[0], (std::streamsize)(sizeof(PMD_Material)* _pmd.MaterialCount))) return false; } // bone if (!stream.read((char*)&_pmd.BoneCount, sizeof(_pmd.BoneCount))) return false; if (_pmd.BoneCount > 0) { _pmd.BoneList.resize(_pmd.BoneCount); if (!stream.read((char*)&_pmd.BoneList[0], (std::streamsize)(sizeof(PMD_Bone)* _pmd.BoneCount))) return false; } // IK if (!stream.read((char*)&_pmd.IkCount, sizeof(_pmd.IkCount))) return false; if (_pmd.IkCount > 0) { _pmd.IkList.resize(_pmd.IkCount); for (std::size_t i = 0; i < (std::size_t)_pmd.IkCount; i++) { if (!stream.read((char*)&_pmd.IkList[i].IK, sizeof(_pmd.IkList[i].IK))) return false; if (!stream.read((char*)&_pmd.IkList[i].Target, sizeof(_pmd.IkList[i].Target))) return false; if (!stream.read((char*)&_pmd.IkList[i].LinkCount, sizeof(_pmd.IkList[i].LinkCount))) return false; if (!stream.read((char*)&_pmd.IkList[i].LoopCount, sizeof(_pmd.IkList[i].LoopCount))) return false; if (!stream.read((char*)&_pmd.IkList[i].LimitOnce, sizeof(_pmd.IkList[i].LimitOnce))) return false; _pmd.IkList[i].LinkList.resize(_pmd.IkList[i].LinkCount); if (!stream.read((char*)&_pmd.IkList[i].LinkList[0], (std::streamsize)(sizeof(PMD_Link)* _pmd.IkList[i].LinkCount))) return false; } } // Morph if (!stream.read((char*)&_pmd.MorphCount, sizeof(_pmd.MorphCount))) return false; if (_pmd.MorphCount > 0) { _pmd.MorphList.resize(_pmd.MorphCount); for (std::size_t i = 0; i < (std::size_t)_pmd.MorphCount; i++) { if (!stream.read((char*)&_pmd.MorphList[i].Name, sizeof(_pmd.MorphList[i].Name))) return false; if (!stream.read((char*)&_pmd.MorphList[i].VertexCount, sizeof(_pmd.MorphList[i].VertexCount))) return false; if (!stream.read((char*)&_pmd.MorphList[i].Category, sizeof(_pmd.MorphList[i].Category))) return false; if (_pmd.MorphList[i].VertexCount > 0) { _pmd.MorphList[i].VertexList.resize(_pmd.MorphList[i].VertexCount); if (!stream.read((char*)&_pmd.MorphList[i].VertexList[0], (std::streamsize)(sizeof(PMD_MorphVertex)* _pmd.MorphList[i].VertexCount))) return false; } } } // frame window if (!stream.read((char*)&_pmd.FrameWindow.ExpressionListCount, sizeof(_pmd.FrameWindow.ExpressionListCount))) return false; if (_pmd.FrameWindow.ExpressionListCount > 0) { _pmd.FrameWindow.ExpressionList.resize(_pmd.FrameWindow.ExpressionListCount); if (!stream.read((char*)&_pmd.FrameWindow.ExpressionList[0], (std::streamsize)(sizeof(PMD_Expression)* _pmd.FrameWindow.ExpressionListCount))) return false; } if (!stream.read((char*)&_pmd.FrameWindow.NodeNameCount, sizeof(_pmd.FrameWindow.NodeNameCount))) return false; if (_pmd.FrameWindow.NodeNameCount > 0) { _pmd.FrameWindow.NodeNameList.resize(_pmd.FrameWindow.NodeNameCount); if (!stream.read((char*)&_pmd.FrameWindow.NodeNameList[0].Name, (std::streamsize)(sizeof(PMD_NodeName)* _pmd.FrameWindow.NodeNameCount))) return false; } if (!stream.read((char*)&_pmd.FrameWindow.BoneToNodeCount, sizeof(_pmd.FrameWindow.BoneToNodeCount))) return false; if (_pmd.FrameWindow.BoneToNodeCount > 0) { _pmd.FrameWindow.BoneToNodeList.resize(_pmd.FrameWindow.BoneToNodeCount); if (!stream.read((char*)&_pmd.FrameWindow.BoneToNodeList[0].Bone, (std::streamsize)(sizeof(PMD_BoneToNode)* _pmd.FrameWindow.BoneToNodeCount))) return false; } // description if (!stream.read((char*)&_pmd.HasDescription, sizeof(_pmd.HasDescription))) return false; if (_pmd.HasDescription) { if (!stream.read((char*)&_pmd.Description.ModelName, sizeof(_pmd.Description.ModelName))) return false; if (!stream.read((char*)&_pmd.Description.Comment, sizeof(_pmd.Description.Comment))) return false; for (PMD_BoneCount i = 0; i < _pmd.BoneCount; i++) { PMD_BoneName name; if (!stream.read((char*)&name.Name, sizeof(name))) return false; _pmd.Description.BoneName.push_back(name); } for (PMD_uint8_t i = 0; i < _pmd.FrameWindow.ExpressionListCount; i++) { PMD_MorphName name; if (!stream.read((char*)&name.Name, sizeof(name))) return false; _pmd.Description.FaceName.push_back(name); } for (PMD_uint8_t i = 0; i < _pmd.FrameWindow.NodeNameCount; i++) { PMD_NodeName name; if (!stream.read((char*)&name.Name, sizeof(name))) return false; _pmd.Description.FrameName.push_back(name); } } // toon _pmd.ToonCount = PMD_NUM_TOON; _pmd.ToonList.resize(_pmd.ToonCount); if (!stream.read((char*)&_pmd.ToonList[0].Name, (std::streamsize)(sizeof(PMD_Toon) * _pmd.ToonCount))) return false; // rigidbody if (!stream.read((char*)&_pmd.BodyCount, sizeof(_pmd.BodyCount))) return false; if (_pmd.BodyCount > 0) { _pmd.BodyList.resize(_pmd.BodyCount); if (!stream.read((char*)&_pmd.BodyList[0], (std::streamsize)(sizeof(PMD_Body)* _pmd.BodyCount))) return false; } // joint if (!stream.read((char*)&_pmd.JointCount, sizeof(_pmd.JointCount))) return false; if (_pmd.JointCount > 0) { _pmd.JointList.resize(_pmd.JointCount); if (!stream.read((char*)&_pmd.JointList[0], (std::streamsize)(sizeof(PMD_Body)* _pmd.JointCount))) return false; } for (std::size_t index = 0; index < _pmd.MaterialList.size(); index++) { auto& it = _pmd.MaterialList[index]; auto material = std::make_shared<MaterialProperty>(); material->set(MATKEY_COLOR_DIFFUSE, it.Diffuse); material->set(MATKEY_COLOR_AMBIENT, it.Ambient); material->set(MATKEY_COLOR_SPECULAR, it.Specular); material->set(MATKEY_OPACITY, it.Opacity); material->set(MATKEY_SHININESS, it.Shininess); std::string name = it.TextureName; std::string::size_type substr = name.find_first_of("*"); if (substr != std::string::npos) { name.erase(name.begin() + substr, name.end()); } material->set(MATKEY_TEXTURE_DIFFUSE(0), name); material->set(MATKEY_TEXTURE_AMBIENT(0), name); model.addMaterial(material); } PMD_Index* indices = _pmd.IndexList.data(); PMD_Vertex* vertices = _pmd.VertexList.data(); MeshPropertyPtr root = std::make_shared<MeshProperty>(); MeshPropertyPtr mesh = root; MeshPropertyPtr last = nullptr; for (std::size_t index = 0; index < _pmd.MaterialList.size(); index++) { auto& it = _pmd.MaterialList[index]; Vector3Array points; Vector3Array normals; Vector2Array texcoords; VertexWeights weights; UintArray faces; for (PMD_IndexCount i = 0; i < it.FaceVertexCount; i++, indices++) { PMD_Vertex& v = vertices[*indices]; points.push_back(v.Position); normals.push_back(v.Normal); texcoords.push_back(v.UV); faces.push_back(i); VertexWeight weight; weight.weight1 = v.Weight / 100.0; weight.weight2 = 1.0 - weight.weight1; weight.weight3 = 0.0f; weight.weight4 = 0.0f; weight.bone1 = v.Bone.Bone1; weight.bone2 = v.Bone.Bone2; weight.bone3 = 0; weight.bone4 = 0; weights.push_back(weight); } if (last == mesh) { mesh = std::make_shared<MeshProperty>(); root->addChild(mesh); } mesh->setMaterialID(index); mesh->setVertexArray(points); mesh->setNormalArray(normals); mesh->setTexcoordArray(texcoords); mesh->setWeightArray(weights); mesh->setFaceArray(faces); last = mesh; } if (_pmd.BoneCount > 0) { Bones bones; InverseKinematics iks; for (auto& it : _pmd.BoneList) { Bone bone; char inbuf[MAX_PATH + 1] = { 0 }; char outbuf[MAX_PATH + 1] = { 0 }; char *in = inbuf; char *out = outbuf; std::size_t in_size = (size_t)MAX_PATH; std::size_t out_size = (size_t)MAX_PATH; memcpy(in, it.Name.Name, sizeof(it.Name.Name)); iconv_t ic = iconv_open("GBK", "SJIS"); iconv(ic, &in, &in_size, &out, &out_size); iconv_close(ic); bone.setName(std::string(outbuf)); bone.setPosition(it.Position); bone.setParent(it.Parent); bone.setChild(it.Child); bones.push_back(bone); } for (auto& it : _pmd.IkList) { IKAttr attr; attr.IKBoneIndex = it.IK; attr.IKTargetBoneIndex = it.Target; attr.IKLimitedRadian = it.LimitOnce; attr.IKLinkCount = it.LinkCount; attr.IKLoopCount = it.LoopCount; for (auto& bone : it.LinkList) { IKChild child; child.BoneIndex = bone; child.MinimumRadian = Vector3::Zero; child.MaximumRadian = Vector3(3.14, 3.14, 3.14); child.RotateLimited = 1; attr.IKList.push_back(child); } iks.push_back(attr); } root->setInverseKinematics(iks); root->setBoneArray(bones); } model.addMesh(root); return true; }
bool SDKMeshHandler::doLoad(Model& model, istream& stream) noexcept { SDKMESH_HEADER hdr; if (!stream.read((char*)&hdr, sizeof(hdr))) return false; std::vector<SDKMESH_VERTEX_BUFFER_HEADER> vbs; std::vector<SDKMESH_INDEX_BUFFER_HEADER> ibs; std::vector<SDKMESH_MESH> meshes; std::vector<SDKMESH_MATERIAL> materials; vbs.resize(hdr.NumVertexBuffers); ibs.resize(hdr.NumIndexBuffers); meshes.resize(hdr.NumMeshes); materials.resize(hdr.NumMaterials); if (!stream.seekg(hdr.VertexStreamHeadersOffset, ios_base::beg)) return false; if (!stream.read((char*)vbs.data(), sizeof(SDKMESH_VERTEX_BUFFER_HEADER) * hdr.NumVertexBuffers)) return false; if (!stream.seekg(hdr.IndexStreamHeadersOffset, ios_base::beg)) return false; if (!stream.read((char*)ibs.data(), sizeof(SDKMESH_INDEX_BUFFER_HEADER) * hdr.NumIndexBuffers)) return false; if (!stream.seekg(hdr.MeshDataOffset, ios_base::beg)) return false; if (!stream.read((char*)meshes.data(), sizeof(SDKMESH_MESH) * hdr.NumMeshes)) return false; if (!stream.seekg(hdr.MaterialDataOffset, ios_base::beg)) return false; if (!stream.read((char*)materials.data(), sizeof(SDKMESH_MATERIAL) * hdr.NumMaterials)) return false; Vector3Array vertices; Vector3Array normals; Vector3Array tangets; Vector2Array texcoord; UintArray faces; MeshPropertyPtr root = nullptr; for (auto& it : materials) { auto material = std::make_shared<MaterialProperty>(); material->set(MATKEY_NAME, it.Name); material->set(MATKEY_COLOR_DIFFUSE, it.Diffuse); material->set(MATKEY_COLOR_AMBIENT, it.Ambient); material->set(MATKEY_COLOR_SPECULAR, Vector3(0.5,0.5,0.5)); material->set(MATKEY_SHININESS, it.Power); if (it.DiffuseTexture[0] != 0) { material->set(MATKEY_TEXTURE_DIFFUSE(0), it.DiffuseTexture); material->set(MATKEY_TEXTURE_AMBIENT(0), it.DiffuseTexture); } if (it.NormalTexture[0] != 0) { material->set(MATKEY_TEXTURE_NORMALS(0), it.NormalTexture); } if (it.SpecularTexture[0] != 0) { material->set(MATKEY_TEXTURE_SPECULAR(0), it.SpecularTexture); } model.addMaterial(material); } for (std::size_t meshIndex = 0; meshIndex < hdr.NumMeshes; meshIndex++) { auto& mesh = meshes[meshIndex]; for (std::size_t i = 0; i < mesh.NumVertexBuffers; i++) { stream.seekg(vbs[i].DataOffset, ios_base::beg); for (std::size_t j = 0; j < vbs[i].NumVertices; j++) { std::uint8_t offset = 0; std::uint8_t buffer[MAX_VERTEX_BUFFER]; stream.read((char*)buffer, vbs[i].StrideBytes); for (std::size_t element = 0; element < MAX_VERTEX_ELEMENTS; element++) { if (vbs[i].Decl[element].Stream != 0) { offset = 0; break; } if (vbs[i].Decl[element].Usage == USAGE_POSITION) { vertices.push_back(*(Vector3*)((char*)&buffer + offset)); offset += sizeof(Vector3); } else if (vbs[i].Decl[element].Usage == USAGE_NORMAL) { normals.push_back(*(Vector3*)((char*)&buffer + offset)); offset += sizeof(Vector3); } else if (vbs[i].Decl[element].Usage == USAGE_TANGENT) { tangets.push_back(*(Vector3*)((char*)&buffer + offset)); offset += sizeof(Vector3); } else if (vbs[i].Decl[element].Usage == USAGE_TEXCOORD) { texcoord.push_back(*(Vector2*)((char*)&buffer + offset)); offset += sizeof(Vector2); } } } } stream.seekg(ibs[mesh.IndexBuffer].DataOffset, ios_base::beg); auto sizeofdata = ibs[mesh.IndexBuffer].SizeBytes / ibs[mesh.IndexBuffer].NumIndices; for (std::size_t j = 0; j < ibs[mesh.IndexBuffer].NumIndices; j++) { std::uint32_t buffer = 0; stream.read((char*)&buffer, sizeofdata); faces.push_back(buffer); } MeshPropertyPtr subset = std::make_shared<MeshProperty>(); subset->setMaterialID(0); subset->setVertexArray(vertices); subset->setNormalArray(normals); subset->setTexcoordArray(texcoord); subset->setTangentArray(tangets); subset->setFaceArray(faces); if (root) root->addChild(subset); else root = subset; } model.addMesh(root); return true; }