source: trunk/test/btphystest.cpp @ 2451

Last change on this file since 2451 was 2451, checked in by sam, 10 years ago

build: bad lolbot! fix the mess caused by its file renames.

File size: 15.8 KB
Line 
1//
2// BtPhysTest
3//
4// Copyright: (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
5//            (c) 2012-2013 Sam Hocevar <sam@hocevar.net>
6//
7
8#if defined HAVE_CONFIG_H
9#   include "config.h"
10#endif
11
12#if defined _XBOX
13#   define _USE_MATH_DEFINES /* for M_PI */
14#   include <xtl.h>
15#   undef near /* Fuck Microsoft */
16#   undef far /* Fuck Microsoft again */
17#elif defined _WIN32
18#   define _USE_MATH_DEFINES /* for M_PI */
19#   define WIN32_LEAN_AND_MEAN
20#   include <windows.h>
21#   undef near /* Fuck Microsoft */
22#   undef far /* Fuck Microsoft again */
23#else
24#   include <cmath>
25#endif
26
27#include "core.h"
28#include "loldebug.h"
29
30using namespace lol;
31
32#ifndef HAVE_PHYS_USE_BULLET
33#define HAVE_PHYS_USE_BULLET
34#endif /* HAVE_PHYS_USE_BULLET */
35
36#include "physics/lolphysics.h"
37#include "physics/easyphysics.h"
38#include "physicobject.h"
39#include "btphystest.h"
40
41using namespace lol::phys;
42
43#define CUBE_HALF_EXTENTS .5f
44#define EXTRA_HEIGHT 1.f
45
46int gNumObjects = 64;
47
48#define USE_WALL        1
49#define USE_PLATFORM    1
50#define USE_ROPE        0
51#define USE_BODIES        1
52#define USE_ROTATION    0
53#define USE_CHARACTER    1
54#define USE_STAIRS        1
55
56#define    IPT_MOVE_FORWARD        "Move_Forward"
57#define    IPT_MOVE_BACKWARD        "Move_Backward"
58#define    IPT_MOVE_LEFT            "Move_Left"
59#define    IPT_MOVE_RIGHT            "Move_Right"
60#define    IPT_MOVE_UP                "Move_Up"
61#define    IPT_MOVE_DOWN            "Move_Down"
62#define    IPT_MOVE_JUMP            "Move_Jump"
63
64BtPhysTest::BtPhysTest(bool editor)
65{
66    m_loop_value = .0f;
67
68    /* Create a camera that matches the settings of XNA BtPhysTest */
69    m_camera = new Camera(vec3(0.f, 600.f, 0.f),
70                          vec3(0.f, 0.f, 0.f),
71                          vec3(0, 1, 0));
72    m_camera->SetRotation(quat::fromeuler_xyz(0.f, 0.f, 0.f));
73    m_camera->SetPerspective(45.f, 1280.f, 960.f, .1f, 1000.f);
74    //m_camera->SetOrtho(1280.f / 6, 960.f / 6, -1000.f, 1000.f);
75    Ticker::Ref(m_camera);
76
77    m_ready = false;
78
79    m_simulation = new Simulation();
80    m_simulation->SetWorldLimit(vec3(-1000.0f, -1000.0f, -1000.0f), vec3(1000.0f, 1000.0f, 1000.0f));
81    m_simulation->Init();
82    vec3 NewGravity = vec3(.0f, -10.0f, .0f);
83    m_simulation->SetGravity(NewGravity);
84    m_simulation->SetContinuousDetection(true);
85    m_simulation->SetTimestep(1.f / 120.f);
86    Ticker::Ref(m_simulation);
87
88    /* Add a white directional light */
89    m_light1 = new Light();
90    m_light1->SetPosition(vec4(0.2f, 0.2f, 0.f, 0.f));
91    m_light1->SetColor(vec4(0.5f, 0.5f, 0.5f, 1.f));
92    Ticker::Ref(m_light1);
93
94    /* Add an orangeish point light */
95    m_light2 = new Light();
96    m_light2->SetPosition(vec4(-15.f, 15.f, 15.f, 1.f));
97    m_light2->SetColor(vec4(0.4f, 0.3f, 0.2f, 1.f));
98    Ticker::Ref(m_light2);
99
100    float offset = 29.5f;
101    vec3 pos_offset = vec3(.0f, 30.f, .0f);
102    if (USE_STAIRS)
103    {
104        vec3 new_offset = vec3(1.0f, .125f, .0f);
105        quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
106        vec3 NewPosition = pos_offset + vec3(5.0f, -29.f, 15.0f);
107        {
108            NewRotation = quat::fromeuler_xyz(0.f, 0.f, 30.f);
109            NewPosition += vec3(4.0f, .0f, -4.0f);
110
111            PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3);
112            Ticker::Ref(NewPhyobj);
113            m_stairs_list << NewPhyobj;
114        }
115        {
116            NewRotation = quat::fromeuler_xyz(0.f, 0.f, 40.f);
117            NewPosition += vec3(4.0f, .0f, -4.0f);
118
119            PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3);
120            Ticker::Ref(NewPhyobj);
121            m_stairs_list << NewPhyobj;
122        }
123        NewPosition = pos_offset + vec3(5.0f, -29.5f, 15.0f);
124        NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
125        for (int i=0; i < 15; i++)
126        {
127            NewPosition += new_offset;
128
129            PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3);
130            Ticker::Ref(NewPhyobj);
131            m_stairs_list << NewPhyobj;
132        }
133    }
134
135    if (USE_WALL)
136    {
137        for (int i=0; i < 6; i++)
138        {
139            vec3 NewPosition = vec3(.0f);
140            quat NewRotation = quat(1.f);
141
142            PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation);
143
144            int idx = i/2;
145            NewPosition = pos_offset;
146            NewPosition[idx] += offset;
147            offset *= -1.f;
148
149            if (idx != 1)
150            {
151                vec3 NewAxis = vec3(.0f);
152                NewAxis[2 - idx] = 1;
153                NewRotation = quat::rotate(90.f, NewAxis);
154            }
155
156            NewPhyobj->SetTransform(NewPosition, NewRotation);
157            Ticker::Ref(NewPhyobj);
158            m_ground_list << NewPhyobj;
159        }
160    }
161
162    PhysicsObject* BasePhyobj = NULL;
163    if (USE_PLATFORM)
164    {
165        quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
166        vec3 NewPosition = pos_offset + vec3(5.0f, -25.0f, -15.0f);
167
168        PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
169
170        m_platform_list << NewPhyobj;
171        Ticker::Ref(NewPhyobj);
172
173        NewPosition = pos_offset + vec3(-15.0f, -25.0f, 5.0f);
174
175        NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
176        BasePhyobj = NewPhyobj;
177
178        m_platform_list << NewPhyobj;
179        Ticker::Ref(NewPhyobj);
180
181        NewRotation = quat::fromeuler_xyz(0.f, 0.f, 90.f);
182        NewPosition = pos_offset + vec3(-20.0f, -25.0f, 5.0f);
183
184        NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
185
186        NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, true);
187        m_platform_list << NewPhyobj;
188        Ticker::Ref(NewPhyobj);
189
190        //NewPosition += vec3(-0.0f, .0f, .0f);
191        //NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
192
193        //NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, false);
194        //m_platform_list << NewPhyobj;
195        //Ticker::Ref(NewPhyobj);
196
197        //NewPosition += vec3(-2.0f, .0f, .0f);
198        //NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
199
200        //NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), false, false);
201        //m_platform_list << NewPhyobj;
202        //Ticker::Ref(NewPhyobj);
203    }
204
205    if (USE_CHARACTER)
206    {
207        quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
208        vec3 NewPosition = pos_offset + vec3(-5.0f, -10.0f, 15.0f);
209
210        PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2);
211
212        m_character_list << NewPhyobj;
213        Ticker::Ref(NewPhyobj);
214
215
216        Input::LinkActionToKey(IPT_MOVE_FORWARD,        Key::Up);
217        Input::LinkActionToKey(IPT_MOVE_BACKWARD,        Key::Down);
218        Input::LinkActionToKey(IPT_MOVE_LEFT,            Key::Left);
219        Input::LinkActionToKey(IPT_MOVE_RIGHT,            Key::Right);
220        Input::LinkActionToKey(IPT_MOVE_JUMP,            Key::Space);
221        Input::LinkActionToKey(IPT_MOVE_UP,                Key::PageUp);
222        Input::LinkActionToKey(IPT_MOVE_DOWN,            Key::PageDown);
223
224        //NewPhyobj->GetCharacter()->AttachTo(BasePhyobj->GetPhysic(), true, true);
225    }
226
227    if (USE_BODIES)
228    {
229        for (int x=0; x < 6; x++)
230        {
231            for (int y=0; y < 6; y++)
232            {
233                for (int z=0; z < 5; z++)
234                {
235                    PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f,
236                        vec3(-20.f, 15.f, -20.f) +
237                        vec3(8.f * (float)x, 8.f * (float)y, 8.f * (float)z));
238                    m_physobj_list << new_physobj;
239                    Ticker::Ref(new_physobj);
240                }
241            }
242        }
243    }
244
245    if (USE_ROPE)
246    {
247        Array<PhysicsObject*> RopeElements;
248        for (int i = 0; i < 14; i++)
249        {
250            PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f,
251                vec3(0.f, 15.f, -20.f) +
252                vec3(0.f, 0.f, 2.f * (float)i), 1);
253            RopeElements << new_physobj;
254            m_physobj_list << new_physobj;
255            Ticker::Ref(new_physobj);
256            if (RopeElements.Count() > 1)
257            {
258                EasyConstraint* new_constraint = new EasyConstraint();
259
260                vec3 A2B = .5f * (RopeElements[i]->GetPhysic()->GetTransform().v3.xyz -
261                            RopeElements[i - 1]->GetPhysic()->GetTransform().v3.xyz);
262                new_constraint->SetPhysObjA(RopeElements[i - 1]->GetPhysic(), lol::mat4::translate(A2B));
263                new_constraint->SetPhysObjB(RopeElements[i]->GetPhysic(), lol::mat4::translate(-A2B));
264                new_constraint->InitConstraintToPoint2Point();
265                new_constraint->DisableCollisionBetweenObjs(true);
266                new_constraint->AddToSimulation(m_simulation);
267                m_constraint_list << new_constraint;
268            }
269        }
270    }
271}
272
273void BtPhysTest::TickGame(float seconds)
274{
275    WorldEntity::TickGame(seconds);
276
277    if (Input::WasReleased(Key::Escape))
278        Ticker::Shutdown();
279
280    m_loop_value += seconds;
281    if (m_loop_value > M_PI * 2.0f)
282        m_loop_value -= M_PI * 2.0f;
283
284    vec3 GroundBarycenter = vec3(.0f);
285    vec3 PhysObjBarycenter = vec3(.0f);
286    float factor = .0f;
287
288    if (USE_WALL)
289    {
290        for (int i = 0; i < m_ground_list.Count(); i++)
291        {
292            PhysicsObject* PhysObj = m_ground_list[i];
293            mat4 GroundMat = PhysObj->GetTransform();
294
295            GroundBarycenter += GroundMat.v3.xyz;
296            factor += 1.f;
297        }
298
299        GroundBarycenter /= factor;
300
301        for (int i = 0; i < m_ground_list.Count(); i++)
302        {
303            PhysicsObject* PhysObj = m_ground_list[i];
304
305            mat4 GroundMat = PhysObj->GetTransform();
306            vec3 CenterToGround = GroundMat.v3.xyz - GroundBarycenter;
307            vec3 CenterToCam = m_camera->m_position - GroundBarycenter;
308
309            if (dot(normalize(CenterToCam - CenterToGround),
310                    normalize(CenterToGround)) > 0.f)
311                PhysObj->SetRender(false);
312            else
313                PhysObj->SetRender(true);
314        }
315    }
316
317    if (USE_ROTATION)
318    {
319        for (int i = 0; i < m_ground_list.Count(); i++)
320        {
321            PhysicsObject* PhysObj = m_ground_list[i];
322
323            mat4 GroundMat = PhysObj->GetTransform();
324            mat4 CenterMx = mat4::translate(GroundBarycenter);
325            GroundMat = inverse(CenterMx) * GroundMat;
326            GroundMat = CenterMx *
327                        mat4(quat::fromeuler_xyz(vec3(.0f, 20.f, 20.0f) * seconds))
328                        * GroundMat;
329            PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
330        }
331    }
332
333    if (USE_PLATFORM)
334    {
335        for (int i = 0; i < m_platform_list.Count(); i++)
336        {
337            PhysicsObject* PhysObj = m_platform_list[i];
338
339            mat4 GroundMat = PhysObj->GetTransform();
340            if (i == 0)
341            {
342                GroundMat = GroundMat * mat4(quat::fromeuler_xyz(vec3(20.f, .0f, .0f) * seconds));
343                PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
344            }
345            else if (i == 1)
346            {
347                GroundMat =
348                    mat4::translate(vec3(-15.0f, 5.0f, lol::cos(m_loop_value) * 8.f)) *
349                    mat4(quat::fromeuler_xyz(vec3(.0f, lol::cos(m_loop_value) * 20.f, .0f)));
350                PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
351            }
352        }
353    }
354
355    if (USE_CHARACTER)
356    {
357        for (int i = 0; i < m_character_list.Count(); i++)
358        {
359            PhysicsObject* PhysObj = m_character_list[i];
360            EasyCharacterController* Character = (EasyCharacterController*)PhysObj->GetCharacter();
361            mat4 CtlrMx = Character->GetTransform();
362
363            int HMovement = Input::GetStatus(IPT_MOVE_RIGHT) - Input::GetStatus(IPT_MOVE_LEFT);
364            int VMovement = Input::GetStatus(IPT_MOVE_FORWARD) - Input::GetStatus(IPT_MOVE_BACKWARD);
365            int RMovement = Input::GetStatus(IPT_MOVE_UP) - Input::GetStatus(IPT_MOVE_DOWN);
366            vec3 CharMove = vec3((float)VMovement * seconds * 4.f, (float)RMovement * seconds * 10.f, (float)HMovement * seconds * 4.f);
367
368            if (Input::WasReleased(IPT_MOVE_JUMP))
369                Character->Jump();
370            Character->SetMovementForFrame(CharMove);
371
372            RayCastResult HitResult;
373            if (m_simulation->RayHits(HitResult, ERT_Closest, Character->GetTransform().v3.xyz, (Character->GetTransform().v3.xyz + vec3(.0f, -1.f, .0f)), Character))
374                Character->AttachTo(HitResult.m_collider_list[0], true, true);
375            else
376                Character->AttachTo(NULL);
377        }
378    }
379
380    if (USE_CHARACTER)
381    {
382        PhysObjBarycenter = vec3(.0f);
383        factor = .0f;
384
385        for (int i = 0; i < m_character_list.Count(); i++)
386        {
387            PhysicsObject* PhysObj = m_character_list[i];
388            mat4 GroundMat = PhysObj->GetTransform();
389
390            PhysObjBarycenter += GroundMat.v3.xyz;
391            factor += 1.f;
392        }
393
394        PhysObjBarycenter /= factor;
395
396        m_camera->SetTarget(m_camera->GetTarget() + (seconds / (seconds + 0.18f)) * (PhysObjBarycenter - m_camera->GetTarget()));
397        vec3 CamPosCenter = m_camera->GetTarget() + vec3(.0f, 5.0f, .0f);
398        m_camera->SetPosition(CamPosCenter + normalize(m_camera->GetPosition() - CamPosCenter) * 20.0f);
399    }
400    else
401    {
402        PhysObjBarycenter = vec3(.0f);
403        for (int i = 0; i < m_physobj_list.Count(); i++)
404        {
405            PhysicsObject* PhysObj = m_physobj_list[i];
406            mat4 GroundMat = PhysObj->GetTransform();
407
408            PhysObjBarycenter += GroundMat.v3.xyz;
409            factor += 1.f;
410        }
411
412        PhysObjBarycenter /= factor;
413
414        m_camera->SetTarget(PhysObjBarycenter);
415        m_camera->SetPosition(GroundBarycenter + normalize(GroundBarycenter - PhysObjBarycenter) * 60.0f);
416    }
417
418}
419
420void BtPhysTest::TickDraw(float seconds)
421{
422    WorldEntity::TickDraw(seconds);
423
424    if (!m_ready)
425    {
426        /* FIXME: this object never cleans up */
427        m_ready = true;
428    }
429
430    //Video::SetClearColor(vec4(0.0f, 0.0f, 0.12f, 1.0f));
431
432}
433
434BtPhysTest::~BtPhysTest()
435{
436    Ticker::Unref(m_camera);
437    Ticker::Unref(m_light1);
438    Ticker::Unref(m_light2);
439
440    while (m_constraint_list.Count())
441    {
442        EasyConstraint* CurPop = m_constraint_list.Last();
443        m_constraint_list.Pop();
444        CurPop->RemoveFromSimulation(m_simulation);
445        delete CurPop;
446    }
447    while (m_ground_list.Count())
448    {
449        PhysicsObject* CurPop = m_ground_list.Last();
450        m_ground_list.Pop();
451        CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
452        Ticker::Unref(CurPop);
453    }
454    while (m_stairs_list.Count())
455    {
456        PhysicsObject* CurPop = m_stairs_list.Last();
457        m_stairs_list.Pop();
458        CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
459        Ticker::Unref(CurPop);
460    }
461    while (m_character_list.Count())
462    {
463        PhysicsObject* CurPop = m_character_list.Last();
464        m_character_list.Pop();
465        CurPop->GetCharacter()->RemoveFromSimulation(m_simulation);
466        Ticker::Unref(CurPop);
467    }
468    while (m_platform_list.Count())
469    {
470        PhysicsObject* CurPop = m_platform_list.Last();
471        m_platform_list.Pop();
472        CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
473        Ticker::Unref(CurPop);
474    }
475    while (m_physobj_list.Count())
476    {
477        PhysicsObject* CurPop = m_physobj_list.Last();
478        m_physobj_list.Pop();
479        CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
480        Ticker::Unref(CurPop);
481    }
482    Ticker::Unref(m_simulation);
483
484}
485
486int main(int argc, char **argv)
487{
488    System::Init(argc, argv);
489
490    Application app("BtPhysTest", ivec2(1280, 720), 60.0f);
491
492    new BtPhysTest(argc > 1);
493    app.ShowPointer(false);
494
495    app.Run();
496
497    return EXIT_SUCCESS;
498}
499
Note: See TracBrowser for help on using the repository browser.