void FrameGraphRenderable::drawGraphLine(TimeGraphLine& line, uint16_t graphLine) { Ogre::Real ogreTop, bulletTop, worldTop, unknownTop; ogreTop = (line.ogre / mCurrentScaling); bulletTop = ogreTop + (line.bullet / mCurrentScaling); worldTop = bulletTop + (line.world / mCurrentScaling); unknownTop = worldTop + (line.unknown / mCurrentScaling); ogreTop = ogreTop * 2 - 1.0f; bulletTop = bulletTop * 2 - 1.0f; worldTop = worldTop * 2 - 1.0f; unknownTop = unknownTop * 2 - 1.0f; Ogre::HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); Ogre::Real *vertices = static_cast<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); vertices += graphLine * ValuesPerGraphLine; // Set the ogre line top vertex vertices[ 4] = ogreTop; // Set the bullet line vertices vertices[ 7] = ogreTop; vertices[10] = bulletTop; // Set the world line vertices vertices[13] = bulletTop; vertices[16] = worldTop; // Set the unknown line vertices vertices[19] = worldTop; vertices[22] = unknownTop; vbuf->unlock(); }
void processPositionElement( VertexData* vertexData, const VertexElement* vertexElem ) { int nMaxVert= vertexData->vertexCount ; //const Ogre::VertexElement* VertexEle_POS = vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_POSITION ); // get vertex buffer info via the input element Ogre::HardwareVertexBufferSharedPtr VertexBufPOS = vertexData->vertexBufferBinding->getBuffer( vertexElem->getSource() ); //LOCK BUFFER unsigned char* VertexPtrPOS = static_cast<unsigned char*>( VertexBufPOS->lock( Ogre::HardwareBuffer::HBL_NORMAL) ); int VertSizePOS=VertexBufPOS->getVertexSize(); float * pElementPOS=NULL; //A vector of every vertices position std::vector<Ogre::Vector3> positions(nMaxVert); //Copy each position into position vector for(int nVert=0 ; nVert<nMaxVert ; nVert++) { vertexElem->baseVertexPointerToElement( VertexPtrPOS, &pElementPOS ); Ogre::Vector3 vertex(pElementPOS); vertex = mTransform * vertex; pElementPOS[0] = vertex.x; pElementPOS[1] = vertex.y; pElementPOS[2] = vertex.z; mBoundingBox.merge(vertex); VertexPtrPOS+=VertSizePOS ; } //UNLOCK BUFFER if(VertexBufPOS->isLocked()){VertexBufPOS->unlock();} }
void Selection2D::setCorners(Ogre::Real left, Ogre::Real top, Ogre::Real right, Ogre::Real bottom, bool updateAABB) { Ogre::HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); float* pFloat = static_cast<float*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); *pFloat++ = left; *pFloat++ = top; *pFloat++ = -1; *pFloat++ = left; *pFloat++ = bottom; *pFloat++ = -1; *pFloat++ = right; *pFloat++ = bottom; *pFloat++ = -1; *pFloat++ = right; *pFloat++ = top; *pFloat++ = -1; *pFloat++ = left; *pFloat++ = top; *pFloat++ = -1; vbuf->unlock(); if(updateAABB) { mBox.setExtents( std::min(left, right), std::min(top, bottom), 0, std::max(left, right), std::max(top, bottom), 0); } }
void FrameGraphRenderable::redrawGraph() { Ogre::Real ogreTop, bulletTop, worldTop, unknownTop; Ogre::HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); Ogre::Real *vertices = static_cast<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); for (size_t i = 0; i < mNumFrames; i++) { ogreTop = (mlastTimes[i].ogre / mCurrentScaling); bulletTop = ogreTop + (mlastTimes[i].bullet / mCurrentScaling); worldTop = bulletTop + (mlastTimes[i].world / mCurrentScaling); unknownTop = worldTop + (mlastTimes[i].unknown / mCurrentScaling); ogreTop = ogreTop * 2 - 1.0f; bulletTop = bulletTop * 2 - 1.0f; worldTop = worldTop * 2 - 1.0f; unknownTop = unknownTop * 2 - 1.0f; // Set the ogre line top vertex vertices[ 4] = ogreTop; // Set the bullet line vertices vertices[ 7] = ogreTop; vertices[10] = bulletTop; // Set the world line vertices vertices[13] = bulletTop; vertices[16] = worldTop; // Set the unknown line vertices vertices[19] = worldTop; vertices[22] = unknownTop; vertices += ValuesPerGraphLine; } vbuf->unlock(); }
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 DynamicLines::fillHardwareBuffers() { unsigned int size = (unsigned int)mPoints.size(); prepareHardwareBuffers(size, 0); if(!size) { mBox.setExtents(Ogre::Vector3::ZERO, Ogre::Vector3::ZERO); mDirty = false; return; } Ogre::Vector3 vaabMin = mPoints[0]; Ogre::Vector3 vaabMax = mPoints[0]; Ogre::HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); Ogre::Real *prPos = static_cast<Ogre::Real *>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); { for(unsigned int i = 0; i < size; i++) { *prPos++ = mPoints[i].x; *prPos++ = mPoints[i].y; *prPos++ = mPoints[i].z; if(!mUse2D) { if(mPoints[i].x < vaabMin.x) vaabMin.x = mPoints[i].x; if(mPoints[i].y < vaabMin.y) vaabMin.y = mPoints[i].y; if(mPoints[i].z < vaabMin.z) vaabMin.z = mPoints[i].z; if(mPoints[i].x > vaabMax.x) vaabMax.x = mPoints[i].x; if(mPoints[i].y > vaabMax.y) vaabMax.y = mPoints[i].y; if(mPoints[i].z > vaabMax.z) vaabMax.z = mPoints[i].z; } } } vbuf->unlock(); if(mUse2D) mBox.setInfinite(); else mBox.setExtents(vaabMin, vaabMax); mDirty = false; }
void TerrainTileEditable::_notifyHeightModified(int xstart, int zstart, int xend, int zend) { assert(0 <= xstart && xstart < xend && xend <= mXSize+1); assert(0 <= zstart && zstart < zend && zend <= mZSize+1); if (mVertexDatas.empty()) { // Nothing todo when buffer never initialised return; } // TODO: (optimization) some grid may be need to recompute normal only TerrainData* data = mOwner->getData(); Ogre::HardwareVertexBufferSharedPtr posNormBuffer = mVertexDatas.front()->vertexBufferBinding->getBuffer(0); float* pPosNormBuffer = static_cast<float*>(posNormBuffer->lock(Ogre::HardwareBuffer::HBL_NORMAL)); float buffer[6]; int xsize = mXSize; int zsize = mZSize; int xbase = mXBase; int zbase = mZBase; for (int z = zstart; z < zend; ++z) { for (int x = xstart; x < xend; ++x) { Ogre::Vector3 v; v = data->_getPosition(x+xbase, z+zbase); buffer[0] = v.x; buffer[1] = v.y; buffer[2] = v.z; v = data->_getNormal(x+xbase, z+zbase); buffer[3] = v.x; buffer[4] = v.y; buffer[5] = v.z; if (0 < z) { if (0 < x) memcpy(pPosNormBuffer + (((z-1) * xsize + (x-1)) * 4 + 3) * 6, buffer, 6*sizeof(float)); if (x < xsize) memcpy(pPosNormBuffer + (((z-1) * xsize + (x-0)) * 4 + 2) * 6, buffer, 6*sizeof(float)); } if (z < zsize) { if (0 < x) memcpy(pPosNormBuffer + (((z-0) * xsize + (x-1)) * 4 + 1) * 6, buffer, 6*sizeof(float)); if (x < xsize) memcpy(pPosNormBuffer + (((z-0) * xsize + (x-0)) * 4 + 0) * 6, buffer, 6*sizeof(float)); } } } posNormBuffer->unlock(); // re-compue bounding box data->_computeTileBoundingBox(mBounds, xbase, zbase, xsize, zsize); // trigger update of bounding box getParentNode()->needUpdate(); }
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 GrassPatch::Update(const Ogre::Vector3 &sphere_center, float sphere_radius, Ogre::Real t) { int i; static bool inited = false; Ogre::Vector3 delta; float length; int end=0; Ogre::Vector3 a, b; float radius=sphere_radius*sphere_radius*2.2; // Update the particle field m_Particles->Step(0.001f); // use of t ? Ogre::HardwareVertexBufferSharedPtr vVertices = mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING); Ogre::Real *pVertices = static_cast<Ogre::Real*>( vVertices->lock( //Ogre::HardwareBuffer::HBL_DISCARD Ogre::HardwareBuffer::HBL_NORMAL ) ); // Upload new blade positions if(!inited) { for (i = 0; i < m_NbBlades; i++) { m_Blades[i]->Constrain(sphere_center, sphere_radius); m_Particles->GetGrassParticle(i).ClearForce(); m_Blades[i]->UpdateVertexBuffer(i, pVertices); } inited=true; vVertices->unlock(); } else { for (i = 0; i < m_NbBlades; i++) { m_Blades[i]-> GetPosition(a); delta = a - sphere_center; length = delta.x * delta.x + delta.y * delta.y+ delta.z*delta.z; if ((m_Blades[i]->moving)||(length-radius<0)) { m_Blades[i]->Constrain(sphere_center, sphere_radius); m_Particles->GetGrassParticle(i).ClearForce(); m_Blades[i]->UpdateVertexBuffer(i, pVertices); end++; } } vVertices->unlock(); } int ttt = sprintf(iterations, "Iterations: %d ", end); end=0; }
void ImGuiInterface::RenderDrawLists(ImDrawList** const cmdLists, int cmdListsCount) { // Assume render system is configured according to InterfaceManager::_configureRenderSystem mRenderSystem->_setWorldMatrix(Ogre::Matrix4::IDENTITY); // For each command list for (int i = 0; i < cmdListsCount; i++) { ImVector<ImDrawCmd>& commands = cmdLists[i]->commands; // Allocate more space if needed if (mSize < cmdLists[i]->vtx_buffer.size()) { mSize = cmdLists[i]->vtx_buffer.size(); AllocateVertexBuffer(mSize); } // Copy vertices into VB Ogre::HardwareVertexBufferSharedPtr vb = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); ImDrawVert* vertices = static_cast<ImDrawVert*>( vb->lock(0, vb->getSizeInBytes(), Ogre::HardwareBuffer::HBL_DISCARD)); memcpy(vertices, &cmdLists[i]->vtx_buffer[0], cmdLists[i]->vtx_buffer.size() * sizeof(ImDrawVert)); vb->unlock(); // Execute draw calls int offset = 0; for (auto c : commands) { mRenderSystem->setScissorTest(true, c.clip_rect.x, c.clip_rect.y, c.clip_rect.z, c.clip_rect.w); // Set texture if (c.texture_id) { ImguiTextureHandle* handle = reinterpret_cast<ImguiTextureHandle*>(c.texture_id); mRenderSystem->_setTexture(0, true, handle->texturePtr); mRenderSystem->_setTextureBlendMode(0, mAlphaBlendMode); } else { mRenderSystem->_disableTextureUnit(0); } // Draw vertices mRenderOp.vertexData->vertexStart = offset; mRenderOp.vertexData->vertexCount = c.vtx_count; mRenderSystem->_render(mRenderOp); offset += c.vtx_count; } } mRenderSystem->setScissorTest(false); }
//------------------------------------------------------------------------------------------------ void DynamicLines::fillHardwareBuffers() { int size = m_Points.size(); prepareHardwareBuffers(size,0); if (!size) { mBox.setExtents(Vec3::ZERO,Vec3::ZERO); m_bDirty=false; return; } Vec3 vaabMin = m_Points[0]; Vec3 vaabMax = m_Points[0]; Ogre::HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); real *prPos = static_cast<real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); { for(int i = 0; i < size; i++) { *prPos++ = m_Points[i].x; *prPos++ = m_Points[i].y; *prPos++ = m_Points[i].z; if(m_Points[i].x < vaabMin.x) vaabMin.x = m_Points[i].x; if(m_Points[i].y < vaabMin.y) vaabMin.y = m_Points[i].y; if(m_Points[i].z < vaabMin.z) vaabMin.z = m_Points[i].z; if(m_Points[i].x > vaabMax.x) vaabMax.x = m_Points[i].x; if(m_Points[i].y > vaabMax.y) vaabMax.y = m_Points[i].y; if(m_Points[i].z > vaabMax.z) vaabMax.z = m_Points[i].z; } } vbuf->unlock(); mBox.setExtents(vaabMin, vaabMax); m_bDirty = false; }
//------------------------------------------------------------------------------------------------ void VertexIndexToShape::addStaticVertexData(const Ogre::VertexData *vertex_data) { if (!vertex_data) { return; } const Ogre::VertexData *data = vertex_data; const unsigned int prev_size = mVertexCount; mVertexCount += (unsigned int)data->vertexCount; Ogre::Vector3 *tmp_vert = new Ogre::Vector3[mVertexCount]; if (mVertexBuffer) { memcpy(tmp_vert, mVertexBuffer, sizeof(Ogre::Vector3) * prev_size); delete[] mVertexBuffer; } mVertexBuffer = tmp_vert; // Get the positional buffer element { const Ogre::VertexElement *posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); unsigned char *vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); float *pReal = NULL; Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; const unsigned int vertexCount = (unsigned int)data->vertexCount; for (unsigned int j = 0; j < vertexCount; ++j) { posElem->baseVertexPointerToElement(vertex, &pReal); vertex += vSize; curVertices->x = (*pReal++); curVertices->y = (*pReal++); curVertices->z = (*pReal++); *curVertices = mTransform * (*curVertices); curVertices++; } vbuf->unlock(); } }
//------------------------------------------------------- // http://www.ogre3d.org/tikiwiki/Raycasting+to+the+polygon+level std::pair<bool, float> Ground::GetVertexIntersection(const Ogre::Ray & ray, const Ogre::SubMesh* subMesh) { OgreAssert(false == subMesh->useSharedVertices, "Mesh with shared data is not supported"); const Ogre::VertexElement* posElem = subMesh->vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuffer = subMesh->vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertexes = reinterpret_cast<unsigned char*>(vbuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); size_t count = subMesh->vertexData->vertexCount; float intersection = -1.0f; OgreAssert(count == REGION_SIZE * REGION_SIZE * 4, "Wrong buffer size"); float* pReal; for (size_t i = 0; i < REGION_SIZE * REGION_SIZE; ++i) { Ogre::Vector3 v0, v1, v2, v3; for (auto vp : { &v0, &v1, &v2, &v3 }) { posElem->baseVertexPointerToElement(vertexes, &pReal); *vp = Ogre::Vector3(pReal[0], pReal[1], pReal[2]); vertexes += vbuffer->getVertexSize(); } auto hit1 = Ogre::Math::intersects(ray, v1, v2, v0, true, false); if (hit1.first && (intersection < 0.0f || hit1.second < intersection)) { intersection = hit1.second; } auto hit2 = Ogre::Math::intersects(ray, v3, v2, v1, true, false); if (hit2.first && (intersection < 0.0f || hit2.second < intersection)) { intersection = hit2.second; } } vbuffer->unlock(); if (intersection >= 0.0f) { return std::make_pair(true, intersection); } return std::make_pair(false, -1.0f); }
void FrameGraphRenderable::fillHardwareBuffers() { Ogre::HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); Ogre::Real *vertices = static_cast<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); Ogre::HardwareVertexBufferSharedPtr vcbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(1); Ogre::RGBA* pColours = static_cast<Ogre::RGBA*>(vcbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); Ogre::RenderSystem* rs = Ogre::Root::getSingleton().getRenderSystem(); uint16_t index = 0; for (uint16_t i = 0; i < mNumFrames; i++) { float x = i * mLineSpace - 1.0f; // OgreTime line vertices[index + 0] = x; vertices[index + 1] = -1; vertices[index + 2] = 0; // Vertex rs->convertColourValue(Ogre::ColourValue(1.0f, 0.0f, 0.0f), pColours++); // Color vertices[index + 3] = x; vertices[index + 4] = -1; vertices[index + 5] = 0; // Vertex rs->convertColourValue(Ogre::ColourValue(1.0f, 0.0f, 0.0f), pColours++); // Color // BulletTime line vertices[index + 6] = x; vertices[index + 7] = -1; vertices[index + 8] = 0; // Vertex rs->convertColourValue(Ogre::ColourValue(0.0f, 1.0f, 0.0f), pColours++); // Color vertices[index + 9] = x; vertices[index + 10] = -1; vertices[index + 11] = 0; // Vertex rs->convertColourValue(Ogre::ColourValue(0.0f, 1.0f, 0.0f), pColours++); // Color // WorldTime line vertices[index + 12] = x; vertices[index + 13] = -1; vertices[index + 14] = 0; // Vertex rs->convertColourValue(Ogre::ColourValue(0.0f, 0.0f, 1.0f), pColours++); // Color vertices[index + 15] = x; vertices[index + 16] = -1; vertices[index + 17] = 0; // Vertex rs->convertColourValue(Ogre::ColourValue(0.0f, 0.0f, 1.0f), pColours++); // Color // UnknownTime line vertices[index + 18] = x; vertices[index + 19] = -1; vertices[index + 20] = 0; // Vertex rs->convertColourValue(Ogre::ColourValue(1.0f, 1.0f, 1.0f), pColours++); // Color vertices[index + 21] = x; vertices[index + 22] = -1; vertices[index + 23] = 0; // Vertex rs->convertColourValue(Ogre::ColourValue(1.0f, 1.0f, 1.0f), pColours++); // Color index += ValuesPerGraphLine; } vcbuf->unlock(); vbuf->unlock(); mBox.setInfinite(); }
void CDynamicLineDrawer::FillHardwareBuffers() { int Size = int(Points.size()); PrepareHardwareBuffers(Size); if (!Size) { mBox.setExtents( Ogre::Vector3::ZERO, Ogre::Vector3::ZERO ); Dirty = false; return; } Ogre::Vector3 AABMin = Points[0]; Ogre::Vector3 AABMax = Points[0]; Ogre::HardwareVertexBufferSharedPtr VBuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); Ogre::HardwareVertexBufferSharedPtr CBuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(1); // get rendersystem to pack colours Ogre::RenderSystem* RS = Ogre::Root::getSingleton().getRenderSystem(); Ogre::Real* VPrPos = static_cast<Ogre::Real*>(VBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); Ogre::RGBA* CPrPos = static_cast<Ogre::RGBA*>(CBuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); for(int i = 0; i < Size; i++) { *VPrPos++ = Points[i].x; *VPrPos++ = Points[i].y; *VPrPos++ = Points[i].z; Ogre::RGBA color; RS->convertColourValue(Colours[i], &color); *CPrPos++ = color; //*CPrPos++ = unsigned int(Colours[i].g); //*CPrPos++ = unsigned int(Colours[i].b); if(Points[i].x < AABMin.x) AABMin.x = Points[i].x; if(Points[i].y < AABMin.y) AABMin.y = Points[i].y; if(Points[i].z < AABMin.z) AABMin.z = Points[i].z; if(Points[i].x > AABMax.x) AABMax.x = Points[i].x; if(Points[i].y > AABMax.y) AABMax.y = Points[i].y; if(Points[i].z > AABMax.z) AABMax.z = Points[i].z; } VBuf->unlock(); CBuf->unlock(); mBox.setExtents(AABMin, AABMax); Dirty = false; }
void TerrainTileEditable::fillLayerBuffer(size_t layer, const Ogre::HardwareVertexBufferSharedPtr& buffer) { float* pFloat = static_cast<float*>(buffer->lock(Ogre::HardwareBuffer::HBL_DISCARD)); const TerrainData* data = mOwner->getData(); int xbase = mXBase; int zbase = mZBase; int xsize = mXSize; int zsize = mZSize; for (int z = 0; z < zsize; ++z) { for (int x = 0; x < xsize; ++x) { size_t grid = (zbase + z) * data->mXSize + (xbase + x); const TerrainData::GridInfo& gridInfo = data->mGridInfos[grid]; const TerrainData::LayerInfo& layerInfo = gridInfo.layers[layer]; if (layerInfo.pixmapId) { std::pair<Real, Real> t; t = mOwner->_getPixmapCorner(layerInfo, TerrainData::LEFT_TOP, gridInfo.flags); *pFloat++ = t.first; *pFloat++ = t.second; t = mOwner->_getPixmapCorner(layerInfo, TerrainData::RIGHT_TOP, gridInfo.flags); *pFloat++ = t.first; *pFloat++ = t.second; t = mOwner->_getPixmapCorner(layerInfo, TerrainData::LEFT_BOTTOM, gridInfo.flags); *pFloat++ = t.first; *pFloat++ = t.second; t = mOwner->_getPixmapCorner(layerInfo, TerrainData::RIGHT_BOTTOM, gridInfo.flags); *pFloat++ = t.first; *pFloat++ = t.second; } else { pFloat += 2 * 4; } } } buffer->unlock(); }
void VertexBuffer::AddFromVertexData(Ogre::VertexData* vertexData) { // Get vertex count const unsigned int addedCount = vertexData->vertexCount; if(_reserved < _size + addedCount) { Reserve(_size + addedCount); } // Get VertexElement with info on used vertex semantics const Ogre::VertexElement* vertexElement = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); // Get actual vertex buffer and its size Ogre::HardwareVertexBufferSharedPtr hardwareBuffer = vertexData->vertexBufferBinding->getBuffer(vertexElement->getSource()); const unsigned int vertexSize = (unsigned int)hardwareBuffer->getVertexSize(); // Lock buffer with read-only to retrieve vertex data unsigned char* buffer = static_cast<unsigned char*>( hardwareBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); // Pointer to one component of vertex vector float *curVertexData = NULL; for (unsigned int j = 0; j < addedCount; ++j) { vertexElement->baseVertexPointerToElement(buffer, &curVertexData); buffer += vertexSize; _buffer.push_back(Ogre::Vector3( *curVertexData, *(curVertexData+1) , *(curVertexData+2))); curVertexData += 3; } _size = _buffer.size(); hardwareBuffer->unlock(); }
std::vector<Ogre::Vector3> OgreRecast::getManualObjectVertices(Ogre::ManualObject *manual) { std::vector<Ogre::Vector3> returnVertices; unsigned long thisSectionStart = 0; for (size_t i=0; i < manual->getNumSections(); i++) { Ogre::ManualObject::ManualObjectSection * section = manual->getSection(i); Ogre::RenderOperation * renderOp = section->getRenderOperation(); //Collect the vertices { const Ogre::VertexElement * vertexElement = renderOp->vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vertexBuffer = renderOp->vertexData->vertexBufferBinding->getBuffer(vertexElement->getSource()); char * verticesBuffer = (char*)vertexBuffer->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); float * positionArrayHolder; thisSectionStart = returnVertices.size(); returnVertices.reserve(returnVertices.size() + renderOp->vertexData->vertexCount); for (unsigned int j=0; j<renderOp->vertexData->vertexCount; j++) { vertexElement->baseVertexPointerToElement(verticesBuffer + j * vertexBuffer->getVertexSize(), &positionArrayHolder); Ogre::Vector3 vertexPos = Ogre::Vector3(positionArrayHolder[0], positionArrayHolder[1], positionArrayHolder[2]); //vertexPos = (orient * (vertexPos * scale)) + position; returnVertices.push_back(vertexPos); } vertexBuffer->unlock(); } } return returnVertices; }
void OgreMeshRay::GetMeshInformation(const Ogre::ManualObject* manual, size_t& vertex_count, Ogre::Vector3*& vertices, size_t& index_count, unsigned long*& indices, const Ogre::Vector3& position, const Ogre::Quaternion& orient, const Ogre::Vector3& scale) { std::vector<Ogre::Vector3> returnVertices; std::vector<unsigned long> returnIndices; unsigned long thisSectionStart = 0; for (unsigned int i = 0, size = manual->getNumSections(); i < size; ++i) { Ogre::ManualObject::ManualObjectSection* section = manual->getSection( i); Ogre::RenderOperation* renderOp = section->getRenderOperation(); std::vector<Ogre::Vector3> pushVertices; //Collect the vertices { const Ogre::VertexElement* vertexElement = renderOp->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vertexBuffer = renderOp->vertexData->vertexBufferBinding->getBuffer( vertexElement->getSource()); char* verticesBuffer = static_cast<char*>(vertexBuffer->lock( Ogre::HardwareBuffer::HBL_READ_ONLY)); float* positionArrayHolder; thisSectionStart = returnVertices.size() + pushVertices.size(); pushVertices.reserve(renderOp->vertexData->vertexCount); for (unsigned int j = 0; j < renderOp->vertexData->vertexCount; ++j) { vertexElement->baseVertexPointerToElement( verticesBuffer + j * vertexBuffer->getVertexSize(), &positionArrayHolder); Ogre::Vector3 vertexPos = Ogre::Vector3(positionArrayHolder[0], positionArrayHolder[1], positionArrayHolder[2]); vertexPos = (orient * (vertexPos * scale)) + position; pushVertices.push_back(vertexPos); } vertexBuffer->unlock(); } //Collect the indices { if (renderOp->useIndexes) { Ogre::HardwareIndexBufferSharedPtr indexBuffer = renderOp->indexData->indexBuffer; if (indexBuffer.isNull() || renderOp->operationType != Ogre::RenderOperation::OT_TRIANGLE_LIST) { //No triangles here, so we just drop the collected vertices and move along to the next section. continue; } else { returnVertices.reserve( returnVertices.size() + pushVertices.size()); returnVertices.insert(returnVertices.end(), pushVertices.begin(), pushVertices.end()); } unsigned int* pLong = static_cast<unsigned int*>(indexBuffer->lock( Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); returnIndices.reserve( returnIndices.size() + renderOp->indexData->indexCount); for (size_t j = 0; j < renderOp->indexData->indexCount; ++j) { unsigned long index; //We also have got to remember that for a multi section object, each section has //different vertices, so the indices will not be correct. To correct this, we //have to add the position of the first vertex in this section to the index //(At least I think so...) if (indexBuffer->getType() == Ogre::HardwareIndexBuffer::IT_32BIT) index = static_cast<unsigned long>(pLong[j]) + thisSectionStart; else index = static_cast<unsigned long>(pShort[j]) + thisSectionStart; returnIndices.push_back(index); } indexBuffer->unlock(); } } } //Now we simply return the data. index_count = returnIndices.size(); vertex_count = returnVertices.size(); vertices = new Ogre::Vector3[vertex_count]; for (unsigned long i = 0; i < vertex_count; ++i) vertices[i] = returnVertices[i]; indices = new unsigned long[index_count]; for (unsigned long i = 0; i < index_count; ++i) indices[i] = returnIndices[i]; //All done. return; }
void Animation::handleShapes(std::vector<Nif::NiTriShapeCopy>* allshapes, Ogre::Entity* creaturemodel, Ogre::SkeletonInstance *skel){ shapeNumber = 0; if (allshapes == NULL || creaturemodel == NULL || skel == NULL) { return; } std::vector<Nif::NiTriShapeCopy>::iterator allshapesiter; for(allshapesiter = allshapes->begin(); allshapesiter != allshapes->end(); allshapesiter++) { //std::map<unsigned short, PosAndRot> vecPosRot; Nif::NiTriShapeCopy& copy = *allshapesiter; std::vector<Ogre::Vector3>* allvertices = ©.vertices; //std::set<unsigned int> vertices; //std::set<unsigned int> normals; //std::vector<Nif::NiSkinData::BoneInfoCopy> boneinfovector = copy.boneinfo; std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> >* verticesToChange = ©.vertsToWeights; //std::cout << "Name " << copy.sname << "\n"; Ogre::HardwareVertexBufferSharedPtr vbuf = creaturemodel->getMesh()->getSubMesh(copy.sname)->vertexData->vertexBufferBinding->getBuffer(0); Ogre::Real* pReal = static_cast<Ogre::Real*>(vbuf->lock(Ogre::HardwareBuffer::HBL_NORMAL)); std::vector<Ogre::Vector3> initialVertices = copy.morph.getInitialVertices(); //Each shape has multiple indices if(initialVertices.size() ) { if(copy.vertices.size() == initialVertices.size()) { //Create if it doesn't already exist if(shapeIndexI.size() == static_cast<std::size_t> (shapeNumber)) { std::vector<int> vec; shapeIndexI.push_back(vec); } if(time >= copy.morph.getStartTime() && time <= copy.morph.getStopTime()){ float x; for (unsigned int i = 0; i < copy.morph.getAdditionalVertices().size(); i++){ int j = 0; if(shapeIndexI[shapeNumber].size() <= i) shapeIndexI[shapeNumber].push_back(0); if(timeIndex(time,copy.morph.getRelevantTimes()[i],(shapeIndexI[shapeNumber])[i], j, x)){ int indexI = (shapeIndexI[shapeNumber])[i]; std::vector<Ogre::Vector3> relevantData = (copy.morph.getRelevantData()[i]); float v1 = relevantData[indexI].x; float v2 = relevantData[j].x; float t = v1 + (v2 - v1) * x; if ( t < 0 ) t = 0; if ( t > 1 ) t = 1; if( t != 0 && initialVertices.size() == copy.morph.getAdditionalVertices()[i].size()) { for (unsigned int v = 0; v < initialVertices.size(); v++){ initialVertices[v] += ((copy.morph.getAdditionalVertices()[i])[v]) * t; } } } } allvertices = &initialVertices; } shapeNumber++; } } if(verticesToChange->size() > 0){ for(std::map<int, std::vector<Nif::NiSkinData::IndividualWeight> >::iterator iter = verticesToChange->begin(); iter != verticesToChange->end(); iter++) { std::vector<Nif::NiSkinData::IndividualWeight> inds = iter->second; int verIndex = iter->first; Ogre::Vector3 currentVertex = (*allvertices)[verIndex]; Nif::NiSkinData::BoneInfoCopy* boneinfocopy = &(allshapesiter->boneinfo[inds[0].boneinfocopyindex]); Ogre::Bone *bonePtr = 0; Ogre::Vector3 vecPos; Ogre::Quaternion vecRot; std::map<Nif::NiSkinData::BoneInfoCopy*, PosAndRot>::iterator result = vecRotPos.find(boneinfocopy); if(result == vecRotPos.end()){ bonePtr = skel->getBone(boneinfocopy->bonename); vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; PosAndRot both; both.vecPos = vecPos; both.vecRot = vecRot; vecRotPos[boneinfocopy] = both; } else{ PosAndRot both = result->second; vecPos = both.vecPos; vecRot = both.vecRot; } Ogre::Vector3 absVertPos = (vecPos + vecRot * currentVertex) * inds[0].weight; for(std::size_t i = 1; i < inds.size(); i++){ boneinfocopy = &(allshapesiter->boneinfo[inds[i].boneinfocopyindex]); result = vecRotPos.find(boneinfocopy); if(result == vecRotPos.end()){ bonePtr = skel->getBone(boneinfocopy->bonename); vecPos = bonePtr->_getDerivedPosition() + bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.trans; vecRot = bonePtr->_getDerivedOrientation() * boneinfocopy->trafo.rotation; PosAndRot both; both.vecPos = vecPos; both.vecRot = vecRot; vecRotPos[boneinfocopy] = both; } else{ PosAndRot both = result->second; vecPos = both.vecPos; vecRot = both.vecRot; } absVertPos += (vecPos + vecRot * currentVertex) * inds[i].weight; } Ogre::Real* addr = (pReal + 3 * verIndex); *addr = absVertPos.x; *(addr+1) = absVertPos.y; *(addr+2) = absVertPos.z; } } else { //Ogre::Bone *bonePtr = creaturemodel->getSkeleton()->getBone(copy.bonename); Ogre::Quaternion shaperot = copy.trafo.rotation; Ogre::Vector3 shapetrans = copy.trafo.trans; float shapescale = copy.trafo.scale; std::vector<std::string> boneSequence = copy.boneSequence; Ogre::Vector3 transmult; Ogre::Quaternion rotmult; float scale; if(boneSequence.size() > 0){ std::vector<std::string>::iterator boneSequenceIter = boneSequence.begin(); if(skel->hasBone(*boneSequenceIter)){ Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); transmult = bonePtr->getPosition(); rotmult = bonePtr->getOrientation(); scale = bonePtr->getScale().x; boneSequenceIter++; for(; boneSequenceIter != boneSequence.end(); boneSequenceIter++) { if(skel->hasBone(*boneSequenceIter)){ Ogre::Bone *bonePtr = skel->getBone(*boneSequenceIter); // Computes C = B + AxC*scale transmult = transmult + rotmult * bonePtr->getPosition(); rotmult = rotmult * bonePtr->getOrientation(); scale = scale * bonePtr->getScale().x; } //std::cout << "Bone:" << *boneSequenceIter << " "; } transmult = transmult + rotmult * shapetrans; rotmult = rotmult * shaperot; scale = shapescale * scale; //std::cout << "Position: " << transmult << "Rotation: " << rotmult << "\n"; } } else { transmult = shapetrans; rotmult = shaperot; scale = shapescale; } // Computes C = B + AxC*scale // final_vector = old_vector + old_rotation*new_vector*old_scale/ for(unsigned int i = 0; i < allvertices->size(); i++){ Ogre::Vector3 current = transmult + rotmult * (*allvertices)[i]; Ogre::Real* addr = pReal + i * 3; *addr = current.x; *(addr+1) = current.y; *(addr + 2) = current.z; }/* for(int i = 0; i < allnormals.size(); i++){ Ogre::Vector3 current =rotmult * allnormals[i]; Ogre::Real* addr = pRealNormal + i * 3; *addr = current.x; *(addr+1) = current.y; *(addr + 2) = current.z; }*/ } vbuf->unlock(); } }
void Utils::GetMeshInformation( const Ogre::MeshPtr mesh, size_t &vertexCount, Ogre::Vector3* &vertices, size_t &indexCount, unsigned* &indices) { bool addShared = false; size_t currentOffset = 0; size_t shared_offset = 0; size_t nextOffset = 0; size_t indexOffset = 0; vertexCount = indexCount = 0; for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh(i); if(submesh->useSharedVertices) { if( !addShared ) { vertexCount += mesh->sharedVertexData->vertexCount; addShared = true; } } else { vertexCount += submesh->vertexData->vertexCount; } indexCount += submesh->indexData->indexCount; } vertices = new Ogre::Vector3[vertexCount]; indices = new unsigned[indexCount]; addShared = false; for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh(i); Ogre::VertexData* vertexData = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; if ((!submesh->useSharedVertices) || (submesh->useSharedVertices && !addShared)) { if(submesh->useSharedVertices) { addShared = true; shared_offset = currentOffset; } const Ogre::VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); float* pReal; for( size_t j = 0; j < vertexData->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]); vertices[currentOffset + j] = pt; } vbuf->unlock(); nextOffset += vertexData->vertexCount; } Ogre::IndexData* indexData = submesh->indexData; size_t numTris = indexData->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); unsigned long* pLong = static_cast<unsigned long*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); size_t offset = (submesh->useSharedVertices)? shared_offset : currentOffset; if ( use32bitindexes ) { for ( size_t k = 0; k < numTris*3; ++k) { indices[indexOffset++] = pLong[k] + static_cast<unsigned long>(offset); } } else { for ( size_t k = 0; k < numTris*3; ++k) { indices[indexOffset++] = static_cast<unsigned long>(pShort[k]) + static_cast<unsigned long>(offset); } } ibuf->unlock(); currentOffset = nextOffset; } }
void OgreMeshAsset::CreateKdTree() { meshData.Clear(); normals.clear(); uvs.clear(); subMeshTriangleCounts.clear(); for(unsigned short i = 0; i < ogreMesh->getNumSubMeshes(); ++i) { Ogre::SubMesh *submesh = ogreMesh->getSubMesh(i); assert(submesh); Ogre::VertexData *vertexData = submesh->useSharedVertices ? ogreMesh->sharedVertexData : submesh->vertexData; assert(vertexData); const Ogre::VertexElement *posElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); if (!posElem) { subMeshTriangleCounts.push_back(0); continue; // No position element. Ignore this submesh. } Ogre::HardwareVertexBufferSharedPtr vbufPos = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char *pos = (unsigned char*)vbufPos->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); assert(pos); size_t posOffset = posElem->getOffset(); size_t posSize = vbufPos->getVertexSize(); // Texcoord element is not mandatory unsigned char *texCoord = 0; size_t texOffset = 0; size_t texSize = 0; Ogre::HardwareVertexBufferSharedPtr vbufTex; const Ogre::VertexElement *texElem = vertexData->vertexDeclaration->findElementBySemantic(Ogre::VES_TEXTURE_COORDINATES); if (texElem) { vbufTex = vertexData->vertexBufferBinding->getBuffer(texElem->getSource()); // Check if the texcoord buffer is different than the position buffer, in that case lock it separately if (vbufTex != vbufPos) texCoord = static_cast<unsigned char*>(vbufTex->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); else texCoord = pos; texOffset = texElem->getOffset(); texSize = vbufTex->getVertexSize(); } Ogre::IndexData *indexData = submesh->indexData; Ogre::HardwareIndexBufferSharedPtr ibuf = indexData->indexBuffer; u32 *pLong = (u32*)ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY); u16 *pShort = (u16*)pLong; const bool use32BitIndices = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); for(unsigned j = 0; j+2 < indexData->indexCount; j += 3) { unsigned i0, i1, i2; if (use32BitIndices) { i0 = pLong[j]; i1 = pLong[j+1]; i2 = pLong[j+2]; } else { i0 = pShort[j]; i1 = pShort[j+1]; i2 = pShort[j+2]; } float3 v0 = *(float3*)(pos + posOffset + i0 * posSize); float3 v1 = *(float3*)(pos + posOffset + i1 * posSize); float3 v2 = *(float3*)(pos + posOffset + i2 * posSize); Triangle t(v0, v1, v2); meshData.AddObjects(&t, 1); if (texElem) { uvs.push_back(*((float2*)(texCoord + texOffset + i0 * texSize))); uvs.push_back(*((float2*)(texCoord + texOffset + i1 * texSize))); uvs.push_back(*((float2*)(texCoord + texOffset + i2 * texSize))); } float3 edge1 = v1 - v0; float3 edge2 = v2 - v0; float3 normal = edge1.Cross(edge2); normal.Normalize(); normals.push_back(normal); } subMeshTriangleCounts.push_back((int)(indexData->indexCount / 3)); vbufPos->unlock(); if (!vbufTex.isNull() && vbufTex != vbufPos) vbufTex->unlock(); ibuf->unlock(); } { PROFILE(OgreMeshAsset_KdTree_Build); meshData.Build(); } }
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 VertexIndexToShape::addAnimatedVertexData(const Ogre::VertexData *vertex_data, const Ogre::VertexData *blend_data, const Ogre::Mesh::IndexMap *indexMap) { // Get the bone index element assert(vertex_data); const Ogre::VertexData *data = blend_data; const unsigned int prev_size = mVertexCount; mVertexCount += (unsigned int)data->vertexCount; Ogre::Vector3 *tmp_vert = new Ogre::Vector3[mVertexCount]; if (mVertexBuffer) { memcpy(tmp_vert, mVertexBuffer, sizeof(Ogre::Vector3) * prev_size); delete[] mVertexBuffer; } mVertexBuffer = tmp_vert; // Get the positional buffer element { const Ogre::VertexElement *posElem = data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); assert(posElem); Ogre::HardwareVertexBufferSharedPtr vbuf = data->vertexBufferBinding->getBuffer(posElem->getSource()); const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); unsigned char *vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); float *pReal; Ogre::Vector3 * curVertices = &mVertexBuffer[prev_size]; const unsigned int vertexCount = (unsigned int)data->vertexCount; for (unsigned int j = 0; j < vertexCount; ++j) { posElem->baseVertexPointerToElement(vertex, &pReal); vertex += vSize; curVertices->x = (*pReal++); curVertices->y = (*pReal++); curVertices->z = (*pReal++); *curVertices = mTransform * (*curVertices); curVertices++; } vbuf->unlock(); } { const Ogre::VertexElement *bneElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_BLEND_INDICES); assert(bneElem); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(bneElem->getSource()); const unsigned int vSize = (unsigned int)vbuf->getVertexSize(); unsigned char *vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned char *pBone = NULL; if (!mBoneIndex) { mBoneIndex = new BoneIndex(); } Ogre::Vector3 *curVertices = &mVertexBuffer[prev_size]; const unsigned int vertexCount = (unsigned int)vertex_data->vertexCount; for (unsigned int j = 0; j < vertexCount; ++j) { bneElem->baseVertexPointerToElement(vertex, &pBone); vertex += vSize; const unsigned char currBone = (indexMap) ? (*indexMap)[*pBone] : *pBone; const BoneIndex::iterator i = mBoneIndex->find(currBone); Vector3Array *l = NULL; if (i == mBoneIndex->end()) { l = new Vector3Array; mBoneIndex->insert(BoneKeyIndex(currBone, l)); } else { l = i->second; } l->push_back(*curVertices); curVertices++; } vbuf->unlock(); } }
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); } }
// Get the mesh information for the given mesh. // Code found on this forum link: http://www.ogre3d.org/wiki/index.php/RetrieveVertexData void CollisionTools::GetMeshInformation(const Ogre::MeshPtr mesh, size_t &vertex_count, Ogre::Vector3* &vertices, size_t &index_count, Ogre::uint32* &indices, const Ogre::Vector3 &position, const Ogre::Quaternion &orient, const Ogre::Vector3 &scale) { bool added_shared = false; size_t current_offset = 0; size_t shared_offset = 0; size_t next_offset = 0; size_t index_offset = 0; vertex_count = index_count = 0; // Calculate how many vertices and indices we're going to need for (unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh( i ); // We only need to add the shared vertices once if(submesh->useSharedVertices) { if( !added_shared ) { vertex_count += mesh->sharedVertexData->vertexCount; added_shared = true; } } else { vertex_count += submesh->vertexData->vertexCount; } // Add the indices index_count += submesh->indexData->indexCount; } // Allocate space for the vertices and indices vertices = new Ogre::Vector3[vertex_count]; indices = new Ogre::uint32[index_count]; added_shared = false; // Run through the submeshes again, adding the data into the arrays for ( unsigned short i = 0; i < mesh->getNumSubMeshes(); ++i) { Ogre::SubMesh* submesh = mesh->getSubMesh(i); Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared)) { if(submesh->useSharedVertices) { added_shared = true; shared_offset = current_offset; } const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); // There is _no_ baseVertexPointerToElement() which takes an Ogre::Ogre::Real or a double // as second argument. So make it float, to avoid trouble when Ogre::Ogre::Real will // be comiled/typedefed as double: // Ogre::Ogre::Real* pOgre::Real; float* pReal; for( size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Ogre::Vector3 pt(pReal[0], pReal[1], pReal[2]); vertices[current_offset + j] = (orient * (pt * scale)) + position; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } Ogre::IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); Ogre::uint32* pLong = static_cast<Ogre::uint32*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); unsigned short* pShort = reinterpret_cast<unsigned short*>(pLong); size_t offset = (submesh->useSharedVertices)? shared_offset : current_offset; if ( use32bitindexes ) { for ( size_t k = 0; k < numTris*3; ++k) { indices[index_offset++] = pLong[k] + static_cast<Ogre::uint32>(offset); } } else { for ( size_t k = 0; k < numTris*3; ++k) { indices[index_offset++] = static_cast<Ogre::uint32>(pShort[k]) + static_cast<Ogre::uint32>(offset); } } ibuf->unlock(); current_offset = next_offset; } }
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 PhysicsManager::getMeshInformation(Ogre::MeshPtr mesh,size_t &vertex_count,Vector3* &vertices, size_t &index_count, unsigned* &indices, const Ogre::Vector3 &position, const Ogre::Quaternion &orient,const Ogre::Vector3 &scale) { vertex_count = index_count = 0; bool added_shared = false; size_t current_offset = vertex_count; size_t shared_offset = vertex_count; size_t next_offset = vertex_count; size_t index_offset = index_count; size_t prev_vert = vertex_count; size_t prev_ind = index_count; // Calculate how many vertices and indices we're going to need for(int i = 0;i < mesh->getNumSubMeshes();i++) { SubMesh* submesh = mesh->getSubMesh(i); // We only need to add the shared vertices once if(submesh->useSharedVertices) { if(!added_shared) { VertexData* vertex_data = mesh->sharedVertexData; vertex_count += vertex_data->vertexCount; added_shared = true; } } else { VertexData* vertex_data = submesh->vertexData; vertex_count += vertex_data->vertexCount; } // Add the indices Ogre::IndexData* index_data = submesh->indexData; index_count += index_data->indexCount; } // Allocate space for the vertices and indices vertices = new Vector3[vertex_count]; indices = new unsigned[index_count]; added_shared = false; // Run through the submeshes again, adding the data into the arrays for(int i = 0;i < mesh->getNumSubMeshes();i++) { SubMesh* submesh = mesh->getSubMesh(i); Ogre::VertexData* vertex_data = submesh->useSharedVertices ? mesh->sharedVertexData : submesh->vertexData; if((!submesh->useSharedVertices)||(submesh->useSharedVertices && !added_shared)) { if(submesh->useSharedVertices) { added_shared = true; shared_offset = current_offset; } const Ogre::VertexElement* posElem = vertex_data->vertexDeclaration->findElementBySemantic(Ogre::VES_POSITION); Ogre::HardwareVertexBufferSharedPtr vbuf = vertex_data->vertexBufferBinding->getBuffer(posElem->getSource()); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); Ogre::Real* pReal; for(size_t j = 0; j < vertex_data->vertexCount; ++j, vertex += vbuf->getVertexSize()) { posElem->baseVertexPointerToElement(vertex, &pReal); Vector3 pt; pt.x = (*pReal++); pt.y = (*pReal++); pt.z = (*pReal++); pt = (orient * (pt * scale)) + position; vertices[current_offset + j].x = pt.x; vertices[current_offset + j].y = pt.y; vertices[current_offset + j].z = pt.z; } vbuf->unlock(); next_offset += vertex_data->vertexCount; } Ogre::IndexData* index_data = submesh->indexData; size_t numTris = index_data->indexCount / 3; unsigned short* pShort; unsigned int* pInt; Ogre::HardwareIndexBufferSharedPtr ibuf = index_data->indexBuffer; bool use32bitindexes = (ibuf->getType() == Ogre::HardwareIndexBuffer::IT_32BIT); if (use32bitindexes) pInt = static_cast<unsigned int*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); else pShort = static_cast<unsigned short*>(ibuf->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); for(size_t k = 0; k < numTris; ++k) { size_t offset = (submesh->useSharedVertices)?shared_offset:current_offset; unsigned int vindex = use32bitindexes? *pInt++ : *pShort++; indices[index_offset + 0] = vindex + offset; vindex = use32bitindexes? *pInt++ : *pShort++; indices[index_offset + 1] = vindex + offset; vindex = use32bitindexes? *pInt++ : *pShort++; indices[index_offset + 2] = vindex + offset; index_offset += 3; } ibuf->unlock(); current_offset = next_offset; } }
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 GPUBillboardSet::createVertexDataForVertexAndGeometryShaders(const std::vector<PhotoSynth::Vertex>& vertices) { // Setup render operation mRenderOp.operationType = Ogre::RenderOperation::OT_POINT_LIST; mRenderOp.vertexData = OGRE_NEW Ogre::VertexData(); mRenderOp.vertexData->vertexCount = vertices.size(); mRenderOp.vertexData->vertexStart = 0; mRenderOp.useIndexes = false; mRenderOp.indexData = 0; // Vertex format declaration unsigned short sourceBufferIdx = 0; Ogre::VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; size_t currOffset = 0; decl->addElement(sourceBufferIdx, currOffset, Ogre::VET_FLOAT3, Ogre::VES_POSITION); currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_FLOAT3); decl->addElement(sourceBufferIdx, currOffset, Ogre::VET_COLOUR, Ogre::VES_DIFFUSE); currOffset += Ogre::VertexElement::getTypeSize(Ogre::VET_COLOUR); // Create vertex buffer Ogre::HardwareVertexBufferSharedPtr vbuf = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(sourceBufferIdx), mRenderOp.vertexData->vertexCount, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Bind vertex buffer Ogre::VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; bind->setBinding(sourceBufferIdx, vbuf); // Fill vertex buffer (see http://www.ogre3d.org/docs/manual/manual_59.html#SEC287) Ogre::RenderSystem* renderSystem = Ogre::Root::getSingletonPtr()->getRenderSystem(); unsigned char* pVert = static_cast<unsigned char*>(vbuf->lock(Ogre::HardwareBuffer::HBL_DISCARD)); Ogre::Real* pReal; Ogre::RGBA* pRGBA; Ogre::VertexDeclaration::VertexElementList elems = decl->findElementsBySource(sourceBufferIdx); Ogre::VertexDeclaration::VertexElementList::iterator itr; for (unsigned int i=0; i<vertices.size(); ++i ) { const PhotoSynth::Vertex& vertex = vertices[i]; for (itr=elems.begin(); itr!=elems.end(); ++itr) { Ogre::VertexElement& elem = *itr; if (elem.getSemantic() == Ogre::VES_POSITION) { elem.baseVertexPointerToElement(pVert, &pReal); *pReal = vertex.position.x; *pReal++; *pReal = vertex.position.y; *pReal++; *pReal = vertex.position.z; *pReal++; } else if (elem.getSemantic() == Ogre::VES_DIFFUSE) { elem.baseVertexPointerToElement(pVert, &pRGBA); renderSystem->convertColourValue(vertex.color, pRGBA); } } // Go to next vertex pVert += vbuf->getVertexSize(); } vbuf->unlock(); // Set material this->setMaterial("GPUBillboardWithGS"); }