source: OGRE/trunk/ogrenew/OgreMain/src/OgreBillboardSet.cpp @ 657

Revision 657, 35.0 KB checked in by mattausch, 19 years ago (diff)

added ogre dependencies and patched ogre sources

RevLine 
[657]1/*
2-----------------------------------------------------------------------------
3This source file is part of OGRE
4    (Object-oriented Graphics Rendering Engine)
5For the latest info, see http://www.ogre3d.org/
6
7Copyright (c) 2000-2005 The OGRE Team
8Also see acknowledgements in Readme.html
9
10This program is free software; you can redistribute it and/or modify it under
11the terms of the GNU Lesser General Public License as published by the Free Software
12Foundation; either version 2 of the License, or (at your option) any later
13version.
14
15This program is distributed in the hope that it will be useful, but WITHOUT
16ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
17FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
18
19You should have received a copy of the GNU Lesser General Public License along with
20this program; if not, write to the Free Software Foundation, Inc., 59 Temple
21Place - Suite 330, Boston, MA 02111-1307, USA, or go to
22http://www.gnu.org/copyleft/lesser.txt.
23-----------------------------------------------------------------------------
24*/
25#include "OgreStableHeaders.h"
26
27#include "OgreBillboardSet.h"
28
29#include "OgreBillboard.h"
30#include "OgreMaterialManager.h"
31#include "OgreHardwareBufferManager.h"
32#include "OgreCamera.h"
33#include "OgreMath.h"
34#include "OgreSphere.h"
35#include "OgreRoot.h"
36#include "OgreException.h"
37#include <algorithm>
38
39namespace Ogre {
40
41    String BillboardSet::msMovableType = "BillboardSet";
42    //-----------------------------------------------------------------------
43    BillboardSet::BillboardSet() :
44        mOriginType( BBO_CENTER ),
45        mAllDefaultSize( true ),
46        mAutoExtendPool( true ),
47        mFixedTextureCoords(true),
48        mWorldSpace(false),
49        mVertexData(0),
50        mIndexData(0),
51        mCullIndividual( false ),
52        mBillboardType(BBT_POINT),
53        mCommonDirection(Ogre::Vector3::UNIT_Z),
54        mBuffersCreated(false),
55        mPoolSize(0),
56        mExternalData(false)
57    {
58        setDefaultDimensions( 100, 100 );
59        setMaterialName( "BaseWhite" );
60        mCastShadows = false;
61    }
62
63    //-----------------------------------------------------------------------
64    BillboardSet::BillboardSet(
65        const String& name,
66        unsigned int poolSize,
67        bool externalData) :
68        mName( name ),
69        mOriginType( BBO_CENTER ),
70        mAllDefaultSize( true ),
71        mAutoExtendPool( true ),
72        mFixedTextureCoords(true),
73        mWorldSpace(false),
74        mVertexData(0),
75        mIndexData(0),
76        mCullIndividual( false ),
77        mBillboardType(BBT_POINT),
78        mCommonDirection(Ogre::Vector3::UNIT_Z),
79        mBuffersCreated(false),
80        mPoolSize(poolSize),
81        mExternalData(externalData)
82    {
83        setDefaultDimensions( 100, 100 );
84        setMaterialName( "BaseWhite" );
85        setPoolSize( poolSize );
86        mCastShadows = false;
87    }
88    //-----------------------------------------------------------------------
89    BillboardSet::~BillboardSet()
90    {
91        // Free pool items
92        BillboardPool::iterator i;
93        for (i = mBillboardPool.begin(); i != mBillboardPool.end(); ++i)
94        {
95            delete *i;
96        }
97
98        // Delete shared buffers
99        if(mVertexData)
100        {
101            delete mVertexData;
102            mVertexData = 0;
103        }
104           
105        if(mIndexData)
106        {
107            delete mIndexData;
108            mIndexData = 0;
109        }
110    }
111    //-----------------------------------------------------------------------
112    Billboard* BillboardSet::createBillboard(
113        const Vector3& position,
114        const ColourValue& colour )
115    {
116        if( mFreeBillboards.empty() )
117        {
118            if( mAutoExtendPool )
119            {
120                setPoolSize( getPoolSize() * 2 );
121            }
122            else
123            {
124                return 0;
125            }
126        }
127
128        // Get a new billboard
129        Billboard* newBill = mFreeBillboards.front();
130        mFreeBillboards.pop_front();
131        mActiveBillboards.push_back(newBill);
132
133        newBill->setPosition(position);
134        newBill->setColour(colour);
135        newBill->mDirection = Vector3::ZERO;
136        newBill->setRotation(Radian(0));
137        newBill->resetDimensions();
138        newBill->_notifyOwner(this);
139
140                // Merge into bounds
141                Real adjust = std::max(mDefaultWidth, mDefaultHeight);
142        Vector3 vecAdjust(adjust, adjust, adjust);
143                Vector3 newMin = position - vecAdjust;
144                Vector3 newMax = position + vecAdjust;
145               
146        mAABB.merge(newMin);
147        mAABB.merge(newMax);
148
149                Real sqlen = std::max(newMin.squaredLength(), newMax.squaredLength());
150                mBoundingRadius = std::max(mBoundingRadius, Math::Sqrt(sqlen));
151               
152        return newBill;
153    }
154
155    //-----------------------------------------------------------------------
156    Billboard* BillboardSet::createBillboard(
157        Real x, Real y, Real z,
158        const ColourValue& colour )
159    {
160        return createBillboard( Vector3( x, y, z ), colour );
161    }
162
163    //-----------------------------------------------------------------------
164    int BillboardSet::getNumBillboards(void) const
165    {
166        return static_cast< int >( mActiveBillboards.size() );
167    }
168
169    //-----------------------------------------------------------------------
170    void BillboardSet::clear()
171    {
172                // Insert actives into free list
173                mFreeBillboards.insert(mFreeBillboards.end(), mActiveBillboards.begin(), mActiveBillboards.end());
174     
175                // Remove all active instances
176        mActiveBillboards.clear();
177    }
178
179    //-----------------------------------------------------------------------
180    Billboard* BillboardSet::getBillboard( unsigned int index ) const
181    {
182        assert(
183            index < mActiveBillboards.size() &&
184            "Billboard index out of bounds." );
185
186        /* We can't access it directly, so we check wether it's in the first
187           or the second half, then we start either from the beginning or the
188           end of the list
189        */
190        ActiveBillboardList::const_iterator it;
191        if( index >= ( mActiveBillboards.size() >> 1 ) )
192        {
193                        index = static_cast<unsigned int>(mActiveBillboards.size()) - index;
194            for( it = mActiveBillboards.end(); index; --index, --it );
195        }
196        else
197        {
198            for( it = mActiveBillboards.begin(); index; --index, ++it );
199        }
200
201        return *it;
202    }
203
204    //-----------------------------------------------------------------------
205    void BillboardSet::removeBillboard(unsigned int index)
206    {
207        assert(
208            index < mActiveBillboards.size() &&
209            "Billboard index out of bounds." );
210
211        /* We can't access it directly, so we check wether it's in the first
212           or the second half, then we start either from the beginning or the
213           end of the list.
214           We then remove the billboard form the 'used' list and add it to
215           the 'free' list.
216        */
217        ActiveBillboardList::iterator it;
218        if( index >= ( mActiveBillboards.size() >> 1 ) )
219        {
220                        index = static_cast<unsigned int>(mActiveBillboards.size()) - index;
221            for( it = mActiveBillboards.end(); index; --index, --it );
222        }
223        else
224        {
225            for( it = mActiveBillboards.begin(); index; --index, ++it );
226        }
227
228        mFreeBillboards.push_back( *it );
229        mActiveBillboards.erase( it );
230    }
231
232    //-----------------------------------------------------------------------
233    void BillboardSet::removeBillboard( Billboard* pBill )
234    {
235        mActiveBillboards.remove( pBill );
236        mFreeBillboards.push_back( pBill );
237    }
238
239    //-----------------------------------------------------------------------
240    void BillboardSet::setBillboardOrigin( BillboardOrigin origin )
241    {
242        mOriginType = origin;
243    }
244
245    //-----------------------------------------------------------------------
246    BillboardOrigin BillboardSet::getBillboardOrigin(void) const
247    {
248        return mOriginType;
249    }
250
251    //-----------------------------------------------------------------------
252    void BillboardSet::setDefaultDimensions( Real width, Real height )
253    {
254        mDefaultWidth = width;
255        mDefaultHeight = height;
256    }
257    //-----------------------------------------------------------------------
258    void BillboardSet::setDefaultWidth(Real width)
259    {
260        mDefaultWidth = width;
261    }
262    //-----------------------------------------------------------------------
263    Real BillboardSet::getDefaultWidth(void) const
264    {
265        return mDefaultWidth;
266    }
267    //-----------------------------------------------------------------------
268    void BillboardSet::setDefaultHeight(Real height)
269    {
270        mDefaultHeight = height;
271    }
272    //-----------------------------------------------------------------------
273    Real BillboardSet::getDefaultHeight(void) const
274    {
275        return mDefaultHeight;
276    }
277    //-----------------------------------------------------------------------
278    void BillboardSet::setMaterialName( const String& name )
279    {
280        mMaterialName = name;
281
282        mpMaterial = MaterialManager::getSingleton().getByName(name);
283
284                if (mpMaterial.isNull())
285                        OGRE_EXCEPT( Exception::ERR_ITEM_NOT_FOUND, "Could not find material " + name,
286                                "BillboardSet::setMaterialName" );
287
288        /* Ensure that the new material was loaded (will not load again if
289           already loaded anyway)
290        */
291        mpMaterial->load();
292    }
293
294    //-----------------------------------------------------------------------
295    const String& BillboardSet::getMaterialName(void) const
296    {
297        return mMaterialName;
298    }
299
300    //-----------------------------------------------------------------------
301    void BillboardSet::_notifyCurrentCamera( Camera* cam )
302    {
303        mCurrentCamera = cam;
304        /* Generate the vertices for all the billboards relative to the camera
305           Also take the opportunity to update the vertex colours
306           May as well do it here to save on loops elsewhere
307        */
308
309        /* NOTE: most engines generate world coordinates for the billboards
310           directly, taking the world axes of the camera as offsets to the
311           center points. I take a different approach, reverse-transforming
312           the camera world axes into local billboard space.
313           Why?
314           Well, it's actually more efficient this way, because I only have to
315           reverse-transform using the billboardset world matrix (inverse)
316           once, from then on it's simple additions (assuming identically
317           sized billboards). If I transformed every billboard center by it's
318           world transform, that's a matrix multiplication per billboard
319           instead.
320           I leave the final transform to the render pipeline since that can
321           use hardware TnL if it is available.
322        */
323
324        // create vertex and index buffers if they haven't already been
325        if(!mBuffersCreated)
326            _createBuffers();
327
328
329
330        // Get offsets for origin type
331        getParametricOffsets(mLeftOff, mRightOff, mTopOff, mBottomOff);
332
333        // Generate axes etc up-front if not oriented per-billboard
334        if (mBillboardType != BBT_ORIENTED_SELF)
335        {
336            genBillboardAxes(cam, &mCamX, &mCamY);
337
338            /* If all billboards are the same size we can precalculate the
339               offsets and just use '+' instead of '*' for each billboard,
340               and it should be faster.
341            */
342            genVertOffsets(mLeftOff, mRightOff, mTopOff, mBottomOff,
343                mDefaultWidth, mDefaultHeight, mCamX, mCamY, mVOffset);
344
345        }
346
347       
348
349        // If we're driving this from our own data, go ahead
350        if (!mExternalData)
351        {
352            beginBillboards();
353            ActiveBillboardList::iterator it;
354            for(it = mActiveBillboards.begin();
355                it != mActiveBillboards.end();
356                ++it )
357            {
358                injectBillboard(*(*it));
359            }
360            endBillboards();
361        }
362
363
364
365    }
366    //-----------------------------------------------------------------------
367    void BillboardSet::beginBillboards(void)
368    {
369        // Init num visible
370        mNumVisibleBillboards = 0;
371
372        mLockPtr = static_cast<float*>(
373            mMainBuf->lock(HardwareBuffer::HBL_DISCARD) );
374
375    }
376    //-----------------------------------------------------------------------
377    void BillboardSet::injectBillboard(const Billboard& bb)
378    {
379        // Skip if not visible (NB always true if not bounds checking individual billboards)
380        if (!billboardVisible(mCurrentCamera, bb)) return;
381
382        if (mBillboardType == BBT_ORIENTED_SELF)
383        {
384            // Have to generate axes & offsets per billboard
385            genBillboardAxes(mCurrentCamera, &mCamX, &mCamY, &bb);
386        }
387
388        if( mAllDefaultSize ) // If they're all the same size
389        {
390            /* No per-billboard checking, just blast through.
391            Saves us an if clause every billboard which may
392            make a difference.
393            */
394
395            if (mBillboardType == BBT_ORIENTED_SELF)
396            {
397                genVertOffsets(mLeftOff, mRightOff, mTopOff, mBottomOff,
398                    mDefaultWidth, mDefaultHeight, mCamX, mCamY, mVOffset);
399            }
400            genVertices(mVOffset, bb);
401        }
402        else // not all default size
403        {
404            Vector3 vOwnOffset[4];
405            // If it has own dimensions, or self-oriented, gen offsets
406            if (mBillboardType == BBT_ORIENTED_SELF ||
407                bb.mOwnDimensions)
408            {
409                // Generate using own dimensions
410                genVertOffsets(mLeftOff, mRightOff, mTopOff, mBottomOff,
411                    bb.mWidth, bb.mHeight, mCamX, mCamY, vOwnOffset);
412                // Create vertex data           
413                genVertices(vOwnOffset, bb);
414            }
415            else // Use default dimension, already computed before the loop, for faster creation
416            {
417                genVertices(mVOffset, bb);
418            }
419        }
420        // Increment visibles
421        mNumVisibleBillboards++;
422    }
423    //-----------------------------------------------------------------------
424    void BillboardSet::endBillboards(void)
425    {
426        mMainBuf->unlock();
427    }
428        //-----------------------------------------------------------------------
429        void BillboardSet::setBounds(const AxisAlignedBox& box, Real radius)
430        {
431                mAABB = box;
432                mBoundingRadius = radius;
433        }
434    //-----------------------------------------------------------------------
435    void BillboardSet::_updateBounds(void)
436    {
437        if (mActiveBillboards.empty())
438        {
439            // No billboards, null bbox
440            mAABB.setNull();
441                        mBoundingRadius = 0.0f;
442        }
443        else
444        {
445                        Real maxSqLen = -1.0f;
446       
447            Vector3 min(Math::POS_INFINITY, Math::POS_INFINITY, Math::POS_INFINITY);
448            Vector3 max(Math::NEG_INFINITY, Math::NEG_INFINITY, Math::NEG_INFINITY);
449            ActiveBillboardList::iterator i, iend;
450
451            iend = mActiveBillboards.end();
452            for (i = mActiveBillboards.begin(); i != iend; ++i)
453            {
454                const Vector3& pos = (*i)->getPosition();
455                min.makeFloor(pos);
456                max.makeCeil(pos);
457
458                                maxSqLen = std::max(maxSqLen, pos.squaredLength());
459            }
460            // Adjust for billboard size
461            Real adjust = std::max(mDefaultWidth, mDefaultHeight);
462            Vector3 vecAdjust(adjust, adjust, adjust);
463            min -= vecAdjust;
464            max += vecAdjust;
465
466            mAABB.setExtents(min, max);
467                        mBoundingRadius = Math::Sqrt(maxSqLen);
468                       
469        }
470
471        if (mParentNode)
472            mParentNode->needUpdate();
473       
474    }
475    //-----------------------------------------------------------------------
476    const AxisAlignedBox& BillboardSet::getBoundingBox(void) const
477    {
478        return mAABB;
479    }
480
481    //-----------------------------------------------------------------------   
482    void BillboardSet::_updateRenderQueue(RenderQueue* queue)
483    {
484        //only set the render queue group if it has been explicitly set.
485        if( mRenderQueueIDSet )
486        {
487           queue->addRenderable(this, mRenderQueueID);
488        } else {
489           queue->addRenderable(this);
490        }
491
492    }
493
494    //-----------------------------------------------------------------------
495    const MaterialPtr& BillboardSet::getMaterial(void) const
496    {
497        return mpMaterial;
498    }
499
500    //-----------------------------------------------------------------------
501    void BillboardSet::getRenderOperation(RenderOperation& op)
502    {
503        op.operationType = RenderOperation::OT_TRIANGLE_LIST;
504        op.useIndexes = true;
505
506        op.vertexData = mVertexData;
507        op.vertexData->vertexCount = mNumVisibleBillboards * 4;
508        op.vertexData->vertexStart = 0;
509
510        op.indexData = mIndexData;
511        op.indexData->indexCount = mNumVisibleBillboards * 6;
512        op.indexData->indexStart = 0;
513    }
514
515    //-----------------------------------------------------------------------
516    void BillboardSet::getWorldTransforms( Matrix4* xform ) const
517    {
518        if (mWorldSpace)
519        {
520            *xform = Matrix4::IDENTITY;
521        }
522        else
523        {
524            *xform = _getParentNodeFullTransform();
525        }
526    }
527    //-----------------------------------------------------------------------
528    const Quaternion& BillboardSet::getWorldOrientation(void) const
529    {
530        return mParentNode->_getDerivedOrientation();
531    }
532    //-----------------------------------------------------------------------
533    const Vector3& BillboardSet::getWorldPosition(void) const
534    {
535        return mParentNode->_getDerivedPosition();
536    }
537    //-----------------------------------------------------------------------
538    void BillboardSet::setAutoextend( bool autoextend )
539    {
540        mAutoExtendPool = autoextend;
541    }
542
543    //-----------------------------------------------------------------------
544    bool BillboardSet::getAutoextend(void) const
545    {
546        return mAutoExtendPool;
547    }
548
549    //-----------------------------------------------------------------------
550    void BillboardSet::setPoolSize( unsigned int size )
551    {
552        // Never shrink below size()
553        size_t currSize = mBillboardPool.size();
554
555        if( currSize < size )
556        {
557            this->increasePool(size);
558
559            for( size_t i = currSize; i < size; ++i )
560            {
561                // Add new items to the queue
562                mFreeBillboards.push_back( mBillboardPool[i] );
563            }
564           
565            mPoolSize = size;
566            mBuffersCreated = false;
567
568            if (mVertexData)
569            {
570                delete mVertexData;
571                mVertexData = 0;
572            }
573            if (mIndexData)
574            {
575                delete mIndexData;
576                mIndexData = 0;
577            }
578        }
579    }
580
581    //-----------------------------------------------------------------------
582    void BillboardSet::_createBuffers(void)
583    {
584        /* Allocate / reallocate vertex data
585           Note that we allocate enough space for ALL the billboards in the pool, but only issue
586           rendering operations for the sections relating to the active billboards
587        */
588
589        /* Alloc positions   ( 4 verts per billboard, 3 components )
590                 colours     ( 1 x RGBA per vertex )
591                 indices     ( 6 per billboard ( 2 tris ) )
592                 tex. coords ( 2D coords, 4 per billboard )
593        */
594        mVertexData = new VertexData();
595        mIndexData  = new IndexData();
596
597        mVertexData->vertexCount = mPoolSize * 4;
598        mVertexData->vertexStart = 0;
599
600        // Vertex declaration
601        VertexDeclaration* decl = mVertexData->vertexDeclaration;
602        VertexBufferBinding* binding = mVertexData->vertexBufferBinding;
603
604        size_t offset = 0;
605        decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
606        offset += VertexElement::getTypeSize(VET_FLOAT3);
607        decl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE);
608        offset += VertexElement::getTypeSize(VET_COLOUR);
609        decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES, 0);
610
611        mMainBuf =
612            HardwareBufferManager::getSingleton().createVertexBuffer(
613                decl->getVertexSize(0),
614                mVertexData->vertexCount,
615                HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
616        // bind position and diffuses
617        binding->setBinding(0, mMainBuf);
618
619
620        mIndexData->indexStart = 0;
621        mIndexData->indexCount = mPoolSize * 6;
622
623        mIndexData->indexBuffer = HardwareBufferManager::getSingleton().
624            createIndexBuffer(HardwareIndexBuffer::IT_16BIT,
625                mIndexData->indexCount,
626                HardwareBuffer::HBU_STATIC_WRITE_ONLY);
627
628        /* Create indexes (will be the same every frame)
629           Using indexes because it means 1/3 less vertex transforms (4 instead of 6)
630
631           Billboard layout relative to camera:
632
633            2-----3
634            |    /|
635            |  /  |
636            |/    |
637            0-----1
638        */
639
640        ushort* pIdx = static_cast<ushort*>(
641            mIndexData->indexBuffer->lock(0,
642              mIndexData->indexBuffer->getSizeInBytes(),
643              HardwareBuffer::HBL_DISCARD) );
644
645        for(
646            size_t idx, idxOff, bboard = 0;
647            bboard < mPoolSize;
648            ++bboard )
649        {
650            // Do indexes
651            idx    = bboard * 6;
652            idxOff = bboard * 4;
653
654            pIdx[idx] = static_cast<unsigned short>(idxOff); // + 0;, for clarity
655            pIdx[idx+1] = static_cast<unsigned short>(idxOff + 1);
656            pIdx[idx+2] = static_cast<unsigned short>(idxOff + 3);
657            pIdx[idx+3] = static_cast<unsigned short>(idxOff + 0);
658            pIdx[idx+4] = static_cast<unsigned short>(idxOff + 3);
659            pIdx[idx+5] = static_cast<unsigned short>(idxOff + 2);
660
661        }
662
663        mIndexData->indexBuffer->unlock();
664        mBuffersCreated = true;
665    }
666
667    //-----------------------------------------------------------------------
668    unsigned int BillboardSet::getPoolSize(void) const
669    {
670        return static_cast< unsigned int >( mBillboardPool.size() );
671    }
672
673    //-----------------------------------------------------------------------
674    void BillboardSet::_notifyBillboardResized(void)
675    {
676        mAllDefaultSize = false;
677    }
678
679    //-----------------------------------------------------------------------
680    void BillboardSet::getParametricOffsets(
681        Real& left, Real& right, Real& top, Real& bottom )
682    {
683        switch( mOriginType )
684        {
685        case BBO_TOP_LEFT:
686            left = 0.0f;
687            right = 1.0f;
688            top = 0.0f;
689            bottom = 1.0f;
690            break;
691
692        case BBO_TOP_CENTER:
693            left = -0.5f;
694            right = 0.5f;
695            top = 0.0f;
696            bottom = 1.0f;
697            break;
698
699        case BBO_TOP_RIGHT:
700            left = -1.0f;
701            right = 0.0f;
702            top = 0.0f;
703            bottom = 1.0f;
704            break;
705
706        case BBO_CENTER_LEFT:
707            left = 0.0f;
708            right = 1.0f;
709            top = -0.5f;
710            bottom = 0.5f;
711            break;
712
713        case BBO_CENTER:
714            left = -0.5f;
715            right = 0.5f;
716            top = -0.5f;
717            bottom = 0.5f;
718            break;
719
720        case BBO_CENTER_RIGHT:
721            left = -1.0f;
722            right = 0.0f;
723            top = -0.5f;
724            bottom = 0.5f;
725            break;
726
727        case BBO_BOTTOM_LEFT:
728            left = 0.0f;
729            right = 1.0f;
730            top = -1.0f;
731            bottom = 0.0f;
732            break;
733
734        case BBO_BOTTOM_CENTER:
735            left = -0.5f;
736            right = 0.5f;
737            top = -1.0f;
738            bottom = 0.0f;
739            break;
740
741        case BBO_BOTTOM_RIGHT:
742            left = -1.0f;
743            right = 0.0f;
744            top = -1.0f;
745            bottom = 0.0f;
746            break;
747        }
748    }
749    //-----------------------------------------------------------------------
750    bool BillboardSet::getCullIndividually(void) const
751    {
752        return mCullIndividual;
753    }
754    //-----------------------------------------------------------------------
755    void BillboardSet::setCullIndividually(bool cullIndividual)
756    {
757        mCullIndividual = cullIndividual;
758    }
759    //-----------------------------------------------------------------------
760    bool BillboardSet::billboardVisible(Camera* cam, const Billboard& bill)
761    {
762        // Return always visible if not culling individually
763        if (!mCullIndividual) return true;
764
765        // Cull based on sphere (have to transform less)
766        Sphere sph;
767        Matrix4 xworld;
768
769        getWorldTransforms(&xworld);
770
771        sph.setCenter(xworld * bill.mPosition);
772
773        if (bill.mOwnDimensions)
774        {
775            sph.setRadius(std::max(bill.mWidth, bill.mHeight));
776        }
777        else
778        {
779            sph.setRadius(std::max(mDefaultWidth, mDefaultHeight));
780        }
781
782        return cam->isVisible(sph);
783       
784    }
785    //-----------------------------------------------------------------------
786    void BillboardSet::increasePool(unsigned int size)
787    {
788        size_t oldSize = mBillboardPool.size();
789
790        // Increase size
791        mBillboardPool.reserve(size);
792        mBillboardPool.resize(size);
793
794        // Create new billboards
795        for( size_t i = oldSize; i < size; ++i )
796            mBillboardPool[i] = new Billboard();
797
798    }
799    //-----------------------------------------------------------------------
800    void BillboardSet::genBillboardAxes(Camera* cam, Vector3* pX,
801        Vector3 *pY, const Billboard* bb)
802    {
803        // Default behaviour is that billboards are in local node space
804        // so orientation of camera (in world space) must be reverse-transformed
805        // into node space to generate the axes
806
807        Quaternion invTransform;
808        if (!mWorldSpace)
809        {
810            invTransform = mParentNode->_getDerivedOrientation().Inverse();
811        }
812        Quaternion camQ;
813                Vector3 camdir = cam->getDerivedDirection();
814
815        switch (mBillboardType)
816        {
817        case BBT_POINT:
818            // Get camera world axes for X and Y (depth is irrelevant)
819            camQ = cam->getDerivedOrientation();
820                        if (cam->isReflected())
821                        {
822                                Vector3 dir = camQ * Vector3::NEGATIVE_UNIT_Z;
823                                Vector3 rdir = camdir.reflect(cam->getReflectionPlane().normal);
824                                camQ = dir.getRotationTo(rdir) * camQ;
825                        }
826            if (!mWorldSpace)
827            {
828                // Convert into billboard local space
829                camQ = invTransform * camQ;
830            }
831            *pX = camQ * Vector3::UNIT_X;
832            *pY = camQ * Vector3::UNIT_Y;
833            break;
834        case BBT_ORIENTED_COMMON:
835            // Y-axis is common direction
836            // X-axis is cross with camera direction
837            *pY = mCommonDirection;
838                        if (cam->isReflected())
839                        {
840                                camdir = camdir.reflect(cam->getReflectionPlane().normal);
841                        }
842            if (!mWorldSpace)
843            {
844                // Convert into billboard local space
845                *pX = (invTransform * camdir).crossProduct(*pY);
846            }
847            else
848            {
849                *pX = camdir.crossProduct(*pY);
850            }
851            pX->normalise();
852           
853            break;
854        case BBT_ORIENTED_SELF:
855            // Y-axis is direction
856            // X-axis is cross with camera direction
857            // Scale direction first
858            *pY = bb->mDirection;
859                        if (cam->isReflected())
860                        {
861                                camdir = camdir.reflect(cam->getReflectionPlane().normal);
862                        }
863            if (!mWorldSpace)
864            {
865                // Convert into billboard local space
866                *pX = (invTransform * camdir).crossProduct(*pY);
867                                pX->normalise();
868            }
869            else
870            {
871                                *pY *= 0.01f;
872                *pX = camdir.crossProduct(*pY);
873            }
874
875            break;
876        }
877
878
879    }
880    //-----------------------------------------------------------------------
881    void BillboardSet::setBillboardType(BillboardType bbt)
882    {
883        mBillboardType = bbt;
884    }
885    //-----------------------------------------------------------------------
886    BillboardType BillboardSet::getBillboardType(void) const
887    {
888        return mBillboardType;
889    }
890    //-----------------------------------------------------------------------
891    void BillboardSet::setCommonDirection(const Vector3& vec)
892    {
893        mCommonDirection = vec;
894    }
895    //-----------------------------------------------------------------------
896    const Vector3& BillboardSet::getCommonDirection(void) const
897    {
898        return mCommonDirection;
899    }
900    //-----------------------------------------------------------------------
901    void BillboardSet::genVertices(
902        const Vector3* const offsets, const Billboard& bb)
903    {
904        RGBA colour;
905        Root::getSingleton().convertColourValue(bb.mColour, &colour);
906                RGBA* pCol;
907        static float basicTexData[8] = {
908            0.0, 1.0,
909            1.0, 1.0,
910            0.0, 0.0,
911            1.0, 0.0 };
912        static float rotTexDataBase[8] = {
913            -0.5, 0.5,
914             0.5, 0.5,
915            -0.5,-0.5,
916             0.5,-0.5 };
917        static float rotTexData[8];
918
919                float* pTexData;
920
921        // Texcoords
922        if (mFixedTextureCoords)
923        {
924                        pTexData = basicTexData;
925        }
926        else
927        {
928
929            const Real      cos_rot  ( Math::Cos(bb.mRotation)   );
930            const Real      sin_rot  ( Math::Sin(bb.mRotation)   );
931
932            rotTexData[0] = (cos_rot * rotTexDataBase[0]) + (sin_rot * rotTexDataBase[1]) + 0.5;
933            rotTexData[1] = (sin_rot * rotTexDataBase[0]) - (cos_rot * rotTexDataBase[1]) + 0.5;
934
935            rotTexData[2] = (cos_rot * rotTexDataBase[2]) + (sin_rot * rotTexDataBase[3]) + 0.5;
936            rotTexData[3] = (sin_rot * rotTexDataBase[2]) - (cos_rot * rotTexDataBase[3]) + 0.5;
937
938            rotTexData[4] = (cos_rot * rotTexDataBase[4]) + (sin_rot * rotTexDataBase[5]) + 0.5;
939            rotTexData[5]= (sin_rot * rotTexDataBase[4]) - (cos_rot * rotTexDataBase[5]) + 0.5;
940
941            rotTexData[6] = (cos_rot * rotTexDataBase[6]) + (sin_rot * rotTexDataBase[7]) + 0.5;
942            rotTexData[7] = (sin_rot * rotTexDataBase[6]) - (cos_rot * rotTexDataBase[7]) + 0.5;
943                        pTexData = rotTexData;
944        }
945               
946
947        // Left-top
948                // Positions
949        *mLockPtr++ = offsets[0].x + bb.mPosition.x;
950        *mLockPtr++ = offsets[0].y + bb.mPosition.y;
951        *mLockPtr++ = offsets[0].z + bb.mPosition.z;
952                // Colour
953                // Convert float* to RGBA*
954        pCol = static_cast<RGBA*>(static_cast<void*>(mLockPtr));
955        *pCol++ = colour;
956        // Update lock pointer
957        mLockPtr = static_cast<float*>(static_cast<void*>(pCol));
958                // Texture coords
959                *mLockPtr++ = *pTexData++;
960                *mLockPtr++ = *pTexData++;
961
962
963                // Right-top
964                // Positions
965        *mLockPtr++ = offsets[1].x + bb.mPosition.x;
966        *mLockPtr++ = offsets[1].y + bb.mPosition.y;
967        *mLockPtr++ = offsets[1].z + bb.mPosition.z;
968                // Colour
969                // Convert float* to RGBA*
970        pCol = static_cast<RGBA*>(static_cast<void*>(mLockPtr));
971        *pCol++ = colour;
972        // Update lock pointer
973        mLockPtr = static_cast<float*>(static_cast<void*>(pCol));
974                // Texture coords
975                *mLockPtr++ = *pTexData++;
976                *mLockPtr++ = *pTexData++;
977
978                // Left-bottom
979                // Positions
980        *mLockPtr++ = offsets[2].x + bb.mPosition.x;
981        *mLockPtr++ = offsets[2].y + bb.mPosition.y;
982        *mLockPtr++ = offsets[2].z + bb.mPosition.z;
983                // Colour
984                // Convert float* to RGBA*
985        pCol = static_cast<RGBA*>(static_cast<void*>(mLockPtr));
986        *pCol++ = colour;
987        // Update lock pointer
988        mLockPtr = static_cast<float*>(static_cast<void*>(pCol));
989                // Texture coords
990                *mLockPtr++ = *pTexData++;
991                *mLockPtr++ = *pTexData++;
992
993                // Right-bottom
994                // Positions
995        *mLockPtr++ = offsets[3].x + bb.mPosition.x;
996        *mLockPtr++ = offsets[3].y + bb.mPosition.y;
997        *mLockPtr++ = offsets[3].z + bb.mPosition.z;
998                // Colour
999                // Convert float* to RGBA*
1000        pCol = static_cast<RGBA*>(static_cast<void*>(mLockPtr));
1001        *pCol++ = colour;
1002        // Update lock pointer
1003        mLockPtr = static_cast<float*>(static_cast<void*>(pCol));
1004                // Texture coords
1005                *mLockPtr++ = *pTexData++;
1006                *mLockPtr++ = *pTexData++;
1007
1008    }
1009    //-----------------------------------------------------------------------
1010    void BillboardSet::genVertOffsets(Real inleft, Real inright, Real intop, Real inbottom,
1011        Real width, Real height, const Vector3& x, const Vector3& y, Vector3* pDestVec)
1012    {
1013        Vector3 vLeftOff, vRightOff, vTopOff, vBottomOff;
1014        /* Calculate default offsets. Scale the axes by
1015           parametric offset and dimensions, ready to be added to
1016           positions.
1017        */
1018
1019        vLeftOff   = x * ( inleft   * width );
1020        vRightOff  = x * ( inright  * width );
1021        vTopOff    = y * ( intop   * height );
1022        vBottomOff = y * ( inbottom * height );
1023
1024        // Make final offsets to vertex positions
1025        pDestVec[0] = vLeftOff  + vTopOff;
1026        pDestVec[1] = vRightOff + vTopOff;
1027        pDestVec[2] = vLeftOff  + vBottomOff;
1028        pDestVec[3] = vRightOff + vBottomOff;
1029
1030    }
1031    //-----------------------------------------------------------------------
1032    const String& BillboardSet::getName(void) const
1033    {
1034        return mName;
1035    }
1036    //-----------------------------------------------------------------------
1037    const String& BillboardSet::getMovableType(void) const
1038    {
1039        return msMovableType;
1040    }
1041    //-----------------------------------------------------------------------
1042    Real BillboardSet::getSquaredViewDepth(const Camera* const cam) const
1043    {
1044        assert(mParentNode);
1045        return mParentNode->getSquaredViewDepth(cam);
1046    }
1047    //-----------------------------------------------------------------------
1048        Real BillboardSet::getBoundingRadius(void) const
1049        {
1050                return mBoundingRadius;
1051        }
1052    //-----------------------------------------------------------------------
1053    const LightList& BillboardSet::getLights(void) const
1054    {
1055        // It's actually quite unlikely that this will be called,
1056        // because most billboards are unlit, but here we go anyway
1057        return getParentSceneNode()->findLights(this->getBoundingRadius());
1058    }
1059
1060}
Note: See TracBrowser for help on using the repository browser.