1 /*
2  *  BSD 3-Clause License
3  *  
4  *  Copyright (c) 2016, Mango-Engine Team
5  *  All rights reserved.
6  *  
7  *  Redistribution and use in source and binary forms, with or without
8  *  modification, are permitted provided that the following conditions are met:
9  *  
10  *  * Redistributions of source code must retain the above copyright notice, this
11  *    list of conditions and the following disclaimer.
12  *  
13  *  * Redistributions in binary form must reproduce the above copyright notice,
14  *    this list of conditions and the following disclaimer in the documentation
15  *    and/or other materials provided with the distribution.
16  *  
17  *  * Neither the name of the copyright holder nor the names of its
18  *    contributors may be used to endorse or promote products derived from
19  *    this software without specific prior written permission.
20  *  
21  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
22  *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
24  *  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
25  *  FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  *  DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
27  *  SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
28  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29  *  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30  *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31 */
32 module mango_engine.graphics.opengl.gl_types;
33 
34 import mango_engine.graphics.model : Vertex, TexturedVertex;
35 import mango_engine.graphics.opengl.gl_backend : gl_check;
36 
37 import derelict.opengl3.gl3;
38 
39 import gl3n.linalg;
40 
41 /++ 
42     Converts an array of Vertexs (vertices) to a raw float array that
43     contains just the vertex coordinates.
44 +/
45 float[] positionVerticesToFloats(Vertex[] vertices) @safe {
46     // TODO: Will have to adapt when more vectors are added
47     float[] data;
48     foreach(vertex; vertices) {
49         data ~= vertex.position.x;
50         data ~= vertex.position.y;
51         data ~= vertex.position.z;
52     }
53     return data;
54 }
55 
56 /++
57     Converts an array of Vertexs (vertices) to a raw float array
58     containing just the texture coordinates.
59 +/
60 float[] textureVerticesToFloats(Vertex[] vertices) @trusted {
61     float[] data;
62     if(!(cast(TexturedVertex[]) vertices)) {
63         import mango_engine.exception : InvalidArgumentException;
64         throw new InvalidArgumentException("Vertices not type of TexturedVertex!");
65     }
66     foreach(vertex; (cast(TexturedVertex[]) vertices)) {
67         data ~= vertex.texture.x;
68         data ~= vertex.texture.y;
69     }
70     return data;
71 }
72 
73 /// Represents an OpenGL VAO.
74 class VAO {
75     private GLuint _vao;
76 
77     /// GLuint id for the VAO.
78     @property GLuint vao() @safe nothrow { return _vao; }
79 
80     private this(GLuint vao) @safe nothrow {
81         _vao = vao;
82     }
83 
84     /++
85         Generate a new VAO.
86         (glGenVertexArrays)
87 
88         Returns: A new, empty VAO.
89     +/
90     static VAO generateNew() @trusted {
91         gl_check();
92         
93         GLuint id;
94         glGenVertexArrays(1, &id);
95 
96         return new VAO(id);
97     }
98 
99     /// Bind the VAO and make it ready for use from OpenGL.
100     void bind() @system nothrow {
101         glBindVertexArray(vao);
102     }
103 
104     /// Unbind the VAO.
105     void unbind() @system nothrow {
106         glBindVertexArray(0);
107     }
108 
109     /++
110         Cleans up resources used by the VAO.
111         Make sure to cleanup() on VBOs aswell.
112     +/
113     void cleanup() @system nothrow {
114         glDeleteVertexArrays(1, &_vao);
115     }
116 }
117 
118 /// Represents an OpenGL VBO.
119 class VBO {
120     private GLenum _type;
121     private GLuint _vbo;
122 
123     /// The VBO's GLuint id.
124     @property GLuint vbo() @safe nothrow { return _vbo; }
125     /// The VBO Type, ex. GL_ARRAY_BUFFER.
126     @property GLenum type() @safe nothrow { return _type; }
127 
128     /++
129         Create a new VBO with the specified type.
130         (glGenBuffers)
131 
132         Params:
133                 type =  The type (or target) of the buffer,
134                         ex. GL_ARRAY_BUFFER.
135     +/
136     this(GLenum type) @trusted {
137         gl_check();
138         
139         _type = type;
140 
141         glGenBuffers(1, &_vbo);
142     }
143 
144     /// Binds the buffer for OpenGL use.
145     void bind() @system nothrow {
146         glBindBuffer(type, vbo);
147     }
148 
149     /++
150         Sets the data of the buffer (raw).
151 
152         Params:
153                 data   =    The data to be placed in the buffer.
154                 length =    The length in bytes of the data.
155                 usage  =    See OpenGL docs on usage parameter in
156                             glBufferData.
157     +/
158     void setDataRaw(GLvoid* data, GLsizei length, GLenum usage = GL_STATIC_DRAW) @system {
159         bind();
160 
161         glBufferData(type, length, data, usage);
162     }
163 
164     /++
165         Set the data of the buffer.
166         Uses glBufferData.
167 
168         Params:
169                 data =      The Data to be placed in the buffer.
170                 usage =     See OpenGL docs on usage parameter in
171                             glBufferData.
172     +/
173     void setData(float[] data, GLenum usage = GL_STATIC_DRAW) @system {
174         bind();
175 
176         glBufferData(type, cast(size_t) (data.length * float.sizeof), data.ptr, usage);
177     }
178 
179     /++
180         Set the data of the buffer.
181         Uses glBufferData.
182 
183         Params:
184                 data =      The Data to be placed in the buffer.
185                 usage =     See OpenGL docs on usage parameter in
186                             glBufferData.
187     +/
188     void setData(uint[] data, GLenum usage = GL_STATIC_DRAW) @system {
189         bind();
190 
191         glBufferData(type, cast(size_t) (data.length * uint.sizeof), data.ptr, usage);
192     }
193 
194     /// Frees resources used by the buffer (deletes it).
195     void cleanup() @system nothrow {
196         glDeleteBuffers(1, &_vbo);
197     }
198 }