10 // Replaces gluPerspective. Sets the frustum to perspective mode.
11 // fovY - Field of vision in degrees in the y direction
12 // aspect - Aspect ratio of the viewport
13 // zNear - The near clipping distance
14 // zFar - The far clipping distance
15 void perspectiveGL (GLdouble fovY
, GLdouble aspect
, GLdouble zNear
, GLdouble zFar
) {
16 import std
.math
: tan
;
17 //Very long (& in theory accurate!) version of Pi. Hopefully an optimizing compiler will replace references to this with the value!
18 enum GLdouble pi
= 3.1415926535897932384626433832795;
19 GLdouble fW
, fH
; // Half of the size of the x and y clipping planes.
20 // Calculate the distance from 0 of the y clipping plane. Basically trig to calculate position of clipper at zNear.
21 // Note: tan( double ) uses radians but OpenGL works in degrees so we convert degrees to radians by dividing by 360 then multiplying by pi.
22 // Formula below corrected by Carsten Jurenz:
23 //fH = tan( (fovY / 2) / 180 * pi ) * zNear;
24 // Which can be reduced to:
25 fH
= tan( fovY
/ 360 * pi
) * zNear
;
26 // Calculate the distance from 0 of the x clipping plane based on the aspect ratio.
28 // Finally call glFrustum, this is all gluPerspective does anyway! This is why we calculate half the distance between the clipping planes
29 // glFrustum takes an offset from zero for each clipping planes distance. (Saves 2 divides)
30 glFrustum( -fW
, fW
, -fH
, fH
, zNear
, zFar
);
43 float timeStep
= 1.0f/60.0f;
45 Vec2 gravity
= Vec2(0.0f, -10.0f);
52 bool frameStepping
= false;
56 static this () { world
= new World(gravity
, iterations
); }
59 static void DrawBody (Body
body) {
60 auto R
= Mat22(body.rotation
);
61 Vec2 x
= body.position
;
62 Vec2 h
= 0.5f*body.width
;
64 Vec2 v1
= x
+R
*Vec2(-h
.x
, -h
.y
);
65 Vec2 v2
= x
+R
*Vec2( h
.x
, -h
.y
);
66 Vec2 v3
= x
+R
*Vec2( h
.x
, h
.y
);
67 Vec2 v4
= x
+R
*Vec2(-h
.x
, h
.y
);
70 glColor3f(0.4f, 0.9f, 0.4f);
72 glColor3f(0.8f, 0.8f, 0.9f);
75 glBegin(GL_LINE_LOOP
);
76 glVertex2f(v1
.x
, v1
.y
);
77 glVertex2f(v2
.x
, v2
.y
);
78 glVertex2f(v3
.x
, v3
.y
);
79 glVertex2f(v4
.x
, v4
.y
);
84 static void DrawJoint (Joint joint
) {
85 Body b1
= joint
.body1
;
86 Body b2
= joint
.body2
;
88 auto R1
= Mat22(b1
.rotation
);
89 auto R2
= Mat22(b2
.rotation
);
91 Vec2 x1
= b1
.position
;
92 Vec2 p1
= x1
+R1
*joint
.localAnchor1
;
94 Vec2 x2
= b2
.position
;
95 Vec2 p2
= x2
+R2
*joint
.localAnchor2
;
97 glColor3f(0.5f, 0.5f, 0.8f);
99 glVertex2f(x1
.x
, x1
.y
);
100 glVertex2f(p1
.x
, p1
.y
);
101 glVertex2f(x2
.x
, x2
.y
);
102 glVertex2f(p2
.x
, p2
.y
);
108 void Demo1 (/*Body b, Joint j*/) {
109 with (auto b
= new Body()) {
110 b
.Set(Vec2(100.0f, 20.0f), float.max
);
111 b
.position
.Set(0.0f, -0.5f*b
.width
.y
);
117 with (auto b
= new Body()) {
118 b
.Set(Vec2(1.0f, 1.0f), 200.0f);
119 b
.position
.Set(0.0f, 4.0f);
127 __gshared
bool paused
= false;
128 __gshared
bool slowmo
= false;
129 __gshared
int slowmocount
= 0;
132 void InitDemo (int index
) {
138 //demos[index].init(bodies, joints);
142 void SimulationLoop () {
143 //static uint64_t t_start = 0;
144 static double accumulator
= 0;
148 glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT
);
151 snprintf(buf, sizeof(buf), "Demo %d: %s", demoIndex+1, demos[demoIndex].name);
152 DrawText(5, 15, buf);
153 DrawText(5, 45, "Keys: 1-9 Demos, Space to Launch the Bomb");
155 static char buffer[512];
156 sprintf(buffer, "(A)ccumulation %s", (World::accumulateImpulses ? "ON" : "OFF"));
157 DrawText(5, 75, buffer);
159 sprintf(buffer, "(P)osition Correction %s", (World::positionCorrection ? "ON" : "OFF"));
160 DrawText(5, 105, buffer);
162 sprintf(buffer, "(W)arm Starting %s", (World::warmStarting ? "ON" : "OFF"));
163 DrawText(5, 135, buffer);
166 glMatrixMode(GL_MODELVIEW
);
168 glTranslatef(0.0f, -7.0f, -25.0f);
171 t_cur = k8clock_msec(NULL);
172 if (t_start == 0) t_start = t_cur;
174 //world.Step(timeStep);
175 accumulator += (t_cur-t_start)/1000.0;
178 if (accumulator < 0.0) accumulator = 0.0;
179 else if (accumulator > 0.1) accumulator = 0.1;
181 while (accumulator >= timeStep) {
182 if (!frameStepping) {
183 world.Step(timeStep);
186 world.Step(timeStep);
190 accumulator -= timeStep;
198 glMatrixMode(GL_MODELVIEW
);
200 glTranslatef(0.0f, -7.0f, -25.0f);
203 foreach (Body b
; world
.bodies
) b
.DrawBody();
204 foreach (Joint j
; world
.joints
) j
.DrawJoint();
209 //setOpenGLContextVersion(3, 2); // up to GLSL 150
210 //openGLContextCompatible = false;
212 auto sdwindow
= new SimpleWindow(GWidth
, GHeight
, "Verlet Physics", OpenGlOptions
.yes
, Resizablity
.fixedSize
);
213 //sdwindow.hideCursor();
215 //sdwindow.closeQuery = delegate () { concmd("quit"); };
217 sdwindow
.redrawOpenGlScene
= delegate () {
218 glClear(GL_COLOR_BUFFER_BIT
);
222 if (dragVertex !is null) {
224 glColor3f(1.0f, 1.0f, 0.0f);
226 glVertex2f(dragVertex.position.x, dragVertex.position.y);
233 sdwindow
.visibleForTheFirstTime
= delegate () {
236 sdwindow
.setAsCurrentOpenGlContext(); // make this window active
237 glbindLoadFunctions();
240 glMatrixMode(GL_PROJECTION);
242 glOrtho(0, GWidth, GHeight, 0, -1, 1);
243 glMatrixMode(GL_MODELVIEW);
246 glViewport(0, 0, GWidth
, GHeight
);
247 glMatrixMode(GL_PROJECTION
);
249 perspectiveGL(45.0, cast(float)GWidth
/cast(float)GHeight
, 0.1, 100.0);
250 sdwindow
.redrawOpenGlScene();
253 sdwindow
.eventLoop(cast(int)(1000.0f/60.0f),
255 if (sdwindow
.closed || world
is null) return;
258 if (--slowmocount
< 0) {
267 sdwindow
.redrawOpenGlSceneNow();
269 delegate (KeyEvent event
) {
270 if (sdwindow
.closed
) return;
271 if (!event
.pressed
) return;
273 case Key
.Escape
: sdwindow
.close(); break;
277 delegate (MouseEvent event
) {
279 if (event.type == MouseEventType.buttonPressed) {
280 if (event.button == MouseButton.left) dragVertex = world.FindVertex(event.x, event.y);
281 if (event.button == MouseButton.right) dragVertex = null;
282 } else if (event.type == MouseEventType.buttonReleased) {
283 if (event.button == MouseButton.left) dragVertex = null;
285 if (dragVertex !is null) dragVertex.position = vec2(cast(float)event.x, cast(float)event.y); // sets the position of the dragVertex to the mouse position to drag it around
288 delegate (dchar ch
) {
289 if (ch
== 'q') { sdwindow
.close(); return; }
290 //if (ch == 'r') { initPhysics(); return; }
291 if (ch
== ' ') { paused
= !paused
; return; }
292 if (ch
== 's') { slowmo
= !slowmo
; return; }