Coverage Report

Created: 2026-05-30 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/ogre/OgreMain/src/OgreHardwareVertexBuffer.cpp
Line
Count
Source
1
/*
2
-----------------------------------------------------------------------------
3
This source file is part of OGRE
4
    (Object-oriented Graphics Rendering Engine)
5
For the latest info, see http://www.ogre3d.org/
6
7
Copyright (c) 2000-2014 Torus Knot Software Ltd
8
9
Permission is hereby granted, free of charge, to any person obtaining a copy
10
of this software and associated documentation files (the "Software"), to deal
11
in the Software without restriction, including without limitation the rights
12
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
13
copies of the Software, and to permit persons to whom the Software is
14
furnished to do so, subject to the following conditions:
15
16
The above copyright notice and this permission notice shall be included in
17
all copies or substantial portions of the Software.
18
19
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
20
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
21
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
22
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
23
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
24
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
25
THE SOFTWARE.
26
-----------------------------------------------------------------------------
27
*/
28
#include "OgreStableHeaders.h"
29
#include "OgreHardwareVertexBuffer.h"
30
31
#include <memory>
32
#include "OgreDefaultHardwareBufferManager.h"
33
34
namespace Ogre {
35
36
    //-----------------------------------------------------------------------------
37
    HardwareVertexBuffer::HardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,
38
        size_t numVertices, HardwareBuffer::Usage usage, bool useShadowBuffer)
39
0
        : HardwareBuffer(usage, useShadowBuffer),
40
0
          mIsInstanceData(false),
41
0
          mMgr(mgr),
42
0
          mNumVertices(numVertices),
43
0
          mVertexSize(vertexSize),
44
0
          mInstanceDataStepRate(1)
45
0
    {
46
        // Calculate the size of the vertices
47
0
        mSizeInBytes = mVertexSize * numVertices;
48
49
        // Create a shadow buffer if required
50
0
        if (useShadowBuffer)
51
0
        {
52
0
            mShadowBuffer = std::make_unique<DefaultHardwareBuffer>(mSizeInBytes);
53
0
        }
54
55
0
    }
56
    HardwareVertexBuffer::HardwareVertexBuffer(HardwareBufferManagerBase* mgr, size_t vertexSize,
57
                                               size_t numVertices, HardwareBuffer* delegate)
58
0
        : HardwareVertexBuffer(mgr, vertexSize, numVertices, delegate->getUsage(), false)
59
0
    {
60
0
        mDelegate.reset(delegate);
61
0
    }
62
    //-----------------------------------------------------------------------------
63
    HardwareVertexBuffer::~HardwareVertexBuffer()
64
0
    {
65
0
        if (mMgr)
66
0
        {
67
0
            mMgr->_notifyVertexBufferDestroyed(this);
68
0
        }
69
0
    }
70
    //-----------------------------------------------------------------------------
71
    void HardwareVertexBuffer::setIsInstanceData( const bool val )
72
0
    {
73
0
        RenderSystem* rs = Root::getSingleton().getRenderSystem();
74
75
0
        OgreAssert(!val || rs->getCapabilities()->hasCapability(RSC_VERTEX_BUFFER_INSTANCE_DATA),
76
0
                   "unsupported by rendersystem");
77
78
0
        mIsInstanceData = val;
79
0
    }
80
    //-----------------------------------------------------------------------------
81
    uint32 HardwareVertexBuffer::getInstanceDataStepRate() const
82
0
    {
83
0
        return mInstanceDataStepRate;
84
0
    }
85
    //-----------------------------------------------------------------------------
86
    void HardwareVertexBuffer::setInstanceDataStepRate( const size_t val )
87
0
    {
88
0
        if (val > 0)
89
0
        {
90
0
            mInstanceDataStepRate = val;
91
0
        }
92
0
        else
93
0
        {
94
0
            OGRE_EXCEPT(Exception::ERR_RENDERINGAPI_ERROR, 
95
0
                "Instance data step rate must be bigger then 0.", 
96
0
                "HardwareVertexBuffer::setInstanceDataStepRate");
97
0
        }
98
0
    }
