// ------------------------------------------------------------------------ void ShadowCaster::extrudeVertices( const HardwareVertexBufferSharedPtr& vertexBuffer, size_t originalVertexCount, const Vector4& light, Real extrudeDist) { assert (vertexBuffer->getVertexSize() == sizeof(float) * 3 && "Position buffer should contain only positions!"); // Extrude the first area of the buffer into the second area // Lock the entire buffer for writing, even though we'll only be // updating the latter because you can't have 2 locks on the same // buffer float* pSrc = static_cast<float*>( vertexBuffer->lock(HardwareBuffer::HBL_NORMAL)); // TODO: We should add extra (ununsed) vertices ensure source and // destination buffer have same alignment for slight performance gain. float* pDest = pSrc + originalVertexCount * 3; OptimisedUtil::getImplementation()->extrudeVertices( light, extrudeDist, pSrc, pDest, originalVertexCount); vertexBuffer->unlock(); }
//--------------------------------------------------------------------- void BorderPanelOverlayElement::updateTextureGeometry() { PanelOverlayElement::updateTextureGeometry(); /* Each cell is 0-----2 | /| | / | |/ | 1-----3 */ // No choice but to lock / unlock each time here, but lock only small sections HardwareVertexBufferSharedPtr vbuf = mRenderOp2.vertexData->vertexBufferBinding->getBuffer(TEXCOORD_BINDING); // Can't use discard since this discards whole buffer float* pUV = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); for (uint i = 0; i < 8; ++i) { *pUV++ = mBorderUV[i].u1; *pUV++ = mBorderUV[i].v1; *pUV++ = mBorderUV[i].u1; *pUV++ = mBorderUV[i].v2; *pUV++ = mBorderUV[i].u2; *pUV++ = mBorderUV[i].v1; *pUV++ = mBorderUV[i].u2; *pUV++ = mBorderUV[i].v2; } vbuf->unlock(); }
//----------------------------------------------------------------------- size_t MeshInformer::getVertices(Vector3* pDst, const VertexData* vertexData) { const VertexElement* posElem = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(posElem->getSource()); size_t vertex_stride = vbuf->getVertexSize(); size_t vertexCount = vertexData->vertexCount; void* pBase = vbuf->lock( vertex_stride * vertexData->vertexStart, vertex_stride * vertexCount, HardwareBuffer::HBL_READ_ONLY); uchar* pSrc; posElem->baseVertexPointerToElement(pBase, &pSrc); for (size_t i = 0; i < vertexCount; ++i, pSrc += vertex_stride, ++pDst) { const float* pFloat = reinterpret_cast<const float*>(pSrc); pDst->x = pFloat[0]; pDst->y = pFloat[1]; pDst->z = pFloat[2]; } vbuf->unlock(); return vertexCount; }
void Rectangle2D::setCorners(Real left, Real top, Real right, Real bottom, bool updateAABB) { HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING); float* pFloat = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); *pFloat++ = left; *pFloat++ = top; *pFloat++ = -1; *pFloat++ = left; *pFloat++ = bottom; *pFloat++ = -1; *pFloat++ = right; *pFloat++ = top; *pFloat++ = -1; *pFloat++ = right; *pFloat++ = bottom; *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 ShaderParticleRenderer::_updateRenderQueue(RenderQueue* queue, Ogre::list<Particle*>::type& currentParticles, bool cullIndividually) { // be sure that we have enough space in buffers if (!allocateBuffers(currentParticles.size())) { assert(0 && "Cannot allocate buffers"); return; } // update vertex data mRadius = 0.0f; if (!currentParticles.empty()) { HardwareVertexBufferSharedPtr pVB = mVertexData->vertexBufferBinding->getBuffer(0); uchar* pDataVB = reinterpret_cast<uchar*>(pVB->lock(HardwareBuffer::HBL_DISCARD)); for (Ogre::list<Particle*>::type::iterator it=currentParticles.begin(); it!=currentParticles.end(); ++it) { Particle* pParticle = *it; addParticle(pDataVB, *pParticle); pDataVB += 4 * mVertexSize; float fDist = (mParentNode != NULL) ? mParentNode->getPosition().distance(pParticle->mPosition) : pParticle->mPosition.length(); if (fDist > mRadius) mRadius = fDist; } pVB->unlock(); } // setup counts mVertexData->vertexCount = currentParticles.size() * 4; mIndexData->indexCount = currentParticles.size() * 6; // update render queue queue->addRenderable(this, mRenderQueueID); }
//--------------------------------------------------------------------- void TextAreaOverlayElement::updateColours(void) { // Convert to system-specific RGBA topColour, bottomColour; Root::getSingleton().convertColourValue(mColourTop, &topColour); Root::getSingleton().convertColourValue(mColourBottom, &bottomColour); HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING); RGBA* pDest = static_cast<RGBA*>( vbuf->lock(HardwareBuffer::HBL_DISCARD, Root::getSingleton().getFreqUpdatedBuffersUploadOption()) ); for (size_t i = 0; i < mAllocSize; ++i) { // First tri (top, bottom, top) *pDest++ = topColour; *pDest++ = bottomColour; *pDest++ = topColour; // Second tri (top, bottom, bottom) *pDest++ = topColour; *pDest++ = bottomColour; *pDest++ = bottomColour; } vbuf->unlock(); }
//-------------------------------------------------------------------------- void MeshLodTests::addProfile(LodConfig& config) { // Get the first two vertices and put the edge into the profile // It doesn't matter if there is no such edge, because edges are removed and created dynamically. // The vertex positions should exist or you get an assert. VertexData* vertexData = config.mesh->getSubMesh(0)->vertexData; const VertexElement* elemPos = vertexData->vertexDeclaration->findElementBySemantic(VES_POSITION); HardwareVertexBufferSharedPtr vbuf = vertexData->vertexBufferBinding->getBuffer(elemPos->getSource()); assert(vbuf->getNumVertices() > 2); unsigned char* vertex = static_cast<unsigned char*>(vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); float* pFloat; elemPos->baseVertexPointerToElement(vertex, &pFloat); ProfiledEdge edge; edge.src.x = *pFloat++; edge.src.y = *pFloat++; edge.src.z = *pFloat; vertex += vbuf->getVertexSize(); elemPos->baseVertexPointerToElement(vertex, &pFloat); edge.dst.x = *pFloat++; edge.dst.y = *pFloat++; edge.dst.z = *pFloat; edge.cost = LodData::NEVER_COLLAPSE_COST; config.advanced.profile.push_back(edge); vbuf->unlock(); }
void Line3D::drawLines(void) { if(mDrawn) return; else mDrawn = true; // Initialization stuff mRenderOp.indexData = 0; mRenderOp.vertexData->vertexCount = mPoints.size(); mRenderOp.vertexData->vertexStart = 0; mRenderOp.operationType = RenderOperation::OT_LINE_LIST; // OT_LINE_LIST, OT_LINE_STRIP mRenderOp.useIndexes = false; VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration; VertexBufferBinding *bind = mRenderOp.vertexData->vertexBufferBinding; decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(POSITION_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); bind->setBinding(POSITION_BINDING, vbuf); // Drawing stuff int size = mPoints.size(); Vector3 vaabMin = mPoints[0]; Vector3 vaabMax = mPoints[0]; Real *prPos = static_cast<Real*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); for(int i = 0; i < size; i++) { *prPos++ = mPoints[i].x; *prPos++ = mPoints[i].y; *prPos++ = mPoints[i].z; 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(); mBox.setExtents(vaabMin, vaabMax); }
void GeomUtils::createCone(Ogre::VertexData*& vertexData, Ogre::IndexData*& indexData, float radius , float height, int nVerticesInBase) { assert(vertexData && indexData); // define the vertex format VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; // positions vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION); // allocate the vertex buffer vertexData->vertexCount = nVerticesInBase + 1; HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer - cone and base indexData->indexCount = (3 * nVerticesInBase) + (3 * (nVerticesInBase - 2)); indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); //Positions : cone head and base for (int i=0; i<3; i++) *pVertex++ = 0.0f; //Base : float fDeltaBaseAngle = (2 * Math::PI) / nVerticesInBase; for (int i=0; i<nVerticesInBase; i++) { float angle = i * fDeltaBaseAngle; *pVertex++ = radius * cosf(angle); *pVertex++ = height; *pVertex++ = radius * sinf(angle); } //Indices : //Cone head to vertices for (int i=0; i<nVerticesInBase; i++) { *pIndices++ = 0; *pIndices++ = (i%nVerticesInBase) + 1; *pIndices++ = ((i+1)%nVerticesInBase) + 1; } //Cone base for (int i=0; i<nVerticesInBase-2; i++) { *pIndices++ = 1; *pIndices++ = i + 3; *pIndices++ = i + 2; } // Unlock vBuf->unlock(); iBuf->unlock(); }
void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType) { // Get the vertex colour buffer of this mesh const Ogre::VertexElement* ves_diffuse = ent->getMesh()->getSubMesh(0)->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_DIFFUSE ); HardwareVertexBufferSharedPtr colourBuffer = ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource()); // Lock void* pData = colourBuffer->lock(HardwareBuffer::HBL_NORMAL); // Iterate over all vertices int vertex_size = colourBuffer->getVertexSize(); float * currentVertex = NULL; for (unsigned int i=0; i<colourBuffer->getNumVertices(); ++i) { // Get a pointer to the vertex colour ves_diffuse->baseVertexPointerToElement( pData, ¤tVertex ); unsigned char alpha=0; if (meshType == 0) alpha = i%2 ? 0 : 255; // this is a cylinder, so every second vertex belongs to the bottom-most row else if (meshType == 1) { if (i>= 49 && i <= 64) alpha = 0; // bottom-most row else if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row else alpha = 255; } uint8 tmpR = static_cast<uint8>(255); uint8 tmpG = static_cast<uint8>(255); uint8 tmpB = static_cast<uint8>(255); uint8 tmpA = static_cast<uint8>(alpha); // This does not matter since R and B are always 1. /*VertexElementType format = Root::getSingleton().getRenderSystem()->getColourVertexElementType(); switch (format) { case VET_COLOUR_ARGB: std::swap(tmpR, tmpB); break; case VET_COLOUR_ABGR: break; default: break; }*/ // Modify *((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24); // Move to the next vertex pData = static_cast<unsigned char *> (pData) + vertex_size; } // Unlock ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock(); }
void NxLine::fillHardwareBuffers() { int size = mPoints.size(); prepareHardwareBuffers(size,0, mUseVertexColour); if (!size) { mBox.setExtents(Vector3::ZERO,Vector3::ZERO); mDirty=false; return; } Nx::Vector3 vaabMin = mPoints[0]; Nx::Vector3 vaabMax = mPoints[0]; HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); Real *prPos = static_cast<Real*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); { for(int i = 0; i < size; i++) { *prPos++ = mPoints[i].x; *prPos++ = mPoints[i].y; *prPos++ = mPoints[i].z; 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( mUseVertexColour ) { HardwareVertexBufferSharedPtr cbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(1); cbuf->writeData(0, size * sizeof(unsigned int), &mPointsColor[0], true ); } mBox.setExtents( NxVec3ToOgre( vaabMin ), NxVec3ToOgre( vaabMax ) ); mDirty = false; }
void MovableText::_updateColors(void){ assert(mpFont); assert(!mpMaterial.isNull()); // Convert to system-specific RGBA color; Root::getSingleton().convertColourValue(mColor, &color); HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING); RGBA *pDest = static_cast<RGBA*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); for (int i = 0; i < (int)mRenderOp.vertexData->vertexCount; ++i) *pDest++ = color; vbuf->unlock(); mUpdateColors = false; }
//--------------------------------------------------------------------- void TangentSpaceCalc::extendBuffers(VertexSplits& vertexSplits) { if (!vertexSplits.empty()) { // ok, need to increase the vertex buffer size, and alter some indexes // vertex buffers first VertexBufferBinding* newBindings = HardwareBufferManager::getSingleton().createVertexBufferBinding(); const VertexBufferBinding::VertexBufferBindingMap& bindmap = mVData->vertexBufferBinding->getBindings(); for (VertexBufferBinding::VertexBufferBindingMap::const_iterator i = bindmap.begin(); i != bindmap.end(); ++i) { HardwareVertexBufferSharedPtr srcbuf = i->second; // Derive vertex count from buffer not vertex data, in case using // the vertexStart option in vertex data size_t newVertexCount = srcbuf->getNumVertices() + vertexSplits.size(); // Create new buffer & bind HardwareVertexBufferSharedPtr newBuf = HardwareBufferManager::getSingleton().createVertexBuffer( srcbuf->getVertexSize(), newVertexCount, srcbuf->getUsage(), srcbuf->hasShadowBuffer()); newBindings->setBinding(i->first, newBuf); // Copy existing contents (again, entire buffer, not just elements referenced) newBuf->copyData(*(srcbuf.get()), 0, 0, srcbuf->getNumVertices() * srcbuf->getVertexSize(), true); // Split vertices, read / write from new buffer char* pBase = static_cast<char*>(newBuf->lock(HardwareBuffer::HBL_NORMAL)); for (VertexSplits::iterator spliti = vertexSplits.begin(); spliti != vertexSplits.end(); ++spliti) { const char* pSrcBase = pBase + spliti->first * newBuf->getVertexSize(); char* pDstBase = pBase + spliti->second * newBuf->getVertexSize(); memcpy(pDstBase, pSrcBase, newBuf->getVertexSize()); } newBuf->unlock(); } // Update vertex data // Increase vertex count according to num splits mVData->vertexCount += vertexSplits.size(); // Flip bindings over to new buffers (old buffers released) HardwareBufferManager::getSingleton().destroyVertexBufferBinding(mVData->vertexBufferBinding); mVData->vertexBufferBinding = newBindings; } }
//--------------------------------------------------------------------- void PanelOverlayElement::updatePositionGeometry(void) { /* 0-----2 | /| | / | |/ | 1-----3 */ Real left, right, top, bottom; /* Convert positions into -1, 1 coordinate space (homogenous clip space). - Left / right is simple range conversion - Top / bottom also need inverting since y is upside down - this means that top will end up greater than bottom and when computing texture coordinates, we have to flip the v-axis (ie. subtract the value from 1.0 to get the actual correct value). */ left = _getDerivedLeft() * 2 - 1; right = left + (mWidth * 2); top = -((_getDerivedTop() * 2) - 1); bottom = top - (mHeight * 2); HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING); float* pPos = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); // Use the furthest away depth value, since materials should have depth-check off // This initialised the depth buffer for any 3D objects in front Real zValue = Root::getSingleton().getRenderSystem()->getMaximumDepthInputValue(); *pPos++ = left; *pPos++ = top; *pPos++ = zValue; *pPos++ = left; *pPos++ = bottom; *pPos++ = zValue; *pPos++ = right; *pPos++ = top; *pPos++ = zValue; *pPos++ = right; *pPos++ = bottom; *pPos++ = zValue; vbuf->unlock(); }
void EdgeBuilderTests::testSingleIndexBufSingleVertexBuf() { /* This tests the edge builders ability to find shared edges in the simple case of a single index buffer referencing a single vertex buffer */ VertexData vd; IndexData id; // Test pyramid vd.vertexCount = 4; vd.vertexStart = 0; vd.vertexDeclaration = HardwareBufferManager::getSingleton().createVertexDeclaration(); vd.vertexDeclaration->addElement(0, 0, VET_FLOAT3, VES_POSITION); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer(sizeof(float)*3, 4, HardwareBuffer::HBU_STATIC,true); vd.vertexBufferBinding->setBinding(0, vbuf); float* pFloat = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); *pFloat++ = 0 ; *pFloat++ = 0 ; *pFloat++ = 0 ; *pFloat++ = 50 ; *pFloat++ = 0 ; *pFloat++ = 0 ; *pFloat++ = 0 ; *pFloat++ = 100; *pFloat++ = 0 ; *pFloat++ = 0 ; *pFloat++ = 0 ; *pFloat++ = -50; vbuf->unlock(); id.indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, 12, HardwareBuffer::HBU_STATIC, true); id.indexCount = 12; id.indexStart = 0; unsigned short* pIdx = static_cast<unsigned short*>(id.indexBuffer->lock(HardwareBuffer::HBL_DISCARD)); *pIdx++ = 0; *pIdx++ = 1; *pIdx++ = 2; *pIdx++ = 0; *pIdx++ = 2; *pIdx++ = 3; *pIdx++ = 1; *pIdx++ = 3; *pIdx++ = 2; *pIdx++ = 0; *pIdx++ = 3; *pIdx++ = 1; id.indexBuffer->unlock(); EdgeListBuilder edgeBuilder; edgeBuilder.addVertexData(&vd); edgeBuilder.addIndexData(&id); EdgeData* edgeData = edgeBuilder.build(); // Should be only one group, since only one vertex buffer CPPUNIT_ASSERT(edgeData->edgeGroups.size() == 1); // 4 tris CPPUNIT_ASSERT(edgeData->triangles.size() == 4); EdgeData::EdgeGroup& eg = edgeData->edgeGroups[0]; // 6 edges CPPUNIT_ASSERT(eg.edges.size() == 6); delete edgeData; }
void DynamicLines::fillHardwareBuffers() { int size = (int)mPoints.size(); prepareHardwareBuffers(size, 0); if (!size) { mBox.setExtents(Vector3::ZERO, Vector3::ZERO); mDirty = false; return; } Vector3 vaabMin = mPoints[0]; Vector3 vaabMax = mPoints[0]; HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(0); Real* prPos = static_cast<Real*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); { for (int i = 0; i < size; i++) { *prPos++ = mPoints[i].x; *prPos++ = mPoints[i].y; *prPos++ = mPoints[i].z; 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(); mBox.setExtents(vaabMin, vaabMax); mDirty = false; }
void DebugRectangle2D::setCorners(Real left, Real top, Real right, Real bottom) { VertexDeclaration * const decl = mRenderOp.vertexData->vertexDeclaration; const VertexElement* poselem = decl->findElementBySemantic(VES_POSITION); const VertexElement* colorelem = decl->findElementBySemantic(VES_DIFFUSE); HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(POSITION_BINDING); const size_t vertexSize = vbuf->getVertexSize (); float *pPos; RGBA *pColor; Root * const root = Root::getSingletonPtr(); uchar* pMain = static_cast<uchar *>( vbuf->lock(HardwareBuffer::HBL_DISCARD)); // #define V3(AX, AY, AZ, ACOLOR) poselem->baseVertexPointerToElement(pMain, &pPos); \ // *pPos++ = AX; *pPos++ = AY; *pPos++ = AZ; \ // pMain += vertexSize; #define V3(A_X, A_Y, A_Z, ACOLOR) poselem->baseVertexPointerToElement(pMain, &pPos); \ *pPos++ = static_cast <float> (A_X); \ *pPos++ = static_cast <float> (A_Y); \ *pPos++ = static_cast <float> (A_Z); \ colorelem->baseVertexPointerToElement(pMain, &pColor); \ root->convertColourValue (ACOLOR, pColor); \ pMain += vertexSize; V3(left, top, -1.0f, ColourValue::White) V3(left, bottom, -1.0f, ColourValue::White) V3(right, bottom, -1.0f, ColourValue::White) V3(right, top, -1.0f, ColourValue::White) vbuf->unlock(); HardwareIndexBufferSharedPtr iBuf = mRenderOp.indexData->indexBuffer; ushort* pIdx = static_cast<ushort*>( iBuf->lock(0, iBuf->getSizeInBytes(),HardwareBuffer::HBL_DISCARD)); *pIdx++ = static_cast<ushort> (0); *pIdx++ = static_cast<ushort> (1); // line 1 *pIdx++ = static_cast<ushort> (1); *pIdx++ = static_cast<ushort> (2);// line 2 *pIdx++ = static_cast<ushort> (2); *pIdx++ = static_cast<ushort> (3);// line 3 *pIdx++ = static_cast<ushort> (3); *pIdx++ = static_cast<ushort> (0);// line 4 iBuf->unlock(); }
void SkyManager::ModVertexAlpha(Entity* ent, unsigned int meshType) { // Get the vertex colour buffer of this mesh const Ogre::VertexElement* ves_diffuse = ent->getMesh()->getSubMesh(0)->vertexData->vertexDeclaration->findElementBySemantic( Ogre::VES_DIFFUSE ); HardwareVertexBufferSharedPtr colourBuffer = ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource()); // Lock void* pData = colourBuffer->lock(HardwareBuffer::HBL_NORMAL); // Iterate over all vertices int vertex_size = colourBuffer->getVertexSize(); float * currentVertex = NULL; for (unsigned int i=0; i<colourBuffer->getNumVertices(); ++i) { // Get a pointer to the vertex colour ves_diffuse->baseVertexPointerToElement( pData, ¤tVertex ); unsigned char alpha=0; if (meshType == 0) alpha = i%2 ? 0 : 255; // this is a cylinder, so every second vertex belongs to the bottom-most row else if (meshType == 1) { if (i>= 49 && i <= 64) alpha = 0; // bottom-most row else if (i>= 33 && i <= 48) alpha = 64; // second bottom-most row else alpha = 255; } // NB we would have to swap R and B depending on rendersystem specific VertexElementType, but doesn't matter since they are both 1 uint8 tmpR = static_cast<uint8>(255); uint8 tmpG = static_cast<uint8>(255); uint8 tmpB = static_cast<uint8>(255); uint8 tmpA = static_cast<uint8>(alpha); // Modify *((uint32*)currentVertex) = tmpR | (tmpG << 8) | (tmpB << 16) | (tmpA << 24); // Move to the next vertex pData = static_cast<unsigned char *> (pData) + vertex_size; } // Unlock ent->getMesh()->getSubMesh(0)->vertexData->vertexBufferBinding->getBuffer(ves_diffuse->getSource())->unlock(); }
AxisAlignedBox getVertexDataAabb( VertexData* vd, const Ogre::Matrix4& transform) { AxisAlignedBox aabb; const VertexElement* ve = vd->vertexDeclaration->findElementBySemantic(VES_POSITION); HardwareVertexBufferSharedPtr vb = vd->vertexBufferBinding->getBuffer(ve->getSource()); unsigned char* data = static_cast<unsigned char*>( vb->lock(Ogre::HardwareBuffer::HBL_READ_ONLY)); for (size_t i = 0; i < vd->vertexCount; ++i) { float* v; ve->baseVertexPointerToElement(data, &v); aabb.merge(transform * Ogre::Vector3(v[0], v[1], v[2])); data += vb->getVertexSize(); } vb->unlock(); return aabb; }
//----------------------------------------------------------------------------------- void Rectangle2D::setNormals( const Ogre::Vector3 &topLeft, const Ogre::Vector3 &bottomLeft, const Ogre::Vector3 &topRight, const Ogre::Vector3 &bottomRight) { HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer( 1 ); float* pFloat = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); *pFloat++ = topLeft.x; *pFloat++ = topLeft.y; *pFloat++ = topLeft.z; if( mQuad ) { *pFloat++ = bottomLeft.x; *pFloat++ = bottomLeft.y; *pFloat++ = bottomLeft.z; *pFloat++ = topRight.x; *pFloat++ = topRight.y; *pFloat++ = topRight.z; *pFloat++ = bottomRight.x; *pFloat++ = bottomRight.y; *pFloat++ = bottomRight.z; } else { *pFloat++ = bottomLeft.x; *pFloat++ = Math::lerp( topLeft.y, bottomLeft.y, 2.0f ); *pFloat++ = bottomLeft.z; *pFloat++ = Math::lerp( topLeft.x, topRight.x, 2.0f ); *pFloat++ = topRight.y; *pFloat++ = topRight.z; } vbuf->unlock(); }
void Rectangle2D::setUVs( const Ogre::Vector2 &topLeft, const Ogre::Vector2 &bottomLeft, const Ogre::Vector2 &topRight, const Ogre::Vector2 &bottomRight) { if( mRenderOp.vertexData->vertexDeclaration->getElementCount() <= TEXCOORD_BINDING ) return; //Vertex data wasn't built with UV buffer HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(TEXCOORD_BINDING); float* pFloat = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); *pFloat++ = topLeft.x; *pFloat++ = topLeft.y; *pFloat++ = bottomLeft.x; *pFloat++ = bottomLeft.y; *pFloat++ = topRight.x; *pFloat++ = topRight.y; *pFloat++ = bottomRight.x; *pFloat++ = bottomRight.y; vbuf->unlock(); }
void Rectangle2D::setNormals(const Ogre::Vector3 &topLeft, const Ogre::Vector3 &bottomLeft, const Ogre::Vector3 &topRight, const Ogre::Vector3 &bottomRight) { HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(NORMAL_BINDING); float* pFloat = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); *pFloat++ = topLeft.x; *pFloat++ = topLeft.y; *pFloat++ = topLeft.z; *pFloat++ = bottomLeft.x; *pFloat++ = bottomLeft.y; *pFloat++ = bottomLeft.z; *pFloat++ = topRight.x; *pFloat++ = topRight.y; *pFloat++ = topRight.z; *pFloat++ = bottomRight.x; *pFloat++ = bottomRight.y; *pFloat++ = bottomRight.z; vbuf->unlock(); }
//--------------------------------------------------------------------- void PanelOverlayElement::updateTextureGeometry(void) { // Generate for as many texture layers as there are in material if (!mpMaterial.isNull() && mInitialised) { // Assume one technique and pass for the moment size_t numLayers = mpMaterial->getTechnique(0)->getPass(0)->getNumTextureUnitStates(); VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; // Check the number of texcoords we have in our buffer now if (mNumTexCoordsInBuffer > numLayers) { // remove extras for (size_t i = mNumTexCoordsInBuffer; i > numLayers; --i) { decl->removeElement(VES_TEXTURE_COORDINATES, static_cast<unsigned short>(i)); } } else if (mNumTexCoordsInBuffer < numLayers) { // Add extra texcoord elements size_t offset = VertexElement::getTypeSize(VET_FLOAT2) * mNumTexCoordsInBuffer; for (size_t i = mNumTexCoordsInBuffer; i < numLayers; ++i) { decl->addElement(TEXCOORD_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, static_cast<unsigned short>(i)); offset += VertexElement::getTypeSize(VET_FLOAT2); } } // if number of layers changed at all, we'll need to reallocate buffer if (mNumTexCoordsInBuffer != numLayers) { // NB reference counting will take care of the old one if it exists HardwareVertexBufferSharedPtr newbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(TEXCOORD_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY // mostly static except during resizing ); // Bind buffer, note this will unbind the old one and destroy the buffer it had mRenderOp.vertexData->vertexBufferBinding->setBinding(TEXCOORD_BINDING, newbuf); // Set num tex coords in use now mNumTexCoordsInBuffer = numLayers; } // Get the tcoord buffer & lock if (mNumTexCoordsInBuffer) { HardwareVertexBufferSharedPtr vbuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(TEXCOORD_BINDING); float* pVBStart = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); size_t uvSize = VertexElement::getTypeSize(VET_FLOAT2) / sizeof(float); size_t vertexSize = decl->getVertexSize(TEXCOORD_BINDING) / sizeof(float); for (ushort i = 0; i < numLayers; ++i) { // Calc upper tex coords Real upperX = mU2 * mTileX[i]; Real upperY = mV2 * mTileY[i]; /* 0-----2 | /| | / | |/ | 1-----3 */ // Find start offset for this set float* pTex = pVBStart + (i * uvSize); pTex[0] = mU1; pTex[1] = mV1; pTex += vertexSize; // jump by 1 vertex stride pTex[0] = mU1; pTex[1] = upperY; pTex += vertexSize; pTex[0] = upperX; pTex[1] = mV1; pTex += vertexSize; pTex[0] = upperX; pTex[1] = upperY; } vbuf->unlock(); } } }
//--------------------------------------------------------------------- void PrefabFactory::createSphere(Mesh* mesh) { // sphere creation code taken from the DeferredShading sample, originally from the wiki SubMesh *pSphereVertex = mesh->createSubMesh(); const int NUM_SEGMENTS = 16; const int NUM_RINGS = 16; const Real SPHERE_RADIUS = 50.0; mesh->sharedVertexData = OGRE_NEW VertexData(); VertexData* vertexData = mesh->sharedVertexData; // define the vertex format VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // two dimensional texture coordinates vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); // allocate the vertex buffer vertexData->vertexCount = (NUM_RINGS + 1) * (NUM_SEGMENTS+1); HardwareVertexBufferSharedPtr vBuf = HardwareBufferManager::getSingleton().createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vBuf); float* pVertex = static_cast<float*>(vBuf->lock(HardwareBuffer::HBL_DISCARD)); // allocate index buffer pSphereVertex->indexData->indexCount = 6 * NUM_RINGS * (NUM_SEGMENTS + 1); pSphereVertex->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer(HardwareIndexBuffer::IT_16BIT, pSphereVertex->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); HardwareIndexBufferSharedPtr iBuf = pSphereVertex->indexData->indexBuffer; unsigned short* pIndices = static_cast<unsigned short*>(iBuf->lock(HardwareBuffer::HBL_DISCARD)); float fDeltaRingAngle = (Math::PI / NUM_RINGS); float fDeltaSegAngle = (2 * Math::PI / NUM_SEGMENTS); unsigned short wVerticeIndex = 0 ; // Generate the group of rings for the sphere for( int ring = 0; ring <= NUM_RINGS; ring++ ) { float r0 = SPHERE_RADIUS * sinf (ring * fDeltaRingAngle); float y0 = SPHERE_RADIUS * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(int seg = 0; seg <= NUM_SEGMENTS; seg++) { float x0 = r0 * sinf(seg * fDeltaSegAngle); float z0 = r0 * cosf(seg * fDeltaSegAngle); // Add one vertex to the strip which makes up the sphere *pVertex++ = x0; *pVertex++ = y0; *pVertex++ = z0; Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy(); *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z; *pVertex++ = (float) seg / (float) NUM_SEGMENTS; *pVertex++ = (float) ring / (float) NUM_RINGS; if (ring != NUM_RINGS) { // each vertex (except the last) has six indicies pointing to it *pIndices++ = wVerticeIndex + NUM_SEGMENTS + 1; *pIndices++ = wVerticeIndex; *pIndices++ = wVerticeIndex + NUM_SEGMENTS; *pIndices++ = wVerticeIndex + NUM_SEGMENTS + 1; *pIndices++ = wVerticeIndex + 1; *pIndices++ = wVerticeIndex; wVerticeIndex ++; } }; // end for seg } // end for ring // Unlock vBuf->unlock(); iBuf->unlock(); // Generate face list pSphereVertex->useSharedVertices = true; // the original code was missing this line: mesh->_setBounds( AxisAlignedBox( Vector3(-SPHERE_RADIUS, -SPHERE_RADIUS, -SPHERE_RADIUS), Vector3(SPHERE_RADIUS, SPHERE_RADIUS, SPHERE_RADIUS) ), false ); mesh->_setBoundingSphereRadius(SPHERE_RADIUS); }
void Rectangle2D::_initRectangle2D(bool includeTextureCoords, Ogre::HardwareBuffer::Usage vBufUsage) { // use identity projection and view matrices mUseIdentityProjection = true; mUseIdentityView = true; mRenderOp.vertexData = OGRE_NEW VertexData(); mRenderOp.indexData = 0; mRenderOp.vertexData->vertexCount = 4; mRenderOp.vertexData->vertexStart = 0; mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP; mRenderOp.useIndexes = false; mRenderOp.useGlobalInstancingVertexBufferIsAvailable = false; VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(POSITION_BINDING), mRenderOp.vertexData->vertexCount, vBufUsage); // Bind buffer bind->setBinding(POSITION_BINDING, vbuf); decl->addElement(NORMAL_BINDING, 0, VET_FLOAT3, VES_NORMAL); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(NORMAL_BINDING), mRenderOp.vertexData->vertexCount, vBufUsage); bind->setBinding(NORMAL_BINDING, vbuf); float *pNorm = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); *pNorm++ = 0.0f; *pNorm++ = 0.0f; *pNorm++ = 1.0f; *pNorm++ = 0.0f; *pNorm++ = 0.0f; *pNorm++ = 1.0f; *pNorm++ = 0.0f; *pNorm++ = 0.0f; *pNorm++ = 1.0f; *pNorm++ = 0.0f; *pNorm++ = 0.0f; *pNorm++ = 1.0f; vbuf->unlock(); if (includeTextureCoords) { decl->addElement(TEXCOORD_BINDING, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES); HardwareVertexBufferSharedPtr tvbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(TEXCOORD_BINDING), mRenderOp.vertexData->vertexCount, vBufUsage); // Bind buffer bind->setBinding(TEXCOORD_BINDING, tvbuf); // Set up basic tex coordinates setDefaultUVs(); } // set basic white material this->setMaterial("BaseWhiteNoLighting"); }
void MeshSerializerTests::assertVertexDataClone(VertexData* a, VertexData* b, MeshVersion version /*= MESH_VERSION_LATEST*/) { CPPUNIT_ASSERT((a == NULL) == (b == NULL)); if (a) { // compare bindings { const VertexBufferBinding::VertexBufferBindingMap& aBindings = a->vertexBufferBinding->getBindings(); const VertexBufferBinding::VertexBufferBindingMap& bBindings = b->vertexBufferBinding->getBindings(); CPPUNIT_ASSERT(aBindings.size() == bBindings.size()); typedef VertexBufferBinding::VertexBufferBindingMap::const_iterator bindingIterator; bindingIterator aIt = aBindings.begin(); bindingIterator aEndIt = aBindings.end(); bindingIterator bIt = bBindings.begin(); for (; aIt != aEndIt; aIt++, bIt++) { CPPUNIT_ASSERT(aIt->first == bIt->first); CPPUNIT_ASSERT((aIt->second.get() == NULL) == (bIt->second.get() == NULL)); if (a) { CPPUNIT_ASSERT(aIt->second->getManager() == bIt->second->getManager()); CPPUNIT_ASSERT(aIt->second->getNumVertices() == bIt->second->getNumVertices()); } } } { const VertexDeclaration::VertexElementList& aElements = a->vertexDeclaration->getElements(); const VertexDeclaration::VertexElementList& bElements = a->vertexDeclaration->getElements(); CPPUNIT_ASSERT(aElements.size() == bElements.size()); typedef VertexDeclaration::VertexElementList::const_iterator bindingIterator; bindingIterator aIt = aElements.begin(); bindingIterator aEndIt = aElements.end(); bindingIterator bIt; for (; aIt != aEndIt; aIt++) { bIt = std::find(bElements.begin(), bElements.end(), *aIt); CPPUNIT_ASSERT(bIt != bElements.end()); #ifndef OGRE_TEST_XMLSERIALIZER const VertexElement& aElem = *aIt; const VertexElement& bElem = *bIt; HardwareVertexBufferSharedPtr abuf = a->vertexBufferBinding->getBuffer(aElem.getSource()); HardwareVertexBufferSharedPtr bbuf = b->vertexBufferBinding->getBuffer(bElem.getSource()); unsigned char* avertex = static_cast<unsigned char*>(abuf->lock(HardwareBuffer::HBL_READ_ONLY)); unsigned char* bvertex = static_cast<unsigned char*>(bbuf->lock(HardwareBuffer::HBL_READ_ONLY)); size_t avSize = abuf->getVertexSize(); size_t bvSize = bbuf->getVertexSize(); size_t elemSize = VertexElement::getTypeSize(aElem.getType()); unsigned char* avEnd = avertex + a->vertexCount * avSize; bool error = false; for (; avertex < avEnd; avertex += avSize, bvertex += bvSize) { float* afloat, * bfloat; aElem.baseVertexPointerToElement(avertex, &afloat); bElem.baseVertexPointerToElement(bvertex, &bfloat); error |= (memcmp(afloat, bfloat, elemSize) != 0); } abuf->unlock(); bbuf->unlock(); CPPUNIT_ASSERT(!error && "Content of vertex buffer differs!"); #endif /* ifndef OGRE_TEST_XMLSERIALIZER */ } } CPPUNIT_ASSERT(a->vertexStart == b->vertexStart); CPPUNIT_ASSERT(a->vertexCount == b->vertexCount); CPPUNIT_ASSERT(a->hwAnimDataItemsUsed == b->hwAnimDataItemsUsed); // Compare hwAnimationData { const VertexData::HardwareAnimationDataList& aAnimData = a->hwAnimationDataList; const VertexData::HardwareAnimationDataList& bAnimData = b->hwAnimationDataList; CPPUNIT_ASSERT(aAnimData.size() == bAnimData.size()); typedef VertexData::HardwareAnimationDataList::const_iterator bindingIterator; bindingIterator aIt = aAnimData.begin(); bindingIterator aEndIt = aAnimData.end(); bindingIterator bIt = bAnimData.begin(); for (; aIt != aEndIt; aIt++, bIt++) { CPPUNIT_ASSERT(aIt->parametric == bIt->parametric); CPPUNIT_ASSERT(aIt->targetBufferIndex == bIt->targetBufferIndex); } } } }
Mesh *GrassLoader::generateGrass_SPRITE(PageInfo &page, GrassLayer *layer, float *grassPositions, unsigned int grassCount) { //Calculate the number of quads to be added unsigned int quadCount; quadCount = grassCount; // check for overflows of the uint16's unsigned int maxUInt16 = std::numeric_limits<uint16>::max(); if(grassCount > maxUInt16) { LogManager::getSingleton().logMessage("grass count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) + " (thats the maximum) grass meshes for one page"); return 0; } if(quadCount > maxUInt16) { LogManager::getSingleton().logMessage("quad count overflow: you tried to use more than " + StringConverter::toString(maxUInt16) + " (thats the maximum) grass meshes for one page"); return 0; } //Create manual mesh to store grass quads MeshPtr mesh = MeshManager::getSingleton().createManual(getUniqueID(), ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *subMesh = mesh->createSubMesh(); subMesh->useSharedVertices = false; //Setup vertex format information subMesh->vertexData = new VertexData; subMesh->vertexData->vertexStart = 0; subMesh->vertexData->vertexCount = 4 * quadCount; VertexDeclaration* dcl = subMesh->vertexData->vertexDeclaration; size_t offset = 0; dcl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); dcl->addElement(0, offset, VET_FLOAT4, VES_NORMAL); offset += VertexElement::getTypeSize(VET_FLOAT4); dcl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE); offset += VertexElement::getTypeSize(VET_COLOUR); dcl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES); offset += VertexElement::getTypeSize(VET_FLOAT2); //Populate a new vertex buffer with grass HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton() .createVertexBuffer(offset, subMesh->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); float* pReal = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); //Calculate size variance float rndWidth = layer->maxWidth - layer->minWidth; float rndHeight = layer->maxHeight - layer->minHeight; float minY = Math::POS_INFINITY, maxY = Math::NEG_INFINITY; float *posPtr = grassPositions; //Position array "iterator" for (uint16 i = 0; i < grassCount; ++i) { //Get the x and z positions from the position array float x = *posPtr++; float z = *posPtr++; //Calculate height float y; if (heightFunction){ y = heightFunction(x, z, heightFunctionUserData); } else { y = 0; } float x1 = (x - page.centerPoint.x); float z1 = (z - page.centerPoint.z); //Get the color at the grass position uint32 color; if (layer->colorMap) color = layer->colorMap->getColorAt(x, z, layer->mapBounds); else color = 0xFFFFFFFF; //Calculate size float rnd = *posPtr++; //The same rnd value is used for width and height to maintain aspect ratio float halfXScale = (layer->minWidth + rndWidth * rnd) * 0.5f; float scaleY = (layer->minHeight + rndHeight * rnd); //Randomly mirror grass textures float uvLeft, uvRight; if (*posPtr++ > 0.5f){ uvLeft = 0; uvRight = 1; } else { uvLeft = 1; uvRight = 0; } //Add vertices *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = -halfXScale; *pReal++ = scaleY; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvLeft; *pReal++ = 0; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = +halfXScale; *pReal++ = scaleY; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvRight; *pReal++ = 0; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = -halfXScale; *pReal++ = 0.0f; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvLeft; *pReal++ = 1; //uv *pReal++ = x1; *pReal++ = y; *pReal++ = z1; //center position *pReal++ = +halfXScale; *pReal++ = 0.0f; *pReal++ = 0; *pReal++ = 0; //normal (used to store relative corner positions) *((uint32*)pReal++) = color; //color *pReal++ = uvRight; *pReal++ = 1; //uv //Update bounds if (y < minY) minY = y; if (y + scaleY > maxY) maxY = y + scaleY; } vbuf->unlock(); subMesh->vertexData->vertexBufferBinding->setBinding(0, vbuf); //Populate index buffer subMesh->indexData->indexStart = 0; subMesh->indexData->indexCount = 6 * quadCount; subMesh->indexData->indexBuffer = HardwareBufferManager::getSingleton() .createIndexBuffer(HardwareIndexBuffer::IT_16BIT, subMesh->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); uint16* pI = static_cast<uint16*>(subMesh->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD)); for (uint16 i = 0; i < quadCount; ++i) { uint16 offset = i * 4; *pI++ = 0 + offset; *pI++ = 2 + offset; *pI++ = 1 + offset; *pI++ = 1 + offset; *pI++ = 2 + offset; *pI++ = 3 + offset; } subMesh->indexData->indexBuffer->unlock(); //subMesh->setBuildEdgesEnabled(autoEdgeBuildEnabled); //Finish up mesh AxisAlignedBox bounds(page.bounds.left - page.centerPoint.x, minY, page.bounds.top - page.centerPoint.z, page.bounds.right - page.centerPoint.x, maxY, page.bounds.bottom - page.centerPoint.z); mesh->_setBounds(bounds); Vector3 temp = bounds.getMaximum() - bounds.getMinimum(); mesh->_setBoundingSphereRadius(temp.length() * 0.5f); LogManager::getSingleton().setLogDetail(static_cast<LoggingLevel>(0)); mesh->setAutoBuildEdgeLists(autoEdgeBuildEnabled); mesh->load(); LogManager::getSingleton().setLogDetail(LL_NORMAL); //Apply grass material to mesh subMesh->setMaterialName(layer->material->getName()); //Return the mesh return mesh.getPointer(); }
void OgreNewtonMesh::ParseEntity (MeshPtr mesh, const Matrix4& matrix) { //find number of sub-meshes unsigned short sub = mesh->getNumSubMeshes(); for (unsigned short cs = 0; cs < sub; cs++) { SubMesh* const sub_mesh = mesh->getSubMesh(cs); //vertex data! VertexData* v_data; if (sub_mesh->useSharedVertices) { v_data = mesh->sharedVertexData; } else { v_data = sub_mesh->vertexData; } //let's find more information about the Vertices... VertexDeclaration* const v_decl = v_data->vertexDeclaration; const VertexElement* const vertexElem = v_decl->findElementBySemantic(VES_POSITION); HardwareVertexBufferSharedPtr vertexPtr = v_data->vertexBufferBinding->getBuffer(vertexElem->getSource()); dNewtonScopeBuffer<Vector3> points(vertexPtr->getNumVertices()); { int size = vertexPtr->getVertexSize(); int offset = vertexElem->getOffset() / sizeof (float); unsigned char* const ptr = static_cast<unsigned char*> (vertexPtr->lock(HardwareBuffer::HBL_READ_ONLY)); for (int i = 0; i < points.GetElementsCount(); i ++) { float* data; vertexElem->baseVertexPointerToElement(ptr + i * size, &data); points[i] = matrix.transformAffine (Vector3 (data[offset + 0], data[offset + 1], data[offset + 2])); } vertexPtr->unlock(); } dNewtonScopeBuffer<Vector3> normals; const VertexElement* const normalElem = v_decl->findElementBySemantic(VES_NORMAL); if (normalElem) { HardwareVertexBufferSharedPtr normalPtr = v_data->vertexBufferBinding->getBuffer(normalElem->getSource()); normals.Init (normalPtr->getNumVertices()); int size = normalPtr->getVertexSize(); int offset = vertexElem->getOffset() / sizeof (float); unsigned char* const ptr = static_cast<unsigned char*> (normalPtr->lock(HardwareBuffer::HBL_READ_ONLY)); for (int i = 0; i < normals.GetElementsCount(); i ++) { float* data; vertexElem->baseVertexPointerToElement(ptr + i * size, &data); normals[i] = matrix * Vector3 (data[offset + 0], data[offset + 1], data[offset + 2]); normals[i] = normals[i].normalise(); } normalPtr->unlock(); } dNewtonScopeBuffer<Vector3> uvs; const VertexElement* const uvElem = v_decl->findElementBySemantic(VES_TEXTURE_COORDINATES); if (uvElem) { HardwareVertexBufferSharedPtr uvPtr = v_data->vertexBufferBinding->getBuffer(uvElem->getSource()); uvs.Init (uvPtr->getNumVertices()); int size = uvPtr->getVertexSize(); int offset = vertexElem->getOffset() / sizeof (float); unsigned char* const ptr = static_cast<unsigned char*> (uvPtr->lock(HardwareBuffer::HBL_READ_ONLY)); for (int i = 0; i < uvs.GetElementsCount(); i ++) { float* data; uvElem->baseVertexPointerToElement(ptr + i * size, &data); uvs[i] = Vector3 (data[offset + 0], data[offset + 1], 0.0f); } uvPtr->unlock(); } //now find more about the index!! IndexData* const i_data = sub_mesh->indexData; size_t index_count = i_data->indexCount; size_t poly_count = index_count / 3; // get pointer! HardwareIndexBufferSharedPtr i_sptr = i_data->indexBuffer; // 16 or 32 bit indices? bool uses32bit = (i_sptr->getType() == HardwareIndexBuffer::IT_32BIT); unsigned long* i_Longptr = NULL; unsigned short* i_Shortptr = NULL; if (uses32bit) { i_Longptr = static_cast<unsigned long*> (i_sptr->lock(HardwareBuffer::HBL_READ_ONLY)); } else { i_Shortptr = static_cast<unsigned short*> (i_sptr->lock(HardwareBuffer::HBL_READ_ONLY)); } //now loop through the indices, getting polygon info! int i_offset = 0; Real poly_verts[3][12]; memset (poly_verts, 0, sizeof (poly_verts)); for (size_t i = 0; i < poly_count; i++) { for (int j = 0; j < 3; j++) { // index to first vertex! int idx = uses32bit ? i_Longptr[i_offset + j] : i_Shortptr[i_offset + j]; poly_verts[j][0] = points[idx].x; poly_verts[j][1] = points[idx].y; poly_verts[j][2] = points[idx].z; poly_verts[j][3] = 0.0f; if (normals.GetElementsCount()) { poly_verts[j][4] = normals[idx].x; poly_verts[j][5] = normals[idx].y; poly_verts[j][6] = normals[idx].z; } if (uvs.GetElementsCount()) { poly_verts[j][7] = uvs[idx].x; poly_verts[j][8] = uvs[idx].y; } } AddFace(3, &poly_verts[0][0], 12 * sizeof (Real), cs); i_offset += 3; } i_sptr->unlock(); } }
/* ******************************************************************************* | implement of CGrassSticks ******************************************************************************* */ void CGrassSticks::createGrassMesh() { MeshPtr mesh = MeshManager::getSingleton().createManual(GRASS_MESH_NAME, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); // create a submesh with the grass material SubMesh* sm = mesh->createSubMesh(); sm->setMaterialName("Examples/GrassBlades"); sm->useSharedVertices = false; sm->vertexData = OGRE_NEW VertexData(); sm->vertexData->vertexStart = 0; sm->vertexData->vertexCount = 12; sm->indexData->indexCount = 18; // specify a vertex format declaration for our mesh: 3 floats for position, 3 floats for normal, 2 floats for UV VertexDeclaration* decl = sm->vertexData->vertexDeclaration; decl->addElement(0, 0, VET_FLOAT3, VES_POSITION); decl->addElement(0, sizeof(float) * 3, VET_FLOAT3, VES_NORMAL); decl->addElement(0, sizeof(float) * 6, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); // create a vertex buffer HardwareVertexBufferSharedPtr vb = HardwareBufferManager::getSingleton().createVertexBuffer (decl->getVertexSize(0), sm->vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); GrassVertex* verts = (GrassVertex*)vb->lock(HardwareBuffer::HBL_DISCARD); // start filling in vertex data for (unsigned int i = 0; i < 3; i++) // each grass mesh consists of 3 planes { // planes intersect along the Y axis with 60 degrees between them Real x = Math::Cos(Degree(i * 60)) * GRASS_WIDTH / 2; Real z = Math::Sin(Degree(i * 60)) * GRASS_WIDTH / 2; for (unsigned int j = 0; j < 4; j++) // each plane has 4 vertices { GrassVertex& vert = verts[i * 4 + j]; vert.x = j < 2 ? -x : x; vert.y = j % 2 ? 0 : GRASS_HEIGHT; vert.z = j < 2 ? -z : z; // all normals point straight up vert.nx = 0; vert.ny = 1; vert.nz = 0; vert.u = j < 2 ? 0 : 1; vert.v = j % 2; } } vb->unlock(); // commit vertex changes sm->vertexData->vertexBufferBinding->setBinding(0, vb); // bind vertex buffer to our submesh // create an index buffer sm->indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer (HardwareIndexBuffer::IT_16BIT, sm->indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // start filling in index data Ogre::uint16* indices = (Ogre::uint16*)sm->indexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD); for (unsigned int i = 0; i < 3; i++) // each grass mesh consists of 3 planes { unsigned int off = i * 4; // each plane consists of 2 triangles *indices++ = 0 + off; *indices++ = 3 + off; *indices++ = 1 + off; *indices++ = 0 + off; *indices++ = 2 + off; *indices++ = 3 + off; } sm->indexData->indexBuffer->unlock(); // commit index changes // update mesh AABB Ogre::AxisAlignedBox aabb; aabb.setExtents(-1,-1,-1,1,1,1); mesh->_setBounds(aabb); // Ogre::MeshSerializer serial; // serial.exportMesh(mesh.getPointer(), "grass.mesh"); }
void MovableText::_setupGeometry() { assert(mpFont); assert(!mpMaterial.isNull()); unsigned int vertexCount = 0; //count letters to determine how many vertices are needed std::string::iterator i = mCaption.begin(); std::string::iterator iend = mCaption.end(); for ( ; i != iend; ++i ) { if ((*i != ' ') && (*i != '\n')) { vertexCount += 6; } } if (mRenderOp.vertexData) { delete mRenderOp.vertexData; mRenderOp.vertexData = NULL; mUpdateColors = true; } if (mCaption.empty()) { return; } if (!mRenderOp.vertexData) mRenderOp.vertexData = new VertexData(); mRenderOp.indexData = 0; mRenderOp.vertexData->vertexStart = 0; mRenderOp.vertexData->vertexCount = vertexCount; mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; mRenderOp.useIndexes = false; VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration; VertexBufferBinding *bind = mRenderOp.vertexData->vertexBufferBinding; size_t offset = 0; // create/bind positions/tex.ccord. buffer if (!decl->findElementBySemantic(VES_POSITION)) decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); if (!decl->findElementBySemantic(VES_TEXTURE_COORDINATES)) decl->addElement(POS_TEX_BINDING, offset, Ogre::VET_FLOAT2, Ogre::VES_TEXTURE_COORDINATES, 0); HardwareVertexBufferSharedPtr ptbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(POS_TEX_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); bind->setBinding(POS_TEX_BINDING, ptbuf); // Colours - store these in a separate buffer because they change less often if (!decl->findElementBySemantic(VES_DIFFUSE)) decl->addElement(COLOUR_BINDING, 0, VET_COLOUR, VES_DIFFUSE); HardwareVertexBufferSharedPtr cbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(COLOUR_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); bind->setBinding(COLOUR_BINDING, cbuf); float *pPCBuff = static_cast<float*> (ptbuf->lock(HardwareBuffer::HBL_DISCARD)); Real spaceWidth = mSpaceWidth; // Derive space width from a capital A if (spaceWidth == 0) spaceWidth = mpFont->getGlyphAspectRatio('A') * mCharHeight * 2.0; float total_height = mCharHeight; float total_width = 0.0f; float current_width = 0.0f; i = mCaption.begin(); iend = mCaption.end(); for ( ; i != iend; ++i ) { if (*i == '\n') { total_height += mCharHeight + 0.01; if ( current_width > total_width ) { total_width = current_width; current_width = 0.0; } } else { current_width += mpFont->getGlyphAspectRatio(*i) * mCharHeight * 2.0; } } if ( current_width > total_width ) { total_width = current_width; } float top = 0.0f; switch (mVerticalAlignment) { case MovableText::V_ABOVE: top = total_height * 2; break; case MovableText::V_CENTER: top = 0.5 * total_height * 2; break; case MovableText::V_BELOW: top = 0.0f; break; } float starting_left = 0.0f; switch (mHorizontalAlignment) { case MovableText::H_LEFT: starting_left = 0.0f; break; case MovableText::H_CENTER: starting_left = -total_width / 2.0f; break; } float left = starting_left; bool newLine = true; Real len = 0.0f; // for calculation of AABB Ogre::Vector3 min(9999999.0f), max(-9999999.0f), currPos(0.0f); Ogre::Real maxSquaredRadius = -99999999.0f; float largestWidth = 0.0f; for (i = mCaption.begin(); i != iend; ++i) { if (newLine) { len = 0.0f; for (String::iterator j = i; j != iend && *j != '\n'; j++) { if (*j == ' ') len += spaceWidth; else len += mpFont->getGlyphAspectRatio(*j) * mCharHeight * 2.0; } newLine = false; } if (*i == '\n') { left = starting_left; top -= mCharHeight * 2.0; newLine = true; continue; } if (*i == ' ') { // Just leave a gap, no tris left += spaceWidth; continue; } Real horiz_height = mpFont->getGlyphAspectRatio(*i); Real u1, u2, v1, v2; Ogre::Font::UVRect utmp; utmp = mpFont->getGlyphTexCoords(*i); u1 = utmp.left; u2 = utmp.right; v1 = utmp.top; v2 = utmp.bottom; // each vert is (x, y, z, u, v) //------------------------------------------------------------------------------------- // First tri // // Upper left currPos = Ogre::Vector3(left, top, 0.0); *pPCBuff++ = currPos.x; *pPCBuff++ = currPos.y; *pPCBuff++ = currPos.z; *pPCBuff++ = u1; *pPCBuff++ = v1; // Deal with bounds min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); top -= mCharHeight * 2.0; // Bottom left currPos = Ogre::Vector3(left, top, 0.0); *pPCBuff++ = currPos.x; *pPCBuff++ = currPos.y; *pPCBuff++ = currPos.z; *pPCBuff++ = u1; *pPCBuff++ = v2; // Deal with bounds min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); top += mCharHeight * 2.0; left += horiz_height * mCharHeight * 2.0; // Top right currPos = Ogre::Vector3(left, top, 0.0); *pPCBuff++ = currPos.x; *pPCBuff++ = currPos.y; *pPCBuff++ = currPos.z; *pPCBuff++ = u2; *pPCBuff++ = v1; //------------------------------------------------------------------------------------- // Deal with bounds min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); //------------------------------------------------------------------------------------- // Second tri // // Top right (again) currPos = Ogre::Vector3(left, top, 0.0); *pPCBuff++ = currPos.x; *pPCBuff++ = currPos.y; *pPCBuff++ = currPos.z; *pPCBuff++ = u2; *pPCBuff++ = v1; min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); top -= mCharHeight * 2.0; left -= horiz_height * mCharHeight * 2.0; // Bottom left (again) currPos = Ogre::Vector3(left, top, 0.0); *pPCBuff++ = currPos.x; *pPCBuff++ = currPos.y; *pPCBuff++ = currPos.z; *pPCBuff++ = u1; *pPCBuff++ = v2; min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); left += horiz_height * mCharHeight * 2.0; // Bottom right currPos = Ogre::Vector3(left, top, 0.0); *pPCBuff++ = currPos.x; *pPCBuff++ = currPos.y; *pPCBuff++ = currPos.z; *pPCBuff++ = u2; *pPCBuff++ = v2; //------------------------------------------------------------------------------------- min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); // Go back up with top top += mCharHeight * 2.0; float currentWidth = (left + 1) / 2 - 0; if (currentWidth > largestWidth) largestWidth = currentWidth; } // Unlock vertex buffer ptbuf->unlock(); // update AABB/Sphere radius mAABB = Ogre::AxisAlignedBox(min, max); mRadius = Ogre::Math::Sqrt(maxSquaredRadius); if (mUpdateColors) this->_updateColors(); mNeedUpdate = false; }