void GraphicsResourceMesh::setMaterialNames(GraphicsResourceMesh* resourcePtr) { Ogre::ResourcePtr meshResource = Ogre::MeshManager::getSingleton().getByName(resourcePtr->getID()); Ogre::Mesh* meshPtr = static_cast<Ogre::Mesh *>(&*meshResource); Ogre::Mesh::SubMeshIterator currSubMeshIter = meshPtr->getSubMeshIterator(); while (currSubMeshIter.hasMoreElements()) { Ogre::SubMesh *curSubMesh = currSubMeshIter.getNext(); if (!OPTION_ENABLE_TEXTURES->as<bool>()) { curSubMesh->setMaterialName("BaseWhiteTexture"); } else { const Ogre::String& curMatName = curSubMesh->getMaterialName(); int pos = curMatName.find_last_of(':'); if (pos != -1) { String start = curMatName.substr(0, pos); String ending = curMatName.substr(pos); std::map<String, String>::iterator itr = resourcePtr->mMaterialNames.find(start); if (itr != resourcePtr->mMaterialNames.end()) curSubMesh->setMaterialName(itr->second + ending); } } } }
void OgreMeshAsset::SetDefaultMaterial() { if (!ogreMesh.get()) return; for(unsigned short i = 0; i < ogreMesh->getNumSubMeshes(); ++i) { Ogre::SubMesh *submesh = ogreMesh->getSubMesh(i); if (submesh) submesh->setMaterialName("LitTextured"); } }
void OgreMeshAsset::SetDefaultMaterial() { if (ogreMesh.isNull()) return; // originalMaterials.clear(); for (uint i = 0; i < ogreMesh->getNumSubMeshes(); ++i) { Ogre::SubMesh *submesh = ogreMesh->getSubMesh(i); if (submesh) { // originalMaterials.push_back(submesh->getMaterialName().c_str()); submesh->setMaterialName("LitTextured"); } } }
Ogre::SubMesh *EMDOgre::createOgreSubmesh(EMDTriangles *triangles, Ogre::MeshPtr mesh, std::string material_name) { Ogre::SubMesh *sub = mesh->createSubMesh(); sub->setMaterialName(name + "_" + material_name + ".material"); const size_t ibufCount = triangles->faces.size(); unsigned short *faces = (unsigned short *)malloc(sizeof(unsigned short) * ibufCount); for (size_t i = 0; i<ibufCount; i++) { faces[i] = triangles->faces[i]; } Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, ibufCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); ibuf->writeData(0, ibuf->getSizeInBytes(), faces, true); sub->useSharedVertices = true; sub->indexData->indexBuffer = ibuf; sub->indexData->indexCount = ibufCount; sub->indexData->indexStart = 0; free(faces); return sub; }
void MapView::createTerrain() { unsigned int sizeX = mMap->getTerrainSize().x; unsigned int sizeZ = mMap->getTerrainSize().z; mTileX = 33; mTileZ = 33; unsigned int tileCount = ((sizeX - 1) / (mTileX - 1)) * ((sizeZ - 1) / (mTileZ - 1)); unsigned int vertexPerTile = mTileX * mTileZ; unsigned int trianglesPerTile = (mTileX - 1) * (mTileZ - 1) * 2; mMeshes.resize(tileCount); mEntities.resize(tileCount); mSceneNodes.resize(tileCount); // vertexPerTile * 3 vertices * 2 texture coordinates * 3 colours * 3 normals VertexVector vertices(vertexPerTile * 11); // trianglesPerTile * 3 indices per each triangle IndexVector indices[3] = { IndexVector(trianglesPerTile * 3 ), IndexVector(trianglesPerTile * 3 / 4), IndexVector(trianglesPerTile * 3 / 8) }; unsigned int vertexIndex, indexIndex = 0, tileIndex = 0; for (unsigned int zIndex = 0; zIndex < mTileZ - 1; ++zIndex) { for (unsigned int xIndex = 0; xIndex < mTileX - 1; ++xIndex) { indices[0][indexIndex++] = zIndex * mTileX + xIndex; indices[0][indexIndex++] = (zIndex + 1) * mTileX + xIndex; indices[0][indexIndex++] = zIndex * mTileX + xIndex + 1; indices[0][indexIndex++] = (zIndex + 1) * mTileX + xIndex; indices[0][indexIndex++] = (zIndex + 1) * mTileX + xIndex + 1; indices[0][indexIndex++] = zIndex * mTileX + xIndex + 1; } } indexIndex = 0; for (unsigned int zIndex = 0; zIndex < mTileZ - 1; zIndex += 2) { for (unsigned int xIndex = 0; xIndex < mTileX - 1; xIndex += 2) { indices[1][indexIndex++] = zIndex * mTileX + xIndex; indices[1][indexIndex++] = (zIndex + 2) * mTileX + xIndex; indices[1][indexIndex++] = zIndex * mTileX + xIndex + 2; indices[1][indexIndex++] = (zIndex + 2) * mTileX + xIndex; indices[1][indexIndex++] = (zIndex + 2) * mTileX + xIndex + 2; indices[1][indexIndex++] = zIndex * mTileX + xIndex + 2; } } indexIndex = 0; for (unsigned int zIndex = 0; zIndex < mTileZ - 1; zIndex += 4) { for (unsigned int xIndex = 0; xIndex < mTileX - 1; xIndex += 4) { indices[2][indexIndex++] = zIndex * mTileX + xIndex; indices[2][indexIndex++] = (zIndex + 4) * mTileX + xIndex; indices[2][indexIndex++] = zIndex * mTileX + xIndex + 4; indices[2][indexIndex++] = (zIndex + 4) * mTileX + xIndex; indices[2][indexIndex++] = (zIndex + 4) * mTileX + xIndex + 4; indices[2][indexIndex++] = zIndex * mTileX + xIndex + 4; } } float scaleX = mMap->getSize().x / (float)(sizeX - 1); float scaleZ = mMap->getSize().z / (float)(sizeZ - 1); for (unsigned int zTile = 0; zTile < (sizeZ - 1); zTile += (mTileZ - 1)) { for (unsigned int xTile = 0; xTile < (sizeX - 1); xTile += (mTileX - 1)) { vertexIndex = 0; for (unsigned int zVertex = zTile; zVertex < zTile + mTileZ; ++zVertex) { for (unsigned int xVertex = xTile; xVertex < xTile + mTileX; ++xVertex) { float yVertex = mMap->getTerrainData()[zVertex * sizeX + xVertex]; vertices[vertexIndex++] = (float)xVertex * scaleX; vertices[vertexIndex++] = (float)yVertex; vertices[vertexIndex++] = (float)zVertex * scaleZ; vertices[vertexIndex++] = (float)xVertex / (float)(sizeX - 1); vertices[vertexIndex++] = (float)zVertex / (float)(sizeZ - 1); vertices[vertexIndex++] = 1.0f; vertices[vertexIndex++] = 1.0f; vertices[vertexIndex++] = 1.0f; vertices[vertexIndex++] = 0.0f; vertices[vertexIndex++] = 1.0f; vertices[vertexIndex++] = 0.0f; } } std::string name = "MapView_" + Convert::ToString(mID) + "_Tile_" + Convert::ToString(tileIndex); // Create mesh. mMeshes[tileIndex] = Ogre::MeshManager::getSingleton().createManual( name, "General").get(); // Create one submesh. Ogre::SubMesh* subMesh = mMeshes[tileIndex]->createSubMesh(); // Create vertex data structure for vertices shared between submeshes. mMeshes[tileIndex]->sharedVertexData = new Ogre::VertexData(); mMeshes[tileIndex]->sharedVertexData->vertexCount = vertexPerTile; // Create declaration (memory format) of vertex data. Ogre::VertexDeclaration* decl = mMeshes[tileIndex]->sharedVertexData->vertexDeclaration; size_t offset = 0; // 1st buffer decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_DIFFUSE); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); // Allocate vertex buffer of the requested number of vertices (vertexPerTile) // and bytes per vertex (offset). Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( offset, vertexPerTile, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Upload the vertex data to the card vbuf->writeData(0, vbuf->getSizeInBytes(), &(vertices.front()), true); // Set vertex buffer binding so buffer 0 is bound to our vertex buffer. Ogre::VertexBufferBinding* bind = mMeshes[tileIndex]->sharedVertexData->vertexBufferBinding; bind->setBinding(0, vbuf); // Allocate index buffer of the requested number of vertices . Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton(). createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT, trianglesPerTile * 3, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Upload the index data to the card. ibuf->writeData(0, ibuf->getSizeInBytes(), &(indices[0].front()), true); /// Set parameters of the submesh subMesh->useSharedVertices = true; subMesh->indexData->indexBuffer = ibuf; subMesh->indexData->indexCount = indices[0].size(); subMesh->indexData->indexStart = 0; subMesh->setMaterialName("terrain"); float xMin = vertices[0]; float yMin = vertices[1]; float zMin = vertices[2]; float xMax = vertices[0]; float yMax = vertices[1]; float zMax = vertices[2]; for (unsigned int i = 0; i < vertexPerTile * 11; i += 11) { if (vertices[i ] < xMin) xMin = vertices[i ]; else if (vertices[i ] > xMax) xMax = vertices[i ]; if (vertices[i + 1] < yMin) yMin = vertices[i + 1]; else if (vertices[i + 1] > yMax) yMax = vertices[i + 1]; if (vertices[i + 2] < zMin) zMin = vertices[i + 2]; else if (vertices[i + 2] > zMax) zMax = vertices[i + 2]; } // Set bounding information (for culling). mMeshes[tileIndex]->_setBounds(Ogre::AxisAlignedBox(xMin, yMin, zMin, xMax, yMax, zMax)); mMeshes[tileIndex]->_setBoundingSphereRadius(1.0f); // Notify Mesh object that it has been loaded. mMeshes[tileIndex]->load(); // Create entity. mEntities[tileIndex] = createEntity(name, name); mEntities[tileIndex]->setCastShadows(false); mEntities[tileIndex]->setUserAny(Ogre::Any(this)); // Create scene node. mSceneNodes[tileIndex] = createSceneNode(); mSceneNodes[tileIndex]->attachObject(mEntities[tileIndex]); // Advance to next tile. tileIndex++; } } }
void NIFMeshLoader::createSubMesh(Ogre::Mesh *mesh, const Nif::NiTriShape *shape) { const Nif::NiTriShapeData *data = shape->data.getPtr(); const Nif::NiSkinInstance *skin = (shape->skin.empty() ? NULL : shape->skin.getPtr()); std::vector<Ogre::Vector3> srcVerts = data->vertices; std::vector<Ogre::Vector3> srcNorms = data->normals; Ogre::HardwareBuffer::Usage vertUsage = Ogre::HardwareBuffer::HBU_STATIC; bool vertShadowBuffer = false; bool geomMorpherController = false; if(!shape->controller.empty()) { Nif::ControllerPtr ctrl = shape->controller; do { if(ctrl->recType == Nif::RC_NiGeomMorpherController) { vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY; vertShadowBuffer = true; geomMorpherController = true; break; } } while(!(ctrl=ctrl->next).empty()); } if(skin != NULL) { vertUsage = Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY; vertShadowBuffer = true; // Only set a skeleton when skinning. Unskinned meshes with a skeleton will be // explicitly attached later. mesh->setSkeletonName(mName); // Convert vertices and normals to bone space from bind position. It would be // better to transform the bones into bind position, but there doesn't seem to // be a reliable way to do that. std::vector<Ogre::Vector3> newVerts(srcVerts.size(), Ogre::Vector3(0.0f)); std::vector<Ogre::Vector3> newNorms(srcNorms.size(), Ogre::Vector3(0.0f)); const Nif::NiSkinData *data = skin->data.getPtr(); const Nif::NodeList &bones = skin->bones; for(size_t b = 0;b < bones.length();b++) { Ogre::Matrix4 mat; mat.makeTransform(data->bones[b].trafo.trans, Ogre::Vector3(data->bones[b].trafo.scale), Ogre::Quaternion(data->bones[b].trafo.rotation)); mat = bones[b]->getWorldTransform() * mat; const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[b].weights; for(size_t i = 0;i < weights.size();i++) { size_t index = weights[i].vertex; float weight = weights[i].weight; newVerts.at(index) += (mat*srcVerts[index]) * weight; if(newNorms.size() > index) { Ogre::Vector4 vec4(srcNorms[index][0], srcNorms[index][1], srcNorms[index][2], 0.0f); vec4 = mat*vec4 * weight; newNorms[index] += Ogre::Vector3(&vec4[0]); } } } srcVerts = newVerts; srcNorms = newNorms; } else { Ogre::SkeletonManager *skelMgr = Ogre::SkeletonManager::getSingletonPtr(); if(skelMgr->getByName(mName).isNull()) { // No skinning and no skeleton, so just transform the vertices and // normals into position. Ogre::Matrix4 mat4 = shape->getWorldTransform(); for(size_t i = 0;i < srcVerts.size();i++) { Ogre::Vector4 vec4(srcVerts[i].x, srcVerts[i].y, srcVerts[i].z, 1.0f); vec4 = mat4*vec4; srcVerts[i] = Ogre::Vector3(&vec4[0]); } for(size_t i = 0;i < srcNorms.size();i++) { Ogre::Vector4 vec4(srcNorms[i].x, srcNorms[i].y, srcNorms[i].z, 0.0f); vec4 = mat4*vec4; srcNorms[i] = Ogre::Vector3(&vec4[0]); } } } // Set the bounding box first BoundsFinder bounds; bounds.add(&srcVerts[0][0], srcVerts.size()); if(!bounds.isValid()) { float v[3] = { 0.0f, 0.0f, 0.0f }; bounds.add(&v[0], 1); } mesh->_setBounds(Ogre::AxisAlignedBox(bounds.minX()-0.5f, bounds.minY()-0.5f, bounds.minZ()-0.5f, bounds.maxX()+0.5f, bounds.maxY()+0.5f, bounds.maxZ()+0.5f)); mesh->_setBoundingSphereRadius(bounds.getRadius()); // This function is just one long stream of Ogre-barf, but it works // great. Ogre::HardwareBufferManager *hwBufMgr = Ogre::HardwareBufferManager::getSingletonPtr(); Ogre::HardwareVertexBufferSharedPtr vbuf; Ogre::HardwareIndexBufferSharedPtr ibuf; Ogre::VertexBufferBinding *bind; Ogre::VertexDeclaration *decl; int nextBuf = 0; Ogre::SubMesh *sub = mesh->createSubMesh(); // Add vertices sub->useSharedVertices = false; sub->vertexData = new Ogre::VertexData(); sub->vertexData->vertexStart = 0; sub->vertexData->vertexCount = srcVerts.size(); decl = sub->vertexData->vertexDeclaration; bind = sub->vertexData->vertexBufferBinding; if(srcVerts.size()) { vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), srcVerts.size(), vertUsage, vertShadowBuffer); vbuf->writeData(0, vbuf->getSizeInBytes(), &srcVerts[0][0], true); decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_POSITION); bind->setBinding(nextBuf++, vbuf); } // Vertex normals if(srcNorms.size()) { vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3), srcNorms.size(), vertUsage, vertShadowBuffer); vbuf->writeData(0, vbuf->getSizeInBytes(), &srcNorms[0][0], true); decl->addElement(nextBuf, 0, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); bind->setBinding(nextBuf++, vbuf); } // Vertex colors const std::vector<Ogre::Vector4> &colors = data->colors; if(colors.size()) { Ogre::RenderSystem *rs = Ogre::Root::getSingleton().getRenderSystem(); std::vector<Ogre::RGBA> colorsRGB(colors.size()); for(size_t i = 0;i < colorsRGB.size();i++) { Ogre::ColourValue clr(colors[i][0], colors[i][1], colors[i][2], colors[i][3]); rs->convertColourValue(clr, &colorsRGB[i]); } vbuf = hwBufMgr->createVertexBuffer(Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR), colorsRGB.size(), Ogre::HardwareBuffer::HBU_STATIC); vbuf->writeData(0, vbuf->getSizeInBytes(), &colorsRGB[0], true); decl->addElement(nextBuf, 0, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); bind->setBinding(nextBuf++, vbuf); } // Texture UV coordinates size_t numUVs = data->uvlist.size(); if (numUVs) { size_t elemSize = Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); for(size_t i = 0; i < numUVs; i++) decl->addElement(nextBuf, elemSize*i, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, i); vbuf = hwBufMgr->createVertexBuffer(decl->getVertexSize(nextBuf), srcVerts.size(), Ogre::HardwareBuffer::HBU_STATIC); std::vector<Ogre::Vector2> allUVs; allUVs.reserve(srcVerts.size()*numUVs); for (size_t vert = 0; vert<srcVerts.size(); ++vert) for(size_t i = 0; i < numUVs; i++) allUVs.push_back(data->uvlist[i][vert]); vbuf->writeData(0, elemSize*srcVerts.size()*numUVs, &allUVs[0], true); bind->setBinding(nextBuf++, vbuf); } // Triangle faces const std::vector<short> &srcIdx = data->triangles; if(srcIdx.size()) { ibuf = hwBufMgr->createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, srcIdx.size(), Ogre::HardwareBuffer::HBU_STATIC); ibuf->writeData(0, ibuf->getSizeInBytes(), &srcIdx[0], true); sub->indexData->indexBuffer = ibuf; sub->indexData->indexCount = srcIdx.size(); sub->indexData->indexStart = 0; } // Assign bone weights for this TriShape if(skin != NULL) { Ogre::SkeletonPtr skel = Ogre::SkeletonManager::getSingleton().getByName(mName); const Nif::NiSkinData *data = skin->data.getPtr(); const Nif::NodeList &bones = skin->bones; for(size_t i = 0;i < bones.length();i++) { Ogre::VertexBoneAssignment boneInf; boneInf.boneIndex = skel->getBone(bones[i]->name)->getHandle(); const std::vector<Nif::NiSkinData::VertWeight> &weights = data->bones[i].weights; for(size_t j = 0;j < weights.size();j++) { boneInf.vertexIndex = weights[j].vertex; boneInf.weight = weights[j].weight; sub->addBoneAssignment(boneInf); } } } const Nif::NiTexturingProperty *texprop = NULL; const Nif::NiMaterialProperty *matprop = NULL; const Nif::NiAlphaProperty *alphaprop = NULL; const Nif::NiVertexColorProperty *vertprop = NULL; const Nif::NiZBufferProperty *zprop = NULL; const Nif::NiSpecularProperty *specprop = NULL; const Nif::NiWireframeProperty *wireprop = NULL; bool needTangents = false; shape->getProperties(texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop); std::string matname = NIFMaterialLoader::getMaterial(data, mesh->getName(), mGroup, texprop, matprop, alphaprop, vertprop, zprop, specprop, wireprop, needTangents); if(matname.length() > 0) sub->setMaterialName(matname); // build tangents if the material needs them if (needTangents) { unsigned short src,dest; if (!mesh->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src,dest)) mesh->buildTangentVectors(Ogre::VES_TANGENT, src,dest); } // Create a dummy vertex animation track if there's a geom morpher controller // This is required to make Ogre create the buffers we will use for software vertex animation if (srcVerts.size() && geomMorpherController) mesh->createAnimation("dummy", 0)->createVertexTrack(1, sub->vertexData, Ogre::VAT_MORPH); }
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); } }
bool OgreMeshResource::SetData(Foundation::AssetPtr source) { if (!source) { OgreRenderingModule::LogError("Null source asset data pointer"); return false; } if (!source->GetSize()) { OgreRenderingModule::LogError("Zero sized mesh asset"); return false; } try { if (ogre_mesh_.isNull()) { ogre_mesh_ = Ogre::MeshManager::getSingleton().createManual( id_, Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); if (ogre_mesh_.isNull()) { OgreRenderingModule::LogError("Failed to create mesh " + id_); return false; } ogre_mesh_->setAutoBuildEdgeLists(false); } Ogre::DataStreamPtr stream(new Ogre::MemoryDataStream((void*)source->GetData(), source->GetSize(), false)); Ogre::MeshSerializer serializer; serializer.importMesh(stream, ogre_mesh_.getPointer()); // Generate tangents to mesh try { unsigned short src, dest; if (!ogre_mesh_->suggestTangentVectorBuildParams(Ogre::VES_TANGENT, src, dest)) ogre_mesh_->buildTangentVectors(Ogre::VES_TANGENT, src, dest); } catch (...) {} // Generate extremity points to submeshes, 1 should be enough try { for(uint i = 0; i < ogre_mesh_->getNumSubMeshes(); ++i) { Ogre::SubMesh *smesh = ogre_mesh_->getSubMesh(i); if (smesh) smesh->generateExtremes(1); } } catch (...) {} // Assign default materials that won't complain original_materials_.clear(); for (uint i = 0; i < ogre_mesh_->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = ogre_mesh_->getSubMesh(i); if (submesh) { original_materials_.push_back(submesh->getMaterialName()); submesh->setMaterialName("UnlitTextured"); } } } catch (Ogre::Exception &e) { OgreRenderingModule::LogError("Failed to create mesh " + id_ + ": " + std::string(e.what())); RemoveMesh(); return false; } OgreRenderingModule::LogDebug("Ogre mesh " + id_ + " created"); return true; }
// Write submesh data to an Ogre compatible mesh bool Submesh::createOgreSubmesh(Ogre::MeshPtr pMesh,const ParamList& params) { size_t i,j; bool stat; // Create a new submesh Ogre::SubMesh* pSubmesh; if (m_name != "") pSubmesh = pMesh->createSubMesh(m_name.c_str()); else pSubmesh = pMesh->createSubMesh(); // Set material pSubmesh->setMaterialName(m_pMaterial->name().c_str()); // Set use shared geometry flag pSubmesh->useSharedVertices = params.useSharedGeom; // Create vertex data for current submesh pSubmesh->vertexData = new Ogre::VertexData(); // Set number of indexes pSubmesh->indexData->indexCount = 3*m_faces.size(); pSubmesh->vertexData->vertexCount = m_vertices.size(); // Check if we need to use 32 bit indexes bool use32BitIndexes = false; if (m_vertices.size() > 65536 || params.useSharedGeom) { use32BitIndexes = true; } // Create a new index buffer pSubmesh->indexData->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( use32BitIndexes ? Ogre::HardwareIndexBuffer::IT_32BIT : Ogre::HardwareIndexBuffer::IT_16BIT, pSubmesh->indexData->indexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Fill the index buffer with faces data if (use32BitIndexes) { Ogre::uint32* pIdx = static_cast<Ogre::uint32*>( pSubmesh->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); for (i=0; i<m_faces.size(); i++) { *pIdx++ = static_cast<Ogre::uint32>(m_faces[i].v[0]); *pIdx++ = static_cast<Ogre::uint32>(m_faces[i].v[1]); *pIdx++ = static_cast<Ogre::uint32>(m_faces[i].v[2]); } pSubmesh->indexData->indexBuffer->unlock(); } else { Ogre::uint16* pIdx = static_cast<Ogre::uint16*>( pSubmesh->indexData->indexBuffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); for (i=0; i<m_faces.size(); i++) { *pIdx++ = static_cast<Ogre::uint16>(m_faces[i].v[0]); *pIdx++ = static_cast<Ogre::uint16>(m_faces[i].v[1]); *pIdx++ = static_cast<Ogre::uint16>(m_faces[i].v[2]); } pSubmesh->indexData->indexBuffer->unlock(); } // Define vertex declaration (only if we're not using shared geometry) if(!params.useSharedGeom) { Ogre::VertexDeclaration* pDecl = pSubmesh->vertexData->vertexDeclaration; unsigned buf = 0; size_t offset = 0; // Add vertex position pDecl->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); // Add vertex normal if (params.exportVertNorm) { pDecl->addElement(buf, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); } // Add vertex colour if(params.exportVertCol) { pDecl->addElement(buf, offset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR); } // Add texture coordinates for (i=0; i<m_vertices[0].texcoords.size(); i++) { Ogre::VertexElementType uvType = Ogre::VertexElement::multiplyTypeCount(Ogre::VET_FLOAT1, 2); pDecl->addElement(buf, offset, uvType, Ogre::VES_TEXTURE_COORDINATES, static_cast<unsigned short>(i)); offset += Ogre::VertexElement::getTypeSize(uvType); } Ogre::VertexDeclaration* pOptimalDecl = pDecl->getAutoOrganisedDeclaration( params.exportVBA, params.exportBlendShapes || params.exportVertAnims, false); // Fill the vertex buffer using the newly created vertex declaration stat = createOgreVertexBuffer(pSubmesh,pDecl,m_vertices); // Write vertex bone assignements list if (params.exportVBA) { // Create a new vertex bone assignements list Ogre::SubMesh::VertexBoneAssignmentList vbas; // Scan list of shared geometry vertices for (i=0; i<m_vertices.size(); i++) { vertex v = m_vertices[i]; // Add all bone assignemnts for every vertex to the bone assignements list for (j=0; j<v.vbas.size(); j++) { Ogre::VertexBoneAssignment vba; vba.vertexIndex = static_cast<unsigned int>(i); vba.boneIndex = v.vbas[j].jointIdx; vba.weight = v.vbas[j].weight; vbas.insert(Ogre::SubMesh::VertexBoneAssignmentList::value_type(i, vba)); } } // Rationalise the bone assignements list pSubmesh->parent->_rationaliseBoneAssignments(pSubmesh->vertexData->vertexCount,vbas); // Add bone assignements to the submesh for (Ogre::SubMesh::VertexBoneAssignmentList::iterator bi = vbas.begin(); bi != vbas.end(); bi++) { pSubmesh->addBoneAssignment(bi->second); } pSubmesh->_compileBoneAssignments(); } pSubmesh->vertexData->reorganiseBuffers(pOptimalDecl); } return true; }
FlexObj::FlexObj(node_t *nds, std::vector<CabTexcoord>& texcoords, int numtriangles, int* triangles, std::vector<CabSubmesh>& submesh_defs, char* texname, const char* name, char* backtexname, char* transtexname) { m_triangle_count = numtriangles; m_all_nodes=nds; // Create the mesh via the MeshManager m_mesh = MeshManager::getSingleton().createManual(name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // Create submeshes m_submeshes.reserve(submesh_defs.size()); for (size_t j=0; j<submesh_defs.size(); j++) { Ogre::SubMesh* submesh = m_mesh->createSubMesh(); switch (submesh_defs[j].backmesh_type) { case CabSubmesh::BACKMESH_OPAQUE: submesh->setMaterialName(backtexname); break; case CabSubmesh::BACKMESH_TRANSPARENT: submesh->setMaterialName(transtexname); break; default: submesh->setMaterialName(texname); } m_submeshes.push_back(submesh); }; // Define the m_vertices_raw (8 vertices, each consisting of 3 groups of 3 floats m_vertex_count = texcoords.size(); m_vertices_raw=(float*)malloc(((2*3+2)*m_vertex_count)*sizeof(float)); m_vertex_nodes=(int*)malloc(m_vertex_count*sizeof(int)); for (size_t i=0; i<m_vertex_count; i++) { m_vertex_nodes[i] = texcoords[i].node_id; //define node ids m_vertices[i].texcoord=Vector2(texcoords[i].texcoord_u, texcoords[i].texcoord_v); //textures coordinates } // Define triangles // The values in this table refer to vertices in the above table m_index_count = 3*numtriangles; m_indices=(unsigned short*)malloc(m_index_count*sizeof(unsigned short)); for (size_t i=0; i<m_index_count; i++) { m_indices[i]=ComputeVertexPos(i/3, triangles[i], submesh_defs); } m_s_ref=(float*)malloc(numtriangles*sizeof(float)); for (size_t i=0; i<(unsigned int)numtriangles;i++) { Ogre::Vector3 base_pos = m_all_nodes[m_vertex_nodes[m_indices[i*3]]].RelPosition; Ogre::Vector3 v1 = m_all_nodes[m_vertex_nodes[m_indices[i*3+1]]].RelPosition - base_pos; Ogre::Vector3 v2 = m_all_nodes[m_vertex_nodes[m_indices[i*3+2]]].RelPosition - base_pos; m_s_ref[i]=v1.crossProduct(v2).length()*2.0; } this->UpdateMesh(); // Initialize the dynamic mesh // Create vertex data structure for vertices shared between submeshes m_mesh->sharedVertexData = new VertexData(); m_mesh->sharedVertexData->vertexCount = m_vertex_count; // Create declaration (memory format) of vertex data m_vertex_format = m_mesh->sharedVertexData->vertexDeclaration; size_t offset = 0; m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); m_vertex_format->addElement(0, offset, VET_FLOAT3, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT3); m_vertex_format->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); offset += VertexElement::getTypeSize(VET_FLOAT2); // Allocate vertex buffer of the requested number of vertices (vertexCount) // and bytes per vertex (offset) m_hw_vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( offset, m_mesh->sharedVertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); // Upload the vertex data to the card m_hw_vbuf->writeData(0, m_hw_vbuf->getSizeInBytes(), m_vertices_raw, true); // Set vertex buffer binding so buffer 0 is bound to our vertex buffer VertexBufferBinding* bind = m_mesh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, m_hw_vbuf); // Set parameters of the submeshes for (size_t j=0; j<m_submeshes.size(); j++) { size_t index_count; if (j == 0) index_count = 3*submesh_defs[j].cabs_pos; else index_count = 3*(submesh_defs[j].cabs_pos-submesh_defs[j-1].cabs_pos); // 3 indices per triangle m_submeshes[j]->useSharedVertices = true; HardwareIndexBufferSharedPtr ibuf = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, index_count, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Upload the index data to the card unsigned short* faces_ptr; if (j == 0) faces_ptr = &m_indices[0]; else faces_ptr = &m_indices[submesh_defs[j-1].cabs_pos * 3]; ibuf->writeData(0, ibuf->getSizeInBytes(), faces_ptr, true); m_submeshes[j]->indexData->indexBuffer = ibuf; m_submeshes[j]->indexData->indexCount = index_count; m_submeshes[j]->indexData->indexStart = 0; } // Set bounding information (for culling) m_mesh->_setBounds(AxisAlignedBox(-100,-100,-100,100,100,100), true); // Notify Mesh object that it has been loaded m_mesh->load(); }
Mesh* OgreSubsystem::createMesh(const MeshData& data,String name) { String nombre = name; if(name=="AUTO_NAME_ME") { nombre = "OryxSceneNodeAutoNamed"+StringUtils::toString(mAutoNameIndex); ++mAutoNameIndex; } using namespace Ogre; bool hasVertexColor = data.getDiffuse(); bool hasNormals = data.getNormals(); int numFaces = data.indices.size()/3; int numVertices = data.vertices.size()/3; HardwareVertexBufferSharedPtr posVertexBuffer; HardwareVertexBufferSharedPtr normVertexBuffer; std::vector<HardwareVertexBufferSharedPtr> texcoordsVertexBuffer; HardwareVertexBufferSharedPtr diffuseVertexBuffer; HardwareIndexBufferSharedPtr indexBuffer; Ogre::Mesh* m = Ogre::MeshManager::getSingletonPtr()->createManual( nombre,ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME).get(); Ogre::SubMesh* sm = m->createSubMesh(); sm->useSharedVertices = false; sm->vertexData = new VertexData(); sm->vertexData->vertexStart = 0; sm->vertexData->vertexCount = numVertices; Ogre::VertexDeclaration* vdecl = sm->vertexData->vertexDeclaration; Ogre::VertexBufferBinding* vbind = sm->vertexData->vertexBufferBinding; size_t bufferCount = 0; vdecl->addElement(bufferCount, 0, VET_FLOAT3, VES_POSITION); if(hasNormals) vdecl->addElement(++bufferCount, 0, VET_FLOAT3, VES_NORMAL); if(hasVertexColor) vdecl->addElement(++bufferCount, 0, VET_FLOAT4, VES_DIFFUSE); for(int i=0;i<data.texcoords.size();++i) vdecl->addElement(++bufferCount, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES,i); bufferCount = 0; // Positions posVertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( 3*sizeof(float),numVertices,Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); vbind->setBinding(bufferCount, posVertexBuffer); float* vertices = data.getVertices(); float* normals = data.getNormals(); float* diffuse = data.getDiffuse(); unsigned short* indices = data.getIndices(); posVertexBuffer->writeData(0,posVertexBuffer->getSizeInBytes(),vertices, true); // Normals if(hasNormals) { normVertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( 3*sizeof(float),numVertices,HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); vbind->setBinding(++bufferCount, normVertexBuffer); normVertexBuffer->writeData(0,normVertexBuffer->getSizeInBytes(),normals, true); } if(hasVertexColor) { diffuseVertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( 4*sizeof(float),numVertices,HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbind->setBinding(++bufferCount, diffuseVertexBuffer); diffuseVertexBuffer->writeData(0,diffuseVertexBuffer->getSizeInBytes(), diffuse, true); } // Texcoords for(int i=0;i<data.texcoords.size();++i) { texcoordsVertexBuffer.push_back(HardwareBufferManager::getSingleton().createVertexBuffer( 2*sizeof(float),numVertices,HardwareBuffer::HBU_STATIC_WRITE_ONLY)); vbind->setBinding(++bufferCount, texcoordsVertexBuffer[i]); texcoordsVertexBuffer[i]->writeData(0,sizeof(float)*data.texcoords[i].size(),&data.texcoords[i][0], false); } if(!data.indices.empty()) { // Prepare buffer for indices indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT,3*numFaces,HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); //unsigned short *faceVertexIndices = (unsigned short*) //indexBuffer->lock(0, numFaces*3*2, HardwareBuffer::HBL_DISCARD); // Set index buffer for this submesh sm->indexData->indexBuffer = indexBuffer; sm->indexData->indexStart = 0; sm->indexData->indexCount = 3*numFaces; indexBuffer->writeData(0,indexBuffer->getSizeInBytes(),indices,true); } //vdecl->sort(); m->load(); m->touch(); m->_setBounds(AxisAlignedBox(data.bbox[0],data.bbox[1],data.bbox[2], data.bbox[3],data.bbox[4],data.bbox[5]), false); sm->setMaterialName("Terrain"); Ogre::Entity* ent = mSceneManager->createEntity(nombre,m->getName()); Ogre::SceneNode* node = mSceneManager->createSceneNode(nombre); node->attachObject(ent); ent->setCastShadows(false); Mesh* mm = new Mesh(nombre,node,ent); mSceneNodes.push_back(mm); return mm; }
void WaterObjectView::createLine() { size_t verticesCount = ((mWaterObject->getPointCount() - 1) * mSegments + 1) * 2; size_t verticesSize = verticesCount * 5; size_t indicesSize = ((mWaterObject->getPointCount() - 1) * mSegments) * 6; verticesCount = mWaterObject->getPointCount() * 2; verticesSize = verticesCount * 5; indicesSize = (mWaterObject->getPointCount() - 1) * 6; Ogre::Real* vertices = new Ogre::Real[verticesSize]; Ogre::uint16* indices = new Ogre::uint16[indicesSize]; unsigned int i, index = 0; // Prepare vertices. for (i = 0; i < mWaterObject->getPointCount(); ++i) { const Point3D& point3D = mWaterObject->getPoint(i); vertices[index++] = point3D.x - mWaterObject->getWidth() * 0.5f; vertices[index++] = point3D.y; vertices[index++] = point3D.z + 1.0f; vertices[index++] = point3D.x - mWaterObject->getWidth() * 0.5f;; vertices[index++] = point3D.z; vertices[index++] = point3D.x + mWaterObject->getWidth() * 0.5f; vertices[index++] = point3D.y; vertices[index++] = point3D.z + 1.0f; vertices[index++] = point3D.x + mWaterObject->getWidth() * 0.5f; vertices[index++] = point3D.z; } index = 0; // Prepare indices. for (i = 0; i < verticesCount - 2; i += 2) { indices[index++] = (Ogre::uint16)i; indices[index++] = (Ogre::uint16)i + 2; indices[index++] = (Ogre::uint16)i + 1; indices[index++] = (Ogre::uint16)i + 2; indices[index++] = (Ogre::uint16)i + 3; indices[index++] = (Ogre::uint16)i + 1; } // Create mesh. mMesh = Ogre::MeshManager::getSingleton().createManual( Ogre::StringConverter::toString(mID), "General").get(); // Create one submesh. Ogre::SubMesh* sub = mMesh->createSubMesh(); // Create vertex data structure for 8 vertices shared between submeshes. mMesh->sharedVertexData = new Ogre::VertexData(); mMesh->sharedVertexData->vertexCount = verticesCount; // Create declaration (memory format) of vertex data. Ogre::VertexDeclaration* decl = mMesh->sharedVertexData->vertexDeclaration; size_t offset = 0; // 1st buffer decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); decl->addElement(0, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT2); /// Allocate vertex buffer of the requested number of vertices (vertexCount) /// and bytes per vertex (offset) Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( offset, mMesh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the vertex data to the card vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer Ogre::VertexBufferBinding* bind = mMesh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, vbuf); /// Allocate index buffer of the requested number of vertices (ibufCount). Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton(). createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT, indicesSize, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); /// Upload the index data to the card. ibuf->writeData(0, ibuf->getSizeInBytes(), indices, true); /// Set parameters of the submesh. sub->useSharedVertices = true; sub->indexData->indexBuffer = ibuf; sub->indexData->indexCount = indicesSize; sub->indexData->indexStart = 0; sub->setMaterialName("Ocean2_Cg"); float xMin = vertices[0]; float yMin = vertices[1]; float zMin = vertices[2]; float xMax = vertices[0]; float yMax = vertices[1]; float zMax = vertices[2]; for (i = 0; i < verticesSize; i += 5) { if (vertices[i ] < xMin) xMin = vertices[i ]; else if (vertices[i ] > xMax) xMax = vertices[i ]; if (vertices[i + 1] < yMin) yMin = vertices[i + 1]; else if (vertices[i + 1] > yMax) yMax = vertices[i + 1]; if (vertices[i + 2] < zMin) zMin = vertices[i + 2]; else if (vertices[i + 2] > zMax) zMax = vertices[i + 2]; } /// Set bounding information (for culling). mMesh->_setBounds(Ogre::AxisAlignedBox(xMin, yMin, zMin, xMax, yMax, zMax)); mMesh->_setBoundingSphereRadius(1.0f); /// Notify Mesh object that it has been loaded. mMesh->load(); delete [] vertices; delete [] indices; }
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; }