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(null, 1000); 68 69 gFloor = New!GeomBox(world, 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(world, 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 Delete(world); 108 sBox.free(); 109 110 font.free(); 111 fpsText.free(); 112 } 113 114 override void onKeyDown(int key) 115 { 116 super.onKeyDown(key); 117 } 118 119 int prevMouseX; 120 int prevMouseY; 121 122 override void onMouseButtonDown(int button) 123 { 124 if (button == SDL_BUTTON_MIDDLE) 125 { 126 prevMouseX = eventManager.mouseX; 127 prevMouseY = eventManager.mouseY; 128 } 129 else if (button == SDL_BUTTON_WHEELUP) 130 { 131 camera.zoom(1.0f); 132 } 133 else if (button == SDL_BUTTON_WHEELDOWN) 134 { 135 camera.zoom(-1.0f); 136 } 137 } 138 139 override void free() 140 { 141 Delete(this); 142 } 143 144 double time = 0.0; 145 146 override void onUpdate() 147 { 148 double dt = eventManager.deltaTime; 149 150 time += dt; 151 if (time >= fixedTimeStep) 152 { 153 time -= fixedTimeStep; 154 world.update(fixedTimeStep); 155 } 156 157 updateCamera(); 158 159 fpsText.setText(format("FPS: %s", eventManager.fps)); 160 } 161 162 override void onRedraw() 163 { 164 double dt = eventManager.deltaTime; 165 166 float aspectRatio = cast(float)eventManager.windowWidth / cast(float)eventManager.windowHeight; 167 168 glMatrixMode(GL_PROJECTION); 169 glLoadIdentity(); 170 gluPerspective(60.0f, aspectRatio, 0.1, 1000.0); 171 glMatrixMode(GL_MODELVIEW); 172 173 glLoadIdentity(); 174 glPushMatrix(); 175 camera.bind(dt); 176 177 grid.draw(dt); 178 glDisable(GL_DEPTH_TEST); 179 axes.draw(dt); 180 glEnable(GL_DEPTH_TEST); 181 182 glEnable(GL_LIGHTING); 183 glEnable(GL_LIGHT0); 184 glLightfv(GL_LIGHT0, GL_POSITION, lightPosition.arrayof.ptr); 185 186 foreach(d; drawables.data) 187 d.draw(dt); 188 189 glDisable(GL_LIGHTING); 190 191 camera.unbind(); 192 glPopMatrix(); 193 194 glMatrixMode(GL_PROJECTION); 195 glLoadIdentity(); 196 glOrtho(0, eventManager.windowWidth, 0, eventManager.windowHeight, 0, 1); 197 glMatrixMode(GL_MODELVIEW); 198 199 fpsText.draw(dt); 200 } 201 202 void updateCamera() 203 { 204 if (eventManager.mouseButtonPressed[SDL_BUTTON_MIDDLE] && eventManager.keyPressed[SDLK_LSHIFT]) 205 { 206 float shift_x = (eventManager.mouseX - prevMouseX) * 0.1f; 207 float shift_y = (eventManager.mouseY - prevMouseY) * 0.1f; 208 Vector3f trans = camera.getUpVector * shift_y + camera.getRightVector * shift_x; 209 camera.translateTarget(trans); 210 } 211 else if (eventManager.mouseButtonPressed[SDL_BUTTON_MIDDLE] && eventManager.keyPressed[SDLK_LCTRL]) 212 { 213 float shift_x = (eventManager.mouseX - prevMouseX); 214 float shift_y = (eventManager.mouseY - prevMouseY); 215 camera.zoom((shift_x + shift_y) * 0.1f); 216 } 217 else if (eventManager.mouseButtonPressed[SDL_BUTTON_MIDDLE]) 218 { 219 float turn_m = (eventManager.mouseX - prevMouseX); 220 float pitch_m = -(eventManager.mouseY - prevMouseY); 221 camera.pitch(pitch_m); 222 camera.turn(turn_m); 223 } 224 225 prevMouseX = eventManager.mouseX; 226 prevMouseY = eventManager.mouseY; 227 } 228 } 229 230 void main(string[] args) 231 { 232 loadLibraries(); 233 writefln("Allocated memory at start: %s", allocatedMemory); 234 auto app = New!TestApp(); 235 app.run(); 236 Delete(app); 237 writefln("Allocated memory at end: %s", allocatedMemory); 238 }