99
    //-----------------------------------------------------------------------------
100
    // VertexElement
101
    //-----------------------------------------------------------------------------
102
    VertexElement::VertexElement(unsigned short source, size_t offset, VertexElementType theType,
103
                                 VertexElementSemantic semantic, unsigned short index)
104
0
        : mOffset(offset), mSource(source), mIndex(index), mType(theType), mSemantic(semantic)
105
0
    {
106
0
    }
107
    //-----------------------------------------------------------------------------
108
    size_t VertexElement::getSize(void) const
109
0
    {
110
0
        return getTypeSize(mType);
111
0
    }
112
    //-----------------------------------------------------------------------------
113
    size_t VertexElement::getTypeSize(VertexElementType etype)
114
0
    {
115
0
        switch(etype)
116
0
        {
117
0
        case VET_FLOAT1:
118
0
            return sizeof(float);
119
0
        case VET_FLOAT2:
120
0
            return sizeof(float)*2;
121
0
        case VET_FLOAT3:
122
0
            return sizeof(float)*3;
123
0
        case VET_FLOAT4:
124
0
            return sizeof(float)*4;
125
0
        case VET_DOUBLE1:
126
0
            return sizeof(double);
127
0
        case VET_DOUBLE2:
128
0
            return sizeof(double)*2;
129
0
        case VET_DOUBLE3:
130
0
            return sizeof(double)*3;
131
0
        case VET_DOUBLE4:
132
0
            return sizeof(double)*4;
133
0
        case VET_SHORT1:
134
0
        case VET_USHORT1:
135
0
        case VET_HALF1:
136
0
            return sizeof( short );
137
0
        case VET_SHORT2:
138
0
        case VET_SHORT2_NORM:
139
0
        case VET_USHORT2:
140
0
        case VET_USHORT2_NORM:
141
0
        case VET_HALF2:
142
0
            return sizeof( short ) * 2;
143
0
        case VET_SHORT3:
144
0
        case VET_USHORT3:
145
0
        case VET_HALF3:
146
0
            return sizeof( short ) * 3;
147
0
        case VET_SHORT4:
148
0
        case VET_SHORT4_NORM:
149
0
        case VET_USHORT4:
150
0
        case VET_USHORT4_NORM:
151
0
        case VET_HALF4:
152
0
            return sizeof( short ) * 4;
153
0
        case VET_INT1:
154
0
        case VET_UINT1:
155
0
            return sizeof( int );
156
0
        case VET_INT2:
157
0
        case VET_UINT2:
158
0
            return sizeof( int ) * 2;
159
0
        case VET_INT3:
160
0
        case VET_UINT3:
161
0
            return sizeof( int ) * 3;
162
0
        case VET_INT4:
163
0
        case VET_UINT4:
164
0
            return sizeof( int ) * 4;
165
0
        case VET_BYTE4:
166
0
        case VET_BYTE4_NORM:
167
0
        case VET_UBYTE4:
168
0
        case VET_UBYTE4_NORM:
169
0
        case _DETAIL_SWAP_RB:
170
0
            return sizeof(char)*4;
171
0
        case VET_INT_10_10_10_2_NORM:
172
0
            return 4;
173
0
        }
174
0
        return 0;
175
0
    }
176
    //-----------------------------------------------------------------------------
177
    unsigned short VertexElement::getTypeCount(VertexElementType etype)
