Main Page   Namespace List   Class Hierarchy   Alphabetical List   Compound List   File List   Namespace Members   Compound Members   File Members   Related Pages  

OgreVertexIndexData.cpp

Go to the documentation of this file.
00001 /*
00002 -----------------------------------------------------------------------------
00003 This source file is part of OGRE
00004     (Object-oriented Graphics Rendering Engine)
00005 For the latest info, see http://www.ogre3d.org/
00006 
00007 Copyright © 2000-2003 The OGRE Team
00008 Also see acknowledgements in Readme.html
00009 
00010 This program is free software; you can redistribute it and/or modify it under
00011 the terms of the GNU Lesser General Public License as published by the Free Software
00012 Foundation; either version 2 of the License, or (at your option) any later
00013 version.
00014 
00015 This program is distributed in the hope that it will be useful, but WITHOUT
00016 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
00017 FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
00018 
00019 You should have received a copy of the GNU Lesser General Public License along with
00020 this program; if not, write to the Free Software Foundation, Inc., 59 Temple
00021 Place - Suite 330, Boston, MA 02111-1307, USA, or go to
00022 http://www.gnu.org/copyleft/lesser.txt.
00023 -----------------------------------------------------------------------------
00024 */
00025 #include "OgreStableHeaders.h"
00026 #include "OgreVertexIndexData.h"
00027 #include "OgreHardwareBufferManager.h"
00028 #include "OgreHardwareVertexBuffer.h"
00029 #include "OgreHardwareIndexBuffer.h"
00030 #include "OgreVector3.h"
00031 #include "OgreAxisAlignedBox.h"
00032 #include "OgreRoot.h"
00033 #include "OgreRenderSystem.h" 
00034 
00035 namespace Ogre {
00036 
00037     //-----------------------------------------------------------------------
00038     VertexData::VertexData()
00039     {
00040         vertexBufferBinding = HardwareBufferManager::getSingleton().
00041             createVertexBufferBinding();
00042         vertexDeclaration = HardwareBufferManager::getSingleton().
00043             createVertexDeclaration();
00044         vertexCount = 0;
00045         vertexStart = 0;
00046 
00047     }
00048     //-----------------------------------------------------------------------
00049     VertexData::~VertexData()
00050     {
00051         HardwareBufferManager::getSingleton().
00052             destroyVertexBufferBinding(vertexBufferBinding);
00053         HardwareBufferManager::getSingleton().destroyVertexDeclaration(vertexDeclaration);
00054 
00055     }
00056     //-----------------------------------------------------------------------
00057     VertexData* VertexData::clone(bool copyData) const
00058     {
00059         VertexData* dest = new VertexData();
00060 
00061         // Copy vertex buffers in turn
00062         const VertexBufferBinding::VertexBufferBindingMap bindings = 
00063             this->vertexBufferBinding->getBindings();
00064         VertexBufferBinding::VertexBufferBindingMap::const_iterator vbi, vbend;
00065         vbend = bindings.end();
00066         for (vbi = bindings.begin(); vbi != vbend; ++vbi)
00067         {
00068             HardwareVertexBufferSharedPtr srcbuf = vbi->second;
00069             HardwareVertexBufferSharedPtr dstBuf;
00070             if (copyData)
00071             {
00072                 // create new buffer with the same settings
00073                 dstBuf = 
00074                     HardwareBufferManager::getSingleton().createVertexBuffer(
00075                         srcbuf->getVertexSize(), srcbuf->getNumVertices(), srcbuf->getUsage(),
00076                         srcbuf->hasShadowBuffer());
00077 
00078                 // copy data
00079                 dstBuf->copyData(*srcbuf, 0, 0, srcbuf->getSizeInBytes(), true);
00080             }
00081             else
00082             {
00083                 // don't copy, point at existing buffer
00084                 dstBuf = srcbuf;
00085             }
00086 
00087             // Copy binding
00088             dest->vertexBufferBinding->setBinding(vbi->first, dstBuf);
00089         }
00090 
00091         // Basic vertex info
00092         dest->vertexStart = this->vertexStart;
00093         dest->vertexCount = this->vertexCount;
00094         // Copy elements
00095         const VertexDeclaration::VertexElementList elems = 
00096             this->vertexDeclaration->getElements();
00097         VertexDeclaration::VertexElementList::const_iterator ei, eiend;
00098         eiend = elems.end();
00099         for (ei = elems.begin(); ei != eiend; ++ei)
00100         {
00101             dest->vertexDeclaration->addElement(
00102                 ei->getSource(),
00103                 ei->getOffset(),
00104                 ei->getType(),
00105                 ei->getSemantic(),
00106                 ei->getIndex() );
00107         }
00108 
00109         
00110         return dest;
00111     }
00112     //-----------------------------------------------------------------------
00113     void VertexData::prepareForShadowVolume(void)
00114     {
00115         /* NOTE
00116         I would dearly, dearly love to just use a 4D position buffer in order to 
00117         store the extra 'w' value I need to differentiate between extruded and 
00118         non-extruded sections of the buffer, so that vertex programs could use that.
00119         Hey, it works fine for GL. However, D3D9 in it's infinite stupidity, does not
00120         support 4d position vertices in the fixed-function pipeline. If you use them, 
00121         you just see nothing. Since we can't know whether the application is going to use
00122         fixed function or vertex programs, we have to stick to 3d position vertices and
00123         store the 'w' in a separate 1D texture coordinate buffer, which is only used
00124         when rendering the shadow.
00125         */
00126 
00127         // Upfront, lets check whether we have vertex program capability
00128         RenderSystem* rend = Root::getSingleton().getRenderSystem();
00129         bool useVertexPrograms = false;
00130         if (rend && rend->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
00131         {
00132             useVertexPrograms = true;
00133         }
00134 
00135 
00136         // Look for a position element
00137         const VertexElement* posElem = vertexDeclaration->findElementBySemantic(VES_POSITION);
00138         if (posElem)
00139         {
00140             size_t v;
00141             unsigned posOldSource = posElem->getSource();
00142 
00143             HardwareVertexBufferSharedPtr vbuf = vertexBufferBinding->getBuffer(posOldSource);
00144             bool wasSharedBuffer = false;
00145             // Are there other elements in the buffer except for the position?
00146             if (vbuf->getVertexSize() > posElem->getSize())
00147             {
00148                 // We need to create another buffer to contain the remaining elements
00149                 // Most drivers don't like gaps in the declaration, and in any case it's waste
00150                 wasSharedBuffer = true;
00151             }
00152             HardwareVertexBufferSharedPtr newPosBuffer, newRemainderBuffer;
00153             if (wasSharedBuffer)
00154             {
00155                 newRemainderBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
00156                     vbuf->getVertexSize() - posElem->getSize(), vbuf->getNumVertices(), vbuf->getUsage(),
00157                     vbuf->hasShadowBuffer());
00158             }
00159             // Allocate new position buffer, will be FLOAT3 and 2x the size
00160             size_t oldVertexCount = vbuf->getNumVertices();
00161             size_t newVertexCount = oldVertexCount * 2;
00162             newPosBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
00163                 VertexElement::getTypeSize(VET_FLOAT3), newVertexCount, vbuf->getUsage(), 
00164                 vbuf->hasShadowBuffer());
00165 
00166             // Iterate over the old buffer, copying the appropriate elements and initialising the rest
00167             Real* pSrc;
00168             unsigned char *pBaseSrc = static_cast<unsigned char*>(
00169                 vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
00170             // Point first destination pointer at the start of the new position buffer,
00171             // the other one half way along
00172             Real *pDest = static_cast<Real*>(newPosBuffer->lock(HardwareBuffer::HBL_DISCARD));
00173             Real* pDest2 = pDest + oldVertexCount * 3; 
00174 
00175             // Precalculate any dimensions of vertex areas outside the position
00176             size_t prePosVertexSize, postPosVertexSize, postPosVertexOffset;
00177             unsigned char *pBaseDestRem = 0;
00178             if (wasSharedBuffer)
00179             {
00180                 pBaseDestRem = static_cast<unsigned char*>(
00181                     newRemainderBuffer->lock(HardwareBuffer::HBL_DISCARD));
00182                 prePosVertexSize = posElem->getOffset();
00183                 postPosVertexOffset = prePosVertexSize + posElem->getSize();
00184                 postPosVertexSize = vbuf->getVertexSize() - postPosVertexOffset;
00185                 // the 2 separate bits together should be the same size as the remainder buffer vertex
00186                 assert (newRemainderBuffer->getVertexSize() == prePosVertexSize + postPosVertexSize);
00187 
00188                 // Iterate over the vertices
00189                 for (v = 0; v < oldVertexCount; ++v)
00190                 {
00191                     // Copy position, into both buffers
00192                     posElem->baseVertexPointerToElement(pBaseSrc, &pSrc);
00193                     *pDest++ = *pDest2++ = *pSrc++;
00194                     *pDest++ = *pDest2++ = *pSrc++;
00195                     *pDest++ = *pDest2++ = *pSrc++;
00196 
00197                     // now deal with any other elements 
00198                     // Basically we just memcpy the vertex excluding the position
00199                     if (prePosVertexSize > 0)
00200                         memcpy(pBaseDestRem, pBaseSrc, prePosVertexSize);
00201                     if (postPosVertexSize > 0)
00202                         memcpy(pBaseDestRem + prePosVertexSize, 
00203                             pBaseSrc + postPosVertexOffset, postPosVertexSize);
00204                     pBaseDestRem += newRemainderBuffer->getVertexSize();
00205 
00206                     pBaseSrc += vbuf->getVertexSize();
00207 
00208                 } // next vertex
00209             }
00210             else
00211             {
00212                 // Unshared buffer, can block copy the whole thing
00213                 memcpy(pDest, pBaseSrc, vbuf->getSizeInBytes());
00214                 memcpy(pDest2, pBaseSrc, vbuf->getSizeInBytes());
00215             }
00216 
00217             vbuf->unlock();
00218             newPosBuffer->unlock();
00219             if (wasSharedBuffer)
00220                 newRemainderBuffer->unlock();
00221 
00222             // At this stage, he original vertex buffer is going to be destroyed
00223             // So we should force the deallocation of any temporary copies
00224             HardwareBufferManager::getSingleton()._forceReleaseBufferCopies(vbuf);
00225 
00226             if (useVertexPrograms)
00227             {
00228                 // Now it's time to set up the w buffer
00229                 hardwareShadowVolWBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
00230                     sizeof(Real), newVertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
00231                 // Fill the first half with 1.0, second half with 0.0
00232                 pDest = static_cast<Real*>(
00233                     hardwareShadowVolWBuffer->lock(HardwareBuffer::HBL_DISCARD));
00234                 for (v = 0; v < oldVertexCount; ++v)
00235                 {
00236                     *pDest++ = 1.0f;
00237                 }
00238                 for (v = 0; v < oldVertexCount; ++v)
00239                 {
00240                     *pDest++ = 0.0f;
00241                 }
00242                 hardwareShadowVolWBuffer->unlock();
00243             }
00244 
00245             unsigned short newPosBufferSource; 
00246             if (wasSharedBuffer)
00247             {
00248                 // Get the a new buffer binding index
00249                 newPosBufferSource= vertexBufferBinding->getNextIndex();
00250                 // Re-bind the old index to the remainder buffer
00251                 vertexBufferBinding->setBinding(posOldSource, newRemainderBuffer);
00252             }
00253             else
00254             {
00255                 // We can just re-use the same source idex for the new position buffer
00256                 newPosBufferSource = posOldSource;
00257             }
00258             // Bind the new position buffer
00259             vertexBufferBinding->setBinding(newPosBufferSource, newPosBuffer);
00260 
00261             // Now, alter the vertex declaration to change the position source
00262             // and the offsets of elements using the same buffer
00263             VertexDeclaration::VertexElementList::const_iterator elemi = 
00264                 vertexDeclaration->getElements().begin();
00265             VertexDeclaration::VertexElementList::const_iterator elemiend = 
00266                 vertexDeclaration->getElements().end();
00267             unsigned short idx;
00268             for(idx = 0; elemi != elemiend; ++elemi, ++idx) 
00269             {
00270                 if (&(*elemi) == posElem)
00271                 {
00272                     // Modify position to point at new position buffer
00273                     vertexDeclaration->modifyElement(
00274                         idx, 
00275                         newPosBufferSource, // new source buffer
00276                         0, // no offset now
00277                         VET_FLOAT3, 
00278                         VES_POSITION);
00279                 }
00280                 else if (wasSharedBuffer &&
00281                     elemi->getSource() == posOldSource &&
00282                     elemi->getOffset() > prePosVertexSize )
00283                 {
00284                     // This element came after position, remove the position's
00285                     // size
00286                     vertexDeclaration->modifyElement(
00287                         idx, 
00288                         posOldSource, // same old source
00289                         elemi->getOffset() - posElem->getSize(), // less offset now
00290                         elemi->getType(), 
00291                         elemi->getSemantic(),
00292                         elemi->getIndex());
00293 
00294                 }
00295 
00296             }
00297 
00298 
00299             // Note that we don't change vertexCount, because the other buffer(s) are still the same
00300             // size after all
00301 
00302 
00303         }
00304     }
00305     //-----------------------------------------------------------------------
00306     IndexData::IndexData()
00307     {
00308         indexCount = 0;
00309         indexStart = 0;
00310         
00311     }
00312     //-----------------------------------------------------------------------
00313     IndexData::~IndexData()
00314     {
00315     }
00316     //-----------------------------------------------------------------------
00317     IndexData* IndexData::clone(bool copyData) const
00318     {
00319         IndexData* dest = new IndexData();
00320         if (indexBuffer.get())
00321         {
00322             if (copyData)
00323             {
00324                 dest->indexBuffer = HardwareBufferManager::getSingleton().
00325                     createIndexBuffer(indexBuffer->getType(), indexBuffer->getNumIndexes(),
00326                     indexBuffer->getUsage(), indexBuffer->hasShadowBuffer());
00327                 dest->indexBuffer->copyData(*indexBuffer, 0, 0, indexBuffer->getSizeInBytes(), true);
00328             }
00329             else
00330             {
00331                 dest->indexBuffer = indexBuffer;
00332             }
00333         }
00334         dest->indexCount = indexCount;
00335         dest->indexStart = indexStart;
00336         return dest;
00337     }
00338 
00339 }

Copyright © 2002-2003 by The OGRE Team
Last modified Fri May 14 23:22:54 2004