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

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

Copyright © 2002-2003 by The OGRE Team
Last modified Sun Nov 28 19:48:15 2004