178
0
    {
179
0
        switch (etype)
180
0
        {
181
0
        case VET_FLOAT1:
182
0
        case VET_SHORT1:
183
0
        case VET_USHORT1:
184
0
        case VET_UINT1:
185
0
        case VET_INT1:
186
0
        case VET_DOUBLE1:
187
0
        case VET_HALF1:
188
0
            return 1;
189
0
        case VET_FLOAT2:
190
0
        case VET_SHORT2:
191
0
        case VET_SHORT2_NORM:
192
0
        case VET_USHORT2:
193
0
        case VET_USHORT2_NORM:
194
0
        case VET_UINT2:
195
0
        case VET_INT2:
196
0
        case VET_DOUBLE2:
197
0
        case VET_HALF2:
198
0
            return 2;
199
0
        case VET_FLOAT3:
200
0
        case VET_SHORT3:
201
0
        case VET_USHORT3:
202
0
        case VET_UINT3:
203
0
        case VET_INT3:
204
0
        case VET_DOUBLE3:
205
0
        case VET_HALF3:
206
0
            return 3;
207
0
        case VET_FLOAT4:
208
0
        case VET_SHORT4:
209
0
        case VET_SHORT4_NORM:
210
0
        case VET_USHORT4:
211
0
        case VET_USHORT4_NORM:
212
0
        case VET_UINT4:
213
0
        case VET_INT4:
214
0
        case VET_DOUBLE4:
215
0
        case VET_BYTE4:
216
0
        case VET_UBYTE4:
217
0
        case VET_BYTE4_NORM:
218
0
        case VET_UBYTE4_NORM:
219
0
        case _DETAIL_SWAP_RB:
220
0
        case VET_INT_10_10_10_2_NORM:
221
0
        case VET_HALF4:
222
0
            return 4;
223
0
        }
224
0
        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid type", 
225
0
            "VertexElement::getTypeCount");
226
0
    }
227
    //-----------------------------------------------------------------------------
228
    VertexElementType VertexElement::multiplyTypeCount(VertexElementType baseType, 
229
        unsigned short count)
230
0
    {
231
0
        OgreAssert(count > 0 && count < 5, "Count out of range");
232
233
0
        switch (baseType)
234
0
        {
235
0
        case VET_FLOAT1:
236
0
        case VET_DOUBLE1:
237
0
        case VET_INT1:
238
0
        case VET_UINT1:
239
0
        case VET_HALF1:
240
            // evil enumeration arithmetic
241
0
            return static_cast<VertexElementType>( baseType + count - 1 );
242
243
0
        case VET_SHORT1:
244
0
        case VET_SHORT2:
245
0
            if ( count <= 2 )
246
0
            {
247
0
                return VET_SHORT2;
248
0
            }
249
0
            return VET_SHORT4;
250
251
0
        case VET_USHORT1:
252
0
        case VET_USHORT2:
253
0
            if ( count <= 2 )
254
0
            {
255
0
                return VET_USHORT2;
256
0
            }
257
0
            return VET_USHORT4;
258
259
0
        case VET_SHORT2_NORM:
260
0
            if ( count <= 2 )
261
0
            {
262
0
                return VET_SHORT2_NORM;
263
0
            }
264
0
            return VET_SHORT4_NORM;
265
266
0
        case VET_USHORT2_NORM:
267
0
            if ( count <= 2 )
268
0
            {
269
0
                return VET_USHORT2_NORM;
270
0
            }
271
0
            return VET_USHORT4_NORM;
272
273
0
        case VET_BYTE4:
274
0
        case VET_BYTE4_NORM:
275
0
        case VET_UBYTE4:
276
0
        case VET_UBYTE4_NORM:
277
0
            return baseType;
278
279
0
        default:
280
0
            break;
281
0
        }
282
0
        OGRE_EXCEPT(Exception::ERR_INVALIDPARAMS, "Invalid base type", 
283
0
            "VertexElement::multiplyTypeCount");
284
0
    }
285
    //--------------------------------------------------------------------------
286
    void VertexElement::convertColourValue(VertexElementType srcType, VertexElementType dstType, uint32* ptr)
