Divide Framework 0.1
A free and open-source 3D Framework under heavy development
Loading...
Searching...
No Matches
VertexBuffer.cpp
Go to the documentation of this file.
1
2
4
11
12namespace Divide {
13
14constexpr U16 BYTE_BUFFER_VERSION = 2u;
15
16namespace {
17// Once vertex buffers reach a certain size, the for loop grows really really fast up to millions of iterations.
18// Multiple if-checks per loop are not an option, so do some template hacks to speed this function up
19template<bool TexCoords, bool Normals, bool Tangents, bool Colour, bool Bones>
20void FillSmallData5(const vector<VertexBuffer::Vertex>& dataIn, Byte* dataOut) noexcept
21{
22 for (const VertexBuffer::Vertex& data : dataIn)
23 {
24 std::memcpy(dataOut, data._position._v, sizeof data._position);
25 dataOut += sizeof data._position;
26
27 if constexpr (TexCoords)
28 {
29 std::memcpy(dataOut, data._texcoord._v, sizeof data._texcoord);
30 dataOut += sizeof data._texcoord;
31 }
32
33 if constexpr(Normals)
34 {
35 std::memcpy(dataOut, &data._normal, sizeof data._normal);
36 dataOut += sizeof data._normal;
37 }
38
39 if constexpr(Tangents)
40 {
41 std::memcpy(dataOut, &data._tangent, sizeof data._tangent);
42 dataOut += sizeof data._tangent;
43 }
44
45 if constexpr(Colour)
46 {
47 std::memcpy(dataOut, data._colour._v, sizeof data._colour);
48 dataOut += sizeof data._colour;
49 }
50
51 if constexpr(Bones)
52 {
53 std::memcpy(dataOut, data._weights._v, sizeof data._weights);
54 dataOut += sizeof data._weights;
55
56 std::memcpy(dataOut, data._indices._v, sizeof data._indices );
57 dataOut += sizeof data._indices;
58 }
59 }
60}
61
62template <bool TexCoords, bool Normals, bool Tangents, bool Colour>
63void FillSmallData4(const vector<VertexBuffer::Vertex>& dataIn, Byte* dataOut, const bool bones) noexcept
64{
65 if (bones)
66 {
67 FillSmallData5<TexCoords, Normals, Tangents, Colour, true>(dataIn, dataOut);
68 }
69 else
70 {
71 FillSmallData5<TexCoords, Normals, Tangents, Colour, false>(dataIn, dataOut);
72 }
73}
74
75template <bool TexCoords, bool Normals, bool Tangents>
76void FillSmallData3(const vector<VertexBuffer::Vertex>& dataIn, Byte* dataOut, const bool colour, const bool bones) noexcept
77{
78 if (colour)
79 {
80 FillSmallData4<TexCoords, Normals, Tangents, true>(dataIn, dataOut, bones);
81 }
82 else
83 {
84 FillSmallData4<TexCoords, Normals, Tangents, false>(dataIn, dataOut, bones);
85 }
86}
87
88template <bool TexCoords, bool Normals>
89void FillSmallData2(const vector<VertexBuffer::Vertex>& dataIn, Byte* dataOut, const bool tangents, const bool colour, const bool bones) noexcept
90{
91 if (tangents)
92 {
93 FillSmallData3<TexCoords, Normals, true>(dataIn, dataOut, colour, bones);
94 }
95 else
96 {
97 FillSmallData3<TexCoords, Normals, false>(dataIn, dataOut, colour, bones);
98 }
99}
100
101template <bool TexCoords>
102void FillSmallData1(const vector<VertexBuffer::Vertex>& dataIn, Byte* dataOut, const bool normals, const bool tangents, const bool colour, const bool bones) noexcept
103{
104 if (normals)
105 {
106 FillSmallData2<TexCoords, true>(dataIn, dataOut, tangents, colour, bones);
107 }
108 else
109 {
110 FillSmallData2<TexCoords, false>(dataIn, dataOut, tangents, colour, bones);
111 }
112}
113
114void FillSmallData(const vector<VertexBuffer::Vertex>& dataIn, Byte* dataOut, const bool texCoords, const bool normals, const bool tangents, const bool colour, const bool bones) noexcept
115{
116 if (texCoords)
117 {
118 FillSmallData1<true>(dataIn, dataOut, normals, tangents, colour, bones);
119 }
120 else
121 {
122 FillSmallData1<false>(dataIn, dataOut, normals, tangents, colour, bones);
123 }
124}
125
126} //namespace
127
129 : VertexDataInterface(context, descriptor._name )
130 , _descriptor(descriptor)
131 , _internalGVD(context.newGVD(1u, descriptor._name))
132{
133}
134
135void VertexBuffer::setVertexCount(const size_t size)
136{
137 resizeVertexCount(size, {});
138}
139
140size_t VertexBuffer::getVertexCount() const noexcept
141{
142 return _data.size();
143}
144
145
147{
148 return _data;
149}
150
151void VertexBuffer::reserveIndexCount(const size_t size)
152{
153 _indices.reserve(size);
154}
155
156void VertexBuffer::resizeVertexCount(const size_t size, const Vertex& defaultValue)
157{
158 _dataLayoutChanged = true;
159 _data.resize(size, defaultValue);
160 _refreshQueued = true;
161}
162
163const vec3<F32>& VertexBuffer::getPosition(const U32 index) const
164{
165 return _data[index]._position;
166}
167
169{
170 return _data[index]._texcoord;
171}
172
174{
175 return _data[index]._normal;
176}
177
178F32 VertexBuffer::getNormal(const U32 index, vec3<F32>& normalOut) const
179{
180 const F32 normal = getNormal(index);
181 Util::UNPACK_VEC3(normal, normalOut.x, normalOut.y, normalOut.z);
182 return normal;
183}
184
186{
187 return _data[index]._tangent;
188}
189
190F32 VertexBuffer::getTangent(const U32 index, vec3<F32>& tangentOut) const
191{
192 const F32 tangent = getTangent(index);
193 Util::UNPACK_VEC3(tangent, tangentOut.x, tangentOut.y, tangentOut.z);
194 return tangent;
195}
196
198{
199 return _data[index]._indices;
200}
201
203{
204 return _data[index]._weights;
205}
206
208{
209 const vec4<U8>& weight = _data[index]._weights;
210 return vec4<F32>(UNORM_CHAR_TO_FLOAT(weight.x),
211 UNORM_CHAR_TO_FLOAT(weight.y),
212 UNORM_CHAR_TO_FLOAT(weight.z),
213 UNORM_CHAR_TO_FLOAT(weight.w));
214}
215
216size_t VertexBuffer::getIndexCount() const noexcept
217{
218 return _indices.size();
219}
220
221U32 VertexBuffer::getIndex(const size_t index) const
222{
223 DIVIDE_ASSERT(index < getIndexCount());
224 return _indices[index];
225}
226
228{
229 return _indices;
230}
231
233{
235 _indices.push_back(index);
236 _indicesChanged = true;
237}
238
240{
241 eastl::transform(eastl::cbegin(indices),
242 eastl::cend(indices),
243 back_inserter(_indices),
245
246 _indicesChanged = true;
247}
248
250{
251 _indices.insert(eastl::cend(_indices), eastl::cbegin(indices), eastl::cend(_indices));
252 _indicesChanged = true;
253}
254
256{
257 primitiveRestartRequired(true);
259}
260
261void VertexBuffer::modifyPositionValues(const U32 indexOffset, const vector<vec3<F32>>& newValues)
262{
263 DIVIDE_ASSERT(indexOffset + newValues.size() - 1 < _data.size());
264 DIVIDE_ASSERT( _refreshQueued || _descriptor._allowDynamicUpdates || _data.empty(), "VertexBuffer error: Modifying static buffers after creation is not allowed!");
265
266 vector<Vertex>::iterator it = _data.begin() + indexOffset;
267 for (const vec3<F32>& value : newValues)
268 {
269 it++->_position.set(value);
270 }
271
274 _refreshQueued = true;
275}
276
277void VertexBuffer::modifyPositionValue(const U32 index, const vec3<F32>& newValue)
278{
279 modifyPositionValue(index, newValue.x, newValue.y, newValue.z);
280}
281
282void VertexBuffer::modifyPositionValue(const U32 index, const F32 x, const F32 y, const F32 z)
283{
284 DIVIDE_ASSERT(index < _data.size());
285 DIVIDE_ASSERT( _refreshQueued || _descriptor._allowDynamicUpdates || _data.empty(), "VertexBuffer error: Modifying static buffers after creation is not allowed!" );
286
287 _data[index]._position.set(x, y, z);
290 _refreshQueued = true;
291}
292
293void VertexBuffer::modifyColourValue(const U32 index, const UColour4& newValue)
294{
295 modifyColourValue(index, newValue.r, newValue.g, newValue.b, newValue.a);
296}
297
298void VertexBuffer::modifyColourValue(const U32 index, const U8 r, const U8 g, const U8 b, const U8 a)
299{
300 DIVIDE_ASSERT(index < _data.size());
301 DIVIDE_ASSERT( _refreshQueued || _descriptor._allowDynamicUpdates || _data.empty(), "VertexBuffer error: Modifying static buffers after creation is not allowed!");
302
303 _data[index]._colour.set(r, g, b, a);
306 _refreshQueued = true;
307}
308
309void VertexBuffer::modifyNormalValue(const U32 index, const vec3<F32>& newValue)
310{
311 modifyNormalValue(index, newValue.x, newValue.y, newValue.z);
312}
313
314void VertexBuffer::modifyNormalValue(const U32 index, const F32 x, const F32 y, const F32 z)
315{
316 DIVIDE_ASSERT(index < _data.size());
317 DIVIDE_ASSERT( _refreshQueued || _descriptor._allowDynamicUpdates || _data.empty(), "VertexBuffer error: Modifying static buffers after creation is not allowed!");
318
319 _data[index]._normal = Util::PACK_VEC3(x, y, z);
322 _refreshQueued = true;
323}
324
325void VertexBuffer::modifyTangentValue(const U32 index, const vec3<F32>& newValue)
326{
327 modifyTangentValue(index, newValue.x, newValue.y, newValue.z);
328}
329
330void VertexBuffer::modifyTangentValue(const U32 index, const F32 x, const F32 y, const F32 z)
331{
332 DIVIDE_ASSERT(index < _data.size());
333 DIVIDE_ASSERT( _refreshQueued || _descriptor._allowDynamicUpdates || _data.empty(), "VertexBuffer error: Modifying static buffers after creation is not allowed!");
334
335 _data[index]._tangent = Util::PACK_VEC3(x, y, z);
338 _refreshQueued = true;
339}
340
341void VertexBuffer::modifyTexCoordValue(const U32 index, const vec2<F32> newValue)
342{
343 modifyTexCoordValue(index, newValue.s, newValue.t);
344}
345
346void VertexBuffer::modifyTexCoordValue(const U32 index, const F32 s, const F32 t)
347{
348 DIVIDE_ASSERT(index < _data.size());
349 DIVIDE_ASSERT( _refreshQueued || _descriptor._allowDynamicUpdates || _data.empty(), "VertexBuffer error: Modifying static buffers after creation is not allowed!");
350
351 _data[index]._texcoord.set(s, t);
354 _refreshQueued = true;
355}
356
357void VertexBuffer::modifyBoneIndices(const U32 index, const vec4<U8> indices)
358{
359 DIVIDE_ASSERT(index < _data.size());
360 DIVIDE_ASSERT( _refreshQueued || _descriptor._allowDynamicUpdates || _data.empty(), "VertexBuffer error: Modifying static buffers after creation is not allowed!");
361
362 _data[index]._indices = indices;
365 _refreshQueued = true;
366}
367
368void VertexBuffer::modifyBoneWeights(const U32 index, const FColour4& weights)
369{
370 vec4<U8> boneWeights;
371 boneWeights.x = FLOAT_TO_CHAR_UNORM(weights.x);
372 boneWeights.y = FLOAT_TO_CHAR_UNORM(weights.y);
373 boneWeights.z = FLOAT_TO_CHAR_UNORM(weights.z);
374 boneWeights.w = FLOAT_TO_CHAR_UNORM(weights.w);
375 modifyBoneWeights(index, boneWeights);
376}
377
378void VertexBuffer::modifyBoneWeights( const U32 index, const vec4<U8> packedWeights )
379{
380 DIVIDE_ASSERT( index < _data.size() );
381 DIVIDE_ASSERT( _refreshQueued || _descriptor._allowDynamicUpdates || _data.empty(), "VertexBuffer error: Modifying static buffers after creation is not allowed!");
382
383 _data[index]._weights = packedWeights;
386 _refreshQueued = true;
387}
388
389size_t VertexBuffer::partitionCount() const noexcept
390{
391 return _partitions.size();
392}
393
395{
396 const size_t previousIndexCount = _partitions.empty() ? 0 : _partitions.back().second;
397 const size_t previousOffset = _partitions.empty() ? 0 : _partitions.back().first;
398 size_t partitionedIndexCount = previousIndexCount + previousOffset;
399 _partitions.emplace_back(partitionedIndexCount, getIndexCount() - partitionedIndexCount);
400 return to_U16(_partitions.size() - 1);
401}
402
404{
405 if (_partitions.empty())
406 {
407 return getIndexCount();
408 }
409
410 DIVIDE_ASSERT(partitionID < _partitions.size() && "VertexBuffer error: Invalid partition offset!");
411 return _partitions[partitionID].second;
412}
413
414size_t VertexBuffer::getPartitionOffset(const U16 partitionID) const
415{
416 if (_partitions.empty())
417 {
418 return 0u;
419 }
420
421 DIVIDE_ASSERT(partitionID < _partitions.size() && "VertexBuffer error: Invalid partition offset!");
422 return _partitions[partitionID].first;
423}
424
426{
427 if (_partitions.empty())
428 {
429 return 0u;
430 }
431
432 return getPartitionOffset(to_U16(_partitions.size() - 1));
433}
434
436bool VertexBuffer::getMinimalData(const vector<Vertex>& dataIn, Byte* dataOut, const size_t dataOutBufferLength)
437{
438 DIVIDE_ASSERT(dataOut != nullptr);
439
440 if (dataOutBufferLength >= dataIn.size() * GetTotalDataSize(_useAttribute))
441 {
442 FillSmallData(dataIn,
443 dataOut,
449 return true;
450 }
451
452 return false;
453}
454
455bool VertexBuffer::refresh( BufferLock& dataLockOut, BufferLock& indexLockOut )
456{
457 if (!_refreshQueued)
458 {
459 return false;
460 }
461
462 _refreshQueued = false;
463
464 DIVIDE_ASSERT(!_indices.empty() && "glVertexArray::refresh error: Invalid index data on Refresh()!");
465 {
466 const size_t effectiveEntrySize = GetTotalDataSize( _useAttribute );
467
468 vector<Byte> smallData(_data.size() * effectiveEntrySize);
469 if (!getMinimalData(_data, smallData.data(), smallData.size()))
470 {
472 }
473
475 {
476 GenericVertexData::SetBufferParams setBufferParams{};
477 setBufferParams._bufferParams._elementSize = effectiveEntrySize;
478 setBufferParams._bufferParams._elementCount = to_U32(_data.size());
479 setBufferParams._bufferParams._flags._updateFrequency = _descriptor._allowDynamicUpdates ? BufferUpdateFrequency::OFTEN : BufferUpdateFrequency::ONCE;
480 setBufferParams._bufferParams._flags._updateUsage = BufferUpdateUsage::CPU_TO_GPU;
481 setBufferParams._initialData = { smallData.data(), smallData.size() };
482 setBufferParams._elementStride = setBufferParams._bufferParams._elementSize;
483 dataLockOut = _internalGVD->setBuffer(setBufferParams);
484 }
485 else
486 {
488
489 dataLockOut = _internalGVD->updateBuffer(0u, 0u, to_U32(_data.size()), smallData.data());
490 }
491
493 {
494 _data.clear();
495 }
496 else
497 {
498 _data.shrink_to_fit();
499 }
500 }
501
502 if (_indicesChanged)
503 {
504 // Check if we need to update the IBO (will be true for the first Refresh() call)
506 idxBuffer.count = _indices.size();
507 idxBuffer.smallIndices = !_descriptor._largeIndices;
508 idxBuffer.indicesNeedCast = idxBuffer.smallIndices;
509 idxBuffer.data = _indices.data();
510 idxBuffer.dynamic = _descriptor._allowDynamicUpdates;
511 indexLockOut = _internalGVD->setIndexBuffer(idxBuffer);
512 _indicesChanged = false;
513 }
514
515 return true;
516}
517
519{
520 // Check if we have a refresh request queued up
521 BufferLock dataLock, indexLock{};
522 const bool refreshed = refresh(dataLock, indexLock);
523
524 _internalGVD->primitiveRestartRequired(primitiveRestartRequired());
525 _internalGVD->draw(command, data);
526
527 if ( refreshed && dataLock._range._length > 0u && indexLock._range._length > 0u )
528 {
529 auto sync = LockManager::CreateSyncObject( _context.renderAPI() );
530
531 if ( dataLock._range._length > 0u )
532 {
533 if ( !dataLock._buffer->lockRange( dataLock._range, sync ) )
534 {
536 }
537 }
538 if ( indexLock._range._length > 0u )
539 {
540 if ( !indexLock._buffer->lockRange( indexLock._range, sync ) )
541 {
543 }
544 }
545 }
546}
547
550{
551 AttributeMap retMap{};
552
553 constexpr U32 positionLoc = to_base(AttribLocation::POSITION);
554 constexpr U32 texCoordLoc = to_base(AttribLocation::TEXCOORD);
555 constexpr U32 normalLoc = to_base(AttribLocation::NORMAL);
556 constexpr U32 tangentLoc = to_base(AttribLocation::TANGENT);
557 constexpr U32 colourLoc = to_base(AttribLocation::COLOR);
558 constexpr U32 boneWeightLoc = to_base(AttribLocation::BONE_WEIGHT);
559 constexpr U32 boneIndiceLoc = to_base(AttribLocation::BONE_INDICE);
560
561 VertexBinding& vertBinding = retMap._vertexBindings.emplace_back();
562 vertBinding._bufferBindIndex = 0u;
564
565 for ( AttributeDescriptor& desc : retMap._attributes )
566 {
567 desc._vertexBindingIndex = vertBinding._bufferBindIndex;
569 }
570 {
571 AttributeDescriptor& desc = retMap._attributes[to_base(AttribLocation::POSITION)];
572 desc._componentsPerElement = 3;
574 desc._normalized = false;
575 desc._strideInBytes = offsets[positionLoc];
576 }
577
578 if (_useAttribute[texCoordLoc])
579 {
580 AttributeDescriptor& desc = retMap._attributes[to_base(AttribLocation::TEXCOORD)];
581 desc._componentsPerElement = 2;
583 desc._normalized = false;
584 desc._strideInBytes = offsets[texCoordLoc];
585 }
586
587 if (_useAttribute[normalLoc])
588 {
589 AttributeDescriptor& desc = retMap._attributes[to_base(AttribLocation::NORMAL)];
590 desc._componentsPerElement = 1;
592 desc._normalized = false;
593 desc._strideInBytes = offsets[normalLoc];
594 }
595
596 if (_useAttribute[tangentLoc])
597 {
598 AttributeDescriptor& desc = retMap._attributes[to_base(AttribLocation::TANGENT)];
599 desc._componentsPerElement = 1;
601 desc._normalized = false;
602 desc._strideInBytes = offsets[tangentLoc];
603 }
604
605 if (_useAttribute[colourLoc])
606 {
607 AttributeDescriptor& desc = retMap._attributes[to_base(AttribLocation::COLOR)];
608 desc._componentsPerElement = 4;
610 desc._normalized = true;
611 desc._strideInBytes = offsets[colourLoc];
612 }
613
614 if (_useAttribute[boneWeightLoc])
615 {
616 DIVIDE_ASSERT( _useAttribute[boneIndiceLoc]);
617 {
618 AttributeDescriptor& desc = retMap._attributes[to_base(AttribLocation::BONE_WEIGHT)];
619 desc._componentsPerElement = 4;
621 desc._normalized = true;
622 desc._strideInBytes = offsets[boneWeightLoc];
623 }
624 {
625 AttributeDescriptor& desc = retMap._attributes[to_base(AttribLocation::BONE_INDICE)];
626 desc._componentsPerElement = 4;
628 desc._normalized = false;
629 desc._strideInBytes = offsets[boneIndiceLoc];
630 }
631 }
632
633 return retMap;
634}
635
636//ref: https://www.iquilezles.org/www/articles/normals/normals.htm
638{
639 const size_t vertCount = getVertexCount();
640 const size_t indexCount = getIndexCount();
641
642 vector<vec3<F32>> normalBuffer(vertCount, 0.0f);
643 for (size_t i = 0u; i < indexCount; i += 3u)
644 {
645
646 const U32 idx0 = getIndex(i + 0);
647
649 {
650 DIVIDE_ASSERT( i > 2);
651 i -= 2;
652 continue;
653 }
654
655 const U32 idx1 = getIndex(i + 1);
656 const U32 idx2 = getIndex(i + 2);
657
658 // get the three vertices that make the faces
659 const vec3<F32>& ia = getPosition(idx0);
660 const vec3<F32>& ib = getPosition(idx1);
661 const vec3<F32>& ic = getPosition(idx2);
662
663 const vec3<F32> no = Cross(ia - ib, ic - ib);
664
665 // Store the face's normal for each of the vertices that make up the face.
666 normalBuffer[idx0] += no;
667 normalBuffer[idx1] += no;
668 normalBuffer[idx2] += no;
669 }
670
671 for (U32 i = 0u; i < vertCount; ++i)
672 {
673 modifyNormalValue(i, Normalized(normalBuffer[i]));
674 }
675}
676
678{
679 const size_t indexCount = getIndexCount();
680
681 // Code from:
682 // http://www.opengl-tutorial.org/intermediate-tutorials/tutorial-13-normal-mapping/#header-1
683
684 vec3<F32> deltaPos1, deltaPos2;
685 vec2<F32> deltaUV1, deltaUV2;
686 vec3<F32> tangent;
687
688 for (U32 i = 0u; i < indexCount; i += 3)
689 {
690 // get the three vertices that make the faces
691 const U32 idx0 = getIndex(i + 0);
693 {
694 DIVIDE_ASSERT( i > 2);
695 i -= 2;
696 continue;
697 }
698
699 const U32 idx1 = getIndex(to_size(i) + 1);
700 const U32 idx2 = getIndex(to_size(i) + 2);
701
702 const vec3<F32>& v0 = getPosition(idx0);
703 const vec3<F32>& v1 = getPosition(idx1);
704 const vec3<F32>& v2 = getPosition(idx2);
705
706 // Shortcuts for UVs
707 const vec2<F32> uv0 = getTexCoord(idx0);
708 const vec2<F32> uv1 = getTexCoord(idx1);
709 const vec2<F32> uv2 = getTexCoord(idx2);
710
711 // Edges of the triangle : position delta
712 deltaPos1.set(v1 - v0);
713 deltaPos2.set(v2 - v0);
714
715 // UV delta
716 deltaUV1.set(uv1 - uv0);
717 deltaUV2.set(uv2 - uv0);
718
719 const F32 r = 1.0f / (deltaUV1.x * deltaUV2.y - deltaUV1.y * deltaUV2.x);
720 tangent.set((deltaPos1 * deltaUV2.y - deltaPos2 * deltaUV1.y) * r);
721 tangent.normalize();
722 // Set the same tangent for all three vertices of the triangle.
723 // They will be merged later, in vbindexer.cpp
724 modifyTangentValue(idx0, tangent);
725 modifyTangentValue(idx1, tangent);
726 modifyTangentValue(idx2, tangent);
727 }
728}
729
731{
732 primitiveRestartRequired(false);
733 _partitions.clear();
734 _data.clear();
735 _indices.clear();
736 _useAttribute.fill(false);
737}
738
740{
741 reset();
742
743 _descriptor = other._descriptor;
744 _partitions = other._partitions;
746 _refreshQueued = true;
747 _dataLayoutChanged = true;
748
749 primitiveRestartRequired(other.primitiveRestartRequired());
751 unchecked_copy(_data, other._data);
752}
753
755{
756 DIVIDE_ASSERT( !dataIn.bufferEmpty());
757
758 auto tempVer = decltype(BYTE_BUFFER_VERSION){0};
759 dataIn >> tempVer;
760
761 if (tempVer == BYTE_BUFFER_VERSION)
762 {
763 U64 idString = 0u;
764 dataIn >> idString;
765 if (idString == _ID("VB"))
766 {
767 reset();
769 dataIn >> _descriptor._keepCPUData;
770 dataIn >> _descriptor._largeIndices;
771 dataIn >> _partitions;
772 dataIn >> _indices;
773 dataIn >> _data;
774 dataIn >> _useAttribute;
775 dataIn >> _primitiveRestartRequired;
776
777 return true;
778 }
779 }
780
781 return false;
782}
783
785{
786 if (_data.empty())
787 {
788 return false;
789 }
790
791 dataOut << BYTE_BUFFER_VERSION;
792 dataOut << _ID("VB");
794 dataOut << _descriptor._keepCPUData;
795 dataOut << _descriptor._largeIndices;
796 dataOut << _partitions;
797 dataOut << _indices;
798 dataOut << _data;
799 dataOut << _useAttribute;
800 dataOut << _primitiveRestartRequired;
801
802 return true;
803}
804
805size_t VertexBuffer::GetTotalDataSize( const AttributeFlags& usedAttributes )
806{
807 size_t ret = sizeof( vec3<F32> );
808
809 ret += usedAttributes[to_base( AttribLocation::TEXCOORD )] ? sizeof( vec2<F32> ) : 0u;
810 ret += usedAttributes[to_base( AttribLocation::NORMAL )] ? sizeof( F32 ) : 0u;
811 ret += usedAttributes[to_base( AttribLocation::TANGENT )] ? sizeof( F32 ) : 0u;
812 ret += usedAttributes[to_base( AttribLocation::COLOR )] ? sizeof( UColour4 ) : 0u;
813 ret += usedAttributes[to_base( AttribLocation::BONE_INDICE )] ? 2 * sizeof( vec4<U8> ) : 0u;
814
815 return ret;
816}
817
818AttributeOffsets VertexBuffer::GetAttributeOffsets(const AttributeFlags& usedAttributes, size_t& totalDataSizeOut)
819{
820 AttributeOffsets offsets{};
821
822 totalDataSizeOut = sizeof(vec3<F32>);
823
824 if (usedAttributes[to_base(AttribLocation::TEXCOORD)])
825 {
826 offsets[to_base(AttribLocation::TEXCOORD)] = to_U32(totalDataSizeOut);
827 totalDataSizeOut += sizeof(vec2<F32>);
828 }
829
830 if (usedAttributes[to_base(AttribLocation::NORMAL)])
831 {
832 offsets[to_base(AttribLocation::NORMAL)] = to_U32(totalDataSizeOut);
833 totalDataSizeOut += sizeof(F32);
834 }
835
836 if (usedAttributes[to_base(AttribLocation::TANGENT)])
837 {
838 offsets[to_base(AttribLocation::TANGENT)] = to_U32(totalDataSizeOut);
839 totalDataSizeOut += sizeof(F32);
840 }
841
842 if (usedAttributes[to_base(AttribLocation::COLOR)])
843 {
844 offsets[to_base(AttribLocation::COLOR)] = to_U32(totalDataSizeOut);
845 totalDataSizeOut += sizeof(UColour4);
846 }
847
848 if (usedAttributes[to_base(AttribLocation::BONE_INDICE)])
849 {
850 offsets[to_base(AttribLocation::BONE_WEIGHT)] = to_U32(totalDataSizeOut);
851 totalDataSizeOut += sizeof(vec4<U8>);
852
853 offsets[to_base(AttribLocation::BONE_INDICE)] = to_U32(totalDataSizeOut);
854 totalDataSizeOut += sizeof( vec4<U8> );
855 }
856
857 return offsets;
858}
859
860};
#define DIVIDE_ASSERT(...)
#define DIVIDE_UNEXPECTED_CALL()
bool bufferEmpty() const noexcept
Returns true if the read position and the write position are identical.
Definition: ByteBuffer.inl:353
Rough around the edges Adapter pattern abstracting the actual rendering API and access to the GPU.
Definition: GFXDevice.h:215
static SyncObjectHandle CreateSyncObject(RenderAPI api, U8 flag=DEFAULT_SYNC_FLAG_INTERNAL)
void addIndex(const U32 index)
void modifyTexCoordValue(const U32 index, vec2< F32 > newValue)
bool deserialize(ByteBuffer &dataIn)
static constexpr U32 PRIMITIVE_RESTART_INDEX_L
Definition: VertexBuffer.h:50
U32 getIndex(const size_t index) const
void modifyPositionValues(const U32 indexOffset, const vector< vec3< F32 > > &newValues)
size_t getPartitionOffset(const U16 partitionID) const
vec4< U8 > getBoneWeightsPacked(const U32 index) const
void draw(const GenericDrawCommand &command, VDIUserData *data) override
Calculates the appropriate attribute offsets and returns the total size of a vertex for this buffer.
VertexBuffer(GFXDevice &context, const Descriptor &descriptor)
size_t getIndexCount() const noexcept
bool refresh(BufferLock &dataLockOut, BufferLock &indexLockOut)
Returns true if data was updated.
vec4< F32 > getBoneWeights(const U32 index) const
size_t lastPartitionOffset() const
AttributeFlags _useAttribute
Definition: VertexBuffer.h:185
const vector< Vertex > & getVertices() const noexcept
GenericVertexData_ptr _internalGVD
Definition: VertexBuffer.h:186
size_t partitionCount() const noexcept
size_t getPartitionIndexCount(const U16 partitionID)
vec2< F32 > getTexCoord(const U32 index) const
void addIndices(const vector< U16 > &indices)
F32 getTangent(const U32 index) const
size_t getVertexCount() const noexcept
void resizeVertexCount(const size_t size, const Vertex &defaultValue)
void fromBuffer(const VertexBuffer &other)
static size_t GetTotalDataSize(const AttributeFlags &usedAttributes)
bool getMinimalData(const vector< Vertex > &dataIn, Byte *dataOut, size_t dataOutBufferLength)
Trim down the Vertex vector to only upload the minimal amount of data to the GPU.
const vec3< F32 > & getPosition(const U32 index) const
void modifyBoneWeights(const U32 index, const FColour4 &weights)
bool serialize(ByteBuffer &dataOut) const
void modifyColourValue(const U32 index, const UColour4 &newValue)
void modifyTangentValue(const U32 index, const vec3< F32 > &newValue)
vec4< U8 > getBoneIndices(const U32 index) const
void reserveIndexCount(const size_t size)
static AttributeOffsets GetAttributeOffsets(const AttributeFlags &usedAttributes, size_t &totalDataSizeOut)
vector< Vertex > _data
Definition: VertexBuffer.h:182
Descriptor _descriptor
Definition: VertexBuffer.h:179
void modifyNormalValue(const U32 index, const vec3< F32 > &newValue)
void setVertexCount(const size_t size)
F32 getNormal(const U32 index) const
const vector< U32 > & getIndices() const noexcept
void modifyBoneIndices(const U32 index, const vec4< U8 > indices)
static constexpr U32 PRIMITIVE_RESTART_INDEX_S
Definition: VertexBuffer.h:51
void modifyPositionValue(const U32 index, const vec3< F32 > &newValue)
AttributeMap generateAttributeMap()
Activate and set all of the required vertex attributes.
vector< std::pair< size_t, size_t > > _partitions
Definition: VertexBuffer.h:181
vector< U32 > _indices
Used for creating an "IB". If it's empty, then an outside source should provide the indices.
Definition: VertexBuffer.h:184
void set(const T *v) noexcept
set the 2 components of the vector manually using a source pointer to a (large enough) array
Definition: MathVectors.h:335
vec3 & normalize() noexcept
transform the vector to unit length
void set(const T *v) noexcept
set the 3 components of the vector manually using a source pointer to a (large enough) array
Definition: MathVectors.h:707
F32 PACK_VEC3(F32_SNORM x, F32_SNORM y, F32_SNORM z) noexcept
Definition: MathHelper.inl:316
void UNPACK_VEC3(F32 src, F32_SNORM &x, F32_SNORM &y, F32_SNORM &z) noexcept
Definition: MathHelper.inl:335
void FillSmallData5(const vector< VertexBuffer::Vertex > &dataIn, Byte *dataOut) noexcept
void FillSmallData1(const vector< VertexBuffer::Vertex > &dataIn, Byte *dataOut, const bool normals, const bool tangents, const bool colour, const bool bones) noexcept
void FillSmallData2(const vector< VertexBuffer::Vertex > &dataIn, Byte *dataOut, const bool tangents, const bool colour, const bool bones) noexcept
void FillSmallData3(const vector< VertexBuffer::Vertex > &dataIn, Byte *dataOut, const bool colour, const bool bones) noexcept
void FillSmallData4(const vector< VertexBuffer::Vertex > &dataIn, Byte *dataOut, const bool bones) noexcept
void FillSmallData(const vector< VertexBuffer::Vertex > &dataIn, Byte *dataOut, const bool texCoords, const bool normals, const bool tangents, const bool colour, const bool bones) noexcept
Handle console commands that start with a forward slash.
Definition: AIProcessor.cpp:7
constexpr U8 FLOAT_TO_CHAR_UNORM(F32_NORM value) noexcept
Returns round(value * 255)
Definition: MathHelper.inl:307
vec2< T > Normalized(vec2< T > vector) noexcept
Definition: MathVectors.inl:98
std::array< bool, to_base(AttribLocation::COUNT)> AttributeFlags
std::byte Byte
constexpr U32 to_U32(const T value)
constexpr F32_NORM UNORM_CHAR_TO_FLOAT(U8 value) noexcept
Returns value / 255.f.
Definition: MathHelper.inl:302
constexpr U16 to_U16(const T value)
uint8_t U8
constexpr U16 BYTE_BUFFER_VERSION
eastl::vector< Type > vector
Definition: Vector.h:42
void unchecked_copy(eastl::vector< T, A1 > &dst, const eastl::vector< T, A2 > &src)
Definition: Vector.h:122
constexpr U16 U16_MAX
uint16_t U16
constexpr U64 _ID(const char *const str, const U64 value=val_64_const) noexcept
vec2< T > Cross(vec2< T > v1, vec2< T > v2) noexcept
general vec2 cross function
Definition: MathVectors.inl:80
constexpr size_t to_size(const T value)
std::array< size_t, to_base(AttribLocation::COUNT)> AttributeOffsets
vec4< U8 > UColour4
Definition: MathHelper.h:72
uint32_t U32
uint64_t U64
constexpr auto to_base(const Type value) -> Type
BufferRange _range
Definition: BufferLocks.h:57
LockableBuffer * _buffer
Definition: BufferLocks.h:60
size_t _elementSize
Buffer primitive size in bytes.
Definition: BufferParams.h:50
bool lockRange(BufferRange range, SyncObjectHandle &sync) const
Definition: BufferLocks.cpp:26