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