287
0
    {
288
0
        if (srcType == dstType)
289
0
            return;
290
291
        // Conversion between ARGB and ABGR is always a case of flipping R/B
292
0
        *ptr = ((*ptr & 0x00FF0000) >> 16) | ((*ptr & 0x000000FF) << 16) | (*ptr & 0xFF00FF00);
293
0
    }
294
    //-----------------------------------------------------------------------------
295
    VertexElementType VertexElement::getBaseType(VertexElementType multiType)
296
0
    {
297
0
        switch (multiType)
298
0
        {
299
0
            case VET_FLOAT1:
300
0
            case VET_FLOAT2:
301
0
            case VET_FLOAT3:
302
0
            case VET_FLOAT4:
303
0
                return VET_FLOAT1;
304
0
            case VET_HALF1:
305
0
            case VET_HALF2:
306
0
            case VET_HALF3:
307
0
            case VET_HALF4:
308
0
                return VET_HALF1;
309
0
            case VET_DOUBLE1:
310
0
            case VET_DOUBLE2:
311
0
            case VET_DOUBLE3:
312
0
            case VET_DOUBLE4:
313
0
                return VET_DOUBLE1;
314
0
            case VET_INT1:
315
0
            case VET_INT2:
316
0
            case VET_INT3:
317
0
            case VET_INT4:
318
0
                return VET_INT1;
319
0
            case VET_UINT1:
320
0
            case VET_UINT2:
321
0
            case VET_UINT3:
322
0
            case VET_UINT4:
323
0
                return VET_UINT1;
324
0
            case VET_SHORT1:
325
0
            case VET_SHORT2:
326
0
            case VET_SHORT3:
327
0
            case VET_SHORT4:
328
0
                return VET_SHORT1;
329
0
            case VET_USHORT1:
330
0
            case VET_USHORT2:
331
0
            case VET_USHORT3:
332
0
            case VET_USHORT4:
333
0
                return VET_USHORT1;
334
0
            case VET_SHORT2_NORM:
335
0
            case VET_SHORT4_NORM:
336
0
                return VET_SHORT2_NORM;
337
0
            case VET_USHORT2_NORM:
338
0
            case VET_USHORT4_NORM:
339
0
                return VET_USHORT2_NORM;
340
0
            case VET_BYTE4:
341
0
                return VET_BYTE4;
342
0
            case VET_BYTE4_NORM:
343
0
                return VET_BYTE4_NORM;
344
0
            case VET_UBYTE4:
345
0
                return VET_UBYTE4;
346
0
            case VET_UBYTE4_NORM:
347
0
            case _DETAIL_SWAP_RB:
348
0
                return VET_UBYTE4_NORM;
349
0
            case VET_INT_10_10_10_2_NORM:
350
0
                return VET_INT_10_10_10_2_NORM;
351
0
        };
352
        // To keep compiler happy
353
0
        return VET_FLOAT1;
354
0
    }
355
    //-----------------------------------------------------------------------------
356
    VertexDeclaration::VertexDeclaration()
357
0
    {
358
0
    }
359
    //-----------------------------------------------------------------------------
360
    VertexDeclaration::~VertexDeclaration()
361
0
    {
362
0
    }
363
    //-----------------------------------------------------------------------------
364
    const VertexDeclaration::VertexElementList& VertexDeclaration::getElements(void) const
365
0
    {
366
0
        return mElementList;
367
0
    }
368
    //-----------------------------------------------------------------------------
369
    const VertexElement& VertexDeclaration::addElement(unsigned short source, 
370
        size_t offset, VertexElementType theType,
371
        VertexElementSemantic semantic, unsigned short index)
372
0
    {
373
0
        mElementList.push_back(VertexElement(source, offset, theType, semantic, index));
374
0
        notifyChanged();
375
0
        return mElementList.back();
376
0
    }
377
    //-----------------------------------------------------------------------------
