void GeomUtils::createSphere( const String& strName , float radius , int nRings, int nSegments , bool bNormals , bool bTexCoords) { MeshPtr pSphere = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *pSphereVertex = pSphere->createSubMesh(); pSphere->sharedVertexData = new VertexData(); createSphere(pSphere->sharedVertexData, pSphereVertex->indexData , radius , nRings, nSegments , bNormals // need normals , bTexCoords // need texture co-ordinates ); // Generate face list pSphereVertex->useSharedVertices = true; // the original code was missing this line: pSphere->_setBounds( AxisAlignedBox( Vector3(-radius, -radius, -radius), Vector3(radius, radius, radius) ), false ); pSphere->_setBoundingSphereRadius(radius); // this line makes clear the mesh is loaded (avoids memory leaks) pSphere->load(); }
void SplineRoad::AddMesh(MeshPtr mesh, String sMesh, const AxisAlignedBox& aabox, Entity** pEnt, SceneNode** pNode, String sEnd) { mesh->_setBounds(aabox); mesh->_setBoundingSphereRadius((aabox.getMaximum()-aabox.getMinimum()).length()/2.0); mesh->load(); unsigned short src, dest; if (!mesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest)) mesh->buildTangentVectors(VES_TANGENT, src, dest); *pEnt = mSceneMgr->createEntity("rd.ent"+sEnd, sMesh); *pNode = mSceneMgr->getRootSceneNode()->createChildSceneNode("rd.node"+sEnd); (*pNode)->attachObject(*pEnt); (*pEnt)->setVisible(false); (*pEnt)->setCastShadows(false); (*pEnt)->setVisibilityFlags(RV_Road); }
//----------------------------------------------------------------------------- MeshPtr ManualObject::convertToMesh(const String& meshName, const String& groupName) { if (mCurrentSection) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "You cannot call convertToMesh() whilst you are in the middle of " "defining the object; call end() first.", "ManualObject::convertToMesh"); } if (mSectionList.empty()) { OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "No data defined to convert to a mesh.", "ManualObject::convertToMesh"); } MeshPtr m = MeshManager::getSingleton().createManual(meshName, groupName); for (SectionList::iterator i = mSectionList.begin(); i != mSectionList.end(); ++i) { ManualObjectSection* sec = *i; RenderOperation* rop = sec->getRenderOperation(); SubMesh* sm = m->createSubMesh(); sm->useSharedVertices = false; sm->operationType = rop->operationType; sm->setMaterialName(sec->getMaterialName(), groupName); // Copy vertex data; replicate buffers too sm->vertexData = rop->vertexData->clone(true); // Copy index data; replicate buffers too; delete the default, old one to avoid memory leaks // check if index data is present if (rop->indexData) { // Copy index data; replicate buffers too; delete the default, old one to avoid memory leaks OGRE_DELETE sm->indexData; sm->indexData = rop->indexData->clone(true); } } // update bounds m->_setBounds(mAABB); m->_setBoundingSphereRadius(mRadius); m->load(); return m; }
MeshPtr Tile::getMesh(std::string tileName) { // Create the overall mesh. MeshPtr tileMesh = MeshManager::getSingleton().createManual(tileName, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // Add the tile as a submesh to mesh major. this->_generateSubMesh(tileMesh); /// Set bounding information (for culling) tileMesh->_setBounds(AxisAlignedBox(-5,-5,-5,5,5,5)); tileMesh->_setBoundingSphereRadius(Math::Sqrt(3*5*5)); // Signal that the mesh has loaded. tileMesh->load(); // Return finished mesh. return tileMesh; }
void GeomUtils::createCone(const Ogre::String& strName , float radius , float height, int nVerticesInBase) { MeshPtr pCone = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *pConeVertex = pCone->createSubMesh(); pCone->sharedVertexData = new VertexData(); createCone(pCone->sharedVertexData, pConeVertex->indexData , radius , height , nVerticesInBase); // Generate face list pConeVertex->useSharedVertices = true; // the original code was missing this line: pCone->_setBounds( AxisAlignedBox( Vector3(-radius, 0, -radius), Vector3(radius, height, radius) ), false ); pCone->_setBoundingSphereRadius(Math::Sqrt(height*height + radius*radius)); // this line makes clear the mesh is loaded (avoids memory leaks) pCone->load(); }
void _prepareMesh() { int i,lvl ; mesh = MeshManager::getSingleton().createManual(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME) ; subMesh = mesh->createSubMesh(); subMesh->useSharedVertices=false; int numVertices = 4 ; if (first) { // first Circle, create some static common data first = false ; // static buffer for position and normals posnormVertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( 6*sizeof(float), // size of one vertex data 4, // number of vertices HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage false); // no shadow buffer float *posnormBufData = (float*) posnormVertexBuffer-> lock(HardwareBuffer::HBL_DISCARD); for(i=0;i<numVertices;i++) { posnormBufData[6*i+0]=((Real)(i%2)-0.5f)*CIRCLE_SIZE; // pos X posnormBufData[6*i+1]=0; // pos Y posnormBufData[6*i+2]=((Real)(i/2)-0.5f)*CIRCLE_SIZE; // pos Z posnormBufData[6*i+3]=0 ; // normal X posnormBufData[6*i+4]=1 ; // normal Y posnormBufData[6*i+5]=0 ; // normal Z } posnormVertexBuffer->unlock(); // static buffers for 16 sets of texture coordinates texcoordsVertexBuffers = new HardwareVertexBufferSharedPtr[16]; for(lvl=0;lvl<16;lvl++) { texcoordsVertexBuffers[lvl] = HardwareBufferManager::getSingleton().createVertexBuffer( 2*sizeof(float), // size of one vertex data numVertices, // number of vertices HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage false); // no shadow buffer float *texcoordsBufData = (float*) texcoordsVertexBuffers[lvl]-> lock(HardwareBuffer::HBL_DISCARD); float x0 = (Real)(lvl % 4) * 0.25 ; float y0 = (Real)(lvl / 4) * 0.25 ; y0 = 0.75-y0 ; // upside down for(i=0;i<4;i++) { texcoordsBufData[i*2 + 0]= x0 + 0.25 * (Real)(i%2) ; texcoordsBufData[i*2 + 1]= y0 + 0.25 * (Real)(i/2) ; } texcoordsVertexBuffers[lvl]->unlock(); } // Index buffer for 2 faces unsigned short faces[6] = {2,1,0, 2,3,1}; indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, 6, HardwareBuffer::HBU_STATIC_WRITE_ONLY); indexBuffer->writeData(0, indexBuffer->getSizeInBytes(), faces, true); // true? } // Initialize vertex data subMesh->vertexData = new VertexData(); subMesh->vertexData->vertexStart = 0; subMesh->vertexData->vertexCount = 4; // first, set vertex buffer bindings VertexBufferBinding *vbind = subMesh->vertexData->vertexBufferBinding ; vbind->setBinding(0, posnormVertexBuffer); vbind->setBinding(1, texcoordsVertexBuffers[0]); // now, set vertex buffer declaration VertexDeclaration *vdecl = subMesh->vertexData->vertexDeclaration ; vdecl->addElement(0, 0, VET_FLOAT3, VES_POSITION); vdecl->addElement(0, 3*sizeof(float), VET_FLOAT3, VES_NORMAL); vdecl->addElement(1, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); // Initialize index data subMesh->indexData->indexBuffer = indexBuffer; subMesh->indexData->indexStart = 0; subMesh->indexData->indexCount = 6; // set mesh bounds AxisAlignedBox circleBounds(-CIRCLE_SIZE/2.0f, 0, -CIRCLE_SIZE/2.0f, CIRCLE_SIZE/2.0f, 0, CIRCLE_SIZE/2.0f); mesh->_setBounds(circleBounds); mesh->load(); mesh->touch(); }
/* ******************************************************************************* | implement of CGrassSticks ******************************************************************************* */ void CGrassSticks::createGrassMesh() { MeshPtr mesh = MeshManager::getSingleton().createManual(GRASS_MESH_NAME, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // create a submesh with the grass material SubMesh* sm = mesh->createSubMesh(); sm->setMaterialName("Examples/GrassBlades"); sm->useSharedVertices = false; sm->vertexData = OGRE_NEW VertexData(); sm->vertexData->vertexStart = 0; sm->vertexData->vertexCount = 12; sm->indexData->indexCount = 18; // specify a vertex format declaration for our mesh: 3 floats for position, 3 floats for normal, 2 floats for UV VertexDeclaration* decl = sm->vertexData->vertexDeclaration; decl->addElement(0, 0, VET_FLOAT3, VES_POSITION); decl->addElement(0, sizeof(float) * 3, VET_FLOAT3, VES_NORMAL); decl->addElement(0, sizeof(float) * 6, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); // create a vertex buffer HardwareVertexBufferSharedPtr vb = HardwareBufferManager::getSingleton().createVertexBuffer (decl->getVertexSize(0), sm->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); GrassVertex* verts = (GrassVertex*)vb->lock(HardwareBuffer::HBL_DISCARD); // start filling in vertex data for (unsigned int i = 0; i < 3; i++) // each grass mesh consists of 3 planes { // planes intersect along the Y axis with 60 degrees between them Real x = Math::Cos(Degree(i * 60)) * GRASS_WIDTH / 2; Real z = Math::Sin(Degree(i * 60)) * GRASS_WIDTH / 2; for (unsigned int j = 0; j < 4; j++) // each plane has 4 vertices { GrassVertex& vert = verts[i * 4 + j]; vert.x = j < 2 ? -x : x; vert.y = j % 2 ? 0 : GRASS_HEIGHT; vert.z = j < 2 ? -z : z; // all normals point straight up vert.nx = 0; vert.ny = 1; vert.nz = 0; vert.u = j < 2 ? 0 : 1; vert.v = j % 2; } } vb->unlock(); // commit vertex changes sm->vertexData->vertexBufferBinding->setBinding(0, vb); // bind vertex buffer to our submesh // create an index buffer sm->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer (HardwareIndexBuffer::IT_16BIT, sm->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // start filling in index data Ogre::uint16* indices = (Ogre::uint16*)sm->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD); for (unsigned int i = 0; i < 3; i++) // each grass mesh consists of 3 planes { unsigned int off = i * 4; // each plane consists of 2 triangles *indices++ = 0 + off; *indices++ = 3 + off; *indices++ = 1 + off; *indices++ = 0 + off; *indices++ = 2 + off; *indices++ = 3 + off; } sm->indexData->indexBuffer->unlock(); // commit index changes // update mesh AABB Ogre::AxisAlignedBox aabb; aabb.setExtents(-1,-1,-1,1,1,1); mesh->_setBounds(aabb); // Ogre::MeshSerializer serial; // serial.exportMesh(mesh.getPointer(), "grass.mesh"); }
Mesh *GrassLoader::generateGrass_SPRITE(PageInfo &page, GrassLayer *layer, float *grassPositions, unsigned int grassCount) { //Calculate the number of quads to be added unsigned int quadCount; quadCount = grassCount; // check for overflows of the uint16's unsigned int maxUInt16 = std::numeric_limits<uint16>::max(); if(grassCount > maxUInt16) { LogManager::getSingleton().logMessage("grass count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) + " (thats the maximum) grass meshes for one page"); return 0; } if(quadCount > maxUInt16) { LogManager::getSingleton().logMessage("quad count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) + " (thats the maximum) grass meshes for one page"); return 0; } //Create manual mesh to store grass quads MeshPtr mesh = MeshManager::getSingleton().createManual(getUniqueID(), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *subMesh = mesh->createSubMesh(); subMesh->useSharedVertices = false; //Setup vertex format information subMesh->vertexData = new VertexData; subMesh->vertexData->vertexStart = 0; subMesh->vertexData->vertexCount = 4 * quadCount; VertexDeclaration* dcl = subMesh->vertexData->vertexDeclaration; size_t offset = 0; dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); dcl->addElement(0, offset, VET_FLOAT4, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT4); dcl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE); offset += VertexElement::getTypeSize(VET_COLOUR); dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES); offset += VertexElement::getTypeSize(VET_FLOAT2); //Populate a new vertex buffer with grass HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton() .createVertexBuffer(offset, subMesh->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); float* pReal = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); //Calculate size variance float rndWidth = layer->maxWidth - layer->minWidth; float rndHeight = layer->maxHeight - layer->minHeight; float minY = Math::POS_INFINITY, maxY = Math::NEG_INFINITY; float *posPtr = grassPositions; //Position array "iterator" for (uint16 i = 0; i < grassCount; ++i) { //Get the x and z positions from the position array float x = *posPtr++; float z = *posPtr++; //Calculate height float y; if (heightFunction){ y = heightFunction(x, z, heightFunctionUserData); } else { y = 0; } float x1 = (x - page.centerPoint.x); float z1 = (z - page.centerPoint.z); //Get the color at the grass position uint32 color; if (layer->colorMap) color = layer->colorMap->getColorAt(x, z, layer->mapBounds); else color = 0xFFFFFFFF; //Calculate size float rnd = *posPtr++; //The same rnd value is used for width and height to maintain aspect ratio float halfXScale = (layer->minWidth + rndWidth * rnd) * 0.5f; float scaleY = (layer->minHeight + rndHeight * rnd); //Randomly mirror grass textures float uvLeft, uvRight; if (*posPtr++ > 0.5f){ uvLeft = 0; uvRight = 1; } else { uvLeft = 1; uvRight = 0; } //Add vertices *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = -halfXScale; *pReal++ = scaleY; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvLeft; *pReal++ = 0; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = +halfXScale; *pReal++ = scaleY; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvRight; *pReal++ = 0; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = -halfXScale; *pReal++ = 0.0f; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvLeft; *pReal++ = 1; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = +halfXScale; *pReal++ = 0.0f; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvRight; *pReal++ = 1; //uv //Update bounds if (y < minY) minY = y; if (y + scaleY > maxY) maxY = y + scaleY; } vbuf->unlock(); subMesh->vertexData->vertexBufferBinding->setBinding(0, vbuf); //Populate index buffer subMesh->indexData->indexStart = 0; subMesh->indexData->indexCount = 6 * quadCount; subMesh->indexData->indexBuffer = HardwareBufferManager::getSingleton() .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, subMesh->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); uint16* pI = static_cast<uint16*>(subMesh->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD)); for (uint16 i = 0; i < quadCount; ++i) { uint16 offset = i * 4; *pI++ = 0 + offset; *pI++ = 2 + offset; *pI++ = 1 + offset; *pI++ = 1 + offset; *pI++ = 2 + offset; *pI++ = 3 + offset; } subMesh->indexData->indexBuffer->unlock(); //subMesh->setBuildEdgesEnabled(autoEdgeBuildEnabled); //Finish up mesh AxisAlignedBox bounds(page.bounds.left - page.centerPoint.x, minY, page.bounds.top - page.centerPoint.z, page.bounds.right - page.centerPoint.x, maxY, page.bounds.bottom - page.centerPoint.z); mesh->_setBounds(bounds); Vector3 temp = bounds.getMaximum() - bounds.getMinimum(); mesh->_setBoundingSphereRadius(temp.length() * 0.5f); LogManager::getSingleton().setLogDetail(static_cast<LoggingLevel>(0)); mesh->setAutoBuildEdgeLists(autoEdgeBuildEnabled); mesh->load(); LogManager::getSingleton().setLogDetail(LL_NORMAL); //Apply grass material to mesh subMesh->setMaterialName(layer->material->getName()); //Return the mesh return mesh.getPointer(); }
void createSphere(const std::string& strName, const float r, const int nRings = 16, const int nSegments = 16) { 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(); }
MeshPtr MeshMergeTool::merge(const Ogre::String& name, const Ogre::String& resourceGroupName) { print("Baking: New Mesh started", V_HIGH); MeshPtr mp = MeshManager::getSingleton().createManual(name, resourceGroupName); if (!mBaseSkeleton.isNull()) { mp->setSkeletonName(mBaseSkeleton->getName()); } AxisAlignedBox totalBounds = AxisAlignedBox(); for (std::vector<Ogre::MeshPtr>::iterator it = mMeshes.begin(); it != mMeshes.end(); ++it) { print("Baking: adding submeshes for " + (*it)->getName(), V_HIGH); // insert all submeshes for (Ogre::ushort sid = 0; sid < (*it)->getNumSubMeshes(); ++sid) { SubMesh* sub = (*it)->getSubMesh(sid); const String name = findSubmeshName((*it), sid); // create submesh with correct name SubMesh* newsub; if (name.length() == 0) { newsub = mp->createSubMesh(); } else { /// @todo check if a submesh with this name has been created before newsub = mp->createSubMesh(name); } newsub->useSharedVertices = sub->useSharedVertices; // add index newsub->indexData = sub->indexData->clone(); // add geometry if (!newsub->useSharedVertices) { newsub->vertexData = sub->vertexData->clone(); if (!mBaseSkeleton.isNull()) { // build bone assignments SubMesh::BoneAssignmentIterator bit = sub->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); newsub->addBoneAssignment(vba); } } } newsub->setMaterialName(sub->getMaterialName()); // Add vertex animations for this submesh Animation *anim = 0; for (unsigned short i = 0; i < (*it)->getNumAnimations(); ++i) { anim = (*it)->getAnimation(i); // get or create the animation for the new mesh Animation *newanim; if (mp->hasAnimation(anim->getName())) { newanim = mp->getAnimation(anim->getName()); } else { newanim = mp->createAnimation(anim->getName(), anim->getLength()); } print("Baking: adding vertex animation " + anim->getName() + " for " + (*it)->getName(), V_HIGH); Animation::VertexTrackIterator vti=anim->getVertexTrackIterator(); while (vti.hasMoreElements()) { VertexAnimationTrack *vt = vti.getNext(); // handle=0 targets the main mesh, handle i (where i>0) targets submesh i-1. // In this case there are only submeshes so index 0 will not be used. unsigned short handle = mp->getNumSubMeshes(); VertexAnimationTrack* newvt = newanim->createVertexTrack( handle, vt->getAssociatedVertexData()->clone(), vt->getAnimationType()); for (int keyFrameIndex = 0; keyFrameIndex < vt->getNumKeyFrames(); ++keyFrameIndex) { switch (vt->getAnimationType()) { case VAT_MORPH: { // copy the keyframe vertex buffer VertexMorphKeyFrame *kf = vt->getVertexMorphKeyFrame(keyFrameIndex); VertexMorphKeyFrame *newkf = newvt->createVertexMorphKeyFrame(kf->getTime()); // This creates a ref to the buffer in the original model // so don't delete it until the export is completed. newkf->setVertexBuffer(kf->getVertexBuffer()); break; } case VAT_POSE: { /// @todo implement pose amination merge break; } case VAT_NONE: default: { break; } } } } } print("Baking: adding submesh '" + name + "' with material " + sub->getMaterialName(), V_HIGH); } // sharedvertices if ((*it)->sharedVertexData) { /// @todo merge with existing sharedVertexData if (!mp->sharedVertexData) { mp->sharedVertexData = (*it)->sharedVertexData->clone(); } if (!mBaseSkeleton.isNull()) { Mesh::BoneAssignmentIterator bit = (*it)->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); mp->addBoneAssignment(vba); } } } print("Baking: adding bounds for " + (*it)->getName(), V_HIGH); // add bounds totalBounds.merge((*it)->getBounds()); } mp->_setBounds(totalBounds); /// @todo merge submeshes with same material /// @todo add parameters mp->buildEdgeList(); print("Baking: Finished", V_HIGH); reset(); return mp; }
MeshPtr MergeMesh::bake() { log( "Baking: New Mesh started" ); MeshPtr mp = MeshManager::getSingleton(). createManual( "mergedMesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); mp->setSkeletonName( m_BaseSkeleton->getName() ); AxisAlignedBox totalBounds = AxisAlignedBox(); for( std::vector< Ogre::MeshPtr >::iterator it = m_Meshes.begin(); it != m_Meshes.end(); ++it ) { log( "Baking: adding submeshes for " + (*it)->getName() ); // insert all submeshes for( Ogre::ushort sid = 0; sid < (*it)->getNumSubMeshes(); ++sid ) { SubMesh* sub = (*it)->getSubMesh( sid ); const String name = findSubmeshName( (*it), sid ); // create submesh with correct name SubMesh* newsub; if( name.length() == 0 ) newsub = mp->createSubMesh( ); else /// @todo check if a submesh with this name has been created before newsub = mp->createSubMesh( name ); newsub->useSharedVertices = sub->useSharedVertices; // add index newsub->indexData = sub->indexData->clone(); // add geometry if( !newsub->useSharedVertices ) { newsub->vertexData = sub->vertexData->clone(); // build bone assignments SubMesh::BoneAssignmentIterator bit = sub->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); newsub->addBoneAssignment(vba); } } newsub->setMaterialName( sub->getMaterialName() ); log("Baking: adding submesh '" + name + "' with material " + sub->getMaterialName()); } // sharedvertices if ((*it)->sharedVertexData) { /// @todo merge with existing sharedVertexData if (!mp->sharedVertexData) { mp->sharedVertexData = (*it)->sharedVertexData->clone(); } Mesh::BoneAssignmentIterator bit = (*it)->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); mp->addBoneAssignment(vba); } } log("Baking: adding bounds for " + (*it)->getName()); // add bounds totalBounds.merge((*it)->getBounds()); } mp->_setBounds( totalBounds ); /// @todo merge submeshes with same material /// @todo add parameters mp->buildEdgeList(); log( "Baking: Finished" ); return mp; }
Ogre::MeshPtr LodOutsideMarker::createConvexHullMesh(const String& meshName, const String& resourceGroupName) { // Based on the wiki sample: http://www.ogre3d.org/tikiwiki/tiki-index.php?page=Generating+A+Mesh // Resource with given name should not exist! assert(MeshManager::getSingleton().getByName(meshName).isNull()); generateHull(); // calculate mHull triangles. // Convex hull can't be empty! assert(!mHull.empty()); MeshPtr mesh = MeshManager::getSingleton().createManual(meshName, resourceGroupName, NULL); SubMesh* subMesh = mesh->createSubMesh(); vector<Real>::type vertexBuffer; vector<unsigned short>::type indexBuffer; // 3 position/triangle * 3 Real/position vertexBuffer.reserve(mHull.size() * 9); // 3 index / triangle indexBuffer.reserve(mHull.size() * 3); int id=0; // min & max position Vector3 minBounds(std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max()); Vector3 maxBounds(std::numeric_limits<Real>::min(), std::numeric_limits<Real>::min(), std::numeric_limits<Real>::min()); for (size_t i = 0; i < mHull.size(); i++) { assert(!mHull[i].removed); for(size_t n = 0; n < 3; n++){ indexBuffer.push_back(id++); vertexBuffer.push_back(mHull[i].vertex[n]->position.x); vertexBuffer.push_back(mHull[i].vertex[n]->position.y); vertexBuffer.push_back(mHull[i].vertex[n]->position.z); minBounds.x = std::min<Real>(minBounds.x, mHull[i].vertex[n]->position.x); minBounds.y = std::min<Real>(minBounds.y, mHull[i].vertex[n]->position.y); minBounds.z = std::min<Real>(minBounds.z, mHull[i].vertex[n]->position.z); maxBounds.x = std::max<Real>(maxBounds.x, mHull[i].vertex[n]->position.x); maxBounds.y = std::max<Real>(maxBounds.y, mHull[i].vertex[n]->position.y); maxBounds.z = std::max<Real>(maxBounds.z, mHull[i].vertex[n]->position.z); } } /// Create vertex data structure for 8 vertices shared between submeshes mesh->sharedVertexData = new VertexData(); mesh->sharedVertexData->vertexCount = mHull.size() * 3; /// Create declaration (memory format) of vertex data VertexDeclaration* decl = mesh->sharedVertexData->vertexDeclaration; size_t offset = 0; // 1st buffer decl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); /// Allocate vertex buffer of the requested number of vertices (vertexCount) /// and bytes per vertex (offset) HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( offset, mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the vertex data to the card vbuf->writeData(0, vbuf->getSizeInBytes(), &vertexBuffer[0], true); /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer VertexBufferBinding* bind = mesh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, vbuf); /// Allocate index buffer of the requested number of vertices (ibufCount) HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, indexBuffer.size(), HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card ibuf->writeData(0, ibuf->getSizeInBytes(), &indexBuffer[0], true); /// Set parameters of the submesh subMesh->useSharedVertices = true; subMesh->indexData->indexBuffer = ibuf; subMesh->indexData->indexCount = indexBuffer.size(); subMesh->indexData->indexStart = 0; /// Set bounding information (for culling) mesh->_setBounds(AxisAlignedBox(minBounds, maxBounds)); mesh->_setBoundingSphereRadius(maxBounds.distance(minBounds) / 2.0f); /// Set material to transparent blue subMesh->setMaterialName("Examples/TransparentBlue50"); /// Notify -Mesh object that it has been loaded mesh->load(); return mesh; }
static MeshPtr importObject(QDataStream &stream) { using namespace Ogre; QVector4D bbMin, bbMax; stream >> bbMin >> bbMax; float distance, distanceSquared; // Here's a bug for you: writes "double"'s instead of floats stream >> distanceSquared >> distance; MeshPtr ogreMesh = MeshManager::getSingleton().createManual("conversion", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); int vertexCount, indexCount; stream >> vertexCount >> indexCount; VertexData *vertexData = new VertexData(); ogreMesh->sharedVertexData = vertexData; LogManager::getSingleton().logMessage("Reading geometry..."); VertexDeclaration* decl = vertexData->vertexDeclaration; VertexBufferBinding* bind = vertexData->vertexBufferBinding; unsigned short bufferId = 0; // Information for calculating bounds Vector3 min = Vector3::ZERO, max = Vector3::UNIT_SCALE, pos = Vector3::ZERO; Real maxSquaredRadius = -1; bool firstVertex = true; /* Create a vertex definition for our buffer */ size_t offset = 0; const VertexElement &positionElement = decl->addElement(bufferId, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); const VertexElement &normalElement = decl->addElement(bufferId, offset, VET_FLOAT3, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT3); // calculate how many vertexes there actually are vertexData->vertexCount = vertexCount; // Now create the vertex buffer HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer(offset, vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); // Bind it bind->setBinding(bufferId, vbuf); // Lock it unsigned char *pVert = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); unsigned char *pVertStart = pVert; QVector<float> positions; positions.reserve(vertexCount * 3); // Iterate over all children (vertexbuffer entries) for (int i = 0; i < vertexCount; ++i) { float *pFloat; QVector4D vertex; stream >> vertex; vertex.setZ(vertex.z() * -1); /* Copy over the position */ positionElement.baseVertexPointerToElement(pVert, &pFloat); *(pFloat++) = (float)vertex.x(); *(pFloat++) = (float)vertex.y(); *(pFloat++) = (float)vertex.z(); positions.append(vertex.x()); positions.append(vertex.y()); positions.append(vertex.z()); /* While we're at it, calculate the bounding sphere */ pos.x = vertex.x(); pos.y = vertex.y(); pos.z = vertex.z(); if (firstVertex) { min = max = pos; maxSquaredRadius = pos.squaredLength(); firstVertex = false; } else { min.makeFloor(pos); max.makeCeil(pos); maxSquaredRadius = qMax(pos.squaredLength(), maxSquaredRadius); } pVert += vbuf->getVertexSize(); } // Set bounds const AxisAlignedBox& currBox = ogreMesh->getBounds(); Real currRadius = ogreMesh->getBoundingSphereRadius(); if (currBox.isNull()) { //do not pad the bounding box ogreMesh->_setBounds(AxisAlignedBox(min, max), false); ogreMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius)); } else { AxisAlignedBox newBox(min, max); newBox.merge(currBox); //do not pad the bounding box ogreMesh->_setBounds(newBox, false); ogreMesh->_setBoundingSphereRadius(qMax(Math::Sqrt(maxSquaredRadius), currRadius)); } /* Create faces */ // All children should be submeshes SubMesh* sm = ogreMesh->createSubMesh(); sm->setMaterialName("clippingMaterial"); sm->operationType = RenderOperation::OT_TRIANGLE_LIST; sm->useSharedVertices = true; // tri list sm->indexData->indexCount = indexCount; // Allocate space HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, sm->indexData->indexCount, HardwareBuffer::HBU_DYNAMIC, false); sm->indexData->indexBuffer = ibuf; unsigned short *pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_DISCARD)); QVector<EdgeData::Triangle> triangles(indexCount / 3); for (int i = 0; i < indexCount / 3; ++i) { quint16 i1, i2, i3; stream >> i1 >> i2 >> i3; *pShort++ = i1; *pShort++ = i2; *pShort++ = i3; triangles[i].vertIndex[0] = i1; triangles[i].vertIndex[1] = i2; triangles[i].vertIndex[2] = i3; } /* Recalculate the vertex normals */ Vector4 *faceNormals = (Vector4*)_aligned_malloc(sizeof(Vector4) * triangles.size(), 16); OptimisedUtil *util = OptimisedUtil::getImplementation(); util->calculateFaceNormals(positions.constData(), triangles.data(), faceNormals, indexCount / 3); // Iterate over all children (vertexbuffer entries) pVert = pVertStart; for (int i = 0; i < vertexCount; ++i) { float *pFloat; Vector3 normal = Vector3::ZERO; int count = 0; /* Search for all faces that use this vertex */ for (int j = 0; j < triangles.size(); ++j) { if (triangles[j].vertIndex[0] == i || triangles[j].vertIndex[1] == i || triangles[j].vertIndex[2] == i) { normal.x += faceNormals[j].x / faceNormals[j].w; normal.y += faceNormals[j].y / faceNormals[j].w; normal.z += faceNormals[j].z / faceNormals[j].w; count++; } } normal.normalise(); /* Copy over the position */ normalElement.baseVertexPointerToElement(pVert, &pFloat); *(pFloat++) = normal.x; *(pFloat++) = normal.y; *(pFloat++) = normal.z; pVert += vbuf->getVertexSize(); } _aligned_free(faceNormals); vbuf->unlock(); ibuf->unlock(); return ogreMesh; }
void TunnelSlice::connect(TunnelSlice* next) { float wallLength1 = getWallLength(); float wallLength2 = next->getWallLength(); int tempID = intermediateMeshID; entireIntermediate = parentNode->createChildSceneNode("intermediateSegmentNode" + Util::toStringInt(intermediateMeshID)); std::string meshName = "intermediateMesh" + Util::toStringInt(intermediateMeshID); ManualObject* manual = parentNode->getCreator()->createManualObject(meshName); Quaternion q1 = getQuaternion(); Quaternion q2 = next->getQuaternion(); Vector3 start = center + getForward() * (depth / 2); Vector3 end = next->center - next->getForward() * (next->depth / 2); Vector3 move; Vector3 p1; Vector3 p2; Vector3 p3; Vector3 p4; Vector3 bl = Vector3(Ogre::Math::POS_INFINITY, Ogre::Math::POS_INFINITY, Ogre::Math::POS_INFINITY); Vector3 tr = Vector3(Ogre::Math::NEG_INFINITY, Ogre::Math::NEG_INFINITY, Ogre::Math::NEG_INFINITY); move = Vector3(-wallLength1 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), wallLength1 / 2, 0); move = q1 * move; p1 = start + move; move = Vector3(-wallLength2 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), wallLength2 / 2, 0); move = q2 * move; p2 = end + move; move = Vector3(-wallLength2 / 2, wallLength2 * (0.5 + Math::Sin(Ogre::Radian(Math::PI) / 4)), 0); move = q2 * move; p3 = end + move; move = Vector3(-wallLength1 / 2, wallLength1 * (0.5 + Math::Sin(Ogre::Radian(Math::PI) / 4)), 0); move = q1 * move; p4 = start + move; if (sidesUsed[NORTHWEST]) setIntermediateWall(entireIntermediate, NORTHWEST, manual, p1, p2, p3, p4, bl, tr); p1 = p4; p2 = p3; move = Vector3(wallLength2 / 2, wallLength2 * (0.5 + Math::Sin(Ogre::Radian(Math::PI) / 4)), 0); move = q2 * move; p3 = end + move; move = Vector3(wallLength1 / 2, wallLength1 * (0.5 + Math::Sin(Ogre::Radian(Math::PI) / 4)), 0); move = q1 * move; p4 = start + move; if (sidesUsed[NORTH]) setIntermediateWall(entireIntermediate, NORTH, manual, p1, p2, p3, p4, bl, tr); p1 = p4; p2 = p3; move = Vector3(wallLength2 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), wallLength2 / 2, 0); move = q2 * move; p3 = end + move; move = Vector3(wallLength1 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), wallLength1 / 2, 0); move = q1 * move; p4 = start + move; if (sidesUsed[NORTHEAST]) setIntermediateWall(entireIntermediate, NORTHEAST, manual, p1, p2, p3, p4, bl, tr); p1 = p4; p2 = p3; move = Vector3(wallLength2 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), -wallLength2 / 2, 0); move = q2 * move; p3 = end + move; move = Vector3(wallLength1 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), -wallLength1 / 2, 0); move = q1 * move; p4 = start + move; if (sidesUsed[EAST]) setIntermediateWall(entireIntermediate, EAST, manual, p1, p2, p3, p4, bl, tr); p1 = p4; p2 = p3; move = Vector3(wallLength2 / 2, -wallLength2 * (0.5 + Math::Sin(Ogre::Radian(Math::PI) / 4)), 0); move = q2 * move; p3 = end + move; move = Vector3(wallLength1 / 2, -wallLength1 * (0.5 + Math::Sin(Ogre::Radian(Math::PI) / 4)), 0); move = q1 * move; p4 = start + move; if (sidesUsed[SOUTHEAST]) setIntermediateWall(entireIntermediate, SOUTHEAST, manual, p1, p2, p3, p4, bl, tr); p1 = p4; p2 = p3; move = Vector3(-wallLength2 / 2, -wallLength2 * (0.5 + Math::Sin(Ogre::Radian(Math::PI) / 4)), 0); move = q2 * move; p3 = end + move; move = Vector3(-wallLength1 / 2, -wallLength1 * (0.5 + Math::Sin(Ogre::Radian(Math::PI) / 4)), 0); move = q1 * move; p4 = start + move; if (sidesUsed[SOUTH]) setIntermediateWall(entireIntermediate, SOUTH, manual, p1, p2, p3, p4, bl, tr); p1 = p4; p2 = p3; move = Vector3(-wallLength2 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), -wallLength2 / 2, 0); move = q2 * move; p3 = end + move; move = Vector3(-wallLength1 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), -wallLength1 / 2, 0); move = q1 * move; p4 = start + move; if (sidesUsed[SOUTHWEST]) setIntermediateWall(entireIntermediate, SOUTHWEST, manual, p1, p2, p3, p4, bl, tr); p1 = p4; p2 = p3; move = Vector3(-wallLength1 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), wallLength1 / 2, 0); move = q2 * move; p3 = end + move; move = Vector3(-wallLength2 * (0.5 + Math::Cos(Ogre::Radian(Math::PI) / 4)), wallLength2 / 2, 0); move = q1 * move; p4 = start + move; if (sidesUsed[WEST]) setIntermediateWall(entireIntermediate, WEST, manual, p1, p2, p3, p4, bl, tr); MeshPtr mesh = manual->convertToMesh(meshName); mesh->_setBounds( AxisAlignedBox( bl, tr ), true ); float l = (tr - bl).length() / 2; mesh->_setBoundingSphereRadius(l); unsigned short src, dest; if (!mesh->suggestTangentVectorBuildParams(VES_TANGENT, src, dest)) { mesh->buildTangentVectors(VES_TANGENT, src, dest); } Entity* intermediateSegmentEntity = entireIntermediate->getCreator()->createEntity("intermediateSegmentEntity" + Util::toStringInt(intermediateMeshID), meshName); //intermediateSegmentEntity->setMaterialName(getMaterialName()); for (int i = 0; i < intermediateSegmentEntity->getNumSubEntities(); ++i) intermediateSegmentEntity->getSubEntity(i)->setMaterialName(getMaterialName()); entireIntermediate->attachObject(intermediateSegmentEntity); meshes.push_back(mesh); intermediateMeshID++; parentNode->getCreator()->destroyManualObject(manual); }
// 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(); }
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(); }