aboutsummaryrefslogtreecommitdiff
path: root/source/Mesh.hpp
blob: a208edae1dadb2e132ca1e7731f980835d20fb0c (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
#pragma once

#include "RcPtr.hpp"
#include "SmallVector.hpp"

#include <glad/glad.h>
#include <cstddef>
#include <cstdint>
#include <vector>

namespace Tags {
/// Vertex element semantics, used to identify the meaning of vertex buffer contents
enum VertexElementSemantic {
	/// Position, typically VET_Float3
	VES_Position = 1,
	/// Blending weights
	VES_BlendWeights = 2,
	/// Blending indices
	VES_BlendIndices = 3,
	/// Normal, typically VET_Float3
	VES_Normal = 4,
	/// Colour, typically VET_Ubyte4
	VES_Colour = 5,
	/// Secondary colour. Generally free for custom data. Means specular with OpenGL FFP.
	VES_Colour2 = 6,
	/// Texture coordinates, typically VET_Float2
	VES_Texture_coordinates = 7,
	/// Binormal (Y axis if normal is Z)
	VES_Binormal = 8,
	/// Tangent (X axis if normal is Z)
	VES_Tangent = 9,
	/// The number of VertexElementSemantic elements (note - the first value VES_Position is 1)
	VES_COUNT = 9,
};

enum VertexElementType {
	VET_Float1,
	VET_Float2,
	VET_Float3,
	VET_Float4,

	VET_Short2,
	VET_Short4,
	VET_Ubyte4,

	// the following are not universally supported on all hardware:
	VET_Double1,
	VET_Double2,
	VET_Double3,
	VET_Double4,
	VET_Ushort2,
	VET_Ushort4,
	VET_Int1,
	VET_Int2,
	VET_Int3,
	VET_Int4,
	VET_Uint1,
	VET_Uint2,
	VET_Uint3,
	VET_Uint4,
	VET_Byte4, /// signed bytes

	VET_NORM_BEGIN,
	VET_Byte4Norm = VET_NORM_BEGIN, /// signed bytes (normalized to -1..1)
	VET_Ubyte4Norm, /// unsigned bytes (normalized to 0..1)
	VET_Short2Norm, /// signed shorts (normalized to -1..1)
	VET_Short4Norm,
	VET_Ushort2Norm, /// unsigned shorts (normalized to 0..1)
	VET_Ushort4Norm,
	VET_NORM_END = VET_Ushort4Norm,
};

int SizeOf(VertexElementType type);
bool IsNormalized(VertexElementType type);

enum IndexType {
	IT_16Bit,
	IT_32Bit,
};

int SizeOf(IndexType type);
} // namespace Tags

struct GpuVertexBuffer : public RefCounted {
	GLuint handle;
	int sizeInBytes;

	GpuVertexBuffer();
	~GpuVertexBuffer();

	void Upload(const std::byte* data, size_t sizeInBytes);
};

struct GpuIndexBuffer : public RefCounted {
	GLuint handle;
	Tags::IndexType indexType;
	int sizeInBytes;

	GpuIndexBuffer();
	~GpuIndexBuffer();

	void Upload(const std::byte* data, size_t count);
	void Upload(const std::byte* data, Tags::IndexType type, size_t count);
};

struct BufferBindings : public RefCounted {
	SmallVector<RcPtr<GpuVertexBuffer>, 4> bindings;

	int GetMaxBindingIndex() const;

	/// Safe. Returns nullptr if the index is not bound to any buffers.
	GpuVertexBuffer* GetBinding(int index) const;
	/// Adds or updates a buffer binding. Setting a binding to nullptr effectively removes the binding.
	void SetBinding(int index, GpuVertexBuffer* buffer);
	void Clear();
};

struct VertexElementFormat {
	int offset;
	int bindingIndex;
	Tags::VertexElementType type;
	Tags::VertexElementSemantic semantic;

	int GetStride() const;

	auto operator<=>(const VertexElementFormat&) const = default;
};

struct VertexFormat : public RefCounted {
	std::vector<VertexElementFormat> elements;
	int vertexSize = 0;

	const std::vector<VertexElementFormat>& GetElements() { return elements; }
	void AddElement(VertexElementFormat element);
	void RemoveElement(int index);

	void Sort();
	void CompactBindingIndex();
};

class GpuMesh : public RefCounted {
public:
	RcPtr<VertexFormat> vertFormat;
	RcPtr<BufferBindings> vertBufBindings;
	RcPtr<GpuIndexBuffer> indexBuf;

public:
	GpuMesh(VertexFormat* vertexFormat, BufferBindings* bindings, GpuIndexBuffer* indexBuffer);

	bool IsEmpty() const;
	void SetVertex(VertexFormat* vertexFormat, BufferBindings* bindings);
	VertexFormat* GetVertexFormat() const;
	BufferBindings* GetVertexBufferBindings() const;
	void SetIndex(GpuIndexBuffer* buffer);
	GpuIndexBuffer* GetIndexBuffer() const;
};