378
    const VertexElement& VertexDeclaration::insertElement(unsigned short atPosition,
379
        unsigned short source, size_t offset, VertexElementType theType,
380
        VertexElementSemantic semantic, unsigned short index)
381
0
    {
382
0
        if (atPosition >= mElementList.size())
383
0
        {
384
0
            return addElement(source, offset, theType, semantic, index);
385
0
        }
386
387
0
        VertexElementList::iterator i = mElementList.begin();
388
0
        for (unsigned short n = 0; n < atPosition; ++n)
389
0
            ++i;
390
391
0
        i = mElementList.insert(i, 
392
0
            VertexElement(source, offset, theType, semantic, index));
393
394
0
        notifyChanged();
395
0
        return *i;
396
0
    }
397
    //-----------------------------------------------------------------------------
398
    const VertexElement* VertexDeclaration::getElement(unsigned short index) const
399
0
    {
400
0
        assert(index < mElementList.size() && "Index out of bounds");
401
402
0
        VertexElementList::const_iterator i = mElementList.begin();
403
0
        for (unsigned short n = 0; n < index; ++n)
404
0
            ++i;
405
406
0
        return &(*i);
407
408
0
    }
409
    //-----------------------------------------------------------------------------
410
    void VertexDeclaration::removeElement(unsigned short elem_index)
411
0
    {
412
0
        assert(elem_index < mElementList.size() && "Index out of bounds");
413
0
        VertexElementList::iterator i = mElementList.begin();
414
0
        for (unsigned short n = 0; n < elem_index; ++n)
415
0
            ++i;
416
0
        mElementList.erase(i);
417
0
        notifyChanged();
418
0
    }
419
    //-----------------------------------------------------------------------------
420
    void VertexDeclaration::removeElement(VertexElementSemantic semantic, unsigned short index)
421
0
    {
422
0
        VertexElementList::iterator ei, eiend;
423
0
        eiend = mElementList.end();
424
0
        for (ei = mElementList.begin(); ei != eiend; ++ei)
425
0
        {
426
0
            if (ei->getSemantic() == semantic && ei->getIndex() == index)
427
0
            {
428
0
                mElementList.erase(ei);
429
0
                notifyChanged();
430
0
                break;
431
0
            }
432
0
        }
433
0
    }
434
    //-----------------------------------------------------------------------------
435
    void VertexDeclaration::removeAllElements(void)
436
0
    {
437
0
        mElementList.clear();
438
0
        notifyChanged();
439
0
    }
440
    //-----------------------------------------------------------------------------
441
    void VertexDeclaration::modifyElement(unsigned short elem_index, 
442
        unsigned short source, size_t offset, VertexElementType theType,
443
        VertexElementSemantic semantic, unsigned short index)
444
0
    {
445
0
        assert(elem_index < mElementList.size() && "Index out of bounds");
446
0
        VertexElementList::iterator i = mElementList.begin();
447
0
        std::advance(i, elem_index);
448
0
        (*i) = VertexElement(source, offset, theType, semantic, index);
449
0
        notifyChanged();
450
0
    }
451
    //-----------------------------------------------------------------------------
452
    const VertexElement* VertexDeclaration::findElementBySemantic(
453
        VertexElementSemantic sem, unsigned short index) const
454
0
    {
455
0
        for (auto& e : mElementList)
456
0
        {
457
0
            if (e.getSemantic() == sem && e.getIndex() == index)
458
0
            {
459
0
                return &e;
460
0
            }
461
0
        }
462
463
0
        return NULL;
464
0
    }
465
    //-----------------------------------------------------------------------------
466
    VertexDeclaration::VertexElementList VertexDeclaration::findElementsBySource(
467
        unsigned short source) const
468
0
    {
469
0
        VertexElementList retList;
470
0
        for (auto& e : mElementList)
471
0
        {
472
0
            if (e.getSource() == source)
473
0
            {
474
0
                retList.push_back(e);
475
0
            }
476
0
        }
477
0
        return retList;
478
0
    }
479
480
    //-----------------------------------------------------------------------------
481
    size_t VertexDeclaration::getVertexSize(unsigned short source) const
482
0
    {
483
0
        size_t sz = 0;
484
0
        for (auto& e : mElementList)
485
0
        {
486
0
            if (e.getSource() == source)
487
0
            {
488
0
                sz += e.getSize();
489
490
0
            }
491
0
        }
492
0
        return sz;
493
0
    }
494
    //-----------------------------------------------------------------------------
495
    VertexDeclaration* VertexDeclaration::clone(HardwareBufferManagerBase* mgr) const
496
0
    {
497
0
        HardwareBufferManagerBase* pManager = mgr ? mgr : HardwareBufferManager::getSingletonPtr(); 
498
0
        VertexDeclaration* ret = pManager->createVertexDeclaration();
499
500
0
        for (auto& e : mElementList)
501
0
        {
502
0
            ret->addElement(e.getSource(), e.getOffset(), e.getType(), e.getSemantic(), e.getIndex());
503
0
        }
504
0
        return ret;
505
0
    }
506
    //-----------------------------------------------------------------------------
507
    // Sort routine for VertexElement
508
    static bool vertexElementLess(const VertexElement& e1, const VertexElement& e2)
509
0
    {
510
        // Sort by source first
511
0
        if (e1.getSource() < e2.getSource())
512
0
        {
513
0
            return true;
514
0
        }
515
0
        else if (e1.getSource() == e2.getSource())
516
0
        {
517
            // Use ordering of semantics to sort
518
0
            if (e1.getSemantic() < e2.getSemantic())
519
0
            {
520
0
                return true;
521
0
            }
522
0
            else if (e1.getSemantic() == e2.getSemantic())
523
0
            {
524
                // Use index to sort
525
0
                if (e1.getIndex() < e2.getIndex())
526
0
                {
527
0
                    return true;
528
0
                }
529
0
            }
530
0
        }
531
0
        return false;
532
0
    }
533
    void VertexDeclaration::sort(void)
534
0
    {
535
0
        mElementList.sort(vertexElementLess);
536
0
    }
537
    //-----------------------------------------------------------------------------
538
    void VertexDeclaration::closeGapsInSource(void)
539
0
    {
540
0
        if (mElementList.empty())
541
0
            return;
542
543
        // Sort first
544
0
        sort();
545
546
0
        unsigned short targetIdx = 0;
547
0
        unsigned short lastIdx = getElement(0)->getSource();
548
0
        unsigned short c = 0;
549
0
        for (auto& elem : mElementList)
550
0
        {
551
0
            if (lastIdx != elem.getSource())
552
0
            {
553
0
                targetIdx++;
554
0
                lastIdx = elem.getSource();
555
0
            }
556
0
            if (targetIdx != elem.getSource())
557
0
            {
558
0
                modifyElement(c, targetIdx, elem.getOffset(), elem.getType(), 
559
0
                    elem.getSemantic(), elem.getIndex());
560
0
            }
561
562
0
            ++c;
563
0
        }
564
0
    }
565
    //-----------------------------------------------------------------------
566
    VertexDeclaration* VertexDeclaration::getAutoOrganisedDeclaration(
567
        bool skeletalAnimation, bool vertexAnimation, bool vertexAnimationNormals) const
