void IndexBuffer::AddFromIndexData(Ogre::IndexData* indexData, const unsigned int offset) { // Get vertex count const unsigned int addedCount = indexData->indexCount; if(_reserved < _size + addedCount) { Reserve(_size + addedCount); } Ogre::HardwareIndexBufferSharedPtr hardwareBuffer = indexData->indexBuffer; const bool use32bitindexes = (hardwareBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); if (use32bitindexes) { const unsigned int* curIndex = static_cast<unsigned int*> (hardwareBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); for(unsigned int k = 0; k < addedCount; ++k) { _buffer.push_back(offset + (*curIndex++)); } } else { const unsigned short* curIndex = static_cast<unsigned short*> (hardwareBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); for(unsigned int k = 0; k < addedCount; ++k) { _buffer.push_back(offset + static_cast<unsigned int>(*curIndex++)); } } _size = _buffer.size(); hardwareBuffer->unlock(); }
void processIndexData(IndexData* indexData) { if (!mFlipVertexWinding) { // Nothing to do. return; } if (indexData->indexCount % 3 != 0) { printf("Index number is not a multiple of 3, no vertex winding flipping possible. Skipped."); return; } //print("Flipping index order for vertex winding flipping.", V_HIGH); Ogre::HardwareIndexBufferSharedPtr buffer = indexData->indexBuffer; unsigned char* data = static_cast<unsigned char*>(buffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); if(buffer->getType() == Ogre::HardwareIndexBuffer::IT_16BIT) { // 16 bit //print("using 16bit indices", V_HIGH); for (size_t i = 0; i < indexData->indexCount; i+=3) { Ogre::uint16 * i0 = (Ogre::uint16*)(data+0 * buffer->getIndexSize()); Ogre::uint16* i2 = (Ogre::uint16*)(data+2 * buffer->getIndexSize()); // flip Ogre::uint16 tmp = *i0; *i0 = *i2; *i2 = tmp; data += 3 * buffer->getIndexSize(); } } else { // 32 bit //print("using 32bit indices", V_HIGH); for (size_t i = 0; i < indexData->indexCount; i+=3) { Ogre::uint32* i0 = (Ogre::uint32*)(data+0 * buffer->getIndexSize()); Ogre::uint32* i2 = (Ogre::uint32*)(data+2 * buffer->getIndexSize()); // flip Ogre::uint32 tmp = *i0; *i0 = *i2; *i2 = tmp; data += 3 * buffer->getIndexSize(); } } buffer->unlock(); }
//------------------------------------------------------------------------------------------------ void VertexIndexToShape::addIndexData(Ogre::IndexData *data, const unsigned int offset) { const unsigned int prev_size = mIndexCount; mIndexCount += (unsigned int)data->indexCount; unsigned int* tmp_ind = new unsigned int[mIndexCount]; if (mIndexBuffer) { memcpy (tmp_ind, mIndexBuffer, sizeof(unsigned int) * prev_size); delete[] mIndexBuffer; } mIndexBuffer = tmp_ind; const unsigned int numTris = (unsigned int) data->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = data->indexBuffer; const bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned int index_offset = prev_size; if (use32bitindexes) { const unsigned int* pInt = static_cast<unsigned int*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); for(unsigned int k = 0; k < numTris; ++k) { mIndexBuffer[index_offset ++] = offset + *pInt++; mIndexBuffer[index_offset ++] = offset + *pInt++; mIndexBuffer[index_offset ++] = offset + *pInt++; } ibuf->unlock(); } else { const unsigned short* pShort = static_cast<unsigned short*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); for(unsigned int k = 0; k < numTris; ++k) { mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int> (*pShort++); mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int> (*pShort++); mIndexBuffer[index_offset ++] = offset + static_cast<unsigned int> (*pShort++); } ibuf->unlock(); } }
mesh::mesh(const std::string &mn, const mat4 &tf, const world &_world): /** Don't know if world() is the best thing to pass but it works for now **/ _mesh(NewtonMeshCreate(_world)) { Ogre::MeshPtr meshPtr; try { meshPtr = Ogre::MeshPtr(Ogre::MeshManager::getSingleton().load(mn, Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME)); } catch(...) { return; } const Ogre::Mesh &mesh = *meshPtr; NewtonMeshBeginFace(_mesh); for (unsigned smi = 0; smi < mesh.getNumSubMeshes(); smi++) { Ogre::SubMesh *subMesh = mesh.getSubMesh(smi); Ogre::VertexData *vertexData = (subMesh->useSharedVertices) ? vertexData = mesh.sharedVertexData : vertexData = subMesh->vertexData; Ogre::VertexDeclaration *vertexDecl = vertexData->vertexDeclaration; const Ogre::VertexElement *element = vertexDecl->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vertexHVBSP = vertexData->vertexBufferBinding->getBuffer(element->getSource()); unsigned char *vPtr = (unsigned char*)(vertexHVBSP->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); Ogre::IndexData *indexData = subMesh->indexData; size_t numIndices = indexData->indexCount; size_t numTris = numIndices / 3; // get pointer! Ogre::HardwareIndexBufferSharedPtr indexHIBSP = indexData->indexBuffer; // 16 or 32 bit indices? bool indicesAre32Bit = (indexHIBSP->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned long *longPtr = NULL; unsigned short *shortPtr = NULL; if (indicesAre32Bit) longPtr = static_cast<unsigned long*>( indexHIBSP->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); else shortPtr = static_cast<unsigned short*>( indexHIBSP->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); //now loop through the indices, getting polygon info! int iOffset = 0; for (size_t i = 0; i < numTris; i++) { vec3 triVertices[3]; unsigned char *vOffset = NULL; float *vertexPosPtr = NULL; int idx = 0; for (int j = 0; j < 3; j++) { if (indicesAre32Bit) idx = longPtr[iOffset + j]; else idx = shortPtr[iOffset + j]; vOffset = vPtr + (idx * vertexHVBSP->getVertexSize()); element->baseVertexPointerToElement(vOffset, &vertexPosPtr); triVertices[j].x = *vertexPosPtr; vertexPosPtr++; triVertices[j].y = *vertexPosPtr; vertexPosPtr++; triVertices[j].z = *vertexPosPtr; vertexPosPtr++; triVertices[j] = tf * triVertices[j]; } // _mesh, 3 vertices (triangle), (float = 4 bytes) * 3 // index = index of sub mesh (easy to recognize) NewtonMeshAddFace(_mesh, 3, &triVertices[0].x, sizeof(float) * 3, smi); iOffset += 3; } //unlock the buffers! vertexHVBSP->unlock(); indexHIBSP->unlock(); } NewtonMeshEndFace(_mesh); }
Rocket::Core::CompiledGeometryHandle RocketInterface::CompileGeometry( Rocket::Core::Vertex* vertices, int numVertices, int* indices, int numIndices, Rocket::Core::TextureHandle texture) { RocketOgreGeometry* geometry = new RocketOgreGeometry(); geometry->texture = texture == 0 ? nullptr : reinterpret_cast<RocketOgreTexture*>(texture); geometry->renderOp.vertexData = new Ogre::VertexData(); geometry->renderOp.vertexData->vertexStart = 0; geometry->renderOp.vertexData->vertexCount = numVertices; geometry->renderOp.indexData = new Ogre::IndexData(); geometry->renderOp.indexData->indexStart = 0; geometry->renderOp.indexData->indexCount = numIndices; geometry->renderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; // Set up the vertex declaration Ogre::VertexDeclaration* vertexDecl = geometry->renderOp.vertexData->vertexDeclaration; size_t offset = 0; vertexDecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); vertexDecl->addElement(0, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR); vertexDecl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); // Create the vertex buffer Ogre::HardwareVertexBufferSharedPtr vb = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( vertexDecl->getVertexSize(0), numVertices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); geometry->renderOp.vertexData->vertexBufferBinding->setBinding(0, vb); // Fill the vertex buffer RocketOgreVertex* vertexData = static_cast<RocketOgreVertex*>( vb->lock(0, vb->getSizeInBytes(), Ogre::HardwareBuffer::HBL_NORMAL)); for (int i = 0; i < numVertices; ++i) { vertexData[i].position.x = vertices[i].position.x; vertexData[i].position.y = vertices[i].position.y; vertexData[i].uv.x = vertices[i].tex_coord[0]; vertexData[i].uv.y = vertices[i].tex_coord[1]; // Calculate colour value Ogre::ColourValue diffuse( vertices[i].colour.red / 255.0f, vertices[i].colour.green / 255.0f, vertices[i].colour.blue / 255.0f, vertices[i].colour.alpha / 255.0f); // Scale colour by gamma value (2.2) diffuse.r = Pow(diffuse.r, 2.2f); diffuse.g = Pow(diffuse.g, 2.2f); diffuse.b = Pow(diffuse.b, 2.2f); diffuse.a = Pow(diffuse.a, 2.2f); mRenderSystem->convertColourValue(diffuse, &vertexData[i].colour); } vb->unlock(); // Create the index buffer Ogre::HardwareIndexBufferSharedPtr ib = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_32BIT, numIndices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); geometry->renderOp.indexData->indexBuffer = ib; geometry->renderOp.useIndexes = true; // Fill the index buffer void* indexData = ib->lock(0, ib->getSizeInBytes(), Ogre::HardwareBuffer::HBL_NORMAL); memcpy(indexData, indices, sizeof(unsigned int) * numIndices); ib->unlock(); return reinterpret_cast<Rocket::Core::CompiledGeometryHandle>(geometry); }
void TerrainTileEditable::createGeometry(TerrainData* data, int xbase, int zbase, int xsize, int zsize) { destoryGeometry(); // build the material backet map MaterialBucketMap materialBucketMap; buildMaterialBucketMap(materialBucketMap); // Build renderables for (MaterialBucketMap::const_iterator im = materialBucketMap.begin(); im != materialBucketMap.end(); ++im) { const MaterialBucket* mb = &im->second; TerrainTileEditableRenderable* renderable = new TerrainTileEditableRenderable(this, mb->layerIndex); mRenderables.push_back(renderable); size_t numQuads = mb->grids.size(); size_t indexCount = numQuads * 6; renderable->mMaterial = mb->material; Ogre::HardwareIndexBufferSharedPtr indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT, indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); Ogre::IndexData* indexData = new Ogre::IndexData; indexData->indexBuffer = indexBuffer; indexData->indexStart = 0; indexData->indexCount = indexCount; renderable->mRenderOp.indexData = indexData; renderable->mRenderOp.vertexData = mVertexDatas[mb->layerIndex]; renderable->mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; renderable->mRenderOp.useIndexes = true; ushort* pIndices = static_cast<ushort*>(indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); for (GridIdList::const_iterator igrid = mb->grids.begin(); igrid != mb->grids.end(); ++igrid) { size_t grid = *igrid; const TerrainData::GridInfo& gridInfo = data->mGridInfos[grid]; const TerrainData::Corner* corners = gridInfo.getCorners(); int x = grid % data->mXSize - xbase; int z = grid / data->mXSize - zbase; assert(x < xsize && z < zsize); size_t index = (z*xsize + x) * 4; *pIndices++ = index + corners[1]; *pIndices++ = index + corners[0]; *pIndices++ = index + corners[2]; *pIndices++ = index + corners[1]; *pIndices++ = index + corners[2]; *pIndices++ = index + corners[3]; } indexBuffer->unlock(); } for (size_t layerIndex = 0; layerIndex < 2; ++layerIndex) { fillLayerBuffer(layerIndex, mVertexDatas.back()->vertexBufferBinding->getBuffer(layerIndex+1)); } mGeometryOutOfDate = false; }
void Utils::GetMeshInformation( const Ogre::MeshPtr mesh, size_t &vertexCount, Ogre::Vector3* &vertices, size_t &indexCount, unsigned* &indices) { bool addShared = false; size_t currentOffset = 0; size_t shared_offset = 0; size_t nextOffset = 0; size_t indexOffset = 0; vertexCount = indexCount = 0; for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh(i); if(submesh->useSharedVertices) { if( !addShared ) { vertexCount += mesh->sharedVertexData->vertexCount; addShared = true; } } else { vertexCount += submesh->vertexData->vertexCount; } indexCount += submesh->indexData->indexCount; } vertices = new Ogre::Vector3[vertexCount]; indices = new unsigned[indexCount]; addShared = false; for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh(i); Ogre::VertexData* vertexData = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !addShared)) { if(submesh->useSharedVertices) { addShared = true; shared_offset = currentOffset; } const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); float* pReal; for( size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]); vertices[currentOffset + j] = pt; } vbuf->unlock(); nextOffset += vertexData->vertexCount; } Ogre::IndexData* indexData = submesh->indexData; size_t numTris = indexData->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); size_t offset = (submesh->useSharedVertices)? shared_offset : currentOffset; if ( use32bitindexes ) { for ( size_t k = 0; k < numTris*3; ++k) { indices[indexOffset++] = pLong[k] + static_cast<unsigned long>(offset); } } else { for ( size_t k = 0; k < numTris*3; ++k) { indices[indexOffset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset); } } ibuf->unlock(); currentOffset = nextOffset; } }
// Get the mesh information for the given mesh. // Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData void CollisionTools::GetMeshInformation(const Ogre::MeshPtr mesh, size_t &vertex_count, Ogre::Vector3* &vertices, size_t &index_count, Ogre::uint32* &indices, const Ogre::Vector3 &position, const Ogre::Quaternion &orient, const Ogre::Vector3 &scale) { bool added_shared = false; size_t current_offset = 0; size_t shared_offset = 0; size_t next_offset = 0; size_t index_offset = 0; vertex_count = index_count = 0; // Calculate how many vertices and indices we're going to need for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh( i ); // We only need to add the shared vertices once if(submesh->useSharedVertices) { if( !added_shared ) { vertex_count += mesh->sharedVertexData->vertexCount; added_shared = true; } } else { vertex_count += submesh->vertexData->vertexCount; } // Add the indices index_count += submesh->indexData->indexCount; } // Allocate space for the vertices and indices vertices = new Ogre::Vector3[vertex_count]; indices = new Ogre::uint32[index_count]; added_shared = false; // Run through the submeshes again, adding the data into the arrays for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh(i); Ogre::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 Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); // There is _no_ baseVertexPointerToElement() which takes an Ogre::Ogre::Real or a double // as second argument. So make it float, to avoid trouble when Ogre::Ogre::Real will // be comiled/typedefed as double: // Ogre::Ogre::Real* pOgre::Real; float* pReal; for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]); vertices[current_offset + j] = (orient * (pt * scale)) + position; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } Ogre::IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); Ogre::uint32* pLong = static_cast<Ogre::uint32*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset; if ( use32bitindexes ) { for ( size_t k = 0; k < numTris*3; ++k) { indices[index_offset++] = pLong[k] + static_cast<Ogre::uint32>(offset); } } else { for ( size_t k = 0; k < numTris*3; ++k) { indices[index_offset++] = static_cast<Ogre::uint32>(pShort[k]) + static_cast<Ogre::uint32>(offset); } } ibuf->unlock(); current_offset = next_offset; } }
void GPUBillboardSet::createVertexDataForVertexShaderOnly(const std::vector<PhotoSynth::Vertex>& vertices) { // Setup render operation mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; mRenderOp.vertexData = OGRE_NEW Ogre::VertexData(); mRenderOp.vertexData->vertexCount = vertices.size() * 4; mRenderOp.vertexData->vertexStart = 0; mRenderOp.useIndexes = true; mRenderOp.indexData = OGRE_NEW Ogre::IndexData(); mRenderOp.indexData->indexCount = vertices.size() * 6; mRenderOp.indexData->indexStart = 0; // Vertex format declaration unsigned short sourceBufferIdx = 0; Ogre::VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; size_t currOffset = 0; decl->addElement(sourceBufferIdx, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); decl->addElement(sourceBufferIdx, currOffset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR); decl->addElement(sourceBufferIdx, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0); currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); // Create vertex buffer Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(sourceBufferIdx), mRenderOp.vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Bind vertex buffer Ogre::VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; bind->setBinding(sourceBufferIdx, vbuf); // Fill vertex buffer (see http://www.ogre3d.org/docs/manual/manual_59.html#SEC287) Ogre::RenderSystem* renderSystem = Ogre::Root::getSingletonPtr()->getRenderSystem(); unsigned char* pVert = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); Ogre::Real* pReal; Ogre::RGBA* pRGBA; Ogre::VertexDeclaration::VertexElementList elems = decl->findElementsBySource(sourceBufferIdx); Ogre::VertexDeclaration::VertexElementList::iterator itr; const Ogre::Vector2 uvs[4] = { Ogre::Vector2( -1.f, 1.f ), Ogre::Vector2( -1.f, -1.f ), Ogre::Vector2( 1.f, -1.f ), Ogre::Vector2( 1.f, 1.f ) }; for (unsigned int i=0; i<vertices.size(); ++i ) { const PhotoSynth::Vertex& vertex = vertices[i]; for ( unsigned int j=0; j<4; j++ ) { for (itr=elems.begin(); itr!=elems.end(); ++itr) { Ogre::VertexElement& elem = *itr; if (elem.getSemantic() == Ogre::VES_POSITION) { elem.baseVertexPointerToElement(pVert, &pReal); *pReal = vertex.position.x; *pReal++; *pReal = vertex.position.y; *pReal++; *pReal = vertex.position.z; *pReal++; } else if (elem.getSemantic() == Ogre::VES_DIFFUSE) { elem.baseVertexPointerToElement(pVert, &pRGBA); renderSystem->convertColourValue(vertex.color, pRGBA); } else if (elem.getSemantic() == Ogre::VES_TEXTURE_COORDINATES && elem.getIndex() == 0) { elem.baseVertexPointerToElement(pVert, &pReal); *pReal = uvs[j].x; *pReal++; *pReal = uvs[j].y; *pReal++; } } // Go to next vertex pVert += vbuf->getVertexSize(); } } vbuf->unlock(); // Create index buffer if (mRenderOp.indexData->indexCount>=65536) { Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_32BIT, mRenderOp.indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); mRenderOp.indexData->indexBuffer = ibuf; Ogre::uint32* indices = static_cast<Ogre::uint32*>(ibuf->lock( Ogre::HardwareBuffer::HBL_DISCARD)); Ogre::uint32 indexFirstVertex = 0; const Ogre::uint32 inds[6] = { 0, 1, 2, 3, 0, 2 }; for (unsigned int i=0; i<vertices.size(); ++i) { for (unsigned int j=0; j<6; ++j) { *indices = indexFirstVertex + inds[j]; indices++; } indexFirstVertex +=4; } ibuf->unlock(); } else { Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT, mRenderOp.indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); mRenderOp.indexData->indexBuffer = ibuf; Ogre::uint16* indices = static_cast<Ogre::uint16*>( ibuf->lock( Ogre::HardwareBuffer::HBL_DISCARD ) ); Ogre::uint32 indexFirstVertex = 0; const Ogre::uint16 inds[6] = { 0, 1, 2, 3, 0, 2 }; for ( unsigned int i=0; i<vertices.size(); ++i ) { for ( unsigned int j=0; j<6; ++j ) { *indices = indexFirstVertex + inds[j]; indices++; } indexFirstVertex +=4; } ibuf->unlock(); } // Set material this->setMaterial("GPUBillboard"); }
void PhysicsManager::getMeshInformation(Ogre::MeshPtr mesh,size_t &vertex_count,Vector3* &vertices, size_t &index_count, unsigned* &indices, const Ogre::Vector3 &position, const Ogre::Quaternion &orient,const Ogre::Vector3 &scale) { vertex_count = index_count = 0; bool added_shared = false; size_t current_offset = vertex_count; size_t shared_offset = vertex_count; size_t next_offset = vertex_count; size_t index_offset = index_count; size_t prev_vert = vertex_count; size_t prev_ind = index_count; // Calculate how many vertices and indices we're going to need for(int i = 0;i < mesh->getNumSubMeshes();i++) { SubMesh* submesh = mesh->getSubMesh(i); // We only need to add the shared vertices once if(submesh->useSharedVertices) { if(!added_shared) { VertexData* vertex_data = mesh->sharedVertexData; vertex_count += vertex_data->vertexCount; added_shared = true; } } else { VertexData* vertex_data = submesh->vertexData; vertex_count += vertex_data->vertexCount; } // Add the indices Ogre::IndexData* index_data = submesh->indexData; index_count += index_data->indexCount; } // Allocate space for the vertices and indices vertices = new Vector3[vertex_count]; indices = new unsigned[index_count]; added_shared = false; // Run through the submeshes again, adding the data into the arrays for(int i = 0;i < mesh->getNumSubMeshes();i++) { SubMesh* submesh = mesh->getSubMesh(i); Ogre::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 Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); Ogre::Real* pReal; for(size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Vector3 pt; pt.x = (*pReal++); pt.y = (*pReal++); pt.z = (*pReal++); pt = (orient * (pt * scale)) + position; vertices[current_offset + j].x = pt.x; vertices[current_offset + j].y = pt.y; vertices[current_offset + j].z = pt.z; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } Ogre::IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; unsigned short* pShort; unsigned int* pInt; Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); if (use32bitindexes) pInt = static_cast<unsigned int*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); else pShort = static_cast<unsigned short*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); for(size_t k = 0; k < numTris; ++k) { size_t offset = (submesh->useSharedVertices)?shared_offset:current_offset; unsigned int vindex = use32bitindexes? *pInt++ : *pShort++; indices[index_offset + 0] = vindex + offset; vindex = use32bitindexes? *pInt++ : *pShort++; indices[index_offset + 1] = vindex + offset; vindex = use32bitindexes? *pInt++ : *pShort++; indices[index_offset + 2] = vindex + offset; index_offset += 3; } ibuf->unlock(); current_offset = next_offset; } }
/*求对象rend和射线ray的全部交点到射线原点的距离 */ vector<Ogre::Real> BaseManager::Intersect(const Ogre::Ray& ray,Ogre::Renderable *rend){ Ogre::RenderOperation op; Ogre::VertexElementType vtype; size_t offset,pkgsize,source,indexNums,vertexNums; vector<Ogre::Real> result; rend->getRenderOperation( op ); if( !op.indexData || op.operationType==Ogre::RenderOperation::OT_LINE_LIST || op.operationType==Ogre::RenderOperation::OT_LINE_STRIP || op.operationType==Ogre::RenderOperation::OT_POINT_LIST ) return result; Ogre::VertexDeclaration* pvd = op.vertexData->vertexDeclaration; source = -1; for( size_t i = 0;i < pvd->getElementCount();++i ){ if( pvd->getElement(i)->getSemantic()==Ogre::VES_POSITION ){ source = pvd->getElement(i)->getSource(); offset = pvd->getElement(i)->getOffset(); vtype = pvd->getElement(i)->getType(); break; } } if( source == - 1 || vtype != Ogre::VET_FLOAT3 ) //别的格式目前没有考虑 return result; /*source对应与一个缓存区 getVertexSize(source)求缓存区中一个紧密数据包的大小 例如:一个数据包里面包括POSITION,COLOR,NORMAL,TEXCROOD然后在这个缓冲 区中循环。而getVertexSize求出这个包的字节大小 例如POSITION(FLOAT3) TEXCROOD(FLOAT2) 这样前面的是12字节后面的是8字节 getVertexSize返回20 */ pkgsize = pvd->getVertexSize(source); Ogre::HardwareVertexBufferSharedPtr hvb = op.vertexData->vertexBufferBinding->getBuffer(source); Ogre::HardwareIndexBufferSharedPtr ivb = op.indexData->indexBuffer; Ogre::HardwareIndexBuffer::IndexType indexType = op.indexData->indexBuffer->getType(); /*先将顶点数据复制一份,然后变换到世界坐标系 */ vertexNums = hvb->getNumVertices(); indexNums = ivb->getNumIndexes(); boost::scoped_array<float> vp( new float[3*vertexNums] ); boost::scoped_array<unsigned int> ip( new unsigned int[indexNums] ); { Ogre::Vector3 p3; Ogre::Matrix4 mat; rend->getWorldTransforms( &mat ); float* preal = (float*)hvb->lock( Ogre::HardwareBuffer::HBL_READ_ONLY ); float* ptarget = vp.get(); //这里考虑到对齐,我假设offset和pkgsize都可以被sizeof(float)整除 preal += offset/sizeof(float); size_t strip = pkgsize/sizeof(float); for( size_t i = 0; i < vertexNums;++i ){ p3.x = *preal; p3.y = *(preal+1); p3.z = *(preal+2); p3 = mat * p3; *ptarget++ = p3.x; *ptarget++ = p3.y; *ptarget++ = p3.z; preal += strip; } hvb->unlock(); } //拷贝出顶点数据 { unsigned int* pindex32 = ip.get(); if( indexType==Ogre::HardwareIndexBuffer::IT_16BIT ){ unsigned short* pi16 = (unsigned short*)ivb->lock( Ogre::HardwareBuffer::HBL_READ_ONLY ); copy( pi16,pi16+indexNums,pindex32 ); }else memcpy( pindex32,ivb->lock( Ogre::HardwareBuffer::HBL_READ_ONLY ),ivb->getSizeInBytes() ); ivb->unlock(); } /*数据都准备好了,vp保存了变换好的顶点,ip保存了顶点索引 下面根据情况求交点 */ switch( op.operationType ){ case Ogre::RenderOperation::OT_TRIANGLE_LIST: { /* 0,1,2 组成一个三角 3,4,5 下一个... */ Ogre::Vector3 a[3],n; int index,k = 0; float* preal = vp.get(); unsigned int* pindex = ip.get(); for( size_t i = 0;i<indexNums;++i ){ if( pindex[i] < vertexNums ){ index = pindex[i]*3; //对应与格式VET_FLOAT3 a[k].x = preal[index]; a[k].y = preal[index+1]; a[k].z = preal[index+2]; if( k == 2 ){//三个点都填满了 //这里使用的是Math3d的求交函数,而不是Ogre::Math的 //原因就在于Ogre::Math的求交点函数不能得到射线背面那个负的交点 std::pair<bool,Ogre::Real> res = Math3d::intersects(ray,a[0],a[1],a[2],true,true); if( res.first ) result.push_back( res.second ); k = 0; }else k++; }else{ WARNING_LOG("Game::Intersect"<<" Invalid index rang out" << " pindex["<<i<<"]="<<pindex[i] << "("<<vertexNums<<")"); return result; } } } break; case Ogre::RenderOperation::OT_TRIANGLE_FAN: {/* 0,1,2组成一个三角 0,2,3 组成下一个 0,3,4... */ assert( false||"Game::Intersect can't support OT_TRIANGLE_FAN " ); } break; case Ogre::RenderOperation::OT_TRIANGLE_STRIP: {//0,1,2组成第一个三角 1,2,3 组成下一个 2,3,4... assert( false||"Game::Intersect can't support OT_TRIANGLE_STRIP " ); } break; default:; } return result; }
void MeshUtils::meshBuffersToArrays(const Ogre::MeshPtr& mesh, Ogre::Vector3* vertices, unsigned long* indices) { bool added_shared = false; size_t current_offset = 0; size_t shared_offset = 0; size_t next_offset = 0; size_t index_offset = 0; //const Ogre::Vector3 &position = ent->getParentNode()->_getDerivedPosition(); //const Ogre::Quaternion &orient = ent->getParentNode()->_getDerivedOrientation(); //const Ogre::Vector3 &scale = ent->getParentNode()->_getDerivedScale(); const Ogre::Vector3 &position = Ogre::Vector3::ZERO; const Ogre::Quaternion &orient = Ogre::Quaternion::IDENTITY; const Ogre::Vector3 &scale = Ogre::Vector3::UNIT_SCALE; Ogre::Mesh::SubMeshIterator itr = mesh->getSubMeshIterator(); while (itr.hasMoreElements()) { Ogre::SubMesh* submesh = itr.getNext(); Ogre::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 Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*> (vbuf->lock(Ogre::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 will // be comiled/typedefed as double: // Ogre::Real* pReal; float* pReal; for (size_t k = 0; k < vertex_data->vertexCount; ++k, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]); vertices[current_offset + k] = (orient * (pt * scale)) + position; //vertices[current_offset + k] = pt; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } Ogre::IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned long* pLong = static_cast<unsigned long*> (ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*> (pLong); size_t offset = (submesh->useSharedVertices) ? shared_offset : current_offset; if (use32bitindexes) { for (size_t k = 0; k < numTris * 3; ++k) { indices[index_offset++] = pLong[k] + static_cast<unsigned long> (offset); } } else { for (size_t k = 0; k < numTris * 3; ++k) { indices[index_offset++] = static_cast<unsigned long> (pShort[k]) + static_cast<unsigned long> (offset); } } ibuf->unlock(); current_offset = next_offset; } }
bool ShaderParticleRenderer::allocateBuffers(size_t iNumParticles) { // prepare vertex declaration if (mVertexData->vertexDeclaration->getElementCount() == 0) { VertexDeclaration* pDecl = mVertexData->vertexDeclaration; size_t ofs = 0; ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_POSITION).getSize(); // position if (mVertexFormatColour) ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_DIFFUSE).getSize(); // diffuse colour // other data are stored in vertex as texture coordinates ushort ix = 0; if (mVertexFormatTexture) ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // general texture coord if (mVertexFormatSize) ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // particle size if (mVertexFormatRotation || mVertexFormatRotationSpeed) { if (mVertexFormatRotation && mVertexFormatRotationSpeed) ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // current rotation and rotation speed else ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++).getSize(); // current rotation or rotation speed } if (mVertexFormatDirection) ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++).getSize(); // particle direction (as speed) // add packed times size_t iNumTimes = 0; if (mVertexFormatTTL) iNumTimes++; if (mVertexFormatTotalTTL) iNumTimes++; if (mVertexFormatTimeFragment) iNumTimes++; if (mVertexFormatTimeFragmentInv) iNumTimes++; switch(iNumTimes) { case 1: ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++).getSize(); break; case 2: ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); break; case 3: ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++).getSize(); break; case 4: ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize(); break; } // add custom parameters ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize(); assert(ix <= 8); // cache vertex size mVertexSize = pDecl->getVertexSize(0); } Ogre::HardwareVertexBufferSharedPtr pVB; if (mVertexData->vertexBufferBinding->isBufferBound(0)) pVB = mVertexData->vertexBufferBinding->getBuffer(0); // prepare vertex buffer if (pVB.isNull() || pVB->getNumVertices() < iNumParticles * 4) { assert(iNumParticles * 4 < 65536); // we are using 16bit index buffer pVB = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(mVertexSize, 4 * iNumParticles, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); if (pVB.isNull()) return false; mVertexData->vertexBufferBinding->setBinding(0, pVB); } // prepare index buffer Ogre::HardwareIndexBufferSharedPtr pIB = mIndexData->indexBuffer; if (pIB.isNull() || pIB->getNumIndexes() < iNumParticles * 6) { pIB = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, iNumParticles * 6, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); if (pIB.isNull()) return false; mIndexData->indexBuffer = pIB; // fill Ogre::uint16* pDataIB = reinterpret_cast<Ogre::uint16*>(pIB->lock(Ogre::HardwareBuffer::HBL_NORMAL)); for (Ogre::uint16 k=0; k<static_cast<Ogre::uint16>(iNumParticles); ++k) { pDataIB[0] = k*4 + 0; pDataIB[1] = k*4 + 1; pDataIB[2] = k*4 + 2; pDataIB[3] = k*4 + 0; pDataIB[4] = k*4 + 2; pDataIB[5] = k*4 + 3; pDataIB += 6; } pIB->unlock(); } return true; }
void TutorialApplication::createSphere(const std::string& strName, const float r, const int nRings, const int nSegments) { Ogre::MeshPtr pSphere = Ogre::MeshManager::getSingleton().createManual(Ogre::String(strName), Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); Ogre::SubMesh *pSphereVertex = pSphere->createSubMesh(); pSphere->sharedVertexData = new Ogre::VertexData(); Ogre::VertexData* vertexData = pSphere->sharedVertexData; // define the vertex format Ogre::VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); // normals vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); // two dimensional texture coordinates vertexDecl->addElement(0, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0); currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); // allocate the vertex buffer vertexData->vertexCount = (nRings + 1) * (nSegments+1); Ogre::HardwareVertexBufferSharedPtr vBuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); Ogre::VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); // allocate index buffer pSphereVertex->indexData->indexCount = 6 * nRings * (nSegments + 1); pSphereVertex->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, pSphereVertex->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); Ogre::HardwareIndexBufferSharedPtr iBuf = pSphereVertex->indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); float fDeltaRingAngle = (Ogre::Math::PI / nRings); float fDeltaSegAngle = (2 * Ogre::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; Ogre::Vector3 vNormal = Ogre::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( Ogre::AxisAlignedBox( Ogre::Vector3(-r, -r, -r), Ogre::Vector3(r, r, r) ), false ); pSphere->_setBoundingSphereRadius(r); // this line makes clear the mesh is loaded (avoids memory leaks) pSphere->load(); }
/* ----------------------------------------------------------------------- | the function describe retrieve vertexbuffer from Ogre entity : | (Ref:http://www.ogre3d.org/tikiwiki/tiki-index.php?page=RetrieveVertexData) | | @prama in : Ogre entity | @pamra out : vertex buffer, size of vertexbuffer, vertex indices, sizeof vertex indices ----------------------------------------------------------------------- */ void getVertexBuffer(Ogre::Entity* ent, void* &vertices, size_t& vertexCount, void* &indices, size_t& indexCount) { bool added_shared = false; size_t current_offset = 0; size_t shared_offset = 0; size_t next_offset = 0; size_t index_offset = 0; vertexCount = indexCount = 0; const Ogre::MeshPtr& mesh = ent->getMesh(); // Calculate vertexCount, indexCount for ( Ogre::ushort i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* subMesh = mesh->getSubMesh(i); if (subMesh->useSharedVertices) { if( !added_shared ) { vertexCount += mesh->sharedVertexData->vertexCount; added_shared = true; } vertexCount += mesh->sharedVertexData->vertexCount; } else vertexCount += subMesh->vertexData->vertexCount; indexCount += subMesh->indexData->indexCount; } // Alloc vertices, indices vertices = new Ogre::Vector3[ vertexCount ]; indices = new Ogre::ulong[ indexCount ]; added_shared = false; // Assign vertices data, indices data for (Ogre::ushort i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* subMesh = mesh->getSubMesh(i); Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mesh->sharedVertexData : subMesh->vertexData; if ((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !added_shared)) { if(subMesh->useSharedVertices) { added_shared = true; shared_offset = current_offset; } // Retrieve vertices const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); Ogre::uchar* vertex = static_cast<Ogre::uchar*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); Ogre::Real* data; for (size_t j = 0 ; j < vertexData->vertexCount ; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &data); Ogre::Vector3 origin(data[0], data[1], data[2]); // ((Ogre::Vector3*)vertices)[ current_offset + j ] = (orient * (origin * scale)) + position; ((Ogre::Vector3*)vertices)[ current_offset + j ] = origin; } // End for vbuf->unlock(); next_offset += vertexData->vertexCount; } // End if // Retrieve indices Ogre::IndexData* indexData = subMesh->indexData; size_t trisCount = indexData->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); void* index = (ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); Ogre::ulong offset = (subMesh->useSharedVertices) ? shared_offset : current_offset; for (Ogre::ulong k = 0; k < trisCount * 3; ++k) { if ( use32bitindexes ) ((Ogre::ulong*)indices)[ index_offset++ ] = ((Ogre::ulong*)index)[ k + offset ]; else ((Ogre::ulong*)indices)[ index_offset++ ] = ((Ogre::ushort*)index)[ k + offset ]; } ibuf->unlock(); current_offset = next_offset; } // End for }
//----------------------------------------------------------------------- void MeshInfo::getMeshInformation( Ogre::MeshPtr mesh, const Vector3 &position, const Quaternion &orient, const Vector3 &scale) { size_t vertexCount = 0; size_t indexCount = 0; Vector3* vertices = 0; Vector3* normals; unsigned long* indices = 0; bool added_shared = false; size_t current_offset = 0; size_t shared_offset = 0; size_t next_offset = 0; size_t index_offset = 0; // Calculate how many vertices and indices we're going to need for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh( i ); // We only need to add the shared vertices once if(submesh->useSharedVertices) { if( !added_shared ) { vertexCount += mesh->sharedVertexData->vertexCount; added_shared = true; } } else { vertexCount += submesh->vertexData->vertexCount; } // Add the indices indexCount += submesh->indexData->indexCount; } // Allocate space for the vertices and indices vertices = new Vector3[vertexCount]; normals = new Vector3[vertexCount]; indices = new unsigned long[indexCount]; added_shared = false; // Run through the submeshes again, adding the data into the arrays for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh(i); Ogre::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 Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); const Ogre::VertexElement* normalElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_NORMAL); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); float* pReal; for( size_t 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] = (orient * (pt * scale)) + position; normalElem->baseVertexPointerToElement(vertex, &pReal); Vector3 nt(pReal[0], pReal[1], pReal[2]); normals[current_offset + j] = nt; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } Ogre::IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset; size_t numTrisMultThree = numTris*3; if ( use32bitindexes ) { for ( size_t k = 0; k < numTrisMultThree; ++k) { indices[index_offset++] = pLong[k] + static_cast<unsigned long>(offset); } } else { for ( size_t k = 0; k < numTrisMultThree; ++k) { indices[index_offset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset); } } ibuf->unlock(); current_offset = next_offset; } // Create triangles from the retrieved data for (size_t k = 0; k < indexCount-1; k+=3) { Triangle t; t.v1 = vertices [indices[k]]; t.vn1 = normals [indices[k]]; t.v2 = vertices [indices[k+1]]; t.vn2 = normals [indices[k+1]]; t.v3 = vertices [indices[k+2]]; t.vn3 = normals [indices[k+2]]; t.calculateSquareSurface(); t.calculateSurfaceNormal(); t.calculateEdgeNormals(); _triangles.push_back(t); } // Delete intermediate arrays delete [] indices; delete [] normals; delete [] vertices; // Sort the triangle on their size, if needed (only if a gaussian random number generator // function is used to perform a random lookup of a triangle) if (mDistribution == MSD_HOMOGENEOUS) sort(_triangles.begin(), _triangles.end(), SortDescending()); else if (mDistribution == MSD_HETEROGENEOUS_1) sort(_triangles.begin(), _triangles.end(), SortAscending()); }
void PolyMousePicker::GetMeshInformation( Ogre::Entity *entity, size_t &vertex_count, Ogre::Vector3* &vertices, size_t &index_count, Ogre::uint32* &indices, const Ogre::Vector3 &position, const Ogre::Quaternion &orient, const Ogre::Vector3 &scale) { bool added_shared = false; size_t current_offset = 0; size_t shared_offset = 0; size_t next_offset = 0; size_t index_offset = 0; vertex_count = index_count = 0; Ogre::MeshPtr mesh = entity->getMesh(); bool useSoftwareBlendingVertices = entity->hasSkeleton(); if (useSoftwareBlendingVertices) { entity->_updateAnimation(); } // Calculate how many vertices and indices we're going to need for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh( i ); // We only need to add the shared vertices once if(submesh->useSharedVertices) { if( !added_shared ) { vertex_count += mesh->sharedVertexData->vertexCount; added_shared = true; } } else { vertex_count += submesh->vertexData->vertexCount; } // Add the indices index_count += submesh->indexData->indexCount; } // Allocate space for the vertices and indices vertices = new Ogre::Vector3[vertex_count]; indices = new Ogre::uint32[index_count]; added_shared = false; // Run through the submeshes again, adding the data into the arrays for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh(i); //---------------------------------------------------------------- // GET VERTEXDATA //---------------------------------------------------------------- Ogre::VertexData* vertex_data; //When there is animation: if(useSoftwareBlendingVertices) vertex_data = submesh->useSharedVertices ? entity->_getSkelAnimVertexData() : entity->getSubEntity(i)->_getSkelAnimVertexData(); else 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 Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::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 will // be comiled/typedefed as double: // Ogre::Real* pReal; float* pReal; for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]); vertices[current_offset + j] = (orient * (pt * scale)) + position; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } Ogre::IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); void* hwBuf = ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset; size_t index_start = index_data->indexStart; size_t last_index = numTris*3 + index_start; if (use32bitindexes) { Ogre::uint32* hwBuf32 = static_cast<Ogre::uint32*>(hwBuf); for (size_t k = index_start; k < last_index; ++k) { indices[index_offset++] = hwBuf32[k] + static_cast<Ogre::uint32>( offset ); } } else { Ogre::uint16* hwBuf16 = static_cast<Ogre::uint16*>(hwBuf); for (size_t k = index_start; k < last_index; ++k) { indices[ index_offset++ ] = static_cast<Ogre::uint32>( hwBuf16[k] ) + static_cast<Ogre::uint32>( offset ); } } ibuf->unlock(); current_offset = next_offset; } }
void Renderer::FindClosestPolygon(Ogre::Entity* entity, float& closestDistance, Ogre::Vector3& position, Ogre::Vector3& normal) { closestDistance = std::numeric_limits<float>::max(); // default value (means // nothing detected) // Get transformation Ogre::SceneNode* parentNode = entity->getParentSceneNode(); Ogre::Vector3 parentPos; Ogre::Quaternion parentOrientation; Ogre::Vector3 parentScale; if (parentNode) { parentPos = parentNode->_getDerivedPosition(); parentOrientation = parentNode->_getDerivedOrientation(); parentScale = parentNode->_getDerivedScale(); } else { parentPos = Ogre::Vector3::ZERO; parentOrientation = Ogre::Quaternion::IDENTITY; parentScale = Ogre::Vector3::UNIT_SCALE; } // Handle animated entities bool isAnimated = entity->hasSkeleton(); if (isAnimated) { entity->addSoftwareAnimationRequest(false); entity->_updateAnimation(); } // Loop through each submesh Ogre::MeshPtr mesh = entity->getMesh(); for (uint i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* subMesh = mesh->getSubMesh(i); // Ignore anything that isn't a triangle List if (subMesh->operationType != Ogre::RenderOperation::OT_TRIANGLE_LIST) continue; // Get the vertex data Ogre::VertexData* vertexData; if (subMesh->useSharedVertices) { if (isAnimated) vertexData = entity->_getSkelAnimVertexData(); else vertexData = mesh->sharedVertexData; } else { if (isAnimated) vertexData = entity->getSubEntity(i)->_getSkelAnimVertexData(); else vertexData = subMesh->vertexData; } // Get the size of one vertex const Ogre::VertexElement* posEl = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vBuff = vertexData->vertexBufferBinding->getBuffer(posEl->getSource()); uint vertexSize = vBuff->getVertexSize(); // Save pointer to first vertex short* pVertex = (short*)vBuff->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); short* pStartVertex = pVertex; // Get the index buffer // If it is null then skip as it must be a point cloud Ogre::HardwareIndexBufferSharedPtr iBuff = subMesh->indexData->indexBuffer; if (iBuff.isNull()) continue; uint* pLong = (uint*)iBuff->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); uint16_t* pShort = (uint16_t*)pLong; // Look through each vertex and check each triangle with the ray Ogre::Vector3 vertexPos; Ogre::Vector3 vertex1; Ogre::Vector3 vertex2; float* pReal; uint index; for (uint k = 0; k < subMesh->indexData->indexCount; k++) { // Read index value if (iBuff->getType() == Ogre::HardwareIndexBuffer::IT_32BIT) // if 32bit indexes { index = (uint)pLong[k]; } else { index = (uint)pShort[k]; } // Read referenced vertex pVertex = pStartVertex + (vertexSize * index); // calculate pointer posEl->baseVertexPointerToElement(pVertex, &pReal); // read vertex vertexPos = Ogre::Vector3(pReal[0], pReal[1], pReal[2]); // read position values // Apply world transformations if (parentNode) vertexPos = (parentOrientation * (vertexPos * parentScale)) + parentPos; // Figure out triangle and calculate the distance if it's the closest switch (k % 3) { case 0: vertex1 = vertexPos; break; case 1: vertex2 = vertexPos; break; case 2: RayToTriangleCheck(vertex1, vertex2, vertexPos, closestDistance, position, normal); break; default: break; } } iBuff->unlock(); vBuff->unlock(); } if (isAnimated) { entity->removeSoftwareAnimationRequest(false); } }
void GetTrianglesFromMesh(Ogre::Mesh* mesh, std::vector<float3>& dest) { dest.clear(); try { for(uint i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh(i); Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertices = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); size_t vertexSize = vbuf->getVertexSize(); float* pReal = 0; Ogre::IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; u32* pLong = static_cast<u32*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); u16* pShort = reinterpret_cast<u16*>(pLong); bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); if (use32bitindexes) { for(size_t k = 0; k < numTris * 3; k += 3) { uint i1 = pLong[k]; uint i2 = pLong[k+1]; uint i3 = pLong[k+2]; posElem->baseVertexPointerToElement(vertices + i1 * vertexSize, &pReal); dest.push_back(float3(pReal[0], pReal[1], pReal[2])); posElem->baseVertexPointerToElement(vertices + i2 * vertexSize, &pReal); dest.push_back(float3(pReal[0], pReal[1], pReal[2])); posElem->baseVertexPointerToElement(vertices + i3 * vertexSize, &pReal); dest.push_back(float3(pReal[0], pReal[1], pReal[2])); } } else { for(size_t k = 0; k < numTris * 3; k += 3) { uint i1 = pShort[k]; uint i2 = pShort[k+1]; uint i3 = pShort[k+2]; posElem->baseVertexPointerToElement(vertices + i1 * vertexSize, &pReal); dest.push_back(float3(pReal[0], pReal[1], pReal[2])); posElem->baseVertexPointerToElement(vertices + i2 * vertexSize, &pReal); dest.push_back(float3(pReal[0], pReal[1], pReal[2])); posElem->baseVertexPointerToElement(vertices + i3 * vertexSize, &pReal); dest.push_back(float3(pReal[0], pReal[1], pReal[2])); } } vbuf->unlock(); ibuf->unlock(); } } catch(Ogre::Exception &e) { ///\todo Fix Ogre to not allow meshes like this to be successfully created. LogError("GetTrianglesFromMesh failed for mesh! Ogre threw an exception: " + QString(e.what())); dest.clear(); } }
void MilkshapePlugin::doExportMesh(msModel* pModel) { // Create singletons Ogre::SkeletonManager skelMgr; Ogre::DefaultHardwareBufferManager defHWBufMgr; Ogre::LogManager& logMgr = Ogre::LogManager::getSingleton(); Ogre::MeshManager meshMgr; // // choose filename // OPENFILENAME ofn; memset (&ofn, 0, sizeof (OPENFILENAME)); char szFile[MS_MAX_PATH]; char szFileTitle[MS_MAX_PATH]; char szDefExt[32] = "mesh"; char szFilter[128] = "OGRE .mesh Files (*.mesh)\0*.mesh\0All Files (*.*)\0*.*\0\0"; szFile[0] = '\0'; szFileTitle[0] = '\0'; ofn.lStructSize = sizeof (OPENFILENAME); ofn.lpstrDefExt = szDefExt; ofn.lpstrFilter = szFilter; ofn.lpstrFile = szFile; ofn.nMaxFile = MS_MAX_PATH; ofn.lpstrFileTitle = szFileTitle; ofn.nMaxFileTitle = MS_MAX_PATH; ofn.Flags = OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST; ofn.lpstrTitle = "Export to OGRE Mesh"; if (!::GetSaveFileName (&ofn)) return /*0*/; logMgr.logMessage("Creating Mesh object..."); Ogre::MeshPtr ogreMesh = Ogre::MeshManager::getSingleton().create("export", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); logMgr.logMessage("Mesh object created."); bool foundBoneAssignment = false; // No shared geometry int i; int wh, numbones; int intweight[3], intbones[3]; size_t j; Ogre::Vector3 min, max, currpos; Ogre::Real maxSquaredRadius; bool first = true; for (i = 0; i < msModel_GetMeshCount (pModel); i++) { msMesh *pMesh = msModel_GetMeshAt (pModel, i); logMgr.logMessage("Creating SubMesh object..."); Ogre::SubMesh* ogreSubMesh = ogreMesh->createSubMesh(); logMgr.logMessage("SubMesh object created."); // Set material logMgr.logMessage("Getting SubMesh Material..."); int matIdx = msMesh_GetMaterialIndex(pMesh); if (matIdx == -1) { // No material, use blank ogreSubMesh->setMaterialName("BaseWhite"); logMgr.logMessage("No Material, using default 'BaseWhite'."); } else { msMaterial *pMat = msModel_GetMaterialAt(pModel, matIdx); ogreSubMesh->setMaterialName(pMat->szName); logMgr.logMessage("SubMesh Material Done."); } logMgr.logMessage("Setting up geometry..."); // Set up mesh geometry ogreSubMesh->vertexData = new Ogre::VertexData(); ogreSubMesh->vertexData->vertexCount = msMesh_GetVertexCount (pMesh); ogreSubMesh->vertexData->vertexStart = 0; Ogre::VertexBufferBinding* bind = ogreSubMesh->vertexData->vertexBufferBinding; Ogre::VertexDeclaration* decl = ogreSubMesh->vertexData->vertexDeclaration; // Always 1 texture layer, 2D coords #define POSITION_BINDING 0 #define NORMAL_BINDING 1 #define TEXCOORD_BINDING 2 decl->addElement(POSITION_BINDING, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); decl->addElement(NORMAL_BINDING, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); decl->addElement(TEXCOORD_BINDING, 0, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); // Create buffers Ogre::HardwareVertexBufferSharedPtr pbuf = Ogre::HardwareBufferManager::getSingleton(). createVertexBuffer(decl->getVertexSize(POSITION_BINDING), ogreSubMesh->vertexData->vertexCount, Ogre::HardwareBuffer::HBU_DYNAMIC, false); Ogre::HardwareVertexBufferSharedPtr nbuf = Ogre::HardwareBufferManager::getSingleton(). createVertexBuffer(decl->getVertexSize(NORMAL_BINDING), ogreSubMesh->vertexData->vertexCount, Ogre::HardwareBuffer::HBU_DYNAMIC, false); Ogre::HardwareVertexBufferSharedPtr tbuf = Ogre::HardwareBufferManager::getSingleton(). createVertexBuffer(decl->getVertexSize(TEXCOORD_BINDING), ogreSubMesh->vertexData->vertexCount, Ogre::HardwareBuffer::HBU_DYNAMIC, false); bind->setBinding(POSITION_BINDING, pbuf); bind->setBinding(NORMAL_BINDING, nbuf); bind->setBinding(TEXCOORD_BINDING, tbuf); ogreSubMesh->useSharedVertices = false; float* pPos = static_cast<float*>( pbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); logMgr.logMessage("Doing positions and texture coords..."); for (j = 0; j < ogreSubMesh->vertexData->vertexCount; ++j) { logMgr.logMessage("Doing vertex " + Ogre::StringConverter::toString(j)); msVertex *pVertex = msMesh_GetVertexAt (pMesh, (int)j); msVertexEx *pVertexEx=msMesh_GetVertexExAt(pMesh, (int)j); msVec3 Vertex; msVertex_GetVertex (pVertex, Vertex); *pPos++ = Vertex[0]; *pPos++ = Vertex[1]; *pPos++ = Vertex[2]; // Deal with bounds currpos = Ogre::Vector3(Vertex[0], Vertex[1], Vertex[2]); if (first) { min = max = currpos; maxSquaredRadius = currpos.squaredLength(); first = false; } else { min.makeFloor(currpos); max.makeCeil(currpos); maxSquaredRadius = std::max(maxSquaredRadius, currpos.squaredLength()); } int boneIdx = msVertex_GetBoneIndex(pVertex); if (boneIdx != -1) { foundBoneAssignment = true; numbones = 1; intbones[0] = intbones[1] = intbones[2] = -1; intweight[0] = intweight[1] = intweight[2] = 0; for(wh = 0; wh < 3; ++wh) { intbones[wh] = msVertexEx_GetBoneIndices(pVertexEx, wh); if(intbones[wh] == -1) break; ++numbones; intweight[wh] = msVertexEx_GetBoneWeights(pVertexEx, wh); } // for(k) Ogre::VertexBoneAssignment vertAssign; vertAssign.boneIndex = boneIdx; vertAssign.vertexIndex = (unsigned int)j; if(numbones == 1) { vertAssign.weight = 1.0; } // single assignment else { vertAssign.weight=(Ogre::Real)intweight[0]/100.0; } ogreSubMesh->addBoneAssignment(vertAssign); if(numbones > 1) { // this somewhat contorted logic is because the first weight [0] matches to the bone assignment // located with pVertex. The next two weights [1][2] match up to the first two bones found // with pVertexEx [0][1]. The weight for the fourth bone, if present, is the unassigned weight for(wh = 0; wh < 3; wh++) { boneIdx = intbones[wh]; if(boneIdx == -1) break; vertAssign.boneIndex = boneIdx; vertAssign.vertexIndex = (unsigned int)j; if(wh == 2) { // fourth weight is 1.0-(sumoffirstthreeweights) vertAssign.weight = 1.0-(((Ogre::Real)intweight[0]/100.0)+ ((Ogre::Real)intweight[1]/100.0)+((Ogre::Real)intweight[2]/100.0)); } else { vertAssign.weight=(Ogre::Real)intweight[wh+1]; } ogreSubMesh->addBoneAssignment(vertAssign); } // for(k) } // if(numbones) } } pbuf->unlock(); float* pTex = static_cast<float*>( tbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); logMgr.logMessage("Doing uvs, normals and indexes (v2)..."); // Aargh, Milkshape uses stupid separate normal indexes for the same vertex like 3DS // Normals aren't described per vertex but per triangle vertex index // Pain in the arse, we have to do vertex duplication again if normals differ at a vertex (non smooth) // WHY don't people realise this format is a pain for passing to 3D APIs in vertex buffers? float* pNorm = static_cast<float*>( nbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); ogreSubMesh->indexData->indexCount = msMesh_GetTriangleCount (pMesh) * 3; // Always use 16-bit buffers, Milkshape can't handle more anyway Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton(). createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, ogreSubMesh->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); ogreSubMesh->indexData->indexBuffer = ibuf; unsigned short *pIdx = static_cast<unsigned short*>( ibuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); for (j = 0; j < ogreSubMesh->indexData->indexCount; j+=3) { msTriangle *pTriangle = msMesh_GetTriangleAt (pMesh, (int)j/3); msTriangleEx *pTriangleEx=msMesh_GetTriangleExAt(pMesh, (int)j/3); word nIndices[3]; msTriangle_GetVertexIndices (pTriangle, nIndices); msVec3 Normal; msVec2 uv; int k, vertIdx; for (k = 0; k < 3; ++k) { vertIdx = nIndices[k]; // Face index pIdx[j+k] = vertIdx; // Vertex normals // For the moment, ignore any discrepancies per vertex msTriangleEx_GetNormal(pTriangleEx, k, &Normal[0]); msTriangleEx_GetTexCoord(pTriangleEx, k, &uv[0]); pTex[(vertIdx*2)]=uv[0]; pTex[(vertIdx*2)+1]=uv[1]; pNorm[(vertIdx*3)] = Normal[0]; pNorm[(vertIdx*3)+1] = Normal[1]; pNorm[(vertIdx*3)+2] = Normal[2]; } } // Faces nbuf->unlock(); ibuf->unlock(); tbuf->unlock(); // Now use Ogre's ability to reorganise the vertex buffers the best way Ogre::VertexDeclaration* newDecl = ogreSubMesh->vertexData->vertexDeclaration->getAutoOrganisedDeclaration( foundBoneAssignment, false); Ogre::BufferUsageList bufferUsages; for (size_t u = 0; u <= newDecl->getMaxSource(); ++u) bufferUsages.push_back(Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); ogreSubMesh->vertexData->reorganiseBuffers(newDecl, bufferUsages); logMgr.logMessage("Geometry done."); } // SubMesh // Set bounds ogreMesh->_setBoundingSphereRadius(Ogre::Math::Sqrt(maxSquaredRadius)); ogreMesh->_setBounds(Ogre::AxisAlignedBox(min, max), false); // Keep hold of a Skeleton pointer for deletion later // Mesh uses Skeleton pointer for skeleton name Ogre::SkeletonPtr pSkel; if (exportSkeleton && foundBoneAssignment) { // export skeleton, also update mesh to point to it pSkel = doExportSkeleton(pModel, ogreMesh); } else if (!exportSkeleton && foundBoneAssignment) { // We've found bone assignments, but skeleton is not to be exported // Prompt the user to find the skeleton if (!locateSkeleton(ogreMesh)) return; } // Export logMgr.logMessage("Creating MeshSerializer.."); Ogre::MeshSerializer serializer; logMgr.logMessage("MeshSerializer created."); // Generate LODs if required if (generateLods) { // Build LOD depth list Ogre::Mesh::LodDistanceList distList; float depth = 0; for (unsigned short depthidx = 0; depthidx < numLods; ++depthidx) { depth += lodDepthIncrement; distList.push_back(depth); } ogreMesh->generateLodLevels(distList, lodReductionMethod, lodReductionAmount); } if (generateEdgeLists) { ogreMesh->buildEdgeList(); } if (generateTangents) { unsigned short src, dest; ogreMesh->suggestTangentVectorBuildParams(tangentSemantic, src, dest); ogreMesh->buildTangentVectors(tangentSemantic, src, dest, tangentsSplitMirrored, tangentsSplitRotated, tangentsUseParity); } // Export Ogre::String msg; msg = "Exporting mesh data to file '" + Ogre::String(szFile) + "'"; logMgr.logMessage(msg); serializer.exportMesh(ogreMesh.getPointer(), szFile); logMgr.logMessage("Export successful"); Ogre::MeshManager::getSingleton().remove(ogreMesh->getHandle()); if (!pSkel.isNull()) Ogre::SkeletonManager::getSingleton().remove(pSkel->getHandle()); if (exportMaterials && msModel_GetMaterialCount(pModel) > 0) { doExportMaterials(pModel); } }
Mesh loadMesh(const std::string& meshName) { Mesh result; bool addedShared = false; size_t currentOffset = 0; size_t sharedOffset = 0; size_t nextOffset = 0; size_t indexOffset = 0; const v3 scale = v3::UNIT_SCALE; const v3 position = v3::ZERO; const qv4 orientation = qv4::IDENTITY; Ogre::MeshManager* mm = Ogre::MeshManager::getSingletonPtr(); if (! mm) { initOgreForMeshLoading(); mm = Ogre::MeshManager::getSingletonPtr(); } Ogre::MeshPtr mesh = mm->load(meshName, "General"); // Calculate how many result.mVertices and result.mIndices we're going to need for (unsigned short i=0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* subMesh = mesh->getSubMesh(i); // We only need to add the shared result.mVertices once if (subMesh->useSharedVertices) { if (!addedShared) { result.mVertexCount += mesh->sharedVertexData->vertexCount; addedShared = true; } } else { result.mVertexCount += subMesh->vertexData->vertexCount; } result.mIndexCount += subMesh->indexData->indexCount; } result.mVertices.reset(new v3[result.mVertexCount]); result.mIndices.reset(new u32[result.mIndexCount]); addedShared = false; // Run through the sub-meshes again, adding the data into the arrays for (unsigned short i=0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* subMesh = mesh->getSubMesh(i); Ogre::VertexData* vertexData = subMesh->useSharedVertices ? mesh->sharedVertexData : subMesh->vertexData; if((!subMesh->useSharedVertices) || (subMesh->useSharedVertices && !addedShared)) { if(subMesh->useSharedVertices) { addedShared = true; sharedOffset = currentOffset; } const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::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 will // be compiled/typedefed as double: float* pReal; for( size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); v3 pt(pReal[0], pReal[1], pReal[2]); result.mVertices[currentOffset + j] = (orientation * (pt * scale)) + position; } vbuf->unlock(); nextOffset += vertexData->vertexCount; } Ogre::IndexData* index_data = subMesh->indexData; size_t numTris = index_data->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); size_t offset = (subMesh->useSharedVertices)? sharedOffset : currentOffset; if (use32bitindexes) { for (size_t k = 0; k < numTris*3; ++k) { result.mIndices[indexOffset++] = pLong[k] + static_cast<unsigned long>(offset); } } else { for (size_t k = 0; k < numTris*3; ++k) { result.mIndices[indexOffset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset); } } ibuf->unlock(); currentOffset = nextOffset; } return result; }
void OgreMeshAsset::CreateKdTree() { meshData.Clear(); normals.clear(); uvs.clear(); subMeshTriangleCounts.clear(); for(unsigned short i = 0; i < ogreMesh->getNumSubMeshes(); ++i) { Ogre::SubMesh *submesh = ogreMesh->getSubMesh(i); assert(submesh); Ogre::VertexData *vertexData = submesh->useSharedVertices ? ogreMesh->sharedVertexData : submesh->vertexData; assert(vertexData); const Ogre::VertexElement *posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); if (!posElem) { subMeshTriangleCounts.push_back(0); continue; // No position element. Ignore this submesh. } Ogre::HardwareVertexBufferSharedPtr vbufPos = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char *pos = (unsigned char*)vbufPos->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); assert(pos); size_t posOffset = posElem->getOffset(); size_t posSize = vbufPos->getVertexSize(); // Texcoord element is not mandatory unsigned char *texCoord = 0; size_t texOffset = 0; size_t texSize = 0; Ogre::HardwareVertexBufferSharedPtr vbufTex; const Ogre::VertexElement *texElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES); if (texElem) { vbufTex = vertexData->vertexBufferBinding->getBuffer(texElem->getSource()); // Check if the texcoord buffer is different than the position buffer, in that case lock it separately if (vbufTex != vbufPos) texCoord = static_cast<unsigned char*>(vbufTex->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); else texCoord = pos; texOffset = texElem->getOffset(); texSize = vbufTex->getVertexSize(); } Ogre::IndexData *indexData = submesh->indexData; Ogre::HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer; u32 *pLong = (u32*)ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); u16 *pShort = (u16*)pLong; const bool use32BitIndices = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); for(unsigned j = 0; j+2 < indexData->indexCount; j += 3) { unsigned i0, i1, i2; if (use32BitIndices) { i0 = pLong[j]; i1 = pLong[j+1]; i2 = pLong[j+2]; } else { i0 = pShort[j]; i1 = pShort[j+1]; i2 = pShort[j+2]; } float3 v0 = *(float3*)(pos + posOffset + i0 * posSize); float3 v1 = *(float3*)(pos + posOffset + i1 * posSize); float3 v2 = *(float3*)(pos + posOffset + i2 * posSize); Triangle t(v0, v1, v2); meshData.AddObjects(&t, 1); if (texElem) { uvs.push_back(*((float2*)(texCoord + texOffset + i0 * texSize))); uvs.push_back(*((float2*)(texCoord + texOffset + i1 * texSize))); uvs.push_back(*((float2*)(texCoord + texOffset + i2 * texSize))); } float3 edge1 = v1 - v0; float3 edge2 = v2 - v0; float3 normal = edge1.Cross(edge2); normal.Normalize(); normals.push_back(normal); } subMeshTriangleCounts.push_back((int)(indexData->indexCount / 3)); vbufPos->unlock(); if (!vbufTex.isNull() && vbufTex != vbufPos) vbufTex->unlock(); ibuf->unlock(); } { PROFILE(OgreMeshAsset_KdTree_Build); meshData.Build(); } }
GrassPatch::GrassPatch(int nb_blades, int nb_blade_segments, float width, float height, Ogre::SceneManager* ScnMgr) { int i, nb_particles; // Create the particle field nb_particles = nb_blades * (nb_blade_segments + 1); m_Particles = new GrassParticleField(nb_particles, 1); // Allocate the blade list m_Blades = new Blade *[nb_blades]; m_NbBlades = nb_blades; Ogre::Radian *angle = new Ogre::Radian(Ogre::Math::PI * ((rand()%1000) / 1000.0f)); // Create the blades of grass for (i = 0; i < nb_blades; i++) { m_Blades[i] = new Blade(m_Particles, i * (nb_blade_segments + 1), nb_blade_segments, 4 + ((rand()%1000) / 1000.0f)*0.5f, 0.3f + ((rand()%1000) / 1000.0f)*0.1f, width / 2 - ((rand()%1000) / 500.0f) * width, height / 2 - ((rand()%1000) / 500.0f) * height, *angle); m_Blades[i]->moving = true; m_Blades[i]->timeout = 0; } m_VertexCount = nb_blades * m_Blades[0]->GetStrippedVertexCount(); m_TriangleCount = ((nb_blade_segments - 1) << 1) + 1; mvertexData = new Ogre::VertexData (); // Vertex declaration Ogre::VertexDeclaration* decl = mvertexData->vertexDeclaration; Ogre::VertexBufferBinding* binding = mvertexData->vertexBufferBinding; size_t offset = 0; //position decl->addElement (POSITION_BINDING, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); // normal here decl->addElement(POSITION_BINDING, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); // Diffuse Color decl->addElement(POSITION_BINDING, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR); // texture here decl->addElement(POSITION_BINDING, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); //position updated each frame Ogre::HardwareVertexBufferSharedPtr vbuf1 = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer (offset, // size of one whole vertex m_VertexCount, // number of vertices Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY, // usage false); // no shadow buffer binding->setBinding(POSITION_BINDING, vbuf1); Ogre::HardwareVertexBufferSharedPtr vVertices = binding->getBuffer(POSITION_BINDING); Ogre::Real *pVertices = static_cast<Ogre::Real*>( vVertices->lock( Ogre::HardwareBuffer::HBL_DISCARD ) ); // Colour up the blades for (i = 0; i < m_NbBlades; i++) m_Blades[i]->Paint (i, pVertices); vVertices->unlock(); // Index buffer to handle triangle strip vertex buffer as triangle list // Create index buffer int nIndexes = m_TriangleCount*3*m_NbBlades; Ogre::HardwareIndexBufferSharedPtr iBuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer (Ogre::HardwareIndexBuffer::IT_32BIT, nIndexes, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); // Fill index buffer unsigned int* pIdx = static_cast<unsigned int*> (iBuf->lock (Ogre::HardwareBuffer::HBL_DISCARD)); unsigned int j = 0; for (i = 0; i < m_NbBlades; i++) m_Blades[i]->UpdateIndexBuffer(&j, i, pIdx); iBuf->unlock (); mRenderOp.vertexData = mvertexData; // mRenderOp.vertexData->vertexCount = m_VertexCount; mRenderOp.vertexData->vertexCount= nIndexes; mRenderOp.vertexData->vertexStart = 0; mRenderOp.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; mRenderOp.indexData = new Ogre::IndexData(); mRenderOp.indexData->indexBuffer = iBuf; mRenderOp.indexData->indexCount = nIndexes; mRenderOp.indexData->indexStart = 0; mRenderOp.useIndexes = true; mRenderOp.srcRenderable = this; setMaterial ("Examples/Grass"); // setup radius the bounding box of this SimpleRenderable to big values to be sure to achieve drawing. mRadius = 100; setBoundingBox(Ogre::AxisAlignedBox(-300, -300, -300, 600, 600, 600)); }
void OgreMeshRay::GetMeshInformation(const Ogre::ManualObject* manual, size_t& vertex_count, Ogre::Vector3*& vertices, size_t& index_count, unsigned long*& indices, const Ogre::Vector3& position, const Ogre::Quaternion& orient, const Ogre::Vector3& scale) { std::vector<Ogre::Vector3> returnVertices; std::vector<unsigned long> returnIndices; unsigned long thisSectionStart = 0; for (unsigned int i = 0, size = manual->getNumSections(); i < size; ++i) { Ogre::ManualObject::ManualObjectSection* section = manual->getSection( i); Ogre::RenderOperation* renderOp = section->getRenderOperation(); std::vector<Ogre::Vector3> pushVertices; //Collect the vertices { const Ogre::VertexElement* vertexElement = renderOp->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vertexBuffer = renderOp->vertexData->vertexBufferBinding->getBuffer( vertexElement->getSource()); char* verticesBuffer = static_cast<char*>(vertexBuffer->lock( Ogre::HardwareBuffer::HBL_READ_ONLY)); float* positionArrayHolder; thisSectionStart = returnVertices.size() + pushVertices.size(); pushVertices.reserve(renderOp->vertexData->vertexCount); for (unsigned int j = 0; j < renderOp->vertexData->vertexCount; ++j) { vertexElement->baseVertexPointerToElement( verticesBuffer + j * vertexBuffer->getVertexSize(), &positionArrayHolder); Ogre::Vector3 vertexPos = Ogre::Vector3(positionArrayHolder[0], positionArrayHolder[1], positionArrayHolder[2]); vertexPos = (orient * (vertexPos * scale)) + position; pushVertices.push_back(vertexPos); } vertexBuffer->unlock(); } //Collect the indices { if (renderOp->useIndexes) { Ogre::HardwareIndexBufferSharedPtr indexBuffer = renderOp->indexData->indexBuffer; if (indexBuffer.isNull() || renderOp->operationType != Ogre::RenderOperation::OT_TRIANGLE_LIST) { //No triangles here, so we just drop the collected vertices and move along to the next section. continue; } else { returnVertices.reserve( returnVertices.size() + pushVertices.size()); returnVertices.insert(returnVertices.end(), pushVertices.begin(), pushVertices.end()); } unsigned int* pLong = static_cast<unsigned int*>(indexBuffer->lock( Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); returnIndices.reserve( returnIndices.size() + renderOp->indexData->indexCount); for (size_t j = 0; j < renderOp->indexData->indexCount; ++j) { unsigned long index; //We also have got to remember that for a multi section object, each section has //different vertices, so the indices will not be correct. To correct this, we //have to add the position of the first vertex in this section to the index //(At least I think so...) if (indexBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT) index = static_cast<unsigned long>(pLong[j]) + thisSectionStart; else index = static_cast<unsigned long>(pShort[j]) + thisSectionStart; returnIndices.push_back(index); } indexBuffer->unlock(); } } } //Now we simply return the data. index_count = returnIndices.size(); vertex_count = returnVertices.size(); vertices = new Ogre::Vector3[vertex_count]; for (unsigned long i = 0; i < vertex_count; ++i) vertices[i] = returnVertices[i]; indices = new unsigned long[index_count]; for (unsigned long i = 0; i < index_count; ++i) indices[i] = returnIndices[i]; //All done. return; }
CompoundCollisionShape* CollisionShapeManager::PerformConvexDecomposition(const String& Name, Graphics::Mesh* ObjectMesh, Whole Depth, Real CPercent, Real PPercent, Boole UseAllSubmeshes) { //new submesh friendly code Ogre::MeshPtr myMesh = ObjectMesh->_GetInternalMesh(); Ogre::SubMesh* subMesh = NULL; Ogre::IndexData* indexData = NULL; Ogre::VertexData* vertexData = NULL; Boole use32bitindexes = false; unsigned int currtriCount = 0; unsigned int triCount = 0; unsigned int vCount = 0; unsigned int iCount = 0; Whole VertPrevSize = 0; Whole IndiPrevSize = 0; Boole SharedVerts = myMesh->getSubMesh(0)->useSharedVertices; Whole* VertPerSubMesh = NULL; if(UseAllSubmeshes) { VertPerSubMesh = new Whole[myMesh->getNumSubMeshes()]; for( Whole X = 0 ; X < myMesh->getNumSubMeshes() ; X++ ) { vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount; iCount += myMesh->getSubMesh(X)->indexData->indexCount; VertPerSubMesh[X] = SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(X)->vertexData->vertexCount; } }else{ vCount += SharedVerts ? myMesh->sharedVertexData->vertexCount : myMesh->getSubMesh(0)->vertexData->vertexCount; iCount += myMesh->getSubMesh(0)->indexData->indexCount; } Ogre::Vector3* vertices = new Ogre::Vector3[vCount]; unsigned int* indices = new unsigned int[iCount]; for( unsigned short int SubMeshIndex = 0 ; SubMeshIndex < myMesh->getNumSubMeshes() ; SubMeshIndex++ ) { if( !UseAllSubmeshes && (SubMeshIndex > 0) ) break; if( SharedVerts && (SubMeshIndex > 0) ) break; subMesh = myMesh->getSubMesh(SubMeshIndex); indexData = subMesh->indexData; vertexData = SharedVerts ? myMesh->sharedVertexData : myMesh->getSubMesh(SubMeshIndex)->vertexData; const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vBuffer = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); Ogre::HardwareIndexBufferSharedPtr iBuffer = indexData->indexBuffer; currtriCount=indexData->indexCount/3; triCount+=(indexData->indexCount/3); unsigned char* vertex = static_cast<unsigned char*>(vBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); float* pReal = NULL; for( size_t j = 0 ; j < vertexData->vertexCount ; j++, vertex += vBuffer->getVertexSize() ) { posElem->baseVertexPointerToElement(vertex, &pReal); vertices[j + VertPrevSize].x = *pReal++; vertices[j + VertPrevSize].y = *pReal++; vertices[j + VertPrevSize].z = *pReal++; } vBuffer->unlock(); size_t index_offset = 0; use32bitindexes = (iBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned long* pLong = static_cast<unsigned long*>(iBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); if( use32bitindexes ) { for (size_t k = 0; k < currtriCount*3; ++k) { if(SubMeshIndex > 0 && VertPerSubMesh) { indices[index_offset+IndiPrevSize] = pLong[k] + VertPerSubMesh[SubMeshIndex]; }else{ indices[index_offset+IndiPrevSize] = pLong[k]; } index_offset++; } }else{ for( size_t k = 0 ; k < currtriCount * 3 ; ++k ) { if(SubMeshIndex > 0 && VertPerSubMesh) { indices[index_offset+IndiPrevSize] = (static_cast<unsigned long>(pShort[k])) + VertPerSubMesh[SubMeshIndex]; }else{ indices[index_offset+IndiPrevSize] = static_cast<unsigned long>(pShort[k]); } index_offset++; } } iBuffer->unlock(); VertPrevSize += vertexData->vertexCount; IndiPrevSize += indexData->indexCount; } ConvexDecomposition::DecompDesc desc; desc.mVcount = vertexData->vertexCount; desc.mTcount = triCount; desc.mVertices = &vertices[0].x; desc.mIndices = &indices[0]; unsigned int maxv = 16; float skinWidth = 0.0; desc.mDepth = Depth; desc.mCpercent = CPercent; desc.mPpercent = PPercent; desc.mMaxVertices = maxv; desc.mSkinWidth = skinWidth; Internal::MezzConvexDecomposition decomp; desc.mCallback = &decomp; ConvexBuilder cb(desc.mCallback); cb.process(desc); CompoundCollisionShape* compound = new CompoundCollisionShape(Name); btTransform trans; trans.setIdentity(); for (int i=0;i<decomp.m_convexShapes.size();i++) { std::stringstream namestream; namestream << Name << "Child" << i; Vector3 centroid(decomp.m_convexCentroids[i]); ConvexHullCollisionShape* convexShape = new ConvexHullCollisionShape(namestream.str(),decomp.m_convexShapes[i]); compound->AddChildShape(convexShape,centroid); } delete[] vertices; delete[] indices; delete[] VertPerSubMesh; return compound; }
void GeometryFactory::generateSphericDome (const Ogre::String &name, int segments, DomeType type) { // Return now if already exists if (Ogre::MeshManager::getSingleton ().resourceExists (name)) { return; } Ogre::LogManager::getSingleton ().logMessage ( "Caelum: Creating " + name + " sphere mesh resource..."); // Use the mesh manager to create the mesh Ogre::MeshPtr msh = Ogre::MeshManager::getSingleton ().createManual (name, RESOURCE_GROUP_NAME); // Create a submesh Ogre::SubMesh *sub = msh->createSubMesh (); // Create the shared vertex data Ogre::VertexData *vertexData = new Ogre::VertexData (); msh->sharedVertexData = vertexData; // Define the vertices' format Ogre::VertexDeclaration *vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // Position vertexDecl->addElement (0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); currOffset += Ogre::VertexElement::getTypeSize (Ogre::VET_FLOAT3); // Normal vertexDecl->addElement (0, currOffset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); currOffset += Ogre::VertexElement::getTypeSize (Ogre::VET_FLOAT3); // Texture coordinates vertexDecl->addElement (0, currOffset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0); currOffset += Ogre::VertexElement::getTypeSize (Ogre::VET_FLOAT2); // Allocate the vertex buffer switch (type) { case DT_GRADIENTS: vertexData->vertexCount = segments * (segments - 1) + 2; break; case DT_STARFIELD: vertexData->vertexCount = (segments + 1) * (segments + 1); break; }; Ogre::HardwareVertexBufferSharedPtr vBuf = Ogre::HardwareBufferManager::getSingleton ().createVertexBuffer (vertexDecl->getVertexSize (0), vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); Ogre::VertexBufferBinding *binding = vertexData->vertexBufferBinding; binding->setBinding (0, vBuf); float *pVertex = static_cast<float *>(vBuf->lock (Ogre::HardwareBuffer::HBL_DISCARD)); // Allocate the index buffer switch (type) { case DT_GRADIENTS: sub->indexData->indexCount = 2 * segments * (segments - 1) * 3; break; case DT_STARFIELD: sub->indexData->indexCount = 2 * (segments - 1) * segments * 3; break; }; sub->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton ().createIndexBuffer (Ogre::HardwareIndexBuffer::IT_16BIT, sub->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); Ogre::HardwareIndexBufferSharedPtr iBuf = sub->indexData->indexBuffer; unsigned short *pIndices = static_cast<unsigned short *>(iBuf->lock (Ogre::HardwareBuffer::HBL_DISCARD)); // Fill the buffers switch (type) { case DT_GRADIENTS: fillGradientsDomeBuffers (pVertex, pIndices, segments); break; case DT_STARFIELD: fillStarfieldDomeBuffers (pVertex, pIndices, segments); break; }; // Close the vertex buffer vBuf->unlock (); // Close the index buffer iBuf->unlock (); // Finishing it... sub->useSharedVertices = true; msh->_setBounds (Ogre::AxisAlignedBox (-1, -1, -1, 1, 1, 1), false); msh->_setBoundingSphereRadius (1); msh->load (); Ogre::LogManager::getSingleton ().logMessage ( "Caelum: generateSphericDome DONE"); }
bool Terrain::createTerrain() { if(mMainViewport == NULL) mMainViewport = Core::getSingleton().mCamera->getViewport(); Ogre::CompositorManager::getSingleton().addCompositor(mMainViewport, "DemoCompositor"); Ogre::CompositorManager::getSingleton().setCompositorEnabled(mMainViewport, "DemoCompositor", true); mMapData = MapDataManager::getSingletonPtr(); DataLibrary* datalib = DataLibrary::getSingletonPtr(); int terrainszie = mMapData->getMapSize() + 2 * MAPBOLDER + 1; Core::getSingleton().mSceneMgr->setSkyBox(true, "SkyBox",200); Ogre::GpuSharedParametersPtr sharedparams = Ogre::GpuProgramManager::getSingleton().getSharedParameters("TestSharedParamsName"); float border = mMapData->getMapSize() * 12.0f; sharedparams->setNamedConstant("border", border); //创建灯光 Core::getSingleton().mSceneMgr->setAmbientLight(Ogre::ColourValue(0.5f, 0.5f, 0.5f)); mLight = Core::getSingleton().mSceneMgr->createLight("TerrainLight"); mLight->setType(Ogre::Light::LT_DIRECTIONAL); mLight->setPosition(-500.0f,500.0f, 500.0f); mLight->setDirection(1.0f, -1.0f, -1.0f); mLight->setDiffuseColour(Ogre::ColourValue(0.5f, 0.5f,0.5f)); mLight->setSpecularColour(Ogre::ColourValue(0.8f, 0.8f,0.8f)); //设置深度图投影 Ogre::TexturePtr tex = Ogre::TextureManager::getSingleton().getByName("shadowdepthmap"); if(tex.isNull()) tex = Ogre::TextureManager::getSingleton().createManual("shadowdepthmap", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 2048, 2048, 0, Ogre::PF_FLOAT16_R, Ogre::TU_RENDERTARGET); mShadowDepthMapTarget = tex->getBuffer()->getRenderTarget(); Ogre::Viewport* vp = mShadowDepthMapTarget->addViewport(CameraContral::getSingleton().getShadowMapCamera()); vp->setSkiesEnabled(false); vp->setOverlaysEnabled(false); vp->setVisibilityMask(VISMASK_OPAQUE); vp->setMaterialScheme("WriteDepthMap"); vp->setBackgroundColour(Ogre::ColourValue(1.0f,1.0f,1.0f)); mShadowDepthMapTarget->addListener(this); //弱爆了…… Ogre::MaterialPtr mat; mat = Ogre::MaterialManager::getSingleton().getByName("TerrainTile"); Ogre::AliasTextureNamePairList texAliasList; std::string texname; datalib->getData("GameData/BattleData/MapData/Ground/G0Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); datalib->getData("GameData/BattleData/MapData/Ground/G1Tex",texname); texAliasList.insert(std::make_pair("Diffuse1",texname)); datalib->getData("GameData/BattleData/MapData/Ground/G2Tex",texname); texAliasList.insert(std::make_pair("Diffuse2",texname)); datalib->getData("GameData/BattleData/MapData/Ground/G3Tex",texname); texAliasList.insert(std::make_pair("Diffuse3",texname)); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("CliffMat1"); datalib->getData("GameData/BattleData/MapData/Ground/G0Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("CliffMat2"); datalib->getData("GameData/BattleData/MapData/Ground/G1Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("CliffMat3"); datalib->getData("GameData/BattleData/MapData/Ground/G2Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("CliffMat4"); datalib->getData("GameData/BattleData/MapData/Ground/G3Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("BankMat1"); datalib->getData("GameData/BattleData/MapData/Ground/G0Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("BankMat2"); datalib->getData("GameData/BattleData/MapData/Ground/G1Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("BankMat3"); datalib->getData("GameData/BattleData/MapData/Ground/G2Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); mat = Ogre::MaterialManager::getSingleton().getByName("BankMat4"); datalib->getData("GameData/BattleData/MapData/Ground/G3Tex",texname); texAliasList.insert(std::make_pair("Diffuse",texname)); texAliasList.insert(std::make_pair("Diffuse1","Cliff.tga")); mat->applyTextureAliases(texAliasList); texAliasList.clear(); //创建地面Mesh mTerrainNode = Core::getSingleton().mSceneMgr->getRootSceneNode()->createChildSceneNode("TerrainNode"); int numVertices = terrainszie * terrainszie * VERTEX_QUAD; int numIndex = terrainszie * terrainszie * VERTEX_PREQUAD; Ogre::MeshPtr mTerrainMesh = Ogre::MeshManager::getSingleton().createManual("TerrianMesh", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); Ogre::SubMesh* subMesh = mTerrainMesh->createSubMesh(); subMesh->useSharedVertices=false; subMesh->setMaterialName("TerrainTile"); // 创建顶点数据结构 subMesh->vertexData = new Ogre::VertexData(); subMesh->vertexData->vertexStart = 0; subMesh->vertexData->vertexCount = numVertices; //顶点声明与缓冲区绑定 Ogre::VertexDeclaration* vdecl = subMesh->vertexData->vertexDeclaration; Ogre::VertexBufferBinding* vbind = subMesh->vertexData->vertexBufferBinding; //设置顶点数据结构 size_t offsetUV = 0; vdecl->addElement(VERTEX_POS_BINDING, 0, Ogre::VET_FLOAT3,Ogre::VES_POSITION);//向顶点添加一个位置元素 vdecl->addElement(VERTEX_NOM_BINDING, 0, Ogre::VET_FLOAT3,Ogre::VES_NORMAL); for(int i = 0 ; i < TEXTURE_COUNT ; i ++) { offsetUV += vdecl->addElement (VERTEX_UV_BINDING, offsetUV, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES , i).getSize(); } // 创建世界坐标顶点缓冲区 Ogre::HardwareVertexBufferSharedPtr vbufPos = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( vdecl->getVertexSize(VERTEX_POS_BINDING), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); vbind->setBinding(VERTEX_POS_BINDING, vbufPos); Ogre::HardwareVertexBufferSharedPtr vbufNOM = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( vdecl->getVertexSize(VERTEX_NOM_BINDING), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); vbind->setBinding(VERTEX_NOM_BINDING, vbufNOM); // 创建纹理坐标顶点缓冲区 Ogre::HardwareVertexBufferSharedPtr vbufUV = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( vdecl->getVertexSize(VERTEX_UV_BINDING), numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); vbind->setBinding(VERTEX_UV_BINDING, vbufUV); // 创建索引缓冲区 Ogre::HardwareIndexBufferSharedPtr indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT , numIndex, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); //创建地形 float* pBufferPos = (float*)vbufPos->lock(Ogre::HardwareBuffer::HBL_DISCARD); float* pBufferUV = (float*)vbufUV->lock(Ogre::HardwareBuffer::HBL_DISCARD); float* pBufferNom = (float*)vbufNOM->lock(Ogre::HardwareBuffer::HBL_DISCARD); float startpos = - terrainszie * TILESIZE / 2; for(int y = 0 ; y < terrainszie; y ++) { for(int x = 0 ; x < terrainszie; x ++) { createTile(x, y, startpos + x * TILESIZE, startpos + y * TILESIZE, pBufferPos, pBufferUV, pBufferNom); pBufferPos += 3 * VERTEX_QUAD ; pBufferNom += 3 * VERTEX_QUAD ; pBufferUV += 2 * VERTEX_QUAD * 4; } } vbufNOM->unlock(); vbufUV->unlock(); vbufPos->unlock(); //写入索引信息 // 锁定索引缓冲区 Ogre::ushort* pIdx = (Ogre::ushort*)indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD); for(int y = 0 ; y < terrainszie ; y ++) { for(int x = 0 ; x < terrainszie ; x ++) { Ogre::ushort iIndexTopLeft = (x + y * terrainszie) * VERTEX_QUAD; Ogre::ushort iIndexTopRight = iIndexTopLeft + 1; Ogre::ushort iIndexBottomLeft = iIndexTopLeft + 2; Ogre::ushort iIndexBottomRight = iIndexTopLeft + 3; *pIdx++ = iIndexBottomLeft; *pIdx++ = iIndexBottomRight; *pIdx++ = iIndexTopLeft; *pIdx++ = iIndexBottomRight; *pIdx++ = iIndexTopRight; *pIdx++ = iIndexTopLeft; } } indexBuffer->unlock(); //设置模型的的索引数据 subMesh->indexData->indexBuffer = indexBuffer; subMesh->indexData->indexStart = 0; subMesh->indexData->indexCount =numIndex; Ogre::AxisAlignedBox meshBounds(startpos,0,startpos, -startpos,5,-startpos); mTerrainMesh->_setBounds(meshBounds); mTerrainEntity = Core::getSingleton().mSceneMgr->createEntity("TerrianMesh"); mTerrainNode->attachObject(mTerrainEntity); mTerrainEntity->setQueryFlags(QUERYMASK_TERRAIN); mTerrainNode->setPosition(0,0,0); //创建水面 tex = Ogre::TextureManager::getSingleton().getByName("reflection"); if(tex.isNull()) tex = Ogre::TextureManager::getSingleton().createManual("reflection", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, Ogre::TEX_TYPE_2D, 512, 512, 0, Ogre::PF_R8G8B8, Ogre::TU_RENDERTARGET); mReflectionTarget = tex->getBuffer()->getRenderTarget(); mReflectionTarget->addViewport(Core::getSingleton().mCamera)->setOverlaysEnabled(false); mReflectionTarget->addListener(this); // mat = Ogre::MaterialManager::getSingleton().getByName("ReflectionWater"); // tech = mat->getTechnique(0); // pass = tech->getPass(0); // tu = pass->getTextureUnitState(1); // tu->setTextureName(tex->getName()); mWaterPlane = Ogre::Plane(Ogre::Vector3::UNIT_Y, WATERHEIGHT); mWaterNode = Core::getSingleton().mSceneMgr->getRootSceneNode()->createChildSceneNode("WaterNode"); mWaterObject = Core::getSingleton().mSceneMgr->createManualObject("WaterObject"); mWaterObject->begin("DemoWater",Ogre::RenderOperation::OT_TRIANGLE_LIST); startpos += TILESIZE/2; for(int y = 0; y < terrainszie; y++) for(int x = 0; x < terrainszie; x++) { if(mMapData->getTerrainType(x -MAPBOLDER, y -MAPBOLDER ) == Water) { mWaterObject->position(startpos + x * TILESIZE, 0.0f, startpos + y * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(0.0f,0.0f); mWaterObject->position(startpos + (x+1) * TILESIZE, 0.0f, startpos + (y+1) * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(1.0f,1.0f); mWaterObject->position(startpos + (x+1) * TILESIZE, 0.0f, startpos + y * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(1.0f,0.0f); mWaterObject->position(startpos + (x+1) * TILESIZE, 0.0f, startpos + (y+1) * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(1.0f,1.0f); mWaterObject->position(startpos + x * TILESIZE, 0.0f, startpos + y * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(0.0f,0.0f); mWaterObject->position(startpos + x * TILESIZE, 0.0f, startpos + (y+1) * TILESIZE); mWaterObject->colour(1.0f,1.0f,1.0f); mWaterObject->normal(0.0f,1.0f,0.0f); mWaterObject->textureCoord(0.0f,1.0f); } } mWaterObject->end(); mWaterNode->attachObject(mWaterObject); mWaterNode->setPosition(0,WATERHEIGHT,0); //设置摄像机移动范围 float minx = 0.0f;// = ( - (float)(terrainszie - 2 * MAPBOLDER) / 2.0f - 1.0f) * TILESIZE ; getWorldCoords(0,0,minx,minx); minx -= TILESIZE/2; CameraContral::getSingleton().setMoveRect(minx, minx); CameraContral::getSingleton().resetCamera(); //深度投影测试 // Ogre::MeshManager::getSingleton().createPlane("testplane", Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME, // mWaterPlane, 64, 64, 1, 1, true, 1, 1, 1, Ogre::Vector3::UNIT_Z); // Ogre::Entity* testent = Core::getSingleton().mSceneMgr->createEntity("testplaneent", "testplane"); // testent->setMaterialName("DepthTest"); // Ogre::SceneNode* testnode = Core::getSingleton().mSceneMgr->getRootSceneNode()->createChildSceneNode(); // testnode->attachObject(testent); // testnode->setPosition(0.0f,10.0f,0.0f); return true; }