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