568
0
    {
569
0
        VertexDeclaration* newDecl = this->clone();
570
        // Set all sources to the same buffer (for now)
571
0
        const VertexDeclaration::VertexElementList& elems = newDecl->getElements();
572
0
        unsigned short c = 0;
573
0
        for (auto& elem : elems)
574
0
        {
575
            // Set source & offset to 0 for now, before sort
576
0
            newDecl->modifyElement(c, 0, 0, elem.getType(), elem.getSemantic(), elem.getIndex());
577
0
            ++c;
578
0
        }
579
0
        newDecl->sort();
580
        // Now sort out proper buffer assignments and offsets
581
0
        size_t offset = 0;
582
0
        c = 0;
583
0
        unsigned short buffer = 0;
584
0
        VertexElementSemantic prevSemantic = VES_POSITION;
585
0
        for (auto& elem : elems)
586
0
        {
587
0
            bool splitWithPrev = false;
588
0
            bool splitWithNext = false;
589
0
            switch (elem.getSemantic())
590
0
            {
591
0
            case VES_POSITION:
592
                // Split positions if vertex animated with only positions
593
                // group with normals otherwise
594
0
                splitWithPrev = false;
595
0
                splitWithNext = vertexAnimation && !vertexAnimationNormals;
596
0
                break;
597
0
            case VES_NORMAL:
598
                // Normals can't share with blend weights/indices
599
0
                splitWithPrev = (prevSemantic == VES_BLEND_WEIGHTS || prevSemantic == VES_BLEND_INDICES);
600
                // All animated meshes have to split after normal
601
0
                splitWithNext = (skeletalAnimation || (vertexAnimation && vertexAnimationNormals));
602
0
                break;
603
0
            case VES_BLEND_WEIGHTS:
604
                // Blend weights/indices can be sharing with their own buffer only
605
0
                splitWithPrev = true;
606
0
                break;
607
0
            case VES_BLEND_INDICES:
608
                // Blend weights/indices can be sharing with their own buffer only
609
0
                splitWithNext = true;
610
0
                break;
611
0
            default:
612
0
            case VES_DIFFUSE:
613
0
            case VES_SPECULAR:
614
0
            case VES_TEXTURE_COORDINATES:
615
0
            case VES_BINORMAL:
616
0
            case VES_TANGENT:
617
                // Make sure position is separate if animated & there were no normals
618
0
                splitWithPrev = prevSemantic == VES_POSITION && 
619
0
                    (skeletalAnimation || vertexAnimation);
620
0
                break;
621
0
            }
622
623
0
            if (splitWithPrev && offset)
624
0
            {
625
0
                ++buffer;
626
0
                offset = 0;
627
0
            }
628
629
0
            prevSemantic = elem.getSemantic();
630
0
            newDecl->modifyElement(c, buffer, offset,
631
0
                elem.getType(), elem.getSemantic(), elem.getIndex());
632
633
0
            if (splitWithNext)
634
0
            {
635
0
                ++buffer;
636
0
                offset = 0;
637
0
            }
638
0
            else
639
0
            {
640
0
                offset += elem.getSize();
641
0
            }
642
0
            ++c;
643
0
        }
644
645
0
        return newDecl;
646
647
648
0
    }
649
    //-----------------------------------------------------------------------------
650
    unsigned short VertexDeclaration::getMaxSource(void) const
651
0
    {
652
0
        unsigned short ret = 0;
653
0
        for (auto& e : mElementList)
654
0
        {
655
0
            if (e.getSource() > ret)
656
0
            {
657
0
                ret = e.getSource();
658
0
            }
659
0
        }
660
0
        return ret;
661
0
    }
662
    //-----------------------------------------------------------------------------
663
    unsigned short VertexDeclaration::getNextFreeTextureCoordinate() const
664
0
    {
665
0
        unsigned short texCoord = 0;
666
0
        for (const auto & el : mElementList)
667
0
        {
668
0
            if (el.getSemantic() == VES_TEXTURE_COORDINATES)
669
0
            {
670
0
                ++texCoord;
671
0
            }
672
0
        }
673
0
        return texCoord;
674
0
    }
675
    //-----------------------------------------------------------------------------
676
0
    VertexBufferBinding::VertexBufferBinding() : mHighIndex(0)
677
0
    {
678
0
    }
679
    //-----------------------------------------------------------------------------
