/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 | | } |