MeshPtr MergeMesh::bake() { log( "Baking: New Mesh started" ); MeshPtr mp = MeshManager::getSingleton(). createManual( "mergedMesh", ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME ); mp->setSkeletonName( m_BaseSkeleton->getName() ); AxisAlignedBox totalBounds = AxisAlignedBox(); for( std::vector< Ogre::MeshPtr >::iterator it = m_Meshes.begin(); it != m_Meshes.end(); ++it ) { log( "Baking: adding submeshes for " + (*it)->getName() ); // insert all submeshes for( Ogre::ushort sid = 0; sid < (*it)->getNumSubMeshes(); ++sid ) { SubMesh* sub = (*it)->getSubMesh( sid ); const String name = findSubmeshName( (*it), sid ); // create submesh with correct name SubMesh* newsub; if( name.length() == 0 ) newsub = mp->createSubMesh( ); else /// @todo check if a submesh with this name has been created before newsub = mp->createSubMesh( name ); newsub->useSharedVertices = sub->useSharedVertices; // add index newsub->indexData = sub->indexData->clone(); // add geometry if( !newsub->useSharedVertices ) { newsub->vertexData = sub->vertexData->clone(); // build bone assignments SubMesh::BoneAssignmentIterator bit = sub->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); newsub->addBoneAssignment(vba); } } newsub->setMaterialName( sub->getMaterialName() ); log("Baking: adding submesh '" + name + "' with material " + sub->getMaterialName()); } // sharedvertices if ((*it)->sharedVertexData) { /// @todo merge with existing sharedVertexData if (!mp->sharedVertexData) { mp->sharedVertexData = (*it)->sharedVertexData->clone(); } Mesh::BoneAssignmentIterator bit = (*it)->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); mp->addBoneAssignment(vba); } } log("Baking: adding bounds for " + (*it)->getName()); // add bounds totalBounds.merge((*it)->getBounds()); } mp->_setBounds( totalBounds ); /// @todo merge submeshes with same material /// @todo add parameters mp->buildEdgeList(); log( "Baking: Finished" ); return mp; }
MeshPtr MeshMergeTool::merge(const Ogre::String& name, const Ogre::String& resourceGroupName) { print("Baking: New Mesh started", V_HIGH); MeshPtr mp = MeshManager::getSingleton().createManual(name, resourceGroupName); if (!mBaseSkeleton.isNull()) { mp->setSkeletonName(mBaseSkeleton->getName()); } AxisAlignedBox totalBounds = AxisAlignedBox(); for (std::vector<Ogre::MeshPtr>::iterator it = mMeshes.begin(); it != mMeshes.end(); ++it) { print("Baking: adding submeshes for " + (*it)->getName(), V_HIGH); // insert all submeshes for (Ogre::ushort sid = 0; sid < (*it)->getNumSubMeshes(); ++sid) { SubMesh* sub = (*it)->getSubMesh(sid); const String name = findSubmeshName((*it), sid); // create submesh with correct name SubMesh* newsub; if (name.length() == 0) { newsub = mp->createSubMesh(); } else { /// @todo check if a submesh with this name has been created before newsub = mp->createSubMesh(name); } newsub->useSharedVertices = sub->useSharedVertices; // add index newsub->indexData = sub->indexData->clone(); // add geometry if (!newsub->useSharedVertices) { newsub->vertexData = sub->vertexData->clone(); if (!mBaseSkeleton.isNull()) { // build bone assignments SubMesh::BoneAssignmentIterator bit = sub->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); newsub->addBoneAssignment(vba); } } } newsub->setMaterialName(sub->getMaterialName()); // Add vertex animations for this submesh Animation *anim = 0; for (unsigned short i = 0; i < (*it)->getNumAnimations(); ++i) { anim = (*it)->getAnimation(i); // get or create the animation for the new mesh Animation *newanim; if (mp->hasAnimation(anim->getName())) { newanim = mp->getAnimation(anim->getName()); } else { newanim = mp->createAnimation(anim->getName(), anim->getLength()); } print("Baking: adding vertex animation " + anim->getName() + " for " + (*it)->getName(), V_HIGH); Animation::VertexTrackIterator vti=anim->getVertexTrackIterator(); while (vti.hasMoreElements()) { VertexAnimationTrack *vt = vti.getNext(); // handle=0 targets the main mesh, handle i (where i>0) targets submesh i-1. // In this case there are only submeshes so index 0 will not be used. unsigned short handle = mp->getNumSubMeshes(); VertexAnimationTrack* newvt = newanim->createVertexTrack( handle, vt->getAssociatedVertexData()->clone(), vt->getAnimationType()); for (int keyFrameIndex = 0; keyFrameIndex < vt->getNumKeyFrames(); ++keyFrameIndex) { switch (vt->getAnimationType()) { case VAT_MORPH: { // copy the keyframe vertex buffer VertexMorphKeyFrame *kf = vt->getVertexMorphKeyFrame(keyFrameIndex); VertexMorphKeyFrame *newkf = newvt->createVertexMorphKeyFrame(kf->getTime()); // This creates a ref to the buffer in the original model // so don't delete it until the export is completed. newkf->setVertexBuffer(kf->getVertexBuffer()); break; } case VAT_POSE: { /// @todo implement pose amination merge break; } case VAT_NONE: default: { break; } } } } } print("Baking: adding submesh '" + name + "' with material " + sub->getMaterialName(), V_HIGH); } // sharedvertices if ((*it)->sharedVertexData) { /// @todo merge with existing sharedVertexData if (!mp->sharedVertexData) { mp->sharedVertexData = (*it)->sharedVertexData->clone(); } if (!mBaseSkeleton.isNull()) { Mesh::BoneAssignmentIterator bit = (*it)->getBoneAssignmentIterator(); while (bit.hasMoreElements()) { VertexBoneAssignment vba = bit.getNext(); mp->addBoneAssignment(vba); } } } print("Baking: adding bounds for " + (*it)->getName(), V_HIGH); // add bounds totalBounds.merge((*it)->getBounds()); } mp->_setBounds(totalBounds); /// @todo merge submeshes with same material /// @todo add parameters mp->buildEdgeList(); print("Baking: Finished", V_HIGH); reset(); return mp; }
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(); } }