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