00001 #include "PhysSystem.h"
00002
00003 PhysSystem::PhysSystem()
00004 {
00005 gravity.SetVector(glVector(0,-9.8,0));
00006 wind.SetVector(glVector(0,0,0));
00007 }
00008
00009 bool PhysSystem::AddObjects(vector<Object3d*> &new_obj_list)
00010 {
00011 Object3d *new_obj;
00012 for(int i = 0; i < new_obj_list.size(); i++)
00013 {
00014 new_obj = new_obj_list[i];
00015 obj_list.push_back(new_obj);
00016 obj_list.back().qrot_velocity = Quaternion(0, 0, 0);
00017 }
00018 }
00019
00020 void PhysSystem::UpdateAll()
00021 {
00022 physics_timer.GetElapsedSeconds();
00023 for(int a = 0; a < obj_list.size(); a++)
00024 {
00025 WorldEffect(obj_list[a]);
00026 for(int b = a+1; b < obj_list.size(); b++)
00027 {
00028 float center_distance = ((obj_list[a].bsphere_list[0].offset + *obj_list[a].center) -
00029 (obj_list[b].bsphere_list[0].offset + *obj_list[b].center)).length();
00030 float radius_total = obj_list[a].bsphere_list[0].radius + obj_list[b].bsphere_list[0].radius;
00031
00032 if(center_distance - radius_total < 0)
00033 CollideObjects(obj_list[a], obj_list[b]);
00034 }
00035 Update(obj_list[a]);
00036 }
00037 }
00038
00039 void PhysSystem::CollideObjects(PhysObject &Object1, PhysObject &Object2)
00040 {
00041 glVector p1_offset;
00042 glVector p2_offset;
00043
00044 for(int c = 1; c < Object1.bsphere_list.size(); c++)
00045 {
00046 for(int d = 1; d < Object2.bsphere_list.size(); d++)
00047 {
00048 Quaternion q1(Object1.center->rot);
00049 Quaternion q2(Object2.center->rot);
00050 p1_offset = q1.RotateV(Object1.bsphere_list[c].offset);
00051 p2_offset = q2.RotateV(Object2.bsphere_list[d].offset);
00052
00053 float center_distance = ((p1_offset + *Object1.center) - (p2_offset + *Object2.center)).length();
00054 float radius_total = Object1.bsphere_list[c].radius + Object2.bsphere_list[d].radius;
00055 if(center_distance - radius_total < 0)
00056 {
00057 float radius1 = p1_offset.length();
00058 float radius2 = p2_offset.length();
00059 glVector v1;
00060 glVector v2;
00061 glVector v1_lin;
00062 glVector v2_lin;
00063 glVector v1_ang;
00064 glVector v2_ang;
00065
00066 v1 = Object1.velocity;
00067 v2 = Object2.velocity;
00068
00069 Quaternion qin_1(Object1.qrot_velocity);
00070 Quaternion qin_2(Object2.qrot_velocity);
00071
00072 float angspeed_1 = qin_1.GetAngle();
00073 float angspeed_2 = qin_2.GetAngle();
00074
00075 glVector angvector_1 = !((q1 * qin_1 * ~q1).v % p1_offset);
00076 glVector angvector_2 = !((q2 * qin_2 * ~q2).v % p2_offset);
00077
00078 v1 += (angvector_1 * radius1 * angspeed_1);
00079 v2 += (angvector_2 * radius2 * angspeed_2);
00080
00081 float m1 = Object1.mass + Object1.inertial_moment;
00082 float m2 = Object2.mass + Object2.inertial_moment;
00083
00084 if(!CollidePoints(p1_offset + *Object1.center, v1, m1, Object1.elasticity,
00085 p2_offset + *Object2.center, v2, m2, Object2.elasticity))
00086 return;
00087
00088 if(radius1 != 0) v1_lin = v1.ProjectOnto(p1_offset);
00089 else v1_lin = v1;
00090 if(radius2 != 0) v2_lin = v2.ProjectOnto(p2_offset);
00091 else v2_lin = v2;
00092
00093 v1_ang = v1 - v1_lin;
00094 v2_ang = v2 - v2_lin;
00095
00096 if(radius1 != 0)
00097 {
00098 Quaternion qout_1(v1_ang.length() / radius1, !(p1_offset % v1_ang));
00099 Object1.qrot_velocity = Object1.qrot_velocity * (~q1 * qout_1 * q1);
00100 }
00101 if(radius2 != 0)
00102 {
00103 Quaternion qout_2(v2_ang.length() / radius2, !(p2_offset % v2_ang));
00104 Object2.qrot_velocity = Object2.qrot_velocity * (~q2 * qout_2 * q2);
00105 }
00106
00107 Object1.velocity += (v1_lin);
00108 Object2.velocity += (v2_lin);
00109 }
00110 }
00111 }
00112 }
00113
00114 bool PhysSystem::CollidePoints(glVector point1, glVector &momentum1, float m1, float cor1,
00115 glVector point2, glVector &momentum2, float m2, float cor2)
00116 {
00117 glVector col_vector = !(point2 - point1);
00118 glVector rel_momentum = momentum1 - momentum2;
00119 glVector proj_momentum = rel_momentum.ProjectOnto(col_vector);
00120
00121 if((proj_momentum * col_vector) > 0)
00122 {
00123 momentum1 = proj_momentum * -(m2/(m1+m2))*(1+cor1);
00124 momentum2 = proj_momentum * (m1/(m1+m2))*(1+cor2);
00125 return true;
00126 }
00127 return false;
00128 }
00129
00130 void PhysSystem::WorldEffect(PhysObject &cur_obj)
00131 {
00132 cur_obj.velocity = cur_obj.velocity + (!(glVector(*cur_obj.center) - glVector(*obj_list[0].center)) * -98.0/2.0 * cur_obj.gravity_effect) * physics_timer.difference_time;
00133
00134 }
00135
00136 void PhysSystem::Update(PhysObject &cur_obj)
00137 {
00138 cur_obj.center->Move(cur_obj.velocity * physics_timer.difference_time);
00139
00140 Quaternion rot_step(cur_obj.qrot_velocity.GetAngle() * physics_timer.difference_time, cur_obj.qrot_velocity.GetAxis());
00141 cur_obj.center->rot = cur_obj.center->rot * rot_step;
00142 }