// Utility function to allow the user to modify the layout of vertex buffers. void reorganiseVertexBuffers(const String& desc, Mesh& mesh, VertexData* vertexData) { cout << endl << desc << ":- " << endl; // Copy elements into a list VertexDeclaration::VertexElementList elemList; copyElems(vertexData->vertexDeclaration, &elemList); bool finish = false; bool anyChanges = false; while (!finish) { displayVertexBuffers(elemList); cout << endl; cout << "Options: (a)utomatic" << endl; cout << " (m)ove element" << endl; cout << " (d)elete element" << endl; cout << " (r)eset" << endl; cout << " (f)inish" << endl; String response = ""; while (response.empty()) { cin >> response; StringUtil::toLowerCase(response); if (response == "m") { String moveResp; cout << "Which element do you want to move (type number): "; cin >> moveResp; if (!moveResp.empty()) { int eindex = StringConverter::parseInt(moveResp); VertexDeclaration::VertexElementList::iterator movei = elemList.begin(); std::advance(movei, eindex); cout << endl << "Move element " << eindex << "(" + describeSemantic(movei->getSemantic()) << ") to which buffer: "; cin >> moveResp; if (!moveResp.empty()) { int bindex = StringConverter::parseInt(moveResp); // Move (note offset will be wrong) *movei = VertexElement(bindex, 0, movei->getType(), movei->getSemantic(), movei->getIndex()); elemList.sort(vertexElementLess); anyChanges = true; } } } else if (response == "a")
//------------------------------------------------------------------------ void TerrainBatch::createGpuVertexData() { if ( !mGpuVertexData ) { DefaultTerrainTilesGpuBufferAllocator& gpuBufferAllocator = mSurfaceManager->getDefaultTerrainTilesGpuBufferAllocator(); mOneVertexSize = mTileRender->getOneVertexSize(); Ogre::VertexData* tileVertexData = mTileRender->getCpuVertexData(); ///////////////////////////////////////////////////////////////////////////// mGpuVertexData = OGRE_NEW VertexData(); // copy vertex buffers // get new buffers HardwareVertexBufferSharedPtr destPosBuf; gpuBufferAllocator.allocateVertexBuffers(mOneVertexSize, mVertexTotalNum, destPosBuf); // set bindings mGpuVertexData->vertexBufferBinding->setBinding( TerrainTileRender::POSITION_BUFFER, destPosBuf); // Basic vertex info mGpuVertexData->vertexStart = 0; mGpuVertexData->vertexCount = mVertexTotalNum; // Copy elements const VertexDeclaration::VertexElementList elems = tileVertexData->vertexDeclaration->getElements(); VertexDeclaration::VertexElementList::const_iterator ei, eiend; eiend = elems.end(); for (ei = elems.begin(); ei != eiend; ++ei) { mGpuVertexData->vertexDeclaration->addElement( ei->getSource(), ei->getOffset(), ei->getType(), ei->getSemantic(), ei->getIndex() ); } } }
void displayVertexBuffers(VertexDeclaration::VertexElementList& elemList) { // Iterate per buffer unsigned short currentBuffer = 999; unsigned short elemNum = 0; VertexDeclaration::VertexElementList::iterator i, iend; iend = elemList.end(); for (i = elemList.begin(); i != iend; ++i) { if (i->getSource() != currentBuffer) { currentBuffer = i->getSource(); cout << "> Buffer " << currentBuffer << ":" << endl; } cout << " - Element " << elemNum++ << ": " << describeSemantic(i->getSemantic()); if (i->getSemantic() == VES_TEXTURE_COORDINATES) { cout << " (index " << i->getIndex() << ")"; } cout << endl; } }
//----------------------------------------------------------------------- void InstanceBatchShader::setupHardwareSkinned( const SubMesh* baseSubMesh, VertexData *thisVertexData, VertexData *baseVertexData ) { const size_t numBones = baseSubMesh->blendIndexToBoneIndexMap.size(); mNumWorldMatrices = mInstancesPerBatch * numBones; for( size_t i=0; i<=thisVertexData->vertexDeclaration->getMaxSource(); ++i ) { //Create our own vertex buffer HardwareVertexBufferSharedPtr vertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( thisVertexData->vertexDeclaration->getVertexSize(i), thisVertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY ); thisVertexData->vertexBufferBinding->setBinding( i, vertexBuffer ); VertexDeclaration::VertexElementList veList = thisVertexData->vertexDeclaration->findElementsBySource(i); //Grab the base submesh data HardwareVertexBufferSharedPtr baseVertexBuffer = baseVertexData->vertexBufferBinding->getBuffer(i); char* thisBuf = static_cast<char*>(vertexBuffer->lock(HardwareBuffer::HBL_DISCARD)); char* baseBuf = static_cast<char*>(baseVertexBuffer->lock(HardwareBuffer::HBL_READ_ONLY)); char *startBuf = baseBuf; //Copy and repeat for( size_t j=0; j<mInstancesPerBatch; ++j ) { //Repeat source baseBuf = startBuf; for( size_t k=0; k<baseVertexData->vertexCount; ++k ) { VertexDeclaration::VertexElementList::const_iterator it = veList.begin(); VertexDeclaration::VertexElementList::const_iterator en = veList.end(); while( it != en ) { switch( it->getSemantic() ) { case VES_BLEND_INDICES: *(thisBuf + it->getOffset() + 0) = *(baseBuf + it->getOffset() + 0) + j * numBones; *(thisBuf + it->getOffset() + 1) = *(baseBuf + it->getOffset() + 1) + j * numBones; *(thisBuf + it->getOffset() + 2) = *(baseBuf + it->getOffset() + 2) + j * numBones; *(thisBuf + it->getOffset() + 3) = *(baseBuf + it->getOffset() + 3) + j * numBones; break; default: memcpy( thisBuf + it->getOffset(), baseBuf + it->getOffset(), it->getSize() ); break; } ++it; } thisBuf += baseVertexData->vertexDeclaration->getVertexSize(i); baseBuf += baseVertexData->vertexDeclaration->getVertexSize(i); } } baseVertexBuffer->unlock(); vertexBuffer->unlock(); } }
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(); } }