//--------------------------------------------------------------------- void TextAreaOverlayElement::_restoreManualHardwareResources() { if(!mInitialised) return; // 6 verts per char since we're doing tri lists without indexes // Allocate space for positions & texture coords // Note - mRenderOp.vertexData->vertexCount will be less than allocatedVertexCount size_t allocatedVertexCount = mAllocSize * 6; VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; // Create dynamic since text tends to change a lot // positions & texcoords HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer( decl->getVertexSize(POS_TEX_BINDING), allocatedVertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); bind->setBinding(POS_TEX_BINDING, vbuf); // colours vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer( decl->getVertexSize(COLOUR_BINDING), allocatedVertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); bind->setBinding(COLOUR_BINDING, vbuf); // Buffers are restored, but with trash within mGeomPositionsOutOfDate = true; mGeomUVsOutOfDate = true; mColoursChanged = true; }
void GeomUtils::createQuad(VertexData*& vertexData) { assert(vertexData); vertexData->vertexCount = 4; vertexData->vertexStart = 0; VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; VertexBufferBinding* bind = vertexData->vertexBufferBinding; vertexDecl->addElement(0, 0, VET_FLOAT3, VES_POSITION); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( vertexDecl->getVertexSize(0), vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Bind buffer bind->setBinding(0, vbuf); // Upload data float data[]={ -1,1,-1, // corner 1 -1,-1,-1, // corner 2 1,1,-1, // corner 3 1,-1,-1}; // corner 4 vbuf->writeData(0, sizeof(data), data, true); }
void WireBoundingBox::_initWireBoundingBox() { mRenderOp.vertexData = OGRE_NEW VertexData(); mRenderOp.indexData = 0; mRenderOp.vertexData->vertexCount = 24; mRenderOp.vertexData->vertexStart = 0; mRenderOp.operationType = RenderOperation::OT_LINE_LIST; 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, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Bind buffer bind->setBinding(POSITION_BINDING, vbuf); // set basic white material this->setMaterial("BaseWhiteNoLighting"); }
//-------------------------------------------------------------------------------// void OverlayPanelElement::initialise(const String& texName, float width, float height, float left, float top) { mTexture = TextureMgr::getSingletonPtr()->getByName(texName); setSize(width, height); setPosition(left, top); mIsVisible = true; if(!mIsInitialised) { mRenderData.vertexData = TITAN_NEW VertexData(); VertexDeclaration* decl = mRenderData.vertexData->vertexDecl; decl->addElement(0,0, VET_FLOAT3, VES_POSITION); mRenderData.vertexData->vertexStart = 0; mRenderData.vertexData->vertexCount = 4; VertexBufferPtr vbuf = HardwareBufferMgr::getSingletonPtr()->createVertexBuffer(decl->getVertexSize(0), mRenderData.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); mRenderData.vertexData->vertexBufferBinding->setBinding(0, vbuf); mRenderData.useIndex = false; mRenderData.operationType = OT_TRIANGLE_STRIP; mIsInitialised = true; } notifyGeometryOld(); }
//--------------------------------------------------------------------- void PanelOverlayElement::initialise(void) { bool init = !mInitialised; OverlayContainer::initialise(); if (init) { // Setup render op in advance mRenderOp.vertexData = OGRE_NEW VertexData(); // Vertex declaration: 1 position, add texcoords later depending on #layers // Create as separate buffers so we can lock & discard separately VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION); // Basic vertex data mRenderOp.vertexData->vertexStart = 0; mRenderOp.vertexData->vertexCount = 4; // Vertex buffer #1 HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(POSITION_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY// mostly static except during resizing ); // Bind buffer mRenderOp.vertexData->vertexBufferBinding->setBinding(POSITION_BINDING, vbuf); // No indexes & issue as a strip mRenderOp.useIndexes = false; mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP; mInitialised = true; } }
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 OverlayPanelElement::updateTexData() { if(!mTexture.isNull() &&mIsInitialised) { VertexDeclaration* decl = mRenderData.vertexData->vertexDecl; if(mTexCoordNum == 0) { decl->addElement(1, 0,VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); VertexBufferPtr vbuf = HardwareBufferMgr::getSingletonPtr()->createVertexBuffer(decl->getVertexSize(1), mRenderData.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); mRenderData.vertexData->vertexBufferBinding->setBinding(1,vbuf); mTexCoordNum = 1; } if(mTexCoordNum) { VertexBufferPtr buf = mRenderData.vertexData->vertexBufferBinding->getBuffer(1); float* pVBStart = static_cast<float*>(buf->lock(HardwareBuffer::HBL_DISCARD)); size_t uvSize = VertexElement::getTypeSize(VET_FLOAT2) / sizeof(float); size_t vertexSize = decl->getVertexSize(1) / sizeof(float); float* pTex = pVBStart; pTex[0] = mU1; pTex[1] = mV1; pTex += vertexSize; pTex[0] = mU1; pTex[1] = mV2; pTex += vertexSize; pTex[0] = mU2; pTex[1] = mV1; pTex += vertexSize; pTex[0] = mU2; pTex[1] = mV2; buf->unlock(); } } }
void TextAreaOverlayElement::checkMemoryAllocation( size_t numChars ) { if( mAllocSize < numChars) { // Create and bind new buffers // Note that old buffers will be deleted automatically through reference counting // 6 verts per char since we're doing tri lists without indexes // Allocate space for positions & texture coords VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; mRenderOp.vertexData->vertexCount = numChars * 6; // Create dynamic since text tends to change a lot // positions & texcoords HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer( decl->getVertexSize(POS_TEX_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); bind->setBinding(POS_TEX_BINDING, vbuf); // colours vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer( decl->getVertexSize(COLOUR_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); bind->setBinding(COLOUR_BINDING, vbuf); mAllocSize = numChars; mColoursChanged = true; // force colour buffer regeneration } }
DebugRectangle2D::DebugRectangle2D() : SimpleRenderable () { #ifdef PLSM2_EIHORT mUseIdentityProjection = true; mUseIdentityView = true; #endif mRenderOp.indexData = new IndexData(); mRenderOp.vertexData = new VertexData(); mRenderOp.operationType = RenderOperation::OT_LINE_LIST; mRenderOp.indexData->indexCount = 8; mRenderOp.vertexData->vertexCount = 4; mRenderOp.vertexData->vertexStart = 0; mRenderOp.useIndexes = true; VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION); const size_t offset = VertexElement::getTypeSize(VET_FLOAT3); decl->addElement (POSITION_BINDING, offset, VET_COLOUR, VES_DIFFUSE); mRenderOp.indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, mRenderOp.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(POSITION_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Bind buffer bind->setBinding(POSITION_BINDING, vbuf); SimpleRenderable::setBoundingBox(AxisAlignedBox(-1000 * Vector3::UNIT_SCALE, 1000 * Vector3::UNIT_SCALE)); SimpleRenderable::setRenderQueueGroup (RENDER_QUEUE_OVERLAY); // set basic white material SimpleRenderable::setMaterial("BaseWhiteNoLighting"); }
//--------------------------------------------------------------------- void PanelOverlayElement::_restoreManualHardwareResources() { if(!mInitialised) return; VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; // Vertex buffer #1 HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(POSITION_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY// mostly static except during resizing ); // Bind buffer mRenderOp.vertexData->vertexBufferBinding->setBinding(POSITION_BINDING, vbuf); // Buffers are restored, but with trash within mGeomPositionsOutOfDate = true; mGeomUVsOutOfDate = true; }
void EffectBillboardChain::_createBuffer(void) { if (mRenderOp.vertexData) { delete mRenderOp.vertexData; mRenderOp.vertexData = NULL; } mRenderOp.vertexData = new VertexData(); mRenderOp.indexData = NULL; mRenderOp.vertexData->vertexCount = mCurrentNbChainElements * 2; mRenderOp.vertexData->vertexStart = 0; mRenderOp.operationType = RenderOperation::OT_TRIANGLE_STRIP; mRenderOp.useIndexes = false; VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; // Add a description for the buffer of the positions of the vertices size_t offset = 0; decl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); decl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE); offset += VertexElement::getTypeSize(VET_COLOUR); decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES); offset += VertexElement::getTypeSize(VET_FLOAT2); // Create the buffer HardwareVertexBufferSharedPtr pVertexBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(0), mCurrentNbChainElements * 2, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // Bind the buffer bind->setBinding(0, pVertexBuffer); }
void createSphere(const std::string& strName, const float r, const int nRings = 16, const int nSegments = 16) { MeshPtr pSphere = MeshManager::getSingleton().createManual(strName, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *pSphereVertex = pSphere->createSubMesh(); pSphere->sharedVertexData = new VertexData(); VertexData* vertexData = pSphere->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); currOffset += VertexElement::getTypeSize(VET_FLOAT2); // allocate the vertex buffer vertexData->vertexCount = (nRings + 1) * (nSegments + 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 * nRings * (nSegments + 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 / nRings); float fDeltaSegAngle = (2 * Math::PI / nSegments); unsigned short wVerticeIndex = 0; // Generate the group of rings for the sphere for (int ring = 0; ring <= nRings; ring++) { float r0 = r * sinf(ring * fDeltaRingAngle); float y0 = r * cosf(ring * fDeltaRingAngle); // Generate the group of segments for the current ring for (int seg = 0; seg <= nSegments; 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)nSegments; *pVertex++ = (float)ring / (float)nRings; if (ring != nRings) { // each vertex (except the last) has six indices pointing to it *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex; *pIndices++ = wVerticeIndex + nSegments; *pIndices++ = wVerticeIndex + nSegments + 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: pSphere->_setBounds(AxisAlignedBox(Vector3(-r, -r, -r), Vector3(r, r, r)), false); pSphere->_setBoundingSphereRadius(r); // this line makes clear the mesh is loaded (avoids memory leaks) pSphere->load(); }
void MovableText::_setupGeometry() { assert(mpFont); assert(!mpMaterial.isNull()); unsigned int vertexCount = static_cast<unsigned int>(mCaption.size() * 6); if (mRenderOp.vertexData) { // Removed this test as it causes problems when replacing a caption // of the same size: replacing "Hello" with "hello" // as well as when changing the text alignment //if (mRenderOp.vertexData->vertexCount != vertexCount) { delete mRenderOp.vertexData; mRenderOp.vertexData = NULL; mUpdateColors = true; } } 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); size_t charlen = mCaption.size(); float *pPCBuff = static_cast<float*>(ptbuf->lock(HardwareBuffer::HBL_DISCARD)); float largestWidth = 0; float left = 0 * 2.0 - 1.0; float top = -((0 * 2.0) - 1.0); Real spaceWidth = mSpaceWidth; // Derive space width from a capital A if (spaceWidth == 0) spaceWidth = mpFont->getGlyphAspectRatio('A') * mCharHeight * 2.0; // for calculation of AABB Ogre::Vector3 min, max, currPos; Ogre::Real maxSquaredRadius; bool first = true; // Use iterator String::iterator i, iend; iend = mCaption.end(); bool newLine = true; Real len = 0.0f; Real verticalOffset = 0; switch (mVerticalAlignment) { case MovableText::V_ABOVE: verticalOffset = mCharHeight; break; case MovableText::V_CENTER: verticalOffset = 0.5*mCharHeight; break; case MovableText::V_BELOW: verticalOffset = 0; break; } // Raise the first line of the caption top += verticalOffset; for (i = mCaption.begin(); i != iend; ++i) { if (*i == '\n') top += verticalOffset * 2.0; } 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((unsigned char)*j) * mCharHeight * 2.0; } newLine = false; } if (*i == '\n') { left = 0 * 2.0 - 1.0; top -= mCharHeight * 2.0; newLine = true; // Bugfix by Wladimir Lukutin - thanks :) // Also reduce tri count mRenderOp.vertexData->vertexCount -= 6; // Bugfix end. continue; } if (*i == ' ') { // Just leave a gap, no tris left += spaceWidth; // Also reduce tri count mRenderOp.vertexData->vertexCount -= 6; continue; } Real horiz_height = mpFont->getGlyphAspectRatio((unsigned char)*i); Real u1, u2, v1, v2; Ogre::Font::UVRect utmp; utmp = mpFont->getGlyphTexCoords((unsigned char)*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 if(mHorizontalAlignment == MovableText::H_LEFT) *pPCBuff++ = left; else *pPCBuff++ = left - (len / 2); *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u1; *pPCBuff++ = v1; // Deal with bounds if(mHorizontalAlignment == MovableText::H_LEFT) currPos = Ogre::Vector3(left, top, -1.0); else currPos = Ogre::Vector3(left - (len / 2), top, -1.0); if (first) { min = max = currPos; maxSquaredRadius = currPos.squaredLength(); first = false; } else { min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); } top -= mCharHeight * 2.0; // Bottom left if(mHorizontalAlignment == MovableText::H_LEFT) *pPCBuff++ = left; else *pPCBuff++ = left - (len / 2); *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u1; *pPCBuff++ = v2; // Deal with bounds if(mHorizontalAlignment == MovableText::H_LEFT) currPos = Ogre::Vector3(left, top, -1.0); else currPos = Ogre::Vector3(left - (len / 2), top, -1.0); min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); top += mCharHeight * 2.0; left += horiz_height * mCharHeight * 2.0; // Top right if(mHorizontalAlignment == MovableText::H_LEFT) *pPCBuff++ = left; else *pPCBuff++ = left - (len / 2); *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u2; *pPCBuff++ = v1; //------------------------------------------------------------------------------------- // Deal with bounds if(mHorizontalAlignment == MovableText::H_LEFT) currPos = Ogre::Vector3(left, top, -1.0); else currPos = Ogre::Vector3(left - (len / 2), top, -1.0); min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); //------------------------------------------------------------------------------------- // Second tri // // Top right (again) if(mHorizontalAlignment == MovableText::H_LEFT) *pPCBuff++ = left; else *pPCBuff++ = left - (len / 2); *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u2; *pPCBuff++ = v1; currPos = Ogre::Vector3(left, top, -1.0); 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) if(mHorizontalAlignment == MovableText::H_LEFT) *pPCBuff++ = left; else *pPCBuff++ = left - (len / 2); *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u1; *pPCBuff++ = v2; currPos = Ogre::Vector3(left, top, -1.0); min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); left += horiz_height * mCharHeight * 2.0; // Bottom right if(mHorizontalAlignment == MovableText::H_LEFT) *pPCBuff++ = left; else *pPCBuff++ = left - (len / 2); *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u2; *pPCBuff++ = v2; //------------------------------------------------------------------------------------- currPos = Ogre::Vector3(left, top, -1.0); 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; }
size_t MeshBuilder::generateBuffers(RenderOperation &operation) { // Early out if nothing to do. if (mIndices.size() == 0) { return 0; } // Prepare vertex buffer operation.operationType = RenderOperation::OT_TRIANGLE_LIST; operation.vertexData = OGRE_NEW VertexData(); operation.vertexData->vertexCount = mVertices.size(); operation.vertexData->vertexStart = 0; VertexDeclaration *decl = operation.vertexData->vertexDeclaration; VertexBufferBinding *bind = operation.vertexData->vertexBufferBinding; size_t offset = 0; // Add vertex-positions to the buffer decl->addElement(0, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); // Add vertex-normals to the buffer decl->addElement(0, offset, VET_FLOAT3, VES_NORMAL); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(MAIN_BINDING), operation.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); bind->setBinding(0, vbuf); float* vertices = static_cast<float*>(vbuf->lock(HardwareBuffer::HBL_DISCARD)); VecVertex::const_iterator endVertices = mVertices.end(); for (VecVertex::const_iterator iter = mVertices.begin(); iter != endVertices; ++iter) { *vertices++ = (float)iter->x; *vertices++ = (float)iter->y; *vertices++ = (float)iter->z; *vertices++ = (float)iter->nX; *vertices++ = (float)iter->nY; *vertices++ = (float)iter->nZ; } vbuf->unlock(); // Get Indexarray operation.indexData = OGRE_NEW IndexData(); operation.indexData->indexCount = mIndices.size(); operation.indexData->indexStart = 0; VecIndices::const_iterator endIndices = mIndices.end(); if (operation.indexData->indexCount > USHRT_MAX) { operation.indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_32BIT, operation.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); unsigned int* indices = static_cast<unsigned int*>( operation.indexData->indexBuffer->lock(0, operation.indexData->indexBuffer->getSizeInBytes(), HardwareBuffer::HBL_DISCARD)); for (VecIndices::const_iterator iter = mIndices.begin(); iter != endIndices; ++iter) { *indices++ = *iter; } } else { operation.indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, operation.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); unsigned short* indices = static_cast<unsigned short*>( operation.indexData->indexBuffer->lock(0, operation.indexData->indexBuffer->getSizeInBytes(), HardwareBuffer::HBL_DISCARD)); for (VecIndices::const_iterator iter = mIndices.begin(); iter != endIndices; ++iter) { *indices++ = (unsigned short)*iter; } } operation.indexData->indexBuffer->unlock(); return mIndices.size() / 3; }
bool ShaderParticleRenderer::allocateBuffers(size_t iNumParticles) { // prepare vertex declaration if (mVertexData->vertexDeclaration->getElementCount() == 0) { VertexDeclaration* pDecl = mVertexData->vertexDeclaration; size_t ofs = 0; ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_POSITION).getSize(); // position if (mVertexFormatColour) ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_DIFFUSE).getSize(); // diffuse colour // other data are stored in vertex as texture coordinates ushort ix = 0; if (mVertexFormatTexture) ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // general texture coord if (mVertexFormatSize) ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // particle size if (mVertexFormatRotation || mVertexFormatRotationSpeed) { if (mVertexFormatRotation && mVertexFormatRotationSpeed) ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); // current rotation and rotation speed else ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++).getSize(); // current rotation or rotation speed } if (mVertexFormatDirection) ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++).getSize(); // particle direction (as speed) // add packed times size_t iNumTimes = 0; if (mVertexFormatTTL) iNumTimes++; if (mVertexFormatTotalTTL) iNumTimes++; if (mVertexFormatTimeFragment) iNumTimes++; if (mVertexFormatTimeFragmentInv) iNumTimes++; switch(iNumTimes) { case 1: ofs += pDecl->addElement(0, ofs, VET_FLOAT1, VES_TEXTURE_COORDINATES, ix++).getSize(); break; case 2: ofs += pDecl->addElement(0, ofs, VET_FLOAT2, VES_TEXTURE_COORDINATES, ix++).getSize(); break; case 3: ofs += pDecl->addElement(0, ofs, VET_FLOAT3, VES_TEXTURE_COORDINATES, ix++).getSize(); break; case 4: ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize(); break; } // add custom parameters ofs += pDecl->addElement(0, ofs, VET_FLOAT4, VES_TEXTURE_COORDINATES, ix++).getSize(); assert(ix <= 8); // cache vertex size mVertexSize = pDecl->getVertexSize(0); } Ogre::HardwareVertexBufferSharedPtr pVB; if (mVertexData->vertexBufferBinding->isBufferBound(0)) pVB = mVertexData->vertexBufferBinding->getBuffer(0); // prepare vertex buffer if (pVB.isNull() || pVB->getNumVertices() < iNumParticles * 4) { assert(iNumParticles * 4 < 65536); // we are using 16bit index buffer pVB = Ogre::HardwareBufferManager::getSingleton().createVertexBuffer(mVertexSize, 4 * iNumParticles, Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE); if (pVB.isNull()) return false; mVertexData->vertexBufferBinding->setBinding(0, pVB); } // prepare index buffer Ogre::HardwareIndexBufferSharedPtr pIB = mIndexData->indexBuffer; if (pIB.isNull() || pIB->getNumIndexes() < iNumParticles * 6) { pIB = Ogre::HardwareBufferManager::getSingleton().createIndexBuffer(Ogre::HardwareIndexBuffer::IT_16BIT, iNumParticles * 6, Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY); if (pIB.isNull()) return false; mIndexData->indexBuffer = pIB; // fill Ogre::uint16* pDataIB = reinterpret_cast<Ogre::uint16*>(pIB->lock(Ogre::HardwareBuffer::HBL_NORMAL)); for (Ogre::uint16 k=0; k<static_cast<Ogre::uint16>(iNumParticles); ++k) { pDataIB[0] = k*4 + 0; pDataIB[1] = k*4 + 1; pDataIB[2] = k*4 + 2; pDataIB[3] = k*4 + 0; pDataIB[4] = k*4 + 2; pDataIB[5] = k*4 + 3; pDataIB += 6; } pIB->unlock(); } return true; }
//----------------------------------------------------------------------------------- void Rectangle2D::initRectangle2D(void) { // use identity projection and view matrices mUseIdentityProjection = true; mUseIdentityView = true; mRenderOp.vertexData = OGRE_NEW VertexData(); mRenderOp.indexData = 0; mRenderOp.vertexData->vertexCount = mQuad ? 4 : 3; mRenderOp.vertexData->vertexStart = 0; //Strip or list is fine for triangle, but using lists avoids tiny unnecessary state //switches (assuming most of normal render is indexed list). mRenderOp.operationType = mQuad ? RenderOperation::OT_TRIANGLE_STRIP : RenderOperation::OT_TRIANGLE_LIST; mRenderOp.useIndexes = false; mRenderOp.useGlobalInstancingVertexBufferIsAvailable = false; VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; size_t offset = 0; decl->addElement( 0, 0, VET_FLOAT3, VES_POSITION ); offset += VertexElement::getTypeSize( VET_FLOAT3 ); decl->addElement( 0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES ); HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize( 0 ), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY ); // Bind buffer bind->setBinding( 0, vbuf ); float *pVerts = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); if( mQuad ) { //1st Top-left *pVerts++ = -1.0f; *pVerts++ = 1.0f; *pVerts++ = -1.0f; *pVerts++ = 0.0f; *pVerts++ = 0.0f; //2nd Bottom-left *pVerts++ = -1.0f; *pVerts++ = -1.0f; *pVerts++ = -1.0f; *pVerts++ = 0.0f; *pVerts++ = 1.0f; //3rd Top-right *pVerts++ = 1.0f; *pVerts++ = 1.0f; *pVerts++ = -1.0f; *pVerts++ = 1.0f; *pVerts++ = 0.0f; //4th Bottom-right *pVerts++ = 1.0f; *pVerts++ = -1.0f; *pVerts++ = -1.0f; *pVerts++ = 1.0f; *pVerts++ = 1.0f; } else { //1st Top-left *pVerts++ = -1.0f; *pVerts++ = 1.0f; *pVerts++ = -1.0f; *pVerts++ = 0.0f; *pVerts++ = 0.0f; //2nd Bottom-left *pVerts++ = -1.0f; *pVerts++ = -3.0f; //3 = lerp( -1, 1, 2 ); *pVerts++ = -1.0f; *pVerts++ = 0.0f; *pVerts++ = 2.0f; //3rd Top-right *pVerts++ = 3.0f; *pVerts++ = 1.0f; *pVerts++ = -1.0f; *pVerts++ = 2.0f; *pVerts++ = 0.0f; } vbuf->unlock(); //Add the normals. decl->addElement( 1, 0, VET_FLOAT3, VES_NORMAL ); vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize( 1 ), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE ); bind->setBinding( 1, 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; if( mQuad ) { *pNorm++ = 0.0f; *pNorm++ = 0.0f; *pNorm++ = 1.0f; } vbuf->unlock(); // set basic white material this->setMaterial( "BaseWhiteNoLighting" ); }
void SplineRoad::CreateMesh(SubMesh* mesh, AxisAlignedBox& aabox, const std::vector<Vector3>& pos, const std::vector<Vector3>& norm, const std::vector<Vector4>& clr, const std::vector<Vector2>& tcs, const std::vector<Ogre::uint16>& idx, String sMtrName) { size_t i, si = pos.size(); if (si == 0) { LogO("Error!! CreateMesh 0 verts !"); return; } mesh->useSharedVertices = false; mesh->vertexData = new VertexData(); mesh->vertexData->vertexStart = 0; mesh->vertexData->vertexCount = si; // decl VertexDeclaration* decl = mesh->vertexData->vertexDeclaration; size_t offset = 0; offset += decl->addElement(0,offset,VET_FLOAT3,VES_POSITION).getSize(); offset += decl->addElement(0,offset,VET_FLOAT3,VES_NORMAL).getSize(); offset += decl->addElement(0,offset,VET_FLOAT2,VES_TEXTURE_COORDINATES).getSize(); if (clr.size() > 0) offset += decl->addElement(0,offset,VET_FLOAT4,VES_DIFFUSE).getSize(); // vertex //----------------------------------------- HardwareVertexBufferSharedPtr vbuffer = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(0), si, HardwareBuffer::HBU_STATIC); float* vp = static_cast<float*>(vbuffer->lock(HardwareBuffer::HBL_DISCARD)); // fill vb, update aabb if (clr.size() > 0) for (i=0; i < si; ++i) { const Vector3& p = pos[i]; *vp++ = p.x; *vp++ = p.y; *vp++ = p.z; aabox.merge(p); const Vector3& n = norm[i]; *vp++ = n.x; *vp++ = n.y; *vp++ = n.z; *vp++ = tcs[i].x; *vp++ = tcs[i].y; const Vector4& c = clr[i]; *vp++ = c.x; *vp++ = c.y; *vp++ = c.z; *vp++ = c.w; } else for (i=0; i < si; ++i) { const Vector3& p = pos[i]; *vp++ = p.x; *vp++ = p.y; *vp++ = p.z; aabox.merge(p); const Vector3& n = norm[i]; *vp++ = n.x; *vp++ = n.y; *vp++ = n.z; *vp++ = tcs[i].x; *vp++ = tcs[i].y; } vbuffer->unlock(); mesh->vertexData->vertexBufferBinding->setBinding(0,vbuffer); // index //----------------------------------------- IndexData* id = mesh->indexData; id->indexCount = idx.size(); id->indexStart = 0; id->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, id->indexCount, HardwareBuffer::HBU_STATIC); uint16* ip = static_cast<uint16*>(id->indexBuffer->lock(HardwareBuffer::HBL_DISCARD)); // fill ib for (size_t i=0; i < idx.size(); ++i) *ip++ = idx[i]; id->indexBuffer->unlock(); mesh->setMaterialName(sMtrName); }
//----------------------------------------------------------------------- void MeshManager::loadManualCurvedIllusionPlane(Mesh* pMesh, MeshBuildParams& params) { if (params.ySegmentsToKeep == -1) params.ySegmentsToKeep = params.ysegments; if ((params.xsegments + 1) * (params.ySegmentsToKeep + 1) > 65536) OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Plane tessellation is too high, must generate max 65536 vertices", __FUNCTION__); SubMesh *pSub = pMesh->createSubMesh(); // Set up vertex data // Use a single shared buffer pMesh->sharedVertexData = OGRE_NEW VertexData(); VertexData* vertexData = pMesh->sharedVertexData; // Set up Vertex Declaration VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // We always need positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // Optional normals if(params.normals) { vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); } for (unsigned short i = 0; i < params.numTexCoordSets; ++i) { // Assumes 2D texture coords vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, i); currOffset += VertexElement::getTypeSize(VET_FLOAT2); } vertexData->vertexCount = (params.xsegments + 1) * (params.ySegmentsToKeep + 1); // Allocate vertex buffer HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, params.vertexBufferUsage, params.vertexShadowBuffer); // Set up the binding (one source only) VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vbuf); // Work out the transform required // Default orientation of plane is normal along +z, distance 0 Matrix4 xlate, xform, rot; Matrix3 rot3; xlate = rot = Matrix4::IDENTITY; // Determine axes Vector3 zAxis, yAxis, xAxis; zAxis = params.plane.normal; zAxis.normalise(); yAxis = params.upVector; yAxis.normalise(); xAxis = yAxis.crossProduct(zAxis); if (xAxis.length() == 0) { //upVector must be wrong OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "The upVector you supplied is parallel to the plane normal, so is not valid.", "MeshManager::createPlane"); } rot3.FromAxes(xAxis, yAxis, zAxis); rot = rot3; // Set up standard transform from origin xlate.setTrans(params.plane.normal * -params.plane.d); // concatenate xform = xlate * rot; // Generate vertex data // Imagine a large sphere with the camera located near the top // The lower the curvature, the larger the sphere // Use the angle from viewer to the points on the plane // Credit to Aftershock for the general approach Real camPos; // Camera position relative to sphere center // Derive sphere radius Vector3 vertPos; // position relative to camera Real sphDist; // Distance from camera to sphere along box vertex vector // Vector3 camToSph; // camera position to sphere Real sphereRadius;// Sphere radius // Actual values irrelevant, it's the relation between sphere radius and camera position that's important const Real SPHERE_RAD = 100.0; const Real CAM_DIST = 5.0; sphereRadius = SPHERE_RAD - params.curvature; camPos = sphereRadius - CAM_DIST; // Lock the whole buffer float* pFloat = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); Real xSpace = params.width / params.xsegments; Real ySpace = params.height / params.ysegments; Real halfWidth = params.width / 2; Real halfHeight = params.height / 2; Vector3 vec, norm; Vector3 min = Vector3::ZERO, max = Vector3::UNIT_SCALE; Real maxSquaredLength = 0; bool firstTime = true; for (int y = params.ysegments - params.ySegmentsToKeep; y < params.ysegments + 1; ++y) { for (int x = 0; x < params.xsegments + 1; ++x) { // Work out centered on origin vec.x = (x * xSpace) - halfWidth; vec.y = (y * ySpace) - halfHeight; vec.z = 0.0f; // Transform by orientation and distance vec = xform.transformAffine(vec); // Assign to geometry *pFloat++ = vec.x; *pFloat++ = vec.y; *pFloat++ = vec.z; // Build bounds as we go if (firstTime) { min = vec; max = vec; maxSquaredLength = vec.squaredLength(); firstTime = false; } else { min.makeFloor(vec); max.makeCeil(vec); maxSquaredLength = std::max(maxSquaredLength, vec.squaredLength()); } if (params.normals) { // Default normal is along unit Z norm = Vector3::UNIT_Z; // Rotate norm = params.orientation * norm; *pFloat++ = norm.x; *pFloat++ = norm.y; *pFloat++ = norm.z; } // Generate texture coords // Normalise position // modify by orientation to return +y up vec = params.orientation.Inverse() * vec; vec.normalise(); // Find distance to sphere sphDist = Math::Sqrt(camPos*camPos * (vec.y*vec.y-1.0f) + sphereRadius*sphereRadius) - camPos*vec.y; vec.x *= sphDist; vec.z *= sphDist; // Use x and y on sphere as texture coordinates, tiled Real s = vec.x * (0.01f * params.xTile); Real t = 1.0f - (vec.z * (0.01f * params.yTile)); for (unsigned short i = 0; i < params.numTexCoordSets; ++i) { *pFloat++ = s; *pFloat++ = t; } } // x } // y // Unlock vbuf->unlock(); // Generate face list pSub->useSharedVertices = true; tesselate2DMesh(pSub, params.xsegments + 1, params.ySegmentsToKeep + 1, false, params.indexBufferUsage, params.indexShadowBuffer); pMesh->_setBounds(AxisAlignedBox(min, max), true); pMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredLength)); }
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(); }
// Generate normals for polygon meshes void IndexedGeometry::createIndexedFaceSet() { if (_coords.empty()) throw std::runtime_error("No coordinates given."); if (_coordIndex.empty()) throw std::runtime_error("No coordinate index given."); MeshPtr mesh = MeshManager::getSingleton().createManual(_name, ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME); SubMesh *sub = mesh->createSubMesh(); bool hasTextureCoordinates = !_texCoords.empty(); bool hasPointColors = !_colors.empty() && _colorPerVertex; bool hasPointNormals = !_normals.empty() && _normalPerVertex; bool hasCellColors = !_colors.empty() && !hasPointColors; bool hasCellNormals = !_normals.empty() && !hasPointNormals; bool calcPointNormals = _normals.empty() && _normalPerVertex; std::vector<face> faces; face f; for (std::vector<int>::const_iterator I=_coordIndex.begin(); I !=_coordIndex.end(); ++I) { if (*I == -1) { faces.resize(faces.size()+1); faces.back().indices.swap(f.indices); } else f.indices.push_back(I - _coordIndex.begin()); } if (!f.indices.empty()) { faces.resize(faces.size()+1); faces.back().indices.swap(f.indices); } std::vector<vertex> vertices; std::vector<triangle> triangles; VertMap vertexMap; // triangulate and expand vertices for (std::vector<face>::const_iterator f=faces.begin(), e=faces.end(); f!=e; ++f) { int faceNr = f - faces.begin(); int triVertNr = 0; int triVerts[2] = { -1, -1 }; for (std::vector<int>::const_iterator i = f->indices.begin(), e=f->indices.end(); i!=e; ++i, ++triVertNr) { int triVertNr = i - f->indices.begin(); int index = *i; vertex vert; // get full indices for vertex data vert.pos = _coordIndex[index]; vert.normal = !_normals.empty() ? getIndex(_coordIndex, _normalIndex, _normalPerVertex, faceNr, index) : 0; vert.colour = !_colors.empty() ? getIndex(_coordIndex, _colorIndex, _colorPerVertex, faceNr, index) : 0; vert.tc = hasTextureCoordinates ? getIndex(_coordIndex, _texCoordIndex, true, faceNr, index) : 0; // avoid duplication //int nvert = vertexMap.size(); //int &vpos = vertexMap[vert]; //if (nvert != vertexMap.size()) { int vpos = vertices.size(); vertices.push_back(vert); //} // emit triangle (maybe) if (triVertNr == 0) triVerts[0] = vpos; else if (triVertNr == 1) triVerts[1] = vpos; else { triangle t; t.vertices[0] = triVerts[0]; t.vertices[1] = triVerts[1]; t.vertices[2] = vpos; if (!_ccw) std::swap(t.vertices[1], t.vertices[2]); triangles.push_back(t); triVerts[1] = vpos; } } } // createOgreMesh int nvertices = vertices.size(); int nfaces = triangles.size(); VertexData* vertexData = new VertexData(); sub->vertexData = vertexData; IndexData* indexData = sub->indexData; VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); if (hasPointNormals) { // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); } // two dimensional texture coordinates if (hasTextureCoordinates) { vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); currOffset += VertexElement::getTypeSize(VET_FLOAT2); } std::cout << std::endl; // allocate index buffer indexData->indexCount = nfaces * 3; 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)); std::cout << triangles.size() << ": "; for(std::vector<triangle>::const_iterator T = triangles.begin(); T != triangles.end(); T++) { const triangle &t = (*T); *pIndices++ = t.vertices[0]; *pIndices++ = t.vertices[1]; *pIndices++ = t.vertices[2]; std::cout << t.vertices[0] << " " << t.vertices[1] << " " << t.vertices[2] << " "; } std::cout << std::endl; // allocate the vertex buffer vertexData->vertexCount = nvertices; 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)); AxisAlignedBox aabox; std::cout << vertices.size() << ": "; for(std::vector<vertex>::const_iterator V = vertices.begin(); V != vertices.end(); V++) { const vertex &v = (*V); SFVec3f pos = _coords.at(v.pos); *pVertex++ = pos.x; *pVertex++ = pos.y; *pVertex++ = pos.z; aabox.merge(Vector3(pos.x, pos.y, pos.z)); std::cout << pos.x << " " << pos.y << " " << pos.z << " " << std::endl; //std::cout << v.pos << " "; if (hasPointNormals) { const SFVec3f normal = _normals.at(v.normal); *pVertex++ = normal.x; *pVertex++ = normal.y; *pVertex++ = normal.z; } } std::cout << std::endl; // Unlock vBuf->unlock(); iBuf->unlock(); sub->useSharedVertices = false; // the original code was missing this line: mesh->_setBounds(aabox); mesh->_setBoundingSphereRadius((aabox.getMaximum()-aabox.getMinimum()).length()/2.0); // this line makes clear the mesh is loaded (avoids memory leaks) mesh->load(); }
void GeomUtils::createSphere(VertexData*& vertexData, IndexData*& indexData , float radius , int nRings, int nSegments , bool bNormals , bool bTexCoords) { assert(vertexData && indexData); // 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); if (bNormals) { // normals vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); } // two dimensional texture coordinates if (bTexCoords) { vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); } // allocate the vertex buffer vertexData->vertexCount = (nRings + 1) * (nSegments+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 indexData->indexCount = 6 * nRings * (nSegments + 1); 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)); float fDeltaRingAngle = (Math::PI / nRings); float fDeltaSegAngle = (2 * Math::PI / nSegments); unsigned short wVerticeIndex = 0 ; // Generate the group of rings for the sphere for( int ring = 0; ring <= nRings; ring++ ) { float r0 = radius * sinf (ring * fDeltaRingAngle); float y0 = radius * cosf (ring * fDeltaRingAngle); // Generate the group of segments for the current ring for(int seg = 0; seg <= nSegments; 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; if (bNormals) { Vector3 vNormal = Vector3(x0, y0, z0).normalisedCopy(); *pVertex++ = vNormal.x; *pVertex++ = vNormal.y; *pVertex++ = vNormal.z; } if (bTexCoords) { *pVertex++ = (float) seg / (float) nSegments; *pVertex++ = (float) ring / (float) nRings; } if (ring != nRings) { // each vertex (except the last) has six indices pointing to it *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex; *pIndices++ = wVerticeIndex + nSegments; *pIndices++ = wVerticeIndex + nSegments + 1; *pIndices++ = wVerticeIndex + 1; *pIndices++ = wVerticeIndex; wVerticeIndex ++; } }; // end for seg } // end for ring // Unlock vBuf->unlock(); iBuf->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 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; }
//--------------------------------------------------------------------- void BorderPanelOverlayElement::_restoreManualHardwareResources() { if(!mInitialised) return; PanelOverlayElement::_restoreManualHardwareResources(); // Vertex data VertexDeclaration* decl = mRenderOp2.vertexData->vertexDeclaration; // Vertex buffer #1, position HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(POSITION_BINDING), mRenderOp2.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // bind position VertexBufferBinding* binding = mRenderOp2.vertexData->vertexBufferBinding; binding->setBinding(POSITION_BINDING, vbuf); // Vertex buffer #2, texcoords vbuf = HardwareBufferManager::getSingleton().createVertexBuffer( decl->getVertexSize(TEXCOORD_BINDING), mRenderOp2.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); // bind texcoord binding->setBinding(TEXCOORD_BINDING, vbuf); // Index data /* Each cell is 0-----2 | /| | / | |/ | 1-----3 */ mRenderOp2.indexData->indexBuffer = HardwareBufferManager::getSingleton().createIndexBuffer( HardwareIndexBuffer::IT_16BIT, mRenderOp2.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); ushort* pIdx = static_cast<ushort*>( mRenderOp2.indexData->indexBuffer->lock( 0, mRenderOp2.indexData->indexBuffer->getSizeInBytes(), HardwareBuffer::HBL_DISCARD) ); for (ushort cell = 0; cell < 8; ++cell) { ushort base = cell * 4; *pIdx++ = base; *pIdx++ = base + 1; *pIdx++ = base + 2; *pIdx++ = base + 2; *pIdx++ = base + 1; *pIdx++ = base + 3; } mRenderOp2.indexData->indexBuffer->unlock(); }
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 BorderPanelOverlayElement::initialise(void) { bool init = !mInitialised; PanelOverlayElement::initialise(); // superclass will handle the interior panel area if (init) { // Setup render op in advance mRenderOp2.vertexData = OGRE_NEW VertexData(); mRenderOp2.vertexData->vertexCount = 4 * 8; // 8 cells, can't necessarily share vertices cos // texcoords may differ mRenderOp2.vertexData->vertexStart = 0; // Vertex declaration VertexDeclaration* decl = mRenderOp2.vertexData->vertexDeclaration; // Position and texture coords each have their own buffers to allow // each to be edited separately with the discard flag decl->addElement(POSITION_BINDING, 0, VET_FLOAT3, VES_POSITION); decl->addElement(TEXCOORD_BINDING, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); // Vertex buffer #1, position HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton() .createVertexBuffer( decl->getVertexSize(POSITION_BINDING), mRenderOp2.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); // bind position VertexBufferBinding* binding = mRenderOp2.vertexData->vertexBufferBinding; binding->setBinding(POSITION_BINDING, vbuf); // Vertex buffer #2, texcoords vbuf = HardwareBufferManager::getSingleton() .createVertexBuffer( decl->getVertexSize(TEXCOORD_BINDING), mRenderOp2.vertexData->vertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, true); // bind texcoord binding->setBinding(TEXCOORD_BINDING, vbuf); mRenderOp2.operationType = RenderOperation::OT_TRIANGLE_LIST; mRenderOp2.useIndexes = true; // Index data mRenderOp2.indexData = OGRE_NEW IndexData(); mRenderOp2.indexData->indexCount = 8 * 6; mRenderOp2.indexData->indexStart = 0; mRenderOp2.useGlobalInstancingVertexBufferIsAvailable = false; /* Each cell is 0-----2 | /| | / | |/ | 1-----3 */ mRenderOp2.indexData->indexBuffer = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, mRenderOp2.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); ushort* pIdx = static_cast<ushort*>( mRenderOp2.indexData->indexBuffer->lock( 0, mRenderOp2.indexData->indexBuffer->getSizeInBytes(), HardwareBuffer::HBL_DISCARD) ); for (ushort cell = 0; cell < 8; ++cell) { ushort base = cell * 4; *pIdx++ = base; *pIdx++ = base + 1; *pIdx++ = base + 2; *pIdx++ = base + 2; *pIdx++ = base + 1; *pIdx++ = base + 3; } mRenderOp2.indexData->indexBuffer->unlock(); // Create sub-object for rendering border mBorderRenderable = OGRE_NEW BorderRenderable(this); mInitialised = true; } }
//--------------------------------------------------------------------- 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 MovableText::_setupGeometry() { RlAssert1(mFont); RlAssert1(!mMaterial.isNull()); unsigned int vertexCount = mCaption.size() * 6; if (mRenderOp.vertexData) { if (mRenderOp.vertexData->vertexCount != vertexCount) { delete mRenderOp.vertexData; mRenderOp.vertexData = NULL; mUpdateColours = true; } } 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, VET_FLOAT2, 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); size_t charlen = mCaption.size(); Real *pPCBuff = static_cast<Real*>(ptbuf->lock(HardwareBuffer::HBL_DISCARD)); float largestWidth = 0; float left = 0 * 2.0 - 1.0; float top = -((0 * 2.0) - 1.0); // Derive space width from a capital A if (mSpaceWidth == 0) { mSpaceWidth = mFont->getGlyphAspectRatio('A') * mCharHeight * 2.0; } // for calculation of AABB Ogre::Vector3 min, max, currPos; Ogre::Real maxSquaredRadius; bool first = true; // Use iterator String::iterator i, iend; iend = mCaption.end(); bool newLine = true; for (i = mCaption.begin(); i != iend; ++i) { if (newLine) { Real len = 0.0f; for (String::iterator j = i; j != iend && *j != '\n'; j++) { if (*j == ' ') len += mSpaceWidth; else len += mFont->getGlyphAspectRatio(*j) * mCharHeight * 2.0; } newLine = false; } if (*i == '\n') { left = 0 * 2.0 - 1.0; top -= mCharHeight * 2.0; newLine = true; continue; } if (*i == ' ') { // Just leave a gap, no tris left += mSpaceWidth; // Also reduce tri count mRenderOp.vertexData->vertexCount -= 6; continue; } Real horiz_height = mFont->getGlyphAspectRatio(*i); Real u1, u2, v1, v2; mFont->getGlyphTexCoords(*i, u1, v1, u2, v2); // each vert is (x, y, z, u, v) //--------------------------------------------------------------- // First tri // // Upper left *pPCBuff++ = left; *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u1; *pPCBuff++ = v1; // Deal with bounds currPos = Ogre::Vector3(left, top, -1.0); if (first) { min = max = currPos; maxSquaredRadius = currPos.squaredLength(); first = false; } else { min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); } top -= mCharHeight * 2.0; // Bottom left *pPCBuff++ = left; *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u1; *pPCBuff++ = v2; // Deal with bounds currPos = Ogre::Vector3(left, top, -1.0); min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); top += mCharHeight * 2.0; left += horiz_height * mCharHeight * 2.0; // Top right *pPCBuff++ = left; *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u2; *pPCBuff++ = v1; //--------------------------------------------------------------- // Deal with bounds currPos = Ogre::Vector3(left, top, -1.0); min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); //--------------------------------------------------------------- // Second tri // // Top right (again) *pPCBuff++ = left; *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u2; *pPCBuff++ = v1; currPos = Ogre::Vector3(left, top, -1.0); 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) *pPCBuff++ = left; *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u1; *pPCBuff++ = v2; currPos = Ogre::Vector3(left, top, -1.0); min.makeFloor(currPos); max.makeCeil(currPos); maxSquaredRadius = std::max(maxSquaredRadius, currPos.squaredLength()); left += horiz_height * mCharHeight * 2.0; // Bottom right *pPCBuff++ = left; *pPCBuff++ = top; *pPCBuff++ = -1.0; *pPCBuff++ = u2; *pPCBuff++ = v2; //--------------------------------------------------------------- currPos = Ogre::Vector3(left, top, -1.0); 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 (mUpdateColours) { this->_updateColours(); } mNeedUpdate = false; }
/* ******************************************************************************* | 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 MeshManager::loadManualPlane(Mesh* pMesh, MeshBuildParams& params) { if ((params.xsegments + 1) * (params.ysegments + 1) > 65536) OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Plane tessellation is too high, must generate max 65536 vertices", __FUNCTION__); SubMesh *pSub = pMesh->createSubMesh(); // Set up vertex data // Use a single shared buffer pMesh->sharedVertexData = OGRE_NEW VertexData(); VertexData* vertexData = pMesh->sharedVertexData; // Set up Vertex Declaration VertexDeclaration* vertexDecl = vertexData->vertexDeclaration; size_t currOffset = 0; // We always need positions vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_POSITION); currOffset += VertexElement::getTypeSize(VET_FLOAT3); // Optional normals if(params.normals) { vertexDecl->addElement(0, currOffset, VET_FLOAT3, VES_NORMAL); currOffset += VertexElement::getTypeSize(VET_FLOAT3); } for (unsigned short i = 0; i < params.numTexCoordSets; ++i) { // Assumes 2D texture coords vertexDecl->addElement(0, currOffset, VET_FLOAT2, VES_TEXTURE_COORDINATES, i); currOffset += VertexElement::getTypeSize(VET_FLOAT2); } vertexData->vertexCount = (params.xsegments + 1) * (params.ysegments + 1); // Allocate vertex buffer HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer(vertexDecl->getVertexSize(0), vertexData->vertexCount, params.vertexBufferUsage, params.vertexShadowBuffer); // Set up the binding (one source only) VertexBufferBinding* binding = vertexData->vertexBufferBinding; binding->setBinding(0, vbuf); // Work out the transform required // Default orientation of plane is normal along +z, distance 0 Matrix4 xlate, xform, rot; Matrix3 rot3; xlate = rot = Matrix4::IDENTITY; // Determine axes Vector3 zAxis, yAxis, xAxis; zAxis = params.plane.normal; zAxis.normalise(); yAxis = params.upVector; yAxis.normalise(); xAxis = yAxis.crossProduct(zAxis); if (xAxis.length() == 0) { //upVector must be wrong OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "The upVector you supplied is parallel to the plane normal, so is not valid.", "MeshManager::createPlane"); } rot3.FromAxes(xAxis, yAxis, zAxis); rot = rot3; // Set up standard transform from origin xlate.setTrans(params.plane.normal * -params.plane.d); // concatenate xform = xlate * rot; // Generate vertex data // Lock the whole buffer float* pReal = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); Real xSpace = params.width / params.xsegments; Real ySpace = params.height / params.ysegments; Real halfWidth = params.width / 2; Real halfHeight = params.height / 2; Real xTex = (1.0f * params.xTile) / params.xsegments; Real yTex = (1.0f * params.yTile) / params.ysegments; Vector3 vec; Vector3 min = Vector3::ZERO, max = Vector3::UNIT_SCALE; Real maxSquaredLength = 0; bool firstTime = true; for (int y = 0; y < params.ysegments + 1; ++y) { for (int x = 0; x < params.xsegments + 1; ++x) { // Work out centered on origin vec.x = (x * xSpace) - halfWidth; vec.y = (y * ySpace) - halfHeight; vec.z = 0.0f; // Transform by orientation and distance vec = xform.transformAffine(vec); // Assign to geometry *pReal++ = vec.x; *pReal++ = vec.y; *pReal++ = vec.z; // Build bounds as we go if (firstTime) { min = vec; max = vec; maxSquaredLength = vec.squaredLength(); firstTime = false; } else { min.makeFloor(vec); max.makeCeil(vec); maxSquaredLength = std::max(maxSquaredLength, vec.squaredLength()); } if (params.normals) { // Default normal is along unit Z vec = Vector3::UNIT_Z; // Rotate vec = rot.transformAffine(vec); *pReal++ = vec.x; *pReal++ = vec.y; *pReal++ = vec.z; } for (unsigned short i = 0; i < params.numTexCoordSets; ++i) { *pReal++ = x * xTex; *pReal++ = 1 - (y * yTex); } } // x } // y // Unlock vbuf->unlock(); // Generate face list pSub->useSharedVertices = true; tesselate2DMesh(pSub, params.xsegments + 1, params.ysegments + 1, false, params.indexBufferUsage, params.indexShadowBuffer); pMesh->_setBounds(AxisAlignedBox(min, max), true); pMesh->_setBoundingSphereRadius(Math::Sqrt(maxSquaredLength)); }