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;
35 
36 import derelict.opengl3.gl3;
37 
38 import gl3n.linalg;
39 
40 /++ 
41     Converts an array of Vertexs (vertices) to a raw float array that
42     contains just the vertex coordinates.
43 +/
44 float[] positionVerticesToFloats(Vertex[] vertices) @safe {
45     // TODO: Will have to adapt when more vectors are added
46     float[] data;
47     foreach(vertex; vertices) {
48         data ~= vertex.x;
49         data ~= vertex.y;
50         data ~= vertex.z;
51     }
52     return data;
53 }
54 
55 /++
56     Converts an array of Vertexs (vertices) to a raw float array
57     containing just the texture coordinates.
58 +/
59 float[] textureVerticesToFloats(Vertex[] vertices) @trusted {
60     float[] data;
61     if(!(cast(TexturedVertex[]) vertices)) {
62         throw new Exception("Vertices not type of TexturedVertex!");
63     }
64     foreach(vertex; (cast(TexturedVertex[]) vertices)) {
65         data ~= vertex.tX;
66         data ~= vertex.tY;
67     }
68     return data;
69 }
70 
71 /// Represents an OpenGL VAO.
72 class VAO {
73     private GLuint _vao;
74 
75     /// GLuint id for the VAO.
76     @property GLuint vao() @trusted nothrow { return _vao; }
77 
78     private this(GLuint vao) @trusted nothrow {
79         _vao = vao;
80     }
81 
82     /++
83         Generate a new VAO.
84         (glGenVertexArrays)
85         Returns: A new, empty VAO.
86     +/
87     static VAO generateNew() @trusted {
88         GLuint id;
89         glGenVertexArrays(1, &id);
90 
91         return new VAO(id);
92     }
93 
94     /// Bind the VAO and make it ready for use from OpenGL.
95     void bind() @system nothrow {
96         glBindVertexArray(vao);
97     }
98 
99     /// Unbind the VAO.
100     void unbind() @system nothrow {
101         glBindVertexArray(0);
102     }
103 
104     /++
105         Cleans up resources used by the VAO.
106         Make sure to cleanup() on VBOs aswell.
107     +/
108     void cleanup() @system nothrow {
109         glDeleteVertexArrays(1, &_vao);
110     }
111 }
112 
113 /// Represents an OpenGL VBO.
114 class VBO {
115     private GLenum _type;
116     private GLuint _vbo;
117 
118     /// The VBO's GLuint id.
119     @property GLuint vbo() @trusted nothrow { return _vbo; }
120     /// The VBO Type, ex. GL_ARRAY_BUFFER.
121     @property GLenum type() @trusted nothrow { return _type; }
122 
123     /++
124         Create a new VBO with the specified type.
125         (glGenBuffers)
126         Params:
127                 type =  The type (or target) of the buffer,
128                         ex. GL_ARRAY_BUFFER.
129     +/
130     this(GLenum type) @trusted {
131         _type = type;
132 
133         glGenBuffers(1, &_vbo);
134     }
135 
136     /// Binds the buffer for OpenGL use.
137     void bind() @system nothrow {
138         glBindBuffer(type, vbo);
139     }
140 
141     /++
142         Sets the data of the buffer (raw).
143         Params:
144                 data   =    The data to be placed in the buffer.
145                 length =    The length in bytes of the data.
146                 usage  =    See OpenGL docs on usage parameter in
147                             glBufferData.
148     +/
149     void setDataRaw(GLvoid* data, GLsizei length, GLenum usage = GL_STATIC_DRAW) @system {
150         bind();
151 
152         glBufferData(type, length, data, usage);
153     }
154 
155     /++
156         Set the data of the buffer.
157         Uses glBufferData.
158         Params:
159                 data =      The Data to be placed in the buffer.
160                 usage =     See OpenGL docs on usage parameter in
161                             glBufferData.
162     +/
163     void setData(float[] data, GLenum usage = GL_STATIC_DRAW) @system {
164         bind();
165 
166         glBufferData(type, cast(size_t) (data.length * float.sizeof), data.ptr, usage);
167     }
168 
169     /++
170         Set the data of the buffer.
171         Uses glBufferData.
172         Params:
173                 data =      The Data to be placed in the buffer.
174                 usage =     See OpenGL docs on usage parameter in
175                             glBufferData.
176     +/
177     void setData(uint[] data, GLenum usage = GL_STATIC_DRAW) @system {
178         bind();
179 
180         glBufferData(type, cast(size_t) (data.length * uint.sizeof), data.ptr, usage);
181     }
182 
183     void setSubData(GLvoid* data, GLintptr offset, GLsizei length) @system {
184         bind();
185 
186         glBufferSubData(type, offset, length, data);
187     }
188 
189     /// Frees resources used by the buffer (deletes it).
190     void cleanup() @system nothrow {
191         glDeleteBuffers(1, &_vbo);
192     }
193 }