GhoulPrimitivesOgre.cpp

Go to the documentation of this file.
00001 #include "lugre_prefix.h"
00002 #include <Ogre.h>
00003 #include "GhoulPrimitives.h"
00004 
00005 using namespace GhoulPrimitive;
00006 using namespace Ogre;
00007 using namespace Lugre;
00008 
00009 
00010 #define MY_VERTEX_BINDING_SOURCE 0
00011 
00012 
00013 
00014 /*
00015 TODO : useful ?
00016 # Split your vertex buffers up if you find that your usage patterns for different elements of the vertex are different.
00017 No point having one huge updateable buffer with all the vertex data in it, if all you need to update is the texture coordinates.
00018 Split that part out into it's own buffer and make the rest HBU_STATIC_WRITE_ONLY.
00019 
00020 see also
00021 vertex buffer : file:///usr/src/ogrenew/Docs/manual/manual_42.html#SEC178
00022 index buffer :  file:///usr/src/ogrenew/Docs/manual/manual_47.html#SEC186
00023 */
00024 
00025 
00027 OgreRenderableDrawer::OgreRenderableDrawer  () { PROFILE
00028     setMaterial("BaseWhiteNoLighting");
00029     mReady = false;
00030     mRenderOp.vertexData = new VertexData;
00031     mIndexBufferInitialized = false;
00032     mVertexDecInitialized = false;
00033     mVertexBufferCapacity = 0;
00034     mIndexBufferCapacity = 0;
00035 }
00036 
00037 OgreRenderableDrawer::~OgreRenderableDrawer() { PROFILE
00038     delete mRenderOp.vertexData;
00039     if (mIndexBufferInitialized)
00040         delete mRenderOp.indexData;
00041 }
00042 
00043 // Drawer interface
00044 void    OgreRenderableDrawer::Prepare       (eOpType opType,eGeometryChange gcHint,size_t vertexCount,size_t indexCount,bool hasNormals,bool hasTexCoords) { PROFILE
00045     assert(!mReady && "Prepare called twice");
00046 
00047     // Create vertex declaration
00048     if (!mVertexDecInitialized || hasNormals != mHasNormals || mHasTexCoords != hasTexCoords) {
00049         mHasNormals = hasNormals;
00050         mHasTexCoords = hasTexCoords;
00051         VertexDeclaration *decl = mRenderOp.vertexData->vertexDeclaration;
00052         if (mVertexDecInitialized) {
00053             while (decl->getVertexSize(MY_VERTEX_BINDING_SOURCE) > 0) {
00054                 //printf("Clearing old vertexdecl\n");
00055                 decl->removeElement(0); // clear would have been nice
00056             }
00057         }
00058 
00059         //printf("create vertex decl\n");
00060         size_t offset = 0;
00061         offset += decl->addElement(MY_VERTEX_BINDING_SOURCE, 0, VET_FLOAT3, VES_POSITION).getSize();
00062         if (mHasNormals)    offset += decl->addElement(MY_VERTEX_BINDING_SOURCE,offset,VET_FLOAT3,VES_NORMAL).getSize();
00063         if (mHasTexCoords)  offset += decl->addElement(MY_VERTEX_BINDING_SOURCE,offset,VET_FLOAT2,VES_TEXTURE_COORDINATES).getSize();
00064 
00065         mVertexDecInitialized = true;
00066 
00067         /*
00068         NOTES :
00069         decl->addElement(source,offset,theType,semantic,index=0);
00070         // VES_DIFFUSE,VES_SPECULAR
00071         // VES_BLEND_WEIGHTS,VES_BLEND_INDICES,VES_BINORMAL,VES_TANGENT
00072         // VET_FLOAT1-4,VET_COLOUR,
00073         // source=POSITION_BINDING
00074         source  The binding index of HardwareVertexBuffer which will provide the source for this element. See VertexBufferBindingState for full information.
00075         offset  The offset in bytes where this element is located in the buffer
00076         theType     The data format of the element (3 floats, a colour etc)
00077         semantic    The meaning of the data (position, normal, diffuse colour etc)
00078         index   Optional index for multi-input elements like texture coordinates
00079         //size_t offset = decl->getVertexSize(MY_VERTEX_BINDING_SOURCE);
00080         */
00081     }
00082 
00083     // initialize RenderOp
00084     mRenderOp.operationType = GetOgreOpType(opType);
00085     mRenderOp.useIndexes = indexCount > 0;
00086     if (mRenderOp.useIndexes && !mIndexBufferInitialized) {
00087         mRenderOp.indexData = new IndexData;
00088         mIndexBufferInitialized = true;
00089     }
00090     mRenderOp.vertexData->vertexCount = vertexCount;
00091     if (mRenderOp.useIndexes) mRenderOp.indexData->indexCount = indexCount;
00092 
00093     // init membervars for receiving vertices
00094     mReady = true;
00095     miVerticesLeft = vertexCount;
00096     miIndicesLeft = indexCount;
00097     mBoundingBoxEmpty = true;
00098     mvAABMin = Vector3::ZERO;
00099     mvAABMax = Vector3::ZERO;
00100 
00101     // if there are no vertices, there is no need for a buffer
00102     if (vertexCount <= 0) return;
00103 
00104     // Create new vertex buffer
00105     if (mVertexBufferCapacity != vertexCount) {
00106         mVertexBufferCapacity  = vertexCount;
00107         //printf("alloc vertexbuffer for max %d vertices\n",mVertexBufferCapacity);
00108         mHWVBuf = HardwareBufferManager::getSingleton().createVertexBuffer(
00109                 mRenderOp.vertexData->vertexDeclaration->getVertexSize(MY_VERTEX_BINDING_SOURCE),
00110                 vertexCount,
00111                 HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
00112         // Bind buffer
00113         mRenderOp.vertexData->vertexBufferBinding->setBinding(MY_VERTEX_BINDING_SOURCE, mHWVBuf);
00114 
00115         // TODO : memory leak if reassigned ??
00116     }
00117     mRenderOp.vertexData->vertexCount = vertexCount;
00118 
00119 
00120     // Create new index buffer
00121     //printf("preindex\n");
00122     if (mIndexBufferCapacity != indexCount && mRenderOp.useIndexes) {
00123         mIndexBufferCapacity  = indexCount;
00124         //printf("alloc index for max %d indices\n",mIndexBufferCapacity);
00125         mHWIBuf = HardwareBufferManager::getSingleton().createIndexBuffer(
00126                 HardwareIndexBuffer::IT_16BIT,
00127                 indexCount,
00128                 HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY);
00129         mRenderOp.indexData->indexBuffer = mHWIBuf;
00130         // TODO : memory leak if reassigned ??
00131         //HardwareIndexBufferSharedPtr iBuf = mRenderOp.indexData->indexBuffer;
00132     }
00133     if (mRenderOp.useIndexes) mRenderOp.indexData->indexCount = indexCount;
00134 
00135     //mHWVBuf = mRenderOp.vertexData->vertexBufferBinding->getBuffer(MY_VERTEX_BINDING_SOURCE);
00136     mWritePtr = (vertexCount > 0) ? (static_cast<Real*>(mHWVBuf->lock(HardwareBuffer::HBL_DISCARD))) : 0;
00137     mIndexWritePtr = (indexCount > 0) ? (static_cast<unsigned short*>(mHWIBuf->lock(HardwareBuffer::HBL_DISCARD))) : 0;
00138 }
00139 
00140 void    OgreRenderableDrawer::AddVertex     (kReal x,kReal y,kReal z,kReal nx,kReal ny,kReal nz,kReal u,kReal v) { PROFILE
00141     //printf("AddVertex(%0.1f,%0.1f,%0.1f, %0.1f,%0.1f,%0.1f, %0.1f,%0.1f)\n",x,y,z,nx,ny,nz,u,v);
00142     assert(mReady && "Prepare not called");
00143     assert(miVerticesLeft > 0 && "vertex buffer overflow");
00144     if (miVerticesLeft <= 0) return;
00145     --miVerticesLeft;
00146     *mWritePtr++ = x;
00147     *mWritePtr++ = y;
00148     *mWritePtr++ = z;
00149     if (mHasNormals) {
00150         *mWritePtr++ = nx;
00151         *mWritePtr++ = ny;
00152         *mWritePtr++ = nz;
00153     }
00154     if (mHasTexCoords) {
00155         *mWritePtr++ = u;
00156         *mWritePtr++ = v;
00157     }
00158     if (mBoundingBoxEmpty || mvAABMin.x > x) mvAABMin.x = x;
00159     if (mBoundingBoxEmpty || mvAABMin.y > y) mvAABMin.y = y;
00160     if (mBoundingBoxEmpty || mvAABMin.z > z) mvAABMin.z = z;
00161     if (mBoundingBoxEmpty || mvAABMax.x < x) mvAABMax.x = x;
00162     if (mBoundingBoxEmpty || mvAABMax.y < y) mvAABMax.y = y;
00163     if (mBoundingBoxEmpty || mvAABMax.z < z) mvAABMax.z = z;
00164     mBoundingBoxEmpty = false;
00165 }
00166 
00167 void    OgreRenderableDrawer::AddIndex  (IndexInt i) { PROFILE
00168     //printf("AddIndex(%d)\n",i);
00169     assert(mReady && "Prepare not called");
00170     assert(miIndicesLeft > 0 && "index buffer overflow");
00171     if (miIndicesLeft <= 0) return;
00172     --miIndicesLeft;
00173     *mIndexWritePtr++ = i;
00174 }
00175 
00176 void    OgreRenderableDrawer::Finish        () { PROFILE
00177     assert(mReady && "Prepare not called");
00178     assert(miVerticesLeft == 0 && "not enough vertices written");
00179     assert(miIndicesLeft == 0 && "not enough indices written");
00180     mBox.setExtents(mvAABMin,mvAABMax);
00181     mReady = false;
00182     if (mVertexBufferCapacity > 0) mHWVBuf->unlock();
00183     if (mIndexBufferCapacity > 0) mHWIBuf->unlock();
00184 }
00185 
00186 Ogre::Real  OgreRenderableDrawer::getBoundingRadius(void) const { PROFILE
00187     return Math::Sqrt(std::max(mBox.getMaximum().squaredLength(), mBox.getMinimum().squaredLength()));
00188 }
00189 
00190 Ogre::Real  OgreRenderableDrawer::getSquaredViewDepth(const Ogre::Camera* cam) const { PROFILE
00191     Vector3 vMin, vMax, vMid, vDist;
00192     vMin = mBox.getMinimum();
00193     vMax = mBox.getMaximum();
00194     vMid = ((vMin - vMax) * 0.5) + vMin;
00195     vDist = cam->getDerivedPosition() - vMid;
00196     return vDist.squaredLength();
00197 }
00198 
00199 
00201 Ogre::RenderOperation::OperationType    OgreRenderableDrawer::GetOgreOpType (const eOpType opType) { PROFILE
00202     switch (opType) {
00203         default:
00204         case kOpType_POINT_LIST     : return Ogre::RenderOperation::OT_POINT_LIST;
00205         case kOpType_LINE_LIST      : return Ogre::RenderOperation::OT_LINE_LIST;
00206         case kOpType_LINE_STRIP     : return Ogre::RenderOperation::OT_LINE_STRIP;
00207         case kOpType_TRIANGLE_LIST  : return Ogre::RenderOperation::OT_TRIANGLE_LIST;
00208         case kOpType_TRIANGLE_STRIP : return Ogre::RenderOperation::OT_TRIANGLE_STRIP;
00209         case kOpType_TRIANGLE_FAN   : return Ogre::RenderOperation::OT_TRIANGLE_FAN;
00210     }
00211 }
00212 
00214 Ogre::HardwareBuffer::Usage             OgreRenderableDrawer::GetOgreHWBUsage   (const eGeometryChange geometryChangeHint) { PROFILE
00215     switch (geometryChangeHint) {
00216         default:
00217         case kGeometryChange_Seldom             : return Ogre::HardwareBuffer::HBU_STATIC_WRITE_ONLY;
00218         case kGeometryChange_Often              : return Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY;
00219         case kGeometryChange_AlmostEveryFrame   : return Ogre::HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE;
00220     }
00221     /*
00222     from  file:///usr/src/ogrenew/Docs/manual/manual_38.html :
00223     HBU_STATIC
00224         SLOW because READ ENABLED
00225         This means you do not need to update the buffer very often, but you might occasionally want to read from it.
00226 
00227     HBU_STATIC_WRITE_ONLY
00228         This means you do not need to update the buffer very often, and you do not need to read from it. However, you may read from it's shadow buffer if you set one up (See section 5.3 Shadow Buffers). This is the optimal buffer usage setting.
00229 
00230     HBU_DYNAMIC
00231         SLOW because READ ENABLED
00232         This means you expect to update the buffer often, and that you may wish to read from it. This is the least optimal buffer setting.
00233 
00234     HBU_DYNAMIC_WRITE_ONLY
00235         This means you expect to update the buffer often, but that you never want to read from it. However, you may read from it's shadow buffer if you set one up (See section 5.3 Shadow Buffers). If you use this option, and replace the entire contents of the buffer every frame, then you should use HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE instead, since that has better performance characteristics on some platforms.
00236 
00237     HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE
00238         This means that you expect to replace the entire contents of the buffer on an extremely regular basis, most likely every frame. By selecting this option, you free the system up from having to be concerned about losing the existing contents of the buffer at any time, because if it does lose them, you will be replacing them next frame anyway. On some platforms this can make a significant performance difference, so you should try to use this whenever you have a buffer you need to update regularly. Note that if you create a buffer this way, you should use the HBL_DISCARD flag when locking the contents of it for writing.
00239     */
00240 }

Generated on Tue May 22 06:00:14 2012 for cpp by  doxygen 1.5.6