Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreBillboardChain.cpp @ 10

Last change on this file since 10 was 5, checked in by anonymous, 17 years ago

=hoffentlich gehts jetzt

File size: 23.1 KB
Line 
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-2006 Torus Knot Software Ltd
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
24You may alternatively use this source under the terms of a specific version of
25the OGRE Unrestricted License provided you have obtained such a license from
26Torus Knot Software Ltd.
27-----------------------------------------------------------------------------
28*/
29
30// Thanks to Vincent Cantin (karmaGfa) for the original implementation of this
31// class, although it has now been mostly rewritten
32
33#include "OgreStableHeaders.h"
34#include "OgreBillboardChain.h"
35
36#include "OgreSimpleRenderable.h"
37#include "OgreHardwareBufferManager.h"
38#include "OgreNode.h"
39#include "OgreCamera.h"
40#include "OgreRoot.h"
41#include "OgreMaterialManager.h"
42#include "OgreLogManager.h"
43#include "OgreStringConverter.h"
44
45namespace Ogre {
46        const size_t BillboardChain::SEGMENT_EMPTY = 0xffffffff;
47        //-----------------------------------------------------------------------
48        BillboardChain::Element::Element()
49        {
50        }
51        //-----------------------------------------------------------------------
52        BillboardChain::Element::Element(Vector3 _position,
53                Real _width,
54                Real _texCoord,
55                ColourValue _colour) :
56        position(_position),
57                width(_width),
58                texCoord(_texCoord),
59                colour(_colour)
60        {
61        }
62        //-----------------------------------------------------------------------
63        BillboardChain::BillboardChain(const String& name, size_t maxElements,
64                size_t numberOfChains, bool useTextureCoords, bool useColours, bool dynamic)
65                :MovableObject(name),
66                mMaxElementsPerChain(maxElements),
67                mChainCount(numberOfChains),
68                mUseTexCoords(useTextureCoords),
69                mUseVertexColour(useColours),
70                mDynamic(dynamic),
71                mVertexDeclDirty(true),
72                mBuffersNeedRecreating(true),
73                mBoundsDirty(true),
74                mIndexContentDirty(true),
75                mRadius(0.0f),
76                mTexCoordDir(TCD_U)
77        {
78                mVertexData = new VertexData();
79                mIndexData = new IndexData();
80
81                mOtherTexCoordRange[0] = 0.0f;
82                mOtherTexCoordRange[1] = 1.0f;
83
84                setupChainContainers();
85
86                mVertexData->vertexStart = 0;
87                // index data set up later
88                // set basic white material
89                this->setMaterialName("BaseWhiteNoLighting");
90
91        }
92        //-----------------------------------------------------------------------
93        BillboardChain::~BillboardChain()
94        {
95                delete mVertexData;
96                delete mIndexData;
97        }
98        //-----------------------------------------------------------------------
99        void BillboardChain::setupChainContainers(void)
100        {
101                // Allocate enough space for everything
102                mChainElementList.resize(mChainCount * mMaxElementsPerChain);
103                mVertexData->vertexCount = mChainElementList.size() * 2;
104
105                // Configure chains
106                mChainSegmentList.resize(mChainCount);
107                for (size_t i = 0; i < mChainCount; ++i)
108                {
109                        ChainSegment& seg = mChainSegmentList[i];
110                        seg.start = i * mMaxElementsPerChain;
111                        seg.tail = seg.head = SEGMENT_EMPTY;
112
113                }
114
115
116        }
117        //-----------------------------------------------------------------------
118        void BillboardChain::setupVertexDeclaration(void)
119        {
120                if (mVertexDeclDirty)
121                {
122                        VertexDeclaration* decl = mVertexData->vertexDeclaration;
123                        decl->removeAllElements();
124
125                        size_t offset = 0;
126                        // Add a description for the buffer of the positions of the vertices
127                        decl->addElement(0, offset, VET_FLOAT3, VES_POSITION);
128                        offset += VertexElement::getTypeSize(VET_FLOAT3);
129
130                        if (mUseVertexColour)
131                        {
132                                decl->addElement(0, offset, VET_COLOUR, VES_DIFFUSE);
133                                offset += VertexElement::getTypeSize(VET_COLOUR);
134                        }
135
136                        if (mUseTexCoords)
137                        {
138                                decl->addElement(0, offset, VET_FLOAT2, VES_TEXTURE_COORDINATES);
139                                offset += VertexElement::getTypeSize(VET_FLOAT2);
140                        }
141
142                        if (!mUseTexCoords && !mUseVertexColour)
143                        {
144                                LogManager::getSingleton().logMessage(
145                                        "Error - BillboardChain '" + mName + "' is using neither "
146                                        "texture coordinates or vertex colours; it will not be "
147                                        "visible on some rendering APIs so you should change this "
148                                        "so you use one or the other.");
149                        }
150                        mVertexDeclDirty = false;
151                }
152        }
153        //-----------------------------------------------------------------------
154        void BillboardChain::setupBuffers(void)
155        {
156                setupVertexDeclaration();
157                if (mBuffersNeedRecreating)
158                {
159                        // Create the vertex buffer (always dynamic due to the camera adjust)
160                        HardwareVertexBufferSharedPtr pBuffer =
161                                HardwareBufferManager::getSingleton().createVertexBuffer(
162                                mVertexData->vertexDeclaration->getVertexSize(0),
163                                mVertexData->vertexCount,
164                                HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY_DISCARDABLE);
165
166                        // (re)Bind the buffer
167                        // Any existing buffer will lose its reference count and be destroyed
168                        mVertexData->vertexBufferBinding->setBinding(0, pBuffer);
169
170                        mIndexData->indexBuffer =
171                                HardwareBufferManager::getSingleton().createIndexBuffer(
172                                        HardwareIndexBuffer::IT_16BIT,
173                                        mChainCount * mMaxElementsPerChain * 6, // max we can use
174                                        mDynamic? HardwareBuffer::HBU_DYNAMIC_WRITE_ONLY : HardwareBuffer::HBU_STATIC_WRITE_ONLY);
175                        // NB we don't set the indexCount on IndexData here since we will
176                        // probably use less than the maximum number of indices
177
178                        mBuffersNeedRecreating = false;
179                }
180        }
181        //-----------------------------------------------------------------------
182        void BillboardChain::setMaxChainElements(size_t maxElements)
183        {
184                mMaxElementsPerChain = maxElements;
185                setupChainContainers();
186        mBuffersNeedRecreating = mIndexContentDirty = true;
187        }
188        //-----------------------------------------------------------------------
189        void BillboardChain::setNumberOfChains(size_t numChains)
190        {
191                mChainCount = numChains;
192                setupChainContainers();
193        mBuffersNeedRecreating = mIndexContentDirty = true;
194        }
195        //-----------------------------------------------------------------------
196        void BillboardChain::setUseTextureCoords(bool use)
197        {
198                mUseTexCoords = use;
199                mVertexDeclDirty = mBuffersNeedRecreating = true;
200        mIndexContentDirty = true;
201        }
202        //-----------------------------------------------------------------------
203        void BillboardChain::setTextureCoordDirection(BillboardChain::TexCoordDirection dir)
204        {
205                mTexCoordDir = dir;
206        }
207        //-----------------------------------------------------------------------
208        void BillboardChain::setOtherTextureCoordRange(Real start, Real end)
209        {
210                mOtherTexCoordRange[0] = start;
211                mOtherTexCoordRange[1] = end;
212        }
213        //-----------------------------------------------------------------------
214        void BillboardChain::setUseVertexColours(bool use)
215        {
216                mUseVertexColour = use;
217                mVertexDeclDirty = mBuffersNeedRecreating = true;
218        mIndexContentDirty = true;
219        }
220        //-----------------------------------------------------------------------
221        void BillboardChain::setDynamic(bool dyn)
222        {
223                mDynamic = dyn;
224                mBuffersNeedRecreating = mIndexContentDirty = true;
225        }
226        //-----------------------------------------------------------------------
227        void BillboardChain::addChainElement(size_t chainIndex,
228                const BillboardChain::Element& dtls)
229        {
230
231                if (chainIndex >= mChainCount)
232                {
233                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
234                                "chainIndex out of bounds",
235                                "BillboardChain::addChainElement");
236                }
237                ChainSegment& seg = mChainSegmentList[chainIndex];
238                if (seg.head == SEGMENT_EMPTY)
239                {
240                        // Tail starts at end, head grows backwards
241                        seg.tail = mMaxElementsPerChain - 1;
242                        seg.head = seg.tail;
243                        mIndexContentDirty = true;
244                }
245                else
246                {
247                        if (seg.head == 0)
248                        {
249                                // Wrap backwards
250                                seg.head = mMaxElementsPerChain - 1;
251                        }
252                        else
253                        {
254                                // Just step backward
255                                --seg.head;
256                        }
257                        // Run out of elements?
258                        if (seg.head == seg.tail)
259                        {
260                                // Move tail backwards too, losing the end of the segment and re-using
261                                // it in the head
262                                if (seg.tail == 0)
263                                        seg.tail = mMaxElementsPerChain - 1;
264                                else
265                                        --seg.tail;
266                        }
267                }
268
269                // Set the details
270                mChainElementList[seg.start + seg.head] = dtls;
271
272                mIndexContentDirty = true;
273                mBoundsDirty = true;
274                // tell parent node to update bounds
275                if (mParentNode)
276                        mParentNode->needUpdate();
277
278        }
279        //-----------------------------------------------------------------------
280        void BillboardChain::removeChainElement(size_t chainIndex)
281        {
282                if (chainIndex >= mChainCount)
283                {
284                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
285                                "chainIndex out of bounds",
286                                "BillboardChain::removeChainElement");
287                }
288                ChainSegment& seg = mChainSegmentList[chainIndex];
289                if (seg.head == SEGMENT_EMPTY)
290                        return; // do nothing, nothing to remove
291
292
293                if (seg.tail == seg.head)
294                {
295                        // last item
296                        seg.head = seg.tail = SEGMENT_EMPTY;
297                }
298                else if (seg.tail == 0)
299                {
300                        seg.tail = mMaxElementsPerChain - 1;
301                }
302                else
303                {
304                        --seg.tail;
305                }
306
307                // we removed an entry so indexes need updating
308                mIndexContentDirty = true;
309                mBoundsDirty = true;
310                // tell parent node to update bounds
311                if (mParentNode)
312                        mParentNode->needUpdate();
313
314        }
315        //-----------------------------------------------------------------------
316        void BillboardChain::clearChain(size_t chainIndex)
317        {
318                if (chainIndex >= mChainCount)
319                {
320                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
321                                "chainIndex out of bounds",
322                                "BillboardChain::removeChainElement");
323                }
324                ChainSegment& seg = mChainSegmentList[chainIndex];
325
326                // Just reset head & tail
327                seg.tail = seg.head = SEGMENT_EMPTY;
328
329                // we removed an entry so indexes need updating
330                mIndexContentDirty = true;
331                mBoundsDirty = true;
332                // tell parent node to update bounds
333                if (mParentNode)
334                        mParentNode->needUpdate();
335
336        }
337        //-----------------------------------------------------------------------
338        void BillboardChain::clearAllChains(void)
339        {
340                for (size_t i = 0; i < mChainCount; ++i)
341                {
342                        clearChain(i);
343                }
344
345        }
346        //-----------------------------------------------------------------------
347        void BillboardChain::updateChainElement(size_t chainIndex, size_t elementIndex,
348                const BillboardChain::Element& dtls)
349        {
350                if (chainIndex >= mChainCount)
351                {
352                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
353                                "chainIndex out of bounds",
354                                "BillboardChain::updateChainElement");
355                }
356                ChainSegment& seg = mChainSegmentList[chainIndex];
357                if (seg.head == SEGMENT_EMPTY)
358                {
359                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
360                                "Chain segment is empty",
361                                "BillboardChain::updateChainElement");
362                }
363
364                size_t idx = seg.head + elementIndex;
365                // adjust for the edge and start
366                idx = (idx % mMaxElementsPerChain) + seg.start;
367
368                mChainElementList[idx] = dtls;
369
370                mBoundsDirty = true;
371                // tell parent node to update bounds
372                if (mParentNode)
373                        mParentNode->needUpdate();
374
375
376        }
377        //-----------------------------------------------------------------------
378        const BillboardChain::Element&
379        BillboardChain::getChainElement(size_t chainIndex, size_t elementIndex) const
380        {
381
382                if (chainIndex >= mChainCount)
383                {
384                        OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
385                                "chainIndex out of bounds",
386                                "BillboardChain::updateChainElement");
387                }
388                const ChainSegment& seg = mChainSegmentList[chainIndex];
389
390                size_t idx = seg.head + elementIndex;
391                // adjust for the edge and start
392                idx = (idx % mMaxElementsPerChain) + seg.start;
393
394                return mChainElementList[idx];
395        }
396        //-----------------------------------------------------------------------
397        void BillboardChain::updateBoundingBox(void) const
398        {
399                if (mBoundsDirty)
400                {
401                        mAABB.setNull();
402                        Vector3 widthVector;
403                        for (ChainSegmentList::const_iterator segi = mChainSegmentList.begin();
404                                segi != mChainSegmentList.end(); ++segi)
405                        {
406                                const ChainSegment& seg = *segi;
407
408                                if (seg.head != SEGMENT_EMPTY)
409                                {
410
411                                        for(size_t e = seg.head; ; ++e) // until break
412                                        {
413                                                // Wrap forwards
414                                                if (e == mMaxElementsPerChain)
415                                                        e = 0;
416
417                                                const Element& elem = mChainElementList[seg.start + e];
418
419                                                widthVector.x = widthVector.y = widthVector.z = elem.width;
420                                                mAABB.merge(elem.position - widthVector);
421                                                mAABB.merge(elem.position + widthVector);
422
423                                                if (e == seg.tail)
424                                                        break;
425
426                                        }
427                                }
428
429                        }
430
431                        // Set the current radius
432                        if (mAABB.isNull())
433                        {
434                                mRadius = 0.0f;
435                        }
436                        else
437                        {
438                                mRadius = Math::Sqrt(
439                                        std::max(mAABB.getMinimum().squaredLength(),
440                                        mAABB.getMaximum().squaredLength()));
441                        }
442
443                        mBoundsDirty = false;
444                }
445        }
446        //-----------------------------------------------------------------------
447        void BillboardChain::updateVertexBuffer(Camera* cam)
448        {
449                setupBuffers();
450                HardwareVertexBufferSharedPtr pBuffer =
451                        mVertexData->vertexBufferBinding->getBuffer(0);
452                void* pBufferStart = pBuffer->lock(HardwareBuffer::HBL_DISCARD);
453
454                const Vector3& camPos = cam->getDerivedPosition();
455                Vector3 eyePos = mParentNode->_getDerivedOrientation().Inverse() *
456                        (camPos - mParentNode->_getDerivedPosition()) / mParentNode->_getDerivedScale();
457
458                Vector3 chainTangent;
459                for (ChainSegmentList::iterator segi = mChainSegmentList.begin();
460                        segi != mChainSegmentList.end(); ++segi)
461                {
462                        ChainSegment& seg = *segi;
463
464                        // Skip 0 or 1 element segment counts
465                        if (seg.head != SEGMENT_EMPTY && seg.head != seg.tail)
466                        {
467                                size_t laste = seg.head;
468                                for (size_t e = seg.head; ; ++e) // until break
469                                {
470                                        // Wrap forwards
471                                        if (e == mMaxElementsPerChain)
472                                                e = 0;
473
474                                        Element& elem = mChainElementList[e + seg.start];
475                                        assert (((e + seg.start) * 2) < 65536 && "Too many elements!");
476                                        uint16 baseIdx = static_cast<uint16>((e + seg.start) * 2);
477
478                                        // Determine base pointer to vertex #1
479                                        void* pBase = static_cast<void*>(
480                                                static_cast<char*>(pBufferStart) +
481                                                        pBuffer->getVertexSize() * baseIdx);
482
483                                        // Get index of next item
484                                        size_t nexte = e + 1;
485                                        if (nexte == mMaxElementsPerChain)
486                                                nexte = 0;
487
488                                        if (e == seg.head)
489                                        {
490                                                // No laste, use next item
491                                                chainTangent = mChainElementList[nexte + seg.start].position - elem.position;
492                                        }
493                                        else if (e == seg.tail)
494                                        {
495                                                // No nexte, use only last item
496                                                chainTangent = elem.position - mChainElementList[laste + seg.start].position;
497                                        }
498                                        else
499                                        {
500                                                // A mid position, use tangent across both prev and next
501                                                chainTangent = mChainElementList[nexte + seg.start].position - mChainElementList[laste + seg.start].position;
502
503                                        }
504
505                                        Vector3 vP1ToEye = eyePos - elem.position;
506                                        Vector3 vPerpendicular = chainTangent.crossProduct(vP1ToEye);
507                                        vPerpendicular.normalise();
508                                        vPerpendicular *= (elem.width * 0.5);
509
510                                        Vector3 pos0 = elem.position - vPerpendicular;
511                                        Vector3 pos1 = elem.position + vPerpendicular;
512
513                                        float* pFloat = static_cast<float*>(pBase);
514                                        // pos1
515                                        *pFloat++ = pos0.x;
516                                        *pFloat++ = pos0.y;
517                                        *pFloat++ = pos0.z;
518
519                                        pBase = static_cast<void*>(pFloat);
520
521                                        if (mUseVertexColour)
522                                        {
523                                                RGBA* pCol = static_cast<RGBA*>(pBase);
524                                                Root::getSingleton().convertColourValue(elem.colour, pCol);
525                                                pCol++;
526                                                pBase = static_cast<void*>(pCol);
527                                        }
528
529                                        if (mUseTexCoords)
530                                        {
531                                                pFloat = static_cast<float*>(pBase);
532                                                if (mTexCoordDir == TCD_U)
533                                                {
534                                                        *pFloat++ = elem.texCoord;
535                                                        *pFloat++ = mOtherTexCoordRange[0];
536                                                }
537                                                else
538                                                {
539                                                        *pFloat++ = mOtherTexCoordRange[0];
540                                                        *pFloat++ = elem.texCoord;
541                                                }
542                                                pBase = static_cast<void*>(pFloat);
543                                        }
544
545                                        // pos2
546                                        pFloat = static_cast<float*>(pBase);
547                                        *pFloat++ = pos1.x;
548                                        *pFloat++ = pos1.y;
549                                        *pFloat++ = pos1.z;
550                                        pBase = static_cast<void*>(pFloat);
551
552                                        if (mUseVertexColour)
553                                        {
554                                                RGBA* pCol = static_cast<RGBA*>(pBase);
555                                                Root::getSingleton().convertColourValue(elem.colour, pCol);
556                                                pCol++;
557                                                pBase = static_cast<void*>(pCol);
558                                        }
559
560                                        if (mUseTexCoords)
561                                        {
562                                                pFloat = static_cast<float*>(pBase);
563                                                if (mTexCoordDir == TCD_U)
564                                                {
565                                                        *pFloat++ = elem.texCoord;
566                                                        *pFloat++ = mOtherTexCoordRange[1];
567                                                }
568                                                else
569                                                {
570                                                        *pFloat++ = mOtherTexCoordRange[1];
571                                                        *pFloat++ = elem.texCoord;
572                                                }
573                                                pBase = static_cast<void*>(pFloat);
574                                        }
575
576                                        if (e == seg.tail)
577                                                break; // last one
578
579                                        laste = e;
580
581                                } // element
582                        } // segment valid?
583
584                } // each segment
585
586
587
588                pBuffer->unlock();
589
590
591        }
592        //-----------------------------------------------------------------------
593        void BillboardChain::updateIndexBuffer(void)
594        {
595
596                setupBuffers();
597                if (mIndexContentDirty)
598                {
599
600                        uint16* pShort = static_cast<uint16*>(
601                                mIndexData->indexBuffer->lock(HardwareBuffer::HBL_DISCARD));
602                        mIndexData->indexCount = 0;
603                        // indexes
604                        for (ChainSegmentList::iterator segi = mChainSegmentList.begin();
605                                segi != mChainSegmentList.end(); ++segi)
606                        {
607                                ChainSegment& seg = *segi;
608
609                                // Skip 0 or 1 element segment counts
610                                if (seg.head != SEGMENT_EMPTY && seg.head != seg.tail)
611                                {
612                                        // Start from head + 1 since it's only useful in pairs
613                                        size_t laste = seg.head;
614                                        while(1) // until break
615                                        {
616                                                size_t e = laste + 1;
617                                                // Wrap forwards
618                                                if (e == mMaxElementsPerChain)
619                                                        e = 0;
620                                                // indexes of this element are (e * 2) and (e * 2) + 1
621                                                // indexes of the last element are the same, -2
622                                                assert (((e + seg.start) * 2) < 65536 && "Too many elements!");
623                                                uint16 baseIdx = static_cast<uint16>((e + seg.start) * 2);
624                                                uint16 lastBaseIdx = static_cast<uint16>((laste + seg.start) * 2);
625                                                *pShort++ = lastBaseIdx;
626                                                *pShort++ = lastBaseIdx + 1;
627                                                *pShort++ = baseIdx;
628                                                *pShort++ = lastBaseIdx + 1;
629                                                *pShort++ = baseIdx + 1;
630                                                *pShort++ = baseIdx;
631
632                                                mIndexData->indexCount += 6;
633
634
635                                                if (e == seg.tail)
636                                                        break; // last one
637
638                                                laste = e;
639
640                                        }
641                                }
642
643                        }
644                        mIndexData->indexBuffer->unlock();
645
646                        mIndexContentDirty = false;
647                }
648
649        }
650        //-----------------------------------------------------------------------
651        void BillboardChain::_notifyCurrentCamera(Camera* cam)
652        {
653                updateVertexBuffer(cam);
654        }
655        //-----------------------------------------------------------------------
656        Real BillboardChain::getSquaredViewDepth(const Camera* cam) const
657        {
658                Vector3 min, max, mid, dist;
659                min = mAABB.getMinimum();
660                max = mAABB.getMaximum();
661                mid = ((max - min) * 0.5) + min;
662                dist = cam->getDerivedPosition() - mid;
663
664                return dist.squaredLength();
665        }
666        //-----------------------------------------------------------------------
667        Real BillboardChain::getBoundingRadius(void) const
668        {
669                return mRadius;
670        }
671        //-----------------------------------------------------------------------
672        const AxisAlignedBox& BillboardChain::getBoundingBox(void) const
673        {
674                updateBoundingBox();
675                return mAABB;
676        }
677        //-----------------------------------------------------------------------
678        const MaterialPtr& BillboardChain::getMaterial(void) const
679        {
680                return mMaterial;
681        }
682        //-----------------------------------------------------------------------
683        void BillboardChain::setMaterialName(const String& name)
684        {
685                mMaterialName = name;
686                mMaterial = MaterialManager::getSingleton().getByName(mMaterialName);
687
688                if (mMaterial.isNull())
689                {
690                        LogManager::getSingleton().logMessage("Can't assign material " + name +
691                                " to BillboardChain " + mName + " because this "
692                                "Material does not exist. Have you forgotten to define it in a "
693                                ".material script?");
694                        mMaterial = MaterialManager::getSingleton().getByName("BaseWhiteNoLighting");
695                        if (mMaterial.isNull())
696                        {
697                                OGRE_EXCEPT(Exception::ERR_INTERNAL_ERROR, "Can't assign default material "
698                                        "to BillboardChain of " + mName + ". Did "
699                                        "you forget to call MaterialManager::initialise()?",
700                                        "BillboardChain.setMaterialName");
701                        }
702                }
703                // Ensure new material loaded (will not load again if already loaded)
704                mMaterial->load();
705        }
706        //-----------------------------------------------------------------------
707        const String& BillboardChain::getMovableType(void) const
708        {
709                return BillboardChainFactory::FACTORY_TYPE_NAME;
710        }
711        //-----------------------------------------------------------------------
712        void BillboardChain::_updateRenderQueue(RenderQueue* queue)
713        {
714                updateIndexBuffer();
715
716                if (mIndexData->indexCount > 0)
717                {
718            if (mRenderQueueIDSet)
719                queue->addRenderable(this, mRenderQueueID);
720            else
721                queue->addRenderable(this);
722                }
723
724        }
725        //-----------------------------------------------------------------------
726        void BillboardChain::getRenderOperation(RenderOperation& op)
727        {
728                op.indexData = mIndexData;
729                op.operationType = RenderOperation::OT_TRIANGLE_LIST;
730                op.srcRenderable = this;
731                op.useIndexes = true;
732                op.vertexData = mVertexData;
733        }
734        //-----------------------------------------------------------------------
735        void BillboardChain::getWorldTransforms(Matrix4* xform) const
736        {
737                *xform = _getParentNodeFullTransform();
738        }
739        //-----------------------------------------------------------------------
740        const Quaternion& BillboardChain::getWorldOrientation(void) const
741        {
742                return getParentNode()->_getDerivedOrientation();
743        }
744        //-----------------------------------------------------------------------
745        const Vector3& BillboardChain::getWorldPosition(void) const
746        {
747                return getParentNode()->_getDerivedPosition();
748        }
749        //-----------------------------------------------------------------------
750        const LightList& BillboardChain::getLights(void) const
751        {
752                return queryLights();
753        }
754        //-----------------------------------------------------------------------
755        //-----------------------------------------------------------------------
756        String BillboardChainFactory::FACTORY_TYPE_NAME = "BillboardChain";
757        //-----------------------------------------------------------------------
758        const String& BillboardChainFactory::getType(void) const
759        {
760                return FACTORY_TYPE_NAME;
761        }
762        //-----------------------------------------------------------------------
763        MovableObject* BillboardChainFactory::createInstanceImpl( const String& name,
764                const NameValuePairList* params)
765        {
766                size_t maxElements = 20;
767                size_t numberOfChains = 1;
768                bool useTex = true;
769                bool useCol = true;
770                bool dynamic = true;
771                // optional params
772                if (params != 0)
773                {
774                        NameValuePairList::const_iterator ni = params->find("maxElements");
775                        if (ni != params->end())
776                        {
777                                maxElements = StringConverter::parseUnsignedLong(ni->second);
778                        }
779                        ni = params->find("numberOfChains");
780                        if (ni != params->end())
781                        {
782                                numberOfChains = StringConverter::parseUnsignedLong(ni->second);
783                        }
784                        ni = params->find("useTextureCoords");
785                        if (ni != params->end())
786                        {
787                                useTex = StringConverter::parseBool(ni->second);
788                        }
789                        ni = params->find("useVertexColours");
790                        if (ni != params->end())
791                        {
792                                useCol = StringConverter::parseBool(ni->second);
793                        }
794                        ni = params->find("dynamic");
795                        if (ni != params->end())
796                        {
797                                dynamic = StringConverter::parseBool(ni->second);
798                        }
799
800                }
801
802                return new BillboardChain(name, maxElements, numberOfChains, useTex, useCol, dynamic);
803
804        }
805        //-----------------------------------------------------------------------
806        void BillboardChainFactory::destroyInstance( MovableObject* obj)
807        {
808                delete obj;
809        }
810
811}
812
Note: See TracBrowser for help on using the repository browser.