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