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 }