1 #include "dxut\dxstdafx.h"
2 #include "resource.h"
3 #include "d3dapp.h"
4 #include "tokamaksampleApp.h"
5
6 const s32 WALL_NUMBER = 1;
7
8 #define XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE 7849
9 #define XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE 8689
10 #define XINPUT_GAMEPAD_TRIGGER_THRESHOLD 30
11
12 D3DXHANDLE g_hShaderTechTokamak;
13
14 D3DXVECTOR4 vLightWorld[NUM_LIGHT] = { D3DXVECTOR4(1.f,2.f,1.f,0.f),
15 D3DXVECTOR4(-1.f,1.f,1.f,0.f)};
16
17 D3DXVECTOR4 vLightColor[NUM_LIGHT] = { D3DXVECTOR4(0.7f,0.7f,0.7f,0.f),
18 D3DXVECTOR4(0.5f,0.5f,0.5f,0.f)};
19
20 const D3DXVECTOR3 g_MinBound( -4.0f, -GROUND_Y, -6.0f );
21 const D3DXVECTOR3 g_MaxBound( 4.0f, GROUND_Y, 6.0f );
22
23 struct DemoData
24 {
25 neV3 pos;
26 neV3 boxSize;
27 neV3 colour;
28 };
29
30 DemoData gFloor = { {0.0f,-11.0f,0.0f}, {200.0f,2.0f,200.0f}, {0.3f,0.3f,0.6f}};
31
32 #define N_BARRIERS 4
33
34 DemoData gBarriers[N_BARRIERS] = { {{0.0f,-11.0f,-100.0f}, {200.0f,5.0f,2.0f}, {0.3f,0.3f,0.6f}},
35 {{0.0f,-11.0f,100.0f}, {200.0f,5.0f,2.0f}, {0.3f,0.3f,0.6f}},
36 {{-100.0f,-11.0f,0.0f}, {2.0f,5.0f,200.0f}, {0.3f,0.3f,0.6f}},
37 {{100.0f,-11.0f,0.0f}, {2.0f,5.0f,200.0f}, {0.3f,0.3f,0.6f}}};
38
39 #define N_RAMPS 4
40
41 struct RampData
42 {
43 neV3 pos;
44 neV3 boxSize;
45 neV3 colour;
46 neV3 angle;
47 };
48
49 RampData gRamps[N_RAMPS] = {
50 {{-40.0f,-12.0f,-50.0f}, {30.0f,2.0f,30.0f}, {0.3f,0.3f,0.6f}, {0.0f,0.0f,NE_PI * 0.07f}},
51 {{50.0f,-12.0f,30.0f}, {30.0f,2.0f,30.0f}, {0.3f,0.3f,0.6f}, {-NE_PI * 0.07f,0.0f,0.0f}},
52 {{-30.0f,-12.0f,50.0f}, {30.0f,2.0f,30.0f}, {0.3f,0.3f,0.6f}, {0.0f,0.0f,-NE_PI * 0.07f}},
53 {{50.0f,-12.0f,-30.0f}, {30.0f,2.0f,30.0f}, {0.3f,0.3f,0.6f}, {-NE_PI * 0.07f,0.0f,0.0f}}
54 };
55
56 const s32 N_CARS = 10;
57 // TARGET_CAR = 0,
58 const s32 N_BODY_BOXES = 2;
59 const s32 N_PARTS = 3;
60 const s32 N_RENDER_PRIMITIVES = (N_BODY_BOXES + N_PARTS);
61 const s32 MAX_OVERLAPPED_PAIR = 1000;
62 const f32 WHEEL_DIAMETER = 0.9f;
63 const f32 WHEEL_WIDTH = 0.3f;
64 const f32 MAX_SPEED = 5.0f;
65 const f32 MAX_REVERSE_SPEED = -2.0f;
66 const f32 MAX_STEER = 0.7f;
67 const f32 MAX_SLIDE = 0.8f;
68
69 struct SensorData
70 {
71 neV3 pos;
72 };
73
74 SensorData sensorData[4] =
75 {
76 {2.0f, 0.0f, 1.5f},
77 {2.0f, 0.0f, -1.5f},
78 {-2.0f, 0.0f, 1.5f},
79 {-2.0f, 0.0f, -1.5f},
80 };
81
82 class CControllerCB: public neRigidBodyControllerCallback
83 {
84 public:
85
86 void RigidBodyControllerCallback(neRigidBodyController * controller, float timeStep);
87 };
88
89 CControllerCB cb;
90
91 class CSampleCar;
92
93 class CCar
94 {
95 public:
96 void MakeCar(neSimulator * sim, neV3 & pos);
97
98 void MakeParts(neSimulator * sim, neV3 & pos);
99
100 void CarController(neRigidBodyController * controller);
101
102 void Process(XINPUT_STATE &);
103
AddRenderPrimitive()104 CRenderPrimitive * AddRenderPrimitive()
105 {
106 return &carRenderPrimitives[nextRenderPrim++];
107 }
108
109 public:
CCar()110 CCar()
111 {
112 id = -1;
113
114 accel = 0.0f;
115
116 steer = 0.0f;
117
118 slide = 0.0f;
119
120 gameWorld = NULL;
121
122 nextRenderPrim = 0;
123 }
124
125 neRigidBody * carRigidBody;
126
127 neRigidBody * carParts[N_PARTS];
128
129 CRenderPrimitive carRenderPrimitives[N_RENDER_PRIMITIVES];
130
131 CRenderPrimitive wheelRenderPrimitive;
132
133 neV3 displayLines[4][2];
134
135 f32 suspensionLength[4];
136
137 CSampleCar * gameWorld;
138
139 s32 id;
140
141 f32 accel;
142
143 f32 steer;
144
145 f32 slide;
146
147 neV3 steerDir;
148
149 s32 nextRenderPrim;
150 };
151
152 class CSampleCar
153 {
154 public:
155 neSimulator * sim;
156 neAllocatorDefault allocator;
157 nePerformanceReport perfReport;
158
159 CRenderPrimitive groundRender;
160 neAnimatedBody * ground;
161
162 CRenderPrimitive barrierRenders[N_BARRIERS];
163 neAnimatedBody * barriers[N_BARRIERS];
164
165 CRenderPrimitive rampRenders[N_RAMPS];
166 neAnimatedBody * ramps[N_RAMPS];
167
168 CCar cars[N_CARS];
169
170 public:
CSampleCar()171 CSampleCar() : sim(NULL) {};
172
173 void CreateSimulator();
174
175 void CreateGround();
176
177 void Reset();
178
179 void Cleanup();
180 };
181
182 CSampleCar sample;
183
CreateSimulator()184 void CSampleCar::CreateSimulator()
185 {
186 if (sim)
187 {
188 neSimulator::DestroySimulator(sim);
189
190 sim = NULL;
191 }
192 // creat the physics simulation
193
194 neSimulatorSizeInfo sizeInfo;
195
196 sizeInfo.rigidBodiesCount = (N_PARTS + 1) * N_CARS;
197 sizeInfo.animatedBodiesCount = WALL_NUMBER + N_RAMPS + N_BARRIERS + 1;
198 sizeInfo.geometriesCount = (N_RENDER_PRIMITIVES + 1) * N_CARS + WALL_NUMBER;
199 sizeInfo.overlappedPairsCount = MAX_OVERLAPPED_PAIR;
200 { //dont need any of these
201 sizeInfo.rigidParticleCount = 0;
202 sizeInfo.terrainNodesStartCount = 200;
203 }
204 neV3 gravity; gravity.Set(0.0f, -8.0f, 0.0f);
205
206 sim = neSimulator::CreateSimulator(sizeInfo, &allocator, &gravity);
207 }
208
CreateGround()209 void CSampleCar::CreateGround()
210 {
211 ground = sim->CreateAnimatedBody();
212
213 neGeometry * geom = ground->AddGeometry();
214
215 geom->SetBoxSize(gFloor.boxSize);
216
217 ground->UpdateBoundingInfo();
218
219 ground->SetPos(gFloor.pos);
220
221 groundRender.SetGraphicBox(gFloor.boxSize[0], gFloor.boxSize[1], gFloor.boxSize[2]);
222
223 for (s32 i = 0; i < N_BARRIERS; i++)
224 {
225 barriers[i] = sim->CreateAnimatedBody();
226
227 geom = barriers[i]->AddGeometry();
228
229 geom->SetBoxSize(gBarriers[i].boxSize);
230
231 barriers[i]->UpdateBoundingInfo();
232
233 barriers[i]->SetPos(gBarriers[i].pos);
234
235 barrierRenders[i].SetGraphicBox(gBarriers[i].boxSize[0], gBarriers[i].boxSize[1], gBarriers[i].boxSize[2]);
236
237 barrierRenders[i].SetDiffuseColor(D3DXCOLOR(0.6f, 0.8f, 0.5f, 1));
238 }
239
240 for (s32 i = 0; i < N_RAMPS; i++)
241 {
242 ramps[i] = sim->CreateAnimatedBody();
243
244 geom = ramps[i]->AddGeometry();
245
246 geom->SetBoxSize(gRamps[i].boxSize);
247
248 ramps[i]->UpdateBoundingInfo();
249
250 ramps[i]->SetPos(gRamps[i].pos);
251
252 neM3 rot; rot.RotateXYZ(gRamps[i].angle);
253
254 ramps[i]->SetRotation(rot);
255
256 rampRenders[i].SetGraphicBox(gRamps[i].boxSize[0], gRamps[i].boxSize[1], gRamps[i].boxSize[2]);
257
258 rampRenders[i].SetDiffuseColor(D3DXCOLOR(0.6f, 0.2f, 0.8f, 1));
259 }
260 }
261
Reset()262 void CSampleCar::Reset()
263 {
264 Cleanup();
265
266 // reset the camera position
267 D3DXVECTOR3 vecEye (30.0f, 12.0f, 40.0f);//(0.0f, -GROUND_Y + 1.7f, 0.0f);
268 D3DXVECTOR3 vecAt (0.0f, 0.0f, 1.0f);//(0.0f, -GROUND_Y + 1.7f, 1.0f);
269 g_Camera.SetViewParams( &vecEye, &vecAt );
270
271 CreateSimulator();
272
273 CreateGround();
274
275 neV3 carPos;
276
277 carPos.Set(0.0f, -1.0f, 10.0f);
278
279 for (int i = 0; i < N_CARS; i++)
280 {
281 cars[i].id = i;
282
283 cars[i].MakeCar(sim, carPos);
284
285 carPos[0] -= 7;
286 }
287 }
288
Cleanup()289 void CSampleCar::Cleanup()
290 {
291 sample.groundRender.mMesh.Destroy();
292
293 for (s32 i = 0; i < N_BARRIERS; i++)
294 sample.barrierRenders[i].mMesh.Destroy();
295
296 for (s32 i = 0; i < N_RAMPS; i++)
297 sample.rampRenders[i].mMesh.Destroy();
298
299 for (s32 i = 0; i < N_CARS; i++)
300 {
301 sample.cars[i].wheelRenderPrimitive.mMesh.Destroy();
302
303 for (s32 j = 0; j < N_RENDER_PRIMITIVES; j++)
304 {
305 sample.cars[i].carRenderPrimitives[j].mMesh.Destroy();
306 }
307 }
308
309 neSimulator::DestroySimulator(sample.sim);
310
311 sim = NULL;
312 }
313
MakeCar(neSimulator * sim,neV3 & pos)314 void CCar::MakeCar(neSimulator * sim, neV3 & pos)
315 {
316 f32 mass = 1.0f;
317
318 neRigidBody * rigidBody = sim->CreateRigidBody();
319
320 // rigidBody->SetSleepingParameter(0.01f);
321
322 rigidBody->CollideConnected(true);
323
324 neGeometry * geom = rigidBody->AddGeometry();
325
326 neV3 boxSize;
327 {
328 // the car consist of two boxes
329
330 boxSize.Set(6.0f, 1.0f, 3.2f);
331
332 geom->SetBoxSize(boxSize);
333
334 neT3 t;
335
336 t.SetIdentity();
337
338 t.pos.Set(0.0f, 0.25f, 0.0f);
339
340 geom->SetTransform(t);
341
342 geom = rigidBody->AddGeometry();
343
344 boxSize.Set(2.5f, 1.0f, 2.8f);
345
346 geom->SetBoxSize(boxSize[0],boxSize[1],boxSize[2]);
347
348 t.pos.Set(-0.6f, 1.0f, 0.0f);
349
350 geom->SetTransform(t);
351 }
352 { // add 4 sensors to the rigid body
353 neSensor * sn;
354
355 for (s32 si = 0; si < 4; si++)
356 {
357 sn =rigidBody->AddSensor();
358
359 neV3 snPos, snDir;
360
361 snDir.Set(0.0f, -1.0f, 0.0f);
362
363 snPos.Set(sensorData[si].pos);
364
365 sn->SetLineSensor(snPos, snDir);
366 }
367
368 // add a controller to the rigid body
369
370 neRigidBodyController * controller;
371
372 controller = rigidBody->AddController(&cb, 0);
373 }
374
375 neV3 tensorSize;
376
377 tensorSize = boxSize;
378
379 rigidBody->UpdateBoundingInfo();
380
381 rigidBody->SetInertiaTensor(neBoxInertiaTensor(tensorSize, mass));
382
383 rigidBody->SetMass(mass);
384
385 rigidBody->SetUserData((u32)this);
386
387 carRigidBody = rigidBody;
388
389 { // setup the display boxes for the car
390
391 s32 i = 0;
392
393 rigidBody->BeginIterateGeometry();
394
395 while (geom = rigidBody->GetNextGeometry())
396 {
397 //neSimpleToken * token = gw.MakeToken(geom);
398
399 //token->SetDiffuseColour(neV4(0.2f, 0.2f, 0.8f, 1.0f));
400
401 //token->SetAmbientColour(neV4(0.0f, 0.2f, 0.3f, 1.0f));
402
403 neV3 boxSize;
404
405 geom->GetBoxSize(boxSize);
406
407 CRenderPrimitive * renderPrim = AddRenderPrimitive();
408
409 renderPrim->SetGraphicBox(boxSize[0], boxSize[1], boxSize[2]);
410
411 geom->SetUserData((u32)renderPrim);
412
413 renderPrim->SetDiffuseColor(D3DXCOLOR(0.2f, 0.2f, 0.8f, 1));
414 }
415 }
416
417 wheelRenderPrimitive.SetGraphicCylinder(WHEEL_DIAMETER * 0.5f, WHEEL_WIDTH);
418
419 // set the car position
420
421 carRigidBody->SetPos(pos);
422
423 // add bonnet to the car
424
425 MakeParts(sim, pos);
426 }
427
428 struct PartData
429 {
430 neV3 boxSize;
431 neV3 position;
432 neV3 jointPos;
433 neV3 jointRot;
434 f32 lowerLimit;
435 f32 upperLimit;
436 };
437
438 PartData parts[] =
439 {
440 { // Bonet
441 {2.0f, 0.1f, 3.0f},
442 {1.65f, 0.8f, 0.0f},
443 {0.65f, 0.8f, 0.0f},
444 {NE_PI * 0.5f, 0.0f, 0.0f},
445 0.0f,
446 NE_PI * 0.4f,
447 },
448 { //Left Door
449 {2.0f, 0.8f, 0.1f},
450 {-0.2f, 0.25f, 1.6f},
451 {0.65f, 0.25f, 1.6f},
452 {0.0f, 0.0f, 0.0f},
453 0.0f,
454 NE_PI * 0.4f,
455 },
456 { //Right Door
457 {2.0f, 0.8f, 0.1f},
458 {-0.2f, 0.25f, -1.6f},
459 {0.65f, 0.25f, -1.6f},
460 {0.0f, 0.0f, 0.0f},
461 -NE_PI * 0.4f,
462 0.0f,
463 },
464 };
465
MakeParts(neSimulator * sim,neV3 & pos)466 void CCar::MakeParts(neSimulator * sim, neV3 & pos)
467 {
468 s32 i;
469
470 for (i = 0; i < N_PARTS; i++)
471 {
472 neRigidBody * rb = sim->CreateRigidBody();
473
474 if (id == 0 ) //make it harder to sleep
475 rb->SetSleepingParameter(0.1f);
476
477 rb->SetPos(parts[i].position + pos);
478
479 neGeometry * geom = rb->AddGeometry();
480
481 geom->SetBoxSize(parts[i].boxSize);
482
483 rb->SetMass(0.01f);
484
485 rb->UpdateBoundingInfo();
486
487 rb->SetInertiaTensor(neBoxInertiaTensor(parts[i].boxSize, 0.01f));
488
489 neJoint * joint = sim->CreateJoint(rb, carRigidBody);
490
491 neT3 trans;
492
493 trans.pos = parts[i].jointPos + pos;
494
495 trans.rot.RotateXYZ(parts[i].jointRot);
496
497 joint->SetJointFrameWorld(trans);
498
499 joint->SetType(neJoint::NE_JOINT_HINGE);
500
501 joint->SetLowerLimit(parts[i].lowerLimit);
502
503 joint->SetUpperLimit(parts[i].upperLimit);
504
505 joint->SetEpsilon(0.0f);
506
507 joint->SetIteration(4);
508
509 joint->EnableLimit(true);
510
511 joint->Enable(true);
512
513 carParts[i] = rb;
514
515 CRenderPrimitive * renderPrim = AddRenderPrimitive();
516
517 renderPrim->SetGraphicBox(parts[i].boxSize[0], parts[i].boxSize[1], parts[i].boxSize[2]);
518
519 geom->SetUserData((u32)renderPrim);
520 }
521 }
522
MyAppInit()523 void MyAppInit()
524 {
525 // TODO: Perform any application-level initialization here
526 // Setup the camera
527 D3DXVECTOR3 MinBound( g_MinBound.x + CAMERA_SIZE, g_MinBound.y + CAMERA_SIZE, g_MinBound.z + CAMERA_SIZE );
528 D3DXVECTOR3 MaxBound( g_MaxBound.x - CAMERA_SIZE, g_MaxBound.y - CAMERA_SIZE, g_MaxBound.z - CAMERA_SIZE );
529
530 g_Camera.SetEnableYAxisMovement( true );
531 g_Camera.SetRotateButtons( false, false, true );
532 g_Camera.SetScalers( 0.01f, 50.0f );
533 D3DXVECTOR3 vecEye (0.0f, 0.0f, -10.0f);//(0.0f, -GROUND_Y + 1.7f, 0.0f);
534 D3DXVECTOR3 vecAt (0.0f, 0.0f, 1.0f);//(0.0f, -GROUND_Y + 1.7f, 1.0f);
535 g_Camera.SetViewParams( &vecEye, &vecAt );
536
537 for (s32 i = 0; i < NUM_LIGHT; i++)
538 D3DXVec4Normalize(&vLightWorld[i], &vLightWorld[i]);
539
540 // OnMyAppDestroyDevice(g_pD3dDevice);
541
542 sample.Reset();
543 };
544
OnMyAppFrameMove(IDirect3DDevice9 * pd3dDevice,double fTime,float fElapsedTime,void * pUserContext)545 void CALLBACK OnMyAppFrameMove( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
546 {
547 f32 t = 1.0f / 30.0f;//(f32)delta / 1000.0f;
548
549 //sim->Advance(TIME_STEP, 1, &g_PerfReport);
550 sample.sim->Advance(t, 1.0f / 30.0f, 1.0f/ 30.0f, NULL);
551
552 D3DXVECTOR3 vecEye (30.0f, 12.0f, 40.0f);
553
554 neV3 v = sample.cars[0].carRigidBody->GetPos();
555 D3DXVECTOR3 vecAt(v[0], v[1], v[2]);
556
557 D3DXVECTOR3 offset(0.0f, 0.0f, 80.0f);
558
559 vecEye = vecAt + offset;
560
561 vecEye[1] = 40.0f;
562
563 g_Camera.SetViewParams( &vecEye, &vecAt );
564
565 DWORD dwResult;
566
567 XINPUT_STATE state;
568
569 ZeroMemory( &state, sizeof(XINPUT_STATE) );
570
571 // Simply get the state of the controller from XInput.
572 dwResult = XInputGetState( 0, &state );
573
574 //if( dwResult == ERROR_SUCCESS )
575 {
576 // Controller is connected
577 sample.cars[0].Process(state);
578 }
579 }
580
OnMyAppFrameRender(IDirect3DDevice9 * pd3dDevice,double fTime,float fElapsedTime,void * pUserContext)581 void CALLBACK OnMyAppFrameRender( IDirect3DDevice9* pd3dDevice, double fTime, float fElapsedTime, void* pUserContext )
582 {
583 neT3 t;
584
585 t = sample.ground->GetTransform();
586
587 t.MakeD3DCompatibleMatrix();
588
589 sample.groundRender.Render(pd3dDevice, &t);
590
591 for (s32 i = 0; i < N_BARRIERS; i++)
592 {
593 t = sample.barriers[i]->GetTransform();
594
595 t.MakeD3DCompatibleMatrix();
596
597 sample.barrierRenders[i].Render(pd3dDevice, &t);
598 }
599
600 for (s32 i = 0; i < N_RAMPS; i++)
601 {
602 t = sample.ramps[i]->GetTransform();
603
604 t.MakeD3DCompatibleMatrix();
605
606 sample.rampRenders[i].Render(pd3dDevice, &t);
607 }
608
609 for (s32 i = 0; i < N_CARS; i++)
610 {
611 CCar * car = &sample.cars[i];
612
613 t = car->carRigidBody->GetTransform();
614
615 car->carRigidBody->BeginIterateGeometry();
616
617 while (neGeometry * geom = car->carRigidBody->GetNextGeometry())
618 {
619 neT3 t2 = geom->GetTransform();
620
621 neT3 t3 = t * t2;
622
623 t3.MakeD3DCompatibleMatrix();
624
625 CRenderPrimitive * rp = (CRenderPrimitive *)geom->GetUserData();
626
627 rp->Render(pd3dDevice, &t3);
628 }
629
630 for (s32 j = 0; j < N_PARTS; j++)
631 {
632 t = car->carParts[j]->GetTransform();
633
634 t.MakeD3DCompatibleMatrix();
635
636 car->carParts[j]->BeginIterateGeometry();
637
638 neGeometry * geom = car->carParts[j]->GetNextGeometry();
639
640 CRenderPrimitive * rp = (CRenderPrimitive *)geom->GetUserData();
641
642 rp->Render(pd3dDevice, &t);
643 }
644
645 for (s32 j = 0; j < 4; j++)
646 {
647 //GETDISPLAY->DrawLine(2, colour, &displayLines[i][0]);
648
649 neT3 wheel2World, suspension2Body, tire2Suspension, cylinder2Tire;
650
651 suspension2Body.SetIdentity();
652
653 suspension2Body.pos.Set(0.0f, -car->suspensionLength[j] + WHEEL_DIAMETER / 2.0f, 0.0f);
654
655 suspension2Body.pos += sensorData[j].pos;
656
657 cylinder2Tire.SetIdentity();
658
659 neV3 rot; rot.Set(NE_PI * 0.5f, 0.0f, 0.0f);
660
661 cylinder2Tire.rot.RotateXYZ(rot);
662
663 tire2Suspension.SetIdentity();
664
665 if (j == 0 || j == 1)
666 {
667 rot.Set(0.0f, car->steer, 0.0f);
668
669 tire2Suspension.rot.RotateXYZ(rot);
670 }
671
672 wheel2World = car->carRigidBody->GetTransform() * suspension2Body * tire2Suspension * cylinder2Tire;
673
674 if (j == 0 || j == 1)
675 {
676 car->steerDir = wheel2World.rot[0];
677 }
678 wheel2World.MakeD3DCompatibleMatrix();
679
680 car->wheelRenderPrimitive.Render(pd3dDevice, &wheel2World);
681 }
682 }
683
684 WCHAR * str[2];
685
686 str[0] = L"Tokamak Car Sample";
687 str[1] = L"";
688
689 MyRenderText(str, 2);
690 }
691
MyAppMsgProc(HWND hWnd,UINT uMsg,WPARAM wParam,LPARAM lParam,bool * pbNoFurtherProcessing,void * pUserContext)692 LRESULT CALLBACK MyAppMsgProc( HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam,
693 bool* pbNoFurtherProcessing, void* pUserContext )
694 {
695 return 0;
696 }
697
OnMyAppDestroyDevice(void * pUserContext)698 void CALLBACK OnMyAppDestroyDevice( void* pUserContext )
699 {
700 SAFE_RELEASE( g_pEffect );
701
702 sample.Cleanup();
703 }
704
MyAppKeyboardProc(UINT nChar,bool bKeyDown,bool bAltDown,void * pUserContext)705 void CALLBACK MyAppKeyboardProc( UINT nChar, bool bKeyDown, bool bAltDown, void* pUserContext )
706 {
707 if( bKeyDown )
708 {
709 switch( nChar )
710 {
711 case 'R':
712 {
713 //OnMyAppDestroyDevice(g_pD3dDevice);
714
715 sample.Reset();
716 }
717 break;
718
719 default:
720 break;
721 }
722 }
723 }
724
RigidBodyControllerCallback(neRigidBodyController * controller,float timeStep)725 void CControllerCB::RigidBodyControllerCallback(neRigidBodyController * controller, float timeStep)
726 {
727 neRigidBody * rb = controller->GetRigidBody();
728
729 CCar * car = (CCar *)(rb->GetUserData());
730
731 car->CarController(controller);
732 }
733
CarController(neRigidBodyController * controller)734 void CCar::CarController(neRigidBodyController * controller)
735 {
736 neT3 body2World = carRigidBody->GetTransform();
737
738 carRigidBody->BeginIterateSensor();
739
740 neSensor * sn;
741
742 neV3 force, torque;
743
744 force.SetZero();
745
746 torque.SetZero();
747
748 s32 i = 0;
749
750 while (sn = carRigidBody->GetNextSensor())
751 {
752 f32 k = 15.0f; //spring constant
753
754 f32 u = 3.f; //damping constant
755
756 if (i == 2 || i == 3)
757 {
758 k = 10.0f;
759 }
760
761 // add spring force
762
763 f32 depth = sn->GetDetectDepth();
764
765 //gw.car.suspensionLength[i] = 1.0f - depth;
766 suspensionLength[i] = 1.0f - depth;
767
768 if (depth == 0.0f)
769 {
770 i++;
771 continue;
772 }
773 //if (depth > 0.7f)
774 // depth = 0.7f;
775
776 neV3 groundNormal = sn->GetDetectNormal();
777
778 neV3 lineNormal = body2World.rot * sn->GetLineUnitVector();
779
780 neV3 linePos = body2World * sn->GetLinePos();
781
782 f32 dot = lineNormal.Dot(groundNormal) * -1.0f;
783
784 //if (dot <= 0.7f)
785 // continue;
786
787 neV3 f = depth * lineNormal * -k;// * dot;
788
789 force += f;
790
791 neV3 r = linePos - carRigidBody->GetPos();
792
793 torque += r.Cross(f);
794
795 // add damping force
796
797 f32 speed = carRigidBody->GetVelocityAtPoint(r).Dot(lineNormal);
798
799 f = -speed * lineNormal * u;
800
801 force += f;
802
803 torque += r.Cross(f);
804
805 // add friction force
806
807 neV3 vel = carRigidBody->GetVelocityAtPoint(sn->GetDetectContactPoint() - carRigidBody->GetPos());
808
809 vel.RemoveComponent(groundNormal);
810
811 if (i == 0 || i == 1)
812 {
813 //steering
814
815 vel.RemoveComponent(steerDir);
816 }
817 else
818 {
819 vel.RemoveComponent(body2World.rot[0]); //rear wheel always parallel to car body
820 }
821
822
823 f = vel;
824
825 f.Normalize();
826
827 f *= -7.0f;
828
829 if (i == 2 || i ==3)
830 {
831 //f *= (1.0f - slide);
832 }
833 f[1] = 0.0f;
834
835 force += f;
836
837 r = sn->GetDetectContactPoint() - carRigidBody->GetPos();
838
839 torque += r.Cross(f);
840
841 // driving force
842
843 if (i == 2 || i == 3) // rear wheel
844 {
845 f = body2World.rot[0];
846
847 f *= accel;
848
849 force += f;
850
851 torque += r.Cross(f);
852 }
853 /*
854 gw.car.displayLines[i][0] = linePos;
855
856 gw.car.displayLines[i][1] = sn->GetDetectContactPoint();
857 */
858 i++;
859 }
860
861 // drag
862 f32 dragConstant = 0.3f;
863
864 neV3 vel = carRigidBody->GetVelocity();
865
866 f32 dot = vel.Dot(body2World.rot[0]);
867
868 neV3 drag = dot * body2World.rot[0] * -dragConstant;
869
870 force += drag;
871
872 controller->SetControllerForce(force);
873
874 controller->SetControllerTorque(torque);
875 }
876
Process(XINPUT_STATE & InputState)877 void CCar::Process(XINPUT_STATE & InputState)
878 {
879 // Zero value if thumbsticks are within the dead zone
880 if( (InputState.Gamepad.sThumbLX < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
881 InputState.Gamepad.sThumbLX > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) &&
882 (InputState.Gamepad.sThumbLY < XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE &&
883 InputState.Gamepad.sThumbLY > -XINPUT_GAMEPAD_LEFT_THUMB_DEADZONE) )
884 {
885 InputState.Gamepad.sThumbLX = 0;
886 InputState.Gamepad.sThumbLY = 0;
887 }
888
889 if( (InputState.Gamepad.sThumbRX < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
890 InputState.Gamepad.sThumbRX > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) &&
891 (InputState.Gamepad.sThumbRY < XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE &&
892 InputState.Gamepad.sThumbRY > -XINPUT_GAMEPAD_RIGHT_THUMB_DEADZONE) )
893 {
894 InputState.Gamepad.sThumbRX = 0;
895 InputState.Gamepad.sThumbRY = 0;
896 }
897
898 neV3 vel;
899
900 if (GetAsyncKeyState('S'))
901 {
902 accel += 0.1f;
903
904 if (accel > MAX_SPEED)
905 accel = MAX_SPEED;
906 }
907 else if (GetAsyncKeyState('X'))
908 {
909 accel -= 0.1f;
910
911 if (accel < MAX_REVERSE_SPEED)
912 accel = MAX_REVERSE_SPEED;
913 }
914 else if (InputState.Gamepad.bRightTrigger > 0)
915 {
916 accel = (float)InputState.Gamepad.bRightTrigger / 255.0f * MAX_SPEED;
917 }
918 else if (InputState.Gamepad.bLeftTrigger > 0)
919 {
920 accel = (float)InputState.Gamepad.bLeftTrigger / 255.0f * MAX_REVERSE_SPEED;
921 }
922 else
923 {
924 //accel *= 0.99f;
925 }
926
927 if (GetAsyncKeyState('L'))
928 {
929 steer += 0.02f;
930 steer = MAX_STEER;
931 if (steer > MAX_STEER)
932 {
933 steer = MAX_STEER;
934
935 slide += 0.05f;
936 }
937 }
938 else if (GetAsyncKeyState('K'))
939 {
940 steer -= 0.02f;
941 steer = -MAX_STEER;
942 if (steer < -MAX_STEER)
943 {
944 steer = -MAX_STEER;
945
946 slide += 0.05f;
947 }
948 }
949 else if (InputState.Gamepad.sThumbLX != 0)
950 {
951 steer = (float)InputState.Gamepad.sThumbLX / 32767.0f * MAX_STEER;
952
953 if (abs(steer) > (0.9 * MAX_STEER))
954 {
955 slide += 0.02f;
956 }
957 }
958 else
959 {
960 steer *= 0.9f;
961
962 slide *= 0.85f;
963 }
964 if (slide > MAX_SLIDE)
965 {
966 slide = MAX_SLIDE;
967 }
968 }
969
970
971