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.game; 35 import mango_engine.util; 36 import mango_engine.graphics.renderer; 37 import mango_engine.graphics.texture; 38 import mango_engine.graphics.shader; 39 40 import mango_stl.misc; 41 42 import gl3n.linalg; 43 44 /// Struct that represents a Vertex with a vec3 (position) 45 class Vertex { 46 shared float x; 47 shared float y; 48 shared float z; 49 50 /// Vector containing the Vertex's coordinates (3D). 51 vec3 positionToVec3() @safe nothrow { 52 return vec3(x, y, z); 53 } 54 55 /// Creates a copy of the vertex. 56 Vertex duplicate() @safe nothrow { 57 return new Vertex(vec3(this.x, this.y, this.z)); 58 } 59 60 this(vec3 position) @safe nothrow { 61 this.x = position.x; 62 this.y = position.y; 63 this.z = position.z; 64 } 65 } 66 67 /++ 68 Struct that represents a Vertex with 69 a position vector(vec3), and a texture 70 vector (vec2). 71 +/ 72 class TexturedVertex : Vertex { 73 shared float tX; 74 shared float tY; 75 76 /// Vector containing the texture coordinates. 77 vec2 textureToVec2() @safe nothrow { 78 return vec2(tX, tY); 79 } 80 81 override Vertex duplicate() @safe nothrow { 82 return new TexturedVertex(vec3(this.x, this.y, this.z), vec2(this.tX, this.tY)); 83 } 84 85 this(vec3 position, vec2 texture) @safe nothrow { 86 super(position); 87 this.tX = texture.x; 88 this.tY = texture.y; 89 } 90 } 91 92 /// Represents a Model which can be rendered. A Model has a Shader and a Texture 93 class Model { 94 immutable string name; 95 96 private shared GameManager _game; 97 private shared Lock lock; 98 99 protected shared Vertex[] vertices; 100 protected shared uint[] _indices; 101 102 protected shared Texture _texture; 103 protected shared ShaderProgram _shader; 104 105 @property uint[] indices() @trusted nothrow { return cast(uint[]) _indices; } 106 107 @property Texture texture() @trusted nothrow { return cast(Texture) _texture; } 108 @property shared void texture(shared Texture texture) @safe { 109 synchronized(lock) { 110 this._texture = texture; 111 } 112 } 113 114 @property ShaderProgram shader() @trusted nothrow { return cast(ShaderProgram) _shader; } 115 116 @property GameManager game() @trusted nothrow { return cast(GameManager) _game; } 117 118 protected this(in string name, GameManager game, Vertex[] vertices, uint[] indices, Texture texture, ShaderProgram shader) @trusted nothrow { 119 this.name = name; 120 this._game = cast(shared) game; 121 this.lock = new Lock(); 122 123 this.vertices = cast(shared) vertices; 124 this._indices = cast(shared) indices; 125 126 this._texture = cast(shared) texture; 127 this._shader = cast(shared) shader; 128 } 129 130 static Model build(in string name, GameManager game, Vertex[] vertices, uint[] indices, Texture texture, ShaderProgram shader) @safe { 131 mixin(InterfaceClassFactory!("model", "Model", "name, game, vertices, indices, texture, shader")); 132 } 133 134 final void render(Renderer renderer) @system { 135 //game.eventManager.fireEvent(new ModelRenderBeginEvent(cast(shared) this)); 136 synchronized(this.lock) { 137 render_(renderer); 138 } 139 } 140 141 final void replaceVertices(Vertex[] vertices) @trusted { 142 synchronized(this.lock) { 143 this.vertices = cast(shared) vertices; 144 replaceVertices_(); 145 } 146 } 147 148 final void replaceVertex(size_t arrayPosition, Vertex vertex) @trusted 149 in { 150 assert(arrayPosition < this.vertices.length, "Invalid arrayPosition (greater than array size!)"); 151 } body { 152 synchronized(this.lock) { 153 this.vertices[arrayPosition] = cast(shared) vertex; 154 replaceVertex_(arrayPosition, vertex); 155 } 156 } 157 158 final Vertex getVertex(size_t arrayPosition) @trusted 159 in { 160 assert(arrayPosition < this.vertices.length, "Invalid arrayPosition (greater than array size!)"); 161 } body { 162 synchronized(this.lock) { 163 return (cast(Vertex) this.vertices[arrayPosition]).duplicate(); 164 } 165 } 166 167 Vertex[] getVertices() @trusted nothrow { 168 return cast(Vertex[]) this.vertices; 169 } 170 171 /// Allows returning the lock used for preventing changes while renderering. 172 shared(Lock) getRenderingLock() @safe nothrow { 173 return this.lock; 174 } 175 176 abstract void cleanup() @system; 177 178 abstract protected void replaceVertices_() @system; 179 abstract protected void replaceVertex_(size_t pos, Vertex v) @system; 180 abstract protected void render_(Renderer renderer) @system; 181 }