FCT
载入中...
搜索中...
未找到
Vertex.h
浏览该文件的文档.
1#ifndef FCT_VERTEX_H
2#define FCT_VERTEX_H
3#include "./Format.h"
4#include "./DataTypes.h"
5#include "../Base/string.h"
6#include <boost/container_hash/hash.hpp>
7namespace FCT
8{
26 /*
27 *添加一个需要 添加
28 * GetDefaultModelAttribute
29 * GetDefaultFormat
30 * GetDefaultSemantic
31 */
32
34 Position, // 对应 position
35 Normal, // 对应 normal
36 TexCoord0, // 对应 texCoords[0]
37 TexCoord1, // 对应 texCoords[1]
44 Color0, // 对应 colors[0]
45 Color1, // 对应 colors[1]
52 Tangent, // 对应 tangent
53 Bitangent, // 对应 bitangent
54 None // 不对应任何ModelVertex属性
55 };
94
95 constexpr bool isPositionType(VtxType type) noexcept
96 {
97 return type == VtxType::Position2f || type == VtxType::Position3f || type == VtxType::Position4f;
98 }
99
100 constexpr Format GetDefaultFormat(VtxType type) noexcept {
101 switch (type)
102 {
117 case VtxType::Color3f:
119 case VtxType::Color4f:
124 return Format::R32_UINT;
125 case VtxType::BatchID:
126 return Format::R32_UINT;
127 case VtxType::FaceId:
128 return Format::R32_UINT;
130 return Format::R32_UINT;
131 case VtxType::Custom:
132 default:
133 return Format::UNDEFINED;
134 }
135 }
136
137 constexpr const char* GetDefaultSemantic(VtxType type) noexcept {
138 switch (type)
139 {
143 return "pos";
145 return "normal";
147 return "tangent";
149 return "bitangent";
151 return "texcoord";
152 case VtxType::Color3f:
153 case VtxType::Color4f:
154 return "color";
156 return "vertexcoord";
158 return "cmdoffset";
160 return "cmdSize";
161 case VtxType::FaceId:
162 return "faceId";
163 case VtxType::Custom:
164 default:
165 return "Custom";
166 }
167 }
168
170 public:
173 template<typename... Args>
174 constexpr VertexElement(Args&&... args) noexcept
177 processArgs(std::forward<Args>(args)...);
178 }
179 constexpr ModelVertexAttribute getModelAttribute() const noexcept { return m_modelAttribute; }
180
181 constexpr VtxType getType() const noexcept { return m_type; }
182
183 constexpr Format getFormat() const noexcept { return m_format; }
184
185 constexpr const char* getSemantic() const noexcept { return m_semantic; }
186
187 constexpr size_t getSize() const noexcept {
188 return FormatSize(m_format);
189 }
190 size_t getHash() const noexcept {
191 size_t seed = 0;
192 boost::hash_combine(seed, static_cast<size_t>(m_type));
193 boost::hash_combine(seed, static_cast<size_t>(m_format));
194 boost::hash_combine(seed, static_cast<size_t>(m_modelAttribute));
195 boost::hash_combine(seed, boost::hash<const char*>()(m_semantic));
196 return seed;
197 }
198
199 private:
200 constexpr void processArgs() noexcept {}
201 constexpr void processArgs(VtxType type) noexcept {
202 m_type = type;
205 }
206 if (StringEquals(m_semantic, "")) {
208 }
211 }
212 }
213
214 constexpr void processArgs(Format format) noexcept {
215 m_format = format;
216 }
217
218 constexpr void processArgs(const char* semantic) noexcept {
219 m_semantic = semantic;
220 }
221
222 constexpr void processArgs(ModelVertexAttribute attr) noexcept {
223 m_modelAttribute = attr;
224 }
225
226 template<typename First, typename... Rest>
227 constexpr void processArgs(First&& first, Rest&&... rest) noexcept {
228 processArgs(std::forward<First>(first));
229 processArgs(std::forward<Rest>(rest)...);
230 }
233 const char* m_semantic;
235 };
236
238 {
239 public:
240 template<typename... Elements>
241 constexpr VertexLayout(const Elements&... elements) noexcept {
242 (addElement(elements), ...);
243 }
244 constexpr void addElement(const VertexElement& element) noexcept {
246 m_elements[m_elementCount++] = element;
247 m_stride += element.getSize();
248 }
249 }
250
251 constexpr size_t getElementCount() const noexcept {
252 return m_elementCount;
253 }
254
255 constexpr const VertexElement& getElement(size_t index) const noexcept {
256 return (index < m_elementCount) ? m_elements[index] : m_elements[0];
257 }
258
259 constexpr size_t getStride() const noexcept {
260 return m_stride;
261 }
262
263 constexpr int getElementIndexBySemantic(const char* semantic) const noexcept {
264 for (size_t i = 0; i < m_elementCount; ++i) {
265 if (StringEquals(m_elements[i].getSemantic(), semantic)) {
266 return static_cast<int>(i);
267 }
268 }
269 return -1;
270 }
271
272 constexpr int getElementIndexByType(VtxType type) const noexcept {
273 for (size_t i = 0; i < m_elementCount; ++i) {
274 if (m_elements[i].getType() == type) {
275 return static_cast<int>(i);
276 }
277 }
278 return -1;
279 }
280
281 constexpr const VertexElement* getElementByType(VtxType type) const noexcept {
282 int index = getElementIndexByType(type);
283 return (index >= 0) ? &m_elements[index] : nullptr;
284 }
285
286 constexpr const VertexElement* getElementBySemantic(const char* semantic) const noexcept {
287 int index = getElementIndexBySemantic(semantic);
288 return (index >= 0) ? &m_elements[index] : nullptr;
289 }
290
291 constexpr size_t getElementOffset(size_t index) const noexcept {
292 size_t offset = 0;
293 for (size_t i = 0; i < index && i < m_elementCount; ++i) {
294 offset += m_elements[i].getSize();
295 }
296 return offset;
297 }
298
299 constexpr size_t getElementOffsetByType(VtxType type) const noexcept {
300 int index = getElementIndexByType(type);
301 return (index >= 0) ? getElementOffset(index) : 0;
302 }
303
304 constexpr size_t getElementOffsetBySemantic(const char* semantic) const noexcept {
305 int index = getElementIndexBySemantic(semantic);
306 return (index >= 0) ? getElementOffset(index) : 0;
307 }
308 size_t getHash() const noexcept {
309 size_t seed = 0;
310 for (size_t i = 0; i < m_elementCount; ++i) {
311 boost::hash_combine(seed, m_elements[i].getHash());
312 }
313 return seed;
314 }
315
316 private:
317 static constexpr size_t MaxElements = 64;
319 size_t m_elementCount = 0;
320 size_t m_stride = 0;
321 };
323 {
324 public:
325 //constexpr PixelLayout() noexcept : m_elementCount(0), m_stride(0) {}
326
327 template<typename... Args>
328 constexpr PixelLayout(Args&&... args) noexcept : m_elementCount(0), m_stride(0) {
329 addElements(std::forward<Args>(args)...);
330 }
331
332 constexpr void addElement(const VertexElement& element) noexcept {
334 m_elements[m_elementCount++] = element;
335 m_stride += element.getSize();
336 }
337 }
338
339 constexpr void addElements(const VertexLayout& layout) noexcept {
340 for (size_t i = 0; i < layout.getElementCount() && m_elementCount < MaxElements; ++i) {
341 addElement(layout.getElement(i));
342 }
343 }
344
345 constexpr void addElements(const PixelLayout& layout) noexcept {
346 for (size_t i = 0; i < layout.getElementCount() && m_elementCount < MaxElements; ++i) {
347 addElement(layout.getElement(i));
348 }
349 }
350
351 constexpr size_t getElementCount() const noexcept {
352 return m_elementCount;
353 }
354
355 constexpr const VertexElement& getElement(size_t index) const noexcept {
356 return (index < m_elementCount) ? m_elements[index] : m_elements[0];
357 }
358
359 constexpr size_t getStride() const noexcept {
360 return m_stride;
361 }
362
363 constexpr int getElementIndexBySemantic(const char* semantic) const noexcept {
364 for (size_t i = 0; i < m_elementCount; ++i) {
365 if (StringEquals(m_elements[i].getSemantic(), semantic)) {
366 return static_cast<int>(i);
367 }
368 }
369 return -1;
370 }
371
372 constexpr int getElementIndexByType(VtxType type) const noexcept {
373 for (size_t i = 0; i < m_elementCount; ++i) {
374 if (m_elements[i].getType() == type) {
375 return static_cast<int>(i);
376 }
377 }
378 return -1;
379 }
380
381 constexpr const VertexElement* getElementByType(VtxType type) const noexcept {
382 int index = getElementIndexByType(type);
383 return (index >= 0) ? &m_elements[index] : nullptr;
384 }
385
386 constexpr const VertexElement* getElementBySemantic(const char* semantic) const noexcept {
387 int index = getElementIndexBySemantic(semantic);
388 return (index >= 0) ? &m_elements[index] : nullptr;
389 }
390
391 constexpr size_t getElementOffset(size_t index) const noexcept {
392 size_t offset = 0;
393 for (size_t i = 0; i < index && i < m_elementCount; ++i) {
394 offset += m_elements[i].getSize();
395 }
396 return offset;
397 }
398
399 constexpr size_t getElementOffsetByType(VtxType type) const noexcept {
400 int index = getElementIndexByType(type);
401 return (index >= 0) ? getElementOffset(index) : 0;
402 }
403
404 constexpr size_t getElementOffsetBySemantic(const char* semantic) const noexcept {
405 int index = getElementIndexBySemantic(semantic);
406 return (index >= 0) ? getElementOffset(index) : 0;
407 }
408
409 constexpr void ensurePositionFirst() noexcept {
411 if (posIndex < 0) {
413 }
414
415 if (posIndex > 0) {
416 VertexElement posElement = m_elements[posIndex];
417
418 for (int i = posIndex; i > 0; --i) {
419 m_elements[i] = m_elements[i - 1];
420 }
421
422 m_elements[0] = posElement;
423
424 }
425 }
426
427 size_t getHash() const noexcept {
428 size_t seed = 0;
429 for (size_t i = 0; i < m_elementCount; ++i) {
430 boost::hash_combine(seed, m_elements[i].getHash());
431 }
432 return seed;
433 }
434
435
436 private:
437 constexpr void addElements() noexcept {}
438
439 template<typename... Rest>
440 constexpr void addElements(const VertexElement& element, Rest&&... rest) noexcept {
441 addElement(element);
442 addElements(std::forward<Rest>(rest)...);
443 }
444
445 template<typename... Rest>
446 constexpr void addElements(const VertexLayout& layout, Rest&&... rest) noexcept {
447 addElements(layout);
448 addElements(std::forward<Rest>(rest)...);
449 }
450
451 static constexpr size_t MaxElements = 64;
454 size_t m_stride;
455 };
456 class VertexBuffer;
457
458 class Vertex {
459 friend class VertexBuffer;
460 public:
461 template<typename T>
462 T& getAttribute(VtxType type) noexcept {
463 const auto* element = m_layout.getElementByType(type);
464 if (element) {
465 size_t offset = m_layout.getElementOffsetByType(type);
466 return *reinterpret_cast<T*>(m_data + offset);
467 }
468 static T dummy{};
469 return dummy;
470 }
471
472 template<typename T>
473 T& getAttribute(const char* semantic) noexcept {
474 const auto* element = m_layout.getElementBySemantic(semantic);
475 if (element) {
476 size_t offset = m_layout.getElementOffsetBySemantic(semantic);
477 return *reinterpret_cast<T*>(m_data + offset);
478 }
479 static T dummy{};
480 return dummy;
481 }
482
483 template<typename T>
484 void setAttribute(VtxType type, const T& value) noexcept {
485 const auto* element = m_layout.getElementByType(type);
486 if (element) {
487 size_t offset = m_layout.getElementOffsetByType(type);
488 *reinterpret_cast<T*>(m_data + offset) = value;
489 }
490 }
491 template<typename T>
492 void setAttribute(size_t elementIndex, const T& value) noexcept {
493 if (elementIndex < m_layout.getElementCount()) {
494 size_t offset = m_layout.getElementOffset(elementIndex);
495 *reinterpret_cast<T*>(m_data + offset) = value;
496 }
497 }
498
499 template<typename T>
500 void setAttribute(const char* semantic, const T& value) noexcept {
501 const auto* element = m_layout.getElementBySemantic(semantic);
502 if (element) {
503 size_t offset = m_layout.getElementOffsetBySemantic(semantic);
504 *reinterpret_cast<T*>(m_data + offset) = value;
505 }
506 }
507
508 uint8_t* getData() noexcept {
509 return m_data;
510 }
511
512 const uint8_t* getData() const noexcept {
513 return m_data;
514 }
515
516 const VertexLayout& getLayout() const noexcept {
517 return m_layout;
518 }
519
520 private:
521 Vertex(uint8_t* data, const VertexLayout& layout) noexcept
522 : m_data(data), m_layout(layout) {}
523
524 uint8_t* m_data;
526 };
527
529 public:
530 ConstVertex(const Vertex& vertex) noexcept
531 : m_data(vertex.getData()), m_layout(vertex.getLayout()) {}
532
533 template<typename T>
534 const T& getAttribute(VtxType type) const noexcept {
535 const auto* element = m_layout.getElementByType(type);
536 if (element) {
537 size_t offset = m_layout.getElementOffsetByType(type);
538 return *reinterpret_cast<const T*>(m_data + offset);
539 }
540 static const T dummy{};
541 return dummy;
542 }
543
544 template<typename T>
545 const T& getAttribute(const char* semantic) const noexcept {
546 const auto* element = m_layout.getElementBySemantic(semantic);
547 if (element) {
548 size_t offset = m_layout.getElementOffsetBySemantic(semantic);
549 return *reinterpret_cast<const T*>(m_data + offset);
550 }
551 static const T dummy{};
552 return dummy;
553 }
554
555 const uint8_t* getData() const noexcept {
556 return m_data;
557 }
558
559 const VertexLayout& getLayout() const noexcept {
560 return m_layout;
561 }
562
563 private:
564 const uint8_t* m_data;
566 };
568 public:
569 explicit VertexBuffer(const VertexLayout& layout) noexcept
570 : m_layout(layout), m_stride(layout.getStride()) {}
571
572 const VertexLayout& getLayout() const noexcept {
573 return m_layout;
574 }
575
576 size_t getVertexCount() const noexcept {
577 return m_data.size() / m_stride;
578 }
579
580 size_t getStride() const noexcept {
581 return m_stride;
582 }
583 void* getData()
584 {
585 return m_data.data();
586 }
587
588 const void* getData() const noexcept {
589 return m_data.data();
590 }
591
592 size_t getDataSize() const noexcept {
593 return m_data.size();
594 }
595
596 void reserve(size_t vertexCount) {
597 m_data.reserve(vertexCount * m_stride);
598 }
599
600 void resize(size_t vertexCount) {
601 m_data.resize(vertexCount * m_stride);
602 }
603
604 void clear() noexcept {
605 m_data.clear();
606 }
607
608 size_t addVertex() {
609 size_t index = getVertexCount();
610 m_data.resize((index + 1) * m_stride);
611 return index;
612 }
613
614 Vertex operator[](size_t index) noexcept {
615 assert(index < getVertexCount() && "Vertex index out of range");
616 return Vertex(m_data.data() + (index * m_stride), m_layout);
617 }
618/*
619 ConstVertex operator[](size_t index) const noexcept {
620 assert(index < getVertexCount() && "Vertex index out of range");
621 return ConstVertex(Vertex(const_cast<uint8_t*>(m_data.data()) + (index * m_stride), m_layout));
622 }*/
623
624 Vertex front() noexcept {
625 assert(!m_data.empty() && "Vertex buffer is empty");
626 return Vertex(m_data.data(), m_layout);
627 }
628
629 Vertex back() noexcept {
630 assert(!m_data.empty() && "Vertex buffer is empty");
631 return Vertex(m_data.data() + ((getVertexCount() - 1) * m_stride), m_layout);
632 }
633
634 ConstVertex front() const noexcept {
635 assert(!m_data.empty() && "Vertex buffer is empty");
636 return ConstVertex(Vertex(const_cast<uint8_t*>(m_data.data()), m_layout));
637 }
638
639 ConstVertex back() const noexcept {
640 assert(!m_data.empty() && "Vertex buffer is empty");
641 return ConstVertex(Vertex(const_cast<uint8_t*>(m_data.data() + ((getVertexCount() - 1) * m_stride)), m_layout));
642 }
643
644 template<typename... Args>
645 void emplaceBack(Args&&... args) {
646 static_assert(sizeof...(args) > 0, "At least one attribute must be provided");
647
648 size_t index = addVertex();
649 Vertex vertex = (*this)[index];
650
651 setAttributes(vertex, 0, std::forward<Args>(args)...);
652 }
653
654
655 private:
656 template<typename T>
657 void setAttributes(Vertex& vertex, size_t elementIndex, T&& value) {
658 if (elementIndex < m_layout.getElementCount()) {
659 vertex.setAttribute(elementIndex, std::forward<T>(value));
660 }
661 }
662
663 template<typename T, typename... Rest>
664 void setAttributes(Vertex& vertex, size_t elementIndex, T&& first, Rest&&... rest) {
665 if (elementIndex < m_layout.getElementCount()) {
666 vertex.setAttribute(elementIndex, std::forward<T>(first));
667 setAttributes(vertex, elementIndex + 1, std::forward<Rest>(rest)...);
668 }
669 }
670
671 std::vector<uint8_t> m_data;
673 size_t m_stride;
674 };
675}
676#endif //VERTEX_H
const uint8_t * m_data
const VertexLayout & getLayout() const noexcept
const T & getAttribute(const char *semantic) const noexcept
const VertexLayout & m_layout
const uint8_t * getData() const noexcept
ConstVertex(const Vertex &vertex) noexcept
const T & getAttribute(VtxType type) const noexcept
constexpr const VertexElement * getElementByType(VtxType type) const noexcept
constexpr void addElements(const VertexElement &element, Rest &&... rest) noexcept
constexpr size_t getElementCount() const noexcept
size_t getHash() const noexcept
constexpr size_t getElementOffsetBySemantic(const char *semantic) const noexcept
constexpr const VertexElement & getElement(size_t index) const noexcept
constexpr size_t getElementOffset(size_t index) const noexcept
constexpr void addElements(const VertexLayout &layout, Rest &&... rest) noexcept
VertexElement m_elements[MaxElements]
constexpr void ensurePositionFirst() noexcept
constexpr void addElement(const VertexElement &element) noexcept
static constexpr size_t MaxElements
constexpr void addElements() noexcept
constexpr const VertexElement * getElementBySemantic(const char *semantic) const noexcept
constexpr int getElementIndexBySemantic(const char *semantic) const noexcept
constexpr size_t getElementOffsetByType(VtxType type) const noexcept
constexpr PixelLayout(Args &&... args) noexcept
constexpr int getElementIndexByType(VtxType type) const noexcept
constexpr void addElements(const PixelLayout &layout) noexcept
constexpr void addElements(const VertexLayout &layout) noexcept
constexpr size_t getStride() const noexcept
VertexBuffer(const VertexLayout &layout) noexcept
void emplaceBack(Args &&... args)
void reserve(size_t vertexCount)
Vertex back() noexcept
size_t getStride() const noexcept
ConstVertex front() const noexcept
Vertex front() noexcept
const void * getData() const noexcept
void setAttributes(Vertex &vertex, size_t elementIndex, T &&first, Rest &&... rest)
size_t getDataSize() const noexcept
std::vector< uint8_t > m_data
void setAttributes(Vertex &vertex, size_t elementIndex, T &&value)
size_t getVertexCount() const noexcept
ConstVertex back() const noexcept
VertexLayout m_layout
Vertex operator[](size_t index) noexcept
void clear() noexcept
const VertexLayout & getLayout() const noexcept
void resize(size_t vertexCount)
constexpr void processArgs(First &&first, Rest &&... rest) noexcept
constexpr VtxType getType() const noexcept
size_t getHash() const noexcept
constexpr void processArgs(VtxType type) noexcept
const char * m_semantic
constexpr Format getFormat() const noexcept
constexpr void processArgs(Format format) noexcept
constexpr void processArgs(ModelVertexAttribute attr) noexcept
constexpr VertexElement() noexcept
constexpr size_t getSize() const noexcept
constexpr const char * getSemantic() const noexcept
constexpr ModelVertexAttribute getModelAttribute() const noexcept
constexpr void processArgs(const char *semantic) noexcept
constexpr VertexElement(Args &&... args) noexcept
ModelVertexAttribute m_modelAttribute
constexpr void processArgs() noexcept
uint8_t * m_data
void setAttribute(const char *semantic, const T &value) noexcept
void setAttribute(size_t elementIndex, const T &value) noexcept
uint8_t * getData() noexcept
void setAttribute(VtxType type, const T &value) noexcept
const VertexLayout & getLayout() const noexcept
Vertex(uint8_t *data, const VertexLayout &layout) noexcept
friend class VertexBuffer
T & getAttribute(const char *semantic) noexcept
T & getAttribute(VtxType type) noexcept
const uint8_t * getData() const noexcept
const VertexLayout & m_layout
constexpr const VertexElement * getElementByType(VtxType type) const noexcept
VertexElement m_elements[MaxElements]
constexpr size_t getElementOffset(size_t index) const noexcept
constexpr size_t getStride() const noexcept
constexpr int getElementIndexByType(VtxType type) const noexcept
constexpr size_t getElementOffsetBySemantic(const char *semantic) const noexcept
constexpr size_t getElementOffsetByType(VtxType type) const noexcept
constexpr int getElementIndexBySemantic(const char *semantic) const noexcept
size_t getHash() const noexcept
static constexpr size_t MaxElements
constexpr void addElement(const VertexElement &element) noexcept
constexpr size_t getElementCount() const noexcept
constexpr const VertexElement & getElement(size_t index) const noexcept
constexpr const VertexElement * getElementBySemantic(const char *semantic) const noexcept
constexpr VertexLayout(const Elements &... elements) noexcept
constexpr const char * GetDefaultSemantic(VtxType type) noexcept
constexpr bool StringEquals(const char *a, const char *b) noexcept
定义 string.h:8
constexpr bool isPositionType(VtxType type) noexcept
constexpr ModelVertexAttribute GetDefaultModelAttribute(VtxType type) noexcept
ModelVertexAttribute
constexpr Format GetDefaultFormat(VtxType type) noexcept
constexpr size_t FormatSize(Format format) noexcept