source: trunk/test/BtPhysTest.cpp @ 2291

Last change on this file since 2291 was 2241, checked in by sam, 8 years ago

core: pass the project directory to the binary build and get rid of
that 2-year old "temporary Win32 hack".

File size: 15.3 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/Include/LolPhysics.h"
37#include "Physics/Include/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    float offset = 29.5f;
89    vec3 pos_offset = vec3(.0f, 30.f, .0f);
90    if (USE_STAIRS)
91    {
92        vec3 new_offset = vec3(1.0f, .125f, .0f);
93        quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
94        vec3 NewPosition = pos_offset + vec3(5.0f, -29.f, 15.0f);
95        {
96            NewRotation = quat::fromeuler_xyz(0.f, 0.f, 30.f);
97            NewPosition += vec3(4.0f, .0f, -4.0f);
98
99            PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3);
100            Ticker::Ref(NewPhyobj);
101            m_stairs_list << NewPhyobj;
102        }
103        {
104            NewRotation = quat::fromeuler_xyz(0.f, 0.f, 40.f);
105            NewPosition += vec3(4.0f, .0f, -4.0f);
106
107            PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3);
108            Ticker::Ref(NewPhyobj);
109            m_stairs_list << NewPhyobj;
110        }
111        NewPosition = pos_offset + vec3(5.0f, -29.5f, 15.0f);
112        NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
113        for (int i=0; i < 15; i++)
114        {
115            NewPosition += new_offset;
116
117            PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 3);
118            Ticker::Ref(NewPhyobj);
119            m_stairs_list << NewPhyobj;
120        }
121    }
122
123    if (USE_WALL)
124    {
125        for (int i=0; i < 6; i++)
126        {
127            vec3 NewPosition = vec3(.0f);
128            quat NewRotation = quat(1.f);
129
130            PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation);
131
132            int idx = i/2;
133            NewPosition = pos_offset;
134            NewPosition[idx] += offset;
135            offset *= -1.f;
136
137            if (idx != 1)
138            {
139                vec3 NewAxis = vec3(.0f);
140                NewAxis[2 - idx] = 1;
141                NewRotation = quat::rotate(90.f, NewAxis);
142            }
143
144            NewPhyobj->SetTransform(NewPosition, NewRotation);
145            Ticker::Ref(NewPhyobj);
146            m_ground_list << NewPhyobj;
147        }
148    }
149
150    PhysicsObject* BasePhyobj = NULL;
151    if (USE_PLATFORM)
152    {
153        quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
154        vec3 NewPosition = pos_offset + vec3(5.0f, -25.0f, -15.0f);
155
156        PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
157
158        m_platform_list << NewPhyobj;
159        Ticker::Ref(NewPhyobj);
160
161        NewPosition = pos_offset + vec3(-15.0f, -25.0f, 5.0f);
162
163        NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
164        BasePhyobj = NewPhyobj;
165
166        m_platform_list << NewPhyobj;
167        Ticker::Ref(NewPhyobj);
168
169        NewRotation = quat::fromeuler_xyz(0.f, 0.f, 90.f);
170        NewPosition = pos_offset + vec3(-20.0f, -25.0f, 5.0f);
171
172        NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
173
174        NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, true);
175        m_platform_list << NewPhyobj;
176        Ticker::Ref(NewPhyobj);
177
178        //NewPosition += vec3(-0.0f, .0f, .0f);
179        //NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
180
181        //NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), true, false);
182        //m_platform_list << NewPhyobj;
183        //Ticker::Ref(NewPhyobj);
184
185        //NewPosition += vec3(-2.0f, .0f, .0f);
186        //NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 1);
187
188        //NewPhyobj->GetPhysic()->AttachTo(BasePhyobj->GetPhysic(), false, false);
189        //m_platform_list << NewPhyobj;
190        //Ticker::Ref(NewPhyobj);
191    }
192
193    if (USE_CHARACTER)
194    {
195        quat NewRotation = quat::fromeuler_xyz(0.f, 0.f, 0.f);
196        vec3 NewPosition = pos_offset + vec3(-5.0f, -10.0f, 15.0f);
197
198        PhysicsObject* NewPhyobj = new PhysicsObject(m_simulation, NewPosition, NewRotation, 2);
199
200        m_character_list << NewPhyobj;
201        Ticker::Ref(NewPhyobj);
202
203
204        Input::LinkActionToKey(IPT_MOVE_FORWARD,        Key::Up);
205        Input::LinkActionToKey(IPT_MOVE_BACKWARD,        Key::Down);
206        Input::LinkActionToKey(IPT_MOVE_LEFT,            Key::Left);
207        Input::LinkActionToKey(IPT_MOVE_RIGHT,            Key::Right);
208        Input::LinkActionToKey(IPT_MOVE_JUMP,            Key::Space);
209        Input::LinkActionToKey(IPT_MOVE_UP,                Key::PageUp);
210        Input::LinkActionToKey(IPT_MOVE_DOWN,            Key::PageDown);
211
212        //NewPhyobj->GetCharacter()->AttachTo(BasePhyobj->GetPhysic(), true, true);
213    }
214
215    if (USE_BODIES)
216    {
217        for (int x=0; x < 6; x++)
218        {
219            for (int y=0; y < 6; y++)
220            {
221                for (int z=0; z < 5; z++)
222                {
223                    PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f,
224                        vec3(-20.f, 15.f, -20.f) +
225                        vec3(8.f * (float)x, 8.f * (float)y, 8.f * (float)z));
226                    m_physobj_list << new_physobj;
227                    Ticker::Ref(new_physobj);
228                }
229            }
230        }
231    }
232
233    if (USE_ROPE)
234    {
235        Array<PhysicsObject*> RopeElements;
236        for (int i = 0; i < 14; i++)
237        {
238            PhysicsObject* new_physobj = new PhysicsObject(m_simulation, 1000.f,
239                vec3(0.f, 15.f, -20.f) +
240                vec3(0.f, 0.f, 2.f * (float)i), 1);
241            RopeElements << new_physobj;
242            m_physobj_list << new_physobj;
243            Ticker::Ref(new_physobj);
244            if (RopeElements.Count() > 1)
245            {
246                EasyConstraint* new_constraint = new EasyConstraint();
247
248                vec3 A2B = .5f * (RopeElements[i]->GetPhysic()->GetTransform().v3.xyz -
249                            RopeElements[i - 1]->GetPhysic()->GetTransform().v3.xyz);
250                new_constraint->SetPhysObjA(RopeElements[i - 1]->GetPhysic(), lol::mat4::translate(A2B));
251                new_constraint->SetPhysObjB(RopeElements[i]->GetPhysic(), lol::mat4::translate(-A2B));
252                new_constraint->InitConstraintToPoint2Point();
253                new_constraint->DisableCollisionBetweenObjs(true);
254                new_constraint->AddToSimulation(m_simulation);
255                m_constraint_list << new_constraint;
256            }
257        }
258    }
259}
260
261void BtPhysTest::TickGame(float seconds)
262{
263    WorldEntity::TickGame(seconds);
264
265    if (Input::WasReleased(Key::Escape))
266        Ticker::Shutdown();
267
268    m_loop_value += seconds;
269    if (m_loop_value > M_PI * 2.0f)
270        m_loop_value -= M_PI * 2.0f;
271
272    vec3 GroundBarycenter = vec3(.0f);
273    vec3 PhysObjBarycenter = vec3(.0f);
274    float factor = .0f;
275
276    if (USE_WALL)
277    {
278        for (int i = 0; i < m_ground_list.Count(); i++)
279        {
280            PhysicsObject* PhysObj = m_ground_list[i];
281            mat4 GroundMat = PhysObj->GetTransform();
282
283            GroundBarycenter += GroundMat.v3.xyz;
284            factor += 1.f;
285        }
286
287        GroundBarycenter /= factor;
288
289        for (int i = 0; i < m_ground_list.Count(); i++)
290        {
291            PhysicsObject* PhysObj = m_ground_list[i];
292
293            mat4 GroundMat = PhysObj->GetTransform();
294            vec3 CenterToGround = GroundMat.v3.xyz - GroundBarycenter;
295            vec3 CenterToCam = m_camera->m_position - GroundBarycenter;
296
297            if (dot(normalize(CenterToCam - CenterToGround),
298                    normalize(CenterToGround)) > 0.f)
299                PhysObj->SetRender(false);
300            else
301                PhysObj->SetRender(true);
302        }
303    }
304
305    if (USE_ROTATION)
306    {
307        for (int i = 0; i < m_ground_list.Count(); i++)
308        {
309            PhysicsObject* PhysObj = m_ground_list[i];
310
311            mat4 GroundMat = PhysObj->GetTransform();
312            mat4 CenterMx = mat4::translate(GroundBarycenter);
313            GroundMat = inverse(CenterMx) * GroundMat;
314            GroundMat = CenterMx *
315                        mat4(quat::fromeuler_xyz(vec3(.0f, 20.f, 20.0f) * seconds))
316                        * GroundMat;
317            PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
318        }
319    }
320
321    if (USE_PLATFORM)
322    {
323        for (int i = 0; i < m_platform_list.Count(); i++)
324        {
325            PhysicsObject* PhysObj = m_platform_list[i];
326
327            mat4 GroundMat = PhysObj->GetTransform();
328            if (i == 0)
329            {
330                GroundMat = GroundMat * mat4(quat::fromeuler_xyz(vec3(20.f, .0f, .0f) * seconds));
331                PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
332            }
333            else if (i == 1)
334            {
335                GroundMat =
336                    mat4::translate(vec3(-15.0f, 5.0f, lol::cos(m_loop_value) * 8.f)) *
337                    mat4(quat::fromeuler_xyz(vec3(.0f, lol::cos(m_loop_value) * 20.f, .0f)));
338                PhysObj->SetTransform(GroundMat.v3.xyz, quat(GroundMat));
339            }
340        }
341    }
342
343    if (USE_CHARACTER)
344    {
345        for (int i = 0; i < m_character_list.Count(); i++)
346        {
347            PhysicsObject* PhysObj = m_character_list[i];
348            EasyCharacterController* Character = (EasyCharacterController*)PhysObj->GetCharacter();
349            mat4 CtlrMx = Character->GetTransform();
350
351            int HMovement = Input::GetStatus(IPT_MOVE_RIGHT) - Input::GetStatus(IPT_MOVE_LEFT);
352            int VMovement = Input::GetStatus(IPT_MOVE_FORWARD) - Input::GetStatus(IPT_MOVE_BACKWARD);
353            int RMovement = Input::GetStatus(IPT_MOVE_UP) - Input::GetStatus(IPT_MOVE_DOWN);
354            vec3 CharMove = vec3((float)VMovement * seconds * 4.f, (float)RMovement * seconds * 10.f, (float)HMovement * seconds * 4.f);
355
356            if (Input::WasReleased(IPT_MOVE_JUMP))
357                Character->Jump();
358            Character->SetMovementForFrame(CharMove);
359
360            RayCastResult HitResult;
361            if (m_simulation->RayHits(HitResult, ERT_Closest, Character->GetTransform().v3.xyz, (Character->GetTransform().v3.xyz + vec3(.0f, -1.f, .0f)), Character))
362                Character->AttachTo(HitResult.m_collider_list[0], true, true);
363            else
364                Character->AttachTo(NULL);
365        }
366    }
367
368    if (USE_CHARACTER)
369    {
370        PhysObjBarycenter = vec3(.0f);
371        factor = .0f;
372
373        for (int i = 0; i < m_character_list.Count(); i++)
374        {
375            PhysicsObject* PhysObj = m_character_list[i];
376            mat4 GroundMat = PhysObj->GetTransform();
377
378            PhysObjBarycenter += GroundMat.v3.xyz;
379            factor += 1.f;
380        }
381
382        PhysObjBarycenter /= factor;
383
384        m_camera->SetTarget(m_camera->GetTarget() + (seconds / (seconds + 0.18f)) * (PhysObjBarycenter - m_camera->GetTarget()));
385        vec3 CamPosCenter = m_camera->GetTarget() + vec3(.0f, 5.0f, .0f);
386        m_camera->SetPosition(CamPosCenter + normalize(m_camera->GetPosition() - CamPosCenter) * 20.0f);
387    }
388    else
389    {
390        PhysObjBarycenter = vec3(.0f);
391        for (int i = 0; i < m_physobj_list.Count(); i++)
392        {
393            PhysicsObject* PhysObj = m_physobj_list[i];
394            mat4 GroundMat = PhysObj->GetTransform();
395
396            PhysObjBarycenter += GroundMat.v3.xyz;
397            factor += 1.f;
398        }
399
400        PhysObjBarycenter /= factor;
401
402        m_camera->SetTarget(PhysObjBarycenter);
403        m_camera->SetPosition(GroundBarycenter + normalize(GroundBarycenter - PhysObjBarycenter) * 60.0f);
404    }
405
406}
407
408void BtPhysTest::TickDraw(float seconds)
409{
410    WorldEntity::TickDraw(seconds);
411
412    if (!m_ready)
413    {
414        /* FIXME: this object never cleans up */
415        m_ready = true;
416    }
417
418    //Video::SetClearColor(vec4(0.0f, 0.0f, 0.12f, 1.0f));
419
420}
421
422BtPhysTest::~BtPhysTest()
423{
424    Ticker::Unref(m_camera);
425
426    while (m_constraint_list.Count())
427    {
428        EasyConstraint* CurPop = m_constraint_list.Last();
429        m_constraint_list.Pop();
430        CurPop->RemoveFromSimulation(m_simulation);
431        delete CurPop;
432    }
433    while (m_ground_list.Count())
434    {
435        PhysicsObject* CurPop = m_ground_list.Last();
436        m_ground_list.Pop();
437        CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
438        Ticker::Unref(CurPop);
439    }
440    while (m_stairs_list.Count())
441    {
442        PhysicsObject* CurPop = m_stairs_list.Last();
443        m_stairs_list.Pop();
444        CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
445        Ticker::Unref(CurPop);
446    }
447    while (m_character_list.Count())
448    {
449        PhysicsObject* CurPop = m_character_list.Last();
450        m_character_list.Pop();
451        CurPop->GetCharacter()->RemoveFromSimulation(m_simulation);
452        Ticker::Unref(CurPop);
453    }
454    while (m_platform_list.Count())
455    {
456        PhysicsObject* CurPop = m_platform_list.Last();
457        m_platform_list.Pop();
458        CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
459        Ticker::Unref(CurPop);
460    }
461    while (m_physobj_list.Count())
462    {
463        PhysicsObject* CurPop = m_physobj_list.Last();
464        m_physobj_list.Pop();
465        CurPop->GetPhysic()->RemoveFromSimulation(m_simulation);
466        Ticker::Unref(CurPop);
467    }
468    Ticker::Unref(m_simulation);
469
470}
471
472int main(int argc, char **argv)
473{
474    System::Init(argc, argv);
475
476    Application app("BtPhysTest", ivec2(1280, 720), 60.0f);
477
478    new BtPhysTest(argc > 1);
479    app.ShowPointer(false);
480
481    app.Run();
482
483    return EXIT_SUCCESS;
484}
485
Note: See TracBrowser for help on using the repository browser.