joint.cpp
上传用户:qccn516
上传日期:2013-05-02
资源大小:3382k
文件大小:14k
源码类别:

游戏引擎

开发平台:

Visual C++

  1. /* Joints
  2.  *
  3.  * Copyright (C) 2003-2004, Alexander Zaprjagaev <frustum@frustum.org>
  4.  *
  5.  * This program is free software; you can redistribute it and/or modify
  6.  * it under the terms of the GNU General Public License as published by
  7.  * the Free Software Foundation; either version 2 of the License, or
  8.  * (at your option) any later version.
  9.  *
  10.  * This program is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13.  * GNU General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU General Public License
  16.  * along with this program; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  */
  19. #include <stdio.h>
  20. #include <string.h>
  21. #include "physic.h"
  22. #include "rigidbody.h"
  23. #include "joint.h"
  24. Joint::Joint(RigidBody *rigidbody_0,RigidBody *rigidbody_1) : rigidbody_0(rigidbody_0), rigidbody_1(rigidbody_1) {
  25. if(rigidbody_0->num_joints == RigidBody::NUM_JOINTS || rigidbody_1->num_joints == RigidBody::NUM_JOINTS) {
  26. rigidbody_0 = NULL;
  27. rigidbody_1 = NULL;
  28. fprintf(stderr,"Joint::Joint(): many joints in RigidBodyn");
  29. return;
  30. }
  31. rigidbody_0->joints[rigidbody_0->num_joints] = this;
  32. rigidbody_0->joined_rigidbodies[rigidbody_0->num_joints++] = rigidbody_1;
  33. rigidbody_1->joints[rigidbody_1->num_joints] = this;
  34. rigidbody_1->joined_rigidbodies[rigidbody_1->num_joints++] = rigidbody_0;
  35. Joint **j = new Joint*[++Physic::all_joints];
  36. memcpy(j,Physic::joints,sizeof(Joint*) * (Physic::all_joints - 1));
  37. if(Physic::joints) delete Physic::joints;
  38. Physic::joints = j;
  39. }
  40. Joint::~Joint() {
  41. if(!rigidbody_0 || !rigidbody_1) return;
  42. for(int i = 0, j = 0; i < rigidbody_0->num_joints; i++) {
  43. if(i != j) {
  44. rigidbody_0->joints[j] = rigidbody_0->joints[i];
  45. rigidbody_0->joined_rigidbodies[j] = rigidbody_0->joined_rigidbodies[i];
  46. }
  47. if(rigidbody_0->joints[i] != this) j++;
  48. }
  49. rigidbody_0->num_joints--;
  50. for(int i = 0, j = 0; i < rigidbody_1->num_joints; i++) {
  51. if(i != j) {
  52. rigidbody_1->joints[j] = rigidbody_1->joints[i];
  53. rigidbody_1->joined_rigidbodies[j] = rigidbody_1->joined_rigidbodies[i];
  54. }
  55. if(rigidbody_1->joints[i] != this) j++;
  56. }
  57. rigidbody_1->num_joints--;
  58. if(Physic::all_joints) Physic::all_joints--;
  59. else {
  60. delete Physic::joints;
  61. Physic::joints = NULL;
  62. }
  63. }
  64. /*
  65.  */
  66. int Joint::response(float) {
  67. fprintf(stderr,"Joint::response()n");
  68. return 1;
  69. }
  70. /*
  71.  */
  72. int Joint::restriction_response(float ifps,const vec3 &point_0,const vec3 &point_1,float min_dist) {
  73. if(min_dist == JOINT_DIST * 2.0f) return 1;
  74. vec3 p0 = rigidbody_0->transform * point_0;
  75. vec3 p1 = rigidbody_1->transform * point_1;
  76. vec3 r0 = p0 - rigidbody_0->pos;
  77. vec3 r1 = p1 - rigidbody_1->pos;
  78. vec3 vel0 = cross(rigidbody_0->angularVelocity,r0) + rigidbody_0->velocity;
  79. vec3 vel1 = cross(rigidbody_1->angularVelocity,r1) + rigidbody_1->velocity;
  80. vec3 normal = p0 - p1 + vel0 * ifps - vel1 * ifps;
  81. float dist = normal.length();
  82. if(dist >= min_dist) return 1;
  83. normal.normalize();
  84. vec3 vel = vel0 - vel1;
  85. float normal_vel = normal * vel;
  86. float impulse_numerator = -normal_vel + (min_dist - dist) * Physic::penetration_speed / ifps;
  87. float impulse_denominator = 1.0f / rigidbody_0->mass + 1.0f / rigidbody_1->mass
  88. + normal * cross(rigidbody_0->iWorldInertiaTensor * cross(r0,normal),r0)
  89. + normal * cross(rigidbody_1->iWorldInertiaTensor * cross(r1,normal),r1);
  90. if(rigidbody_0->immovable == 0) rigidbody_0->addImpulse(p0,normal * impulse_numerator / impulse_denominator);
  91. if(rigidbody_1->immovable == 0) rigidbody_1->addImpulse(p1,-normal * impulse_numerator / impulse_denominator);
  92. if(rigidbody_0->immovable && rigidbody_1->immovable == 0) rigidbody_1->addImpulse(p1,-normal * impulse_numerator / impulse_denominator);
  93. if(rigidbody_1->immovable && rigidbody_0->immovable == 0) rigidbody_0->addImpulse(p0,normal * impulse_numerator / impulse_denominator);
  94. return 0;
  95. }
  96. /*****************************************************************************/
  97. /*                                                                           */
  98. /* JointBall                                                                 */
  99. /*                                                                           */
  100. /*****************************************************************************/
  101. JointBall::JointBall(RigidBody *rigidbody_0,RigidBody *rigidbody_1,const vec3 &point,const vec3 &restriction_axis_0,const vec3 &restriction_axis_1,float restriction_angle) : Joint(rigidbody_0,rigidbody_1) {
  102. point_0 = rigidbody_0->itransform * point;
  103. point_1 = rigidbody_1->itransform * point;
  104. vec3 a;
  105. a = restriction_axis_0;
  106. a.normalize();
  107. restriction_point_0 = rigidbody_0->itransform * (point + a * JOINT_DIST);
  108. a = restriction_axis_1;
  109. a.normalize();
  110. restriction_point_1 = rigidbody_1->itransform * (point - a * JOINT_DIST);
  111. restriction_min_dist = sqrt(2.0f * JOINT_DIST * JOINT_DIST * (1.0f - cos(restriction_angle * DEG2RAD)));
  112. }
  113. JointBall::~JointBall() {
  114. }
  115. /*
  116.  */
  117. int JointBall::response(float ifps) {
  118. vec3 p0 = rigidbody_0->transform * point_0;
  119. vec3 p1 = rigidbody_1->transform * point_1;
  120. vec3 r0 = p0 - rigidbody_0->pos;
  121. vec3 r1 = p1 - rigidbody_1->pos;
  122. vec3 vel0 = cross(rigidbody_0->angularVelocity,r0) + rigidbody_0->velocity;
  123. vec3 vel1 = cross(rigidbody_1->angularVelocity,r1) + rigidbody_1->velocity;
  124. vec3 vel = (p0 - p1) * Physic::penetration_speed / ifps + vel0 - vel1;
  125. float normal_vel = vel.length();
  126. if(normal_vel < EPSILON) return 1;
  127. if(normal_vel > Physic::velocity_max) normal_vel = Physic::velocity_max;
  128. vec3 normal = vel;
  129. normal.normalize();
  130. float impulse_numerator = -normal_vel;
  131. float impulse_denominator = 1.0f / rigidbody_0->mass + 1.0f / rigidbody_1->mass
  132. + normal * cross(rigidbody_0->iWorldInertiaTensor * cross(r0,normal),r0)
  133. + normal * cross(rigidbody_1->iWorldInertiaTensor * cross(r1,normal),r1);
  134. if(rigidbody_0->immovable == 0) rigidbody_0->addImpulse(p0,normal * impulse_numerator / impulse_denominator);
  135. if(rigidbody_1->immovable == 0) rigidbody_1->addImpulse(p1,-normal * impulse_numerator / impulse_denominator);
  136. if(rigidbody_0->immovable && rigidbody_1->immovable == 0) rigidbody_1->addImpulse(p1,-normal * impulse_numerator / impulse_denominator);
  137. if(rigidbody_1->immovable && rigidbody_0->immovable == 0) rigidbody_0->addImpulse(p0,normal * impulse_numerator / impulse_denominator);
  138. // angle restriction
  139. restriction_response(ifps,restriction_point_0,restriction_point_1,restriction_min_dist);
  140. return 0;
  141. }
  142. /*****************************************************************************/
  143. /*                                                                           */
  144. /* JointHinge                                                                 */
  145. /*                                                                           */
  146. /*****************************************************************************/
  147. JointHinge::JointHinge(RigidBody *rigidbody_0,RigidBody *rigidbody_1,const vec3 &point,const vec3 &axis,const vec3 &restriction_axis_0,const vec3 &restriction_axis_1,float restriction_angle) : Joint(rigidbody_0,rigidbody_1) {
  148. itransform_0 = rigidbody_0->itransform;
  149. itransform_1 = rigidbody_1->itransform;
  150. this->point = point;
  151. point_00 = itransform_0 * (point);
  152. point_01 = itransform_1 * (point);
  153. setAxis0(axis);
  154. setAxis1(axis);
  155. vec3 a;
  156. a = restriction_axis_0;
  157. a.normalize();
  158. restriction_point_0 = rigidbody_0->itransform * (point + a * JOINT_DIST);
  159. a = restriction_axis_1;
  160. a.normalize();
  161. restriction_point_1 = rigidbody_1->itransform * (point - a * JOINT_DIST);
  162. restriction_min_dist = sqrt(2.0f * JOINT_DIST * JOINT_DIST * (1.0f - cos(restriction_angle * DEG2RAD)));
  163. }
  164. JointHinge::~JointHinge() {
  165. }
  166. /*
  167.  */
  168. void JointHinge::setAxis0(const vec3 &axis) {
  169. axis_0 = axis;
  170. axis_0.normalize();
  171. point_10 = itransform_0 * (point + axis_0 * JOINT_DIST);
  172. }
  173. /*
  174.  */
  175. void JointHinge::setAxis1(const vec3 &axis) {
  176. axis_1 = axis;
  177. axis_1.normalize();
  178. point_11 = itransform_1 * (point + axis_1 * JOINT_DIST);
  179. }
  180. /*
  181.  */
  182. void JointHinge::setAngularVelocity0(float velocity) {
  183. rigidbody_0->angularMomentum = rigidbody_0->orienation * (axis_0 * velocity);
  184. rigidbody_0->angularVelocity = rigidbody_0->iWorldInertiaTensor * rigidbody_0->angularMomentum;
  185. }
  186. /*
  187.  */
  188. void JointHinge::setAngularVelocity1(float velocity) {
  189. rigidbody_1->angularMomentum = rigidbody_1->orienation * (axis_1 * velocity);
  190. rigidbody_1->angularVelocity = rigidbody_1->iWorldInertiaTensor * rigidbody_1->angularMomentum;
  191. }
  192. /*
  193.  */
  194. int JointHinge::response(float ifps) {
  195. for(int i = 0; i < 2; i++) {
  196. vec3 p0,p1;
  197. if(i == 0) {
  198. p0 = rigidbody_0->transform * point_00;
  199. p1 = rigidbody_1->transform * point_01;
  200. } else {
  201. p0 = rigidbody_0->transform * point_10;
  202. p1 = rigidbody_1->transform * point_11;
  203. }
  204. vec3 r0 = p0 - rigidbody_0->pos;
  205. vec3 r1 = p1 - rigidbody_1->pos;
  206. vec3 vel0 = cross(rigidbody_0->angularVelocity,r0) + rigidbody_0->velocity;
  207. vec3 vel1 = cross(rigidbody_1->angularVelocity,r1) + rigidbody_1->velocity;
  208. vec3 vel = (p0 - p1) * Physic::penetration_speed / ifps + vel0 - vel1;
  209. float normal_vel = vel.length();
  210. if(normal_vel < EPSILON) continue;
  211. if(normal_vel > Physic::velocity_max) normal_vel = Physic::velocity_max;
  212. vec3 normal = vel;
  213. normal.normalize();
  214. float impulse_numerator = -normal_vel;
  215. float impulse_denominator = 1.0f / rigidbody_0->mass + 1.0f / rigidbody_1->mass
  216. + normal * cross(rigidbody_0->iWorldInertiaTensor * cross(r0,normal),r0)
  217. + normal * cross(rigidbody_1->iWorldInertiaTensor * cross(r1,normal),r1);
  218. if(rigidbody_0->immovable == 0) rigidbody_0->addImpulse(p0,normal * impulse_numerator / impulse_denominator);
  219. if(rigidbody_1->immovable == 0) rigidbody_1->addImpulse(p1,-normal * impulse_numerator / impulse_denominator);
  220. if(rigidbody_0->immovable && rigidbody_1->immovable == 0) rigidbody_1->addImpulse(p1,-normal * impulse_numerator / impulse_denominator);
  221. if(rigidbody_1->immovable && rigidbody_0->immovable == 0) rigidbody_0->addImpulse(p0,normal * impulse_numerator / impulse_denominator);
  222. }
  223. // angle restriction
  224. restriction_response(ifps,restriction_point_0,restriction_point_1,restriction_min_dist);
  225. return 0;
  226. }
  227. /*****************************************************************************/
  228. /*                                                                           */
  229. /* JointUniversal                                                            */
  230. /*                                                                           */
  231. /*****************************************************************************/
  232. JointUniversal::JointUniversal(RigidBody *rigidbody_0,RigidBody *rigidbody_1,const vec3 &point,const vec3 &axis_0,const vec3 &axis_1,const vec3 &restriction_axis_0,const vec3 &restriction_axis_1,float restriction_angle) : Joint(rigidbody_0,rigidbody_1) {
  233. this->point = point;
  234. this->axis_0 = axis_0;
  235. this->axis_0.normalize();
  236. this->axis_1 = axis_1;
  237. this->axis_1.normalize();
  238. point_00 = rigidbody_0->itransform * point;
  239. point_01 = rigidbody_1->itransform * point;
  240. point_10 = rigidbody_0->itransform * (point + this->axis_0 * JOINT_DIST);
  241. point_11 = rigidbody_1->itransform * (point + this->axis_0 * JOINT_DIST);
  242. this->axis_0 = rigidbody_0->itransform.rotation() * this->axis_0;
  243. this->axis_1 = rigidbody_1->itransform.rotation() * this->axis_1;
  244. vec3 a;
  245. a = restriction_axis_0;
  246. a.normalize();
  247. restriction_point_0 = rigidbody_0->itransform * (point + a * JOINT_DIST);
  248. a = restriction_axis_1;
  249. a.normalize();
  250. restriction_point_1 = rigidbody_1->itransform * (point - a * JOINT_DIST);
  251. restriction_min_dist = sqrt(2.0f * JOINT_DIST * JOINT_DIST * (1.0f - cos(restriction_angle * DEG2RAD)));
  252. }
  253. JointUniversal::~JointUniversal() {
  254. }
  255. /*
  256.  */
  257. int JointUniversal::response(float ifps) {
  258. for(int i = 0; i < 2; i++) {
  259. vec3 p0,p1;
  260. if(i == 0) {
  261. p0 = rigidbody_0->transform * point_00;
  262. p1 = rigidbody_1->transform * point_01;
  263. } else {
  264. p0 = rigidbody_0->transform * point_10;
  265. p1 = rigidbody_1->transform * point_11;
  266. }
  267. vec3 r0 = p0 - rigidbody_0->pos;
  268. vec3 r1 = p1 - rigidbody_1->pos;
  269. vec3 vel0 = cross(rigidbody_0->angularVelocity,r0) + rigidbody_0->velocity;
  270. vec3 vel1 = cross(rigidbody_1->angularVelocity,r1) + rigidbody_1->velocity;
  271. vec3 vel = (p0 - p1) * Physic::penetration_speed / ifps + vel0 - vel1;
  272. if(i == 1) {
  273. vec3 ax0 = rigidbody_0->transform.rotation() * axis_1;
  274. vec3 ax1 = rigidbody_1->transform.rotation() * axis_1;
  275. vec3 a = ax0 + ax1;
  276. a.normalize();
  277. vec3 d = a * ((p0 - p1) * a);
  278. vel = d * Physic::penetration_speed / ifps + a * ((vel0 - vel1) * a);
  279. }
  280. float normal_vel = vel.length();
  281. if(normal_vel < EPSILON) continue;
  282. if(normal_vel > Physic::velocity_max) normal_vel = Physic::velocity_max;
  283. vec3 normal = vel;
  284. normal.normalize();
  285. float impulse_numerator = -normal_vel;
  286. float impulse_denominator = 1.0f / rigidbody_0->mass + 1.0f / rigidbody_1->mass
  287. + normal * cross(rigidbody_0->iWorldInertiaTensor * cross(r0,normal),r0)
  288. + normal * cross(rigidbody_1->iWorldInertiaTensor * cross(r1,normal),r1);
  289. if(rigidbody_0->immovable == 0) rigidbody_0->addImpulse(p0,normal * impulse_numerator / impulse_denominator);
  290. if(rigidbody_1->immovable == 0) rigidbody_1->addImpulse(p1,-normal * impulse_numerator / impulse_denominator);
  291. if(rigidbody_0->immovable && rigidbody_1->immovable == 0) rigidbody_1->addImpulse(p1,-normal * impulse_numerator / impulse_denominator);
  292. if(rigidbody_1->immovable && rigidbody_0->immovable == 0) rigidbody_0->addImpulse(p0,normal * impulse_numerator / impulse_denominator);
  293. }
  294. // angle restriction
  295. restriction_response(ifps,restriction_point_0,restriction_point_1,restriction_min_dist);
  296. return 0;
  297. }