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 }