Open Dynamics Engine

collision_kernel.h

00001 /*************************************************************************
00002  *                                                                       *
00003  * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
00004  * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
00005  *                                                                       *
00006  * This library is free software; you can redistribute it and/or         *
00007  * modify it under the terms of EITHER:                                  *
00008  *   (1) The GNU Lesser General Public License as published by the Free  *
00009  *       Software Foundation; either version 2.1 of the License, or (at  *
00010  *       your option) any later version. The text of the GNU Lesser      *
00011  *       General Public License is included with this library in the     *
00012  *       file LICENSE.TXT.                                               *
00013  *   (2) The BSD-style license that is included with this library in     *
00014  *       the file LICENSE-BSD.TXT.                                       *
00015  *                                                                       *
00016  * This library is distributed in the hope that it will be useful,       *
00017  * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
00018  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
00019  * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
00020  *                                                                       *
00021  *************************************************************************/
00022 
00023 /*
00024 
00025 internal data structures and functions for collision detection.
00026 
00027 */
00028 
00029 #ifndef _ODE_COLLISION_KERNEL_H_
00030 #define _ODE_COLLISION_KERNEL_H_
00031 
00032 #include <ode/common.h>
00033 #include <ode/contact.h>
00034 #include <ode/collision.h>
00035 #include "objects.h"
00036 #include "odetls.h"
00037 
00038 //****************************************************************************
00039 // constants and macros
00040 
00041 // mask for the number-of-contacts field in the dCollide() flags parameter
00042 #define NUMC_MASK (0xffff)
00043 
00044 #define IS_SPACE(geom) \
00045   ((geom)->type >= dFirstSpaceClass && (geom)->type <= dLastSpaceClass)
00046 
00047 //****************************************************************************
00048 // geometry object base class
00049 
00050 
00051 // geom flags.
00052 //
00053 // GEOM_DIRTY means that the space data structures for this geom are
00054 // potentially not up to date. NOTE THAT all space parents of a dirty geom
00055 // are themselves dirty. this is an invariant that must be enforced.
00056 //
00057 // GEOM_AABB_BAD means that the cached AABB for this geom is not up to date.
00058 // note that GEOM_DIRTY does not imply GEOM_AABB_BAD, as the geom might
00059 // recalculate its own AABB but does not know how to update the space data
00060 // structures for the space it is in. but GEOM_AABB_BAD implies GEOM_DIRTY.
00061 // the valid combinations are: 
00062 //    0
00063 //    GEOM_DIRTY
00064 //    GEOM_DIRTY|GEOM_AABB_BAD
00065 //    GEOM_DIRTY|GEOM_AABB_BAD|GEOM_POSR_BAD
00066 
00067 enum {
00068   GEOM_DIRTY   = 1,    // geom is 'dirty', i.e. position unknown
00069   GEOM_POSR_BAD = 2,    // geom's final posr is not valid
00070   GEOM_AABB_BAD   = 4,    // geom's AABB is not valid
00071   GEOM_PLACEABLE = 8,   // geom is placeable
00072   GEOM_ENABLED = 16,    // geom is enabled
00073   GEOM_ZERO_SIZED = 32, // geom is zero sized
00074 
00075   GEOM_ENABLE_TEST_MASK = GEOM_ENABLED | GEOM_ZERO_SIZED,
00076   GEOM_ENABLE_TEST_VALUE = GEOM_ENABLED,
00077 
00078   // Ray specific
00079   RAY_FIRSTCONTACT = 0x10000,
00080   RAY_BACKFACECULL = 0x20000,
00081   RAY_CLOSEST_HIT  = 0x40000
00082 };
00083 
00084 enum dxContactMergeOptions {
00085    DONT_MERGE_CONTACTS,
00086    MERGE_CONTACT_NORMALS,
00087    MERGE_CONTACTS_FULLY,
00088 };
00089 
00090 
00091 // geometry object base class. pos and R will either point to a separately
00092 // allocated buffer (if body is 0 - pos points to the dxPosR object) or to
00093 // the pos and R of the body (if body nonzero).
00094 // a dGeomID is a pointer to this object.
00095 
00096 struct dxGeom : public dBase {
00097   int type;    // geom type number, set by subclass constructor
00098   int gflags;     // flags used by geom and space
00099   void *data;     // user-defined data pointer
00100   dBodyID body;      // dynamics body associated with this object (if any)
00101   dxGeom *body_next; // next geom in body's linked list of associated geoms
00102   dxPosR *final_posr;   // final position of the geom in world coordinates
00103   dxPosR *offset_posr;  // offset from body in local coordinates
00104 
00105   // information used by spaces
00106   dxGeom *next;      // next geom in linked list of geoms
00107   dxGeom **tome;  // linked list backpointer
00108   dxSpace *parent_space;// the space this geom is contained in, 0 if none
00109   dReal aabb[6];  // cached AABB for this space
00110   unsigned long category_bits,collide_bits;
00111 
00112   dxGeom (dSpaceID _space, int is_placeable);
00113   virtual ~dxGeom();
00114 
00115   // Set or clear GEOM_ZERO_SIZED flag
00116   void updateZeroSizedFlag(bool is_zero_sized) { gflags = is_zero_sized ? (gflags | GEOM_ZERO_SIZED) : (gflags & ~GEOM_ZERO_SIZED); }
00117   // Get parent space TLS kind
00118   unsigned getParentSpaceTLSKind() const;
00119 
00120   // calculate our new final position from our offset and body
00121   void computePosr();
00122 
00123   // recalculate our new final position if needed
00124   void recomputePosr()
00125   {
00126     if (gflags & GEOM_POSR_BAD) {
00127       computePosr();
00128       gflags &= ~GEOM_POSR_BAD;
00129     }
00130   }
00131 
00132   bool checkControlValueSizeValidity(void *dataValue, int *dataSize, int iRequiresSize) { return (*dataSize == iRequiresSize && dataValue != 0) ? true : !(*dataSize = iRequiresSize); } // Here it is the intent to return true for 0 required size in any case
00133   virtual bool controlGeometry(int controlClass, int controlCode, void *dataValue, int *dataSize);
00134 
00135   virtual void computeAABB()=0;
00136   // compute the AABB for this object and put it in aabb. this function
00137   // always performs a fresh computation, it does not inspect the
00138   // GEOM_AABB_BAD flag.
00139 
00140   virtual int AABBTest (dxGeom *o, dReal aabb[6]);
00141   // test whether the given AABB object intersects with this object, return
00142   // 1=yes, 0=no. this is used as an early-exit test in the space collision
00143   // functions. the default implementation returns 1, which is the correct
00144   // behavior if no more detailed implementation can be provided.
00145 
00146   // utility functions
00147 
00148   // compute the AABB only if it is not current. this function manipulates
00149   // the GEOM_AABB_BAD flag.
00150 
00151   void recomputeAABB() {
00152     if (gflags & GEOM_AABB_BAD) {
00153       // our aabb functions assume final_posr is up to date
00154       recomputePosr(); 
00155       computeAABB();
00156       gflags &= ~GEOM_AABB_BAD;
00157     }
00158   }
00159 
00160   // add and remove this geom from a linked list maintained by a space.
00161 
00162   void spaceAdd (dxGeom **first_ptr) {
00163     next = *first_ptr;
00164     tome = first_ptr;
00165     if (*first_ptr) (*first_ptr)->tome = &next;
00166     *first_ptr = this;
00167   }
00168   void spaceRemove() {
00169     if (next) next->tome = tome;
00170     *tome = next;
00171   }
00172 
00173   // add and remove this geom from a linked list maintained by a body.
00174 
00175   void bodyAdd (dxBody *b) {
00176     body = b;
00177     body_next = b->geom;
00178     b->geom = this;
00179   }
00180   void bodyRemove();
00181 };
00182 
00183 //****************************************************************************
00184 // the base space class
00185 //
00186 // the contained geoms are divided into two kinds: clean and dirty.
00187 // the clean geoms have not moved since they were put in the list,
00188 // and their AABBs are valid. the dirty geoms have changed position, and
00189 // their AABBs are may not be valid. the two types are distinguished by the
00190 // GEOM_DIRTY flag. all dirty geoms come *before* all clean geoms in the list.
00191 
00192 #if dTLS_ENABLED
00193 #define dSPACE_TLS_KIND_INIT_VALUE OTK__DEFAULT
00194 #define dSPACE_TLS_KIND_MANUAL_VALUE OTK_MANUALCLEANUP
00195 #else
00196 #define dSPACE_TLS_KIND_INIT_VALUE 0
00197 #define dSPACE_TLS_KIND_MANUAL_VALUE 0
00198 #endif
00199 
00200 struct dxSpace : public dxGeom {
00201   int count;         // number of geoms in this space
00202   dxGeom *first;     // first geom in list
00203   int cleanup;       // cleanup mode, 1=destroy geoms on exit
00204   int sublevel;         // space sublevel (used in dSpaceCollide2). NOT TRACKED AUTOMATICALLY!!!
00205   unsigned tls_kind; // space TLS kind to be used for global caches retrieval
00206 
00207   // cached state for getGeom()
00208   int current_index;    // only valid if current_geom != 0
00209   dxGeom *current_geom;    // if 0 then there is no information
00210 
00211   // locking stuff. the space is locked when it is currently traversing its
00212   // internal data structures, e.g. in collide() and collide2(). operations
00213   // that modify the contents of the space are not permitted when the space
00214   // is locked.
00215   int lock_count;
00216 
00217   dxSpace (dSpaceID _space);
00218   ~dxSpace();
00219 
00220   void computeAABB();
00221 
00222   void setCleanup (int mode) { cleanup = (mode != 0); }
00223   int getCleanup() const { return cleanup; }
00224   void setSublevel(int value) { sublevel = value; }
00225   int getSublevel() const { return sublevel; }
00226   void setManulCleanup(int value) { tls_kind = (value ? dSPACE_TLS_KIND_MANUAL_VALUE : dSPACE_TLS_KIND_INIT_VALUE); }
00227   int getManualCleanup() const { return (tls_kind == dSPACE_TLS_KIND_MANUAL_VALUE) ? 1 : 0; }
00228   int query (dxGeom *geom) const { dAASSERT(geom); return (geom->parent_space == this); }
00229   int getNumGeoms() const { return count; }
00230 
00231   virtual dxGeom *getGeom (int i);
00232 
00233   virtual void add (dxGeom *);
00234   virtual void remove (dxGeom *);
00235   virtual void dirty (dxGeom *);
00236 
00237   virtual void cleanGeoms()=0;
00238   // turn all dirty geoms into clean geoms by computing their AABBs and any
00239   // other space data structures that are required. this should clear the
00240   // GEOM_DIRTY and GEOM_AABB_BAD flags of all geoms.
00241 
00242   virtual void collide (void *data, dNearCallback *callback)=0;
00243   virtual void collide2 (void *data, dxGeom *geom, dNearCallback *callback)=0;
00244 };
00245 
00246 
00247 //****************************************************************************
00248 // Initialization and finalization functions
00249 
00250 void dInitColliders();
00251 void dFinitColliders();
00252 
00253 void dClearPosrCache(void);
00254 void dFinitUserClasses();
00255 
00256 
00257 #endif