// Generate normals for polygon meshes void IndexedGeometry::createIndexedFaceSet() { if (_coords.empty()) throw std::runtime_error("No coordinates given."); if (_coordIndex.empty()) throw std::runtime_error("No coordinate index given."); MeshPtr mesh = MeshManager::getSingleton().createManual(_name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *sub = mesh->createSubMesh(); bool hasTextureCoordinates = !_texCoords.empty(); bool hasPointColors = !_colors.empty() && _colorPerVertex; bool hasPointNormals = !_normals.empty() && _normalPerVertex; bool hasCellColors = !_colors.empty() && !hasPointColors; bool hasCellNormals = !_normals.empty() && !hasPointNormals; bool calcPointNormals = _normals.empty() && _normalPerVertex; std::vector<face> faces; face f; for (std::vector<int>::const_iterator I=_coordIndex.begin(); I !=_coordIndex.end(); ++I) { if (*I == -1) { faces.resize(faces.size()+1); faces.back().indices.swap(f.indices); } else f.indices.push_back(I - _coordIndex.begin()); } if (!f.indices.empty()) { faces.resize(faces.size()+1); faces.back().indices.swap(f.indices); } std::vector<vertex> vertices; std::vector<triangle> triangles; VertMap vertexMap; // triangulate and expand vertices for (std::vector<face>::const_iterator f=faces.begin(), e=faces.end(); f!=e; ++f) { int faceNr = f - faces.begin(); int triVertNr = 0; int triVerts[2] = { -1, -1 }; for (std::vector<int>::const_iterator i = f->indices.begin(), e=f->indices.end(); i!=e; ++i, ++triVertNr) { int triVertNr = i - f->indices.begin(); int index = *i; vertex vert; // get full indices for vertex data vert.pos = _coordIndex[index]; vert.normal = !_normals.empty() ? getIndex(_coordIndex, _normalIndex, _normalPerVertex, faceNr, index) : 0; vert.colour = !_colors.empty() ? getIndex(_coordIndex, _colorIndex, _colorPerVertex, faceNr, index) : 0; vert.tc = hasTextureCoordinates ? getIndex(_coordIndex, _texCoordIndex, true, faceNr, index) : 0; // avoid duplication //int nvert = vertexMap.size(); //int &vpos = vertexMap[vert]; //if (nvert != vertexMap.size()) { int vpos = vertices.size(); vertices.push_back(vert); //} // emit triangle (maybe) if (triVertNr == 0) triVerts[0] = vpos; else if (triVertNr == 1) triVerts[1] = vpos; else { triangle t; t.vertices[0] = triVerts[0]; t.vertices[1] = triVerts[1]; t.vertices[2] = vpos; if (!_ccw) std::swap(t.vertices[1], t.vertices[2]); triangles.push_back(t); triVerts[1] = vpos; } } } // createOgreMesh int nvertices = vertices.size(); int nfaces = triangles.size(); VertexData* vertexData = new VertexData(); sub->vertexData = vertexData; IndexData* indexData = sub->indexData; VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); if (hasPointNormals) { // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); } // two dimensional texture coordinates if (hasTextureCoordinates) { vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); currOffset += VertexElement::getTypeSize(VET_FLOAT2); } std::cout << std::endl; // allocate index buffer indexData->indexCount = nfaces * 3; indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); std::cout << triangles.size() << ": "; for(std::vector<triangle>::const_iterator T = triangles.begin(); T != triangles.end(); T++) { const triangle &t = (*T); *pIndices++ = t.vertices[0]; *pIndices++ = t.vertices[1]; *pIndices++ = t.vertices[2]; std::cout << t.vertices[0] << " " << t.vertices[1] << " " << t.vertices[2] << " "; } std::cout << std::endl; // allocate the vertex buffer vertexData->vertexCount = nvertices; HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); AxisAlignedBox aabox; std::cout << vertices.size() << ": "; for(std::vector<vertex>::const_iterator V = vertices.begin(); V != vertices.end(); V++) { const vertex &v = (*V); SFVec3f pos = _coords.at(v.pos); *pVertex++ = pos.x; *pVertex++ = pos.y; *pVertex++ = pos.z; aabox.merge(Vector3(pos.x, pos.y, pos.z)); std::cout << pos.x << " " << pos.y << " " << pos.z << " " << std::endl; //std::cout << v.pos << " "; if (hasPointNormals) { const SFVec3f normal = _normals.at(v.normal); *pVertex++ = normal.x; *pVertex++ = normal.y; *pVertex++ = normal.z; } } std::cout << std::endl; // Unlock vBuf->unlock(); iBuf->unlock(); sub->useSharedVertices = false; // the original code was missing this line: mesh->_setBounds(aabox); mesh->_setBoundingSphereRadius((aabox.getMaximum()-aabox.getMinimum()).length()/2.0); // this line makes clear the mesh is loaded (avoids memory leaks) mesh->load(); }
FlexObj::FlexObj(node_t *nds, int numtexcoords, Vector3* texcoords, int numtriangles, int* triangles, int numsubmeshes, int* subtexindex, int* subtriindex, char* texname, char* name, int* subisback, char* backtexname, char* transtexname) { unsigned int i; int j; triangleCount = numtriangles; /* //okay, we munch a bit the data to optimize submesh count Vector3* texcoords=(Vector3*)malloc(sizeof(Vector3)*numtexcoords); int* triangles=(int*)malloc(sizeof(int)*3*numtriangles); int numsubmeshes=3; int subtexindex[4]; int subtriindex[4]; int subisback[3]={0,1,2}; int numtex[3]={0,0,0}; int numtri[3]={0,0,0}; int postex[3]={0,0,0}; int postri[3]={0,0,0}; for (j=0; j<onumsubmeshes; j++) { int type=0; // if (j<numsubmeshes-1) { type=osubisback[j+1]; } numtex[type]+=osubtexindex[j+1]-osubtexindex[j]; numtri[type]+=osubtriindex[j+1]-osubtriindex[j]; } postex[0]=0; postex[1]=numtex[0]; postex[2]=numtex[0]+numtex[1]; subtexindex[0]=0; subtexindex[1]=numtex[0]; subtexindex[2]=numtex[0]+numtex[1]; subtexindex[3]=numtex[0]+numtex[1]+numtex[2]; postri[0]=0; postri[1]=numtri[0]; postri[2]=numtri[0]+numtri[1]; subtriindex[0]=0; subtriindex[1]=numtri[0]; subtriindex[2]=numtri[0]+numtri[1]; subtriindex[3]=numtri[0]+numtri[1]+numtri[2]; for (j=0; j<onumsubmeshes; j++) { int type=0; if (j<numsubmeshes-1) { type=osubisback[j+1]; } for (i=0; i<osubtexindex[j+1]-osubtexindex[j]; i++) { texcoords[postex[type]]=otexcoords[osubtexindex[j]+i]; } postex[type]+=osubtexindex[j+1]-osubtexindex[j]; for (i=0; i<osubtriindex[j+1]-osubtriindex[j]; i++) { int k; for (k=0; k<3; k++) triangles[postri[type]*3+k]=otriangles[(osubtriindex[j]+i)*3+k]; } postri[type]+=osubtriindex[j+1]-osubtriindex[j]; } */ //finished munching gEnv->sceneManager=gEnv->sceneManager; nodes=nds; /// Create the mesh via the MeshManager msh = MeshManager::getSingleton().createManual(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,new ResourceBuffer()); /// Create submeshes subs=(SubMesh**)malloc(numsubmeshes*sizeof(SubMesh*)); for (j=0; j<numsubmeshes; j++) { subs[j] = msh->createSubMesh(); //materials if (j<numsubmeshes-1) { if (subisback[j+1]==0) subs[j]->setMaterialName(texname); if (subisback[j+1]==1) subs[j]->setMaterialName(backtexname); if (subisback[j+1]==2) subs[j]->setMaterialName(transtexname); } else subs[j]->setMaterialName(texname); }; /// Define the vertices (8 vertices, each consisting of 3 groups of 3 floats nVertices = numtexcoords; vbufCount = (2*3+2)*nVertices; vertices=(float*)malloc(vbufCount*sizeof(float)); //shadow shadownorvertices=(float*)malloc(nVertices*(3+2)*sizeof(float)); shadowposvertices=(float*)malloc(nVertices*3*2*sizeof(float)); nodeIDs=(int*)malloc(nVertices*sizeof(int)); //define node ids for (i=0; i<nVertices; i++) { nodeIDs[i]=(int)(texcoords[i].x); } //textures coordinates for (i=0; i<nVertices; i++) { covertices[i].texcoord=Vector2(texcoords[i].y,texcoords[i].z); } /// Define triangles /// The values in this table refer to vertices in the above table ibufCount = 3*numtriangles; faces=(unsigned short*)malloc(ibufCount*sizeof(unsigned short)); for (i=0; i<ibufCount; i++) { faces[i]=findID(i/3, triangles[i], numsubmeshes, subtexindex, subtriindex); } sref=(float*)malloc(numtriangles*sizeof(float)); for (i=0; i<(unsigned int)numtriangles;i++) { Vector3 v1, v2; v1=nodes[nodeIDs[faces[i*3+1]]].RelPosition-nodes[nodeIDs[faces[i*3]]].RelPosition; v2=nodes[nodeIDs[faces[i*3+2]]].RelPosition-nodes[nodeIDs[faces[i*3]]].RelPosition; v1=v1.crossProduct(v2); sref[i]=v1.length()*2.0; } //update coords updateVertices(); /// Create vertex data structure for vertices shared between submeshes msh->sharedVertexData = new VertexData(); msh->sharedVertexData->vertexCount = nVertices; /// Create declaration (memory format) of vertex data decl = msh->sharedVertexData->vertexDeclaration; size_t offset = 0; decl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT3); // decl->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE); // offset += VertexElement::getTypeSize(VET_FLOAT3); decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); offset += VertexElement::getTypeSize(VET_FLOAT2); /// Allocate vertex buffer of the requested number of vertices (vertexCount) /// and bytes per vertex (offset) vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); /// Upload the vertex data to the card vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, vbuf); /// Set parameters of the submeshes for (j=0; j<numsubmeshes; j++) { int smcount=3*(subtriindex[j+1]-subtriindex[j]); subs[j]->useSharedVertices = true; /// Allocate index buffer of the requested number of vertices (ibufCount) HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, smcount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card ibuf->writeData(0, ibuf->getSizeInBytes(), &faces[subtriindex[j]*3], true); subs[j]->indexData->indexBuffer = ibuf; subs[j]->indexData->indexCount = smcount; subs[j]->indexData->indexStart = 0; } /// Set bounding information (for culling) msh->_setBounds(AxisAlignedBox(-100,-100,-100,100,100,100), true); //msh->_setBoundingSphereRadius(100); /// Notify Mesh object that it has been loaded msh->load(); msh->buildEdgeList(); }
FlexAirfoil::FlexAirfoil(char* name, node_t *nds, int pnfld, int pnfrd, int pnflu, int pnfru, int pnbld, int pnbrd, int pnblu, int pnbru, char* texband, Vector2 texlf, Vector2 texrf, Vector2 texlb, Vector2 texrb, char mtype, float controlratio, float mind, float maxd, char* afname, float lift_coef, AeroEngine** tps, bool break_able) { // innan=0; liftcoef=lift_coef; breakable=break_able; broken=false; debug[0]=0; free_wash=0; aeroengines=tps; nodes=nds; useInducedDrag=false; nfld=pnfld; nodes[nfld].iIsSkin=true; nfrd=pnfrd; nodes[nfrd].iIsSkin=true; nflu=pnflu; nodes[nflu].iIsSkin=true; nfru=pnfru; nodes[nfru].iIsSkin=true; nbld=pnbld; nodes[nbld].iIsSkin=true; nbrd=pnbrd; nodes[nbrd].iIsSkin=true; nblu=pnblu; nodes[nblu].iIsSkin=true; nbru=pnbru; nodes[nbru].iIsSkin=true; mindef=mind; maxdef=maxd; airfoil=new Airfoil(afname); //airfoil->getcl(-180.0, 0, 0); //airfoil->dumpcl(); int i; for (i=0; i<90; i++) airfoilpos[i]=refairfoilpos[i]; type=mtype; hascontrol=(mtype!='n' && mtype!='S'&& mtype!='T' && mtype!='U'&& mtype!='V'); isstabilator=(mtype=='S' || mtype=='T' || mtype=='U' || mtype=='V'); stabilleft=(mtype=='T' || mtype=='V'); deflection=0.0; chordratio=controlratio; if (hascontrol) { //setup control surface airfoilpos[56]=controlratio; airfoilpos[56+3]=controlratio; airfoilpos[56+6]=controlratio; airfoilpos[56+9]=controlratio; airfoilpos[55]=-controlratio+1.5; airfoilpos[55+3]=-controlratio+1.5; airfoilpos[55+6]=controlratio-0.5; airfoilpos[55+9]=controlratio-0.5; for (i=0; i<12; i++) airfoilpos[54+12+i]=airfoilpos[54+i]; } /// Create the mesh via the MeshManager msh = MeshManager::getSingleton().createManual(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, new ResourceBuffer()); /// Create submeshes subface = msh->createSubMesh(); subband = msh->createSubMesh(); subcup=msh->createSubMesh(); subcdn=msh->createSubMesh(); //materials subface->setMaterialName(texband); subband->setMaterialName(texband); subcup->setMaterialName(texband); subcdn->setMaterialName(texband); /// Define the vertices nVertices = 24*2+4+2; vbufCount = (2*3+2)*nVertices; vertices=(float*)malloc(vbufCount*sizeof(float)); //shadow shadownorvertices=(float*)malloc(nVertices*(3+2)*sizeof(float)); shadowposvertices=(float*)malloc(nVertices*3*2*sizeof(float)); //textures coordinates covertices[0].texcoord=texlf; covertices[1].texcoord=texrf; covertices[2].texcoord=texlf+(texlb-texlf)*0.03; covertices[3].texcoord=texrf+(texrb-texrf)*0.03; covertices[4].texcoord=texlf+(texlb-texlf)*0.03; covertices[5].texcoord=texrf+(texrb-texrf)*0.03; covertices[6].texcoord=texlf+(texlb-texlf)*0.10; covertices[7].texcoord=texrf+(texrb-texrf)*0.10; covertices[8].texcoord=texlf+(texlb-texlf)*0.10; covertices[9].texcoord=texrf+(texrb-texrf)*0.10; covertices[10].texcoord=texlf+(texlb-texlf)*0.25; covertices[11].texcoord=texrf+(texrb-texrf)*0.25; covertices[12].texcoord=texlf+(texlb-texlf)*0.25; covertices[13].texcoord=texrf+(texrb-texrf)*0.25; covertices[14].texcoord=texlf+(texlb-texlf)*0.45; covertices[15].texcoord=texrf+(texrb-texrf)*0.45; covertices[16].texcoord=texlf+(texlb-texlf)*0.45; covertices[17].texcoord=texrf+(texrb-texrf)*0.45; covertices[18].texcoord=texlf+(texlb-texlf)*airfoilpos[56]; covertices[19].texcoord=texrf+(texrb-texrf)*airfoilpos[56]; covertices[20].texcoord=texlf+(texlb-texlf)*airfoilpos[56]; covertices[21].texcoord=texrf+(texrb-texrf)*airfoilpos[56]; covertices[22].texcoord=covertices[18].texcoord; covertices[23].texcoord=covertices[19].texcoord; covertices[24].texcoord=covertices[20].texcoord; covertices[25].texcoord=covertices[21].texcoord; covertices[26].texcoord=texlb; covertices[27].texcoord=texrb; covertices[28].texcoord=texlb; covertices[29].texcoord=texrb; for (i=0; i<24; i++) covertices[i+30].texcoord=covertices[i].texcoord; /// Define triangles /// The values in this table refer to vertices in the above table bandibufCount = 3*20; faceibufCount = 3*20; cupibufCount=3*2; cdnibufCount=3*2; facefaces=(unsigned short*)malloc(faceibufCount*sizeof(unsigned short)); bandfaces=(unsigned short*)malloc(bandibufCount*sizeof(unsigned short)); cupfaces=(unsigned short*)malloc(cupibufCount*sizeof(unsigned short)); cdnfaces=(unsigned short*)malloc(cdnibufCount*sizeof(unsigned short)); //attack bandfaces[0]=0; bandfaces[1]=2; bandfaces[2]=1; bandfaces[3]=2; bandfaces[4]=3; bandfaces[5]=1; bandfaces[6]=0; bandfaces[7]=1; bandfaces[8]=4; bandfaces[9]=4; bandfaces[10]=1; bandfaces[11]=5; for (i=0; i<5; i++) { //band int v=i*4+2; if (i!=4) { bandfaces[i*12+12]=v; bandfaces[i*12+13]=v+4; bandfaces[i*12+14]=v+1; bandfaces[i*12+15]=v+4; bandfaces[i*12+16]=v+5; bandfaces[i*12+17]=v+1; bandfaces[i*12+18]=v+2; bandfaces[i*12+19]=v+3; bandfaces[i*12+20]=v+6; bandfaces[i*12+21]=v+6; bandfaces[i*12+22]=v+3; bandfaces[i*12+23]=v+7; } /* if (i==4) { bandfaces[i*12+20]=v+4; bandfaces[i*12+21]=v+4; bandfaces[i*12+23]=v+5; } */ //sides facefaces[i*12]=30+0; facefaces[i*12+1]=30+v+4; facefaces[i*12+2]=30+v; facefaces[i*12+3]=30+0; facefaces[i*12+4]=30+v+2; facefaces[i*12+5]=30+v+6; facefaces[i*12+6]=30+1; facefaces[i*12+7]=30+v+1; facefaces[i*12+8]=30+v+5; facefaces[i*12+9]=30+1; facefaces[i*12+10]=30+v+7; facefaces[i*12+11]=30+v+3; if (i==4) { // facefaces[i*12+5]=20+v+4; // facefaces[i*12+10]=20+v+5; facefaces[i*12]=30+0; facefaces[i*12+1]=30+v+2; facefaces[i*12+2]=30+v; facefaces[i*12+3]=30+v+4; facefaces[i*12+4]=30+v; facefaces[i*12+5]=30+v+2; facefaces[i*12+6]=30+1; facefaces[i*12+7]=30+v+1; facefaces[i*12+8]=30+v+3; facefaces[i*12+9]=30+v+5; facefaces[i*12+10]=30+v+3; facefaces[i*12+11]=30+v+1; } } cupfaces[0]=22; cupfaces[1]=26; cupfaces[2]=23; cupfaces[3]=26; cupfaces[4]=27; cupfaces[5]=23; cdnfaces[0]=24; cdnfaces[1]=25; cdnfaces[2]=29; cdnfaces[3]=24; cdnfaces[4]=29; cdnfaces[5]=28; float tsref=2.0*(nodes[nfrd].RelPosition-nodes[nfld].RelPosition).crossProduct(nodes[nbld].RelPosition-nodes[nfld].RelPosition).length(); sref=2.0*(nodes[nfrd].RelPosition-nodes[nfld].RelPosition).crossProduct(nodes[nbrd].RelPosition-nodes[nfrd].RelPosition).length(); if (tsref>sref) sref=tsref; sref=sref*sref; lratio=(nodes[nfld].RelPosition-nodes[nflu].RelPosition).length()/(nodes[nfld].RelPosition-nodes[nbld].RelPosition).length(); rratio=(nodes[nfrd].RelPosition-nodes[nfru].RelPosition).length()/(nodes[nfrd].RelPosition-nodes[nbrd].RelPosition).length(); thickness=(nodes[nfld].RelPosition-nodes[nflu].RelPosition).length(); //update coords updateVertices(); /// Create vertex data structure for 8 vertices shared between submeshes msh->sharedVertexData = new VertexData(); msh->sharedVertexData->vertexCount = nVertices; /// Create declaration (memory format) of vertex data decl = msh->sharedVertexData->vertexDeclaration; size_t offset = 0; decl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT3); // decl->addElement(0, offset, VET_FLOAT3, VES_DIFFUSE); // offset += VertexElement::getTypeSize(VET_FLOAT3); decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); offset += VertexElement::getTypeSize(VET_FLOAT2); /// Allocate vertex buffer of the requested number of vertices (vertexCount) /// and bytes per vertex (offset) vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( offset, msh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); /// Upload the vertex data to the card vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, vbuf); //for the face /// Allocate index buffer of the requested number of vertices (ibufCount) HardwareIndexBufferSharedPtr faceibuf = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, faceibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card faceibuf->writeData(0, faceibuf->getSizeInBytes(), facefaces, true); /// Set parameters of the submesh subface->useSharedVertices = true; subface->indexData->indexBuffer = faceibuf; subface->indexData->indexCount = faceibufCount; subface->indexData->indexStart = 0; //for the band /// Allocate index buffer of the requested number of vertices (ibufCount) HardwareIndexBufferSharedPtr bandibuf = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, bandibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card bandibuf->writeData(0, bandibuf->getSizeInBytes(), bandfaces, true); /// Set parameters of the submesh subband->useSharedVertices = true; subband->indexData->indexBuffer = bandibuf; subband->indexData->indexCount = bandibufCount; subband->indexData->indexStart = 0; //for the aileron up /// Allocate index buffer of the requested number of vertices (ibufCount) HardwareIndexBufferSharedPtr cupibuf = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, cupibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card cupibuf->writeData(0, cupibuf->getSizeInBytes(), cupfaces, true); /// Set parameters of the submesh subcup->useSharedVertices = true; subcup->indexData->indexBuffer = cupibuf; subcup->indexData->indexCount = cupibufCount; subcup->indexData->indexStart = 0; //for the aileron down /// Allocate index buffer of the requested number of vertices (ibufCount) HardwareIndexBufferSharedPtr cdnibuf = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, cdnibufCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card cdnibuf->writeData(0, cdnibuf->getSizeInBytes(), cdnfaces, true); /// Set parameters of the submesh subcdn->useSharedVertices = true; subcdn->indexData->indexBuffer = cdnibuf; subcdn->indexData->indexCount = cdnibufCount; subcdn->indexData->indexStart = 0; /// Set bounding information (for culling) msh->_setBounds(AxisAlignedBox(-20,-20,-20,20,20,20), true); //msh->_setBoundingSphereRadius(20.0); /// Notify Mesh object that it has been loaded //MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes(false); msh->buildEdgeList(); //msh->prepareForShadowVolume(); msh->load(); //MeshManager::getSingleton().setPrepareAllMeshesForShadowVolumes() }
void OgreToBulletMesh::getMeshInformation(MeshPtr mesh, unsigned& vertex_count, std::vector<Vector3>& vertices, unsigned& index_count, std::vector<unsigned>& indices, const Vector3& position, const Quaternion& orientation, const Vector3& scale) { bool added_shared = false; unsigned current_offset = 0; unsigned shared_offset = 0; unsigned next_offset = 0; unsigned index_offset = 0; vertex_count = index_count = 0; for (uint16_t i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* submesh = mesh->getSubMesh(i); if (submesh->useSharedVertices) { if (!added_shared) { vertex_count += mesh->sharedVertexData->vertexCount; added_shared = true; } } else vertex_count += submesh->vertexData->vertexCount; index_count += submesh->indexData->indexCount; } vertices.clear(); vertices.reserve(vertex_count); indices.clear(); indices.reserve(index_count); added_shared = false; for (uint16_t i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* submesh = mesh->getSubMesh(i); VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; if (!submesh->useSharedVertices || (submesh->useSharedVertices && !added_shared)) { if (submesh->useSharedVertices) { added_shared = true; shared_offset = current_offset; } const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(VertexElementSemantic::VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); uint8_t* vertex = (uint8_t*)vbuf->lock(HardwareBuffer::LockOptions::HBL_READ_ONLY); float* pReal; for (int j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Vector3 pt(pReal[0], pReal[1], pReal[2]); vertices[current_offset + j] = (orientation * (pt * scale)) + position; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } IndexData* index_data = submesh->indexData; uint numTris = index_data->indexCount / 3; HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IndexType::IT_32BIT); uint* pLong = (uint*)ibuf->lock(HardwareBuffer::LockOptions::HBL_READ_ONLY); ushort* pShort = (ushort*)pLong; uint offset = submesh->useSharedVertices ? shared_offset : current_offset; if (use32bitindexes) for (int k = 0; k < index_data->indexCount; ++k) indices[index_offset++] = pLong[k] + offset; else for (int k = 0; k < index_data->indexCount; ++k) indices[index_offset++] = (uint)pShort[k] + (uint)offset; ibuf->unlock(); current_offset = next_offset; } }
// Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given // mesh. void NIFLoader::createOgreSubMesh(NiTriShape *shape, const String &material, std::list<VertexBoneAssignment> &vertexBoneAssignments) { // cout << "s:" << shape << "\n"; NiTriShapeData *data = shape->data.getPtr(); SubMesh *sub = mesh->createSubMesh(shape->name.toString()); int nextBuf = 0; // This function is just one long stream of Ogre-barf, but it works // great. // Add vertices int numVerts = data->vertices.length / 3; sub->vertexData = new VertexData(); sub->vertexData->vertexCount = numVerts; sub->useSharedVertices = false; VertexDeclaration *decl = sub->vertexData->vertexDeclaration; decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT3), numVerts, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, false); if(flip) { float *datamod = new float[data->vertices.length]; //std::cout << "Shape" << shape->name.toString() << "\n"; for(int i = 0; i < numVerts; i++) { int index = i * 3; const float *pos = data->vertices.ptr + index; Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); original = mTransform * original; mBoundingBox.merge(original); datamod[index] = original.x; datamod[index+1] = original.y; datamod[index+2] = original.z; } vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); delete [] datamod; } else { vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, false); } VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; bind->setBinding(nextBuf++, vbuf); if (data->normals.length) { decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT3), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); if(flip) { Quaternion rotation = mTransform.extractQuaternion(); rotation.normalise(); float *datamod = new float[data->normals.length]; for(int i = 0; i < numVerts; i++) { int index = i * 3; const float *pos = data->normals.ptr + index; Ogre::Vector3 original = Ogre::Vector3(*pos ,*(pos+1), *(pos+2)); original = rotation * original; if (mNormaliseNormals) { original.normalise(); } datamod[index] = original.x; datamod[index+1] = original.y; datamod[index+2] = original.z; } vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); delete [] datamod; } else { vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, false); } bind->setBinding(nextBuf++, vbuf); } // Vertex colors if (data->colors.length) { const float *colors = data->colors.ptr; RenderSystem* rs = Root::getSingleton().getRenderSystem(); std::vector<RGBA> colorsRGB(numVerts); RGBA *pColour = &colorsRGB.front(); for (int i=0; i<numVerts; i++) { rs->convertColourValue(ColourValue(colors[0],colors[1],colors[2], colors[3]),pColour++); colors += 4; } decl->addElement(nextBuf, 0, VET_COLOUR, VES_DIFFUSE); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_COLOUR), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true); bind->setBinding(nextBuf++, vbuf); } if (data->uvlist.length) { decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT2), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY,false); if(flip) { float *datamod = new float[data->uvlist.length]; for(unsigned int i = 0; i < data->uvlist.length; i+=2){ float x = *(data->uvlist.ptr + i); float y = *(data->uvlist.ptr + i + 1); datamod[i] =x; datamod[i + 1] =y; } vbuf->writeData(0, vbuf->getSizeInBytes(), datamod, false); delete [] datamod; } else vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, false); bind->setBinding(nextBuf++, vbuf); } // Triangle faces - The total number of triangle points int numFaces = data->triangles.length; if (numFaces) { sub->indexData->indexCount = numFaces; sub->indexData->indexStart = 0; HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). createIndexBuffer(HardwareIndexBuffer::IT_16BIT, numFaces, HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); if(flip && mFlipVertexWinding && sub->indexData->indexCount % 3 == 0){ sub->indexData->indexBuffer = ibuf; uint16 *datamod = new uint16[numFaces]; int index = 0; for (size_t i = 0; i < sub->indexData->indexCount; i+=3) { const short *pos = data->triangles.ptr + index; uint16 i0 = (uint16) *(pos+0); uint16 i1 = (uint16) *(pos+1); uint16 i2 = (uint16) *(pos+2); //std::cout << "i0: " << i0 << "i1: " << i1 << "i2: " << i2 << "\n"; datamod[index] = i2; datamod[index+1] = i1; datamod[index+2] = i0; index += 3; } ibuf->writeData(0, ibuf->getSizeInBytes(), datamod, false); delete [] datamod; } else ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, false); sub->indexData->indexBuffer = ibuf; } // Set material if one was given if (!material.empty()) sub->setMaterialName(material); //add vertex bone assignments for (std::list<VertexBoneAssignment>::iterator it = vertexBoneAssignments.begin(); it != vertexBoneAssignments.end(); it++) { sub->addBoneAssignment(*it); } if(mSkel.isNull()) needBoneAssignments.push_back(sub); }
// Convert Nif::NiTriShape to Ogre::SubMesh, attached to the given // mesh. static void createOgreMesh(Mesh *mesh, NiTriShape *shape, const String &material) { NiTriShapeData *data = shape->data.getPtr(); SubMesh *sub = mesh->createSubMesh(shape->name.toString()); int nextBuf = 0; // This function is just one long stream of Ogre-barf, but it works // great. // Add vertices int numVerts = data->vertices.length / 3; sub->vertexData = new VertexData(); sub->vertexData->vertexCount = numVerts; sub->useSharedVertices = false; VertexDeclaration *decl = sub->vertexData->vertexDeclaration; decl->addElement(nextBuf, 0, VET_FLOAT3, VES_POSITION); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT3), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbuf->writeData(0, vbuf->getSizeInBytes(), data->vertices.ptr, true); VertexBufferBinding* bind = sub->vertexData->vertexBufferBinding; bind->setBinding(nextBuf++, vbuf); // Vertex normals if(data->normals.length) { decl->addElement(nextBuf, 0, VET_FLOAT3, VES_NORMAL); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT3), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbuf->writeData(0, vbuf->getSizeInBytes(), data->normals.ptr, true); bind->setBinding(nextBuf++, vbuf); } // Vertex colors if(data->colors.length) { const float *colors = data->colors.ptr; RenderSystem* rs = Root::getSingleton().getRenderSystem(); std::vector<RGBA> colorsRGB(numVerts); RGBA *pColour = &colorsRGB.front(); for(int i=0; i<numVerts; i++) { rs->convertColourValue(ColourValue(colors[0],colors[1],colors[2], colors[3]),pColour++); colors += 4; } decl->addElement(nextBuf, 0, VET_COLOUR, VES_DIFFUSE); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_COLOUR), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB.front(), true); bind->setBinding(nextBuf++, vbuf); } // Texture UV coordinates if(data->uvlist.length) { decl->addElement(nextBuf, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( VertexElement::getTypeSize(VET_FLOAT2), numVerts, HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbuf->writeData(0, vbuf->getSizeInBytes(), data->uvlist.ptr, true); bind->setBinding(nextBuf++, vbuf); } // Triangle faces int numFaces = data->triangles.length; if(numFaces) { HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). createIndexBuffer(HardwareIndexBuffer::IT_16BIT, numFaces, HardwareBuffer::HBU_STATIC_WRITE_ONLY); ibuf->writeData(0, ibuf->getSizeInBytes(), data->triangles.ptr, true); sub->indexData->indexBuffer = ibuf; sub->indexData->indexCount = numFaces; sub->indexData->indexStart = 0; } // Set material if one was given if(!material.empty()) sub->setMaterialName(material); /* Old commented D code. Might be useful when reimplementing animation. // Assign this submesh to the given bone VertexBoneAssignment v; v.boneIndex = ((Bone*)bone)->getHandle(); v.weight = 1.0; std::cerr << "+ Assigning bone index " << v.boneIndex << "\n"; for(int i=0; i < numVerts; i++) { v.vertexIndex = i; sub->addBoneAssignment(v); } */ }
//----------------------------------------------------------------------- void MeshManager::tesselate2DMesh(SubMesh* sm, unsigned short meshWidth, unsigned short meshHeight, bool doubleSided, HardwareBuffer::Usage indexBufferUsage, bool indexShadowBuffer) { // The mesh is built, just make a list of indexes to spit out the triangles unsigned short vInc, v, iterations; if (doubleSided) { iterations = 2; vInc = 1; v = 0; // Start with front } else { iterations = 1; vInc = 1; v = 0; } // Allocate memory for faces // Num faces, width*height*2 (2 tris per square), index count is * 3 on top sm->indexData->indexCount = (meshWidth-1) * (meshHeight-1) * 2 * iterations * 3; sm->indexData->indexBuffer = HardwareBufferManager::getSingleton(). createIndexBuffer(HardwareIndexBuffer::IT_16BIT, sm->indexData->indexCount, indexBufferUsage, indexShadowBuffer); unsigned short v1, v2, v3; //bool firstTri = true; HardwareIndexBufferSharedPtr ibuf = sm->indexData->indexBuffer; // Lock the whole buffer unsigned short* pIndexes = static_cast<unsigned short*>( ibuf->lock(HardwareBuffer::HBL_DISCARD) ); while (iterations--) { // Make tris in a zigzag pattern (compatible with strips) unsigned short u = 0; unsigned short uInc = 1; // Start with moving +u unsigned short vCount = meshHeight - 1; while (vCount--) { unsigned short uCount = meshWidth - 1; while (uCount--) { // First Tri in cell // ----------------- v1 = ((v + vInc) * meshWidth) + u; v2 = (v * meshWidth) + u; v3 = ((v + vInc) * meshWidth) + (u + uInc); // Output indexes *pIndexes++ = v1; *pIndexes++ = v2; *pIndexes++ = v3; // Second Tri in cell // ------------------ v1 = ((v + vInc) * meshWidth) + (u + uInc); v2 = (v * meshWidth) + u; v3 = (v * meshWidth) + (u + uInc); // Output indexes *pIndexes++ = v1; *pIndexes++ = v2; *pIndexes++ = v3; // Next column u += uInc; } // Next row v += vInc; u = 0; } // Reverse vInc for double sided v = meshHeight - 1; vInc = -vInc; } // Unlock ibuf->unlock(); }
void GeomUtils::createSphere(VertexData*& vertexData, IndexData*& indexData , float radius , int nRings, int nSegments , bool bNormals , bool bTexCoords) { assert(vertexData && indexData); // define the vertex format VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); if (bNormals) { // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); } // two dimensional texture coordinates if (bTexCoords) { vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); currOffset += VertexElement::getTypeSize(VET_FLOAT2); } // allocate the vertex buffer vertexData->vertexCount = (nRings + 1) * (nSegments+1); HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer indexData->indexCount = 6 * nRings * (nSegments + 1); indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); float fDeltaRingAngle = (Math::PI / nRings); float fDeltaSegAngle = (2 * Math::PI / nSegments); unsigned short wVerticeIndex = 0 ; // Generate the group of rings for the sphere for( int ring = 0; ring <= nRings; ring++ ) { float r0 = radius * sinf (ring * fDeltaRingAngle); float y0 = radius * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(int seg = 0; seg <= nSegments; seg++) { float x0 = r0 * sinf(seg * fDeltaSegAngle); float z0 = r0 * cosf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere *pVertex++ = x0; *pVertex++ = y0; *pVertex++ = z0; if (bNormals) { Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy(); *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z; } if (bTexCoords) { *pVertex++ = (float) seg / (float) nSegments; *pVertex++ = (float) ring / (float) nRings; } if (ring != nRings) { // each vertex (except the last) has six indices pointing to it *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex; *pIndices++ = wVerticeIndex + nSegments; *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex + 1; *pIndices++ = wVerticeIndex; wVerticeIndex ++; } }; // end for seg } // end for ring // Unlock vBuf->unlock(); iBuf->unlock(); }
/// reads out mesh vertices and indices /// must be called before rayintersect if the mesh has moved/deformed, probably every frame for animated meshes and mousepicking /// calling it once for static meshes is enough /// code is based on OgreOpCode MeshCollisionShape::convertMeshData void MeshShape::Update (Ogre::Entity *pEntity) { // if (!pEntity) return; if (mpMesh.isNull()) return; if (pEntity && mbInitialised && !pEntity->hasSkeleton()) return; // no need to update static models every frame... mbInitialised = true; //printf("#### MeshShape::Update\n"); //printf("MeshShape::Update skeleton=%d\n",pEntity->hasSkeleton()?1:0); //assert(pEntity->getMesh().get() == mpMesh.get() && "mesh pointer changed ! (ogrecaching/garbage collection?)"); mlVertices.clear(); mlIndices.clear(); bool added_shared = false; size_t current_offset = 0; size_t shared_offset = 0; size_t next_offset = 0; size_t index_offset = 0; int numOfSubs = 0; // true if the entity is possibly animated (=has skeleton) , this means Update should be called every frame bool useSoftwareBlendingVertices = pEntity && pEntity->hasSkeleton(); if (useSoftwareBlendingVertices) { pEntity->_updateAnimation(); } // Run through the submeshes again, adding the data into the arrays for ( size_t i = 0; i < mpMesh->getNumSubMeshes(); ++i) { SubMesh* submesh = mpMesh->getSubMesh(i); bool useSharedVertices = submesh->useSharedVertices; //---------------------------------------------------------------- // GET VERTEXDATA //---------------------------------------------------------------- const VertexData * vertex_data; if(useSoftwareBlendingVertices) vertex_data = useSharedVertices ? pEntity->_getSkelAnimVertexData() : pEntity->getSubEntity(i)->_getSkelAnimVertexData(); else vertex_data = useSharedVertices ? mpMesh->sharedVertexData : submesh->vertexData; if((!useSharedVertices)||(useSharedVertices && !added_shared)) { if(useSharedVertices) { added_shared = true; shared_offset = current_offset; } const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double // as second argument. So make it float, to avoid trouble when Ogre::Real is // comiled/typedefed as double: float* pReal; mlVertices.reserve(mlVertices.size()+vertex_data->vertexCount); for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); if (mlVertices.size() == 0) { mvMin.x = mvMax.x = pReal[0]; mvMin.y = mvMax.y = pReal[1]; mvMin.z = mvMax.z = pReal[2]; } else { if (mvMin.x > pReal[0]) mvMin.x = pReal[0]; if (mvMin.y > pReal[1]) mvMin.y = pReal[1]; if (mvMin.z > pReal[2]) mvMin.z = pReal[2]; if (mvMax.x < pReal[0]) mvMax.x = pReal[0]; if (mvMax.y < pReal[1]) mvMax.y = pReal[1]; if (mvMax.z < pReal[2]) mvMax.z = pReal[2]; } mlVertices.push_back(Vector3(pReal[0],pReal[1],pReal[2])); } vbuf->unlock(); next_offset += vertex_data->vertexCount; } // TODO : GET TEXCOORD DATA // TODO : GET FACE-MATERIAL MAP, or at least material cound.... // TODO : no need to update index, texcoord and material buffers for animation ! // TODO : const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES); // for texture alpha checking, VertexElementType should be VET_FLOAT2 //---------------------------------------------------------------- // GET INDEXDATA //---------------------------------------------------------------- IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT); ::uint32 *pLong = static_cast< ::uint32*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); ::uint16* pShort = reinterpret_cast< ::uint16*>(pLong); size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset; mlIndices.reserve(mlIndices.size()+3*numTris); if ( use32bitindexes ) { for ( size_t k = 0; k < numTris*3; ++k) { mlIndices.push_back(pLong[k] + static_cast<int>(offset)); } } else { for ( size_t k = 0; k < numTris*3; ++k) { mlIndices.push_back(static_cast<int>(pShort[k]) + static_cast<int>(offset)); } } ibuf->unlock(); current_offset = next_offset; } //mvMid = 0.5*(mvMin + mvMax); //mfBoundRad = 0.5 * (mvMax - mvMin).length(); }
void createSphereMesh(const String &name, const float radius, const int slices, const int stacks) { MeshPtr mesh = MeshManager::getSingleton().createManual(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mesh->sharedVertexData = new VertexData(); mesh->_setBounds(AxisAlignedBox(Vector3(-radius, -radius, -radius), Vector3(radius, radius, radius))); mesh->_setBoundingSphereRadius(radius); VertexData *vertexData = mesh->sharedVertexData; vertexData->vertexDeclaration->addElement(0, 0, VET_FLOAT3, VES_POSITION); vertexData->vertexDeclaration->addElement(1, 0, VET_FLOAT3, VES_NORMAL); vertexData->vertexCount = slices * (stacks + 1); HardwareVertexBufferSharedPtr positionBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( vertexData->vertexDeclaration->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); HardwareVertexBufferSharedPtr normalBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( vertexData->vertexDeclaration->getVertexSize(1), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); float *position = static_cast<float *>(positionBuffer->lock(HardwareBuffer::HBL_DISCARD)); float *normal = static_cast<float *>(normalBuffer->lock(HardwareBuffer::HBL_DISCARD)); for (int ring = 0; ring <= stacks; ring++) { float r = radius * sinf(ring * Math::PI / stacks); float y = radius * cosf(ring * Math::PI / stacks); for (int segment = 0; segment < slices; segment++) { float x = r * sinf(segment * 2 * Math::PI / slices); float z = r * cosf(segment * 2 * Math::PI / slices); *position++ = x; *position++ = y; *position++ = z; Vector3 tmp = Vector3(x, y, z).normalisedCopy(); *normal++ = tmp.x; *normal++ = tmp.y; *normal++ = tmp.z; } } positionBuffer->unlock(); normalBuffer->unlock(); vertexData->vertexBufferBinding->setBinding(0, positionBuffer); vertexData->vertexBufferBinding->setBinding(1, normalBuffer); SubMesh *subMesh = mesh->createSubMesh(); subMesh->useSharedVertices = true; IndexData *indexData = subMesh->indexData; indexData->indexCount = 6 * slices * stacks; HardwareIndexBufferSharedPtr indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); unsigned short *index = static_cast<unsigned short *>(indexBuffer->lock(HardwareBuffer::HBL_DISCARD)); unsigned short i = 0; for (int ring = 0; ring < stacks; ring++) { for (int segment = 0; segment < slices - 1; segment++) { *index++ = i; *index++ = i + slices; *index++ = i + slices + 1; *index++ = i; *index++ = i + slices + 1; *index++ = i + 1; i++; } *index++ = i; *index++ = i + slices; *index++ = i + 1; *index++ = i; *index++ = i + 1; *index++ = i + 1 - slices; i++; } indexBuffer->unlock(); indexData->indexBuffer = indexBuffer; mesh->load(); }
void Obstacle::createSphere(const std::string& strName, const float r, const int nRings, const int nSegments) { MeshPtr pSphere = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *pSphereVertex = pSphere->createSubMesh(); pSphere->sharedVertexData = new VertexData(); VertexData* vertexData = pSphere->sharedVertexData; // define the vertex format VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // two dimensional texture coordinates vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); currOffset += VertexElement::getTypeSize(VET_FLOAT2); // allocate the vertex buffer vertexData->vertexCount = (nRings + 1) * (nSegments+1); HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer pSphereVertex->indexData->indexCount = 6 * nRings * (nSegments + 1); pSphereVertex->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, pSphereVertex->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = pSphereVertex->indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); float fDeltaRingAngle = (Math::PI / nRings); float fDeltaSegAngle = (2 * Math::PI / nSegments); unsigned short wVerticeIndex = 0 ; // Generate the group of rings for the sphere for( int ring = 0; ring <= nRings; ring++ ) { float r0 = r * sinf (ring * fDeltaRingAngle); float y0 = r * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(int seg = 0; seg <= nSegments; seg++) { float x0 = r0 * sinf(seg * fDeltaSegAngle); float z0 = r0 * cosf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere *pVertex++ = x0; *pVertex++ = y0; *pVertex++ = z0; Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy(); *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z; *pVertex++ = (float) seg / (float) nSegments; *pVertex++ = (float) ring / (float) nRings; if (ring != nRings) { // each vertex (except the last) has six indices pointing to it *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex; *pIndices++ = wVerticeIndex + nSegments; *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex + 1; *pIndices++ = wVerticeIndex; wVerticeIndex ++; } }; // end for seg } // end for ring // Unlock vBuf->unlock(); iBuf->unlock(); // Generate face list pSphereVertex->useSharedVertices = true; // the original code was missing this line: pSphere->_setBounds( AxisAlignedBox( Vector3(-r, -r, -r), Vector3(r, r, r) ), false ); pSphere->_setBoundingSphereRadius(r); // this line makes clear the mesh is loaded (avoids memory leaks) pSphere->load(); }
void ModelConverter::WriteSubMesh( DiSubMesh* subMod, const Ogre::SubMesh* s ) { switch(s->operationType) { case RenderOperation::OT_LINE_LIST: subMod->SetPrimitiveType(D3DPT_LINELIST); break; case RenderOperation::OT_LINE_STRIP: subMod->SetPrimitiveType(D3DPT_LINESTRIP); break; case RenderOperation::OT_POINT_LIST: subMod->SetPrimitiveType(D3DPT_POINTLIST); break; case RenderOperation::OT_TRIANGLE_FAN: subMod->SetPrimitiveType(D3DPT_TRIANGLEFAN); break; case RenderOperation::OT_TRIANGLE_LIST: subMod->SetPrimitiveType(PT_TRIANGLELIST); break; case RenderOperation::OT_TRIANGLE_STRIP: subMod->SetPrimitiveType(D3DPT_TRIANGLESTRIP); break; } VertexData* vertexData = nullptr; if (mMesh->sharedVertexData) { vertexData = mMesh->sharedVertexData; } else { vertexData = s->vertexData; } int numFaces = 0; switch(s->operationType) { case RenderOperation::OT_TRIANGLE_LIST: // triangle list numFaces = s->indexData->indexCount / 3; break; case RenderOperation::OT_LINE_LIST: numFaces = s->indexData->indexCount / 2; break; case RenderOperation::OT_TRIANGLE_FAN: case RenderOperation::OT_TRIANGLE_STRIP: // triangle fan or triangle strip numFaces = s->indexData->indexCount - 2; break; default: OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Unsupported render operation type", __FUNCTION__); } subMod->SetPrimitiveCount(numFaces); subMod->SetVerticeNum(vertexData->vertexCount); // material name DiString matName; matName.Format("%s_%d.mtl",subMod->GetParentMesh()->GetName().c_str(),subMod->GetIndex()); subMod->SetMaterialName(matName); bool use32BitIndexes = (!s->indexData->indexBuffer.isNull() && s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT); // Write each face in turn unsigned int* pInt = 0; unsigned short* pShort = 0; HardwareIndexBufferSharedPtr ibuf = s->indexData->indexBuffer; // index data if (use32BitIndexes) { pInt = static_cast<unsigned int*>( ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); } else { pShort = static_cast<unsigned short*>( ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); } void* indata = subMod->CreateIndexData(s->indexData->indexCount,use32BitIndexes?TRUE:FALSE); if (use32BitIndexes) { memcpy(indata,pInt,sizeof(unsigned int)*s->indexData->indexCount); } else { memcpy(indata,pShort,sizeof(unsigned short)*s->indexData->indexCount); } ibuf->unlock(); // vertex declaration VertexDeclaration* decl = vertexData->vertexDeclaration; VertexBufferBinding* bind = vertexData->vertexBufferBinding; VertexBufferBinding::VertexBufferBindingMap::const_iterator b, bend; bend = bind->getBindings().end(); // iterate over buffers int bindCount = 0; for(b = bind->getBindings().begin(); b != bend; ++b,++bindCount) { const HardwareVertexBufferSharedPtr vbuf = b->second; unsigned short bufferIdx = b->first; // get all the elements that relate to this buffer VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufferIdx); VertexDeclaration::VertexElementList::iterator i, iend; iend = elems.end(); unsigned short nuDemiureCoords = 0; for (i = elems.begin(); i != iend; ++i) { VertexElement& elem = *i; D3DDECLTYPE type = ConverteVertType(elem.getType()); D3DDECLUSAGE usage; bool texcoord = false; switch(elem.getSemantic()) { case VES_POSITION: usage = D3DDECLUSAGE_POSITION; break; case VES_NORMAL: usage = D3DDECLUSAGE_NORMAL; break; case VES_TANGENT: usage = D3DDECLUSAGE_TANGENT; break; case VES_BINORMAL: usage = D3DDECLUSAGE_BINORMAL; break; case VES_DIFFUSE: case VES_SPECULAR: usage = D3DDECLUSAGE_COLOR; break; case VES_TEXTURE_COORDINATES: usage = D3DDECLUSAGE_TEXCOORD; ++nuDemiureCoords; texcoord = true; break; default: DI_ERROR("Unsupported semantic"); } subMod->GetVertexElements().AddElement(bindCount,type,usage,texcoord?nuDemiureCoords-1:0); } int stride = subMod->GetVertexElements().GetStreamElementsSize(bindCount); void* vertData = subMod->CreateSourceData(bindCount,vertexData->vertexCount,stride); unsigned char* pVert = static_cast<unsigned char*>( vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); memcpy(vertData,pVert,vertexData->vertexCount*stride); vbuf->unlock(); } // vertex weight if (mMesh->hasSkeleton()) { LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments..."); if(const_cast<SubMesh*>(s)->getBoneAssignments().empty()) { SubMesh::BoneAssignmentIterator bi = mMesh->getBoneAssignmentIterator(); while (bi.hasMoreElements()) { const VertexBoneAssignment& assign = bi.getNext(); if (assign.weight > 0.0f) { subMod->AddWeight(assign.vertexIndex,assign.boneIndex,assign.weight); } } } else { SubMesh::BoneAssignmentIterator bi = (const_cast<SubMesh*>(s))->getBoneAssignmentIterator(); while (bi.hasMoreElements()) { const VertexBoneAssignment& assign = bi.getNext(); if (assign.weight > 0.0f) { subMod->AddWeight(assign.vertexIndex,assign.boneIndex,assign.weight); } } } subMod->RationaliseBoneWeights(); } }
// ------------------------------------------------------------------------ void ShadowCaster::generateShadowVolume(EdgeData* edgeData, const HardwareIndexBufferSharedPtr& indexBuffer, const Light* light, ShadowRenderableList& shadowRenderables, unsigned long flags) { // Edge groups should be 1:1 with shadow renderables assert(edgeData->edgeGroups.size() == shadowRenderables.size()); // Whether to use the McGuire method, a triangle fan covering all silhouette // this won't work properly with multiple separate edge groups bool useMcGuire = edgeData->edgeGroups.size() <= 1; EdgeData::EdgeGroupList::const_iterator egi, egiend; ShadowRenderableList::const_iterator si; Light::LightTypes lightType = light->getType(); // pre-count the size of index data we need since it makes a big perf difference // to GL in particular if we lock a smaller area of the index buffer size_t preCountIndexes = 0; si = shadowRenderables.begin(); egiend = edgeData->edgeGroups.end(); for (egi = edgeData->edgeGroups.begin(); egi != egiend; ++egi, ++si) { const EdgeData::EdgeGroup& eg = *egi; bool firstDarkCapTri = true; EdgeData::EdgeList::const_iterator i, iend; iend = eg.edges.end(); for (i = eg.edges.begin(); i != iend; ++i) { const EdgeData::Edge& edge = *i; // Silhouette edge, when two tris has opposite light facing, or // degenerate edge where only tri 1 is valid and the tri light facing char lightFacing = edgeData->triangleLightFacings[edge.triIndex[0]]; if ((edge.degenerate && lightFacing) || (!edge.degenerate && (lightFacing != edgeData->triangleLightFacings[edge.triIndex[1]]))) { preCountIndexes += 3; // Are we extruding to infinity? if (!(lightType == Light::LT_DIRECTIONAL && flags & SRF_EXTRUDE_TO_INFINITY)) { preCountIndexes += 3; } if(useMcGuire) { // Do dark cap tri // Use McGuire et al method, a triangle fan covering all silhouette // edges and one point (taken from the initial tri) if (flags & SRF_INCLUDE_DARK_CAP) { if (firstDarkCapTri) { firstDarkCapTri = false; } else { preCountIndexes += 3; } } } } } if(useMcGuire) { // Do light cap if (flags & SRF_INCLUDE_LIGHT_CAP) { // Iterate over the triangles which are using this vertex set EdgeData::TriangleList::const_iterator ti, tiend; EdgeData::TriangleLightFacingList::const_iterator lfi; ti = edgeData->triangles.begin() + eg.triStart; tiend = ti + eg.triCount; lfi = edgeData->triangleLightFacings.begin() + eg.triStart; for ( ; ti != tiend; ++ti, ++lfi) { const EdgeData::Triangle& t = *ti; assert(t.vertexSet == eg.vertexSet); // Check it's light facing if (*lfi) { preCountIndexes += 3; } } } } else { // Do both caps int increment = ((flags & SRF_INCLUDE_DARK_CAP) ? 3 : 0) + ((flags & SRF_INCLUDE_LIGHT_CAP) ? 3 : 0); if(increment != 0) { // Iterate over the triangles which are using this vertex set EdgeData::TriangleList::const_iterator ti, tiend; EdgeData::TriangleLightFacingList::const_iterator lfi; ti = edgeData->triangles.begin() + eg.triStart; tiend = ti + eg.triCount; lfi = edgeData->triangleLightFacings.begin() + eg.triStart; for ( ; ti != tiend; ++ti, ++lfi) { const EdgeData::Triangle& t = *ti; assert(t.vertexSet == eg.vertexSet); // Check it's light facing if (*lfi) preCountIndexes += increment; } break; } } } // End pre-count // Lock index buffer for writing, just enough length as we need unsigned short* pIdx = static_cast<unsigned short*>( indexBuffer->lock(0, sizeof(unsigned short) * preCountIndexes, HardwareBuffer::HBL_DISCARD)); size_t numIndices = 0; // Iterate over the groups and form renderables for each based on their // lightFacing si = shadowRenderables.begin(); egiend = edgeData->edgeGroups.end(); for (egi = edgeData->edgeGroups.begin(); egi != egiend; ++egi, ++si) { const EdgeData::EdgeGroup& eg = *egi; // Initialise the index start for this shadow renderable IndexData* indexData = (*si)->getRenderOperationForUpdate()->indexData; indexData->indexStart = numIndices; // original number of verts (without extruded copy) size_t originalVertexCount = eg.vertexData->vertexCount; bool firstDarkCapTri = true; unsigned short darkCapStart; EdgeData::EdgeList::const_iterator i, iend; iend = eg.edges.end(); for (i = eg.edges.begin(); i != iend; ++i) { const EdgeData::Edge& edge = *i; // Silhouette edge, when two tris has opposite light facing, or // degenerate edge where only tri 1 is valid and the tri light facing char lightFacing = edgeData->triangleLightFacings[edge.triIndex[0]]; if ((edge.degenerate && lightFacing) || (!edge.degenerate && (lightFacing != edgeData->triangleLightFacings[edge.triIndex[1]]))) { size_t v0 = edge.vertIndex[0]; size_t v1 = edge.vertIndex[1]; if (!lightFacing) { // Inverse edge indexes when t1 is light away std::swap(v0, v1); } /* Note edge(v0, v1) run anticlockwise along the edge from the light facing tri so to point shadow volume tris outward, light cap indexes have to be backwards We emit 2 tris if light is a point light, 1 if light is directional, because directional lights cause all points to converge to a single point at infinity. First side tri = near1, near0, far0 Second tri = far0, far1, near1 'far' indexes are 'near' index + originalVertexCount because 'far' verts are in the second half of the buffer */ assert(v1 < 65536 && v0 < 65536 && (v0 + originalVertexCount) < 65536 && "Vertex count exceeds 16-bit index limit!"); *pIdx++ = static_cast<unsigned short>(v1); *pIdx++ = static_cast<unsigned short>(v0); *pIdx++ = static_cast<unsigned short>(v0 + originalVertexCount); numIndices += 3; // Are we extruding to infinity? if (!(lightType == Light::LT_DIRECTIONAL && flags & SRF_EXTRUDE_TO_INFINITY)) { // additional tri to make quad *pIdx++ = static_cast<unsigned short>(v0 + originalVertexCount); *pIdx++ = static_cast<unsigned short>(v1 + originalVertexCount); *pIdx++ = static_cast<unsigned short>(v1); numIndices += 3; } if(useMcGuire) { // Do dark cap tri // Use McGuire et al method, a triangle fan covering all silhouette // edges and one point (taken from the initial tri) if (flags & SRF_INCLUDE_DARK_CAP) { if (firstDarkCapTri) { darkCapStart = static_cast<unsigned short>(v0 + originalVertexCount); firstDarkCapTri = false; } else { *pIdx++ = darkCapStart; *pIdx++ = static_cast<unsigned short>(v1 + originalVertexCount); *pIdx++ = static_cast<unsigned short>(v0 + originalVertexCount); numIndices += 3; } } } } } if(!useMcGuire) { // Do dark cap if (flags & SRF_INCLUDE_DARK_CAP) { // Iterate over the triangles which are using this vertex set EdgeData::TriangleList::const_iterator ti, tiend; EdgeData::TriangleLightFacingList::const_iterator lfi; ti = edgeData->triangles.begin() + eg.triStart; tiend = ti + eg.triCount; lfi = edgeData->triangleLightFacings.begin() + eg.triStart; for ( ; ti != tiend; ++ti, ++lfi) { const EdgeData::Triangle& t = *ti; assert(t.vertexSet == eg.vertexSet); // Check it's light facing if (*lfi) { assert(t.vertIndex[0] < 65536 && t.vertIndex[1] < 65536 && t.vertIndex[2] < 65536 && "16-bit index limit exceeded!"); *pIdx++ = static_cast<unsigned short>(t.vertIndex[1] + originalVertexCount); *pIdx++ = static_cast<unsigned short>(t.vertIndex[0] + originalVertexCount); *pIdx++ = static_cast<unsigned short>(t.vertIndex[2] + originalVertexCount); numIndices += 3; } } } } // Do light cap if (flags & SRF_INCLUDE_LIGHT_CAP) { // separate light cap? if ((*si)->isLightCapSeparate()) { // update index count for this shadow renderable indexData->indexCount = numIndices - indexData->indexStart; // get light cap index data for update indexData = (*si)->getLightCapRenderable()->getRenderOperationForUpdate()->indexData; // start indexes after the current total indexData->indexStart = numIndices; } // Iterate over the triangles which are using this vertex set EdgeData::TriangleList::const_iterator ti, tiend; EdgeData::TriangleLightFacingList::const_iterator lfi; ti = edgeData->triangles.begin() + eg.triStart; tiend = ti + eg.triCount; lfi = edgeData->triangleLightFacings.begin() + eg.triStart; for ( ; ti != tiend; ++ti, ++lfi) { const EdgeData::Triangle& t = *ti; assert(t.vertexSet == eg.vertexSet); // Check it's light facing if (*lfi) { assert(t.vertIndex[0] < 65536 && t.vertIndex[1] < 65536 && t.vertIndex[2] < 65536 && "16-bit index limit exceeded!"); *pIdx++ = static_cast<unsigned short>(t.vertIndex[0]); *pIdx++ = static_cast<unsigned short>(t.vertIndex[1]); *pIdx++ = static_cast<unsigned short>(t.vertIndex[2]); numIndices += 3; } } } // update index count for current index data (either this shadow renderable or its light cap) indexData->indexCount = numIndices - indexData->indexStart; } // Unlock index buffer indexBuffer->unlock(); // In debug mode, check we didn't overrun the index buffer assert(numIndices <= indexBuffer->getNumIndexes() && "Index buffer overrun while generating shadow volume!! " "You must increase the size of the shadow index buffer."); }