vrecko
virtual reality framework
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Pages
SNCH_Object.h
Go to the documentation of this file.
1 
2 #ifndef SNCH_OBJECT_H
3 #define SNCH_OBJECT_H
4 
5 #include "SphereBVH_Object.h"
6 #include "SNCH_Object_Data.h"
7 
9 #include <vrecko/MTLock.h>
10 
11 using namespace vrecko;
12 
13 namespace APSpacePartitioning {
14 
15 // Flags for SNCH_Object::LocalMinimumDistance::dwFlags
16 #define SNCH_LMD_F_INTERSECTION 0x00000001
17  // The returned points don't mean points of collision, but it is a part of the intersection polyline
18 #define SNCH_LMD_F_NEGATIVE_DISTANCE 0x00000002
19  // The LMD points define negative distance, which (usually?) means largest intersection distance
20  // in a local neigbourhood (and not smallest distance between surfaces).
21  // This can arise only in localSearch and it depends on firstly finding the intersection.
22 
23 
24 /*
25 
26 // Flags for SNCH_Object::LocalMinimumDistance::closeFeatures and other
27 
28 Not implemented (yet?)
29 
30 #define SNCH_CF_VERTEX1 0x01
31 #define SNCH_CF_VERTEX2 0x02
32 #define SNCH_CF_VERTEX3 0x04
33 #define SNCH_CF_EDGE1 0x08
34 #define SNCH_CF_EDGE2 0x10
35 #define SNCH_CF_EDGE3 0x20
36 
37 */
38 
39 #define SNCH_FLOAT_SMALL_NUM 0.00000001f
40 //#define SNCH_FLOAT_TOLERANCE 0.001f
41 #define SNCH_FLOAT_TOLERANCE SNCH_FLOAT_SMALL_NUM
42 
43 
44 
45 #define SP_OBJECT_INTERFACE_ID__SNCH 20
46 
47 
49 public:
50  //
51  // constructors / destructors
52  //
53  SNCH_Object();
54  ~SNCH_Object();
55 
56  virtual void preInitialize(void);
57 
58  float getForce(void);
59 
60  void setNCoeficient(double nc) {ncoeficient = nc;}
61  double getNCoeficient(void) {return ncoeficient;}
62  void setMaxForce(double mforce) {max_force = mforce;}
63  double getMaxForce(void) {return max_force;}
64 
65  virtual bool getCollisions(CollisionParams * params, COLLISION_POINTS_VECTOR ** colPoints,
66  unsigned long obj1ID, unsigned long obj2ID);
67  // overriden method from SP_ObjectInterface
68 
69  typedef struct LocalMinimumDistance {
70  unsigned long dwFlags; // Combination of SNCH_LMD_F_*
71  unsigned long faces[2]; // indices of faces that are colliding
72  osg::Vec3 pointsTrans[2];
73  // Points transformed into world space. Exact meaning depends on [dwFlags].
74  // It is either a possible-future-contact points pair or an intersection line.
75  unsigned short closeFeatures[2];
76  // The vertices and/or edges which are the closest one to the contact points.
77  // Can have of of the values:
78  // 0, 1, 2 - index of the respective vertex
79  // 3, 4, 5 - index of the respective edge + 3
80  // 0xFF - if all of the vertices are too far
81  osg::Vec3 vecTriMaxNegDist;
82  // Used only if [dwFlags] contains SNCH_LMD_F_NEGATIVE_DISTANCE.
83  };
84  typedef std::vector<LocalMinimumDistance> LMDvector;
85 
86  class LMDStore {
87  public:
88  LMDStore() { active_LMD = 0; bLMDValid[0] = bLMDValid[1] = false; }
89 
90  unsigned char active_LMD;
91  // Which of the LMDs vector is used for local updates (strictly 0 or 1).
92  // The other is for background calculation of global update.
93  bool bLMDValid[2];
94  // Is a particular LMD vector valid? (i.e. Have the initial calculations already ended?)
95  LMDvector LMDs[2];
96 
97  // add a timestamp? (TODO?)
98 
100  // TODO: This might create too many critical sections/mutexes.
101  // (one for each collision pair)
102  // It's a critical section/mutex to protect switching [active_LMD] to the other vector.
103  };
104 
105 protected:
106  double ncoeficient, max_force;
107 
108  typedef __int64 LMD_HASH; // May need some adjustments for Linux or non-MSVC compilers. (Now it has to be at least 64 bits long.)
109  typedef Sgi::hash_map<LMD_HASH, LMDStore*> LMD_STORE_MAP;
111  // DON'T ACCESS THIS DIRECTLY !!! It has to have a multithread access protection.
112  // USE the getLMDStore() method.
113  // The KEY of this hash_map is composed of two object IDs.
114  // Use calcLMDHash() method to calculate it.
116  inline LMD_HASH calcLMDHash(unsigned long int id1, unsigned long int id2)
117  { return (((LMD_HASH)id1) << 32) + (LMD_HASH)id2; }
118 
119  LMDStore* getLMDStore(LMD_HASH hash);
120  // Gets a LMDStore for the given hash. Creates one if it doesn't exist.
121 
122 
123  double reject_distance_for_surfaces, reject_distance_for_BS;
124  double angle_tolerance; // LOD - plane detection (convex, concave surface)
125 
126  void globalSearch(SNCH_Object_Data *pOData1, SNCH_Object_Data *pOData2, LMDStore *lmds,
127  CollisionParams *params);
128  void localSearch(SNCH_Object_Data *pOData1, SNCH_Object_Data *pOData2, LMDStore *lmds,
129  CollisionParams *params, int lmdIndex, int dbgWriterGLIndex = 0);
130  bool testNodeNorec(SNCH_Object_Data::STNodeSNCH *pSTNode1, SNCH_Object_Data *pOData1, osg::Matrix *transf1,
131  SNCH_Object_Data::STNodeSNCH *pSTNode2, SNCH_Object_Data *pOData2, osg::Matrix *transf2,
132  LMDStore *lmds, CollisionParams * params);
133  // no-recursion
134 
135  bool getObjectsTransformations(SNCH_Object_Data *pOData1, SNCH_Object_Data *pOData2, CollisionParams *params,
136  osg::Matrix *transf1, osg::Matrix *transf2);
137 
138 
140  osg::Vec3 pos;
141  osg::Vec3 normal;
142  };
143  class OneTri {
144  public:
145  OneTri() { reset(); };
146  inline void reset() { planeNormal.x() = FLT_MAX; planeD = FLT_MAX; };
147 
148  inline void calcNormal() {
149  if (planeNormal.x() == FLT_MAX) {
150  planeNormal = (v[1].pos - v[0].pos) ^ (v[2].pos - v[0].pos);
151  float len = planeNormal.length();
152 
153  bZeroNormal = true;
154  if (len >= SNCH_FLOAT_SMALL_NUM) {
155  bZeroNormal = false;
156  planeNormal /= len;
157  }
158  }
159  }
160 
161  inline void calcD() {
162  if (planeD == FLT_MAX)
163  planeD = -(v[0].pos.x() * planeNormal.x() + v[0].pos.y() * planeNormal.y() + v[0].pos.z() * planeNormal.z());
164  }
165 
167 
168  bool bZeroNormal; // if the [planeNormal] is zero, this will be set to "true".
169  osg::Vec3 planeNormal;
170  float planeD;
171  };
172  typedef OneTri TWO_TRIS[2];
173 
174  typedef enum {
175  NoIntersection, // no intersection between the triangle cone and the other triangle
176  OriginalTriangleIntersection, // intersection between the triangles
177  ConeIntersection // intersection between the triangle cone and the other triangle
178  } ProjectionIntersectionResult;
179 
180  ProjectionIntersectionResult triProjectionIntersection(
181  OneTri *points0,
182  OneTri *points1,
183  osg::Vec3 *outIntersectionPoint0 = NULL,
184  osg::Vec3 *outIntersectionPoint1 = NULL,
185 
186  bool bPerformPretests = true
187  );
188  // WARNING: This function is optimized and so it expects that it will be called twice
189  // for two triangles (with reversed parameters).
190  // This is due to some test at the beginning of the function.
191  //
192  // The idea:
193  // Project vertices on [tri1] using the normals into the plane specified by [tri2].
194  // Then the 2D triangles are tested for intersection.
195  // If triangles lie on the same plane, they are intersecting in theory, but we will take
196  // it as non-intersecting triangles with distance = 0.
197  // [outIntersectionPoint0] and [outIntersectionPoint1] are filled only if the original triangles intersect.
198 
199 
200  bool triIntersects(OneTri *points0, OneTri *points1, osg::Vec3 *outPoint0Trans = NULL, osg::Vec3 *outPoint1Trans = NULL,
201  osg::Vec3 *outPoint0Tri0Cross = NULL, osg::Vec3 *outPoint1Tri0Cross = NULL, bool *bOutPointsTriCrossValid = NULL);
202  // Returns if both triangles intersects in 3D space.
203  // ASSUMES that the triangles DOES NOT lie on the same plane (this should be checked by the triProjectionIntersection() method)
204  // (SIDE NOTE: The method returns "false" if triangles are coplanar. This would be also OK for us
205  // if they were on the same plane, so basically no assumption needed)
206  // Therefore this method conculdes that if the triangles lie on the planes with
207  // the same or opposite normal, then the triangles don't intersect.
208  // If the triangles intersect, it can also return the middle point of intersection
209  // [outPoint0Tri0Cross], [outPoint0Tri1Cross] are only calculated and outputted if requested.
210  // They represetns the points in space where [tri1] intersects the plane defined by [tri2].
211 
212  float triDistance(OneTri *points0, OneTri *points1, osg::Vec3 *outPoint1Trans = NULL, osg::Vec3 *outPoint2Trans = NULL,
213  unsigned short *closeFeature0 = NULL, unsigned short *closeFeature1 = NULL);
214  // Calculates the triangle distance in 3D space.
215  // NOTE that it ASSUMES that the triangles DON'T INTERSECT. This should have been resolved before.
216  // Can calculate points here the distance was achieved.
217  // The points are already transformed into the world space.
218 
219  bool old_getTriLMD(
220  SNCH_Object_Data::STNodeSNCH *pSTNode1, SNCH_Object_Data *pOData1, osg::Matrix *transf1, osg::Vec3 *center1,
221  SNCH_Object_Data::STNodeSNCH *pSTNode2, SNCH_Object_Data *pOData2, osg::Matrix *transf2, osg::Vec3 *center2,
222  osg::Vec3 point[2][7], unsigned long *index1, unsigned long *index2);
223  // Getting the LMDs using the old algorithm.
224  // [pSTNode1/2] and [center1/2] may be NULL - in that case the cones won't be used.
225  // (Only the distance between those 7x7 points.)
226 
227 };
228 
229 
230 }
231 
232 #endif
233 
234