Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/OgreMain/src/OgreVertexIndexData.cpp @ 1

Last change on this file since 1 was 1, checked in by landauf, 17 years ago
File size: 34.0 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#include "OgreStableHeaders.h"
30#include "OgreVertexIndexData.h"
31#include "OgreHardwareBufferManager.h"
32#include "OgreHardwareVertexBuffer.h"
33#include "OgreHardwareIndexBuffer.h"
34#include "OgreVector3.h"
35#include "OgreAxisAlignedBox.h"
36#include "OgreRoot.h"
37#include "OgreRenderSystem.h"
38#include "OgreException.h"
39
40namespace Ogre {
41
42    //-----------------------------------------------------------------------
43        VertexData::VertexData()
44        {
45                vertexBufferBinding = HardwareBufferManager::getSingleton().
46                        createVertexBufferBinding();
47                vertexDeclaration = HardwareBufferManager::getSingleton().
48                        createVertexDeclaration();
49                vertexCount = 0;
50                vertexStart = 0;
51                hwAnimDataItemsUsed = 0;
52
53        }
54    //-----------------------------------------------------------------------
55        VertexData::~VertexData()
56        {
57                HardwareBufferManager::getSingleton().
58                        destroyVertexBufferBinding(vertexBufferBinding);
59                HardwareBufferManager::getSingleton().destroyVertexDeclaration(vertexDeclaration);
60
61        }
62    //-----------------------------------------------------------------------
63        VertexData* VertexData::clone(bool copyData) const
64        {
65                VertexData* dest = new VertexData();
66
67                // Copy vertex buffers in turn
68                const VertexBufferBinding::VertexBufferBindingMap& bindings = 
69                        this->vertexBufferBinding->getBindings();
70                VertexBufferBinding::VertexBufferBindingMap::const_iterator vbi, vbend;
71                vbend = bindings.end();
72                for (vbi = bindings.begin(); vbi != vbend; ++vbi)
73                {
74                        HardwareVertexBufferSharedPtr srcbuf = vbi->second;
75            HardwareVertexBufferSharedPtr dstBuf;
76            if (copyData)
77            {
78                            // create new buffer with the same settings
79                            dstBuf = 
80                                    HardwareBufferManager::getSingleton().createVertexBuffer(
81                                            srcbuf->getVertexSize(), srcbuf->getNumVertices(), srcbuf->getUsage(),
82                                            srcbuf->hasShadowBuffer());
83
84                            // copy data
85                            dstBuf->copyData(*srcbuf, 0, 0, srcbuf->getSizeInBytes(), true);
86            }
87            else
88            {
89                // don't copy, point at existing buffer
90                dstBuf = srcbuf;
91            }
92
93                        // Copy binding
94                        dest->vertexBufferBinding->setBinding(vbi->first, dstBuf);
95        }
96
97        // Basic vertex info
98        dest->vertexStart = this->vertexStart;
99                dest->vertexCount = this->vertexCount;
100        // Copy elements
101        const VertexDeclaration::VertexElementList elems = 
102            this->vertexDeclaration->getElements();
103        VertexDeclaration::VertexElementList::const_iterator ei, eiend;
104        eiend = elems.end();
105        for (ei = elems.begin(); ei != eiend; ++ei)
106        {
107            dest->vertexDeclaration->addElement(
108                ei->getSource(),
109                ei->getOffset(),
110                ei->getType(),
111                ei->getSemantic(),
112                ei->getIndex() );
113        }
114
115                // Copy reference to hardware shadow buffer, no matter whether copy data or not
116        dest->hardwareShadowVolWBuffer = hardwareShadowVolWBuffer;
117
118                // copy anim data
119                dest->hwAnimationDataList = hwAnimationDataList;
120                dest->hwAnimDataItemsUsed = hwAnimDataItemsUsed;
121
122       
123        return dest;
124        }
125    //-----------------------------------------------------------------------
126    void VertexData::prepareForShadowVolume(void)
127    {
128        /* NOTE
129        I would dearly, dearly love to just use a 4D position buffer in order to
130        store the extra 'w' value I need to differentiate between extruded and
131        non-extruded sections of the buffer, so that vertex programs could use that.
132        Hey, it works fine for GL. However, D3D9 in it's infinite stupidity, does not
133        support 4d position vertices in the fixed-function pipeline. If you use them,
134        you just see nothing. Since we can't know whether the application is going to use
135        fixed function or vertex programs, we have to stick to 3d position vertices and
136        store the 'w' in a separate 1D texture coordinate buffer, which is only used
137        when rendering the shadow.
138        */
139
140        // Upfront, lets check whether we have vertex program capability
141        RenderSystem* rend = Root::getSingleton().getRenderSystem();
142        bool useVertexPrograms = false;
143        if (rend && rend->getCapabilities()->hasCapability(RSC_VERTEX_PROGRAM))
144        {
145            useVertexPrograms = true;
146        }
147
148
149        // Look for a position element
150        const VertexElement* posElem = vertexDeclaration->findElementBySemantic(VES_POSITION);
151        if (posElem)
152        {
153            size_t v;
154            unsigned posOldSource = posElem->getSource();
155
156            HardwareVertexBufferSharedPtr vbuf = vertexBufferBinding->getBuffer(posOldSource);
157            bool wasSharedBuffer = false;
158            // Are there other elements in the buffer except for the position?
159            if (vbuf->getVertexSize() > posElem->getSize())
160            {
161                // We need to create another buffer to contain the remaining elements
162                // Most drivers don't like gaps in the declaration, and in any case it's waste
163                wasSharedBuffer = true;
164            }
165            HardwareVertexBufferSharedPtr newPosBuffer, newRemainderBuffer;
166            if (wasSharedBuffer)
167            {
168                newRemainderBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
169                    vbuf->getVertexSize() - posElem->getSize(), vbuf->getNumVertices(), vbuf->getUsage(),
170                    vbuf->hasShadowBuffer());
171            }
172            // Allocate new position buffer, will be FLOAT3 and 2x the size
173            size_t oldVertexCount = vbuf->getNumVertices();
174            size_t newVertexCount = oldVertexCount * 2;
175            newPosBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
176                VertexElement::getTypeSize(VET_FLOAT3), newVertexCount, vbuf->getUsage(), 
177                vbuf->hasShadowBuffer());
178
179            // Iterate over the old buffer, copying the appropriate elements and initialising the rest
180            float* pSrc;
181            unsigned char *pBaseSrc = static_cast<unsigned char*>(
182                vbuf->lock(HardwareBuffer::HBL_READ_ONLY));
183            // Point first destination pointer at the start of the new position buffer,
184            // the other one half way along
185            float *pDest = static_cast<float*>(newPosBuffer->lock(HardwareBuffer::HBL_DISCARD));
186            float* pDest2 = pDest + oldVertexCount * 3; 
187
188            // Precalculate any dimensions of vertex areas outside the position
189            size_t prePosVertexSize = 0, postPosVertexSize, postPosVertexOffset;
190            unsigned char *pBaseDestRem = 0;
191            if (wasSharedBuffer)
192            {
193                pBaseDestRem = static_cast<unsigned char*>(
194                    newRemainderBuffer->lock(HardwareBuffer::HBL_DISCARD));
195                prePosVertexSize = posElem->getOffset();
196                postPosVertexOffset = prePosVertexSize + posElem->getSize();
197                postPosVertexSize = vbuf->getVertexSize() - postPosVertexOffset;
198                // the 2 separate bits together should be the same size as the remainder buffer vertex
199                assert (newRemainderBuffer->getVertexSize() == prePosVertexSize + postPosVertexSize);
200
201                // Iterate over the vertices
202                for (v = 0; v < oldVertexCount; ++v)
203                {
204                    // Copy position, into both buffers
205                    posElem->baseVertexPointerToElement(pBaseSrc, &pSrc);
206                    *pDest++ = *pDest2++ = *pSrc++;
207                    *pDest++ = *pDest2++ = *pSrc++;
208                    *pDest++ = *pDest2++ = *pSrc++;
209
210                    // now deal with any other elements
211                    // Basically we just memcpy the vertex excluding the position
212                    if (prePosVertexSize > 0)
213                        memcpy(pBaseDestRem, pBaseSrc, prePosVertexSize);
214                    if (postPosVertexSize > 0)
215                        memcpy(pBaseDestRem + prePosVertexSize, 
216                            pBaseSrc + postPosVertexOffset, postPosVertexSize);
217                    pBaseDestRem += newRemainderBuffer->getVertexSize();
218
219                    pBaseSrc += vbuf->getVertexSize();
220
221                } // next vertex
222            }
223            else
224            {
225                // Unshared buffer, can block copy the whole thing
226                memcpy(pDest, pBaseSrc, vbuf->getSizeInBytes());
227                memcpy(pDest2, pBaseSrc, vbuf->getSizeInBytes());
228            }
229
230            vbuf->unlock();
231            newPosBuffer->unlock();
232            if (wasSharedBuffer)
233                newRemainderBuffer->unlock();
234
235            // At this stage, he original vertex buffer is going to be destroyed
236            // So we should force the deallocation of any temporary copies
237            HardwareBufferManager::getSingleton()._forceReleaseBufferCopies(vbuf);
238
239            if (useVertexPrograms)
240            {
241                // Now it's time to set up the w buffer
242                hardwareShadowVolWBuffer = HardwareBufferManager::getSingleton().createVertexBuffer(
243                    sizeof(float), newVertexCount, HardwareBuffer::HBU_STATIC_WRITE_ONLY, false);
244                // Fill the first half with 1.0, second half with 0.0
245                pDest = static_cast<float*>(
246                    hardwareShadowVolWBuffer->lock(HardwareBuffer::HBL_DISCARD));
247                for (v = 0; v < oldVertexCount; ++v)
248                {
249                    *pDest++ = 1.0f;
250                }
251                for (v = 0; v < oldVertexCount; ++v)
252                {
253                    *pDest++ = 0.0f;
254                }
255                hardwareShadowVolWBuffer->unlock();
256            }
257
258            unsigned short newPosBufferSource; 
259            if (wasSharedBuffer)
260            {
261                // Get the a new buffer binding index
262                newPosBufferSource= vertexBufferBinding->getNextIndex();
263                // Re-bind the old index to the remainder buffer
264                vertexBufferBinding->setBinding(posOldSource, newRemainderBuffer);
265            }
266            else
267            {
268                // We can just re-use the same source idex for the new position buffer
269                newPosBufferSource = posOldSource;
270            }
271            // Bind the new position buffer
272            vertexBufferBinding->setBinding(newPosBufferSource, newPosBuffer);
273
274            // Now, alter the vertex declaration to change the position source
275            // and the offsets of elements using the same buffer
276            VertexDeclaration::VertexElementList::const_iterator elemi = 
277                vertexDeclaration->getElements().begin();
278            VertexDeclaration::VertexElementList::const_iterator elemiend = 
279                vertexDeclaration->getElements().end();
280            unsigned short idx;
281            for(idx = 0; elemi != elemiend; ++elemi, ++idx) 
282            {
283                if (&(*elemi) == posElem)
284                {
285                    // Modify position to point at new position buffer
286                    vertexDeclaration->modifyElement(
287                        idx, 
288                        newPosBufferSource, // new source buffer
289                        0, // no offset now
290                        VET_FLOAT3, 
291                        VES_POSITION);
292                }
293                else if (wasSharedBuffer &&
294                    elemi->getSource() == posOldSource &&
295                    elemi->getOffset() > prePosVertexSize )
296                {
297                    // This element came after position, remove the position's
298                    // size
299                    vertexDeclaration->modifyElement(
300                        idx, 
301                        posOldSource, // same old source
302                        elemi->getOffset() - posElem->getSize(), // less offset now
303                        elemi->getType(), 
304                        elemi->getSemantic(),
305                        elemi->getIndex());
306
307                }
308
309            }
310
311
312            // Note that we don't change vertexCount, because the other buffer(s) are still the same
313            // size after all
314
315
316        }
317    }
318        //-----------------------------------------------------------------------
319        void VertexData::reorganiseBuffers(VertexDeclaration* newDeclaration, const BufferUsageList& bufferUsages)
320        {
321        // Firstly, close up any gaps in the buffer sources which might have arisen
322        newDeclaration->closeGapsInSource();
323
324                // Build up a list of both old and new elements in each buffer
325                unsigned short buf = 0;
326                std::vector<void*> oldBufferLocks;
327        std::vector<size_t> oldBufferVertexSizes;
328                std::vector<void*> newBufferLocks;
329        std::vector<size_t> newBufferVertexSizes;
330                VertexBufferBinding* newBinding = 
331                        HardwareBufferManager::getSingleton().createVertexBufferBinding();
332        const VertexBufferBinding::VertexBufferBindingMap& oldBindingMap = vertexBufferBinding->getBindings();
333        VertexBufferBinding::VertexBufferBindingMap::const_iterator itBinding;
334
335        // Pre-allocate old buffer locks
336        if (!oldBindingMap.empty())
337        {
338            size_t count = oldBindingMap.rbegin()->first + 1;
339            oldBufferLocks.resize(count);
340            oldBufferVertexSizes.resize(count);
341        }
342                // Lock all the old buffers for reading
343        for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding)
344        {
345            assert(itBinding->second->getNumVertices() >= vertexCount);
346
347            oldBufferVertexSizes[itBinding->first] =
348                itBinding->second->getVertexSize();
349            oldBufferLocks[itBinding->first] =
350                itBinding->second->lock(
351                    HardwareBuffer::HBL_READ_ONLY);
352        }
353               
354                // Create new buffers and lock all for writing
355                buf = 0;
356                while (!newDeclaration->findElementsBySource(buf).empty())
357                {
358            size_t vertexSize = newDeclaration->getVertexSize(buf);
359
360                        HardwareVertexBufferSharedPtr vbuf = 
361                                HardwareBufferManager::getSingleton().createVertexBuffer(
362                                        vertexSize,
363                                        vertexCount, 
364                                        bufferUsages[buf]);
365                        newBinding->setBinding(buf, vbuf);
366
367            newBufferVertexSizes.push_back(vertexSize);
368                        newBufferLocks.push_back(
369                                vbuf->lock(HardwareBuffer::HBL_DISCARD));
370                        buf++;
371                }
372
373                // Map from new to old elements
374        typedef std::map<const VertexElement*, const VertexElement*> NewToOldElementMap;
375                NewToOldElementMap newToOldElementMap;
376                const VertexDeclaration::VertexElementList& newElemList = newDeclaration->getElements();
377                VertexDeclaration::VertexElementList::const_iterator ei, eiend;
378                eiend = newElemList.end();
379                for (ei = newElemList.begin(); ei != eiend; ++ei)
380                {
381                        // Find corresponding old element
382                        const VertexElement* oldElem = 
383                                vertexDeclaration->findElementBySemantic(
384                                        (*ei).getSemantic(), (*ei).getIndex());
385                        if (!oldElem)
386                        {
387                                // Error, cannot create new elements with this method
388                                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, 
389                                        "Element not found in old vertex declaration", 
390                                        "VertexData::reorganiseBuffers");
391                        }
392                        newToOldElementMap[&(*ei)] = oldElem;
393                }
394                // Now iterate over the new buffers, pulling data out of the old ones
395                // For each vertex
396                for (size_t v = 0; v < vertexCount; ++v)
397                {
398                        // For each (new) element
399                        for (ei = newElemList.begin(); ei != eiend; ++ei)
400                        {
401                                const VertexElement* newElem = &(*ei);
402                NewToOldElementMap::iterator noi = newToOldElementMap.find(newElem);
403                                const VertexElement* oldElem = noi->second;
404                                unsigned short oldBufferNo = oldElem->getSource();
405                                unsigned short newBufferNo = newElem->getSource();
406                                void* pSrcBase = static_cast<void*>(
407                                        static_cast<unsigned char*>(oldBufferLocks[oldBufferNo])
408                                        + v * oldBufferVertexSizes[oldBufferNo]);
409                                void* pDstBase = static_cast<void*>(
410                                        static_cast<unsigned char*>(newBufferLocks[newBufferNo])
411                                        + v * newBufferVertexSizes[newBufferNo]);
412                                void *pSrc, *pDst;
413                                oldElem->baseVertexPointerToElement(pSrcBase, &pSrc);
414                                newElem->baseVertexPointerToElement(pDstBase, &pDst);
415                               
416                                memcpy(pDst, pSrc, newElem->getSize());
417                               
418                        }
419                }
420
421                // Unlock all buffers
422        for (itBinding = oldBindingMap.begin(); itBinding != oldBindingMap.end(); ++itBinding)
423        {
424            itBinding->second->unlock();
425        }
426        for (buf = 0; buf < newBinding->getBufferCount(); ++buf)
427        {
428            newBinding->getBuffer(buf)->unlock();
429        }
430
431                // Delete old binding & declaration
432                HardwareBufferManager::getSingleton().
433                        destroyVertexBufferBinding(vertexBufferBinding);
434                HardwareBufferManager::getSingleton().destroyVertexDeclaration(vertexDeclaration);
435
436                // Assign new binding and declaration
437                vertexDeclaration = newDeclaration;
438                vertexBufferBinding = newBinding;               
439
440        }
441    //-----------------------------------------------------------------------
442    void VertexData::reorganiseBuffers(VertexDeclaration* newDeclaration)
443    {
444        // Derive the buffer usages from looking at where the source has come
445        // from
446        BufferUsageList usages;
447        for (unsigned short b = 0; b <= newDeclaration->getMaxSource(); ++b)
448        {
449            VertexDeclaration::VertexElementList destElems = newDeclaration->findElementsBySource(b);
450            // Initialise with most restrictive version
451            // (not really a usable option, but these flags will be removed)
452            HardwareBuffer::Usage final = static_cast<HardwareBuffer::Usage>(
453                HardwareBuffer::HBU_STATIC_WRITE_ONLY | HardwareBuffer::HBU_DISCARDABLE);
454            VertexDeclaration::VertexElementList::iterator v;
455            for (v = destElems.begin(); v != destElems.end(); ++v)
456            {
457                VertexElement& destelem = *v;
458                // get source
459                const VertexElement* srcelem =
460                    vertexDeclaration->findElementBySemantic(
461                        destelem.getSemantic(), destelem.getIndex());
462                // get buffer
463                HardwareVertexBufferSharedPtr srcbuf = 
464                    vertexBufferBinding->getBuffer(srcelem->getSource());
465                // improve flexibility only
466                if (srcbuf->getUsage() & HardwareBuffer::HBU_DYNAMIC)
467                {
468                    // remove static
469                    final = static_cast<HardwareBuffer::Usage>(
470                        final & ~HardwareBuffer::HBU_STATIC);
471                    // add dynamic
472                    final = static_cast<HardwareBuffer::Usage>(
473                        final | HardwareBuffer::HBU_DYNAMIC);
474                }
475                if (!(srcbuf->getUsage() & HardwareBuffer::HBU_WRITE_ONLY))
476                {
477                    // remove write only
478                    final = static_cast<HardwareBuffer::Usage>(
479                        final & ~HardwareBuffer::HBU_WRITE_ONLY);
480                }
481                if (!(srcbuf->getUsage() & HardwareBuffer::HBU_DISCARDABLE))
482                {
483                    // remove discardable
484                    final = static_cast<HardwareBuffer::Usage>(
485                        final & ~HardwareBuffer::HBU_DISCARDABLE);
486                }
487               
488            }
489            usages.push_back(final);
490        }
491        // Call specific method
492        reorganiseBuffers(newDeclaration, usages);
493
494    }
495    //-----------------------------------------------------------------------
496    void VertexData::closeGapsInBindings(void)
497    {
498        if (!vertexBufferBinding->hasGaps())
499            return;
500
501        // Check for error first
502        const VertexDeclaration::VertexElementList& allelems = 
503            vertexDeclaration->getElements();
504        VertexDeclaration::VertexElementList::const_iterator ai;
505        for (ai = allelems.begin(); ai != allelems.end(); ++ai)
506        {
507            const VertexElement& elem = *ai;
508            if (!vertexBufferBinding->isBufferBound(elem.getSource()))
509            {
510                OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
511                    "No buffer is bound to that element source.",
512                    "VertexData::closeGapsInBindings");
513            }
514        }
515
516        // Close gaps in the vertex buffer bindings
517        VertexBufferBinding::BindingIndexMap bindingIndexMap;
518        vertexBufferBinding->closeGaps(bindingIndexMap);
519
520        // Modify vertex elements to reference to new buffer index
521        unsigned short elemIndex = 0;
522        for (ai = allelems.begin(); ai != allelems.end(); ++ai, ++elemIndex)
523        {
524            const VertexElement& elem = *ai;
525            VertexBufferBinding::BindingIndexMap::const_iterator it =
526                bindingIndexMap.find(elem.getSource());
527            assert(it != bindingIndexMap.end());
528            ushort targetSource = it->second;
529            if (elem.getSource() != targetSource)
530            {
531                vertexDeclaration->modifyElement(elemIndex, 
532                    targetSource, elem.getOffset(), elem.getType(), 
533                    elem.getSemantic(), elem.getIndex());
534            }
535        }
536    }
537    //-----------------------------------------------------------------------
538    void VertexData::removeUnusedBuffers(void)
539    {
540        std::set<ushort> usedBuffers;
541
542        // Collect used buffers
543        const VertexDeclaration::VertexElementList& allelems = 
544            vertexDeclaration->getElements();
545        VertexDeclaration::VertexElementList::const_iterator ai;
546        for (ai = allelems.begin(); ai != allelems.end(); ++ai)
547        {
548            const VertexElement& elem = *ai;
549            usedBuffers.insert(elem.getSource());
550        }
551
552        // Unset unused buffer bindings
553        ushort count = vertexBufferBinding->getLastBoundIndex();
554        for (ushort index = 0; index < count; ++index)
555        {
556            if (usedBuffers.find(index) == usedBuffers.end() &&
557                vertexBufferBinding->isBufferBound(index))
558            {
559                vertexBufferBinding->unsetBinding(index);
560            }
561        }
562
563        // Close gaps
564        closeGapsInBindings();
565    }
566        //-----------------------------------------------------------------------
567        void VertexData::convertPackedColour(
568                VertexElementType srcType, VertexElementType destType)
569        {
570                if (destType != VET_COLOUR_ABGR && destType != VET_COLOUR_ARGB)
571                {
572                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
573                                "Invalid destType parameter", "VertexData::convertPackedColour");
574                }
575                if (srcType != VET_COLOUR_ABGR && srcType != VET_COLOUR_ARGB)
576                {
577                        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS,
578                                "Invalid srcType parameter", "VertexData::convertPackedColour");
579                }
580
581                const VertexBufferBinding::VertexBufferBindingMap& bindMap = 
582                        vertexBufferBinding->getBindings();
583                VertexBufferBinding::VertexBufferBindingMap::const_iterator bindi;
584                for (bindi = bindMap.begin(); bindi != bindMap.end(); ++bindi)
585                {
586                        VertexDeclaration::VertexElementList elems = 
587                                vertexDeclaration->findElementsBySource(bindi->first);
588                        bool conversionNeeded = false;
589                        VertexDeclaration::VertexElementList::iterator elemi;
590                        for (elemi = elems.begin(); elemi != elems.end(); ++elemi)
591                        {
592                                VertexElement& elem = *elemi;
593                                if (elem.getType() == VET_COLOUR || 
594                                        ((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB) 
595                                        && elem.getType() != destType))
596                                {
597                                        conversionNeeded = true;
598                                }
599                        }
600
601                        if (conversionNeeded)
602                        {
603                                void* pBase = bindi->second->lock(HardwareBuffer::HBL_NORMAL);
604
605                                for (size_t v = 0; v < bindi->second->getNumVertices(); ++v)
606                                {
607
608                                        for (elemi = elems.begin(); elemi != elems.end(); ++elemi)
609                                        {
610                                                VertexElement& elem = *elemi;
611                                                VertexElementType currType = (elem.getType() == VET_COLOUR) ?
612                                                        srcType : elem.getType();
613                                                if (elem.getType() == VET_COLOUR || 
614                                                        ((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB) 
615                                                        && elem.getType() != destType))
616                                                {
617                                                        uint32* pRGBA;
618                                                        elem.baseVertexPointerToElement(pBase, &pRGBA);
619                                                        VertexElement::convertColourValue(currType, destType, pRGBA);
620                                                }
621                                        }
622                                        pBase = static_cast<void*>(
623                                                static_cast<char*>(pBase) + bindi->second->getVertexSize());
624                                }
625                                bindi->second->unlock();
626
627                                // Modify the elements to reflect the changed type
628                                const VertexDeclaration::VertexElementList& allelems = 
629                                        vertexDeclaration->getElements();
630                                VertexDeclaration::VertexElementList::const_iterator ai;
631                                unsigned short elemIndex = 0;
632                                for (ai = allelems.begin(); ai != allelems.end(); ++ai, ++elemIndex)
633                                {
634                                        const VertexElement& elem = *ai;
635                                        if (elem.getType() == VET_COLOUR || 
636                                                ((elem.getType() == VET_COLOUR_ABGR || elem.getType() == VET_COLOUR_ARGB) 
637                                                && elem.getType() != destType))
638                                        {
639                                                vertexDeclaration->modifyElement(elemIndex, 
640                                                        elem.getSource(), elem.getOffset(), destType, 
641                                                        elem.getSemantic(), elem.getIndex());
642                                        }
643                                }
644
645                        }
646
647
648                } // each buffer
649
650
651        }
652        //-----------------------------------------------------------------------
653        void VertexData::allocateHardwareAnimationElements(ushort count)
654        {
655                // Find first free texture coord set
656                unsigned short texCoord = 0;
657                const VertexDeclaration::VertexElementList& vel = vertexDeclaration->getElements();
658                for (VertexDeclaration::VertexElementList::const_iterator i = vel.begin(); 
659                        i != vel.end(); ++i)
660                {
661                        const VertexElement& el = *i;
662                        if (el.getSemantic() == VES_TEXTURE_COORDINATES)
663                        {
664                                ++texCoord;
665                        }
666                }
667                assert(texCoord <= OGRE_MAX_TEXTURE_COORD_SETS);
668
669                // Increase to correct size
670                for (size_t c = hwAnimationDataList.size(); c < count; ++c)
671                {
672                        // Create a new 3D texture coordinate set
673                        HardwareAnimationData data;
674                        data.targetVertexElement = &(vertexDeclaration->addElement(
675                                vertexBufferBinding->getNextIndex(), 0, VET_FLOAT3, VES_TEXTURE_COORDINATES, texCoord++));
676
677                        hwAnimationDataList.push_back(data);
678                        // Vertex buffer will not be bound yet, we expect this to be done by the
679                        // caller when it becomes appropriate (e.g. through a VertexAnimationTrack)
680                }
681        }
682    //-----------------------------------------------------------------------
683        //-----------------------------------------------------------------------
684        IndexData::IndexData()
685        {
686                indexCount = 0;
687                indexStart = 0;
688               
689        }
690    //-----------------------------------------------------------------------
691        IndexData::~IndexData()
692        {
693        }
694    //-----------------------------------------------------------------------
695        IndexData* IndexData::clone(bool copyData) const
696        {
697                IndexData* dest = new IndexData();
698                if (indexBuffer.get())
699                {
700            if (copyData)
701            {
702                            dest->indexBuffer = HardwareBufferManager::getSingleton().
703                                    createIndexBuffer(indexBuffer->getType(), indexBuffer->getNumIndexes(),
704                                    indexBuffer->getUsage(), indexBuffer->hasShadowBuffer());
705                            dest->indexBuffer->copyData(*indexBuffer, 0, 0, indexBuffer->getSizeInBytes(), true);
706            }
707            else
708            {
709                dest->indexBuffer = indexBuffer;
710            }
711        }
712                dest->indexCount = indexCount;
713                dest->indexStart = indexStart;
714                return dest;
715        }
716    //-----------------------------------------------------------------------
717    //-----------------------------------------------------------------------
718        // Local Utility class for vertex cache optimizer
719        class Triangle
720    {
721    public:
722                enum EdgeMatchType {
723                        AB, BC, CA, ANY, NONE
724                };
725
726                uint32 a, b, c;         
727
728                inline Triangle()
729                {
730                }
731
732                inline Triangle( uint32 ta, uint32 tb, uint32 tc ) 
733                        : a( ta ), b( tb ), c( tc )
734                {
735                }
736
737                inline Triangle( uint32 t[3] )
738                        : a( t[0] ), b( t[1] ), c( t[2] )
739                {
740                }
741
742                inline Triangle( const Triangle& t )
743                        : a( t.a ), b( t.b ), c( t.c )
744                {
745                }
746
747                inline bool sharesEdge(const Triangle& t) const
748                {
749                        return( a == t.a && b == t.c ||
750                                        a == t.b && b == t.a ||
751                                        a == t.c && b == t.b ||
752                                        b == t.a && c == t.c ||
753                                        b == t.b && c == t.a ||
754                                        b == t.c && c == t.b ||
755                                        c == t.a && a == t.c ||
756                                        c == t.b && a == t.a ||
757                                        c == t.c && a == t.b );
758                }
759
760                inline bool sharesEdge(const uint32 ea, const uint32 eb, const Triangle& t) const
761                {
762                        return( ea == t.a && eb == t.c ||
763                                        ea == t.b && eb == t.a ||
764                                        ea == t.c && eb == t.b );       
765                }
766
767                inline bool sharesEdge(const EdgeMatchType edge, const Triangle& t) const
768                {
769                        if (edge == AB)
770                                return sharesEdge(a, b, t);
771                        else if (edge == BC)
772                                return sharesEdge(b, c, t);
773                        else if (edge == CA)
774                                return sharesEdge(c, a, t);
775                        else
776                                return (edge == ANY) == sharesEdge(t);
777                }
778
779                inline EdgeMatchType endoSharedEdge(const Triangle& t) const
780                {
781                        if (sharesEdge(a, b, t)) return AB;
782                        if (sharesEdge(b, c, t)) return BC;
783                        if (sharesEdge(c, a, t)) return CA;
784                        return NONE;
785                }
786
787                inline EdgeMatchType exoSharedEdge(const Triangle& t) const
788                {
789                        return t.endoSharedEdge(*this);
790                }
791
792                inline void shiftClockwise()
793                {
794                        uint32 t = a;
795                        a = c;
796                        c = b;
797                        b = t;
798                }
799
800                inline void shiftCounterClockwise()
801                {
802                        uint32 t = a;
803                        a = b;
804                        b = c;
805                        c = t;
806                }
807        };
808    //-----------------------------------------------------------------------
809    //-----------------------------------------------------------------------
810        void IndexData::optimiseVertexCacheTriList(void)
811        {
812                if (indexBuffer->isLocked()) return;
813
814                void *buffer = indexBuffer->lock(HardwareBuffer::HBL_NORMAL);
815
816                Triangle* triangles;
817                uint32 *dest;
818
819                size_t nIndexes = indexCount;
820                size_t nTriangles = nIndexes / 3;
821                size_t i, j;
822                uint16 *source;
823
824                if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT)
825                {
826                        triangles = new Triangle[nTriangles];
827                        source = (uint16 *)buffer;
828                        dest = (uint32 *)triangles;
829                        for (i = 0; i < nIndexes; ++i) dest[i] = source[i];
830                }
831                else
832                        triangles = (Triangle*)buffer;
833
834                // sort triangles based on shared edges
835                uint32 *destlist = new uint32[nTriangles];
836                unsigned char *visited = new unsigned char[nTriangles];
837
838                for (i = 0; i < nTriangles; ++i) visited[i] = 0;
839
840                uint32 start = 0, ti = 0, destcount = 0;
841
842                bool found = false;
843                for (i = 0; i < nTriangles; ++i)
844                {
845                        if (found)
846                                found = false;
847                        else
848                        {
849                                while (visited[start++]);
850                                ti = start - 1;
851                        }
852
853                        destlist[destcount++] = ti;
854                        visited[ti] = 1;
855
856                        for (j = start; j < nTriangles; ++j)
857                        {
858                                if (visited[j]) continue;
859                               
860                                if (triangles[ti].sharesEdge(triangles[j]))
861                                {
862                                        found = true;
863                                        ti = static_cast<uint32>(j);
864                                        break;
865                                }
866                        }
867                }
868
869                if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT)
870                {
871                        // reorder the indexbuffer
872                        j = 0;
873                        for (i = 0; i < nTriangles; ++i)
874                        {
875                                Triangle *t = &triangles[destlist[i]];
876                                source[j++] = t->a;
877                                source[j++] = t->b;
878                                source[j++] = t->c;
879                        }
880                        delete[] triangles;
881                }
882                else
883                {
884                        uint32 *reflist = new uint32[nTriangles];
885
886                        // fill the referencebuffer
887                        for (i = 0; i < nTriangles; ++i)
888                                reflist[destlist[i]] = static_cast<uint32>(i);
889                       
890                        // reorder the indexbuffer
891                        for (i = 0; i < nTriangles; ++i)
892                        {
893                                j = destlist[i];
894                                if (i == j) continue; // do not move triangle
895
896                                // swap triangles
897
898                                Triangle t = triangles[i];
899                                triangles[i] = triangles[j];
900                                triangles[j] = t;
901
902                                // change reference
903                                destlist[reflist[i]] = static_cast<uint32>(j);
904                                // destlist[i] = i; // not needed, it will not be used
905                        }
906
907                        delete[] reflist;
908                }
909
910                delete[] destlist;
911                delete[] visited;
912                                       
913                indexBuffer->unlock();
914        }
915        //-----------------------------------------------------------------------
916        //-----------------------------------------------------------------------
917        void VertexCacheProfiler::profile(const HardwareIndexBufferSharedPtr& indexBuffer)
918    {
919                if (indexBuffer->isLocked()) return;
920
921                uint16 *shortbuffer = (uint16 *)indexBuffer->lock(HardwareBuffer::HBL_READ_ONLY);
922
923                if (indexBuffer->getType() == HardwareIndexBuffer::IT_16BIT)
924                        for (unsigned int i = 0; i < indexBuffer->getNumIndexes(); ++i)
925                                inCache(shortbuffer[i]);
926                else
927                {
928                        uint32 *buffer = (uint32 *)shortbuffer;
929                        for (unsigned int i = 0; i < indexBuffer->getNumIndexes(); ++i)
930                                inCache(buffer[i]);
931                }
932
933                indexBuffer->unlock();
934        }
935
936        //-----------------------------------------------------------------------
937        bool VertexCacheProfiler::inCache(unsigned int index)
938        {
939                for (unsigned int i = 0; i < buffersize; ++i)
940                {
941                        if (index == cache[i])
942                        {
943                                hit++;
944                                return true;
945                        }
946                }
947
948                miss++;
949                cache[tail++] = index;
950                tail %= size;
951
952                if (buffersize < size) buffersize++;
953
954                return false;
955        }
956       
957
958}
Note: See TracBrowser for help on using the repository browser.