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.model;
33 
34 import mango_engine.mango;
35 import mango_engine.util;
36 import mango_engine.game;
37 import mango_engine.event.graphics;
38 import mango_engine.graphics.backend;
39 import mango_engine.graphics.renderer;
40 import mango_engine.graphics.texture;
41 import mango_engine.graphics.shader;
42 
43 import gl3n.linalg;
44 
45 /// Struct that represents a Vertex with a vec3 (position)
46 class Vertex {
47     /// Vector containing the Vertex's coordinates (3D).
48     vec3 position;
49 
50     this(vec3 position) @safe nothrow {
51         this.position = position;
52     }
53 }
54 
55 /++
56     Struct that represents a Vertex with
57     a position vector(vec3), and a texture
58     vector (vec2).
59 +/
60 class TexturedVertex : Vertex {
61     /// Vector containing the texture coordinates.
62     vec2 texture;
63 
64     this(vec3 position, vec2 texture) @safe nothrow {
65         super(position);
66         this.texture = texture;
67     }
68 }
69 
70 abstract class Model {
71     private GameManager game;
72     private SyncLock lock;
73 
74     protected shared Vertex[] vertices;
75     protected shared uint[] _indices;
76 
77     protected shared Texture _texture;
78     protected shared ShaderProgram _shader;
79 
80     @property uint[] indices() @trusted nothrow { return cast(uint[]) _indices; }
81     
82     @property Texture texture() @trusted nothrow { return cast(Texture) _texture; }
83     @property shared void texture(shared Texture texture) @safe {
84         synchronized(lock) {
85             this._texture = texture;
86         }
87     }
88     
89     @property ShaderProgram shader() @trusted  nothrow { return cast(ShaderProgram) _shader; }
90 
91     protected this(GameManager game, Vertex[] vertices, uint[] indices, Texture texture, ShaderProgram shader) @trusted nothrow {
92         this.game = game;
93         this.lock = new SyncLock();
94 
95         this.vertices = cast(shared) vertices;
96         this._indices = cast(shared) indices;
97 
98         this._texture = cast(shared) texture;
99         this._shader = cast(shared) shader;
100     }
101 
102     static Model modelFactory(GameManager game, Vertex[] vertices, uint[] indices, Texture texture, ShaderProgram shader, GraphicsBackendType backend) @safe {
103         import mango_engine.graphics.opengl.gl_model : GLModel;
104 
105         mixin(GenFactory!("Model", "game, vertices, indices, texture, shader"));
106     }
107 
108     void render(Renderer renderer) @system {
109         game.eventManager.fireEvent(new ModelRenderBeginEvent(cast(shared) this));
110         synchronized(lock) {
111             render_(renderer);
112         }
113     }
114     abstract void cleanup() @system;
115     
116     abstract protected void render_(Renderer renderer) @system;
117 }