[1] | 1 | /* |
---|
| 2 | ----------------------------------------------------------------------------- |
---|
| 3 | This source file is part of OGRE |
---|
| 4 | (Object-oriented Graphics Rendering Engine) |
---|
| 5 | For the latest info, see http://www.ogre3d.org/ |
---|
| 6 | |
---|
| 7 | Copyright (c) 2000-2006 Torus Knot Software Ltd |
---|
| 8 | Also see acknowledgements in Readme.html |
---|
| 9 | |
---|
| 10 | This program is free software; you can redistribute it and/or modify it under |
---|
| 11 | the terms of the GNU Lesser General Public License as published by the Free Software |
---|
| 12 | Foundation; either version 2 of the License, or (at your option) any later |
---|
| 13 | version. |
---|
| 14 | |
---|
| 15 | This program is distributed in the hope that it will be useful, but WITHOUT |
---|
| 16 | ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
---|
| 17 | FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. |
---|
| 18 | |
---|
| 19 | You should have received a copy of the GNU Lesser General Public License along with |
---|
| 20 | this program; if not, write to the Free Software Foundation, Inc., 59 Temple |
---|
| 21 | Place - Suite 330, Boston, MA 02111-1307, USA, or go to |
---|
| 22 | http://www.gnu.org/copyleft/lesser.txt. |
---|
| 23 | |
---|
| 24 | You may alternatively use this source under the terms of a specific version of |
---|
| 25 | the OGRE Unrestricted License provided you have obtained such a license from |
---|
| 26 | Torus Knot Software Ltd. |
---|
| 27 | ----------------------------------------------------------------------------- |
---|
| 28 | */ |
---|
| 29 | #include "OgreStableHeaders.h" |
---|
| 30 | #include "OgreVertexIndexData.h" |
---|
| 31 | #include "OgreHardwareBufferManager.h" |
---|
| 32 | #include "OgreHardwareVertexBuffer.h" |
---|
| 33 | #include "OgreHardwareIndexBuffer.h" |
---|
| 34 | #include "OgreVector3.h" |
---|
| 35 | #include "OgreAxisAlignedBox.h" |
---|
| 36 | #include "OgreRoot.h" |
---|
| 37 | #include "OgreRenderSystem.h" |
---|
| 38 | #include "OgreException.h" |
---|
| 39 | |
---|
| 40 | namespace Ogre { |
---|
| 41 | |
---|
| 42 | //----------------------------------------------------------------------- |
---|
| 43 | VertexData::VertexData() |
---|
| 44 | { |
---|
| 45 | vertexBufferBinding = HardwareBufferManager::getSingleton(). |
---|
| 46 | createVertexBufferBinding(); |
---|
| 47 | vertexDeclaration = HardwareBufferManager::getSingleton(). |
---|
| 48 | createVertexDeclaration(); |
---|
| 49 | vertexCount = 0; |
---|
| 50 | vertexStart = 0; |
---|
| 51 | hwAnimDataItemsUsed = 0; |
---|
| 52 | |
---|
| 53 | } |
---|
| 54 | //----------------------------------------------------------------------- |
---|
| 55 | VertexData::~VertexData() |
---|
| 56 | { |
---|
| 57 | HardwareBufferManager::getSingleton(). |
---|
| 58 | destroyVertexBufferBinding(vertexBufferBinding); |
---|
| 59 | HardwareBufferManager::getSingleton().destroyVertexDeclaration(vertexDeclaration); |
---|
| 60 | |
---|
| 61 | } |
---|
| 62 | //----------------------------------------------------------------------- |
---|
| 63 | VertexData* VertexData::clone(bool copyData) const |
---|
| 64 | { |
---|
| 65 | VertexData* dest = new VertexData(); |
---|
| 66 | |
---|
| 67 | // Copy vertex buffers in turn |
---|
| 68 | const VertexBufferBinding::VertexBufferBindingMap& bindings = |
---|
| 69 | this->vertexBufferBinding->getBindings(); |
---|
| 70 | VertexBufferBinding::VertexBufferBindingMap::const_iterator vbi, vbend; |
---|
| 71 | vbend = bindings.end(); |
---|
| 72 | for (vbi = bindings.begin(); vbi != vbend; ++vbi) |
---|
| 73 | { |
---|
| 74 | HardwareVertexBufferSharedPtr srcbuf = vbi->second; |
---|
| 75 | HardwareVertexBufferSharedPtr dstBuf; |
---|
| 76 | if (copyData) |
---|
| 77 | { |
---|
| 78 | // create new buffer with the same settings |
---|
| 79 | dstBuf = |
---|
| 80 | HardwareBufferManager::getSingleton().createVertexBuffer( |
---|
| 81 | srcbuf->getVertexSize(), srcbuf->getNumVertices(), srcbuf->getUsage(), |
---|
| 82 | srcbuf->hasShadowBuffer()); |
---|
| 83 | |
---|
| 84 | // copy data |
---|
| 85 | dstBuf->copyData(*srcbuf, 0, 0, srcbuf->getSizeInBytes(), true); |
---|
| 86 | } |
---|
| 87 | else |
---|
| 88 | { |
---|
| 89 | // don't copy, point at existing buffer |
---|
| 90 | dstBuf = srcbuf; |
---|
| 91 | } |
---|
| 92 | |
---|
| 93 | // Copy binding |
---|
| 94 | dest->vertexBufferBinding->setBinding(vbi->first, dstBuf); |
---|
| 95 | } |
---|
| 96 | |
---|
| 97 | // Basic vertex info |
---|
| 98 | dest->vertexStart = this->vertexStart; |
---|
| 99 | dest->vertexCount = this->vertexCount; |
---|
| 100 | // Copy elements |
---|
| 101 | const VertexDeclaration::VertexElementList elems = |
---|
| 102 | this->vertexDeclaration->getElements(); |
---|
| 103 | VertexDeclaration::VertexElementList::const_iterator ei, eiend; |
---|
| 104 | eiend = elems.end(); |
---|
| 105 | for (ei = elems.begin(); ei != eiend; ++ei) |
---|
| 106 | { |
---|
| 107 | dest->vertexDeclaration->addElement( |
---|
| 108 | ei->getSource(), |
---|
| 109 | ei->getOffset(), |
---|
| 110 | ei->getType(), |
---|
| 111 | ei->getSemantic(), |
---|
| 112 | ei->getIndex() ); |
---|
| 113 | } |
---|
| 114 | |
---|
| 115 | // Copy reference to hardware shadow buffer, no matter whether copy data or not |
---|
| 116 | dest->hardwareShadowVolWBuffer = hardwareShadowVolWBuffer; |
---|
| 117 | |
---|
| 118 | // copy anim data |
---|
| 119 | dest->hwAnimationDataList = hwAnimationDataList; |
---|
| 120 | dest->hwAnimDataItemsUsed = hwAnimDataItemsUsed; |
---|
| 121 | |
---|
| 122 | |
---|
| 123 | return dest; |
---|
| 124 | } |
---|
| 125 | //----------------------------------------------------------------------- |
---|
| 126 | void VertexData::prepareForShadowVolume(void) |
---|
| 127 | { |
---|
| 128 | /* NOTE |
---|
| 129 | I would dearly, dearly love to just use a 4D position buffer in order to |
---|
| 130 | store the extra 'w' value I need to differentiate between extruded and |
---|
| 131 | non-extruded sections of the buffer, so that vertex programs could use that. |
---|
| 132 | Hey, it works fine for GL. However, D3D9 in it's infinite stupidity, does not |
---|
| 133 | support 4d position vertices in the fixed-function pipeline. If you use them, |
---|
| 134 | you just see nothing. Since we can't know whether the application is going to use |
---|
| 135 | fixed function or vertex programs, we have to stick to 3d position vertices and |
---|
| 136 | store the 'w' in a separate 1D texture coordinate buffer, which is only used |
---|
| 137 | when rendering the shadow. |
---|
| 138 | */ |
---|
| 139 | |
---|
| 140 | // Upfront, lets check whether we have vertex program capability |
---|
| 141 | RenderSystem* rend = Root::getSingleton().getRenderSystem(); |
---|
| 142 | bool useVertexPrograms = false; |
---|
| 143 | if (rend && rend->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM)) |
---|
| 144 | { |
---|
| 145 | useVertexPrograms = true; |
---|
| 146 | } |
---|
| 147 | |
---|
| 148 | |
---|
| 149 | // Look for a position element |
---|
| 150 | const VertexElement* posElem = vertexDeclaration->findElementBySemantic(VES_POSITION); |
---|
| 151 | if (posElem) |
---|
| 152 | { |
---|
| 153 | size_t v; |
---|
| 154 | unsigned posOldSource = posElem->getSource(); |
---|
| 155 | |
---|
| 156 | HardwareVertexBufferSharedPtr vbuf = vertexBufferBinding->getBuffer(posOldSource); |
---|
| 157 | bool wasSharedBuffer = false; |
---|
| 158 | // Are there other elements in the buffer except for the position? |
---|
| 159 | if (vbuf->getVertexSize() > posElem->getSize()) |
---|
| 160 | { |
---|
| 161 | // We need to create another buffer to contain the remaining elements |
---|
| 162 | // Most drivers don't like gaps in the declaration, and in any case it's waste |
---|
| 163 | wasSharedBuffer = true; |
---|
| 164 | } |
---|
| 165 | HardwareVertexBufferSharedPtr newPosBuffer, newRemainderBuffer; |
---|
| 166 | if (wasSharedBuffer) |
---|
| 167 | { |
---|
| 168 | newRemainderBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( |
---|
| 169 | vbuf->getVertexSize() - posElem->getSize(), vbuf->getNumVertices(), vbuf->getUsage(), |
---|
| 170 | vbuf->hasShadowBuffer()); |
---|
| 171 | } |
---|
| 172 | // Allocate new position buffer, will be FLOAT3 and 2x the size |
---|
| 173 | size_t oldVertexCount = vbuf->getNumVertices(); |
---|
| 174 | size_t newVertexCount = oldVertexCount * 2; |
---|
| 175 | newPosBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( |
---|
| 176 | VertexElement::getTypeSize(VET_FLOAT3), newVertexCount, vbuf->getUsage(), |
---|
| 177 | vbuf->hasShadowBuffer()); |
---|
| 178 | |
---|
| 179 | // Iterate over the old buffer, copying the appropriate elements and initialising the rest |
---|
| 180 | float* pSrc; |
---|
| 181 | unsigned char *pBaseSrc = static_cast<unsigned char*>( |
---|
| 182 | vbuf->lock(HardwareBuffer::HBL_READ_ONLY)); |
---|
| 183 | // Point first destination pointer at the start of the new position buffer, |
---|
| 184 | // the other one half way along |
---|
| 185 | float *pDest = static_cast<float*>(newPosBuffer->lock(HardwareBuffer::HBL_DISCARD)); |
---|
| 186 | float* pDest2 = pDest + oldVertexCount * 3; |
---|
| 187 | |
---|
| 188 | // Precalculate any dimensions of vertex areas outside the position |
---|
| 189 | size_t prePosVertexSize = 0, postPosVertexSize, postPosVertexOffset; |
---|
| 190 | unsigned char *pBaseDestRem = 0; |
---|
| 191 | if (wasSharedBuffer) |
---|
| 192 | { |
---|
| 193 | pBaseDestRem = static_cast<unsigned char*>( |
---|
| 194 | newRemainderBuffer->lock(HardwareBuffer::HBL_DISCARD)); |
---|
| 195 | prePosVertexSize = posElem->getOffset(); |
---|
| 196 | postPosVertexOffset = prePosVertexSize + posElem->getSize(); |
---|
| 197 | postPosVertexSize = vbuf->getVertexSize() - postPosVertexOffset; |
---|
| 198 | // the 2 separate bits together should be the same size as the remainder buffer vertex |
---|
| 199 | assert (newRemainderBuffer->getVertexSize() == prePosVertexSize + postPosVertexSize); |
---|
| 200 | |
---|
| 201 | // Iterate over the vertices |
---|
| 202 | for (v = 0; v < oldVertexCount; ++v) |
---|
| 203 | { |
---|
| 204 | // Copy position, into both buffers |
---|
| 205 | posElem->baseVertexPointerToElement(pBaseSrc, &pSrc); |
---|
| 206 | *pDest++ = *pDest2++ = *pSrc++; |
---|
| 207 | *pDest++ = *pDest2++ = *pSrc++; |
---|
| 208 | *pDest++ = *pDest2++ = *pSrc++; |
---|
| 209 | |
---|
| 210 | // now deal with any other elements |
---|
| 211 | // Basically we just memcpy the vertex excluding the position |
---|
| 212 | if (prePosVertexSize > 0) |
---|
| 213 | memcpy(pBaseDestRem, pBaseSrc, prePosVertexSize); |
---|
| 214 | if (postPosVertexSize > 0) |
---|
| 215 | memcpy(pBaseDestRem + prePosVertexSize, |
---|
| 216 | pBaseSrc + postPosVertexOffset, postPosVertexSize); |
---|
| 217 | pBaseDestRem += newRemainderBuffer->getVertexSize(); |
---|
| 218 | |
---|
| 219 | pBaseSrc += vbuf->getVertexSize(); |
---|
| 220 | |
---|
| 221 | } // next vertex |
---|
| 222 | } |
---|
| 223 | else |
---|
| 224 | { |
---|
| 225 | // Unshared buffer, can block copy the whole thing |
---|
| 226 | memcpy(pDest, pBaseSrc, vbuf->getSizeInBytes()); |
---|
| 227 | memcpy(pDest2, pBaseSrc, vbuf->getSizeInBytes()); |
---|
| 228 | } |
---|
| 229 | |
---|
| 230 | vbuf->unlock(); |
---|
| 231 | newPosBuffer->unlock(); |
---|
| 232 | if (wasSharedBuffer) |
---|
| 233 | newRemainderBuffer->unlock(); |
---|
| 234 | |
---|
| 235 | // At this stage, he original vertex buffer is going to be destroyed |
---|
| 236 | // So we should force the deallocation of any temporary copies |
---|
| 237 | HardwareBufferManager::getSingleton()._forceReleaseBufferCopies(vbuf); |
---|
| 238 | |
---|
| 239 | if (useVertexPrograms) |
---|
| 240 | { |
---|
| 241 | // Now it's time to set up the w buffer |
---|
| 242 | hardwareShadowVolWBuffer = HardwareBufferManager::getSingleton().createVertexBuffer( |
---|
| 243 | sizeof(float), newVertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false); |
---|
| 244 | // Fill the first half with 1.0, second half with 0.0 |
---|
| 245 | pDest = static_cast<float*>( |
---|
| 246 | hardwareShadowVolWBuffer->lock(HardwareBuffer::HBL_DISCARD)); |
---|
| 247 | for (v = 0; v < oldVertexCount; ++v) |
---|
| 248 | { |
---|
| 249 | *pDest++ = 1.0f; |
---|
| 250 | } |
---|
| 251 | for (v = 0; v < oldVertexCount; ++v) |
---|
| 252 | { |
---|
| 253 | *pDest++ = 0.0f; |
---|
| 254 | } |
---|
| 255 | hardwareShadowVolWBuffer->unlock(); |
---|
| 256 | } |
---|
| 257 | |
---|
| 258 | unsigned short newPosBufferSource; |
---|
| 259 | if (wasSharedBuffer) |
---|
| 260 | { |
---|
| 261 | // Get the a new buffer binding index |
---|
| 262 | newPosBufferSource= vertexBufferBinding->getNextIndex(); |
---|
| 263 | // Re-bind the old index to the remainder buffer |
---|
| 264 | vertexBufferBinding->setBinding(posOldSource, newRemainderBuffer); |
---|
| 265 | } |
---|
| 266 | else |
---|
| 267 | { |
---|
| 268 | // We can just re-use the same source idex for the new position buffer |
---|
| 269 | newPosBufferSource = posOldSource; |
---|
| 270 | } |
---|
| 271 | // Bind the new position buffer |
---|
| 272 | vertexBufferBinding->setBinding(newPosBufferSource, newPosBuffer); |
---|
| 273 | |
---|
| 274 | // Now, alter the vertex declaration to change the position source |
---|
| 275 | // and the offsets of elements using the same buffer |
---|
| 276 | VertexDeclaration::VertexElementList::const_iterator elemi = |
---|
| 277 | vertexDeclaration->getElements().begin(); |
---|
| 278 | VertexDeclaration::VertexElementList::const_iterator elemiend = |
---|
| 279 | vertexDeclaration->getElements().end(); |
---|
| 280 | unsigned short idx; |
---|
| 281 | for(idx = 0; elemi != elemiend; ++elemi, ++idx) |
---|
| 282 | { |
---|
| 283 | if (&(*elemi) == posElem) |
---|
| 284 | { |
---|
| 285 | // Modify position to point at new position buffer |
---|
| 286 | vertexDeclaration->modifyElement( |
---|
| 287 | idx, |
---|
| 288 | newPosBufferSource, // new source buffer |
---|
| 289 | 0, // no offset now |
---|
| 290 | VET_FLOAT3, |
---|
| 291 | VES_POSITION); |
---|
| 292 | } |
---|
| 293 | else if (wasSharedBuffer && |
---|
| 294 | elemi->getSource() == posOldSource && |
---|
| 295 | elemi->getOffset() > prePosVertexSize ) |
---|
| 296 | { |
---|
| 297 | // This element came after position, remove the position's |
---|
| 298 | // size |
---|
| 299 | vertexDeclaration->modifyElement( |
---|
| 300 | idx, |
---|
| 301 | posOldSource, // same old source |
---|
| 302 | elemi->getOffset() - posElem->getSize(), // less offset now |
---|
| 303 | elemi->getType(), |
---|
| 304 | elemi->getSemantic(), |
---|
| 305 | elemi->getIndex()); |
---|
| 306 | |
---|
| 307 | } |
---|
| 308 | |
---|
| 309 | } |
---|
| 310 | |
---|
| 311 | |
---|
| 312 | // Note that we don't change vertexCount, because the other buffer(s) are still the same |
---|
| 313 | // size after all |
---|
| 314 | |
---|
| 315 | |
---|
| 316 | } |
---|
| 317 | } |
---|
| 318 | //----------------------------------------------------------------------- |
---|
| 319 | void VertexData::reorganiseBuffers(VertexDeclaration* newDeclaration, const BufferUsageList& bufferUsages) |
---|
| 320 | { |
---|
| 321 | // Firstly, close up any gaps in the buffer sources which might have arisen |
---|
| 322 | newDeclaration->closeGapsInSource(); |
---|
| 323 | |
---|
| 324 | // Build up a list of both old and new elements in each buffer |
---|
| 325 | unsigned short buf = 0; |
---|
| 326 | std::vector<void*> oldBufferLocks; |
---|
| 327 | std::vector<size_t> oldBufferVertexSizes; |
---|
| 328 | std::vector<void*> newBufferLocks; |
---|
| 329 | std::vector<size_t> newBufferVertexSizes; |
---|
| 330 | VertexBufferBinding* newBinding = |
---|
| 331 | HardwareBufferManager::getSingleton().createVertexBufferBinding(); |
---|
| 332 | const VertexBufferBinding::VertexBufferBindingMap& oldBindingMap = vertexBufferBinding->getBindings(); |
---|
| 333 | VertexBufferBinding::VertexBufferBindingMap::const_iterator itBinding; |
---|
| 334 | |
---|
| 335 | // Pre-allocate old buffer locks |
---|
| 336 | if (!oldBindingMap.empty()) |
---|
| 337 | { |
---|
| 338 | size_t count = oldBindingMap.rbegin()->first + 1; |
---|
| 339 | oldBufferLocks.resize(count); |
---|
| 340 | oldBufferVertexSizes.resize(count); |
---|
| 341 | } |
---|
| 342 | // Lock all the old buffers for reading |
---|
| 343 | for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding) |
---|
| 344 | { |
---|
| 345 | assert(itBinding->second->getNumVertices() >= vertexCount); |
---|
| 346 | |
---|
| 347 | oldBufferVertexSizes[itBinding->first] = |
---|
| 348 | itBinding->second->getVertexSize(); |
---|
| 349 | oldBufferLocks[itBinding->first] = |
---|
| 350 | itBinding->second->lock( |
---|
| 351 | HardwareBuffer::HBL_READ_ONLY); |
---|
| 352 | } |
---|
| 353 | |
---|
| 354 | // Create new buffers and lock all for writing |
---|
| 355 | buf = 0; |
---|
| 356 | while (!newDeclaration->findElementsBySource(buf).empty()) |
---|
| 357 | { |
---|
| 358 | size_t vertexSize = newDeclaration->getVertexSize(buf); |
---|
| 359 | |
---|
| 360 | HardwareVertexBufferSharedPtr vbuf = |
---|
| 361 | HardwareBufferManager::getSingleton().createVertexBuffer( |
---|
| 362 | vertexSize, |
---|
| 363 | vertexCount, |
---|
| 364 | bufferUsages[buf]); |
---|
| 365 | newBinding->setBinding(buf, vbuf); |
---|
| 366 | |
---|
| 367 | newBufferVertexSizes.push_back(vertexSize); |
---|
| 368 | newBufferLocks.push_back( |
---|
| 369 | vbuf->lock(HardwareBuffer::HBL_DISCARD)); |
---|
| 370 | buf++; |
---|
| 371 | } |
---|
| 372 | |
---|
| 373 | // Map from new to old elements |
---|
| 374 | typedef std::map<const VertexElement*, const VertexElement*> NewToOldElementMap; |
---|
| 375 | NewToOldElementMap newToOldElementMap; |
---|
| 376 | const VertexDeclaration::VertexElementList& newElemList = newDeclaration->getElements(); |
---|
| 377 | VertexDeclaration::VertexElementList::const_iterator ei, eiend; |
---|
| 378 | eiend = newElemList.end(); |
---|
| 379 | for (ei = newElemList.begin(); ei != eiend; ++ei) |
---|
| 380 | { |
---|
| 381 | // Find corresponding old element |
---|
| 382 | const VertexElement* oldElem = |
---|
| 383 | vertexDeclaration->findElementBySemantic( |
---|
| 384 | (*ei).getSemantic(), (*ei).getIndex()); |
---|
| 385 | if (!oldElem) |
---|
| 386 | { |
---|
| 387 | // Error, cannot create new elements with this method |
---|
| 388 | OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, |
---|
| 389 | "Element not found in old vertex declaration", |
---|
| 390 | "VertexData::reorganiseBuffers"); |
---|
| 391 | } |
---|
| 392 | newToOldElementMap[&(*ei)] = oldElem; |
---|
| 393 | } |
---|
| 394 | // Now iterate over the new buffers, pulling data out of the old ones |
---|
| 395 | // For each vertex |
---|
| 396 | for (size_t v = 0; v < vertexCount; ++v) |
---|
| 397 | { |
---|
| 398 | // For each (new) element |
---|
| 399 | for (ei = newElemList.begin(); ei != eiend; ++ei) |
---|
| 400 | { |
---|
| 401 | const VertexElement* newElem = &(*ei); |
---|
| 402 | NewToOldElementMap::iterator noi = newToOldElementMap.find(newElem); |
---|
| 403 | const VertexElement* oldElem = noi->second; |
---|
| 404 | unsigned short oldBufferNo = oldElem->getSource(); |
---|
| 405 | unsigned short newBufferNo = newElem->getSource(); |
---|
| 406 | void* pSrcBase = static_cast<void*>( |
---|
| 407 | static_cast<unsigned char*>(oldBufferLocks[oldBufferNo]) |
---|
| 408 | + v * oldBufferVertexSizes[oldBufferNo]); |
---|
| 409 | void* pDstBase = static_cast<void*>( |
---|
| 410 | static_cast<unsigned char*>(newBufferLocks[newBufferNo]) |
---|
| 411 | + v * newBufferVertexSizes[newBufferNo]); |
---|
| 412 | void *pSrc, *pDst; |
---|
| 413 | oldElem->baseVertexPointerToElement(pSrcBase, &pSrc); |
---|
| 414 | newElem->baseVertexPointerToElement(pDstBase, &pDst); |
---|
| 415 | |
---|
| 416 | memcpy(pDst, pSrc, newElem->getSize()); |
---|
| 417 | |
---|
| 418 | } |
---|
| 419 | } |
---|
| 420 | |
---|
| 421 | // Unlock all buffers |
---|
| 422 | for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding) |
---|
| 423 | { |
---|
| 424 | itBinding->second->unlock(); |
---|
| 425 | } |
---|
| 426 | for (buf = 0; buf < newBinding->getBufferCount(); ++buf) |
---|
| 427 | { |
---|
| 428 | newBinding->getBuffer(buf)->unlock(); |
---|
| 429 | } |
---|
| 430 | |
---|
| 431 | // Delete old binding & declaration |
---|
| 432 | HardwareBufferManager::getSingleton(). |
---|
| 433 | destroyVertexBufferBinding(vertexBufferBinding); |
---|
| 434 | HardwareBufferManager::getSingleton().destroyVertexDeclaration(vertexDeclaration); |
---|
| 435 | |
---|
| 436 | // Assign new binding and declaration |
---|
| 437 | vertexDeclaration = newDeclaration; |
---|
| 438 | vertexBufferBinding = newBinding; |
---|
| 439 | |
---|
| 440 | } |
---|
| 441 | //----------------------------------------------------------------------- |
---|
| 442 | void VertexData::reorganiseBuffers(VertexDeclaration* newDeclaration) |
---|
| 443 | { |
---|
| 444 | // Derive the buffer usages from looking at where the source has come |
---|
| 445 | // from |
---|
| 446 | BufferUsageList usages; |
---|
| 447 | for (unsigned short b = 0; b <= newDeclaration->getMaxSource(); ++b) |
---|
| 448 | { |
---|
| 449 | VertexDeclaration::VertexElementList destElems = newDeclaration->findElementsBySource(b); |
---|
| 450 | // Initialise with most restrictive version |
---|
| 451 | // (not really a usable option, but these flags will be removed) |
---|
| 452 | HardwareBuffer::Usage final = static_cast<HardwareBuffer::Usage>( |
---|
| 453 | HardwareBuffer::HBU_STATIC_WRITE_ONLY | HardwareBuffer::HBU_DISCARDABLE); |
---|
| 454 | VertexDeclaration::VertexElementList::iterator v; |
---|
| 455 | for (v = destElems.begin(); v != destElems.end(); ++v) |
---|
| 456 | { |
---|
| 457 | VertexElement& destelem = *v; |
---|
| 458 | // get source |
---|
| 459 | const VertexElement* srcelem = |
---|
| 460 | vertexDeclaration->findElementBySemantic( |
---|
| 461 | destelem.getSemantic(), destelem.getIndex()); |
---|
| 462 | // get buffer |
---|
| 463 | HardwareVertexBufferSharedPtr srcbuf = |
---|
| 464 | vertexBufferBinding->getBuffer(srcelem->getSource()); |
---|
| 465 | // improve flexibility only |
---|
| 466 | if (srcbuf->getUsage() & HardwareBuffer::HBU_DYNAMIC) |
---|
| 467 | { |
---|
| 468 | // remove static |
---|
| 469 | final = static_cast<HardwareBuffer::Usage>( |
---|
| 470 | final & ~HardwareBuffer::HBU_STATIC); |
---|
| 471 | // add dynamic |
---|
| 472 | final = static_cast<HardwareBuffer::Usage>( |
---|
| 473 | final | HardwareBuffer::HBU_DYNAMIC); |
---|
| 474 | } |
---|
| 475 | if (!(srcbuf->getUsage() & HardwareBuffer::HBU_WRITE_ONLY)) |
---|
| 476 | { |
---|
| 477 | // remove write only |
---|
| 478 | final = static_cast<HardwareBuffer::Usage>( |
---|
| 479 | final & ~HardwareBuffer::HBU_WRITE_ONLY); |
---|
| 480 | } |
---|
| 481 | if (!(srcbuf->getUsage() & HardwareBuffer::HBU_DISCARDABLE)) |
---|
| 482 | { |
---|
| 483 | // remove discardable |
---|
| 484 | final = static_cast<HardwareBuffer::Usage>( |
---|
| 485 | final & ~HardwareBuffer::HBU_DISCARDABLE); |
---|
| 486 | } |
---|
| 487 | |
---|
| 488 | } |
---|
| 489 | usages.push_back(final); |
---|
| 490 | } |
---|
| 491 | // Call specific method |
---|
| 492 | reorganiseBuffers(newDeclaration, usages); |
---|
| 493 | |
---|
| 494 | } |
---|
| 495 | //----------------------------------------------------------------------- |
---|
| 496 | void VertexData::closeGapsInBindings(void) |
---|
| 497 | { |
---|
| 498 | if (!vertexBufferBinding->hasGaps()) |
---|
| 499 | return; |
---|
| 500 | |
---|
| 501 | // Check for error first |
---|
| 502 | const VertexDeclaration::VertexElementList& allelems = |
---|
| 503 | vertexDeclaration->getElements(); |
---|
| 504 | VertexDeclaration::VertexElementList::const_iterator ai; |
---|
| 505 | for (ai = allelems.begin(); ai != allelems.end(); ++ai) |
---|
| 506 | { |
---|
| 507 | const VertexElement& elem = *ai; |
---|
| 508 | if (!vertexBufferBinding->isBufferBound(elem.getSource())) |
---|
| 509 | { |
---|
| 510 | OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, |
---|
| 511 | "No buffer is bound to that element source.", |
---|
| 512 | "VertexData::closeGapsInBindings"); |
---|
| 513 | } |
---|
| 514 | } |
---|
| 515 | |
---|
| 516 | // Close gaps in the vertex buffer bindings |
---|
| 517 | VertexBufferBinding::BindingIndexMap bindingIndexMap; |
---|
| 518 | vertexBufferBinding->closeGaps(bindingIndexMap); |
---|
| 519 | |
---|
| 520 | // Modify vertex elements to reference to new buffer index |
---|
| 521 | unsigned short elemIndex = 0; |
---|
| 522 | for (ai = allelems.begin(); ai != allelems.end(); ++ai, ++elemIndex) |
---|
| 523 | { |
---|
| 524 | const VertexElement& elem = *ai; |
---|
| 525 | VertexBufferBinding::BindingIndexMap::const_iterator it = |
---|
| 526 | bindingIndexMap.find(elem.getSource()); |
---|
| 527 | assert(it != bindingIndexMap.end()); |
---|
| 528 | ushort targetSource = it->second; |
---|
| 529 | if (elem.getSource() != targetSource) |
---|
| 530 | { |
---|
| 531 | vertexDeclaration->modifyElement(elemIndex, |
---|
| 532 | targetSource, elem.getOffset(), elem.getType(), |
---|
| 533 | elem.getSemantic(), elem.getIndex()); |
---|
| 534 | } |
---|
| 535 | } |
---|
| 536 | } |
---|
| 537 | //----------------------------------------------------------------------- |
---|
| 538 | void VertexData::removeUnusedBuffers(void) |
---|
| 539 | { |
---|
| 540 | std::set<ushort> usedBuffers; |
---|
| 541 | |
---|
| 542 | // Collect used buffers |
---|
| 543 | const VertexDeclaration::VertexElementList& allelems = |
---|
| 544 | vertexDeclaration->getElements(); |
---|
| 545 | VertexDeclaration::VertexElementList::const_iterator ai; |
---|
| 546 | for (ai = allelems.begin(); ai != allelems.end(); ++ai) |
---|
| 547 | { |
---|
| 548 | const VertexElement& elem = *ai; |
---|
| 549 | usedBuffers.insert(elem.getSource()); |
---|
| 550 | } |
---|
| 551 | |
---|
| 552 | // Unset unused buffer bindings |
---|
| 553 | ushort count = vertexBufferBinding->getLastBoundIndex(); |
---|
| 554 | for (ushort index = 0; index < count; ++index) |
---|
| 555 | { |
---|
| 556 | if (usedBuffers.find(index) == usedBuffers.end() && |
---|
| 557 | vertexBufferBinding->isBufferBound(index)) |
---|
| 558 | { |
---|
| 559 | vertexBufferBinding->unsetBinding(index); |
---|
| 560 | } |
---|
| 561 | } |
---|
| 562 | |
---|
| 563 | // Close gaps |
---|
| 564 | closeGapsInBindings(); |
---|
| 565 | } |
---|
| 566 | //----------------------------------------------------------------------- |
---|
| 567 | void VertexData::convertPackedColour( |
---|
| 568 | VertexElementType srcType, VertexElementType destType) |
---|
| 569 | { |
---|
| 570 | if (destType != VET_COLOUR_ABGR && destType != VET_COLOUR_ARGB) |
---|
| 571 | { |
---|
| 572 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 573 | "Invalid destType parameter", "VertexData::convertPackedColour"); |
---|
| 574 | } |
---|
| 575 | if (srcType != VET_COLOUR_ABGR && srcType != VET_COLOUR_ARGB) |
---|
| 576 | { |
---|
| 577 | OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, |
---|
| 578 | "Invalid srcType parameter", "VertexData::convertPackedColour"); |
---|
| 579 | } |
---|
| 580 | |
---|
| 581 | const VertexBufferBinding::VertexBufferBindingMap& bindMap = |
---|
| 582 | vertexBufferBinding->getBindings(); |
---|
| 583 | VertexBufferBinding::VertexBufferBindingMap::const_iterator bindi; |
---|
| 584 | for (bindi = bindMap.begin(); bindi != bindMap.end(); ++bindi) |
---|
| 585 | { |
---|
| 586 | VertexDeclaration::VertexElementList elems = |
---|
| 587 | vertexDeclaration->findElementsBySource(bindi->first); |
---|
| 588 | bool conversionNeeded = false; |
---|
| 589 | VertexDeclaration::VertexElementList::iterator elemi; |
---|
| 590 | for (elemi = elems.begin(); elemi != elems.end(); ++elemi) |
---|
| 591 | { |
---|
| 592 | VertexElement& elem = *elemi; |
---|
| 593 | if (elem.getType() == VET_COLOUR || |
---|
| 594 | ((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB) |
---|
| 595 | && elem.getType() != destType)) |
---|
| 596 | { |
---|
| 597 | conversionNeeded = true; |
---|
| 598 | } |
---|
| 599 | } |
---|
| 600 | |
---|
| 601 | if (conversionNeeded) |
---|
| 602 | { |
---|
| 603 | void* pBase = bindi->second->lock(HardwareBuffer::HBL_NORMAL); |
---|
| 604 | |
---|
| 605 | for (size_t v = 0; v < bindi->second->getNumVertices(); ++v) |
---|
| 606 | { |
---|
| 607 | |
---|
| 608 | for (elemi = elems.begin(); elemi != elems.end(); ++elemi) |
---|
| 609 | { |
---|
| 610 | VertexElement& elem = *elemi; |
---|
| 611 | VertexElementType currType = (elem.getType() == VET_COLOUR) ? |
---|
| 612 | srcType : elem.getType(); |
---|
| 613 | if (elem.getType() == VET_COLOUR || |
---|
| 614 | ((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB) |
---|
| 615 | && elem.getType() != destType)) |
---|
| 616 | { |
---|
| 617 | uint32* pRGBA; |
---|
| 618 | elem.baseVertexPointerToElement(pBase, &pRGBA); |
---|
| 619 | VertexElement::convertColourValue(currType, destType, pRGBA); |
---|
| 620 | } |
---|
| 621 | } |
---|
| 622 | pBase = static_cast<void*>( |
---|
| 623 | static_cast<char*>(pBase) + bindi->second->getVertexSize()); |
---|
| 624 | } |
---|
| 625 | bindi->second->unlock(); |
---|
| 626 | |
---|
| 627 | // Modify the elements to reflect the changed type |
---|
| 628 | const VertexDeclaration::VertexElementList& allelems = |
---|
| 629 | vertexDeclaration->getElements(); |
---|
| 630 | VertexDeclaration::VertexElementList::const_iterator ai; |
---|
| 631 | unsigned short elemIndex = 0; |
---|
| 632 | for (ai = allelems.begin(); ai != allelems.end(); ++ai, ++elemIndex) |
---|
| 633 | { |
---|
| 634 | const VertexElement& elem = *ai; |
---|
| 635 | if (elem.getType() == VET_COLOUR || |
---|
| 636 | ((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB) |
---|
| 637 | && elem.getType() != destType)) |
---|
| 638 | { |
---|
| 639 | vertexDeclaration->modifyElement(elemIndex, |
---|
| 640 | elem.getSource(), elem.getOffset(), destType, |
---|
| 641 | elem.getSemantic(), elem.getIndex()); |
---|
| 642 | } |
---|
| 643 | } |
---|
| 644 | |
---|
| 645 | } |
---|
| 646 | |
---|
| 647 | |
---|
| 648 | } // each buffer |
---|
| 649 | |
---|
| 650 | |
---|
| 651 | } |
---|
| 652 | //----------------------------------------------------------------------- |
---|
| 653 | void VertexData::allocateHardwareAnimationElements(ushort count) |
---|
| 654 | { |
---|
| 655 | // Find first free texture coord set |
---|
| 656 | unsigned short texCoord = 0; |
---|
| 657 | const VertexDeclaration::VertexElementList& vel = vertexDeclaration->getElements(); |
---|
| 658 | for (VertexDeclaration::VertexElementList::const_iterator i = vel.begin(); |
---|
| 659 | i != vel.end(); ++i) |
---|
| 660 | { |
---|
| 661 | const VertexElement& el = *i; |
---|
| 662 | if (el.getSemantic() == VES_TEXTURE_COORDINATES) |
---|
| 663 | { |
---|
| 664 | ++texCoord; |
---|
| 665 | } |
---|
| 666 | } |
---|
| 667 | assert(texCoord <= OGRE_MAX_TEXTURE_COORD_SETS); |
---|
| 668 | |
---|
| 669 | // Increase to correct size |
---|
| 670 | for (size_t c = hwAnimationDataList.size(); c < count; ++c) |
---|
| 671 | { |
---|
| 672 | // Create a new 3D texture coordinate set |
---|
| 673 | HardwareAnimationData data; |
---|
| 674 | data.targetVertexElement = &(vertexDeclaration->addElement( |
---|
| 675 | vertexBufferBinding->getNextIndex(), 0, VET_FLOAT3, VES_TEXTURE_COORDINATES, texCoord++)); |
---|
| 676 | |
---|
| 677 | hwAnimationDataList.push_back(data); |
---|
| 678 | // Vertex buffer will not be bound yet, we expect this to be done by the |
---|
| 679 | // caller when it becomes appropriate (e.g. through a VertexAnimationTrack) |
---|
| 680 | } |
---|
| 681 | } |
---|
| 682 | //----------------------------------------------------------------------- |
---|
| 683 | //----------------------------------------------------------------------- |
---|
| 684 | IndexData::IndexData() |
---|
| 685 | { |
---|
| 686 | indexCount = 0; |
---|
| 687 | indexStart = 0; |
---|
| 688 | |
---|
| 689 | } |
---|
| 690 | //----------------------------------------------------------------------- |
---|
| 691 | IndexData::~IndexData() |
---|
| 692 | { |
---|
| 693 | } |
---|
| 694 | //----------------------------------------------------------------------- |
---|
| 695 | IndexData* IndexData::clone(bool copyData) const |
---|
| 696 | { |
---|
| 697 | IndexData* dest = new IndexData(); |
---|
| 698 | if (indexBuffer.get()) |
---|
| 699 | { |
---|
| 700 | if (copyData) |
---|
| 701 | { |
---|
| 702 | dest->indexBuffer = HardwareBufferManager::getSingleton(). |
---|
| 703 | createIndexBuffer(indexBuffer->getType(), indexBuffer->getNumIndexes(), |
---|
| 704 | indexBuffer->getUsage(), indexBuffer->hasShadowBuffer()); |
---|
| 705 | dest->indexBuffer->copyData(*indexBuffer, 0, 0, indexBuffer->getSizeInBytes(), true); |
---|
| 706 | } |
---|
| 707 | else |
---|
| 708 | { |
---|
| 709 | dest->indexBuffer = indexBuffer; |
---|
| 710 | } |
---|
| 711 | } |
---|
| 712 | dest->indexCount = indexCount; |
---|
| 713 | dest->indexStart = indexStart; |
---|
| 714 | return dest; |
---|
| 715 | } |
---|
| 716 | //----------------------------------------------------------------------- |
---|
| 717 | //----------------------------------------------------------------------- |
---|
| 718 | // Local Utility class for vertex cache optimizer |
---|
| 719 | class Triangle |
---|
| 720 | { |
---|
| 721 | public: |
---|
| 722 | enum EdgeMatchType { |
---|
| 723 | AB, BC, CA, ANY, NONE |
---|
| 724 | }; |
---|
| 725 | |
---|
| 726 | uint32 a, b, c; |
---|
| 727 | |
---|
| 728 | inline Triangle() |
---|
| 729 | { |
---|
| 730 | } |
---|
| 731 | |
---|
| 732 | inline Triangle( uint32 ta, uint32 tb, uint32 tc ) |
---|
| 733 | : a( ta ), b( tb ), c( tc ) |
---|
| 734 | { |
---|
| 735 | } |
---|
| 736 | |
---|
| 737 | inline Triangle( uint32 t[3] ) |
---|
| 738 | : a( t[0] ), b( t[1] ), c( t[2] ) |
---|
| 739 | { |
---|
| 740 | } |
---|
| 741 | |
---|
| 742 | inline Triangle( const Triangle& t ) |
---|
| 743 | : a( t.a ), b( t.b ), c( t.c ) |
---|
| 744 | { |
---|
| 745 | } |
---|
| 746 | |
---|
| 747 | inline bool sharesEdge(const Triangle& t) const |
---|
| 748 | { |
---|
| 749 | return( a == t.a && b == t.c || |
---|
| 750 | a == t.b && b == t.a || |
---|
| 751 | a == t.c && b == t.b || |
---|
| 752 | b == t.a && c == t.c || |
---|
| 753 | b == t.b && c == t.a || |
---|
| 754 | b == t.c && c == t.b || |
---|
| 755 | c == t.a && a == t.c || |
---|
| 756 | c == t.b && a == t.a || |
---|
| 757 | c == t.c && a == t.b ); |
---|
| 758 | } |
---|
| 759 | |
---|
| 760 | inline bool sharesEdge(const uint32 ea, const uint32 eb, const Triangle& t) const |
---|
| 761 | { |
---|
| 762 | return( ea == t.a && eb == t.c || |
---|
| 763 | ea == t.b && eb == t.a || |
---|
| 764 | ea == t.c && eb == t.b ); |
---|
| 765 | } |
---|
| 766 | |
---|
| 767 | inline bool sharesEdge(const EdgeMatchType edge, const Triangle& t) const |
---|
| 768 | { |
---|
| 769 | if (edge == AB) |
---|
| 770 | return sharesEdge(a, b, t); |
---|
| 771 | else if (edge == BC) |
---|
| 772 | return sharesEdge(b, c, t); |
---|
| 773 | else if (edge == CA) |
---|
| 774 | return sharesEdge(c, a, t); |
---|
| 775 | else |
---|
| 776 | return (edge == ANY) == sharesEdge(t); |
---|
| 777 | } |
---|
| 778 | |
---|
| 779 | inline EdgeMatchType endoSharedEdge(const Triangle& t) const |
---|
| 780 | { |
---|
| 781 | if (sharesEdge(a, b, t)) return AB; |
---|
| 782 | if (sharesEdge(b, c, t)) return BC; |
---|
| 783 | if (sharesEdge(c, a, t)) return CA; |
---|
| 784 | return NONE; |
---|
| 785 | } |
---|
| 786 | |
---|
| 787 | inline EdgeMatchType exoSharedEdge(const Triangle& t) const |
---|
| 788 | { |
---|
| 789 | return t.endoSharedEdge(*this); |
---|
| 790 | } |
---|
| 791 | |
---|
| 792 | inline void shiftClockwise() |
---|
| 793 | { |
---|
| 794 | uint32 t = a; |
---|
| 795 | a = c; |
---|
| 796 | c = b; |
---|
| 797 | b = t; |
---|
| 798 | } |
---|
| 799 | |
---|
| 800 | inline void shiftCounterClockwise() |
---|
| 801 | { |
---|
| 802 | uint32 t = a; |
---|
| 803 | a = b; |
---|
| 804 | b = c; |
---|
| 805 | c = t; |
---|
| 806 | } |
---|
| 807 | }; |
---|
| 808 | //----------------------------------------------------------------------- |
---|
| 809 | //----------------------------------------------------------------------- |
---|
| 810 | void IndexData::optimiseVertexCacheTriList(void) |
---|
| 811 | { |
---|
| 812 | if (indexBuffer->isLocked()) return; |
---|
| 813 | |
---|
| 814 | void *buffer = indexBuffer->lock(HardwareBuffer::HBL_NORMAL); |
---|
| 815 | |
---|
| 816 | Triangle* triangles; |
---|
| 817 | uint32 *dest; |
---|
| 818 | |
---|
| 819 | size_t nIndexes = indexCount; |
---|
| 820 | size_t nTriangles = nIndexes / 3; |
---|
| 821 | size_t i, j; |
---|
| 822 | uint16 *source; |
---|
| 823 | |
---|
| 824 | if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT) |
---|
| 825 | { |
---|
| 826 | triangles = new Triangle[nTriangles]; |
---|
| 827 | source = (uint16 *)buffer; |
---|
| 828 | dest = (uint32 *)triangles; |
---|
| 829 | for (i = 0; i < nIndexes; ++i) dest[i] = source[i]; |
---|
| 830 | } |
---|
| 831 | else |
---|
| 832 | triangles = (Triangle*)buffer; |
---|
| 833 | |
---|
| 834 | // sort triangles based on shared edges |
---|
| 835 | uint32 *destlist = new uint32[nTriangles]; |
---|
| 836 | unsigned char *visited = new unsigned char[nTriangles]; |
---|
| 837 | |
---|
| 838 | for (i = 0; i < nTriangles; ++i) visited[i] = 0; |
---|
| 839 | |
---|
| 840 | uint32 start = 0, ti = 0, destcount = 0; |
---|
| 841 | |
---|
| 842 | bool found = false; |
---|
| 843 | for (i = 0; i < nTriangles; ++i) |
---|
| 844 | { |
---|
| 845 | if (found) |
---|
| 846 | found = false; |
---|
| 847 | else |
---|
| 848 | { |
---|
| 849 | while (visited[start++]); |
---|
| 850 | ti = start - 1; |
---|
| 851 | } |
---|
| 852 | |
---|
| 853 | destlist[destcount++] = ti; |
---|
| 854 | visited[ti] = 1; |
---|
| 855 | |
---|
| 856 | for (j = start; j < nTriangles; ++j) |
---|
| 857 | { |
---|
| 858 | if (visited[j]) continue; |
---|
| 859 | |
---|
| 860 | if (triangles[ti].sharesEdge(triangles[j])) |
---|
| 861 | { |
---|
| 862 | found = true; |
---|
| 863 | ti = static_cast<uint32>(j); |
---|
| 864 | break; |
---|
| 865 | } |
---|
| 866 | } |
---|
| 867 | } |
---|
| 868 | |
---|
| 869 | if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT) |
---|
| 870 | { |
---|
| 871 | // reorder the indexbuffer |
---|
| 872 | j = 0; |
---|
| 873 | for (i = 0; i < nTriangles; ++i) |
---|
| 874 | { |
---|
| 875 | Triangle *t = &triangles[destlist[i]]; |
---|
| 876 | source[j++] = t->a; |
---|
| 877 | source[j++] = t->b; |
---|
| 878 | source[j++] = t->c; |
---|
| 879 | } |
---|
| 880 | delete[] triangles; |
---|
| 881 | } |
---|
| 882 | else |
---|
| 883 | { |
---|
| 884 | uint32 *reflist = new uint32[nTriangles]; |
---|
| 885 | |
---|
| 886 | // fill the referencebuffer |
---|
| 887 | for (i = 0; i < nTriangles; ++i) |
---|
| 888 | reflist[destlist[i]] = static_cast<uint32>(i); |
---|
| 889 | |
---|
| 890 | // reorder the indexbuffer |
---|
| 891 | for (i = 0; i < nTriangles; ++i) |
---|
| 892 | { |
---|
| 893 | j = destlist[i]; |
---|
| 894 | if (i == j) continue; // do not move triangle |
---|
| 895 | |
---|
| 896 | // swap triangles |
---|
| 897 | |
---|
| 898 | Triangle t = triangles[i]; |
---|
| 899 | triangles[i] = triangles[j]; |
---|
| 900 | triangles[j] = t; |
---|
| 901 | |
---|
| 902 | // change reference |
---|
| 903 | destlist[reflist[i]] = static_cast<uint32>(j); |
---|
| 904 | // destlist[i] = i; // not needed, it will not be used |
---|
| 905 | } |
---|
| 906 | |
---|
| 907 | delete[] reflist; |
---|
| 908 | } |
---|
| 909 | |
---|
| 910 | delete[] destlist; |
---|
| 911 | delete[] visited; |
---|
| 912 | |
---|
| 913 | indexBuffer->unlock(); |
---|
| 914 | } |
---|
| 915 | //----------------------------------------------------------------------- |
---|
| 916 | //----------------------------------------------------------------------- |
---|
| 917 | void VertexCacheProfiler::profile(const HardwareIndexBufferSharedPtr& indexBuffer) |
---|
| 918 | { |
---|
| 919 | if (indexBuffer->isLocked()) return; |
---|
| 920 | |
---|
| 921 | uint16 *shortbuffer = (uint16 *)indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY); |
---|
| 922 | |
---|
| 923 | if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT) |
---|
| 924 | for (unsigned int i = 0; i < indexBuffer->getNumIndexes(); ++i) |
---|
| 925 | inCache(shortbuffer[i]); |
---|
| 926 | else |
---|
| 927 | { |
---|
| 928 | uint32 *buffer = (uint32 *)shortbuffer; |
---|
| 929 | for (unsigned int i = 0; i < indexBuffer->getNumIndexes(); ++i) |
---|
| 930 | inCache(buffer[i]); |
---|
| 931 | } |
---|
| 932 | |
---|
| 933 | indexBuffer->unlock(); |
---|
| 934 | } |
---|
| 935 | |
---|
| 936 | //----------------------------------------------------------------------- |
---|
| 937 | bool VertexCacheProfiler::inCache(unsigned int index) |
---|
| 938 | { |
---|
| 939 | for (unsigned int i = 0; i < buffersize; ++i) |
---|
| 940 | { |
---|
| 941 | if (index == cache[i]) |
---|
| 942 | { |
---|
| 943 | hit++; |
---|
| 944 | return true; |
---|
| 945 | } |
---|
| 946 | } |
---|
| 947 | |
---|
| 948 | miss++; |
---|
| 949 | cache[tail++] = index; |
---|
| 950 | tail %= size; |
---|
| 951 | |
---|
| 952 | if (buffersize < size) buffersize++; |
---|
| 953 | |
---|
| 954 | return false; |
---|
| 955 | } |
---|
| 956 | |
---|
| 957 | |
---|
| 958 | } |
---|