Vegastrike 0.5.1 rc1  1.0
Original sources for Vegastrike Evolved
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
CSopcodecollider.cpp
Go to the documentation of this file.
1 /*
2  Copyright (C) 2000 by Jorrit Tyberghein
3 
4  This library is free software; you can redistribute it and/or
5  modify it under the terms of the GNU Library General Public
6  License as published by the Free Software Foundation; either
7  version 2 of the License, or (at your option) any later version.
8 
9  This library is distributed in the hope that it will be useful,
10  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  Library General Public License for more details.
13 
14  You should have received a copy of the GNU Library General Public
15  License along with this library; if not, write to the Free
16  Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
17 */
18 
19 /*
20 -------------------------------------------------------------------------
21 * OPCODE library was written by Pierre Terdiman
22 * ported to CS by Charles Quarra
23 * ported to VS from CS by Ed Sweetman
24 -------------------------------------------------------------------------
25 */
26 #include "CSopcodecollider.h"
27 #include "opcodeqsqrt.h"
28 #include "opcodeqint.h"
29 #include "opcodegarray.h"
30 #define _X 1000
31 
32 #undef _X
33 
34 using namespace Opcode;
35 
37 
38 csOPCODECollider::csOPCODECollider (const std::vector <mesh_polygon> &polygons)
39 {
40  m_pCollisionModel = 0;
41  vertholder = 0;
42  pairs.IncRef();
43  TreeCollider.SetFirstContact(true);
44  TreeCollider.SetFullBoxBoxTest(false);
45  TreeCollider.SetTemporalCoherence(false);
46  opcMeshInt.SetCallback (&MeshCallback, this);
47  GeometryInitialize (polygons);
48  CollisionFace collFace;
49  rCollider.SetFirstContact(true);
50 
51 }
52 
53 
54 inline float min3 (float a, float b, float c)
55 { return (a < b ? (a < c ? a : (c < b ? c : b)) : (b < c ? b : c)); }
56 inline float max3(float a, float b, float c)
57 { return (a > b ? (a > c ? a : (c > b ? c : b)) : (b > c ? b : c)); }
58 
59 void csOPCODECollider::GeometryInitialize (const std::vector <mesh_polygon> &polygons )
60 {
61  OPCODECREATE OPCC;
62  unsigned int tri_count = 0;
63  std::vector<Vector>::size_type vert_count = 0;
64  for(std::vector<mesh_polygon>::size_type i = 0; i <polygons.size();++i) {
65  vert_count += polygons[i].v.size();
66  }
67  tri_count = vert_count / 3;
68  if (tri_count) {
69  m_pCollisionModel = new Opcode::Model;
70  if (!m_pCollisionModel)
71  return;
72 
73  vertholder = new Point [vert_count];
74 
75  csBox3 tmp;
76  tmp.StartBoundingBox ();
77  unsigned int last = 0;
78 
79  /* Copies the Vector's in mesh_polygon to Point's in vertholder.
80  * This sucks but i dont see anyway around it */
81  for (std::vector<mesh_polygon>::size_type i = 0; i < polygons.size(); ++i) {
82  const mesh_polygon *p = (&polygons[i]);
83  for(std::vector<Vector>::size_type j = 0; j < p->v.size();++j) {
84  vertholder[last++].Set (p->v[j].i , p->v[j].j , p->v[j].k);
85  tmp.AddBoundingVertex (p->v[j]);
86  }
87  }
88  radius = max3 (tmp.MaxX ()- tmp.MinX (), tmp.MaxY ()- tmp.MinY (),
89  tmp.MaxZ ()- tmp.MinZ ());
90  opcMeshInt.SetNbTriangles (tri_count);
91  opcMeshInt.SetNbVertices (last);
92 
93  // Mesh data
94  OPCC.mIMesh = &opcMeshInt;
96  /* NoLeaf and quantized creates an optimized, both in organization and
97  * memory overhead, tree.*/
98  OPCC.mNoLeaf = true;
99  OPCC.mQuantized = true;
100  } else
101  return;
102 
103  //bool status = m_pCollisionModel->Build (OPCC);
104  m_pCollisionModel->Build (OPCC);
105 }
106 
107 
109 {
110 
111  if (m_pCollisionModel) {
112  delete m_pCollisionModel;
113  m_pCollisionModel = 0;
114  }
115  pairs.DecRef();
116  delete[] vertholder;
117 }
118 
119 
120 void csOPCODECollider::MeshCallback (udword triangle_index,
121  VertexPointers& triangle,
122  void* user_data)
123 {
124  csOPCODECollider* collider = (csOPCODECollider*)user_data;
125  Point *vertholder = collider->vertholder;
126  int index = 3 * triangle_index;
127  triangle.Vertex[0] = &vertholder [index] ;
128  triangle.Vertex[1] = &vertholder [index + 1];
129  triangle.Vertex[2] = &vertholder [index + 2];
130 }
131 
132 bool csOPCODECollider::rayCollide(const Ray &boltbeam, Vector&norm, float&distance)
133 {
134  rCollider.SetHitCallback(&csOPCODECollider::RayCallback);
135  rCollider.SetUserData(this);
136  rCollider.SetFirstContact(false);
137  //rCollider.SetClosestHit(true);
138  collFace.mDistance=FLT_MAX;
139  bool retval=rCollider.Collide(boltbeam,*m_pCollisionModel);
140  rCollider.SetUserData(NULL);
141  if (retval) {
142  retval=collFace.mDistance!=FLT_MAX;
143  if (retval) {
144  distance=collFace.mDistance;
145 #ifdef VS_DEBUG
146  printf("Opcode actually reported a hit at %f meters!\n",distance);
147 #endif
148  } else {
149  return true;//FIXME: buggy! this should return FALSE but the math is obviously broken with opcode, so opcode is rarely telling us about intersections
150  }
151  //FIXME set normal
152  }
153  return retval;
154 }
155 
156 void csOPCODECollider::RayCallback (const CollisionFace &faceHit, void* user_data)
157 {
158  csOPCODECollider* collider = (csOPCODECollider*)user_data;
159  if (collider) {
160  if (collider->collFace.mDistance> faceHit.mDistance)
161  collider->collFace = faceHit;
162  }
163 }
164 
166  const csReversibleTransform *trans1,
167  const csReversibleTransform *trans2)
168 {
169  csOPCODECollider* col2 = (csOPCODECollider*) &otherCollider;
170  ColCache.Model0 = this->m_pCollisionModel;
171  ColCache.Model1 = col2->m_pCollisionModel;
172  csMatrix3 m1;
173  if (trans1) m1 = trans1->GetT2O ();
174  csMatrix3 m2;
175  if (trans2) m2 = trans2->GetT2O ();
176  csVector3 u;
177  Matrix4x4 transform1;
178  transform1.m[0][3] = 0;
179  transform1.m[1][3] = 0;
180  transform1.m[2][3] = 0;
181  transform1.m[3][3] = 1;
182  Matrix4x4 transform2;
183  transform2.m[0][3] = 0;
184  transform2.m[1][3] = 0;
185  transform2.m[2][3] = 0;
186  transform2.m[3][3] = 1;
187  u = m1.Row1 ();
188  transform1.m[0][0] = u.x;
189  transform1.m[1][0] = u.y;
190  transform1.m[2][0] = u.z;
191  u = m2.Row1 ();
192  transform2.m[0][0] = u.x;
193  transform2.m[1][0] = u.y;
194  transform2.m[2][0] = u.z;
195  u = m1.Row2 ();
196  transform1.m[0][1] = u.x;
197  transform1.m[1][1] = u.y;
198  transform1.m[2][1] = u.z;
199  u = m2.Row2 ();
200  transform2.m[0][1] = u.x;
201  transform2.m[1][1] = u.y;
202  transform2.m[2][1] = u.z;
203  u = m1.Row3 ();
204  transform1.m[0][2] = u.x;
205  transform1.m[1][2] = u.y;
206  transform1.m[2][2] = u.z;
207  u = m2.Row3();
208  transform2.m[0][2] = u.x;
209  transform2.m[1][2] = u.y;
210  transform2.m[2][2] = u.z;
211  if (trans1) u = trans1->GetO2TTranslation ();
212  else u.Set (0, 0, 0);
213  transform1.m[3][0] = u.x;
214  transform1.m[3][1] = u.y;
215  transform1.m[3][2] = u.z;
216 
217  if (trans2) u = trans2->GetO2TTranslation ();
218  else u.Set (0, 0, 0);
219  transform2.m[3][0] = u.x;
220  transform2.m[3][1] = u.y;
221  transform2.m[3][2] = u.z;
222  if (TreeCollider.Collide (ColCache, &transform1, &transform2)) {
223  bool status = (TreeCollider.GetContactStatus () != FALSE);
224  if (status) {
225  CopyCollisionPairs (this, col2);
226  }
227  return(status);
228  } else
229  return(false);
230 }
231 
232 
234 {
235  pairs.SetLength(0);
236 }
237 
239 {
240  return(pairs.GetArray());
241 }
242 
244 {
245  return(pairs.Length());
246 }
247 
248 
250 {
251  TreeCollider.SetFirstContact(on);
252  rCollider.SetFirstContact(on);
253 }
254 
255 
256 Vector csOPCODECollider::getVertex(unsigned int which) const
257 {
258  // This function is used to position the damage particles
259  if(!vertholder)
260  return(Vector(0,0,0));
261  return(Vector(vertholder[which].x,vertholder[which].y,vertholder[which].z));
262 }
263 
264 
265 void csOPCODECollider::CopyCollisionPairs(csOPCODECollider* col1,
266  csOPCODECollider* col2)
267 {
268  if(!col1 || !col2) return;
269 
270  unsigned int N_pairs = TreeCollider.GetNbPairs ();
271  if (N_pairs == 0) return;
272 
273  const Pair* colPairs=TreeCollider.GetPairs ();
274  Point* vertholder0 = col1->vertholder;
275  Point* vertholder1 = col2->vertholder;
276  int j;
277  size_t oldlen = pairs.Length ();
278  pairs.SetLength (oldlen + N_pairs);
279 
280  for (unsigned int i = 0 ; i < N_pairs ; ++i) {
281  j = 3 * colPairs[i].id0;
282  pairs[oldlen].a1 = vertholder0[j];
283  pairs[oldlen].b1 = vertholder0[j+1];
284  pairs[oldlen].c1 = vertholder0[j+2];
285  j = 3 * colPairs[i].id1;
286  pairs[oldlen].a2 = vertholder1[j];
287  pairs[oldlen].b2 = vertholder1[j+1];
288  pairs[oldlen].c2 = vertholder1[j+2];
289  ++oldlen;
290  }
291 
292 }