1 module simple; 2 3 import std.stdio; 4 import std.format; 5 6 import dlib.core.memory; 7 import dlib.container.array; 8 import dlib.math.vector; 9 import dlib.image.color; 10 11 import derelict.opengl.gl; 12 import derelict.opengl.glu; 13 import derelict.sdl.sdl; 14 15 import dgl.core.application; 16 import dgl.core.interfaces; 17 import dgl.core.event; 18 import dgl.graphics.shapes; 19 import dgl.graphics.tbcamera; 20 import dgl.graphics.axes; 21 import dgl.ui.font; 22 import dgl.ui.ftfont; 23 import dgl.ui.textline; 24 25 import dmech.world; 26 import dmech.geometry; 27 import dmech.rigidbody; 28 import dmech.shape; 29 30 import testbed.grid; 31 import testbed.physicsentity; 32 33 class TestApp: Application 34 { 35 TrackballCamera camera; 36 DynamicArray!Drawable drawables; 37 Vector4f lightPosition; 38 39 Axes axes; 40 Grid grid; 41 ShapeBox sBox; 42 43 PhysicsWorld world; 44 GeomBox gFloor; 45 GeomBox gBox; 46 47 enum fixedTimeStep = 1.0 / 60.0; 48 49 Font font; 50 TextLine fpsText; 51 52 this() 53 { 54 super(800, 600, "dmech test"); 55 clearColor = Color4f(0.5f, 0.5f, 0.5f); 56 57 camera = New!TrackballCamera(); 58 camera.pitch(45.0f); 59 camera.turn(45.0f); 60 camera.setZoom(20.0f); 61 62 lightPosition = Vector4f(1, 1, 0.5, 0); 63 64 axes = New!Axes(); 65 grid = New!Grid(); 66 67 world = New!PhysicsWorld(1000); 68 69 gFloor = New!GeomBox(Vector3f(40, 1, 40)); 70 auto bFloor = world.addStaticBody(Vector3f(0, -1, 0)); 71 world.addShapeComponent(bFloor, gFloor, Vector3f(0, 0, 0), 1.0f); 72 73 gBox = New!GeomBox(Vector3f(1, 1, 1)); // Physical shape 74 sBox = New!ShapeBox(Vector3f(1, 1, 1)); // Graphical shape 75 76 foreach(i; 0..10) 77 addBoxEntity(Vector3f(-10 + i, 2 + i * 2.1, 0)); 78 79 font = New!FreeTypeFont("data/fonts/droid/DroidSans.ttf", 18); 80 81 fpsText = New!TextLine(font, "FPS: 0", Vector2f(8, 8)); 82 fpsText.color = Color4f(1, 1, 1); 83 } 84 85 PhysicsEntity addBoxEntity(Vector3f pos) 86 { 87 auto bBox = world.addDynamicBody(pos, 0.0f); 88 auto scBox = world.addShapeComponent(bBox, gBox, Vector3f(0, 0, 0), 1.0f); 89 PhysicsEntity peBox = New!PhysicsEntity(sBox, bBox); 90 addDrawable(peBox); 91 return peBox; 92 } 93 94 void addDrawable(Drawable d) 95 { 96 drawables.append(d); 97 } 98 99 ~this() 100 { 101 camera.free(); 102 foreach(d; drawables.data) 103 d.free(); 104 drawables.free(); 105 axes.free(); 106 grid.free(); 107 world.free(); 108 sBox.free(); 109 110 gFloor.free(); 111 gBox.free(); 112 113 font.free(); 114 fpsText.free(); 115 } 116 117 override void onKeyDown(int key) 118 { 119 super.onKeyDown(key); 120 } 121 122 int prevMouseX; 123 int prevMouseY; 124 125 override void onMouseButtonDown(int button) 126 { 127 if (button == SDL_BUTTON_MIDDLE) 128 { 129 prevMouseX = eventManager.mouseX; 130 prevMouseY = eventManager.mouseY; 131 } 132 else if (button == SDL_BUTTON_WHEELUP) 133 { 134 camera.zoom(1.0f); 135 } 136 else if (button == SDL_BUTTON_WHEELDOWN) 137 { 138 camera.zoom(-1.0f); 139 } 140 } 141 142 override void free() 143 { 144 Delete(this); 145 } 146 147 double time = 0.0; 148 149 override void onUpdate() 150 { 151 double dt = eventManager.deltaTime; 152 153 time += dt; 154 if (time >= fixedTimeStep) 155 { 156 time -= fixedTimeStep; 157 world.update(fixedTimeStep); 158 } 159 160 updateCamera(); 161 162 fpsText.setText(format("FPS: %s", eventManager.fps)); 163 } 164 165 override void onRedraw() 166 { 167 double dt = eventManager.deltaTime; 168 169 float aspectRatio = cast(float)eventManager.windowWidth / cast(float)eventManager.windowHeight; 170 171 glMatrixMode(GL_PROJECTION); 172 glLoadIdentity(); 173 gluPerspective(60.0f, aspectRatio, 0.1, 1000.0); 174 glMatrixMode(GL_MODELVIEW); 175 176 glLoadIdentity(); 177 glPushMatrix(); 178 camera.bind(dt); 179 180 grid.draw(dt); 181 glDisable(GL_DEPTH_TEST); 182 axes.draw(dt); 183 glEnable(GL_DEPTH_TEST); 184 185 glEnable(GL_LIGHTING); 186 glEnable(GL_LIGHT0); 187 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition.arrayof.ptr); 188 189 foreach(d; drawables.data) 190 d.draw(dt); 191 192 glDisable(GL_LIGHTING); 193 194 camera.unbind(); 195 glPopMatrix(); 196 197 glMatrixMode(GL_PROJECTION); 198 glLoadIdentity(); 199 glOrtho(0, eventManager.windowWidth, 0, eventManager.windowHeight, 0, 1); 200 glMatrixMode(GL_MODELVIEW); 201 202 fpsText.draw(dt); 203 } 204 205 void updateCamera() 206 { 207 if (eventManager.mouseButtonPressed[SDL_BUTTON_MIDDLE] && eventManager.keyPressed[SDLK_LSHIFT]) 208 { 209 float shift_x = (eventManager.mouseX - prevMouseX) * 0.1f; 210 float shift_y = (eventManager.mouseY - prevMouseY) * 0.1f; 211 Vector3f trans = camera.getUpVector * shift_y + camera.getRightVector * shift_x; 212 camera.translateTarget(trans); 213 } 214 else if (eventManager.mouseButtonPressed[SDL_BUTTON_MIDDLE] && eventManager.keyPressed[SDLK_LCTRL]) 215 { 216 float shift_x = (eventManager.mouseX - prevMouseX); 217 float shift_y = (eventManager.mouseY - prevMouseY); 218 camera.zoom((shift_x + shift_y) * 0.1f); 219 } 220 else if (eventManager.mouseButtonPressed[SDL_BUTTON_MIDDLE]) 221 { 222 float turn_m = (eventManager.mouseX - prevMouseX); 223 float pitch_m = -(eventManager.mouseY - prevMouseY); 224 camera.pitch(pitch_m); 225 camera.turn(turn_m); 226 } 227 228 prevMouseX = eventManager.mouseX; 229 prevMouseY = eventManager.mouseY; 230 } 231 } 232 233 void main(string[] args) 234 { 235 loadLibraries(); 236 writefln("Allocated memory at start: %s", allocatedMemory); 237 auto app = New!TestApp(); 238 app.run(); 239 Delete(app); 240 writefln("Allocated memory at end: %s", allocatedMemory); 241 }