void gfx_decal_init (void) { // TODO: The 4x3 transform will need to be // TODO: Eventually we'd like this uv rect to be configurable per decal. Vector2 uv1(0, 0); Vector2 uv2(1, 1); box_op.operationType = Ogre::RenderOperation::OT_TRIANGLE_LIST; Ogre::VertexData *vdata = OGRE_NEW Ogre::VertexData(); box_op.vertexData = vdata; vdata->vertexStart = 0; const unsigned vertex_count = 8; vdata->vertexCount = vertex_count; unsigned vdecl_size = 0; // strict alignment required here struct Vertex { Vector3 position; Vector2 uv1; Vector2 uv2; }; vdecl_size += vdata->vertexDeclaration->addElement( 0, vdecl_size, Ogre::VET_FLOAT3, Ogre::VES_POSITION).getSize(); vdecl_size += vdata->vertexDeclaration->addElement( 0, vdecl_size, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0).getSize(); vdecl_size += vdata->vertexDeclaration->addElement( 0, vdecl_size, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 1).getSize(); Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( vdecl_size, vdata->vertexCount, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); vdata->vertexBufferBinding->setBinding(0, vbuf); Vertex vdata_raw[vertex_count] = { { Vector3(-0.5, -0.5, -0.5), uv1, uv2 }, { Vector3(-0.5, -0.5, 0.5), uv1, uv2 }, { Vector3(-0.5, 0.5, -0.5), uv1, uv2 }, { Vector3(-0.5, 0.5, 0.5), uv1, uv2 }, { Vector3( 0.5, -0.5, -0.5), uv1, uv2 }, { Vector3( 0.5, -0.5, 0.5), uv1, uv2 }, { Vector3( 0.5, 0.5, -0.5), uv1, uv2 }, { Vector3( 0.5, 0.5, 0.5), uv1, uv2 } }; vbuf->writeData(vdata->vertexStart, vdata->vertexCount*vdecl_size, vdata_raw, true); Ogre::IndexData *idata = OGRE_NEW Ogre::IndexData(); box_op.indexData = idata; box_op.useIndexes = true; const unsigned indexes = 36; // 3 per triangle therefore 6 per face, 6 faces total idata->indexStart = 0; idata->indexCount = indexes; idata->indexBuffer = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_16BIT, indexes, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); uint16_t idata_raw[indexes] = { quad_vertexes(2,6,0,4), quad_vertexes(7,3,5,1), quad_vertexes(3,2,1,0), quad_vertexes(6,7,4,5), quad_vertexes(0,4,1,5), quad_vertexes(3,7,2,6) }; idata->indexBuffer->writeData(0, sizeof(idata_raw), idata_raw, true); }
void ESKOgre::createFakeEntity(Ogre::SceneManager *mSceneMgr) { Ogre::MeshPtr msh = Ogre::MeshManager::getSingleton().createManual(name + "_skeleton", XENOVIEWER_RESOURCE_GROUP); msh->setSkeletonName(name); Ogre::SubMesh* sub = msh->createSubMesh(); const size_t nVertices = 3; const size_t nVertCount = 3; const size_t vbufCount = nVertCount*nVertices; float *vertices = (float *)malloc(sizeof(float)*vbufCount); for (size_t i = 0; i < nVertices; i++) { vertices[i*nVertCount] = 0.0; vertices[i*nVertCount + 1] = 0.0; vertices[i*nVertCount + 2] = 0.0; } const size_t ibufCount = 3; unsigned short *faces = (unsigned short *)malloc(sizeof(unsigned short) * ibufCount); for (size_t i = 0; i < ibufCount; i++) { faces[i] = i; } msh->sharedVertexData = new Ogre::VertexData(); msh->sharedVertexData->vertexCount = nVertices; Ogre::VertexDeclaration* decl = msh->sharedVertexData->vertexDeclaration; size_t offset = 0; decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(offset, msh->sharedVertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); Ogre::VertexBufferBinding* bind = msh->sharedVertexData->vertexBufferBinding; bind->setBinding(0, vbuf); 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; msh->_setBounds(Ogre::AxisAlignedBox(-100, -100, -100, 100, 100, 100)); msh->_setBoundingSphereRadius(100); msh->load(); free(faces); free(vertices); skeleton_entity = mSceneMgr->createEntity(name + "_skeleton"); skeleton_node = mSceneMgr->getRootSceneNode()->createChildSceneNode(); skeleton_node->attachObject(skeleton_entity); skeleton_node->setVisible(false); }
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 EMDOgre::createOgreMesh(EMDSubmesh *submesh, string mesh_name) { string ogre_mesh_name = mesh_name + "_" + submesh->getMaterialName(); Ogre::MeshPtr ogre_mesh = Ogre::MeshManager::getSingleton().createManual(ogre_mesh_name, XENOVIEWER_RESOURCE_GROUP); LibXenoverse::AABB mesh_aabb; mesh_aabb.reset(); if (skeleton) { ogre_mesh->setSkeletonName(skeleton->getName()); } // Create Vertex Pool vector<EMDVertex> submesh_vertices = submesh->getVertices(); const size_t nVertices = submesh_vertices.size(); const size_t nVertCount = 8; const size_t vbufCount = nVertCount*nVertices; float *vertices = (float *)malloc(sizeof(float)*vbufCount); for (size_t i = 0; i < nVertices; i++) { vertices[i*nVertCount] = submesh_vertices[i].x; vertices[i*nVertCount + 1] = submesh_vertices[i].y; vertices[i*nVertCount + 2] = submesh_vertices[i].z; vertices[i*nVertCount + 3] = submesh_vertices[i].nx; vertices[i*nVertCount + 4] = submesh_vertices[i].ny; vertices[i*nVertCount + 5] = submesh_vertices[i].nz; vertices[i*nVertCount + 6] = submesh_vertices[i].u; vertices[i*nVertCount + 7] = submesh_vertices[i].v; mesh_aabb.addPoint(submesh_vertices[i].x, submesh_vertices[i].y, submesh_vertices[i].z); } // Create Submeshes for each Triangle List vector<EMDTriangles> submesh_triangles = submesh->getTriangles(); for (size_t i = 0; i < submesh_triangles.size(); i++) { Ogre::SubMesh *sub = createOgreSubmesh(&submesh_triangles[i], ogre_mesh); } // Create Shared Vertex Data for all submeshes Ogre::VertexData *vertex_data = new Ogre::VertexData(); ogre_mesh->sharedVertexData = vertex_data; vertex_data->vertexCount = nVertices; Ogre::VertexDeclaration* decl = vertex_data->vertexDeclaration; size_t offset = 0; decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); 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); Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(offset, nVertices, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbuf->writeData(0, vbuf->getSizeInBytes(), vertices, true); Ogre::VertexBufferBinding* bind = vertex_data->vertexBufferBinding; bind->setBinding(0, vbuf); // Create Bone Assignments if Skeleton name exists if (skeleton) { Ogre::Skeleton *ogre_skeleton = skeleton->getOgreSkeleton(); if (ogre_skeleton) { for (size_t i = 0; i < submesh_triangles.size(); i++) { EMDTriangles *triangles = &submesh_triangles[i]; vector<unsigned int> vertex_indices; size_t face_count = triangles->faces.size(); // Make a list of all vertex indices being used in the submesh vertex_indices.reserve(face_count); for (size_t j = 0; j < face_count; j++) { bool found = false; for (size_t k = 0; k < vertex_indices.size(); k++) { if (vertex_indices[k] == triangles->faces[j]) { found = true; break; } } if (!found) vertex_indices.push_back(triangles->faces[j]); } // Build Bone Mapping Table vector<unsigned short> bone_table; bone_table.resize(triangles->bone_names.size()); for (size_t j = 0; j < bone_table.size(); j++) { string bone_name = triangles->bone_names[j]; LOG_DEBUG("Bone Skin Table %d: %s\n", j, bone_name.c_str()); if (ogre_skeleton->hasBone(bone_name)) { Ogre::Bone *mBone = ogre_skeleton->getBone(bone_name); bone_table[j] = mBone->getHandle(); } else { LOG_DEBUG("Couldn't find %s in ogre skeleton!\n", bone_name.c_str()); } } // Add bone assignments to all the vertices that were found for (size_t j = 0; j < vertex_indices.size(); j++) { Ogre::VertexBoneAssignment vba; vba.vertexIndex = vertex_indices[j]; EMDVertex *vertex = &submesh_vertices[vba.vertexIndex]; for (size_t k = 0; k < 4; k++) { unsigned char bone_index = vertex->bone[3 - k]; float bone_weight = vertex->bone_weight[k]; if (bone_weight > 0.0f) { vba.boneIndex = bone_table[bone_index]; vba.weight = bone_weight; ogre_mesh->addBoneAssignment(vba); } } } } // Apply changes, build the buffer ogre_mesh->_compileBoneAssignments(); ogre_mesh->sharedVertexData->reorganiseBuffers(decl->getAutoOrganisedDeclaration(true, false, false)); } } //ogre_mesh->_setBounds(Ogre::AxisAlignedBox(mesh_aabb.start_x, mesh_aabb.start_y, mesh_aabb.start_z, mesh_aabb.end_x, mesh_aabb.end_y, mesh_aabb.end_z)); ogre_mesh->_setBounds(Ogre::AxisAlignedBox(-1000, -1000, -1000, 1000, 1000, 1000)); ogre_mesh->_setBoundingSphereRadius(mesh_aabb.sizeMax()); ogre_mesh->load(); free(vertices); created_meshes.push_back(ogre_mesh_name); }
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); }
Ogre::SceneNode *TutorialApplication::loadBSP(std::shared_ptr<l2p::UModel> m, bool ignoreNonVisible) { l2p::Name name = m->package->name; std::vector<float> vertex_data; std::vector<uint32_t> index_buf; l2p::Box bounds; // Build vertex and index buffer. for (auto ni = m->nodes.begin(), ne = m->nodes.end(); ni != ne; ++ni) { l2p::BSPNode &n = *ni; l2p::BSPSurface &s = m->surfaces[n.surface]; if (ignoreNonVisible && ignoreNode(m.get(), n, s)) continue; uint32_t vert_start = vertex_data.size() / 8; const Ogre::Vector3 uvec = ogre_cast(m->vectors[s.U]); const Ogre::Vector3 vvec = ogre_cast(m->vectors[s.V]); const Ogre::Vector3 base = ogre_cast(m->points[s.base]); int usize = 0; int vsize = 0; std::shared_ptr<l2p::UTexture> mat = s.material; if (mat) { usize = mat->USize; vsize = mat->VSize; } if (usize == 0 || vsize == 0) usize = vsize = 64; // Vertex buffer. if (n.num_verticies > 0) { l2p::Vector Normal = m->vectors[s.normal]; for (uint32_t vert_index = 0; vert_index < n.num_verticies; ++vert_index) { const l2p::Vector &pos = m->points[m->vertexes[n.vert_pool + vert_index].vertex]; const Ogre::Vector3 dist(ogre_cast(pos) - base); const Ogre::Vector2 tcoord((dist | uvec) / float(usize), (dist | vvec) / float(vsize)); bounds += pos; vertex_data.push_back(pos.X); vertex_data.push_back(pos.Y); vertex_data.push_back(pos.Z); vertex_data.push_back(Normal.X); vertex_data.push_back(Normal.Y); vertex_data.push_back(Normal.Z); vertex_data.push_back(tcoord.x); vertex_data.push_back(tcoord.y); } if (s.flags & l2p::PF_TwoSided) { for (uint32_t vert_index = 0; vert_index < n.num_verticies; ++vert_index) { const l2p::Vector &pos = m->points[m->vertexes[n.vert_pool + vert_index].vertex]; const Ogre::Vector3 dist(ogre_cast(pos) - base); const Ogre::Vector2 tcoord((dist | uvec) / float(usize), (dist | vvec) / float(vsize)); vertex_data.push_back(pos.X); vertex_data.push_back(pos.Y); vertex_data.push_back(pos.Z); vertex_data.push_back(Normal.X); vertex_data.push_back(Normal.Y); vertex_data.push_back(-Normal.Z); vertex_data.push_back(tcoord.x); vertex_data.push_back(tcoord.y); } } } // Index buffer. for (int verti = 2; verti < n.num_verticies; ++verti) { index_buf.push_back(vert_start); index_buf.push_back(vert_start + verti - 1); index_buf.push_back(vert_start + verti); } if (s.flags & l2p::PF_TwoSided) { for (int verti = 2; verti < n.num_verticies; ++verti) { index_buf.push_back(vert_start); index_buf.push_back(vert_start + verti); index_buf.push_back(vert_start + verti - 1); } } } if (vertex_data.size() == 0 || index_buf.size() == 0) return nullptr; Ogre::MeshPtr mesh = Ogre::MeshManager::getSingleton().createManual(Ogre::String(name) + Ogre::String(m->name), "General"); Ogre::VertexData *data = new Ogre::VertexData(); mesh->sharedVertexData = data; data->vertexCount = vertex_data.size() / 8; Ogre::VertexDeclaration *decl = data->vertexDeclaration; uint32_t offset = 0; decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); offset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); decl->addElement(0, offset, Ogre::VET_FLOAT3, Ogre::VES_NORMAL); 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); Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( offset, data->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); vbuf->writeData(0, vbuf->getSizeInBytes(), &vertex_data.front(), true); data->vertexBufferBinding->setBinding(0, vbuf); // Setup index buffer. Ogre::HardwareIndexBufferSharedPtr ibuf = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer( Ogre::HardwareIndexBuffer::IT_32BIT, index_buf.size(), Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); ibuf->writeData(0, ibuf->getSizeInBytes(), &index_buf.front(), true); Ogre::SubMesh *subMesh = mesh->createSubMesh(); subMesh->useSharedVertices = true; subMesh->indexData->indexBuffer = ibuf; subMesh->indexData->indexCount = index_buf.size(); subMesh->indexData->indexStart = 0; mesh->_setBounds(Ogre::AxisAlignedBox(bounds.min.X, bounds.min.Y, bounds.min.Z, bounds.max.X, bounds.max.Y, bounds.max.Z)); mesh->_setBoundingSphereRadius((std::max(bounds.max.X - bounds.min.X, std::max(bounds.max.Y - bounds.min.Y, bounds.max.Z - bounds.min.Z))) / 2.0); mesh->load(); Ogre::Entity *ent = mSceneMgr->createEntity(Ogre::String(name) + Ogre::String(m->name) + "E", Ogre::String(name) + Ogre::String(m->name)); ent->setUserAny(Ogre::Any(static_cast<l2p::UObject*>(m.get()))); ent->setMaterialName("StaticMesh/Default"); Ogre::SceneNode *node = mUnrealCordNode->createChildSceneNode(); node->attachObject(ent); return node; }
void ChunkBase::generateMesh() { if (!mIsModified) return; generateVertices(); if (isEmpty) { return; } uint32_t numVertices, numIndices; if (mNumVertices > DefaultFaces * 4) { // more vertices than the default buffer can hold -> allocate new one; if (mVertexBufferCreated) { removeMesh(); } numVertices = mNumVertices; numIndices = mNumIndices; } else { numVertices = DefaultFaces * 4; numIndices = DefaultFaces * 6; } if (!mVertexBufferCreated) { mMeshPtr = Ogre::MeshManager::getSingleton().createManual(mChunkName, "Game"); Ogre::SubMesh* sub = mMeshPtr->createSubMesh(); /// Create vertex data structure for 8 vertices shared between submeshes mMeshPtr->sharedVertexData = new Ogre::VertexData(); mMeshPtr->sharedVertexData->vertexCount = mNumVertices; /// Create declaration (memory format) of vertex data Ogre::VertexDeclaration* decl = mMeshPtr->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_FLOAT3, Ogre::VES_NORMAL); 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, numVertices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); /// Upload the vertex data to the card vbuf->writeData(0, (decl->getVertexSize(0) * mNumVertices), mVertices, true); /// Set vertex buffer binding so buffer 0 is bound to our vertex buffer Ogre::VertexBufferBinding* bind = mMeshPtr->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, numIndices, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); /// Upload the index data to the card ibuf->writeData(0, (ibuf->getIndexSize() * mNumIndices), mIndices, true); /// Set parameters of the submesh sub->indexData->indexBuffer = ibuf; sub->indexData->indexCount = mNumIndices; /// Set bounding information (for culling) mMeshPtr->_setBounds(Ogre::AxisAlignedBox(0, 0, 0, Ogre::Real(ChunkSizeX), Ogre::Real(mHighestCube), Ogre::Real(ChunkSizeZ))); mMeshPtr->_setBoundingSphereRadius((Ogre::Real) std::sqrt((float) (2 * 16 * 16 + 128 * 128))); /// Notify -Mesh object that it has been loaded mMeshPtr->load(); mVertexBufferCreated = true; } else { Ogre::VertexDeclaration* decl = mMeshPtr->sharedVertexData->vertexDeclaration; mMeshPtr->sharedVertexData->vertexCount = mNumVertices; Ogre::SubMesh* sub = mMeshPtr->getSubMesh(0); sub->indexData->indexCount = mNumIndices; /// Upload the new vertex data to the card Ogre::HardwareVertexBufferSharedPtr vbuf = mMeshPtr->sharedVertexData->vertexBufferBinding->getBuffer(0); vbuf->writeData(0, (decl->getVertexSize(0) * mNumVertices), mVertices, true); /// Upload the index data to the card Ogre::HardwareIndexBufferSharedPtr ibuf = sub->indexData->indexBuffer; ibuf->writeData(0, (ibuf->getIndexSize() * mNumIndices), mIndices, true); mMeshPtr->_setBounds(Ogre::AxisAlignedBox(0, 0, 0, Ogre::Real(ChunkSizeX), Ogre::Real(mHighestCube), Ogre::Real(ChunkSizeZ))); mMeshPtr->load(); } }
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; }