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

游戏引擎

开发平台:

Visual C++

  1. /* Collide
  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 "engine.h"
  20. #include "object.h"
  21. #include "objectmesh.h"
  22. #include "objectskinnedmesh.h"
  23. #include "mesh.h"
  24. #include "skinnedmesh.h"
  25. #include "rigidbody.h"
  26. #include "collide.h"
  27. int Collide::counter;
  28. Position Collide::position;
  29. int Collide::num_surfaces;
  30. Collide::Surface *Collide::surfaces;
  31. /*
  32.  */
  33. Collide::Collide() : num_contacts(0), num_objects(0) {
  34. contacts = new Contact[NUM_CONTACTS];
  35. objects = new Object*[NUM_OBJECTS];
  36. if(counter++ == 0) {
  37. surfaces = new Surface[NUM_SURFACES];
  38. for(int i = 0; i < NUM_SURFACES; i++) {
  39. surfaces[i].triangles = new Triangle[NUM_TRIANGLES];
  40. }
  41. }
  42. }
  43. Collide::~Collide() {
  44. delete contacts;
  45. delete objects;
  46. if(--counter == 0) {
  47. for(int i = 0; i < NUM_SURFACES; i++) {
  48. delete surfaces[i].triangles;
  49. }
  50. delete surfaces;
  51. }
  52. }
  53. /*****************************************************************************/
  54. /*                                                                           */
  55. /* add contact                                                               */
  56. /*                                                                           */
  57. /*****************************************************************************/
  58. int Collide::addContact(Object *object,Material *material,const vec3 &point,const vec3 &normal,float depth,int min_depth) {
  59. Contact *c = &contacts[num_contacts++];
  60. if(min_depth) {
  61. vec3 p = object->is_identity ? point : object->transform * point;
  62. for(int i = 0; i < num_contacts; i++) {
  63. if(contacts[i].point == p) {
  64. num_contacts--;
  65. if(contacts[i].depth < depth) return 1;
  66. c = &contacts[i];
  67. break;
  68. }
  69. }
  70. }
  71. if(num_contacts == NUM_CONTACTS) {
  72. num_contacts--;
  73. return 0;
  74. }
  75. if(num_objects == 0) {
  76. objects[num_objects++] = object;
  77. } else {
  78. for(int i = 0; i < num_objects; i++) {
  79. if(objects[i] == object) break;
  80. else if(i == num_objects - 1) objects[num_objects++] = object;
  81. }
  82. }
  83. c->object = object;
  84. c->material = material;
  85. c->point = object->is_identity ? point : object->transform * point;
  86. c->normal = object->is_identity ? normal : object->transform.rotation() * normal;
  87. c->depth = depth;
  88. /*glDepthFunc(GL_ALWAYS);
  89. glPointSize(5.0);
  90. glColor3f(0,1,0);
  91. glBegin(GL_POINTS);
  92. glVertex3fv(c->point);
  93. glEnd();
  94. glColor3f(0,0,1);
  95. glBegin(GL_LINES);
  96. glVertex3fv(c->point);
  97. glVertex3fv(c->point + c->normal * c->depth * 20);
  98. glEnd();*/
  99. return 1;
  100. }
  101. /*****************************************************************************/
  102. /*                                                                           */
  103. /* collide with sphere                                                       */
  104. /*                                                                           */
  105. /*****************************************************************************/
  106. int Collide::collide(Object *object,const vec3 &pos,float radius) {
  107. position = pos;
  108. return collide(object,position,radius);
  109. }
  110. int Collide::collide(Object *object,const Position &pos,float radius) {
  111. num_contacts = 0;
  112. num_objects = 0;
  113. if(Bsp::num_sectors == 0) return 0;
  114. if(pos.sector == -1) return 0;
  115. for(int i = 0; i < pos.num_sectors; i++) {
  116. Sector *s = &Bsp::sectors[pos.sectors[i]];
  117. for(int j = 0; j < s->num_node_objects; j++) { // static objects
  118. Object *o = s->node_objects[j];
  119. if((o->getCenter() - pos).length() >= o->getRadius() + radius) continue;
  120. collideObjectSphere(o,pos,radius);
  121. }
  122. for(int j = 0; j < s->num_objects; j++) { // dynamic objects
  123. Object *o = s->objects[j];
  124. if(object == o) continue;
  125. vec3 p = o->is_identity ? pos : o->itransform * pos;
  126. if((o->getCenter() - p).length() >= o->getRadius() + radius) continue;
  127. if(object && object->rigidbody && object->rigidbody->num_joints > 0 && o->rigidbody) {
  128. RigidBody *rb = object->rigidbody;
  129. int k;
  130. for(k = 0; k < rb->num_joints; k++) {
  131. if(rb->joined_rigidbodies[k] == o->rigidbody) break;
  132. }
  133. if(k == rb->num_joints) collideObjectSphere(o,p,radius);
  134. } else {
  135. collideObjectSphere(o,p,radius);
  136. }
  137. }
  138. }
  139. return num_contacts;
  140. }
  141. /*
  142.  */
  143. void Collide::collideObjectSphere(Object *object,const vec3 &pos,float radius) {
  144. static int next[3] = { 1, 2, 0 };
  145. // collide sphere-Mesh
  146. if(object->type == Object::OBJECT_MESH) {
  147. // collide sphere-sphere
  148. if(object->rigidbody && object->rigidbody->collide_type == RigidBody::BODY_SPHERE) {
  149. float r = object->getRadius();
  150. if(pos.length() < radius + r) {
  151. vec3 normal = pos;
  152. normal.normalize();
  153. if(!addContact(object,NULL,normal * radius,normal,radius + r - pos.length())) return;
  154. }
  155. return;
  156. }
  157. // collide sphere-Mesh
  158. Mesh *mesh = reinterpret_cast<ObjectMesh*>(object)->mesh;
  159. for(int i = 0; i < mesh->getNumSurfaces(); i++) {
  160. if((mesh->getCenter(i) - pos).length() > mesh->getRadius(i) + radius) continue;
  161. Mesh::Triangle *triangles = mesh->getTriangles(i);
  162. int num_triangles = mesh->getNumTriangles(i);
  163. for(int j = 0; j < num_triangles; j++) {
  164. Mesh::Triangle *t = &triangles[j];
  165. // distance from the center of sphere to the plane of triangle
  166. float dist = vec4(pos,1) * t->plane;
  167. if(dist >= radius || dist < 0) continue;
  168. vec3 normal = t->plane;
  169. vec3 point = pos - normal * radius;
  170. float depth = radius - dist;
  171. int k; // point in traingle
  172. for(k = 0; k < 3; k++) if(vec4(point,1) * t->c[k] < 0.0) break;
  173. // collide sphere with edges
  174. if(k != 3) {
  175. point = pos - normal * dist; // point on triangle plane
  176. for(k = 0; k < 3; k++) {
  177. vec3 edge = t->v[next[k]] - t->v[k];
  178. vec3 dir = cross(edge,normal);
  179. dir.normalize();
  180. float d = (point - t->v[k]) * dir;
  181. if(d >= radius || d <= 0) continue;
  182. vec3 p = point - dir * d; // point on edge
  183. float dot = p * edge; // clamp point
  184. if(dot > t->v[next[k]] * edge) p = t->v[next[k]];
  185. else if(dot < t->v[k] * edge) p = t->v[k];
  186. d = (point - p).length();
  187. if(d > radius) continue;
  188. depth = sqrt(radius * radius - d * d) - dist;
  189. if(depth <= 0.0) continue;
  190. point = p - normal * depth;
  191. break; // ok
  192. }
  193. if(k == 3) continue; // next triangle
  194. }
  195. // add new contact
  196. if(!addContact(object,object->materials[i],point,t->plane,depth)) return;
  197. }
  198. }
  199. return;
  200. }
  201. // collide sphere-SkinnedMesh
  202. /*if(object->type == Object::OBJECT_SKINNEDMESH) {
  203. ObjectSkinnedMesh *objectskinnedmesh = reinterpret_cast<ObjectSkinnedMesh*>(object);
  204. if(objectskinnedmesh->ragdoll) return;
  205. SkinnedMesh *skinnedmesh = objectskinnedmesh->skinnedmesh;
  206. for(int i = 0; i < skinnedmesh->getNumSurfaces(); i++) {
  207. if((skinnedmesh->getCenter(i) - pos).length() > skinnedmesh->getRadius(i) + radius) continue;
  208. SkinnedMesh::Vertex *vertex = skinnedmesh->getVertex(i);
  209. SkinnedMesh::Triangle *triangles = skinnedmesh->getTriangles(i);
  210. int num_triangles = skinnedmesh->getNumTriangles(i);
  211. for(int j = 0; j < num_triangles; j++) {
  212. SkinnedMesh::Triangle *t = &triangles[j];
  213. // distance from the center of sphere to the plane of triangle
  214. float dist = vec4(pos,1) * t->plane;
  215. if(dist >= radius || dist < 0) continue;
  216. vec3 normal = vec3(t->plane);
  217. vec3 point = pos - normal * radius;
  218. float depth = radius - dist;
  219. int k; // point in traingle
  220. for(k = 0; k < 3; k++) if(vec4(point,1) * t->c[k] < 0.0) break;
  221. // collide sphere with edges
  222. if(k != 3) {
  223. point = pos - normal * dist; // point on triangle plane
  224. for(k = 0; k < 3; k++) {
  225. float d = (point - vertex[t->v[k]].xyz) * t->c[k];
  226. if(d >= radius || d <= 0) continue;
  227. vec3 edge = vertex[t->v[k]].xyz - vertex[t->v[next[k]]].xyz;
  228. vec3 p = point - t->c[k] * d; // point on edge
  229. float dot = p * edge; // clamp point
  230. if(dot > vertex[t->v[next[k]]].xyz * edge) p = vertex[t->v[next[k]]].xyz;
  231. else if(dot < vertex[t->v[k]].xyz * edge) p = vertex[t->v[k]].xyz;
  232. d = (point - p).length();
  233. if(d > radius) continue;
  234. depth = sqrt(radius * radius - d * d) - dist;
  235. if(depth <= 0.0) continue;
  236. point = p - normal * depth;
  237. break; // ok
  238. }
  239. if(k == 3) continue; // next triangle
  240. }
  241. // add new contact
  242. if(!addContact(object,object->materials[i],point,normal,depth)) return;
  243. }
  244. }
  245. return;
  246. }*/
  247. }
  248. /*****************************************************************************/
  249. /*                                                                           */
  250. /* collide with mesh                                                         */
  251. /*                                                                           */
  252. /*****************************************************************************/
  253. int Collide::collide(Object *object) {
  254. num_contacts = 0;
  255. num_objects = 0;
  256. if(Bsp::num_sectors == 0) return 0;
  257. if(object->pos.sector == -1) return 0;
  258. num_surfaces = 0;
  259. // transform and copy triangles from the mesh in to collide surface
  260. if(object->type == Object::OBJECT_MESH) {
  261. Mesh *mesh = reinterpret_cast<ObjectMesh*>(object)->mesh;
  262. for(int i = 0; i < mesh->getNumSurfaces(); i++) {
  263. surfaces[num_surfaces].num_triangles = mesh->getNumTriangles(i);
  264. if(surfaces[num_surfaces].num_triangles > NUM_TRIANGLES) {
  265. fprintf(stderr,"Collide::collide(): many vertex %dn",surfaces[num_surfaces].num_triangles);
  266. continue;
  267. }
  268. Mesh::Triangle *t = mesh->getTriangles(i);
  269. Triangle *ct = surfaces[num_surfaces].triangles;
  270. vec3 min = vec3(1000000,1000000,1000000); // calculate bound box
  271. vec3 max = vec3(-1000000,-1000000,-1000000);
  272. for(int j = 0; j < surfaces[num_surfaces].num_triangles; j++) {
  273. ct[j].v[0] = object->transform * t[j].v[0];
  274. ct[j].v[1] = object->transform * t[j].v[1];
  275. ct[j].v[2] = object->transform * t[j].v[2];
  276. mat4 rotate = object->transform.rotation();
  277. vec3 normal = rotate * vec3(t[j].plane);
  278. ct[j].plane = vec4(normal,-ct[j].v[0] * normal);
  279. normal = rotate * vec4(t[j].c[0]);
  280. ct[j].c[0] = vec4(normal,-ct[j].v[0] * normal);
  281. normal = rotate * vec4(t[j].c[1]);
  282. ct[j].c[1] = vec4(normal,-ct[j].v[1] * normal);
  283. normal = rotate * vec4(t[j].c[2]);
  284. ct[j].c[2] = vec4(normal,-ct[j].v[2] * normal);
  285. for(int k = 0; k < 3; k++) {
  286. if(min.x > ct[j].v[k].x) min.x = ct[j].v[k].x;
  287. else if(max.x < ct[j].v[k].x) max.x = ct[j].v[k].x;
  288. if(min.y > ct[j].v[k].y) min.y = ct[j].v[k].y;
  289. else if(max.y < ct[j].v[k].y) max.y = ct[j].v[k].y;
  290. if(min.z > ct[j].v[k].z) min.z = ct[j].v[k].z;
  291. else if(max.z < ct[j].v[k].z) max.z = ct[j].v[k].z;
  292. }
  293. }
  294. // bound sphere
  295. surfaces[num_surfaces].center = (max + min) / 2.0f;
  296. surfaces[num_surfaces].radius = (max - min).length() / 2.0f;
  297. // bound box
  298. surfaces[num_surfaces].min = min;
  299. surfaces[num_surfaces].max = max;
  300. // new surface
  301. num_surfaces++;
  302. if(num_surfaces == NUM_SURFACES) {
  303. fprintf(stderr,"Collide::collide(): many surfaces %dn",NUM_SURFACES);
  304. break;
  305. }
  306. }
  307. } else {
  308. fprintf(stderr,"Collide::collide(): %d format isn`t supportedn",object->type);
  309. }
  310. if(!num_surfaces) return 0;
  311. // static objects
  312. for(int i = 0; i < object->pos.num_sectors; i++) {
  313. Sector *s = &Bsp::sectors[object->pos.sectors[i]];
  314. for(int j = 0; j < s->num_node_objects; j++) {
  315. Object *o = s->node_objects[j];
  316. if((o->getCenter() - object->pos - object->getCenter()).length() >= o->getRadius() + object->getRadius()) continue;
  317. collideObjectMesh(o);
  318. }
  319. }
  320. // dynamic objects
  321. for(int i = 0; i < object->pos.num_sectors; i++) {
  322. Sector *s = &Bsp::sectors[object->pos.sectors[i]];
  323. for(int j = 0; j < s->num_objects; j++) {
  324. Object *o = s->objects[j];
  325. if(object == o) continue;
  326. if((o->pos + o->getCenter() - object->pos - object->getCenter()).length() >= o->getRadius() + object->getRadius()) continue;
  327. mat4 transform = o->itransform * object->transform;
  328. if(object->rigidbody && object->rigidbody->num_joints > 0 && o->rigidbody) {
  329. RigidBody *rb = object->rigidbody;
  330. int k;
  331. for(k = 0; k < rb->num_joints; k++) {
  332. if(rb->joined_rigidbodies[k] == o->rigidbody) break;
  333. }
  334. if(k != rb->num_joints) continue;
  335. }
  336. // object bound box
  337. vec3 object_min = vec3(1000000,1000000,1000000);
  338. vec3 object_max = vec3(-1000000,-1000000,-1000000);
  339. // transform vertex and calcualte bound box
  340. num_surfaces = 0;
  341. if(object->type == Object::OBJECT_MESH) {
  342. Mesh *mesh = reinterpret_cast<ObjectMesh*>(object)->mesh;
  343. for(int k = 0; k < mesh->getNumSurfaces(); k++) {
  344. surfaces[num_surfaces].num_triangles = mesh->getNumTriangles(k);
  345. if(surfaces[num_surfaces].num_triangles > NUM_TRIANGLES) continue;
  346. Mesh::Triangle *t = mesh->getTriangles(k);
  347. Triangle *ct = surfaces[num_surfaces].triangles;
  348. vec3 min = vec3(1000000,1000000,1000000); // calculate bound box
  349. vec3 max = vec3(-1000000,-1000000,-1000000);
  350. for(int l = 0; l < surfaces[num_surfaces].num_triangles; l++) {
  351. ct[l].v[0] = transform * t[l].v[0];
  352. ct[l].v[1] = transform * t[l].v[1];
  353. ct[l].v[2] = transform * t[l].v[2];
  354. for(int m = 0; m < 3; m++) {
  355. if(min.x > ct[l].v[m].x) min.x = ct[l].v[m].x;
  356. else if(max.x < ct[l].v[m].x) max.x = ct[l].v[m].x;
  357. if(min.y > ct[l].v[m].y) min.y = ct[l].v[m].y;
  358. else if(max.y < ct[l].v[m].y) max.y = ct[l].v[m].y;
  359. if(min.z > ct[l].v[m].z) min.z = ct[l].v[m].z;
  360. else if(max.z < ct[l].v[m].z) max.z = ct[l].v[m].z;
  361. }
  362. }
  363. // bound sphere
  364. surfaces[num_surfaces].center = (max + min) / 2.0f;
  365. surfaces[num_surfaces].radius = (max - min).length() / 2.0f;
  366. // bound box
  367. surfaces[num_surfaces].min = min;
  368. surfaces[num_surfaces].max = max;
  369. // object bound box
  370. if(object_min.x > min.x) object_min.x = min.x;
  371. if(object_max.x < max.x) object_max.x = max.x;
  372. if(object_min.y > min.y) object_min.y = min.y;
  373. if(object_max.y < max.y) object_max.y = max.y;
  374. if(object_min.z > min.z) object_min.z = min.z;
  375. if(object_max.z < max.z) object_max.z = max.z;
  376. num_surfaces++;
  377. if(num_surfaces == NUM_SURFACES) break;
  378. }
  379. }
  380. if(num_surfaces == 0) continue;
  381. // bound box test
  382. const vec3 &min = o->getMin();
  383. const vec3 &max = o->getMax();
  384. if(min.x >= object_max.x) continue;
  385. if(max.x <= object_min.x) continue;
  386. if(min.y >= object_max.y) continue;
  387. if(max.y <= object_min.y) continue;
  388. if(min.z >= object_max.z) continue;
  389. if(max.z <= object_min.z) continue;
  390. // recalculate normals and fast point and triangle
  391. num_surfaces = 0;
  392. if(object->type == Object::OBJECT_MESH) {
  393. Mesh *mesh = reinterpret_cast<ObjectMesh*>(object)->mesh;
  394. for(int k = 0; k < mesh->getNumSurfaces(); k++) {
  395. surfaces[num_surfaces].num_triangles = mesh->getNumTriangles(k);
  396. if(surfaces[num_surfaces].num_triangles > NUM_TRIANGLES) continue;
  397. Mesh::Triangle *t = mesh->getTriangles(k);
  398. Triangle *ct = surfaces[num_surfaces].triangles;
  399. for(int l = 0; l < surfaces[num_surfaces].num_triangles; l++) {
  400. mat4 rotate = transform.rotation();
  401. vec3 normal = rotate * vec3(t[l].plane);
  402. ct[l].plane = vec4(normal,-ct[l].v[0] * normal);
  403. normal = rotate * vec4(t[l].c[0]);
  404. ct[l].c[0] = vec4(normal,-ct[l].v[0] * normal);
  405. normal = rotate * vec4(t[l].c[1]);
  406. ct[l].c[1] = vec4(normal,-ct[l].v[1] * normal);
  407. normal = rotate * vec4(t[l].c[2]);
  408. ct[l].c[2] = vec4(normal,-ct[l].v[2] * normal);
  409. }
  410. num_surfaces++;
  411. if(num_surfaces == NUM_SURFACES) break;
  412. }
  413. }
  414. if(num_surfaces == 0) continue;
  415. // collide it
  416. collideObjectMesh(o);
  417. }
  418. }
  419. return num_contacts;
  420. }
  421. /*
  422.  */
  423. void Collide::collideObjectMesh(Object *object) {
  424. static int next[3] = { 1, 2, 0 };
  425. // collide Mesh-Mesh
  426. if(object->type == Object::OBJECT_MESH) {
  427. Mesh *mesh = reinterpret_cast<ObjectMesh*>(object)->mesh;
  428. for(int i = 0; i < mesh->getNumSurfaces(); i++) {
  429. for(int j = 0; j < num_surfaces; j++) {
  430. if((mesh->getCenter(i) - surfaces[j].center).length() >= mesh->getRadius(i) + surfaces[j].radius) continue;
  431. const vec3 &min = mesh->getMin(i);
  432. const vec3 &max = mesh->getMax(i);
  433. if(min.x >= surfaces[j].max.x) continue;
  434. if(max.x <= surfaces[j].min.x) continue;
  435. if(min.y >= surfaces[j].max.y) continue;
  436. if(max.y <= surfaces[j].min.y) continue;
  437. if(min.z >= surfaces[j].max.z) continue;
  438. if(max.z <= surfaces[j].min.z) continue;
  439. Mesh::Triangle *triangles = mesh->getTriangles(i);
  440. Surface *s = &surfaces[j];
  441. int num_triangles = mesh->getNumTriangles(i);
  442. for(int k = 0; k < num_triangles; k++) {
  443. Mesh::Triangle *t = &triangles[k];
  444. for(int l = 0; l < s->num_triangles; l++) {
  445. Triangle *ct = &s->triangles[l];
  446. // fast triangle-triangle intersection test
  447. float dist0[3];
  448. int collide0 = 0;
  449. for(int m = 0; m < 3; m++) {
  450. dist0[m] = ct->v[m] * t->plane;
  451. if(fabs(dist0[m]) > s->radius * 2) {
  452. collide0 = 3;
  453. break;
  454. }
  455. if(dist0[m] > 0.0) collide0++;
  456. else if(dist0[m] < 0.0) collide0--;
  457. }
  458. if(collide0 == 3 || collide0 == -3) continue;
  459. for(int m = 0; m < 3; m++) {
  460. if(!((dist0[m] <= 0.0) ^ (dist0[next[m]] <= 0.0))) continue;
  461. vec3 &v0 = ct->v[m];
  462. vec3 &v1 = ct->v[next[m]];
  463. vec3 edge = v1 - v0;
  464. vec3 p = v0 - edge * dist0[m] / (dist0[next[m]] - dist0[m]); // intersect ct edge with t plane
  465. int p_inside = p * t->c[0] > 0.0 && p * t->c[1] > 0.0 && p * t->c[2] > 0.0;
  466. if(!p_inside) continue;
  467. int v0_inside = v0 * t->c[0] > 0.0 && v0 * t->c[1] > 0.0 && v0 * t->c[2] > 0.0;
  468. int v1_inside = v1 * t->c[0] > 0.0 && v1 * t->c[1] > 0.0 && v1 * t->c[2] > 0.0;
  469. if(v0_inside && v1_inside) {
  470. float length = edge.length() / 2.0f;
  471. if(dist0[m] < 0.0 && dist0[m] > -length) {
  472. if(!addContact(object,object->materials[i],v0,t->plane,-dist0[m],true)) return;
  473. } else if(dist0[next[m]] < 0.0 && dist0[next[m]] > -length) {
  474. if(!addContact(object,object->materials[i],v1,t->plane,-dist0[next[m]],true)) return;
  475. }
  476. }
  477. if(v0_inside != v1_inside) {
  478. float dist = 1000000;
  479. for(int n = 0; n < 3; n++) {
  480. //float d = t->v[n] * t->c[n];
  481. float d = p * t->c[n];
  482. if(dist > d) dist = d;
  483. }
  484. if(dist0[m] < 0.0) {
  485. float d = (v0 - p).length();
  486. if(dist > d) dist = 0;
  487. else dist = -dist0[m] * dist / d;
  488. } else {
  489. float d = (v1 - p).length();
  490. if(dist > d) dist = 0;
  491. else dist = -dist0[next[m]] * dist / d;
  492. }
  493. if(!addContact(object,object->materials[i],p,-ct->plane,dist)) return;
  494. }
  495. }
  496. // collide with scene
  497. if(!object->rigidbody) {
  498. float dist1[3];
  499. int collide1 = 0;
  500. for(int m = 0; m < 3; m++) {
  501. dist1[m] = t->v[m] * ct->plane;
  502. if(dist1[m] > 0.0) collide1++;
  503. else if(dist1[m] < 0.0) collide1--;
  504. }
  505. if(collide1 == 3 || collide1 == -3) continue;
  506. for(int m = 0; m < 3; m++) {
  507. if(dist1[m] >= 0) continue;
  508. if(dist1[next[m]] <= 0) continue;
  509. vec3 &v0 = t->v[m];
  510. vec3 &v1 = t->v[next[m]];
  511. vec3 edge = v1 - v0;
  512. vec3 p = v0 - edge * dist1[m] / (dist1[next[m]] - dist1[m]); // intersect ct edge with t plane
  513. int p_inside = p * ct->c[0] > 0.0 && p * ct->c[1] > 0.0 && p * ct->c[2] > 0.0;
  514. if(!p_inside) continue;
  515. int v0_inside = v0 * ct->c[0] > 0.0 && v0 * ct->c[1] > 0.0 && v0 * ct->c[2] > 0.0;
  516. int v1_inside = v1 * ct->c[0] > 0.0 && v1 * ct->c[1] > 0.0 && v1 * ct->c[2] > 0.0;
  517. if(v0_inside != v1_inside) {
  518. float dist = 1000000;
  519. for(int n = 0; n < 3; n++) {
  520. float d = p * ct->c[n];
  521. if(dist > d) dist = d;
  522. }
  523. float d = (v0 - p).length();
  524. if(dist > d) dist = 0;
  525. else dist = -dist1[m] * dist / d;
  526. if(!addContact(object,object->materials[i],p,t->plane,dist)) return;
  527. }
  528. }
  529. }
  530. }
  531. }
  532. }
  533. }
  534. return;
  535. }
  536. }
  537. /*****************************************************************************/
  538. /*                                                                           */
  539. /* sorting contacts                                                          */
  540. /*                                                                           */
  541. /*****************************************************************************/
  542. static int contact_cmp(const void *a,const void *b) {
  543. Collide::Contact *c0 = (Collide::Contact*)a;
  544. Collide::Contact *c1 = (Collide::Contact*)b;
  545. if(c0->object->pos.z > c1->object->pos.z) return 1;
  546. if(c0->object->pos.z < c1->object->pos.z) return -1;
  547. if(c0->point.z > c1->point.z) return 1;
  548. if(c0->point.z < c1->point.z) return -1;
  549. return 0;
  550. }
  551. void Collide::sort() {
  552. qsort(contacts,num_contacts,sizeof(Contact),contact_cmp);
  553. }