//---------------------------------------------------------------------
    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;
    }
Exemple #2
0
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;
		}
    }
Exemple #6
0
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);
   }
Exemple #12
0
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;
}
Exemple #16
0
    //-----------------------------------------------------------------------------------
    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));
    }
Exemple #19
0
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();

}
Exemple #21
0
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();
    }
Exemple #25
0
	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));
    }