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