OGRE Wiki
Support and community documentation for Ogre3D
Ogre Forums
ogre3d.org
Log in
Username:
Password:
CapsLock is on.
Remember me (for 1 year)
Log in
Home
Tutorials
Tutorials Home
Basic Tutorials
Intermediate Tutorials
Mad Marx Tutorials
In Depth Tutorials
Older Tutorials
External Tutorials
Cookbook
Cookbook Home
CodeBank
Snippets
Experiences
Ogre Articles
Libraries
Libraries Home
Alternative Languages
Assembling A Toolset
Development Tools
OGRE Libraries
List of Libraries
Tools
Tools Home
DCC Tools
DCC Tutorials
DCC Articles
DCC Resources
Assembling a production pipeline
Development
Development Home
Roadmap
Building Ogre
Installing the Ogre SDK
Setting Up An Application
Ogre Wiki Tutorial Framework
Frequently Asked Questions
Google Summer Of Code
Help Requested
Ogre Core Articles
Community
Community Home
Projects Using Ogre
Recommended Reading
Contractors
Wiki
Immediate Wiki Tasklist
Wiki Ideas
Wiki Guidelines
Article Writing Guidelines
Wiki Styles
Wiki Page Tracker
Ogre Wiki Help
Ogre Wiki Help Overview
Help - Basic Syntax
Help - Images
Help - Pages and Structures
Help - Wiki Plugins
Toolbox
Freetags
Categories
List Pages
Structures
Trackers
Statistics
Rankings
List Galleries
Ogre Lexicon
Comments
History: PieSliceOverlay
View page
Source of version: 4
(current)
__Note:__ This code is hack of OgreBorderPanelOverlayElement and the OgreTextAreaOverlayElement. As such it may contain unnecessary code from these or may lack code which ogre needs. Use with caution! Also uses a lot of trigonometry functions so probably not the fastest method. {maketoc} !PieSliceOverlayElement !!PieSliceOverlayElement.h {CODE(wrap="1", colors="c++")}#ifndef _PieSliceOverlayElement_H__ #define _PieSliceOverlayElement_H__ #include "OgreOverlayElement.h" #include "OgreOverlayElementFactory.h" #include "OgreFont.h" namespace Ogre { class _OgreExport PieSliceOverlayElement : public OverlayElement { public: /** Constructor. */ PieSliceOverlayElement(const String& name); virtual ~PieSliceOverlayElement(); virtual void initialise(void); void setStartAngle( Real angle ); Real getStartAngle() const; void setEndAngle( Real angle ); Real getEndAngle() const; /** See OverlayElement. */ virtual const String& getTypeName(void) const; /** See Renderable. */ void getRenderOperation(RenderOperation& op); /** Overridden from OverlayElement */ void setMaterialName(const String& matName); /** Overridden from OverlayElement */ void setMetricsMode(GuiMetricsMode gmm); /** Overridden from OverlayElement */ void _update(void); //----------------------------------------------------------------------------------------- /** Command object for setting the Start Angle. @see ParamCommand */ class CmdStartAngle : public ParamCommand { public: String doGet( const void* target ) const; void doSet( void* target, const String& val ); }; //----------------------------------------------------------------------------------------- /** Command object for setting the End Angle. @see ParamCommand */ class CmdEndAngle : public ParamCommand { public: String doGet( const void* target ) const; void doSet( void* target, const String& val ); }; protected: /// Flag indicating if this panel should be visual or just group things bool mTransparent; /// Render operation RenderOperation mRenderOp; /// Method for setting up base parameters for this class void addBaseParameters(void); static String msTypeName; static CmdStartAngle msCmdStartAngle; static CmdEndAngle msCmdEndAngle; /// Pie Slice angles Real mStartAngle; Real mEndAngle; /// Inherited function virtual void updatePositionGeometry(); /// Inherited function virtual void updateTextureGeometry(); }; /** Factory for creating PieSliceOverlayElement instances. */ class _OgreExport PieSliceOverlayElementFactory: public OverlayElementFactory { public: /** See OverlayElementFactory */ OverlayElement* createOverlayElement(const String& instanceName) { return new PieSliceOverlayElement(instanceName); } /** See OverlayElementFactory */ const String& getTypeName(void) const { static String name = "PieSlice"; return name; } }; } #endif{CODE} !!PieSliceOverlayElement.cpp {CODE(wrap="1", colors="c++")}#include "OgreStableHeaders.h" #include "PieSliceOverlayElement.h" #include "OgreRoot.h" #include "OgreLogManager.h" #include "OgreOverlayManager.h" #include "OgreHardwareBufferManager.h" #include "OgreHardwareVertexBuffer.h" #include "OgreException.h" #include "OgreStringConverter.h" #include "OgreRenderSystem.h" #include "OgreMath.h" namespace Ogre { //--------------------------------------------------------------------- String PieSliceOverlayElement::msTypeName = "PieSlice"; PieSliceOverlayElement::CmdStartAngle PieSliceOverlayElement::msCmdStartAngle; PieSliceOverlayElement::CmdEndAngle PieSliceOverlayElement::msCmdEndAngle; //--------------------------------------------------------------------- #define POS_TEX_BINDING 0 //--------------------------------------------------------------------- PieSliceOverlayElement::PieSliceOverlayElement(const String& name) : OverlayElement(name) { mTransparent = false; mStartAngle = 0.0f; mEndAngle = Math::TWO_PI; if (createParamDictionary("PieSliceOverlayElement")) { addBaseParameters(); } } void PieSliceOverlayElement::initialise(void) { if (!mInitialised) { // Set up the render op // Combine positions and texture coords since they tend to change together // since character sizes are different mRenderOp.vertexData = new VertexData(); mRenderOp.vertexData->vertexCount = 5; // 8 cells, can't necessarily share vertices cos // texcoords may differ mRenderOp.vertexData->vertexStart = 0; size_t offset = 0; // Positions VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); // Texcoords decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); offset += VertexElement::getTypeSize(VET_FLOAT2); // Vertex buffer position and tex HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer( decl->getVertexSize(POS_TEX_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; bind->setBinding(POS_TEX_BINDING, vbuf); mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; mRenderOp.useIndexes = true; // Index data mRenderOp.indexData = new IndexData(); mRenderOp.indexData->indexCount = 4 * 3; mRenderOp.indexData->indexStart = 0; mRenderOp.indexData->indexBuffer = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, mRenderOp.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); ushort* pIdx = static_cast<ushort*>( mRenderOp.indexData->indexBuffer->lock( 0, mRenderOp.indexData->indexBuffer->getSizeInBytes(), HardwareBuffer::HBL_DISCARD) ); /* 0-----1 |\ /| | \ / | | 2 | | / \ | |/ \| 4-----3 */ *pIdx++ = 0; *pIdx++ = 2; *pIdx++ = 1; *pIdx++ = 2; *pIdx++ = 3; *pIdx++ = 1; *pIdx++ = 3; *pIdx++ = 2; *pIdx++ = 4; *pIdx++ = 4; *pIdx++ = 2; *pIdx++ = 0; mRenderOp.indexData->indexBuffer->unlock(); mInitialised = true; } } void PieSliceOverlayElement::updatePositionGeometry() { /* +-----+ +-----+ |\ 0 /| |\B B/| | \ / | |D\A/D| |3 : 1| | C:C | | / \ | |D/ \D| |/ 2 \| |/D D\| +-----+ +-----+ */ int startSeg, endSeg; Radian startAngle, endAngle,tempAngle; Radian aA,aB,aC,aD; Real sideC; Real left, right, top, bottom, centerX, centerY; left = _getDerivedLeft() * 2 - 1; right = left + (mWidth * 2); top = -((_getDerivedTop() * 2) - 1); bottom = top - (mHeight * 2); centerX = left + (right - left)/2; centerY = top + (bottom - top)/2; aB = Math::ATan((top - bottom)/(right - left)); aA = Radian(Math::PI) - aB -aB; aD = Radian(Math::HALF_PI) - aB; aC = Radian(Math::PI) - aA; sideC = Math::Sqrt(Math::Sqr(bottom - top) + Math::Sqr(right - left))/2.0f; startAngle = Radian(mStartAngle) + (aA/2.0); if (startAngle >= Radian(Math::TWO_PI)) startAngle -= Radian(Math::TWO_PI); endAngle = Radian(mEndAngle) + (aA/2.0); if (endAngle >= Radian(Math::TWO_PI)) endAngle -= Radian(Math::TWO_PI); if (startAngle < aA) startSeg = 0; else { if (startAngle < aA+aC) startSeg = 1; else { if (startAngle < aA+aC+aA) startSeg = 2; else { startSeg = 3; } } } if (endAngle < aA) endSeg = 0; else { if (endAngle < aA+aC) endSeg = 1; else { if (endAngle < aA+aC+aA) endSeg = 2; else { endSeg = 3; } } } // Set up the render op // Combine positions and texture coords since they tend to change together // since character sizes are different mRenderOp.vertexData = new VertexData(); if (startAngle>=endAngle) { if (startSeg == endSeg) mRenderOp.vertexData->vertexCount = 7; else { mRenderOp.vertexData->vertexCount = 3; int currentSeg = startSeg; while (currentSeg != endSeg) { mRenderOp.vertexData->vertexCount++; currentSeg++; currentSeg = currentSeg%4; } } } else { if (startSeg == endSeg) mRenderOp.vertexData->vertexCount = 3; else { mRenderOp.vertexData->vertexCount = 3; int currentSeg = startSeg; while (currentSeg != endSeg) { mRenderOp.vertexData->vertexCount++; currentSeg++; currentSeg = currentSeg%4; } } } mRenderOp.vertexData->vertexStart = 0; size_t offset = 0; // Positions VertexDeclaration* decl = mRenderOp.vertexData->vertexDeclaration; decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT3, VES_POSITION); offset += VertexElement::getTypeSize(VET_FLOAT3); // Texcoords decl->addElement(POS_TEX_BINDING, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); offset += VertexElement::getTypeSize(VET_FLOAT2); // Vertex buffer position and tex HardwareVertexBufferSharedPtr vbuf = HardwareBufferManager::getSingleton(). createVertexBuffer( decl->getVertexSize(POS_TEX_BINDING), mRenderOp.vertexData->vertexCount, HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); VertexBufferBinding* bind = mRenderOp.vertexData->vertexBufferBinding; bind->setBinding(POS_TEX_BINDING, vbuf); float* pPos = static_cast<float*>( vbuf->lock(HardwareBuffer::HBL_DISCARD) ); // Use the furthest away depth value, since materials should have depth-check off // This initialised the depth buffer for any 3D objects in front Real zValue = Root::getSingleton().getRenderSystem()->getMaximumDepthInputValue(); *pPos++ = centerX; *pPos++ = centerY; *pPos++ = zValue; *pPos++ = 0.5; *pPos++ = 0.5; // calc start values here Real startX,startY,startU,startV,sideA; Radian angle; switch(startSeg) { case 0 : { angle = startAngle; sideA = (Math::Sin(angle)*sideC)/Math::Sin(Radian(Math::PI)-angle-aB); startX = sideA+left; startY = top; startU = sideA/(right - left); startV = 0.0; break; } case 1 : { angle = startAngle-aA; sideA = (Math::Sin(angle)*sideC)/Math::Sin(Radian(Math::PI)-angle-aD); startX = right; startY = top-sideA; startU = 1.0; startV = sideA/(top-bottom); break; } case 2 : { angle = startAngle-aA-aC; sideA = (Math::Sin(angle)*sideC)/Math::Sin(Radian(Math::PI)-angle-aB); startX = right-sideA; startY = bottom; startU = 1.0-(sideA/(right - left)); startV = 1.0; break; } case 3 : { angle = startAngle-aA-aC-aA; sideA = (Math::Sin(angle)*sideC)/Math::Sin(Radian(Math::PI)-angle-aD); startX = left; startY = bottom+sideA; startU = 0.0; startV = 1.0-(sideA/(top-bottom)); break; } } *pPos++ = startX; *pPos++ = startY; *pPos++ = zValue; *pPos++ = startU; *pPos++ = startV; int currentSeg = startSeg; int segCount = 1; bool largeSlice = false; if(startAngle >= endAngle) largeSlice = true; while (currentSeg != endSeg || largeSlice) { largeSlice = false; switch (currentSeg) { case 0 : { *pPos++ = right; *pPos++ = top; *pPos++ = zValue; *pPos++ = 1.0; *pPos++ = 0.0; break; } case 1 : { *pPos++ = right; *pPos++ = bottom; *pPos++ = zValue; *pPos++ = 1.0; *pPos++ = 1.0; break; } case 2 : { *pPos++ = left; *pPos++ = bottom; *pPos++ = zValue; *pPos++ = 0.0; *pPos++ = 1.0; break; } case 3 : { *pPos++ = left; *pPos++ = top; *pPos++ = zValue; *pPos++ = 0.0; *pPos++ = 0.0; break; } } currentSeg++; currentSeg = currentSeg % 4; segCount++; } // calc start values here Real endX,endY,endU,endV; switch(endSeg) { case 0 : { angle = endAngle; sideA = (Math::Sin(angle)*sideC)/Math::Sin(Radian(Math::PI)-angle-aB); endX = sideA+left; endY = top; endU = sideA/(right - left); endV = 0.0; break; } case 1 : { angle = endAngle-aA; sideA = (Math::Sin(angle)*sideC)/Math::Sin(Radian(Math::PI)-angle-aD); endX = right; endY = top-sideA; endU = 1.0; endV = sideA/(top-bottom); break; } case 2 : { angle = endAngle-aA-aC; sideA = (Math::Sin(angle)*sideC)/Math::Sin(Radian(Math::PI)-angle-aB); endX = right-sideA; endY = bottom; endU = 1.0-(sideA/(right - left)); endV = 1.0; break; } case 3 : { angle = endAngle-aA-aC-aA; sideA = (Math::Sin(angle)*sideC)/Math::Sin(Radian(Math::PI)-angle-aD); endX = left; endY = bottom+sideA; endU = 0.0; endV = 1.0-(sideA/(top-bottom)); break; } } *pPos++ = endX; *pPos++ = endY; *pPos++ = zValue; *pPos++ = endU; *pPos++ = endV; vbuf->unlock(); mRenderOp.operationType = RenderOperation::OT_TRIANGLE_LIST; mRenderOp.useIndexes = true; // Index data mRenderOp.indexData = new IndexData(); mRenderOp.indexData->indexCount = (segCount+1)*3; mRenderOp.indexData->indexStart = 0; mRenderOp.indexData->indexBuffer = HardwareBufferManager::getSingleton(). createIndexBuffer( HardwareIndexBuffer::IT_16BIT, mRenderOp.indexData->indexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY); ushort* pIdx = static_cast<ushort*>( mRenderOp.indexData->indexBuffer->lock( 0, mRenderOp.indexData->indexBuffer->getSizeInBytes(), HardwareBuffer::HBL_DISCARD) ); /* 5-6-1-2 |\ /| | \ / | | 0 | | / \ | |/ \| 4-----3 */ if (segCount>0) { *pIdx++ = 0; *pIdx++ = 2; *pIdx++ = 1; } if (segCount>1) { *pIdx++ = 0; *pIdx++ = 3; *pIdx++ = 2; } if (segCount>2) { *pIdx++ = 0; *pIdx++ = 4; *pIdx++ = 3; } if (segCount>3) { *pIdx++ = 0; *pIdx++ = 5; *pIdx++ = 4; } if (segCount>4) { *pIdx++ = 0; *pIdx++ = 6; *pIdx++ = 5; } mRenderOp.indexData->indexBuffer->unlock(); } void PieSliceOverlayElement::updateTextureGeometry() { // Nothing to do, we combine positions and textures } void PieSliceOverlayElement::setStartAngle( Real angle ) { mStartAngle = angle; mGeomPositionsOutOfDate = true; } Real PieSliceOverlayElement::getStartAngle() const { return mStartAngle; } void PieSliceOverlayElement::setEndAngle( Real angle ) { mEndAngle = angle; mGeomPositionsOutOfDate = true; } Real PieSliceOverlayElement::getEndAngle() const { return mEndAngle; } //--------------------------------------------------------------------- PieSliceOverlayElement::~PieSliceOverlayElement() { delete mRenderOp.vertexData; } //--------------------------------------------------------------------- const String& PieSliceOverlayElement::getTypeName(void) const { return msTypeName; } //--------------------------------------------------------------------- void PieSliceOverlayElement::getRenderOperation(RenderOperation& op) { op = mRenderOp; } //--------------------------------------------------------------------- void PieSliceOverlayElement::setMaterialName(const String& matName) { OverlayElement::setMaterialName(matName); } //--------------------------------------------------------------------- void PieSliceOverlayElement::addBaseParameters(void) { OverlayElement::addBaseParameters(); ParamDictionary* dict = getParamDictionary(); dict->addParameter(ParameterDef("start_angle", "Sets the start angle." , PT_REAL), &msCmdStartAngle); dict->addParameter(ParameterDef("end_angle", "Sets the end angle." , PT_REAL), &msCmdEndAngle); } //----------------------------------------------------------------------- void PieSliceOverlayElement::setMetricsMode(GuiMetricsMode gmm) { Real vpWidth, vpHeight; vpWidth = (Real) (OverlayManager::getSingleton().getViewportWidth()); vpHeight = (Real) (OverlayManager::getSingleton().getViewportHeight()); OverlayElement::setMetricsMode(gmm); } //----------------------------------------------------------------------- void PieSliceOverlayElement::_update(void) { Real vpWidth, vpHeight; vpWidth = (Real) (OverlayManager::getSingleton().getViewportWidth()); vpHeight = (Real) (OverlayManager::getSingleton().getViewportHeight()); if (mMetricsMode != GMM_RELATIVE && (OverlayManager::getSingleton().hasViewportChanged() || mGeomPositionsOutOfDate)) { // Recalc character size mGeomPositionsOutOfDate = true; } OverlayElement::_update(); } //--------------------------------------------------------------------------------------------- // StartAngle command object // String PieSliceOverlayElement::CmdStartAngle::doGet( const void* target ) const { return StringConverter::toString( static_cast< const PieSliceOverlayElement* >( target )->getStartAngle() ); } void PieSliceOverlayElement::CmdStartAngle::doSet( void* target, const String& val ) { static_cast< PieSliceOverlayElement* >( target )->setStartAngle( StringConverter::parseReal( val ) ); } //--------------------------------------------------------------------------------------------- // EndAngle command object // String PieSliceOverlayElement::CmdEndAngle::doGet( const void* target ) const { return StringConverter::toString( static_cast< const PieSliceOverlayElement* >( target )->getEndAngle() ); } void PieSliceOverlayElement::CmdEndAngle::doSet( void* target, const String& val ) { static_cast< PieSliceOverlayElement* >( target )->setEndAngle( StringConverter::parseReal( val ) ); } }{CODE} !!Usage Create factory. {CODE(wrap="1", colors="c++")}bool MyApplication::setup( void ) { mRoot = new Root(); mPieSliceFactory = new PieSliceOverlayElementFactory(); OverlayManager::getSingleton().addOverlayElementFactory(mPieSliceFactory); . . .{CODE} Then create a normal overlay element, passing parameter for angles. NOTE: Angles need to be in radian. {CODE(wrap="1", colors="c++")} Overlay* PieSliceOverlay = OverlayManager::getSingleton().create("PieSliceOverlay"); PSpecialOverlay->setZOrder(2); NewPanel = static_cast<OverlayContainer*>(OverlayManager::getSingleton().createOverlayElement ("PieSlice", "Minority")); NewPanel->setMaterialName("PieChart/Blue"); NewPanel->setPosition(0.1f,0.1f); NewPanel->setWidth(0.8f); NewPanel->setHeight(0.8f); NewPanel->setParameter("start_angle", StringConverter::toString(Math::fDeg2Rad * 0.0f)); NewPanel->setParameter("end_angle", StringConverter::toString(Math::fDeg2Rad * 60.0f)); PSpecialOverlay->add2D(NewPanel); NewPanel = static_cast<OverlayContainer*>(OverlayManager::getSingleton().createOverlayElement ("PieSlice", "Magority")); NewPanel->setMaterialName("PieChart/Red"); NewPanel->setPosition(0.1f,0.1f); NewPanel->setWidth(0.8f); NewPanel->setHeight(0.8f); NewPanel->setParameter("start_angle", StringConverter::toString(Math::fDeg2Rad * 60.0f)); NewPanel->setParameter("end_angle", StringConverter::toString(Math::fDeg2Rad * 360.0f)); PSpecialOverlay->add2D(NewPanel); PSpecialOverlay->show();{CODE}
Search by Tags
Search Wiki by Freetags
Latest Changes
Ogre 2.1 FAQ
Minimal Ogre Collision
Artifex Terra
OpenMB
Advanced Mogre Framework
MogreSocks
Critter AI
Mogre Add-ons
MOGRE
Mogre MyGUI wrapper
...more
Search
Find
Advanced
Search Help
Online Users
147 online users