//------------------------------------------------------------------------------------------------ void VertexIndexToShape::addIndexData(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; HardwareIndexBufferSharedPtr ibuf = data->indexBuffer; const bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT); unsigned int index_offset = prev_size; if(use32bitindexes) { const unsigned int* pInt = static_cast<unsigned int*>(ibuf->lock(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(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(); } }
void GeomUtils::createCone(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData, float radius , float height, int nVerticesInBase) { assert(vertexData && indexData); // define the vertex format VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; // positions vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION); // allocate the vertex buffer vertexData->vertexCount = nVerticesInBase + 1; HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer - cone and base indexData->indexCount = (3 * nVerticesInBase) + (3 * (nVerticesInBase - 2)); indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); //Positions : cone head and base for (int i=0; i<3; i++) *pVertex++ = 0.0f; //Base : float fDeltaBaseAngle = (2 * Math::PI) / nVerticesInBase; for (int i=0; i<nVerticesInBase; i++) { float angle = i * fDeltaBaseAngle; *pVertex++ = radius * cosf(angle); *pVertex++ = height; *pVertex++ = radius * sinf(angle); } //Indices : //Cone head to vertices for (int i=0; i<nVerticesInBase; i++) { *pIndices++ = 0; *pIndices++ = (i%nVerticesInBase) + 1; *pIndices++ = ((i+1)%nVerticesInBase) + 1; } //Cone base for (int i=0; i<nVerticesInBase-2; i++) { *pIndices++ = 1; *pIndices++ = i + 3; *pIndices++ = i + 2; } // Unlock vBuf->unlock(); iBuf->unlock(); }
void DebugRectangle2D::setCorners(Real left, Real top, Real right, Real bottom) { VertexDeclaration * const decl = mRenderOp.vertexData->vertexDeclaration; const VertexElement* poselem = decl->findElementBySemantic(VES_POSITION); const VertexElement* colorelem = decl->findElementBySemantic(VES_DIFFUSE); HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING); const size_t vertexSize = vbuf->getVertexSize (); float *pPos; RGBA *pColor; Root * const root = Root::getSingletonPtr(); uchar* pMain = static_cast<uchar *>( vbuf->lock(HardwareBuffer::HBL_DISCARD)); // #define V3(AX, AY, AZ, ACOLOR) poselem->baseVertexPointerToElement(pMain, &pPos); \ // *pPos++ = AX; *pPos++ = AY; *pPos++ = AZ; \ // pMain += vertexSize; #define V3(A_X, A_Y, A_Z, ACOLOR) poselem->baseVertexPointerToElement(pMain, &pPos); \ *pPos++ = static_cast <float> (A_X); \ *pPos++ = static_cast <float> (A_Y); \ *pPos++ = static_cast <float> (A_Z); \ colorelem->baseVertexPointerToElement(pMain, &pColor); \ root->convertColourValue (ACOLOR, pColor); \ pMain += vertexSize; V3(left, top, -1.0f, ColourValue::White) V3(left, bottom, -1.0f, ColourValue::White) V3(right, bottom, -1.0f, ColourValue::White) V3(right, top, -1.0f, ColourValue::White) vbuf->unlock(); HardwareIndexBufferSharedPtr iBuf = mRenderOp.indexData->indexBuffer; ushort* pIdx = static_cast<ushort*>( iBuf->lock(0, iBuf->getSizeInBytes(),HardwareBuffer::HBL_DISCARD)); *pIdx++ = static_cast<ushort> (0); *pIdx++ = static_cast<ushort> (1); // line 1 *pIdx++ = static_cast<ushort> (1); *pIdx++ = static_cast<ushort> (2);// line 2 *pIdx++ = static_cast<ushort> (2); *pIdx++ = static_cast<ushort> (3);// line 3 *pIdx++ = static_cast<ushort> (3); *pIdx++ = static_cast<ushort> (0);// line 4 iBuf->unlock(); }
void createSphere(const std::string& strName, const float r, const int nRings = 16, const int nSegments = 16) { MeshPtr pSphere = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *pSphereVertex = pSphere->createSubMesh(); pSphere->sharedVertexData = new VertexData(); VertexData* vertexData = pSphere->sharedVertexData; // define the vertex format VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // two dimensional texture coordinates vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); currOffset += VertexElement::getTypeSize(VET_FLOAT2); // allocate the vertex buffer vertexData->vertexCount = (nRings + 1) * (nSegments + 1); HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer pSphereVertex->indexData->indexCount = 6 * nRings * (nSegments + 1); pSphereVertex->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, pSphereVertex->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = pSphereVertex->indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); float fDeltaRingAngle = (Math::PI / nRings); float fDeltaSegAngle = (2 * Math::PI / nSegments); unsigned short wVerticeIndex = 0; // Generate the group of rings for the sphere for (int ring = 0; ring <= nRings; ring++) { float r0 = r * sinf(ring * fDeltaRingAngle); float y0 = r * cosf(ring * fDeltaRingAngle); // Generate the group of segments for the current ring for (int seg = 0; seg <= nSegments; seg++) { float x0 = r0 * sinf(seg * fDeltaSegAngle); float z0 = r0 * cosf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere *pVertex++ = x0; *pVertex++ = y0; *pVertex++ = z0; Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy(); *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z; *pVertex++ = (float)seg / (float)nSegments; *pVertex++ = (float)ring / (float)nRings; if (ring != nRings) { // each vertex (except the last) has six indices pointing to it *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex; *pIndices++ = wVerticeIndex + nSegments; *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex + 1; *pIndices++ = wVerticeIndex; wVerticeIndex++; } }; // end for seg } // end for ring // Unlock vBuf->unlock(); iBuf->unlock(); // Generate face list pSphereVertex->useSharedVertices = true; // the original code was missing this line: pSphere->_setBounds(AxisAlignedBox(Vector3(-r, -r, -r), Vector3(r, r, r)), false); pSphere->_setBoundingSphereRadius(r); // this line makes clear the mesh is loaded (avoids memory leaks) pSphere->load(); }
void SurfacePatchRenderable::createHardwareBuffers() { VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( mRenderOp.vertexData->vertexDeclaration->getVertexSize(0), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); bind->setBinding(0, vbuf); HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_32BIT, // type of index mRenderOp.indexData->indexCount, // number of indexes HardwareBuffer::HBU_STATIC_WRITE_ONLY, // usage false); // no shadow buffer mRenderOp.indexData->indexBuffer = ibuf; Vector3 vaabMin(std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max(), std::numeric_limits<Real>::max()); Vector3 vaabMax(0.0, 0.0, 0.0); Real* prPos = static_cast<Real*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); const float textureWeights[3][3] = {{1, 0, 0}, {0, 1, 0}, {0, 0, 1}}; /*const int textureNumberOffsets[3][3] = {{0, 1, 2}, {-1, 0, 1}, {-2, -1, 0}};*/ for (int v = 0; v < patch->numVertices * 2; v += 2) { // Position *prPos++ = patch->vertices[v].x; *prPos++ = patch->vertices[v].y; *prPos++ = patch->vertices[v].z; // Normal *prPos++ = patch->vertices[v+1].x; *prPos++ = patch->vertices[v+1].y; *prPos++ = patch->vertices[v+1].z; // texture weights const int curIndex = patch->vertNumbers[v/2]; const int posInTriangle = curIndex % 3; *prPos++ = textureWeights[posInTriangle][0]; *prPos++ = textureWeights[posInTriangle][1]; *prPos++ = textureWeights[posInTriangle][2]; // texture numbers for (int i = 0; i < posInTriangle; i++) *prPos++ = patch->textures[patch->indices[curIndex - (posInTriangle - i)]]; *prPos++ = patch->textures[patch->indices[curIndex]]; for (int i = posInTriangle + 1; i < 3; i++) *prPos++ = patch->textures[patch->indices[curIndex + (i - posInTriangle)]]; // texture numbers //*prPos++ = patch->textures[(v/2)/3*3 + 0] + 0.5f; // 0.5f: number between 0 and 1 as offset because in the shader, //*prPos++ = patch->textures[(v/2)/3*3 + 1] + 0.5f; // floor() is used to determine the texture number as integer and this is //*prPos++ = patch->textures[(v/2)/3*3 + 2] + 0.5f; // much too imprecise if the real texture numbers are passed in! // Adjust bounding box ... if (patch->vertices[v].x < vaabMin.x) vaabMin.x = patch->vertices[v].x; if (patch->vertices[v].y < vaabMin.y) vaabMin.y = patch->vertices[v].y; if (patch->vertices[v].z < vaabMin.z) vaabMin.z = patch->vertices[v].z; if (patch->vertices[v].x > vaabMax.x) vaabMax.x = patch->vertices[v].x; if (patch->vertices[v].y > vaabMax.y) vaabMax.y = patch->vertices[v].y; if (patch->vertices[v].z > vaabMax.z) vaabMax.z = patch->vertices[v].z; } vbuf->unlock(); mBox.setExtents(vaabMin, vaabMax); Ogre::uint* pIdx = static_cast<Ogre::uint*>(ibuf->lock(HardwareBuffer::HBL_DISCARD)); for (int i = 0; i < patch->numIndices; i++) { *pIdx++ = patch->indices[i]; } ibuf->unlock(); // Clean up the surface patch as much as possible delete[] patch->textures; delete[] patch->vertNumbers; }
//----------------------------------------------------------------------- void MeshManager::tesselate2DMesh(SubMesh* sm, unsigned short meshWidth, unsigned short meshHeight, bool doubleSided, HardwareBuffer::Usage indexBufferUsage, bool indexShadowBuffer) { // The mesh is built, just make a list of indexes to spit out the triangles unsigned short vInc, v, iterations; if (doubleSided) { iterations = 2; vInc = 1; v = 0; // Start with front } else { iterations = 1; vInc = 1; v = 0; } // Allocate memory for faces // Num faces, width*height*2 (2 tris per square), index count is * 3 on top sm->indexData->indexCount = (meshWidth-1) * (meshHeight-1) * 2 * iterations * 3; sm->indexData->indexBuffer = HardwareBufferManager::getSingleton(). createIndexBuffer(HardwareIndexBuffer::IT_16BIT, sm->indexData->indexCount, indexBufferUsage, indexShadowBuffer); unsigned short v1, v2, v3; //bool firstTri = true; HardwareIndexBufferSharedPtr ibuf = sm->indexData->indexBuffer; // Lock the whole buffer unsigned short* pIndexes = static_cast<unsigned short*>( ibuf->lock(HardwareBuffer::HBL_DISCARD) ); while (iterations--) { // Make tris in a zigzag pattern (compatible with strips) unsigned short u = 0; unsigned short uInc = 1; // Start with moving +u unsigned short vCount = meshHeight - 1; while (vCount--) { unsigned short uCount = meshWidth - 1; while (uCount--) { // First Tri in cell // ----------------- v1 = ((v + vInc) * meshWidth) + u; v2 = (v * meshWidth) + u; v3 = ((v + vInc) * meshWidth) + (u + uInc); // Output indexes *pIndexes++ = v1; *pIndexes++ = v2; *pIndexes++ = v3; // Second Tri in cell // ------------------ v1 = ((v + vInc) * meshWidth) + (u + uInc); v2 = (v * meshWidth) + u; v3 = (v * meshWidth) + (u + uInc); // Output indexes *pIndexes++ = v1; *pIndexes++ = v2; *pIndexes++ = v3; // Next column u += uInc; } // Next row v += vInc; u = 0; } // Reverse vInc for double sided v = meshHeight - 1; vInc = -vInc; } // Unlock ibuf->unlock(); }
void GeomUtils::createSphere(VertexData*& vertexData, IndexData*& indexData , float radius , int nRings, int nSegments , bool bNormals , bool bTexCoords) { assert(vertexData && indexData); // define the vertex format VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); if (bNormals) { // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); } // two dimensional texture coordinates if (bTexCoords) { vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); } // allocate the vertex buffer vertexData->vertexCount = (nRings + 1) * (nSegments+1); HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer indexData->indexCount = 6 * nRings * (nSegments + 1); indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); float fDeltaRingAngle = (Math::PI / nRings); float fDeltaSegAngle = (2 * Math::PI / nSegments); unsigned short wVerticeIndex = 0 ; // Generate the group of rings for the sphere for( int ring = 0; ring <= nRings; ring++ ) { float r0 = radius * sinf (ring * fDeltaRingAngle); float y0 = radius * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(int seg = 0; seg <= nSegments; seg++) { float x0 = r0 * sinf(seg * fDeltaSegAngle); float z0 = r0 * cosf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere *pVertex++ = x0; *pVertex++ = y0; *pVertex++ = z0; if (bNormals) { Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy(); *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z; } if (bTexCoords) { *pVertex++ = (float) seg / (float) nSegments; *pVertex++ = (float) ring / (float) nRings; } if (ring != nRings) { // each vertex (except the last) has six indices pointing to it *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex; *pIndices++ = wVerticeIndex + nSegments; *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex + 1; *pIndices++ = wVerticeIndex; wVerticeIndex ++; } }; // end for seg } // end for ring // Unlock vBuf->unlock(); iBuf->unlock(); }
void createSphereMesh(const String &name, const float radius, const int slices, const int stacks) { MeshPtr mesh = MeshManager::getSingleton().createManual(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); mesh->sharedVertexData = new VertexData(); mesh->_setBounds(AxisAlignedBox(Vector3(-radius, -radius, -radius), Vector3(radius, radius, radius))); mesh->_setBoundingSphereRadius(radius); VertexData *vertexData = mesh->sharedVertexData; vertexData->vertexDeclaration->addElement(0, 0, VET_FLOAT3, VES_POSITION); vertexData->vertexDeclaration->addElement(1, 0, VET_FLOAT3, VES_NORMAL); vertexData->vertexCount = slices * (stacks + 1); HardwareVertexBufferSharedPtr positionBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( vertexData->vertexDeclaration->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); HardwareVertexBufferSharedPtr normalBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( vertexData->vertexDeclaration->getVertexSize(1), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); float *position = static_cast<float *>(positionBuffer->lock(HardwareBuffer::HBL_DISCARD)); float *normal = static_cast<float *>(normalBuffer->lock(HardwareBuffer::HBL_DISCARD)); for (int ring = 0; ring <= stacks; ring++) { float r = radius * sinf(ring * Math::PI / stacks); float y = radius * cosf(ring * Math::PI / stacks); for (int segment = 0; segment < slices; segment++) { float x = r * sinf(segment * 2 * Math::PI / slices); float z = r * cosf(segment * 2 * Math::PI / slices); *position++ = x; *position++ = y; *position++ = z; Vector3 tmp = Vector3(x, y, z).normalisedCopy(); *normal++ = tmp.x; *normal++ = tmp.y; *normal++ = tmp.z; } } positionBuffer->unlock(); normalBuffer->unlock(); vertexData->vertexBufferBinding->setBinding(0, positionBuffer); vertexData->vertexBufferBinding->setBinding(1, normalBuffer); SubMesh *subMesh = mesh->createSubMesh(); subMesh->useSharedVertices = true; IndexData *indexData = subMesh->indexData; indexData->indexCount = 6 * slices * stacks; HardwareIndexBufferSharedPtr indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); unsigned short *index = static_cast<unsigned short *>(indexBuffer->lock(HardwareBuffer::HBL_DISCARD)); unsigned short i = 0; for (int ring = 0; ring < stacks; ring++) { for (int segment = 0; segment < slices - 1; segment++) { *index++ = i; *index++ = i + slices; *index++ = i + slices + 1; *index++ = i; *index++ = i + slices + 1; *index++ = i + 1; i++; } *index++ = i; *index++ = i + slices; *index++ = i + 1; *index++ = i; *index++ = i + 1; *index++ = i + 1 - slices; i++; } indexBuffer->unlock(); indexData->indexBuffer = indexBuffer; mesh->load(); }
//--------------------------------------------------------------------- void TangentSpaceCalc::processFaces(Result& result) { // Quick pre-check for triangle strips / fans for (OpTypeList::iterator ot = mOpTypes.begin(); ot != mOpTypes.end(); ++ot) { if (*ot != RenderOperation::OT_TRIANGLE_LIST) { // Can't split strips / fans setSplitMirrored(false); setSplitRotated(false); } } for (size_t i = 0; i < mIDataList.size(); ++i) { IndexData* i_in = mIDataList[i]; RenderOperation::OperationType opType = mOpTypes[i]; // Read data from buffers uint16 *p16 = 0; uint32 *p32 = 0; HardwareIndexBufferSharedPtr ibuf = i_in->indexBuffer; if (ibuf->getType() == HardwareIndexBuffer::IT_32BIT) { p32 = static_cast<uint32*>( ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); // offset by index start p32 += i_in->indexStart; } else { p16 = static_cast<uint16*>( ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); // offset by index start p16 += i_in->indexStart; } // current triangle size_t vertInd[3] = { 0, 0, 0 }; // loop through all faces to calculate the tangents and normals size_t faceCount = opType == RenderOperation::OT_TRIANGLE_LIST ? i_in->indexCount / 3 : i_in->indexCount - 2; for (size_t f = 0; f < faceCount; ++f) { bool invertOrdering = false; // Read 1 or 3 indexes depending on type if (f == 0 || opType == RenderOperation::OT_TRIANGLE_LIST) { vertInd[0] = p32? *p32++ : *p16++; vertInd[1] = p32? *p32++ : *p16++; vertInd[2] = p32? *p32++ : *p16++; } else if (opType == RenderOperation::OT_TRIANGLE_FAN) { // Element 0 always remains the same // Element 2 becomes element 1 vertInd[1] = vertInd[2]; // read new into element 2 vertInd[2] = p32? *p32++ : *p16++; } else if (opType == RenderOperation::OT_TRIANGLE_STRIP) { // Shunt everything down one, but also invert the ordering on // odd numbered triangles (== even numbered i's) // we interpret front as anticlockwise all the time but strips alternate if (f & 0x1) { // odd tris (index starts at 3, 5, 7) invertOrdering = true; } vertInd[0] = vertInd[1]; vertInd[1] = vertInd[2]; vertInd[2] = p32? *p32++ : *p16++; } // deal with strip inversion of winding size_t localVertInd[3]; localVertInd[0] = vertInd[0]; if (invertOrdering) { localVertInd[1] = vertInd[2]; localVertInd[2] = vertInd[1]; } else { localVertInd[1] = vertInd[1]; localVertInd[2] = vertInd[2]; } // For each triangle // Calculate tangent & binormal per triangle // Note these are not normalised, are weighted by UV area Vector3 faceTsU, faceTsV, faceNorm; calculateFaceTangentSpace(localVertInd, faceTsU, faceTsV, faceNorm); // Skip invalid UV space triangles if (faceTsU.isZeroLength() || faceTsV.isZeroLength()) continue; addFaceTangentSpaceToVertices(i, f, localVertInd, faceTsU, faceTsV, faceNorm, result); } ibuf->unlock(); } }
// ------------------------------------------------------------------------ void ShadowCaster::generateShadowVolume(EdgeData* edgeData, const HardwareIndexBufferSharedPtr& indexBuffer, const Light* light, ShadowRenderableList& shadowRenderables, unsigned long flags) { // Edge groups should be 1:1 with shadow renderables assert(edgeData->edgeGroups.size() == shadowRenderables.size()); EdgeData::EdgeGroupList::const_iterator egi, egiend; ShadowRenderableList::const_iterator si; Light::LightTypes lightType = light->getType(); // Lock index buffer for writing unsigned short* pIdx = static_cast<unsigned short*>( indexBuffer->lock(HardwareBuffer::HBL_DISCARD)); size_t numIndices = 0; // Iterate over the groups and form renderables for each based on their // lightFacing si = shadowRenderables.begin(); egiend = edgeData->edgeGroups.end(); for (egi = edgeData->edgeGroups.begin(); egi != egiend; ++egi, ++si) { const EdgeData::EdgeGroup& eg = *egi; // Initialise the index start for this shadow renderable IndexData* indexData = (*si)->getRenderOperationForUpdate()->indexData; indexData->indexStart = numIndices; // original number of verts (without extruded copy) size_t originalVertexCount = eg.vertexData->vertexCount; bool firstDarkCapTri = true; unsigned short darkCapStart; EdgeData::EdgeList::const_iterator i, iend; iend = eg.edges.end(); for (i = eg.edges.begin(); i != iend; ++i) { const EdgeData::Edge& edge = *i; // Silhouette edge, when two tris has opposite light facing, or // degenerate edge where only tri 1 is valid and the tri light facing char lightFacing = edgeData->triangleLightFacings[edge.triIndex[0]]; if ((edge.degenerate && lightFacing) || (!edge.degenerate && (lightFacing != edgeData->triangleLightFacings[edge.triIndex[1]]))) { size_t v0 = edge.vertIndex[0]; size_t v1 = edge.vertIndex[1]; if (!lightFacing) { // Inverse edge indexes when t1 is light away std::swap(v0, v1); } /* Note edge(v0, v1) run anticlockwise along the edge from the light facing tri so to point shadow volume tris outward, light cap indexes have to be backwards We emit 2 tris if light is a point light, 1 if light is directional, because directional lights cause all points to converge to a single point at infinity. First side tri = near1, near0, far0 Second tri = far0, far1, near1 'far' indexes are 'near' index + originalVertexCount because 'far' verts are in the second half of the buffer */ *pIdx++ = v1; *pIdx++ = v0; *pIdx++ = v0 + originalVertexCount; numIndices += 3; // Are we extruding to infinity? if (!(lightType == Light::LT_DIRECTIONAL && flags & SRF_EXTRUDE_TO_INFINITY)) { // additional tri to make quad *pIdx++ = v0 + originalVertexCount; *pIdx++ = v1 + originalVertexCount; *pIdx++ = v1; numIndices += 3; } // Do dark cap tri // Use McGuire et al method, a triangle fan covering all silhouette // edges and one point (taken from the initial tri) if (flags & SRF_INCLUDE_DARK_CAP) { if (firstDarkCapTri) { darkCapStart = v0 + originalVertexCount; firstDarkCapTri = false; } else { *pIdx++ = darkCapStart; *pIdx++ = v1 + originalVertexCount; *pIdx++ = v0 + originalVertexCount; numIndices += 3; } } } } // Do light cap if (flags & SRF_INCLUDE_LIGHT_CAP) { // separate light cap? if ((*si)->isLightCapSeparate()) { // update index count for this shadow renderable indexData->indexCount = numIndices - indexData->indexStart; // get light cap index data for update indexData = (*si)->getLightCapRenderable()->getRenderOperationForUpdate()->indexData; // start indexes after the current total indexData->indexStart = numIndices; } // Iterate over the triangles which are using this vertex set EdgeData::TriangleList::const_iterator ti, tiend; EdgeData::TriangleLightFacingList::const_iterator lfi; ti = edgeData->triangles.begin() + eg.triStart; tiend = ti + eg.triCount; lfi = edgeData->triangleLightFacings.begin() + eg.triStart; for ( ; ti != tiend; ++ti, ++lfi) { const EdgeData::Triangle& t = *ti; assert(t.vertexSet == eg.vertexSet); // Check it's light facing if (*lfi) { *pIdx++ = t.vertIndex[0]; *pIdx++ = t.vertIndex[1]; *pIdx++ = t.vertIndex[2]; numIndices += 3; } } } // update index count for current index data (either this shadow renderable or its light cap) indexData->indexCount = numIndices - indexData->indexStart; } // Unlock index buffer indexBuffer->unlock(); // In debug mode, check we didn't overrun the index buffer assert(numIndices <= indexBuffer->getNumIndexes() && "Index buffer overrun while generating shadow volume!! " "You must increase the size of the shadow index buffer."); }
//----------------------------------------------------------------------------------------- bool TemplateUtils::getMeshInformation(const Mesh* mesh, size_t &vertex_count, OgreVector3Array &vertices, size_t &index_count, LongArray &indices, const Vector3 position, const Quaternion &orient, const 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) { SubMesh* submesh = mesh->getSubMesh(i); if(!submesh) { Exception(Exception::ERR_INTERNAL_ERROR,"Could not load submesh at index :" + i,"Mesh::getSubMesh"); } // 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 // NO VALID DATA SHOULD BE PRESENT IN THE FOLLOWING 2 ARRAYS // UNTIL AFTER THE NEXT FOR LOOP /* vertices = new Ogre::Vector3 [vertex_count]; std::vector<Ogre::Vector3> vertices [vertex_count]; indices = new unsigned long [index_count]; std::vector<long> indices [index_count]; */ vertices.resize(vertex_count); indices.resize(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) { SubMesh* submesh = mesh->getSubMesh(i); if(!submesh) { Exception(Exception::ERR_INTERNAL_ERROR,"Could not load submesh at index :" + i,"Mesh::getSubMesh"); } VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !added_shared)) { if(submesh->useSharedVertices) { added_shared = true; shared_offset = current_offset; } const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double // as second argument. So make it float, to avoid trouble when Ogre::Real 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); Vector3 pt(pReal[0], pReal[1], pReal[2]); vertices[current_offset + j] = (orient * (pt * scale)) + position; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT); unsigned int* pLong = static_cast<unsigned int*>(ibuf->lock(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; } return true; }
static MeshPtr importObject(QDataStream &stream) { using namespace Ogre; QVector4D bbMin, bbMax; stream >> bbMin >> bbMax; float distance, distanceSquared; // Here's a bug for you: writes "double"'s instead of floats stream >> distanceSquared >> distance; MeshPtr ogreMesh = MeshManager::getSingleton().createManual("conversion", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); int vertexCount, indexCount; stream >> vertexCount >> indexCount; VertexData *vertexData = new VertexData(); ogreMesh->sharedVertexData = vertexData; LogManager::getSingleton().logMessage("Reading geometry..."); VertexDeclaration* decl = vertexData->vertexDeclaration; VertexBufferBinding* bind = vertexData->vertexBufferBinding; unsigned short bufferId = 0; // Information for calculating bounds Vector3 min = Vector3::ZERO, max = Vector3::UNIT_SCALE, pos = Vector3::ZERO; Real maxSquaredRadius = -1; bool firstVertex = true; /* Create a vertex definition for our buffer */ size_t offset = 0; const VertexElement &positionElement = decl->addElement(bufferId, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); const VertexElement &normalElement = decl->addElement(bufferId, offset, VET_FLOAT3, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT3); // calculate how many vertexes there actually are vertexData->vertexCount = vertexCount; // Now create the vertex buffer HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer(offset, vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); // Bind it bind->setBinding(bufferId, vbuf); // Lock it unsigned char *pVert = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); unsigned char *pVertStart = pVert; QVector<float> positions; positions.reserve(vertexCount * 3); // Iterate over all children (vertexbuffer entries) for (int i = 0; i < vertexCount; ++i) { float *pFloat; QVector4D vertex; stream >> vertex; vertex.setZ(vertex.z() * -1); /* Copy over the position */ positionElement.baseVertexPointerToElement(pVert, &pFloat); *(pFloat++) = (float)vertex.x(); *(pFloat++) = (float)vertex.y(); *(pFloat++) = (float)vertex.z(); positions.append(vertex.x()); positions.append(vertex.y()); positions.append(vertex.z()); /* While we're at it, calculate the bounding sphere */ pos.x = vertex.x(); pos.y = vertex.y(); pos.z = vertex.z(); if (firstVertex) { min = max = pos; maxSquaredRadius = pos.squaredLength(); firstVertex = false; } else { min.makeFloor(pos); max.makeCeil(pos); maxSquaredRadius = qMax(pos.squaredLength(), maxSquaredRadius); } pVert += vbuf->getVertexSize(); } // Set bounds const AxisAlignedBox& currBox = ogreMesh->getBounds(); Real currRadius = ogreMesh->getBoundingSphereRadius(); if (currBox.isNull()) { //do not pad the bounding box ogreMesh->_setBounds(AxisAlignedBox(min, max), false); ogreMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredRadius)); } else { AxisAlignedBox newBox(min, max); newBox.merge(currBox); //do not pad the bounding box ogreMesh->_setBounds(newBox, false); ogreMesh->_setBoundingSphereRadius(qMax(Math::Sqrt(maxSquaredRadius), currRadius)); } /* Create faces */ // All children should be submeshes SubMesh* sm = ogreMesh->createSubMesh(); sm->setMaterialName("clippingMaterial"); sm->operationType = RenderOperation::OT_TRIANGLE_LIST; sm->useSharedVertices = true; // tri list sm->indexData->indexCount = indexCount; // Allocate space HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, sm->indexData->indexCount, HardwareBuffer::HBU_DYNAMIC, false); sm->indexData->indexBuffer = ibuf; unsigned short *pShort = static_cast<unsigned short*>(ibuf->lock(HardwareBuffer::HBL_DISCARD)); QVector<EdgeData::Triangle> triangles(indexCount / 3); for (int i = 0; i < indexCount / 3; ++i) { quint16 i1, i2, i3; stream >> i1 >> i2 >> i3; *pShort++ = i1; *pShort++ = i2; *pShort++ = i3; triangles[i].vertIndex[0] = i1; triangles[i].vertIndex[1] = i2; triangles[i].vertIndex[2] = i3; } /* Recalculate the vertex normals */ Vector4 *faceNormals = (Vector4*)_aligned_malloc(sizeof(Vector4) * triangles.size(), 16); OptimisedUtil *util = OptimisedUtil::getImplementation(); util->calculateFaceNormals(positions.constData(), triangles.data(), faceNormals, indexCount / 3); // Iterate over all children (vertexbuffer entries) pVert = pVertStart; for (int i = 0; i < vertexCount; ++i) { float *pFloat; Vector3 normal = Vector3::ZERO; int count = 0; /* Search for all faces that use this vertex */ for (int j = 0; j < triangles.size(); ++j) { if (triangles[j].vertIndex[0] == i || triangles[j].vertIndex[1] == i || triangles[j].vertIndex[2] == i) { normal.x += faceNormals[j].x / faceNormals[j].w; normal.y += faceNormals[j].y / faceNormals[j].w; normal.z += faceNormals[j].z / faceNormals[j].w; count++; } } normal.normalise(); /* Copy over the position */ normalElement.baseVertexPointerToElement(pVert, &pFloat); *(pFloat++) = normal.x; *(pFloat++) = normal.y; *(pFloat++) = normal.z; pVert += vbuf->getVertexSize(); } _aligned_free(faceNormals); vbuf->unlock(); ibuf->unlock(); return ogreMesh; }
// Generate normals for polygon meshes void IndexedGeometry::createIndexedFaceSet() { if (_coords.empty()) throw std::runtime_error("No coordinates given."); if (_coordIndex.empty()) throw std::runtime_error("No coordinate index given."); MeshPtr mesh = MeshManager::getSingleton().createManual(_name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *sub = mesh->createSubMesh(); bool hasTextureCoordinates = !_texCoords.empty(); bool hasPointColors = !_colors.empty() && _colorPerVertex; bool hasPointNormals = !_normals.empty() && _normalPerVertex; bool hasCellColors = !_colors.empty() && !hasPointColors; bool hasCellNormals = !_normals.empty() && !hasPointNormals; bool calcPointNormals = _normals.empty() && _normalPerVertex; std::vector<face> faces; face f; for (std::vector<int>::const_iterator I=_coordIndex.begin(); I !=_coordIndex.end(); ++I) { if (*I == -1) { faces.resize(faces.size()+1); faces.back().indices.swap(f.indices); } else f.indices.push_back(I - _coordIndex.begin()); } if (!f.indices.empty()) { faces.resize(faces.size()+1); faces.back().indices.swap(f.indices); } std::vector<vertex> vertices; std::vector<triangle> triangles; VertMap vertexMap; // triangulate and expand vertices for (std::vector<face>::const_iterator f=faces.begin(), e=faces.end(); f!=e; ++f) { int faceNr = f - faces.begin(); int triVertNr = 0; int triVerts[2] = { -1, -1 }; for (std::vector<int>::const_iterator i = f->indices.begin(), e=f->indices.end(); i!=e; ++i, ++triVertNr) { int triVertNr = i - f->indices.begin(); int index = *i; vertex vert; // get full indices for vertex data vert.pos = _coordIndex[index]; vert.normal = !_normals.empty() ? getIndex(_coordIndex, _normalIndex, _normalPerVertex, faceNr, index) : 0; vert.colour = !_colors.empty() ? getIndex(_coordIndex, _colorIndex, _colorPerVertex, faceNr, index) : 0; vert.tc = hasTextureCoordinates ? getIndex(_coordIndex, _texCoordIndex, true, faceNr, index) : 0; // avoid duplication //int nvert = vertexMap.size(); //int &vpos = vertexMap[vert]; //if (nvert != vertexMap.size()) { int vpos = vertices.size(); vertices.push_back(vert); //} // emit triangle (maybe) if (triVertNr == 0) triVerts[0] = vpos; else if (triVertNr == 1) triVerts[1] = vpos; else { triangle t; t.vertices[0] = triVerts[0]; t.vertices[1] = triVerts[1]; t.vertices[2] = vpos; if (!_ccw) std::swap(t.vertices[1], t.vertices[2]); triangles.push_back(t); triVerts[1] = vpos; } } } // createOgreMesh int nvertices = vertices.size(); int nfaces = triangles.size(); VertexData* vertexData = new VertexData(); sub->vertexData = vertexData; IndexData* indexData = sub->indexData; VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); if (hasPointNormals) { // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); } // two dimensional texture coordinates if (hasTextureCoordinates) { vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); currOffset += VertexElement::getTypeSize(VET_FLOAT2); } std::cout << std::endl; // allocate index buffer indexData->indexCount = nfaces * 3; indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); std::cout << triangles.size() << ": "; for(std::vector<triangle>::const_iterator T = triangles.begin(); T != triangles.end(); T++) { const triangle &t = (*T); *pIndices++ = t.vertices[0]; *pIndices++ = t.vertices[1]; *pIndices++ = t.vertices[2]; std::cout << t.vertices[0] << " " << t.vertices[1] << " " << t.vertices[2] << " "; } std::cout << std::endl; // allocate the vertex buffer vertexData->vertexCount = nvertices; HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); AxisAlignedBox aabox; std::cout << vertices.size() << ": "; for(std::vector<vertex>::const_iterator V = vertices.begin(); V != vertices.end(); V++) { const vertex &v = (*V); SFVec3f pos = _coords.at(v.pos); *pVertex++ = pos.x; *pVertex++ = pos.y; *pVertex++ = pos.z; aabox.merge(Vector3(pos.x, pos.y, pos.z)); std::cout << pos.x << " " << pos.y << " " << pos.z << " " << std::endl; //std::cout << v.pos << " "; if (hasPointNormals) { const SFVec3f normal = _normals.at(v.normal); *pVertex++ = normal.x; *pVertex++ = normal.y; *pVertex++ = normal.z; } } std::cout << std::endl; // Unlock vBuf->unlock(); iBuf->unlock(); sub->useSharedVertices = false; // the original code was missing this line: mesh->_setBounds(aabox); mesh->_setBoundingSphereRadius((aabox.getMaximum()-aabox.getMinimum()).length()/2.0); // this line makes clear the mesh is loaded (avoids memory leaks) mesh->load(); }
void OgreToBulletMesh::getMeshInformation(MeshPtr mesh, unsigned& vertex_count, std::vector<Vector3>& vertices, unsigned& index_count, std::vector<unsigned>& indices, const Vector3& position, const Quaternion& orientation, const Vector3& scale) { bool added_shared = false; unsigned current_offset = 0; unsigned shared_offset = 0; unsigned next_offset = 0; unsigned index_offset = 0; vertex_count = index_count = 0; for (uint16_t i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* submesh = mesh->getSubMesh(i); if (submesh->useSharedVertices) { if (!added_shared) { vertex_count += mesh->sharedVertexData->vertexCount; added_shared = true; } } else vertex_count += submesh->vertexData->vertexCount; index_count += submesh->indexData->indexCount; } vertices.clear(); vertices.reserve(vertex_count); indices.clear(); indices.reserve(index_count); added_shared = false; for (uint16_t i = 0; i < mesh->getNumSubMeshes(); ++i) { SubMesh* submesh = mesh->getSubMesh(i); VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; if (!submesh->useSharedVertices || (submesh->useSharedVertices && !added_shared)) { if (submesh->useSharedVertices) { added_shared = true; shared_offset = current_offset; } const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(VertexElementSemantic::VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); uint8_t* vertex = (uint8_t*)vbuf->lock(HardwareBuffer::LockOptions::HBL_READ_ONLY); float* pReal; for (int j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Vector3 pt(pReal[0], pReal[1], pReal[2]); vertices[current_offset + j] = (orientation * (pt * scale)) + position; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } IndexData* index_data = submesh->indexData; uint numTris = index_data->indexCount / 3; HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IndexType::IT_32BIT); uint* pLong = (uint*)ibuf->lock(HardwareBuffer::LockOptions::HBL_READ_ONLY); ushort* pShort = (ushort*)pLong; uint offset = submesh->useSharedVertices ? shared_offset : current_offset; if (use32bitindexes) for (int k = 0; k < index_data->indexCount; ++k) indices[index_offset++] = pLong[k] + offset; else for (int k = 0; k < index_data->indexCount; ++k) indices[index_offset++] = (uint)pShort[k] + (uint)offset; ibuf->unlock(); current_offset = next_offset; } }
/// reads out mesh vertices and indices /// must be called before rayintersect if the mesh has moved/deformed, probably every frame for animated meshes and mousepicking /// calling it once for static meshes is enough /// code is based on OgreOpCode MeshCollisionShape::convertMeshData void MeshShape::Update (Ogre::Entity *pEntity) { // if (!pEntity) return; if (mpMesh.isNull()) return; if (pEntity && mbInitialised && !pEntity->hasSkeleton()) return; // no need to update static models every frame... mbInitialised = true; //printf("#### MeshShape::Update\n"); //printf("MeshShape::Update skeleton=%d\n",pEntity->hasSkeleton()?1:0); //assert(pEntity->getMesh().get() == mpMesh.get() && "mesh pointer changed ! (ogrecaching/garbage collection?)"); mlVertices.clear(); mlIndices.clear(); bool added_shared = false; size_t current_offset = 0; size_t shared_offset = 0; size_t next_offset = 0; size_t index_offset = 0; int numOfSubs = 0; // true if the entity is possibly animated (=has skeleton) , this means Update should be called every frame bool useSoftwareBlendingVertices = pEntity && pEntity->hasSkeleton(); if (useSoftwareBlendingVertices) { pEntity->_updateAnimation(); } // Run through the submeshes again, adding the data into the arrays for ( size_t i = 0; i < mpMesh->getNumSubMeshes(); ++i) { SubMesh* submesh = mpMesh->getSubMesh(i); bool useSharedVertices = submesh->useSharedVertices; //---------------------------------------------------------------- // GET VERTEXDATA //---------------------------------------------------------------- const VertexData * vertex_data; if(useSoftwareBlendingVertices) vertex_data = useSharedVertices ? pEntity->_getSkelAnimVertexData() : pEntity->getSubEntity(i)->_getSkelAnimVertexData(); else vertex_data = useSharedVertices ? mpMesh->sharedVertexData : submesh->vertexData; if((!useSharedVertices)||(useSharedVertices && !added_shared)) { if(useSharedVertices) { added_shared = true; shared_offset = current_offset; } const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); // There is _no_ baseVertexPointerToElement() which takes an Ogre::Real or a double // as second argument. So make it float, to avoid trouble when Ogre::Real is // comiled/typedefed as double: float* pReal; mlVertices.reserve(mlVertices.size()+vertex_data->vertexCount); for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); if (mlVertices.size() == 0) { mvMin.x = mvMax.x = pReal[0]; mvMin.y = mvMax.y = pReal[1]; mvMin.z = mvMax.z = pReal[2]; } else { if (mvMin.x > pReal[0]) mvMin.x = pReal[0]; if (mvMin.y > pReal[1]) mvMin.y = pReal[1]; if (mvMin.z > pReal[2]) mvMin.z = pReal[2]; if (mvMax.x < pReal[0]) mvMax.x = pReal[0]; if (mvMax.y < pReal[1]) mvMax.y = pReal[1]; if (mvMax.z < pReal[2]) mvMax.z = pReal[2]; } mlVertices.push_back(Vector3(pReal[0],pReal[1],pReal[2])); } vbuf->unlock(); next_offset += vertex_data->vertexCount; } // TODO : GET TEXCOORD DATA // TODO : GET FACE-MATERIAL MAP, or at least material cound.... // TODO : no need to update index, texcoord and material buffers for animation ! // TODO : const VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES); // for texture alpha checking, VertexElementType should be VET_FLOAT2 //---------------------------------------------------------------- // GET INDEXDATA //---------------------------------------------------------------- IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT); ::uint32 *pLong = static_cast< ::uint32*>(ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); ::uint16* pShort = reinterpret_cast< ::uint16*>(pLong); size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset; mlIndices.reserve(mlIndices.size()+3*numTris); if ( use32bitindexes ) { for ( size_t k = 0; k < numTris*3; ++k) { mlIndices.push_back(pLong[k] + static_cast<int>(offset)); } } else { for ( size_t k = 0; k < numTris*3; ++k) { mlIndices.push_back(static_cast<int>(pShort[k]) + static_cast<int>(offset)); } } ibuf->unlock(); current_offset = next_offset; } //mvMid = 0.5*(mvMin + mvMax); //mfBoundRad = 0.5 * (mvMax - mvMin).length(); }
//--------------------------------------------------------------------- void ProgressiveMesh::addWorkingData(const VertexData * vertexData, const IndexData * indexData) { // Insert blank working data, then fill mWorkingData.push_back(PMWorkingData()); PMWorkingData& work = mWorkingData.back(); // Build vertex list // Resize face list (this will always be this big) work.mFaceVertList.resize(vertexData->vertexCount); // Also resize common vert list to max, to avoid reallocations work.mVertList.resize(vertexData->vertexCount); // locate position element & hte buffer to go with it const VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); // lock the buffer for reading unsigned char* pVertex = static_cast<unsigned char*>( vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); float* pFloat; Vector3 pos; // Map for identifying duplicate position vertices typedef std::map<Vector3, size_t, vectorLess> CommonVertexMap; CommonVertexMap commonVertexMap; CommonVertexMap::iterator iCommonVertex; size_t numCommon = 0; size_t i = 0; for (i = 0; i < vertexData->vertexCount; ++i, pVertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(pVertex, &pFloat); pos.x = *pFloat++; pos.y = *pFloat++; pos.z = *pFloat++; // Try to find this position in the existing map iCommonVertex = commonVertexMap.find(pos); if (iCommonVertex == commonVertexMap.end()) { // Doesn't exist, so create it PMVertex* commonVert = &(work.mVertList[numCommon]); commonVert->setDetails(pos, numCommon); commonVert->removed = false; commonVert->toBeRemoved = false; commonVert->seam = false; // Enter it in the map commonVertexMap.insert(CommonVertexMap::value_type(pos, numCommon) ); // Increment common index ++numCommon; work.mFaceVertList[i].commonVertex = commonVert; work.mFaceVertList[i].realIndex = i; } else { // Exists already, reference it PMVertex* existingVert = &(work.mVertList[iCommonVertex->second]); work.mFaceVertList[i].commonVertex = existingVert; work.mFaceVertList[i].realIndex = i; // Also tag original as a seam since duplicates at this location work.mFaceVertList[i].commonVertex->seam = true; } } vbuf->unlock(); mNumCommonVertices = numCommon; // Build tri list size_t numTris = indexData->indexCount / 3; unsigned short* pShort; unsigned int* pInt; HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer; bool use32bitindexes = (ibuf->getType() == HardwareIndexBuffer::IT_32BIT); if (use32bitindexes) { pInt = static_cast<unsigned int*>( ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); } else { pShort = static_cast<unsigned short*>( ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); } work.mTriList.resize(numTris); // assumed tri list for (i = 0; i < numTris; ++i) { PMFaceVertex *v0, *v1, *v2; // use 32-bit index always since we're not storing unsigned int vindex = use32bitindexes? *pInt++ : *pShort++; v0 = &(work.mFaceVertList[vindex]); vindex = use32bitindexes? *pInt++ : *pShort++; v1 = &(work.mFaceVertList[vindex]); vindex = use32bitindexes? *pInt++ : *pShort++; v2 = &(work.mFaceVertList[vindex]); work.mTriList[i].setDetails(i, v0, v1, v2); work.mTriList[i].removed = false; } ibuf->unlock(); }
//--------------------------------------------------------------------- void TangentSpaceCalc::extendBuffers(VertexSplits& vertexSplits) { if (!vertexSplits.empty()) { // ok, need to increase the vertex buffer size, and alter some indexes // vertex buffers first VertexBufferBinding* newBindings = HardwareBufferManager::getSingleton().createVertexBufferBinding(); const VertexBufferBinding::VertexBufferBindingMap& bindmap = mVData->vertexBufferBinding->getBindings(); for (VertexBufferBinding::VertexBufferBindingMap::const_iterator i = bindmap.begin(); i != bindmap.end(); ++i) { HardwareVertexBufferSharedPtr srcbuf = i->second; // Derive vertex count from buffer not vertex data, in case using // the vertexStart option in vertex data size_t newVertexCount = srcbuf->getNumVertices() + vertexSplits.size(); // Create new buffer & bind HardwareVertexBufferSharedPtr newBuf = HardwareBufferManager::getSingleton().createVertexBuffer( srcbuf->getVertexSize(), newVertexCount, srcbuf->getUsage(), srcbuf->hasShadowBuffer()); newBindings->setBinding(i->first, newBuf); // Copy existing contents (again, entire buffer, not just elements referenced) newBuf->copyData(*(srcbuf.get()), 0, 0, srcbuf->getNumVertices() * srcbuf->getVertexSize(), true); // Split vertices, read / write from new buffer char* pBase = static_cast<char*>(newBuf->lock(HardwareBuffer::HBL_NORMAL)); for (VertexSplits::iterator spliti = vertexSplits.begin(); spliti != vertexSplits.end(); ++spliti) { const char* pSrcBase = pBase + spliti->first * newBuf->getVertexSize(); char* pDstBase = pBase + spliti->second * newBuf->getVertexSize(); memcpy(pDstBase, pSrcBase, newBuf->getVertexSize()); } newBuf->unlock(); } // Update vertex data // Increase vertex count according to num splits mVData->vertexCount += vertexSplits.size(); // Flip bindings over to new buffers (old buffers released) HardwareBufferManager::getSingleton().destroyVertexBufferBinding(mVData->vertexBufferBinding); mVData->vertexBufferBinding = newBindings; // If vertex size requires 32bit index buffer if (mVData->vertexCount > 65536) { for (size_t i = 0; i < mIDataList.size(); ++i) { // check index size IndexData* idata = mIDataList[i]; HardwareIndexBufferSharedPtr srcbuf = idata->indexBuffer; if (srcbuf->getType() == HardwareIndexBuffer::IT_16BIT) { size_t indexCount = srcbuf->getNumIndexes(); // convert index buffer to 32bit. HardwareIndexBufferSharedPtr newBuf = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_32BIT, indexCount, srcbuf->getUsage(), srcbuf->hasShadowBuffer()); uint16* pSrcBase = static_cast<uint16*>(srcbuf->lock(HardwareBuffer::HBL_NORMAL)); uint32* pBase = static_cast<uint32*>(newBuf->lock(HardwareBuffer::HBL_NORMAL)); size_t j = 0; while (j < indexCount) { *pBase++ = *pSrcBase++; ++j; } srcbuf->unlock(); newBuf->unlock(); // assign new index buffer. idata->indexBuffer = newBuf; } } } } }
FarPlanetMesh::FarPlanetMesh(uint32 resolution, float radius) { this->resolution = resolution; this->radius = radius; float invRes = 1.0f / resolution; //Load vertex buffer uint32 vertCount = 6 * (resolution+1) * (resolution+1); assert(vertCount < 0xFFFF); size_t offset = 0; vertexData.vertexDeclaration->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); vertexData.vertexDeclaration->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES); HardwareVertexBufferSharedPtr vertBuff = HardwareBufferManager::getSingleton().createVertexBuffer( vertexData.vertexDeclaration->getVertexSize(0), vertCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); float *vBuff = static_cast<float*>(vertBuff->lock(HardwareBuffer::HBL_DISCARD)); for (uint32 face = 0; face < 6; ++face) { float faceNormalOffsetV = (face % 2) / 2.0f; float faceNormalOffsetU = (face / 2) / 4.0f; for (uint32 y = 0; y <= resolution; ++y) { for (uint32 x = 0; x <= resolution; ++x) { //Calculate UVs and terrain height Real tx = x * invRes; Real ty = y * invRes; //Calculate vertex position Vector3 pos = mapCubeToUnitSphere(mapPlaneToCube(tx, ty, (CubeFace)face)) * radius; //Add vertex *vBuff++ = pos.x; *vBuff++ = pos.y; *vBuff++ = pos.z; *vBuff++ = faceNormalOffsetU + tx * 0.25f; *vBuff++ = faceNormalOffsetV + ty * 0.5f; } } } vertBuff->unlock(); vertexData.vertexStart = 0; vertexData.vertexCount = vertCount; vertexData.vertexBufferBinding->setBinding(0, vertBuff); //Load index buffer uint32 indexCount = 6 * 6 * resolution * resolution; HardwareIndexBufferSharedPtr indexBuff = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); uint16 *iBuff = static_cast<uint16*>(indexBuff->lock(HardwareBuffer::HBL_DISCARD)); //Index the chunk grid for (uint32 face = 0; face < 6; ++face) { uint32 faceOffset = face * ((resolution+1) * (resolution+1)); for (uint32 y = 0; y < resolution; ++y){ for (uint32 x = 0; x < resolution; ++x){ uint16 vTopLeft = faceOffset + (y * (resolution+1) + x); uint16 vBottomLeft = faceOffset + ((y+1) * (resolution+1) + x); *iBuff++ = vBottomLeft; *iBuff++ = vTopLeft+1; *iBuff++ = vTopLeft; *iBuff++ = vBottomLeft; *iBuff++ = vBottomLeft+1; *iBuff++ = vTopLeft+1; } } } indexBuff->unlock(); indexData.indexStart = 0; indexData.indexCount = indexCount; indexData.indexBuffer = indexBuff; }
//--------------------------------------------------------------------- void PrefabFactory::createSphere(Mesh* mesh) { // sphere creation code taken from the DeferredShading sample, originally from the wiki SubMesh *pSphereVertex = mesh->createSubMesh(); const int NUM_SEGMENTS = 16; const int NUM_RINGS = 16; const Real SPHERE_RADIUS = 50.0; mesh->sharedVertexData = OGRE_NEW VertexData(); VertexData* vertexData = mesh->sharedVertexData; // define the vertex format VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // two dimensional texture coordinates vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); // allocate the vertex buffer vertexData->vertexCount = (NUM_RINGS + 1) * (NUM_SEGMENTS+1); HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer pSphereVertex->indexData->indexCount = 6 * NUM_RINGS * (NUM_SEGMENTS + 1); pSphereVertex->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, pSphereVertex->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = pSphereVertex->indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); float fDeltaRingAngle = (Math::PI / NUM_RINGS); float fDeltaSegAngle = (2 * Math::PI / NUM_SEGMENTS); unsigned short wVerticeIndex = 0 ; // Generate the group of rings for the sphere for( int ring = 0; ring <= NUM_RINGS; ring++ ) { float r0 = SPHERE_RADIUS * sinf (ring * fDeltaRingAngle); float y0 = SPHERE_RADIUS * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(int seg = 0; seg <= NUM_SEGMENTS; seg++) { float x0 = r0 * sinf(seg * fDeltaSegAngle); float z0 = r0 * cosf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere *pVertex++ = x0; *pVertex++ = y0; *pVertex++ = z0; Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy(); *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z; *pVertex++ = (float) seg / (float) NUM_SEGMENTS; *pVertex++ = (float) ring / (float) NUM_RINGS; if (ring != NUM_RINGS) { // each vertex (except the last) has six indicies pointing to it *pIndices++ = wVerticeIndex + NUM_SEGMENTS + 1; *pIndices++ = wVerticeIndex; *pIndices++ = wVerticeIndex + NUM_SEGMENTS; *pIndices++ = wVerticeIndex + NUM_SEGMENTS + 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: mesh->_setBounds( AxisAlignedBox( Vector3(-SPHERE_RADIUS, -SPHERE_RADIUS, -SPHERE_RADIUS), Vector3(SPHERE_RADIUS, SPHERE_RADIUS, SPHERE_RADIUS) ), false ); mesh->_setBoundingSphereRadius(SPHERE_RADIUS); }
void ModelConverter::WriteSubMesh( DiSubMesh* subMod, const Ogre::SubMesh* s ) { switch(s->operationType) { case RenderOperation::OT_LINE_LIST: subMod->SetPrimitiveType(D3DPT_LINELIST); break; case RenderOperation::OT_LINE_STRIP: subMod->SetPrimitiveType(D3DPT_LINESTRIP); break; case RenderOperation::OT_POINT_LIST: subMod->SetPrimitiveType(D3DPT_POINTLIST); break; case RenderOperation::OT_TRIANGLE_FAN: subMod->SetPrimitiveType(D3DPT_TRIANGLEFAN); break; case RenderOperation::OT_TRIANGLE_LIST: subMod->SetPrimitiveType(PT_TRIANGLELIST); break; case RenderOperation::OT_TRIANGLE_STRIP: subMod->SetPrimitiveType(D3DPT_TRIANGLESTRIP); break; } VertexData* vertexData = nullptr; if (mMesh->sharedVertexData) { vertexData = mMesh->sharedVertexData; } else { vertexData = s->vertexData; } int numFaces = 0; switch(s->operationType) { case RenderOperation::OT_TRIANGLE_LIST: // triangle list numFaces = s->indexData->indexCount / 3; break; case RenderOperation::OT_LINE_LIST: numFaces = s->indexData->indexCount / 2; break; case RenderOperation::OT_TRIANGLE_FAN: case RenderOperation::OT_TRIANGLE_STRIP: // triangle fan or triangle strip numFaces = s->indexData->indexCount - 2; break; default: OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Unsupported render operation type", __FUNCTION__); } subMod->SetPrimitiveCount(numFaces); subMod->SetVerticeNum(vertexData->vertexCount); // material name DiString matName; matName.Format("%s_%d.mtl",subMod->GetParentMesh()->GetName().c_str(),subMod->GetIndex()); subMod->SetMaterialName(matName); bool use32BitIndexes = (!s->indexData->indexBuffer.isNull() && s->indexData->indexBuffer->getType() == HardwareIndexBuffer::IT_32BIT); // Write each face in turn unsigned int* pInt = 0; unsigned short* pShort = 0; HardwareIndexBufferSharedPtr ibuf = s->indexData->indexBuffer; // index data if (use32BitIndexes) { pInt = static_cast<unsigned int*>( ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); } else { pShort = static_cast<unsigned short*>( ibuf->lock(HardwareBuffer::HBL_READ_ONLY)); } void* indata = subMod->CreateIndexData(s->indexData->indexCount,use32BitIndexes?TRUE:FALSE); if (use32BitIndexes) { memcpy(indata,pInt,sizeof(unsigned int)*s->indexData->indexCount); } else { memcpy(indata,pShort,sizeof(unsigned short)*s->indexData->indexCount); } ibuf->unlock(); // vertex declaration VertexDeclaration* decl = vertexData->vertexDeclaration; VertexBufferBinding* bind = vertexData->vertexBufferBinding; VertexBufferBinding::VertexBufferBindingMap::const_iterator b, bend; bend = bind->getBindings().end(); // iterate over buffers int bindCount = 0; for(b = bind->getBindings().begin(); b != bend; ++b,++bindCount) { const HardwareVertexBufferSharedPtr vbuf = b->second; unsigned short bufferIdx = b->first; // get all the elements that relate to this buffer VertexDeclaration::VertexElementList elems = decl->findElementsBySource(bufferIdx); VertexDeclaration::VertexElementList::iterator i, iend; iend = elems.end(); unsigned short nuDemiureCoords = 0; for (i = elems.begin(); i != iend; ++i) { VertexElement& elem = *i; D3DDECLTYPE type = ConverteVertType(elem.getType()); D3DDECLUSAGE usage; bool texcoord = false; switch(elem.getSemantic()) { case VES_POSITION: usage = D3DDECLUSAGE_POSITION; break; case VES_NORMAL: usage = D3DDECLUSAGE_NORMAL; break; case VES_TANGENT: usage = D3DDECLUSAGE_TANGENT; break; case VES_BINORMAL: usage = D3DDECLUSAGE_BINORMAL; break; case VES_DIFFUSE: case VES_SPECULAR: usage = D3DDECLUSAGE_COLOR; break; case VES_TEXTURE_COORDINATES: usage = D3DDECLUSAGE_TEXCOORD; ++nuDemiureCoords; texcoord = true; break; default: DI_ERROR("Unsupported semantic"); } subMod->GetVertexElements().AddElement(bindCount,type,usage,texcoord?nuDemiureCoords-1:0); } int stride = subMod->GetVertexElements().GetStreamElementsSize(bindCount); void* vertData = subMod->CreateSourceData(bindCount,vertexData->vertexCount,stride); unsigned char* pVert = static_cast<unsigned char*>( vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); memcpy(vertData,pVert,vertexData->vertexCount*stride); vbuf->unlock(); } // vertex weight if (mMesh->hasSkeleton()) { LogManager::getSingleton().logMessage("Exporting dedicated geometry bone assignments..."); if(const_cast<SubMesh*>(s)->getBoneAssignments().empty()) { SubMesh::BoneAssignmentIterator bi = mMesh->getBoneAssignmentIterator(); while (bi.hasMoreElements()) { const VertexBoneAssignment& assign = bi.getNext(); if (assign.weight > 0.0f) { subMod->AddWeight(assign.vertexIndex,assign.boneIndex,assign.weight); } } } else { SubMesh::BoneAssignmentIterator bi = (const_cast<SubMesh*>(s))->getBoneAssignmentIterator(); while (bi.hasMoreElements()) { const VertexBoneAssignment& assign = bi.getNext(); if (assign.weight > 0.0f) { subMod->AddWeight(assign.vertexIndex,assign.boneIndex,assign.weight); } } } subMod->RationaliseBoneWeights(); } }