0001:
0002:
0003:
0004:
0005:
0006:
0007:
0008:
0009: #define STRICT
0010:
0011: #include <windows.h>
0012: #include "main.h"
0013: #include "draw.h"
0014: #include "rigidbody.h"
0015:
0016: CCar car;
0017:
0018:
0019:
0020: const float max_speed = 1.0f;
0021: const float handle_max = PI/4.0f;
0022:
0023:
0024:
0025:
0026: void CRigidBody::Init()
0027: {
0028: this->mass = 1.0f;
0029: D3DXMatrixIdentity(&this->IBody);
0030: D3DXMatrixIdentity(&this->IBodyinv);
0031: this->x = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
0032:
0033: this->R = D3DXQUATERNION (0.0f, 0.0f, 0.0f, 1.0f);
0034: this->p = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
0035: this->L = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
0036:
0037: this->Calc2ndValues();
0038: }
0039:
0040:
0041: void CRigidBody::Calc2ndValues()
0042: {
0043: D3DXVec4Scale(&this->v, &this->p, 1.0f/this->mass);
0044:
0045: D3DXMATRIX m, mt;
0046: D3DXMatrixRotationQuaternion(&m, &this->R);
0047: D3DXMatrixTranspose(&mt, &m);
0048: this->Iinv = m * this->IBodyinv * mt;
0049:
0050: D3DXVec3TransformNormal(&this->omega, &this->L, &this->Iinv);
0051: }
0052:
0053:
0054: void CRigidBody::Update(float dt)
0055: {
0056: this->ComputeForceAndTorque(dt);
0057: this->Calc2ndValues();
0058:
0059: this->x += dt * this->v;
0060: this->p += dt * this->force;
0061: this->L += dt * this->torque;
0062: D3DXQUATERNION dr;
0063: float arg = -dt*D3DXVec3Length(&this->omega);
0064: if(arg < -0.001f || 0.001f < arg){
0065: D3DXQuaternionRotationAxis( &dr, &this->omega, arg);
0066: D3DXQuaternionMultiply(&this->R, &this->R, &dr);
0067: }
0068: }
0069:
0070: D3DXMATRIX CRigidBody::GetRotation() const
0071: {
0072: D3DXMATRIX m;
0073:
0074: D3DXMatrixRotationQuaternion(&m, &this->R);
0075:
0076: return m;
0077: }
0078:
0079: D3DXVECTOR4 CRigidBody::GetTranslate() const
0080: {
0081: return this->x;
0082: }
0083:
0084: void CRigidBody::SetTranslate(const D3DXVECTOR4 tr)
0085: {
0086: this->x = tr;
0087: }
0088:
0089:
0090:
0091: CCar::CCar()
0092: {
0093: this->Init();
0094: }
0095:
0096: void CCar::Init()
0097: {
0098: CRigidBody::Init();
0099:
0100:
0101: float x = 15.0f;
0102: float y = 5.0f;
0103: float z = 25.0f;
0104: this->mass = 1.0f;
0105: this->IBody._11 = this->mass * (y*y+z*z) / 12.0f;
0106: this->IBody._22 = this->mass * (x*x+z*z) / 12.0f;
0107: this->IBody._33 = this->mass * (x*x+y*y) / 12.0f;
0108: this->IBodyinv._11 = 1.0f / this->IBody._11;
0109: this->IBodyinv._22 = 1.0f / this->IBody._22;
0110: this->IBodyinv._33 = 1.0f / this->IBody._33;
0111:
0112: this->dt = 0;
0113: this->time = timeGetTime();
0114: this->speed = 0.0f;
0115: this->handle = 0;
0116: }
0117:
0118: void CCar::Control()
0119: {
0120: this->dt = -this->time;
0121: this->time = timeGetTime();
0122: this->dt += this->time;
0123:
0124: if(0==this->dt) return;
0125:
0126:
0127: if(+max_speed < this->speed) this->speed = +max_speed;
0128: if(this->speed < -max_speed) this->speed = -max_speed;
0129:
0130:
0131: if(this->dt){
0132: if(+handle_max < this->handle*this->dt) this->handle = +handle_max/this->dt;
0133: if(this->handle*this->dt < -handle_max) this->handle = -handle_max/this->dt;
0134: }
0135:
0136: this->Update((float)this->dt);
0137:
0138: this->handle *= (float)exp(-(float)this->dt/1000.0f);
0139: }
0140:
0141: void CCar::AddSpeed(float acc)
0142: {
0143: this->speed += acc;
0144: }
0145:
0146: void CCar::AddHandle(float dh)
0147: {
0148: this->handle += dh;
0149: }
0150:
0151:
0152: static void AddForceAndTorque(D3DXVECTOR4 *force, D3DXVECTOR3 *torque, const D3DXVECTOR4 power, const D3DXVECTOR4 pos)
0153: {
0154: D3DXVECTOR4 p_pall = (D3DXVec4Dot(&pos, &power)/D3DXVec4Dot(&pos, &pos)) * pos;
0155: D3DXVECTOR4 p_vert = power - p_pall;
0156: D3DXVECTOR3 out;
0157:
0158: *force += p_pall;
0159:
0160: D3DXVec3Cross(&out,(D3DXVECTOR3*)&pos, (D3DXVECTOR3*)&p_vert);
0161: *torque += out / D3DXVec4Dot(&pos, &pos);
0162: }
0163:
0164: void CCar::ComputeForceAndTorque(float dt)
0165: {
0166: if(dt < 0.0000000000001f) return;
0167:
0168: int i;
0169:
0170: const float cy = 2.2f;
0171: D3DXVECTOR4 center = D3DXVECTOR4(0.0f, cy, 0.0f, 0.0f);
0172:
0173:
0174: D3DXVECTOR4 tire[4] = {
0175: D3DXVECTOR4( 4.4f, 0.0f, 6.8f, 0.0f),
0176: D3DXVECTOR4(-4.4f, 0.0f, 6.8f, 0.0f),
0177: D3DXVECTOR4( 4.4f, 0.0f,-6.8f, 0.0f),
0178: D3DXVECTOR4(-4.4f, 0.0f,-6.8f, 0.0f),
0179: };
0180: D3DXMATRIX mR;
0181: D3DXMatrixRotationQuaternion(&mR, &this->R);
0182:
0183: for(i = 0; i < 4; i++){
0184: tire[i] -= center;
0185: D3DXVec4Transform(&tire[i], &tire[i], &mR);
0186: tire[i] += center;
0187: }
0188:
0189:
0190: D3DXVECTOR4 dir = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 0.0f);
0191: D3DXVec4Transform(&dir, &dir, &mR);
0192:
0193:
0194: float spd = D3DXVec4Dot(&dir, &this->v);
0195: D3DXVECTOR4 v_pall = spd * dir;
0196: if(spd < 0.0f)spd = -spd;
0197:
0198:
0199: this->force = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
0200: this->torque = D3DXVECTOR3(0.0f, 0.0f, 0.0f);
0201:
0202:
0203: bool hit[4];
0204: float hit_cnt = 0.0f;
0205: for(i = 0; i < 4; i++){
0206: D3DXVECTOR4 p = tire[i] + this->x;
0207: if(-FLOOR_SIZE <= p.x && p.x <= +FLOOR_SIZE
0208: && -FLOOR_SIZE <= p.z && p.z <= +FLOOR_SIZE
0209: && p.y < 0.0f){
0210: hit_cnt += 1.0f;
0211: hit[i] = true;
0212: }else{
0213: hit[i] = false;
0214: }
0215: }
0216:
0217:
0218: for(i = 0; i < 2; i++){
0219: if(hit[i]){
0220: D3DXVECTOR4 power = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
0221: float dy = -(tire[i].y + this->x.y) / hit_cnt;
0222: power[1] += dy;
0223:
0224: D3DXVECTOR4 d_handle = D3DXVECTOR4(0.0f, 0.0f, 1.0f, 0.0f);
0225: D3DXMATRIX m;
0226: D3DXMatrixRotationY(&m, dt*this->handle);
0227: D3DXVec4Transform(&d_handle, &d_handle, &m);
0228: D3DXVec4Transform(&d_handle, &d_handle, &mR);
0229: D3DXVECTOR4 v_handle = D3DXVec4Dot(&d_handle, &this->v) * d_handle;
0230: v_handle = this->v - v_handle;
0231: power -= 0.5f*dt*v_handle;
0232:
0233: AddForceAndTorque(&this->force, &this->torque, power, center-tire[i]);
0234: }
0235: }
0236:
0237: for(i = 2; i < 4; i++){
0238: if(hit[i]){
0239: D3DXVECTOR4 power = D3DXVECTOR4(0.0f, 0.0f, 0.0f, 0.0f);
0240: float dy = -(tire[i].y + this->x.y) / hit_cnt;
0241: power[1] += dy;
0242: power[0] += 0.01f*(this->speed-spd)*dir[0];
0243: power[2] += 0.01f*(this->speed-spd)*dir[2];
0244:
0245: AddForceAndTorque(&this->force, &this->torque, power, center-tire[i]);
0246: }
0247: }
0248:
0249:
0250: force /= (dt*dt);
0251: torque /= (dt*dt);
0252:
0253:
0254: force[1] -= 0.00002f;
0255:
0256:
0257: force += -0.01f*this->v / dt;
0258:
0259: if(0.000001f*dt < this->p[1]) this->p[1] = 0.000001f*dt;
0260: }
0261:
0262:
0263:
0264: void MyMsgProc(UINT wParam)
0265: {
0266: switch(wParam){
0267: case VK_UP:
0268: car.AddSpeed(+0.01f);
0269: break;
0270: case VK_DOWN:
0271: car.AddSpeed(-0.01f);
0272: break;
0273: case VK_RIGHT:
0274: car.AddHandle(+PI/12.0f);
0275: break;
0276: case VK_LEFT:
0277: car.AddHandle(-PI/12.0f);
0278: break;
0279: case VK_RETURN:
0280: case VK_SPACE:
0281:
0282: car.Init();
0283: break;
0284: }
0285: }
0286: