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(); } }
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; }