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