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 vao buffer.
9 	public uint bufferID;
10 	/// OpenGL array of the vbo buffers.
11 	public uint * vbos;
12 	/// Length of the index buffer.
13 	public uint indexLength;
14 
15 	/// Constructor for creating a new RenderableMesh with existing data.
16 	public this(uint bufferID, uint* vbos, uint indexLength)
17 	{
18 		this.bufferID = bufferID;
19 		this.vbos = vbos;
20 		this.indexLength = indexLength;
21 	}
22 }
23 
24 /// Class for raw geometry.
25 class Mesh : IDisposable, IVerifiable
26 {
27 	~this()
28 	{
29 		dispose();
30 	}
31 
32 	/// Array of the vertices.
33 	public @property vec3[] vertices()
34 	{
35 		return _vertices;
36 	}
37 
38 	/// Array of the indices.
39 	public @property uint[] indices()
40 	{
41 		return _indices;
42 	}
43 
44 	/// Array of the texture coordinates.
45 	public @property vec2[] texCoords()
46 	{
47 		return _texCoords;
48 	}
49 
50 	/// Checks if this Mesh can be drawn.
51 	public @property bool valid()
52 	{
53 		return renderable !is null;
54 	}
55 
56 	/// Adds one vertex.
57 	public void addVertex(vec3 vertex)
58 	{
59 		_vertices ~= vertex;
60 	}
61 
62 	/// Adds many vertices.
63 	public void addVertices(const vec3[] vertices)
64 	{
65 		_vertices ~= vertices;
66 	}
67 
68 	/// Adds one index.
69 	public void addIndex(uint index)
70 	{
71 		_indices ~= index;
72 	}
73 
74 	/// Adds many indices.
75 	public void addIndices(const uint[] indices)
76 	{
77 		_indices ~= indices;
78 	}
79 
80 	/// Adds one texture coordinate.
81 	public void addTexCoord(vec2 texCoord)
82 	{
83 		_texCoords ~= texCoord;
84 	}
85 
86 	/// Adds many texture coordinates.
87 	public void addTexCoords(const vec2[] texCoords)
88 	{
89 		_texCoords ~= texCoords;
90 	}
91 
92 	/// Deletes the mesh from memory and cleans up.
93 	public void dispose()
94 	{
95 		if (valid)
96 		{
97 			glDeleteBuffers(3, renderable.vbos);
98 			glDeleteVertexArrays(1, &renderable.bufferID);
99 			renderable = null;
100 		}
101 	}
102 
103 	/// Generates the RenderableMesh from the previously defined vertices and makes `this` valid.
104 	public void create()
105 	{
106 		uint vao;
107 		glGenVertexArrays(1, &vao);
108 		glBindVertexArray(vao);
109 
110 		uint* vbo = new uint[3].ptr;
111 
112 		glGenBuffers(3, vbo);
113 
114 		glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
115 		glBufferData(GL_ARRAY_BUFFER, vec3.sizeof * vertices.length, vertices.ptr, GL_STATIC_DRAW);
116 		glVertexAttribPointer(0u, 3, GL_FLOAT, cast(ubyte) 0, 0, null);
117 		glEnableVertexAttribArray(0);
118 
119 		glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
120 		glBufferData(GL_ARRAY_BUFFER, vec2.sizeof * texCoords.length, texCoords.ptr, GL_STATIC_DRAW);
121 		glVertexAttribPointer(1u, 2, GL_FLOAT, cast(ubyte) 0, 0, null);
122 		glEnableVertexAttribArray(1);
123 
124 		glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]);
125 		glBufferData(GL_ELEMENT_ARRAY_BUFFER, uint.sizeof * indices.length, indices.ptr, GL_STATIC_DRAW);
126 
127 		glBindVertexArray(0);
128 
129 		renderable = new RenderableMesh(vao, vbo, cast(uint) indices.length);
130 	}
131 
132 	/// Renderable mesh when create got called. Before its `null`.
133 	public RenderableMesh renderable = null;
134 
135 	private vec3[]        _vertices;
136 	private vec3[]        _normals;
137 	private vec2[]        _texCoords;
138 	private uint[]        _indices;
139 }