680
    VertexBufferBinding::~VertexBufferBinding()
681
0
    {
682
0
        unsetAllBindings();
683
0
    }
684
    //-----------------------------------------------------------------------------
685
    void VertexBufferBinding::setBinding(unsigned short index, const HardwareVertexBufferSharedPtr& buffer)
686
0
    {
687
        // NB will replace any existing buffer ptr at this index, and will thus cause
688
        // reference count to decrement on that buffer (possibly destroying it)
689
0
        mBindingMap[index] = buffer;
690
0
        mHighIndex = std::max(mHighIndex, (unsigned short)(index+1));
691
0
    }
692
    //-----------------------------------------------------------------------------
693
    void VertexBufferBinding::unsetBinding(unsigned short index)
694
0
    {
695
0
        VertexBufferBindingMap::iterator i = mBindingMap.find(index);
696
0
        if (i == mBindingMap.end())
697
0
        {
698
0
            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND,
699
0
                "Cannot find buffer binding for index " + StringConverter::toString(index),
700
0
                "VertexBufferBinding::unsetBinding");
701
0
        }
702
0
        mBindingMap.erase(i);
703
0
    }
704
    //-----------------------------------------------------------------------------
705
    void VertexBufferBinding::unsetAllBindings(void)
706
0
    {
707
0
        mBindingMap.clear();
708
0
        mHighIndex = 0;
709
0
    }
710
    //-----------------------------------------------------------------------------
711
    const VertexBufferBinding::VertexBufferBindingMap& 
712
    VertexBufferBinding::getBindings(void) const
713
0
    {
714
0
        return mBindingMap;
715
0
    }
716
    //-----------------------------------------------------------------------------
717
    const HardwareVertexBufferSharedPtr& VertexBufferBinding::getBuffer(unsigned short index) const
718
0
    {
719
0
        VertexBufferBindingMap::const_iterator i = mBindingMap.find(index);
720
0
        if (i == mBindingMap.end())
721
0
        {
722
0
            OGRE_EXCEPT(Exception::ERR_ITEM_NOT_FOUND, "No buffer is bound to that index.",
723
0
                "VertexBufferBinding::getBuffer");
724
0
        }
725
0
        return i->second;
726
0
    }
727
    //-----------------------------------------------------------------------------
728
    bool VertexBufferBinding::isBufferBound(unsigned short index) const
729
0
    {
730
0
        return mBindingMap.find(index) != mBindingMap.end();
731
0
    }
732
    //-----------------------------------------------------------------------------
733
    unsigned short VertexBufferBinding::getLastBoundIndex(void) const
734
0
    {
735
0
        return mBindingMap.empty() ? 0 : mBindingMap.rbegin()->first + 1;
736
0
    }
737
    //-----------------------------------------------------------------------------
738
    bool VertexBufferBinding::hasGaps(void) const
739
0
    {
740
0
        if (mBindingMap.empty())
741
0
            return false;
742
0
        if (mBindingMap.rbegin()->first + 1 == (int) mBindingMap.size())
743
0
            return false;
744
0
        return true;
745
0
    }
746
    //-----------------------------------------------------------------------------
747
    void VertexBufferBinding::closeGaps(BindingIndexMap& bindingIndexMap)
748
0
    {
749
0
        bindingIndexMap.clear();
750
751
0
        VertexBufferBindingMap newBindingMap;
752
753
0
        VertexBufferBindingMap::const_iterator it;
754
0
        ushort targetIndex = 0;
755
0
        for (it = mBindingMap.begin(); it != mBindingMap.end(); ++it, ++targetIndex)
756
0
        {
757
0
            bindingIndexMap[it->first] = targetIndex;
758
0
            newBindingMap[targetIndex] = it->second;
759
0
        }
760
761
0
        mBindingMap.swap(newBindingMap);
762
0
        mHighIndex = targetIndex;
763
0
    }
764
}