1 module d2d.rendering.mesh;
2 
3 import d2d;
4 
5 /// Class containing mesh IDs and length for OpenGL drawing.
6 class RenderableMesh
7 {
8 	/// OpenGL id of the buffer.
9 	public uint bufferID;
10 	/// Length of the index/data buffer.
11 	public uint count;
12 	/// Offset index in the index/data buffer.
13 	public uint start;
14 	/// OpenGL primitive type.
15 	public GLenum primitiveType = GL_TRIANGLES;
16 	/// Is this an indexed mesh.
17 	public bool indexed = true;
18 	/// Type of indices.
19 	public GLenum indexType = GL_UNSIGNED_INT;
20 
21 	/// OpenGL array of the vbo buffers.
22 	deprecated("no longer used") public uint[] vbos;
23 
24 	deprecated alias indexLength = count;
25 
26 	uint indexStride() const @property
27 	{
28 		if (!indexed)
29 			return 0;
30 
31 		switch (indexType)
32 		{
33 		case GL_UNSIGNED_BYTE:
34 			return 1;
35 		case GL_UNSIGNED_SHORT:
36 			return 2;
37 		case GL_UNSIGNED_INT:
38 			return 4;
39 		default:
40 			return 0;
41 		}
42 	}
43 
44 	/// Constructor for creating a new RenderableMesh with existing data.
45 	deprecated public this(uint bufferID, uint[] vbos, uint indexLength)
46 	{
47 		this.bufferID = bufferID;
48 		this.vbos = vbos;
49 		this.count = indexLength;
50 		indexed = true;
51 	}
52 
53 	/// Constructor for creating a new RenderableMesh with existing data.
54 	public this(uint bufferID, uint count, bool indexed)
55 	{
56 		this.bufferID = bufferID;
57 		this.count = count;
58 		this.indexed = indexed;
59 	}
60 }
61 
62 /// Class for raw geometry.
63 class Mesh : IDisposable, IVerifiable
64 {
65 	~this()
66 	{
67 		dispose();
68 	}
69 
70 	/// Array of the vertices.
71 	public @property vec3[] vertices()
72 	{
73 		return _vertices;
74 	}
75 
76 	/// Array of the indices.
77 	public @property uint[] indices()
78 	{
79 		return _indices;
80 	}
81 
82 	/// Array of the texture coordinates.
83 	public @property vec2[] texCoords()
84 	{
85 		return _texCoords;
86 	}
87 
88 	/// Checks if this Mesh can be drawn.
89 	public @property bool valid()
90 	{
91 		return renderable !is null;
92 	}
93 
94 	/// Adds one vertex.
95 	public void addVertex(vec3 vertex)
96 	{
97 		_vertices ~= vertex;
98 	}
99 
100 	/// Adds many vertices.
101 	public void addVertices(const vec3[] vertices)
102 	{
103 		_vertices ~= vertices;
104 	}
105 
106 	/// Adds one index.
107 	public void addIndex(uint index)
108 	{
109 		_indices ~= index;
110 	}
111 
112 	/// Adds many indices.
113 	public void addIndices(const uint[] indices)
114 	{
115 		_indices ~= indices;
116 	}
117 
118 	/// Adds one texture coordinate.
119 	public void addTexCoord(vec2 texCoord)
120 	{
121 		_texCoords ~= texCoord;
122 	}
123 
124 	/// Adds many texture coordinates.
125 	public void addTexCoords(const vec2[] texCoords)
126 	{
127 		_texCoords ~= texCoords;
128 	}
129 
130 	/// Deletes the mesh from memory and cleans up.
131 	public void dispose()
132 	{
133 		if (valid)
134 		{
135 			glDeleteVertexArrays(1, &vao);
136 			glDeleteBuffers(vbo.length, &vbo[0]);
137 			glDeleteVertexArrays(1, &renderable.bufferID);
138 			renderable = null;
139 		}
140 	}
141 
142 	/// Generates the RenderableMesh from the previously defined vertices and makes `this` valid.
143 	public void create()
144 	{
145 		glGenVertexArrays(1, &vao);
146 		glBindVertexArray(vao);
147 
148 		glGenBuffers(vbo.length, &vbo[0]);
149 
150 		glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
151 		glBufferData(GL_ARRAY_BUFFER, vec3.sizeof * vertices.length, vertices.ptr, GL_STATIC_DRAW);
152 		glVertexAttribPointer(0u, 3, GL_FLOAT, cast(ubyte) 0, 0, null);
153 		glEnableVertexAttribArray(0);
154 
155 		glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
156 		glBufferData(GL_ARRAY_BUFFER, vec2.sizeof * texCoords.length, texCoords.ptr, GL_STATIC_DRAW);
157 		glVertexAttribPointer(1u, 2, GL_FLOAT, cast(ubyte) 0, 0, null);
158 		glEnableVertexAttribArray(1);
159 
160 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]);
161 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, uint.sizeof * indices.length,
162 				indices.ptr, GL_STATIC_DRAW);
163 
164 		glBindVertexArray(0);
165 
166 		renderable = new RenderableMesh(vao, cast(uint) indices.length, true);
167 	}
168 
169 	/// Renderable mesh when create got called. Before its `null`.
170 	public RenderableMesh renderable = null;
171 
172 	private uint vao;
173 	private uint[3] vbo;
174 
175 	private vec3[] _vertices;
176 	private vec3[] _normals;
177 	private vec2[] _texCoords;
178 	private uint[] _indices;
179 }