bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("solid ",6); const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh)); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u32 indexCount = buffer->getIndexCount(); for (u32 j=0; j<indexCount; j+=3) { writeFace(file, buffer->getPosition(buffer->getIndices()[j]), buffer->getPosition(buffer->getIndices()[j+1]), buffer->getPosition(buffer->getIndices()[j+2])); } file->write("\n",1); } } file->write("endsolid ",9); file->write(name.c_str(),name.size()); return true; }
void CTriangleSelector::updateFromMesh(const IMesh* mesh) const { if (!mesh) return; u32 meshBuffers = mesh->getMeshBufferCount(); u32 triangleCount = 0; BoundingBox.reset(0.f, 0.f, 0.f); for (u32 i = 0; i < meshBuffers; ++i) { IMeshBuffer* buf = mesh->getMeshBuffer(i); u32 idxCnt = buf->getIndexCount(); const u16* indices = buf->getIndices(); for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df& tri = Triangles[triangleCount++]; tri.pointA = buf->getPosition(indices[index + 0]); tri.pointB = buf->getPosition(indices[index + 1]); tri.pointC = buf->getPosition(indices[index + 2]); BoundingBox.addInternalPoint(tri.pointA); BoundingBox.addInternalPoint(tri.pointB); BoundingBox.addInternalPoint(tri.pointC); } } }
bool CSTLMeshWriter::writeMeshASCII(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("solid ",6); const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u16 indexCount = buffer->getIndexCount(); switch(buffer->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); for (u32 j=0; j<indexCount; j+=3) writeFace(file, vtx[buffer->getIndices()[j]].Pos, vtx[buffer->getIndices()[j+1]].Pos, vtx[buffer->getIndices()[j+2]].Pos); } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); for (u32 j=0; j<indexCount; j+=3) writeFace(file, vtx[buffer->getIndices()[j]].Pos, vtx[buffer->getIndices()[j+1]].Pos, vtx[buffer->getIndices()[j+2]].Pos); } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); for (u32 j=0; j<indexCount; j+=3) writeFace(file, vtx[buffer->getIndices()[j]].Pos, vtx[buffer->getIndices()[j+1]].Pos, vtx[buffer->getIndices()[j+2]].Pos); } break; } file->write("\n",1); } } file->write("endsolid ",9); file->write(name.c_str(),name.size()); return true; }
CPlanarShadow::CPlanarShadow(scene::ISceneNode*parent, scene::ISceneManager *mgr, IMesh *mesh, float divisor) : ISceneNode(parent, mgr, -1), Vertices(0), Indices(0), SceneManager(mgr), Divisor(divisor), enableDepth(false) { s32 i; s32 totalVertices = 0; s32 totalIndices = 0; s32 bufcnt = mesh->getMeshBufferCount(); IMeshBuffer* b; for (i=0; i<bufcnt; ++i) { b = mesh->getMeshBuffer(i); totalIndices += b->getIndexCount(); totalVertices += b->getVertexCount(); } Vertices = new core::vector3df[totalVertices]; Indices = new u16[totalIndices]; int indStart = 0, vtxNow = 0; for (i=0; i < bufcnt; ++i) { b = mesh->getMeshBuffer(i); u16* buff = b->getIndices(); for (int o = 0; o < b->getIndexCount(); o++) { Indices[indStart++] = buff[o] + vtxNow; } vtxNow += b->getVertexCount(); } VertexCount = totalVertices; IndexCount = totalIndices; buildMesh(mesh); }
void CTriangleSelector::updateFromMesh(const IMesh* mesh) const { if (!mesh) return; u32 meshBuffers = mesh->getMeshBufferCount(); u32 triangleCount = 0; for (u32 i = 0; i < meshBuffers; ++i) { IMeshBuffer* buf = mesh->getMeshBuffer(i); u32 idxCnt = buf->getIndexCount(); const u16* indices = buf->getIndices(); switch (buf->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buf->getVertices(); for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df & tri = Triangles[triangleCount++]; tri.pointA = vtx[indices[index + 0]].Pos; tri.pointB = vtx[indices[index + 1]].Pos; tri.pointC = vtx[indices[index + 2]].Pos; } } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buf->getVertices(); for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df & tri = Triangles[triangleCount++]; tri.pointA = vtx[indices[index + 0]].Pos; tri.pointB = vtx[indices[index + 1]].Pos; tri.pointC = vtx[indices[index + 2]].Pos; } } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buf->getVertices(); for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df & tri = Triangles[triangleCount++]; tri.pointA = vtx[indices[index + 0]].Pos; tri.pointB = vtx[indices[index + 1]].Pos; tri.pointC = vtx[indices[index + 2]].Pos; } } break; } } }
//----------------------------------------------------------------------- // e x t r a c t T r i a n g l e s //----------------------------------------------------------------------- btTriangleMesh* TMeshShape::extractTriangles(IMesh* mesh, bool removeDupVertices) { vector3df p1, p2, p3; // 32 bit indices, 3 component vertices - allows for use in decomposition. btTriangleMesh* triMesh = new btTriangleMesh(true, false); u32 bufCount = mesh->getMeshBufferCount(); for(u32 i=0;i<bufCount;i++) { IMeshBuffer* mbuf = mesh->getMeshBuffer(i); void* vp = mbuf->getVertices(); E_VERTEX_TYPE vtype = mbuf->getVertexType(); S3DVertex *vstd = (S3DVertex*) vp; S3DVertex2TCoords *v2t = (S3DVertex2TCoords*) vp; S3DVertexTangents *vtan = (S3DVertexTangents*)vp; const u16* ip = mbuf->getIndices(); u32 ic = mbuf->getIndexCount(); u32 fi = 0; while(fi < ic) { S3DVertex *v1,*v2,*v3; switch(vtype) { case EVT_2TCOORDS: v1 = &v2t[ip[fi++]]; v2 = &v2t[ip[fi++]]; v3 = &v2t[ip[fi++]]; break; case EVT_TANGENTS: v1 = &vtan[ip[fi++]]; v2 = &vtan[ip[fi++]]; v3 = &vtan[ip[fi++]]; break; default: v1 = &vstd[ip[fi++]]; v2 = &vstd[ip[fi++]]; v3 = &vstd[ip[fi++]]; break; } p1 = v1->Pos; p2 = v2->Pos; p3 = v3->Pos; btVector3 b1(p1.X, p1.Y, p1.Z); btVector3 b2(p2.X, p2.Y, p2.Z); btVector3 b3(p3.X, p3.Y, p3.Z); triMesh->addTriangle(b1,b2,b3,removeDupVertices); } } return triMesh; }
bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("binary ",7); const core::stringc name(SceneManager->getMeshCache()->getMeshName(mesh)); const s32 sizeleft = 73-name.size(); // 80 byte header if (sizeleft<0) file->write(name.c_str(),73); else { char* buf = new char[80]; memset(buf, 0, 80); file->write(name.c_str(),name.size()); file->write(buf,sizeleft); delete [] buf; } u32 facenum = 0; for (u32 j=0; j<mesh->getMeshBufferCount(); ++j) facenum += mesh->getMeshBuffer(j)->getIndexCount()/3; file->write(&facenum,4); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u32 indexCount = buffer->getIndexCount(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { const core::vector3df& v1 = buffer->getPosition(buffer->getIndices()[j]); const core::vector3df& v2 = buffer->getPosition(buffer->getIndices()[j+1]); const core::vector3df& v3 = buffer->getPosition(buffer->getIndices()[j+2]); const core::plane3df tmpplane(v1,v2,v3); file->write(&tmpplane.Normal, 12); file->write(&v1, 12); file->write(&v2, 12); file->write(&v3, 12); file->write(&attributes, 2); } } } return true; }
void CTriangleSelector::updateFromMesh(const IMesh* mesh) const { if (!mesh) return; bool skinnnedMesh = mesh->getMeshType() == EAMT_SKINNED; u32 meshBuffers = mesh->getMeshBufferCount(); u32 triangleCount = 0; BoundingBox.reset(0.f, 0.f, 0.f); for (u32 i = 0; i < meshBuffers; ++i) { IMeshBuffer* buf = mesh->getMeshBuffer(i); u32 idxCnt = buf->getIndexCount(); const u16* indices = buf->getIndices(); if ( skinnnedMesh ) { const core::matrix4& bufferTransform = ((scene::SSkinMeshBuffer*)buf)->Transformation; for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df& tri = Triangles[triangleCount++]; bufferTransform.transformVect(tri.pointA, buf->getPosition(indices[index + 0])); bufferTransform.transformVect(tri.pointB, buf->getPosition(indices[index + 1])); bufferTransform.transformVect(tri.pointC, buf->getPosition(indices[index + 2])); BoundingBox.addInternalPoint(tri.pointA); BoundingBox.addInternalPoint(tri.pointB); BoundingBox.addInternalPoint(tri.pointC); } } else { for (u32 index = 0; index < idxCnt; index += 3) { core::triangle3df& tri = Triangles[triangleCount++]; tri.pointA = buf->getPosition(indices[index + 0]); tri.pointB = buf->getPosition(indices[index + 1]); tri.pointC = buf->getPosition(indices[index + 2]); BoundingBox.addInternalPoint(tri.pointA); BoundingBox.addInternalPoint(tri.pointB); BoundingBox.addInternalPoint(tri.pointC); } } } }
btSoftBody* MeshTools::createSoftBodyFromMesh(btSoftBodyWorldInfo& worldInfo, IMesh* mesh) { IMeshBuffer* buffer = mesh->getMeshBuffer(0); vector<btScalar> vertices; for (unsigned int i=0; i < buffer->getVertexCount(); ++i) { vector3df p = getBaseVertex(buffer, i).Pos; vertices.push_back(p.X); vertices.push_back(p.Y); vertices.push_back(p.Z); } vector<int> triangles; for (unsigned int i=0; i < buffer->getIndexCount(); ++i) triangles.push_back(buffer->getIndices()[i]); auto result = btSoftBodyHelpers::CreateFromTriMesh(worldInfo, &vertices[0], &triangles[0], buffer->getIndexCount()/3, false); result->m_bUpdateRtCst = true; return result; }
//! creates the tree bool COctTreeSceneNode::createTree(IMesh* mesh) { if (!mesh) return false; MeshName = SceneManager->getMeshCache()->getMeshFilename( mesh ); deleteTree(); u32 beginTime = os::Timer::getRealTime(); u32 nodeCount = 0; u32 polyCount = 0; Box = mesh->getBoundingBox(); if (mesh->getMeshBufferCount()) { vertexType = mesh->getMeshBuffer(0)->getVertexType(); switch(vertexType) { case video::EVT_STANDARD: { for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); StdMeshes.push_back(OctTree<video::S3DVertex>::SMeshChunk()); OctTree<video::S3DVertex>::SMeshChunk &nchunk = StdMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); for (v=0; v<b->getVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertex*)b->getVertices())[v]); polyCount += b->getIndexCount(); nchunk.Indices.reallocate(b->getIndexCount()); for (v=0; v<b->getIndexCount(); ++v) nchunk.Indices.push_back(b->getIndices()[v]); } } StdOctTree = new OctTree<video::S3DVertex>(StdMeshes, MinimalPolysPerNode); nodeCount = StdOctTree->getNodeCount(); } break; case video::EVT_2TCOORDS: { for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); LightMapMeshes.push_back(OctTree<video::S3DVertex2TCoords>::SMeshChunk()); OctTree<video::S3DVertex2TCoords>::SMeshChunk& nchunk = LightMapMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); for (v=0; v<b->getVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertex2TCoords*)b->getVertices())[v]); polyCount += b->getIndexCount(); nchunk.Indices.reallocate(b->getIndexCount()); for (v=0; v<b->getIndexCount(); ++v) nchunk.Indices.push_back(b->getIndices()[v]); } } LightMapOctTree = new OctTree<video::S3DVertex2TCoords>(LightMapMeshes, MinimalPolysPerNode); nodeCount = LightMapOctTree->getNodeCount(); } break; case video::EVT_TANGENTS: { for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* b = mesh->getMeshBuffer(i); if (b->getVertexCount() && b->getIndexCount()) { Materials.push_back(b->getMaterial()); TangentsMeshes.push_back(OctTree<video::S3DVertexTangents>::SMeshChunk()); OctTree<video::S3DVertexTangents>::SMeshChunk& nchunk = TangentsMeshes.getLast(); nchunk.MaterialId = Materials.size() - 1; u32 v; nchunk.Vertices.reallocate(b->getVertexCount()); for (v=0; v<b->getVertexCount(); ++v) nchunk.Vertices.push_back(((video::S3DVertexTangents*)b->getVertices())[v]); polyCount += b->getIndexCount(); nchunk.Indices.reallocate(b->getIndexCount()); for (v=0; v<b->getIndexCount(); ++v) nchunk.Indices.push_back(b->getIndices()[v]); } } TangentsOctTree = new OctTree<video::S3DVertexTangents>(TangentsMeshes, MinimalPolysPerNode); nodeCount = TangentsOctTree->getNodeCount(); } break; } } u32 endTime = os::Timer::getRealTime(); c8 tmp[255]; sprintf(tmp, "Needed %ums to create OctTree SceneNode.(%u nodes, %u polys)", endTime - beginTime, nodeCount, polyCount/3); os::Printer::log(tmp, ELL_INFORMATION); return true; }
bool CSTLMeshWriter::writeMeshBinary(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { // write STL MESH header file->write("binary ",7); const core::stringc name(SceneManager->getMeshCache()->getMeshFilename(mesh)); const s32 sizeleft = 73-name.size(); // 80 byte header if (sizeleft<0) file->write(name.c_str(),73); else { char* buf = new char[80]; memset(buf, 0, 80); file->write(name.c_str(),name.size()); file->write(buf,sizeleft); delete [] buf; } u32 facenum = 0; for (u32 j=0; j<mesh->getMeshBufferCount(); ++j) facenum += mesh->getMeshBuffer(j)->getIndexCount()/3; file->write(&facenum,4); // write mesh buffers for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer) { const u16 indexCount = buffer->getIndexCount(); switch(buffer->getVertexType()) { case video::EVT_STANDARD: { video::S3DVertex* vtx = (video::S3DVertex*)buffer->getVertices(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { file->write(&core::plane3df(vtx[buffer->getIndices()[j]].Pos,vtx[buffer->getIndices()[j+1]].Pos,vtx[buffer->getIndices()[j+2]].Pos).Normal, 12); file->write(&vtx[buffer->getIndices()[j]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+1]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+2]].Pos, 12); file->write(&attributes, 2); } } break; case video::EVT_2TCOORDS: { video::S3DVertex2TCoords* vtx = (video::S3DVertex2TCoords*)buffer->getVertices(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { file->write(&core::plane3df(vtx[buffer->getIndices()[j]].Pos,vtx[buffer->getIndices()[j+1]].Pos,vtx[buffer->getIndices()[j+2]].Pos).Normal, 12); file->write(&vtx[buffer->getIndices()[j]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+1]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+2]].Pos, 12); file->write(&attributes, 2); } } break; case video::EVT_TANGENTS: { video::S3DVertexTangents* vtx = (video::S3DVertexTangents*)buffer->getVertices(); const u16 attributes = 0; for (u32 j=0; j<indexCount; j+=3) { file->write(&core::plane3df(vtx[buffer->getIndices()[j]].Pos,vtx[buffer->getIndices()[j+1]].Pos,vtx[buffer->getIndices()[j+2]].Pos).Normal, 12); file->write(&vtx[buffer->getIndices()[j]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+1]].Pos, 12); file->write(&vtx[buffer->getIndices()[j+2]].Pos, 12); file->write(&attributes, 2); } } break; } } } return true; }
//! writes a mesh bool COBJMeshWriter::writeMesh(io::IWriteFile* file, scene::IMesh* mesh, s32 flags) { if (!file) return false; os::Printer::log("Writing mesh", file->getFileName()); // write OBJ MESH header const core::stringc name(FileSystem->getFileBasename(SceneManager->getMeshCache()->getMeshName(mesh), false)+".mtl"); file->write("# exported by Irrlicht\n",23); file->write("mtllib ",7); file->write(name.c_str(),name.size()); file->write("\n\n",2); // write mesh buffers core::array<video::SMaterial*> mat; u32 allVertexCount=1; // count vertices over the whole file for (u32 i=0; i<mesh->getMeshBufferCount(); ++i) { core::stringc num(i+1); IMeshBuffer* buffer = mesh->getMeshBuffer(i); if (buffer && buffer->getVertexCount()) { file->write("g grp", 5); file->write(num.c_str(), num.size()); file->write("\n",1); u32 j; const u32 vertexCount = buffer->getVertexCount(); for (j=0; j<vertexCount; ++j) { file->write("v ",2); getVectorAsStringLine(buffer->getPosition(j), num); file->write(num.c_str(), num.size()); } for (j=0; j<vertexCount; ++j) { file->write("vt ",3); getVectorAsStringLine(buffer->getTCoords(j), num); file->write(num.c_str(), num.size()); } for (j=0; j<vertexCount; ++j) { file->write("vn ",3); getVectorAsStringLine(buffer->getNormal(j), num); file->write(num.c_str(), num.size()); } file->write("usemtl mat",10); num = ""; for (j=0; j<mat.size(); ++j) { if (*mat[j]==buffer->getMaterial()) { num = core::stringc(j); break; } } if (num == "") { num = core::stringc(mat.size()); mat.push_back(&buffer->getMaterial()); } file->write(num.c_str(), num.size()); file->write("\n",1); const u32 indexCount = buffer->getIndexCount(); for (j=0; j<indexCount; j+=3) { file->write("f ",2); num = core::stringc(buffer->getIndices()[j+2]+allVertexCount); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write(" ",1); num = core::stringc(buffer->getIndices()[j+1]+allVertexCount); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write(" ",1); num = core::stringc(buffer->getIndices()[j+0]+allVertexCount); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write("/",1); file->write(num.c_str(), num.size()); file->write(" ",1); file->write("\n",1); } file->write("\n",1); allVertexCount += vertexCount; } } if (mat.size() == 0) return true; file = FileSystem->createAndWriteFile( name ); if (file) { os::Printer::log("Writing material", file->getFileName()); file->write("# exported by Irrlicht\n\n",24); for (u32 i=0; i<mat.size(); ++i) { core::stringc num(i); file->write("newmtl mat",10); file->write(num.c_str(),num.size()); file->write("\n",1); getColorAsStringLine(mat[i]->AmbientColor, "Ka", num); file->write(num.c_str(),num.size()); getColorAsStringLine(mat[i]->DiffuseColor, "Kd", num); file->write(num.c_str(),num.size()); getColorAsStringLine(mat[i]->SpecularColor, "Ks", num); file->write(num.c_str(),num.size()); getColorAsStringLine(mat[i]->EmissiveColor, "Ke", num); file->write(num.c_str(),num.size()); num = core::stringc(mat[i]->Shininess/0.128f); file->write("Ns ", 3); file->write(num.c_str(),num.size()); file->write("\n", 1); if (mat[i]->getTexture(0)) { file->write("map_Kd ", 7); file->write(mat[i]->getTexture(0)->getName().getPath().c_str(), mat[i]->getTexture(0)->getName().getPath().size()); file->write("\n",1); } file->write("\n",1); } file->drop(); } return true; }
// ISoftBody::createShape() is taken from code found on the Irrlicht forum void ISoftBody::createShape(IMesh* const collMesh) { int cMeshBuffer, j; IMeshBuffer *mb; video::S3DVertex* mb_vertices; u16* mb_indices; std::map<int, int> index_map; std::map<int, int> bullet_map; std::map<int, S3DVertex> vertex_map; int count = 0; indexCount = 0; vertexCount = 0; for(cMeshBuffer=0; cMeshBuffer < 1; cMeshBuffer++) { //printf("Loading new mesh buffer for softbody.\n"); mb = collMesh->getMeshBuffer(cMeshBuffer); mb_vertices = (irr::video::S3DVertex*)mb->getVertices(); mb_indices = mb->getIndices(); indexCount += mb->getIndexCount(); vertexCount += mb->getVertexCount(); for(u32 i=0; i<mb->getIndexCount(); i++) { int iIndex = mb_indices[i]; vector3df iVertex = mb_vertices[iIndex].Pos; bool isFirst = true; for(u32 j=0; j<i; j++) { int jIndex = mb_indices[j]; vector3df jVertex = mb_vertices[jIndex].Pos; if (iVertex == jVertex) { index_map.insert(std::make_pair(i, j)); isFirst = false; break; } } // ???????Bullet??Index?????? if(isFirst) { // Irrlicht?Index??????Index index_map.insert(std::make_pair(i, i)); // ?????Index????Index bullet_map.insert(std::make_pair(i, count)); // ??Index????????? vertex_map.insert(std::make_pair(count, mb_vertices[iIndex])); count++; } } } indices = new int[indexCount]; vertexCount = vertex_map.size(); vertices = new btScalar[vertexCount*3]; for(j=0; j<indexCount; j++) { int index1 = index_map.find(j)->second; int index2 = bullet_map.find(index1)->second; indices[j] = index2; } for(j=0; j<vertexCount; j++) { vertices[3*j] = vertex_map[j].Pos.X; vertices[3*j+1] = vertex_map[j].Pos.Y; vertices[3*j+2] = -vertex_map[j].Pos.Z; } //std::cout << "create softbody" << std::endl; object = btSoftBodyHelpers::CreateFromTriMesh( dynamicsWorld->getSoftBodyWorldInfo(), vertices,indices, indexCount/3); //std::cout << "create map" << std::endl; for(int i=0; i<getPointer()->m_faces.size(); i++) { btSoftBody::Face face = getPointer()->m_faces[i]; for(int j=0; j<3; j++) { if(node_map.find(face.m_n[j]) == node_map.end()) { node_map.insert(std::make_pair(face.m_n[j], node_map.size())); } } for(int j=0; j<3; j++) { m_indices.push_back(node_map.find(face.m_n[j])->second); } } // Reverse node->index to index->node (should be unique on both sides) std::map<btSoftBody::Node*, int>::const_iterator node_iter; for(node_iter = node_map.begin(); node_iter != node_map.end(); ++node_iter) { m_vertices.insert(std::make_pair(node_iter->second, node_iter->first)); } //std::cout << "update Irrlicht vertices" << std::endl; std::map<int, btSoftBody::Node*>::const_iterator it; for(u32 i=0; i<mb->getVertexCount(); i++) { for(it=m_vertices.begin(); it != m_vertices.end(); ++it) { int v_index = it->first; btSoftBody::Node* node = it->second; if(node->m_x.x() == mb_vertices[i].Pos.X && node->m_x.y() == mb_vertices[i].Pos.Y && node->m_x.z() == mb_vertices[i].Pos.Z) { MeshMap.insert(std::make_pair(i, v_index)); break; } } } }
MeshTools::SplitMeshResult MeshTools::splitMeshZ(IMesh* oldMesh, float zCut, float zInsert, bool marginalTrisInLeft, bool marginalTrisInRight) { IMeshBuffer* oldMeshBuf = oldMesh->getMeshBuffer(0); u16* oldInd = oldMeshBuf->getIndices(); SMeshBuffer* leftMeshBuf = new SMeshBuffer(); SMeshBuffer* rightMeshBuf = new SMeshBuffer(); LinkSplitter linkSplitter(oldMeshBuf, zCut); vector3df const offset(0,0, zInsert); set<pair<PsblVertPtr, PsblVertPtr>> leftEdgeLinks; set<pair<PsblVertPtr, PsblVertPtr>> rightEdgeLinks; for (u32 i=0; i < oldMeshBuf->getIndexCount(); i += 3) { // Calling these shapes instead of triangles because they could be triangle or a quad after slice, // (it could also be a degenerate case of a line or a point - those will be discarded by addConvexShape) vector<PsblVertPtr> leftShape; vector<PsblVertPtr> rightShape; int a = oldInd[i]; int b = oldInd[i+1]; int c = oldInd[i+2]; PsblVertPtr mid1; PsblVertPtr mid2; PsblVertPtr mid3; // Don't create a copy just for a triangle that is just kissing the edge. Leave it in the background. if (linkSplitter.compareZ(a)==0 && linkSplitter.compareZ(b)==0 && linkSplitter.compareZ(c)==0) { if (marginalTrisInLeft) { leftShape.push_back(linkSplitter.getVert(a)); leftShape.push_back(linkSplitter.getVert(b)); leftShape.push_back(linkSplitter.getVert(c)); } if (marginalTrisInRight) { rightShape.push_back(linkSplitter.getVert(a)); rightShape.push_back(linkSplitter.getVert(b)); rightShape.push_back(linkSplitter.getVert(c)); } } else { // This is something I had to think hard about so I'm writing this comment so I don't // have to think it through again or forget it: // // Both the left shape and the right shape, and both the triangle and the quad, "magically" // come out with correct winding order when the triangle is split. Here's why: // Let the original triangle vertices be A-B-C. // Let the split midpoints be AB' and CA' as A-B is split and C-A are split respectively. // The shapes (ignore which shape is left or right, call them P and Q instead) // will be filled in the following order: // // round P Q Comment // 1 A - A is not in Q at all // 1 cont. AB' AB' AB' replaces B in P // 2 - B B proper is in Q and not in P // 2 cont. - - Link B-C is not split // 3 - C C proper is in Q and not in P // 3 cont. CA' CA' CA' replaces C in P // // Now, read the columns P and Q vertically top to bottom to see the resultant vertex order. // The triangle P is trivially still the correct winding order; it is just a smaller triangle now. // The new quad Q retains the old triangle's winding order property for the following reason: // As you wrapped around a full circle in old triangle A-B-C you would have traversed C-A then A-B. // The link C-A has been cut and vertex CA' inserted. // The link A-B has been cut and vertex AB' inserted. // If you traverse the new shape starting from the _middle_ you follow the following path: // B-C C-CA' CA'-AB' AB'-B B-C (again) // Compare to old triangle: // B-C C-A A-B B-C (again) // Even though vertex A has been cut off and replaced with two vertices, the two // new vertices lie along the path that the old links took and are in the new shape in the right order. mid1 = linkSplitter.processLink(leftShape, rightShape, a, b); mid2 = linkSplitter.processLink(leftShape, rightShape, b, c); mid3 = linkSplitter.processLink(leftShape, rightShape, c, a); } // If a triangle was split then two of those three midpoints are inhabited by a vertex. // We want to get them both in mid1 and mid2 AND we need them in correct order. PsblVertPtr cut1 = (mid1 && mid2)? mid1 : mid2; PsblVertPtr cut2 = (mid2 && mid3)? mid3 : mid2; if (cut1 && cut2) { vector<PsblVertPtr> chain = linkSplitter.chopLink(cut1, cut2, 1); linkSplitter.insertPoints(leftShape, cut1, cut2, chain); linkSplitter.insertPoints(rightShape, cut1, cut2, chain); } linkSplitter.addConvexShape(leftShape, leftMeshBuf, -offset/2); linkSplitter.addConvexShape(rightShape, rightMeshBuf, offset/2); // Add any edges of the left shape that lie along the border. linkSplitter.addEdgeLinks(leftShape, leftEdgeLinks); // Right side polys that share a border with left side ones will have // opposite winding order. In order for set_intersection to consider them // as matches, we'll store the right side links in reversed order. std::reverse(rightShape.begin(), rightShape.end()); linkSplitter.addEdgeLinks(rightShape, rightEdgeLinks); } SMesh* leftMesh = new SMesh(); leftMeshBuf->recalculateBoundingBox(); leftMeshBuf->setHardwareMappingHint(EHM_STATIC); leftMesh->addMeshBuffer(leftMeshBuf); leftMesh->recalculateBoundingBox(); leftMeshBuf->drop(); // we drop the buf, mesh obj has it now SMesh* rightMesh = new SMesh(); rightMeshBuf->recalculateBoundingBox(); rightMeshBuf->setHardwareMappingHint(EHM_STATIC); rightMesh->addMeshBuffer(rightMeshBuf); rightMesh->recalculateBoundingBox(); rightMeshBuf->drop(); // we drop the buf, mesh obj has it now SMesh* middleMesh = NULL; if (zInsert > 0) { set<pair<PsblVertPtr,PsblVertPtr>> result; std::set_intersection( leftEdgeLinks.begin(), leftEdgeLinks.end(), rightEdgeLinks.begin(), rightEdgeLinks.end(), std::inserter(result, result.begin()) ); size_t debugsize = result.size(); if (result.size() > 0) { SMeshBuffer* middleMeshBuf = new SMeshBuffer(); vector<PsblVertPtr> shape(4); for (auto it=result.begin(); it!=result.end(); ++it) { shape[0] = it->second; shape[1] = it->first; shape[2] = it->first->duplicate(offset); shape[3] = it->second->duplicate(offset); linkSplitter.addConvexShape(shape, middleMeshBuf, -offset/2); } middleMesh = new SMesh(); middleMeshBuf->recalculateBoundingBox(); middleMeshBuf->setHardwareMappingHint(EHM_STATIC); middleMesh->addMeshBuffer(middleMeshBuf); middleMesh->recalculateBoundingBox(); middleMeshBuf->drop(); // we drop the buf, mesh obj has it now } } return SplitMeshResult {leftMesh, middleMesh, rightMesh}; }
//! draws the element and its children void CGUIMeshViewer::draw() { if (!IsVisible) return; IGUISkin* skin = Environment->getSkin(); IVideoDriver* driver = Environment->getVideoDriver(); rect<SINT32> viewPort = AbsoluteRect; viewPort.LowerRightCorner.x -= 1; viewPort.LowerRightCorner.y -= 1; viewPort.UpperLeftCorner.x += 1; viewPort.UpperLeftCorner.y += 1; viewPort.clipAgainst(AbsoluteClippingRect); // draw the frame rect<SINT32> frameRect(AbsoluteRect); frameRect.LowerRightCorner.y = frameRect.UpperLeftCorner.y + 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), frameRect, &AbsoluteClippingRect); frameRect.LowerRightCorner.y = AbsoluteRect.LowerRightCorner.y; frameRect.LowerRightCorner.x = frameRect.UpperLeftCorner.x + 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_SHADOW), frameRect, &AbsoluteClippingRect); frameRect = AbsoluteRect; frameRect.UpperLeftCorner.x = frameRect.LowerRightCorner.x - 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect); frameRect = AbsoluteRect; frameRect.UpperLeftCorner.y = AbsoluteRect.LowerRightCorner.y - 1; skin->draw2DRectangle(this, skin->getColor(EGDC_3D_HIGH_LIGHT), frameRect, &AbsoluteClippingRect); // draw the mesh if (Mesh) { //TODO: if outside of screen, dont draw. // - why is the absolute clipping rect not already the screen? rect<SINT32> oldViewPort = driver->getViewPort(); driver->setViewPort(viewPort); Matrix4 mat; //CameraControl->calculateProjectionMatrix(mat); //driver->setTransform(TS_PROJECTION, mat); mat = Matrix4::IDENTITY; mat.setTrans(Vector3(0, 0, 0)); //mat.setTranslation(Vector3(0, 0, 0)); driver->setTransform(ETS_WORLD, mat); //CameraControl->calculateViewMatrix(mat); //driver->setTransform(TS_VIEW, mat); driver->setMaterial(Material); UINT32 frame = 0; if (Mesh->getFrameCount()) frame = (Timer::getTime() / 20) % Mesh->getFrameCount(); const IMesh* const m = Mesh->getMesh(frame); for (UINT32 i = 0; i<m->getMeshBufferCount(); ++i) { IMeshBuffer* mb = m->getMeshBuffer(i); driver->drawVertexPrimitiveList(mb->getVertices(), mb->getVertexCount(), mb->getIndices(), mb->getIndexCount() / 3, mb->getVertexType(), EPT_TRIANGLES, mb->getIndexType()); } driver->setViewPort(oldViewPort); } IGUIElement::draw(); }
//! sets the mesh from which the shadow volume should be generated. void CShadowVolumeSceneNode::setMeshToRenderFrom(IMesh* mesh) { ShadowVolumesUsed = 0; s32 oldIndexCount = IndexCount; s32 oldVertexCount = VertexCount; VertexCount = 0; IndexCount = 0; if (!mesh) return; // calculate total amount of vertices and indices u32 i; s32 totalVertices = 0; s32 totalIndices = 0; u32 bufcnt = mesh->getMeshBufferCount(); IMeshBuffer* b; for (i=0; i<bufcnt; ++i) { b = mesh->getMeshBuffer(i); totalIndices += b->getIndexCount(); totalVertices += b->getVertexCount(); } // allocate memory if nececcary if (totalVertices > VertexCountAllocated) { delete [] Vertices; Vertices = new core::vector3df[totalVertices]; VertexCountAllocated = totalVertices; } if (totalIndices > IndexCountAllocated) { delete [] Indices; Indices = new u16[totalIndices]; IndexCountAllocated = totalIndices; if (UseZFailMethod) { delete [] FaceData; FaceData = new bool[totalIndices / 3]; } } // copy mesh for (i=0; i<bufcnt; ++i) { b = mesh->getMeshBuffer(i); s32 idxcnt = b->getIndexCount(); s32 vtxnow = VertexCount; const u16* idxp = b->getIndices(); const u16* idxpend = idxp + idxcnt; for (; idxp!=idxpend; ++idxp) Indices[IndexCount++] = *idxp + vtxnow; s32 vtxcnt = b->getVertexCount(); switch(b->getVertexType()) { case video::EVT_STANDARD: { const video::S3DVertex* vp = (video::S3DVertex*)b->getVertices(); const video::S3DVertex* vpend = vp + vtxcnt; for (; vp!=vpend; ++vp) Vertices[VertexCount++] = (*vp).Pos; } break; case video::EVT_2TCOORDS: { const video::S3DVertex2TCoords* vp = (video::S3DVertex2TCoords*)b->getVertices(); const video::S3DVertex2TCoords* vpend = vp + vtxcnt; for (; vp!=vpend; ++vp) Vertices[VertexCount++] = (*vp).Pos; } break; case video::EVT_TANGENTS: { const video::S3DVertexTangents* vp = (video::S3DVertexTangents*)b->getVertices(); const video::S3DVertexTangents* vpend = vp + vtxcnt; for (; vp!=vpend; ++vp) Vertices[VertexCount++] = (*vp).Pos; } break; } } // recalculate adjacency if neccessarry if (oldVertexCount != VertexCount && oldIndexCount != IndexCount && UseZFailMethod) calculateAdjacency(); // create as much shadow volumes as there are lights but // do not ignore the max light settings. u32 lights = SceneManager->getVideoDriver()->getDynamicLightCount(); core::matrix4 mat = Parent->getAbsoluteTransformation(); core::vector3df parentpos = Parent->getAbsolutePosition(); core::vector3df lpos; mat.makeInverse(); for (i=0; i<lights; ++i) { const video::SLight& dl = SceneManager->getVideoDriver()->getDynamicLight(i); lpos = dl.Position; if (dl.CastShadows && fabs((lpos - parentpos).getLengthSQ()) <= (dl.Radius*dl.Radius*4.0f)) { mat.transformVect(lpos); createShadowVolume(lpos); } } }