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-2002 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 00027 #include "OgreBillboardSet.h" 00028 00029 #include "OgreBillboard.h" 00030 #include "OgreMaterialManager.h" 00031 #include "OgreHardwareBufferManager.h" 00032 #include "OgreCamera.h" 00033 #include "OgreMath.h" 00034 #include "OgreSphere.h" 00035 #include "OgreRoot.h" 00036 #include "OgreException.h" 00037 #include <algorithm> 00038 00039 namespace Ogre { 00040 #define POSITION_BINDING 0 00041 #define COLOUR_BINDING 1 00042 #define TEXCOORD_BINDING 2 00043 00044 String BillboardSet::msMovableType = "BillboardSet"; 00045 //----------------------------------------------------------------------- 00046 BillboardSet::BillboardSet() : 00047 mOriginType( BBO_CENTER ), 00048 mAllDefaultSize( true ), 00049 mAutoExtendPool( true ), 00050 mFixedTextureCoords(true), 00051 mVertexData(0), 00052 mIndexData(0), 00053 mCullIndividual( false ), 00054 mBillboardType(BBT_POINT) 00055 { 00056 setDefaultDimensions( 100, 100 ); 00057 setMaterialName( "BaseWhite" ); 00058 } 00059 00060 //----------------------------------------------------------------------- 00061 BillboardSet::BillboardSet( 00062 const String& name, 00063 unsigned int poolSize ) : 00064 mName( name ), 00065 mOriginType( BBO_CENTER ), 00066 mAllDefaultSize( true ), 00067 mAutoExtendPool( true ), 00068 mFixedTextureCoords(true), 00069 mVertexData(0), 00070 mIndexData(0), 00071 mCullIndividual( false ), 00072 mBillboardType(BBT_POINT) 00073 { 00074 setDefaultDimensions( 100, 100 ); 00075 setMaterialName( "BaseWhite" ); 00076 setPoolSize( poolSize ); 00077 } 00078 //----------------------------------------------------------------------- 00079 BillboardSet::~BillboardSet() 00080 { 00081 // Free pool items 00082 BillboardPool::iterator i; 00083 for (i = mBillboardPool.begin(); i != mBillboardPool.end(); ++i) 00084 { 00085 delete *i; 00086 } 00087 00088 // Delete shared buffers 00089 if(mVertexData) 00090 delete mVertexData; 00091 if(mIndexData) 00092 delete mIndexData; 00093 } 00094 //----------------------------------------------------------------------- 00095 Billboard* BillboardSet::createBillboard( 00096 const Vector3& position, 00097 const ColourValue& colour ) 00098 { 00099 if( mFreeBillboards.empty() ) 00100 { 00101 if( mAutoExtendPool ) 00102 { 00103 setPoolSize( getPoolSize() * 2 ); 00104 } 00105 else 00106 { 00107 return 0; 00108 } 00109 } 00110 00111 // Get a new billboard 00112 Billboard* newBill = mFreeBillboards.front(); 00113 mFreeBillboards.pop_front(); 00114 mActiveBillboards.push_back(newBill); 00115 00116 newBill->setPosition(position); 00117 newBill->setColour(colour); 00118 newBill->_notifyOwner(this); 00119 00120 _updateBounds(); 00121 00122 return newBill; 00123 } 00124 00125 //----------------------------------------------------------------------- 00126 Billboard* BillboardSet::createBillboard( 00127 Real x, Real y, Real z, 00128 const ColourValue& colour ) 00129 { 00130 return createBillboard( Vector3( x, y, z ), colour ); 00131 } 00132 00133 //----------------------------------------------------------------------- 00134 int BillboardSet::getNumBillboards(void) const 00135 { 00136 return static_cast< int >( mActiveBillboards.size() ); 00137 } 00138 00139 //----------------------------------------------------------------------- 00140 void BillboardSet::clear() 00141 { 00142 // Remove all active instances 00143 mActiveBillboards.clear(); 00144 } 00145 00146 //----------------------------------------------------------------------- 00147 Billboard* BillboardSet::getBillboard( unsigned int index ) const 00148 { 00149 assert( 00150 index < mActiveBillboards.size() && 00151 "Billboard index out of bounds." ); 00152 00153 /* We can't access it directly, so we check wether it's in the first 00154 or the second half, then we start either from the beginning or the 00155 end of the list 00156 */ 00157 ActiveBillboardList::const_iterator it; 00158 if( index >= ( mActiveBillboards.size() >> 1 ) ) 00159 { 00160 index = static_cast<unsigned int>(mActiveBillboards.size()) - index; 00161 for( it = mActiveBillboards.end(); index; --index, --it ); 00162 } 00163 else 00164 { 00165 for( it = mActiveBillboards.begin(); index; --index, ++it ); 00166 } 00167 00168 return *it; 00169 } 00170 00171 //----------------------------------------------------------------------- 00172 void BillboardSet::removeBillboard(unsigned int index) 00173 { 00174 assert( 00175 index < mActiveBillboards.size() && 00176 "Billboard index out of bounds." ); 00177 00178 /* We can't access it directly, so we check wether it's in the first 00179 or the second half, then we start either from the beginning or the 00180 end of the list. 00181 We then remove the billboard form the 'used' list and add it to 00182 the 'free' list. 00183 */ 00184 ActiveBillboardList::iterator it; 00185 if( index >= ( mActiveBillboards.size() >> 1 ) ) 00186 { 00187 index = static_cast<unsigned int>(mActiveBillboards.size()) - index; 00188 for( it = mActiveBillboards.end(); index; --index, --it ); 00189 } 00190 else 00191 { 00192 for( it = mActiveBillboards.begin(); index; --index, ++it ); 00193 } 00194 00195 mFreeBillboards.push_back( *it ); 00196 mActiveBillboards.erase( it ); 00197 } 00198 00199 //----------------------------------------------------------------------- 00200 void BillboardSet::removeBillboard( Billboard* pBill ) 00201 { 00202 mActiveBillboards.remove( pBill ); 00203 mFreeBillboards.push_back( pBill ); 00204 } 00205 00206 //----------------------------------------------------------------------- 00207 void BillboardSet::setBillboardOrigin( BillboardOrigin origin ) 00208 { 00209 mOriginType = origin; 00210 } 00211 00212 //----------------------------------------------------------------------- 00213 BillboardOrigin BillboardSet::getBillboardOrigin(void) const 00214 { 00215 return mOriginType; 00216 } 00217 00218 //----------------------------------------------------------------------- 00219 void BillboardSet::setDefaultDimensions( Real width, Real height ) 00220 { 00221 mDefaultWidth = width; 00222 mDefaultHeight = height; 00223 } 00224 //----------------------------------------------------------------------- 00225 void BillboardSet::setDefaultWidth(Real width) 00226 { 00227 mDefaultWidth = width; 00228 } 00229 //----------------------------------------------------------------------- 00230 Real BillboardSet::getDefaultWidth(void) const 00231 { 00232 return mDefaultWidth; 00233 } 00234 //----------------------------------------------------------------------- 00235 void BillboardSet::setDefaultHeight(Real height) 00236 { 00237 mDefaultHeight = height; 00238 } 00239 //----------------------------------------------------------------------- 00240 Real BillboardSet::getDefaultHeight(void) const 00241 { 00242 return mDefaultHeight; 00243 } 00244 //----------------------------------------------------------------------- 00245 void BillboardSet::setMaterialName( const String& name ) 00246 { 00247 mMaterialName = name; 00248 00249 mpMaterial = static_cast<Material *>( 00250 MaterialManager::getSingleton().getByName(name) ); 00251 00252 if (!mpMaterial) 00253 Except( Exception::ERR_ITEM_NOT_FOUND, "Could not find material " + name, 00254 "BillboardSet::setMaterialName" ); 00255 00256 /* Ensure that the new material was loaded (will not load again if 00257 already loaded anyway) 00258 */ 00259 mpMaterial->load(); 00260 } 00261 00262 //----------------------------------------------------------------------- 00263 const String& BillboardSet::getMaterialName(void) const 00264 { 00265 return mMaterialName; 00266 } 00267 00268 //----------------------------------------------------------------------- 00269 void BillboardSet::_notifyCurrentCamera( Camera* cam ) 00270 { 00271 /* Generate the vertices for all the billboards relative to the camera 00272 Also take the opportunity to update the vertex colours 00273 May as well do it here to save on loops elsewhere 00274 */ 00275 00276 /* NOTE: most engines generate world coordinates for the billboards 00277 directly, taking the world axes of the camera as offsets to the 00278 center points. I take a different approach, reverse-transforming 00279 the camera world axes into local billboard space. 00280 Why? 00281 Well, it's actually more efficient this way, because I only have to 00282 reverse-transform using the billboardset world matrix (inverse) 00283 once, from then on it's simple additions (assuming identically 00284 sized billboards). If I transformed every billboard center by it's 00285 world transform, that's a matrix multiplication per billboard 00286 instead. 00287 I leave the final transform to the render pipeline since that can 00288 use hardware TnL if it is available. 00289 */ 00290 00291 /* 00292 // Min and max bounds for AABB 00293 Vector3 min( Math::POS_INFINITY, Math::POS_INFINITY, Math::POS_INFINITY ); 00294 Vector3 max( Math::NEG_INFINITY, Math::NEG_INFINITY, Math::NEG_INFINITY ); 00295 */ 00296 00297 ActiveBillboardList::iterator it; 00298 // Parametric offsets of origin 00299 Real leftOff, rightOff, topOff, bottomOff; 00300 00301 // Boundary offsets based on origin and camera orientation 00302 // Vector3 vLeftOff, vRightOff, vTopOff, vBottomOff; 00303 // Final vertex offsets, used where sizes all default to save calcs 00304 Vector3 vOffset[4]; 00305 00306 // Get offsets for origin type 00307 getParametricOffsets(leftOff, rightOff, topOff, bottomOff); 00308 // Get camera axes in billboard space 00309 Vector3 camX, camY; 00310 00311 // Generate axes etc up-front if not oriented per-billboard 00312 if (mBillboardType != BBT_ORIENTED_SELF) 00313 { 00314 genBillboardAxes(*cam, &camX, &camY); 00315 00316 /* If all billboards are the same size we can precalculate the 00317 offsets and just use '+' instead of '*' for each billboard, 00318 and it should be faster. 00319 */ 00320 genVertOffsets(leftOff, rightOff, topOff, bottomOff, 00321 mDefaultWidth, mDefaultHeight, camX, camY, vOffset); 00322 00323 } 00324 00325 // Init num visible 00326 mNumVisibleBillboards = 0; 00327 00328 HardwareVertexBufferSharedPtr vPosBuf = 00329 mVertexData->vertexBufferBinding->getBuffer(POSITION_BINDING); 00330 00331 Real* pV = static_cast<Real*>( 00332 vPosBuf->lock(HardwareBuffer::HBL_DISCARD) ); 00333 00334 HardwareVertexBufferSharedPtr vColBuf = 00335 mVertexData->vertexBufferBinding->getBuffer(COLOUR_BINDING); 00336 00337 RGBA* pC = static_cast<RGBA*>( 00338 vColBuf->lock(HardwareBuffer::HBL_DISCARD) ); 00339 00340 HardwareVertexBufferSharedPtr vTexBuf = 00341 mVertexData->vertexBufferBinding->getBuffer(TEXCOORD_BINDING); 00342 00343 Real* pT = 0; 00344 if (!mFixedTextureCoords) 00345 { 00346 pT = static_cast<Real*>( 00347 vTexBuf->lock(HardwareBuffer::HBL_DISCARD) ); 00348 } 00349 00350 if( mAllDefaultSize ) // If they're all the same size 00351 { 00352 /* No per-billboard checking, just blast through. 00353 Saves us an if clause every billboard which may 00354 make a difference. 00355 */ 00356 00357 if (mBillboardType == BBT_ORIENTED_SELF) 00358 { 00359 for( it = mActiveBillboards.begin(); 00360 it != mActiveBillboards.end(); 00361 ++it ) 00362 { 00363 // Skip if not visible (NB always true if not bounds checking individual billboards) 00364 if (!billboardVisible(cam, it)) continue; 00365 00366 // Have to generate axes & offsets per billboard 00367 genBillboardAxes(*cam, &camX, &camY, *it); 00368 genVertOffsets(leftOff, rightOff, topOff, bottomOff, 00369 mDefaultWidth, mDefaultHeight, camX, camY, vOffset); 00370 00371 genVertices(&pV, &pC, &pT, vOffset, *it); 00372 00373 // Increment visibles 00374 mNumVisibleBillboards++; 00375 } 00376 } else 00377 { 00378 for( it = mActiveBillboards.begin(); 00379 it != mActiveBillboards.end(); 00380 ++it ) 00381 { 00382 // Skip if not visible (NB always true if not bounds checking individual billboards) 00383 if (!billboardVisible(cam, it)) continue; 00384 00385 genVertices(&pV, &pC, &pT, vOffset, *it); 00386 00387 // Increment visibles 00388 mNumVisibleBillboards++; 00389 } 00390 } 00391 } 00392 else // not all default size 00393 { 00394 Vector3 vOwnOffset[4]; 00395 if (mBillboardType == BBT_ORIENTED_SELF) 00396 { 00397 for( it = mActiveBillboards.begin(); it != mActiveBillboards.end(); ++it ) 00398 { 00399 // Skip if not visible (NB always true if not bounds checking individual billboards) 00400 if (!billboardVisible(cam, it)) continue; 00401 00402 // Have to generate axes & offsets per billboard 00403 genBillboardAxes(*cam, &camX, &camY, *it); 00404 00405 // If it has own dimensions, or self-oriented, gen offsets 00406 if( (*it)->mOwnDimensions) 00407 { 00408 // Generate using own dimensions 00409 genVertOffsets(leftOff, rightOff, topOff, bottomOff, 00410 (*it)->mWidth, (*it)->mHeight, camX, camY, vOwnOffset); 00411 // Create vertex data 00412 genVertices(&pV, &pC, &pT, vOwnOffset, *it); 00413 } 00414 else // Use default dimension, already computed before the loop, for faster creation 00415 { 00416 genVertices(&pV, &pC, &pT, vOffset, *it); 00417 } 00418 00419 // Increment visibles 00420 mNumVisibleBillboards++; 00421 00422 } 00423 } else 00424 { 00425 for( it = mActiveBillboards.begin(); it != mActiveBillboards.end(); ++it ) 00426 { 00427 // Skip if not visible (NB always true if not bounds checking individual billboards) 00428 if (!billboardVisible(cam, it)) continue; 00429 00430 // If it has own dimensions, or self-oriented, gen offsets 00431 if( (*it)->mOwnDimensions) 00432 { 00433 // Generate using own dimensions 00434 genVertOffsets(leftOff, rightOff, topOff, bottomOff, 00435 (*it)->mWidth, (*it)->mHeight, camX, camY, vOwnOffset); 00436 // Create vertex data 00437 genVertices(&pV, &pC, &pT, vOwnOffset, *it); 00438 } 00439 else // Use default dimension, already computed before the loop, for faster creation 00440 { 00441 genVertices(&pV, &pC, &pT, vOffset, *it); 00442 } 00443 00444 // Increment visibles 00445 mNumVisibleBillboards++; 00446 00447 } 00448 } 00449 } 00450 00451 if (!mFixedTextureCoords) 00452 vTexBuf->unlock(); 00453 vColBuf->unlock(); 00454 vPosBuf->unlock(); 00455 00456 /* 00457 // Update bounding box limits 00458 unsigned int vertBufferSize = mNumVisibleBillboards * 4 * 3; 00459 00460 for( j = 0; j < vertBufferSize; j += 3 ) 00461 { 00462 min.makeFloor( Vector3( 00463 mpPositions[j], 00464 mpPositions[j+1], 00465 mpPositions[j+2] ) ); 00466 00467 max.makeCeil( Vector3( 00468 mpPositions[j], 00469 mpPositions[j+1], 00470 mpPositions[j+2] ) ); 00471 } 00472 00473 // Set AABB 00474 mAABB.setExtents(min, max); 00475 */ 00476 } 00477 //----------------------------------------------------------------------- 00478 void BillboardSet::_updateBounds(void) 00479 { 00480 if (mActiveBillboards.empty()) 00481 { 00482 // No billboards, null bbox 00483 mAABB.setNull(); 00484 mBoundingRadius = 0.0f; 00485 } 00486 else 00487 { 00488 Real maxSqLen = -1.0f; 00489 00490 Vector3 min(Math::POS_INFINITY, Math::POS_INFINITY, Math::POS_INFINITY); 00491 Vector3 max(Math::NEG_INFINITY, Math::NEG_INFINITY, Math::NEG_INFINITY); 00492 ActiveBillboardList::iterator i, iend; 00493 00494 iend = mActiveBillboards.end(); 00495 for (i = mActiveBillboards.begin(); i != iend; ++i) 00496 { 00497 const Vector3& pos = (*i)->getPosition(); 00498 min.makeFloor(pos); 00499 max.makeCeil(pos); 00500 00501 maxSqLen = std::max(maxSqLen, pos.squaredLength()); 00502 } 00503 // Adjust for billboard size 00504 Real adjust = std::max(mDefaultWidth, mDefaultHeight); 00505 Vector3 vecAdjust(adjust, adjust, adjust); 00506 min -= vecAdjust; 00507 max += vecAdjust; 00508 00509 mAABB.setExtents(min, max); 00510 mBoundingRadius = Math::Sqrt(maxSqLen); 00511 00512 } 00513 00514 if (mParentNode) 00515 mParentNode->needUpdate(); 00516 00517 } 00518 //----------------------------------------------------------------------- 00519 const AxisAlignedBox& BillboardSet::getBoundingBox(void) const 00520 { 00521 return mAABB; 00522 } 00523 00524 //----------------------------------------------------------------------- 00525 void BillboardSet::_updateRenderQueue(RenderQueue* queue) 00526 { 00527 queue->addRenderable(this, mRenderQueueID, RENDERABLE_DEFAULT_PRIORITY); 00528 } 00529 00530 //----------------------------------------------------------------------- 00531 Material* BillboardSet::getMaterial(void) const 00532 { 00533 return mpMaterial; 00534 } 00535 00536 //----------------------------------------------------------------------- 00537 void BillboardSet::getRenderOperation(RenderOperation& op) 00538 { 00539 op.operationType = RenderOperation::OT_TRIANGLE_LIST; 00540 op.useIndexes = true; 00541 00542 op.vertexData = mVertexData; 00543 op.vertexData->vertexCount = mNumVisibleBillboards * 4; 00544 op.vertexData->vertexStart = 0; 00545 00546 op.indexData = mIndexData; 00547 op.indexData->indexCount = mNumVisibleBillboards * 6; 00548 op.indexData->indexStart = 0; 00549 } 00550 00551 //----------------------------------------------------------------------- 00552 void BillboardSet::getWorldTransforms( Matrix4* xform ) const 00553 { 00554 *xform = _getParentNodeFullTransform(); 00555 } 00556 //----------------------------------------------------------------------- 00557 const Quaternion& BillboardSet::getWorldOrientation(void) const 00558 { 00559 return mParentNode->_getDerivedOrientation(); 00560 } 00561 //----------------------------------------------------------------------- 00562 const Vector3& BillboardSet::getWorldPosition(void) const 00563 { 00564 return mParentNode->_getDerivedPosition(); 00565 } 00566 //----------------------------------------------------------------------- 00567 void BillboardSet::setAutoextend( bool autoextend ) 00568 { 00569 mAutoExtendPool = autoextend; 00570 } 00571 00572 //----------------------------------------------------------------------- 00573 bool BillboardSet::getAutoextend(void) const 00574 { 00575 return mAutoExtendPool; 00576 } 00577 00578 //----------------------------------------------------------------------- 00579 void BillboardSet::setPoolSize( unsigned int size ) 00580 { 00581 // Never shrink below size() 00582 size_t currSize = mBillboardPool.size(); 00583 00584 if( currSize < size ) 00585 { 00586 this->increasePool(size); 00587 00588 for( size_t i = currSize; i < size; ++i ) 00589 { 00590 // Add new items to the queue 00591 mFreeBillboards.push_back( mBillboardPool[i] ); 00592 } 00593 00594 /* Allocate / reallocate vertex data 00595 Note that we allocate enough space for ALL the billboards in the pool, but only issue 00596 rendering operations for the sections relating to the active billboards 00597 */ 00598 00599 if (mVertexData) 00600 delete mVertexData; 00601 if (mIndexData) 00602 delete mIndexData; 00603 00604 /* Alloc positions ( 4 verts per billboard, 3 components ) 00605 colours ( 1 x RGBA per vertex ) 00606 indices ( 6 per billboard ( 2 tris ) ) 00607 tex. coords ( 2D coords, 4 per billboard ) 00608 */ 00609 mVertexData = new VertexData(); 00610 mIndexData = new IndexData(); 00611 00612 mVertexData->vertexCount = size * 4; 00613 mVertexData->vertexStart = 0; 00614 00615 // Vertex declaration 00616 VertexDeclaration* decl = mVertexData->vertexDeclaration; 00617 VertexBufferBinding* binding = mVertexData->vertexBufferBinding; 00618 00619 size_t offset = 0; 00620 decl->addElement(POSITION_BINDING, offset, VET_FLOAT3, VES_POSITION); 00621 //offset += VertexElement::getTypeSize(VET_FLOAT2); 00622 decl->addElement(COLOUR_BINDING, offset, VET_COLOUR, VES_DIFFUSE); 00623 decl->addElement(TEXCOORD_BINDING, 0, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0); 00624 00625 HardwareVertexBufferSharedPtr vbuf = 00626 HardwareBufferManager::getSingleton().createVertexBuffer( 00627 decl->getVertexSize(POSITION_BINDING), 00628 mVertexData->vertexCount, 00629 HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); 00630 // bind position and diffuses 00631 binding->setBinding(POSITION_BINDING, vbuf); 00632 00633 vbuf = 00634 HardwareBufferManager::getSingleton().createVertexBuffer( 00635 decl->getVertexSize(COLOUR_BINDING), 00636 mVertexData->vertexCount, 00637 HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); 00638 // bind position and diffuses 00639 binding->setBinding(COLOUR_BINDING, vbuf); 00640 00641 vbuf = 00642 HardwareBufferManager::getSingleton().createVertexBuffer( 00643 decl->getVertexSize(TEXCOORD_BINDING), 00644 mVertexData->vertexCount, 00645 HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY); 00646 // bind position 00647 binding->setBinding(TEXCOORD_BINDING, vbuf); 00648 00649 mIndexData->indexStart = 0; 00650 mIndexData->indexCount = size * 6; 00651 00652 mIndexData->indexBuffer = HardwareBufferManager::getSingleton(). 00653 createIndexBuffer(HardwareIndexBuffer::IT_16BIT, 00654 mIndexData->indexCount, 00655 HardwareBuffer::HBU_STATIC_WRITE_ONLY); 00656 00657 /* Create indexes and tex coords (will be the same every frame) 00658 Using indexes because it means 1/3 less vertex transforms (4 instead of 6) 00659 00660 Billboard layout relative to camera: 00661 00662 2-----3 00663 | /| 00664 | / | 00665 |/ | 00666 0-----1 00667 */ 00668 00669 // Create template texcoord data 00670 Real texData[8] = { 00671 0.0, 1.0, 00672 1.0, 1.0, 00673 0.0, 0.0, 00674 1.0, 0.0 }; 00675 00676 ushort* pIdx = static_cast<ushort*>( 00677 mIndexData->indexBuffer->lock(0, 00678 mIndexData->indexBuffer->getSizeInBytes(), 00679 HardwareBuffer::HBL_DISCARD) ); 00680 00681 vbuf = mVertexData->vertexBufferBinding->getBuffer(TEXCOORD_BINDING); 00682 00683 Real* pT = static_cast<Real*>( 00684 vbuf->lock(HardwareBuffer::HBL_DISCARD) ); 00685 00686 for( 00687 size_t idx, idxOff, texOff, bboard = 0; 00688 bboard < size; 00689 ++bboard ) 00690 { 00691 // Do indexes 00692 idx = bboard * 6; 00693 idxOff = bboard * 4; 00694 texOff = bboard * 4 * 2; 00695 00696 pIdx[idx] = static_cast<unsigned short>(idxOff); // + 0;, for clarity 00697 pIdx[idx+1] = static_cast<unsigned short>(idxOff + 1); 00698 pIdx[idx+2] = static_cast<unsigned short>(idxOff + 3); 00699 pIdx[idx+3] = static_cast<unsigned short>(idxOff + 0); 00700 pIdx[idx+4] = static_cast<unsigned short>(idxOff + 3); 00701 pIdx[idx+5] = static_cast<unsigned short>(idxOff + 2); 00702 00703 // Do tex coords 00704 pT[texOff] = texData[0]; 00705 pT[texOff+1] = texData[1]; 00706 pT[texOff+2] = texData[2]; 00707 pT[texOff+3] = texData[3]; 00708 pT[texOff+4] = texData[4]; 00709 pT[texOff+5] = texData[5]; 00710 pT[texOff+6] = texData[6]; 00711 pT[texOff+7] = texData[7]; 00712 } 00713 00714 vbuf->unlock(); 00715 mIndexData->indexBuffer->unlock(); 00716 } 00717 } 00718 00719 //----------------------------------------------------------------------- 00720 unsigned int BillboardSet::getPoolSize(void) const 00721 { 00722 return static_cast< unsigned int >( mBillboardPool.size() ); 00723 } 00724 00725 //----------------------------------------------------------------------- 00726 void BillboardSet::_notifyBillboardResized(void) 00727 { 00728 mAllDefaultSize = false; 00729 } 00730 00731 //----------------------------------------------------------------------- 00732 void BillboardSet::getParametricOffsets( 00733 Real& left, Real& right, Real& top, Real& bottom ) 00734 { 00735 switch( mOriginType ) 00736 { 00737 case BBO_TOP_LEFT: 00738 left = 0.0f; 00739 right = 1.0f; 00740 top = 0.0f; 00741 bottom = 1.0f; 00742 break; 00743 00744 case BBO_TOP_CENTER: 00745 left = -0.5f; 00746 right = 0.5f; 00747 top = 0.0f; 00748 bottom = 1.0f; 00749 break; 00750 00751 case BBO_TOP_RIGHT: 00752 left = -1.0f; 00753 right = 0.0f; 00754 top = 0.0f; 00755 bottom = 1.0f; 00756 break; 00757 00758 case BBO_CENTER_LEFT: 00759 left = 0.0f; 00760 right = 1.0f; 00761 top = -0.5f; 00762 bottom = 0.5f; 00763 break; 00764 00765 case BBO_CENTER: 00766 left = -0.5f; 00767 right = 0.5f; 00768 top = -0.5f; 00769 bottom = 0.5f; 00770 break; 00771 00772 case BBO_CENTER_RIGHT: 00773 left = -1.0f; 00774 right = 0.0f; 00775 top = -0.5f; 00776 bottom = 0.5f; 00777 break; 00778 00779 case BBO_BOTTOM_LEFT: 00780 left = 0.0f; 00781 right = 1.0f; 00782 top = -1.0f; 00783 bottom = 0.0f; 00784 break; 00785 00786 case BBO_BOTTOM_CENTER: 00787 left = -0.5f; 00788 right = 0.5f; 00789 top = -1.0f; 00790 bottom = 0.0f; 00791 break; 00792 00793 case BBO_BOTTOM_RIGHT: 00794 left = -1.0f; 00795 right = 0.0f; 00796 top = -1.0f; 00797 bottom = 0.0f; 00798 break; 00799 } 00800 } 00801 //----------------------------------------------------------------------- 00802 bool BillboardSet::getCullIndividually(void) const 00803 { 00804 return mCullIndividual; 00805 } 00806 //----------------------------------------------------------------------- 00807 void BillboardSet::setCullIndividually(bool cullIndividual) 00808 { 00809 mCullIndividual = cullIndividual; 00810 } 00811 //----------------------------------------------------------------------- 00812 bool BillboardSet::billboardVisible(Camera* cam, ActiveBillboardList::iterator bill) 00813 { 00814 // Return always visible if not culling individually 00815 if (!mCullIndividual) return true; 00816 00817 // Cull based on sphere (have to transform less) 00818 Sphere sph; 00819 Matrix4 xworld; 00820 00821 getWorldTransforms(&xworld); 00822 00823 sph.setCenter(xworld * (*bill)->mPosition); 00824 00825 if ((*bill)->mOwnDimensions) 00826 { 00827 sph.setRadius(std::max((*bill)->mWidth, (*bill)->mHeight)); 00828 } 00829 else 00830 { 00831 sph.setRadius(std::max(mDefaultWidth, mDefaultHeight)); 00832 } 00833 00834 return cam->isVisible(sph); 00835 00836 } 00837 //----------------------------------------------------------------------- 00838 void BillboardSet::increasePool(unsigned int size) 00839 { 00840 size_t oldSize = mBillboardPool.size(); 00841 00842 // Increase size 00843 mBillboardPool.reserve(size); 00844 mBillboardPool.resize(size); 00845 00846 // Create new billboards 00847 for( size_t i = oldSize; i < size; ++i ) 00848 mBillboardPool[i] = new Billboard(); 00849 00850 } 00851 //----------------------------------------------------------------------- 00852 void BillboardSet:: genBillboardAxes(Camera& cam, Vector3* pX, Vector3 *pY, const Billboard* pBill) 00853 { 00854 // Default behaviour is that billboards are in local node space 00855 // so orientation of camera (in world space) must be reverse-transformed 00856 // into node space to generate the axes 00857 00858 Quaternion invTransform = mParentNode->_getDerivedOrientation().Inverse(); 00859 Quaternion camQ; 00860 00861 switch (mBillboardType) 00862 { 00863 case BBT_POINT: 00864 // Get camera world axes for X and Y (depth is irrelevant) 00865 camQ = cam.getDerivedOrientation(); 00866 // Convert into billboard local space 00867 camQ = invTransform * camQ; 00868 *pX = camQ * Vector3::UNIT_X; 00869 *pY = camQ * Vector3::UNIT_Y; 00870 break; 00871 case BBT_ORIENTED_COMMON: 00872 // Y-axis is common direction 00873 // X-axis is cross with camera direction 00874 *pY = mCommonDirection; 00875 // Convert into billboard local space 00876 *pX = invTransform * cam.getDerivedDirection().crossProduct(*pY); 00877 00878 break; 00879 case BBT_ORIENTED_SELF: 00880 // Y-axis is direction 00881 // X-axis is cross with camera direction 00882 *pY = pBill->mDirection; 00883 // Convert into billboard local space 00884 *pX = invTransform * cam.getDerivedDirection().crossProduct(*pY); 00885 00886 break; 00887 } 00888 00889 } 00890 //----------------------------------------------------------------------- 00891 void BillboardSet::setBillboardType(BillboardType bbt) 00892 { 00893 mBillboardType = bbt; 00894 } 00895 //----------------------------------------------------------------------- 00896 BillboardType BillboardSet::getBillboardType(void) const 00897 { 00898 return mBillboardType; 00899 } 00900 //----------------------------------------------------------------------- 00901 void BillboardSet::setCommonDirection(const Vector3& vec) 00902 { 00903 mCommonDirection = vec; 00904 } 00905 //----------------------------------------------------------------------- 00906 const Vector3& BillboardSet::getCommonDirection(void) const 00907 { 00908 return mCommonDirection; 00909 } 00910 //----------------------------------------------------------------------- 00911 void BillboardSet::genVertices(Real **pPos, RGBA** pCol, Real **pTex, const Vector3* offsets, const Billboard* pBillboard) 00912 { 00913 // Texcoords 00914 00915 if (!mFixedTextureCoords) 00916 { 00917 // Create template texcoord data 00918 Real texData[8] = { 00919 -0.5, 0.5, 00920 0.5, 0.5, 00921 -0.5,-0.5, 00922 0.5,-0.5 }; 00923 00924 const Real rotation = pBillboard->mRotation; 00925 const Real cos_rot = Math::Cos(rotation); 00926 const Real sin_rot = Math::Sin(rotation); 00927 00928 *(*pTex)++ = (cos_rot * texData[0]) + (sin_rot * texData[1]) + 0.5; 00929 *(*pTex)++ = (sin_rot * texData[0]) - (cos_rot * texData[1]) + 0.5; 00930 00931 *(*pTex)++ = (cos_rot * texData[2]) + (sin_rot * texData[3]) + 0.5; 00932 *(*pTex)++ = (sin_rot * texData[2]) - (cos_rot * texData[3]) + 0.5; 00933 00934 *(*pTex)++ = (cos_rot * texData[4]) + (sin_rot * texData[5]) + 0.5; 00935 *(*pTex)++ = (sin_rot * texData[4]) - (cos_rot * texData[5]) + 0.5; 00936 00937 *(*pTex)++ = (cos_rot * texData[6]) + (sin_rot * texData[7]) + 0.5; 00938 *(*pTex)++ = (sin_rot * texData[6]) - (cos_rot * texData[7]) + 0.5; 00939 } 00940 00941 // Positions 00942 00943 // Left-top 00944 *(*pPos)++ = offsets[0].x + pBillboard->mPosition.x; 00945 *(*pPos)++ = offsets[0].y + pBillboard->mPosition.y; 00946 *(*pPos)++ = offsets[0].z + pBillboard->mPosition.z; 00947 // Right-top 00948 *(*pPos)++ = offsets[1].x + pBillboard->mPosition.x; 00949 *(*pPos)++ = offsets[1].y + pBillboard->mPosition.y; 00950 *(*pPos)++ = offsets[1].z + pBillboard->mPosition.z; 00951 // Left-bottom 00952 *(*pPos)++ = offsets[2].x + pBillboard->mPosition.x; 00953 *(*pPos)++ = offsets[2].y + pBillboard->mPosition.y; 00954 *(*pPos)++ = offsets[2].z + pBillboard->mPosition.z; 00955 // Right-bottom 00956 *(*pPos)++ = offsets[3].x + pBillboard->mPosition.x; 00957 *(*pPos)++ = offsets[3].y + pBillboard->mPosition.y; 00958 *(*pPos)++ = offsets[3].z + pBillboard->mPosition.z; 00959 00960 // Update colours 00961 RGBA colour; 00962 Root::getSingleton().convertColourValue(pBillboard->mColour, &colour); 00963 00964 *(*pCol)++ = colour; 00965 *(*pCol)++ = colour; 00966 *(*pCol)++ = colour; 00967 *(*pCol)++ = colour; 00968 00969 } 00970 //----------------------------------------------------------------------- 00971 void BillboardSet::genVertOffsets(Real inleft, Real inright, Real intop, Real inbottom, 00972 Real width, Real height, const Vector3& x, const Vector3& y, Vector3* pDestVec) 00973 { 00974 Vector3 vLeftOff, vRightOff, vTopOff, vBottomOff; 00975 /* Calculate default offsets. Scale the axes by 00976 parametric offset and dimensions, ready to be added to 00977 positions. 00978 */ 00979 00980 vLeftOff = x * ( inleft * width ); 00981 vRightOff = x * ( inright * width ); 00982 vTopOff = y * ( intop * height ); 00983 vBottomOff = y * ( inbottom * height ); 00984 00985 // Make final offsets to vertex positions 00986 pDestVec[0] = vLeftOff + vTopOff; 00987 pDestVec[1] = vRightOff + vTopOff; 00988 pDestVec[2] = vLeftOff + vBottomOff; 00989 pDestVec[3] = vRightOff + vBottomOff; 00990 00991 } 00992 //----------------------------------------------------------------------- 00993 const String& BillboardSet::getName(void) const 00994 { 00995 return mName; 00996 } 00997 //----------------------------------------------------------------------- 00998 const String& BillboardSet::getMovableType(void) const 00999 { 01000 return msMovableType; 01001 } 01002 //----------------------------------------------------------------------- 01003 Real BillboardSet::getSquaredViewDepth(const Camera* cam) const 01004 { 01005 assert(mParentNode); 01006 return mParentNode->getSquaredViewDepth(cam); 01007 } 01008 //----------------------------------------------------------------------- 01009 Real BillboardSet::getBoundingRadius(void) const 01010 { 01011 return mBoundingRadius; 01012 } 01013 //----------------------------------------------------------------------- 01014 const LightList& BillboardSet::getLights(void) const 01015 { 01016 // It's actually quite unlikely that this will be called, 01017 // because most billboards are unlit, but here we go anyway 01018 return mParentNode->getLights(); 01019 } 01020 01021 }
Copyright © 2002-2003 by The OGRE Team
Last modified Wed Jan 21 00:10:02 2004