1 module Engine.Core; 2 3 import derelict.glfw3.glfw3; 4 import derelict.opengl3.gl; 5 public import gl3n.linalg; 6 import Engine.Entity; 7 import std.datetime; 8 import std.stdio; 9 import Engine.Input; 10 import Engine.Coroutine; 11 import Engine.Camera; 12 import Engine.Shader; 13 import Engine.Batch; 14 import std.parallelism; 15 import Engine.Options; 16 import Engine.System; 17 import Engine.Systems.UpdateSystem; 18 import Engine.Systems.AwakeSystem; 19 import Engine.Systems.StartSystem; 20 21 public class Core 22 { 23 public static GLFWwindow* window; 24 package static Entity[] entities; 25 package static Batch[] batches; 26 package static System[] systems; 27 public shared static auto width = 800; 28 public shared static auto height = 600; 29 static Camera camera; 30 static Shader shader; 31 32 public shared static double DeltaTime; 33 34 public static size_t EntitiesCount() { 35 return entities.length; 36 } 37 38 public static void AddEntity(Entity entity) { 39 entities ~= entity; 40 entity.arrayIndex = entities.length-1; 41 foreach (s; systems) { 42 s.onEntityEnter(entity); 43 } 44 } 45 46 47 public static void AddSystem(System s) { 48 systems ~= s; 49 s.start(); 50 foreach (e; entities) { 51 s.onEntityEnter(e); 52 } 53 } 54 55 56 public static void AddBatch(Entity entity, Batchable batch) { 57 auto mat = batch.material; 58 foreach(ref b; batches) { 59 if (b.material == mat) { 60 b.Add(entity,batch); 61 return; 62 } 63 } 64 auto b = new Batch(4, mat); 65 batches ~= b; 66 b.Add(entity, batch); 67 } 68 69 public static void RemoveEntity(Entity entity) { 70 if (entity.inScene) { 71 auto index = entity.arrayIndex; 72 auto replaceEntity = entities[entities.length-1]; 73 entities[index] = replaceEntity; 74 replaceEntity.arrayIndex = index; 75 entity.arrayIndex = -1; 76 entities[entities.length-1] = null; //no idea how array resize works, but lets do it safe 77 entities.length--; 78 79 foreach (s; systems) { 80 s.onEntityLeave(entity); 81 } 82 } 83 } 84 85 public static void Start() 86 { 87 entities = new Entity[100]; 88 entities.length = 0; 89 90 systems ~= new AwakeSystem(); 91 systems ~= new StartSystem(); 92 systems ~= new UpdateSystem(); 93 94 95 96 DerelictGLFW3.load(); 97 DerelictGL3.load(); 98 99 100 if(!glfwInit()) 101 throw new Exception("glfwInit failure"); 102 103 104 105 glfwWindowHint(GLFW_VERSION_MAJOR, 2); // Use OpenGL Core v3.2 106 glfwWindowHint(GLFW_VERSION_MINOR, 1); 107 108 109 window = glfwCreateWindow(width,height,"SpaceSim",null,null); 110 if (!window) 111 throw new Exception("Failed to create window."); 112 113 114 115 glfwMakeContextCurrent(window); 116 DerelictGL3.reload(); 117 118 glfwSwapInterval(0); 119 Input.Initialize(); 120 121 if (glMapBufferRange is null) { 122 Options.useMapBufferRange = false; 123 } 124 125 glDisable(GL_CULL_FACE); 126 glClearDepth(1); 127 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); 128 glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 129 glDepthFunc(GL_NEVER); 130 glEnable(GL_BLEND); 131 glDepthMask(true); 132 initShaders(); 133 134 //glPolygonMode( GL_FRONT_AND_BACK, GL_LINE ); 135 //glLineWidth(5); 136 137 foreach (s; systems) { 138 s.start(); 139 } 140 } 141 142 private static void initShaders() { 143 const auto vertexSource = q"[ 144 #version 120 145 // Input vertex data, different for all executions of this shader. 146 attribute vec2 uv; 147 attribute vec4 color; 148 attribute vec3 vertex; 149 attribute mat3 models; 150 //uniform mat4 model; 151 uniform mat4 projection; 152 uniform mat4 view; 153 varying vec2 UV; 154 varying vec4 Color; 155 //uniform sampler2D transforms; 156 157 const float PI = 3.14159265358979323846264 / 180.0; 158 159 void main(){ 160 vec3 rot = models[1]*PI; 161 162 mat3 rotm = mat3(1,0,0, 163 0,cos(rot.x),-sin(rot.x), 164 0,sin(rot.x),cos(rot.x)) 165 * 166 mat3(cos(rot.y),0,sin(rot.y), 167 0,1,0, 168 -sin(rot.y),0,cos(rot.y)) 169 * 170 mat3(cos(rot.z),-sin(rot.z),0, 171 sin(rot.z),cos(rot.z),0, 172 0,0,1); 173 174 vec3 pos = (rotm*(vertex*models[2]))+models[0]; 175 176 gl_Position = projection * view * vec4(pos, 1.0); 177 UV = uv; 178 Color = color; 179 } 180 ]"; 181 182 183 const auto fragSource = q"[ 184 #version 120 185 varying vec2 UV; 186 varying vec4 Color; 187 uniform sampler2D texture; 188 189 void main() 190 { 191 gl_FragColor = texture2D(texture, UV) * Color; 192 } 193 ]"; 194 195 shader = new Shader(vertexSource, fragSource); 196 Core.shader = shader; 197 } 198 199 public static void Terminate() 200 { 201 glfwTerminate() ; 202 } 203 204 public static void Run() 205 { 206 StopWatch sw; 207 sw.start(); 208 while (!glfwWindowShouldClose(window)) 209 { 210 DeltaTime = cast(double)sw.peek().nsecs / 1000000000; 211 sw.reset(); 212 213 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 214 215 StopWatch t1; 216 t1.start(); 217 218 t1.stop(); 219 //writeln("START", cast(double)sw.peek().nsecs / 1000000000); 220 221 t1.start(); 222 foreach (s; systems) { 223 s.process(); 224 } 225 t1.stop(); 226 //writeln("Update ", cast(double)sw.peek().nsecs / 1000000); 227 228 RunCoroutines(); 229 230 t1.start(); 231 foreach (ref b; batches) { 232 b.Update(); 233 b.Draw(); 234 } 235 t1.stop(); 236 //writeln("Draw ", cast(double)sw.peek().nsecs / 1000000000); 237 //import core.memory; 238 Input.Update(); 239 //GC.enable(); 240 glfwSwapBuffers(window); 241 glfwPollEvents(); 242 //GC.disable(); 243 } 244 } 245 } 246