summaryrefslogtreecommitdiff
path: root/libs/ode-0.16.1/ode/src/collision_kernel.h
blob: c982972a846aac4e36fde1a77918010287447991 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001-2003 Russell L. Smith.       *
 * All rights reserved.  Email: russ@q12.org   Web: www.q12.org          *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file LICENSE-BSD.TXT.                                       *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT and LICENSE-BSD.TXT for more details.                     *
 *                                                                       *
 *************************************************************************/

/*

internal data structures and functions for collision detection.

*/

#ifndef _ODE_COLLISION_KERNEL_H_
#define _ODE_COLLISION_KERNEL_H_

#include <ode/common.h>
#include <ode/contact.h>
#include <ode/collision.h>
#include "objects.h"
#include "odetls.h"
#include "common.h"


//****************************************************************************
// constants and macros

// mask for the number-of-contacts field in the dCollide() flags parameter
#define NUMC_MASK (0xffff)

#define IS_SPACE(geom) \
    dIN_RANGE((geom)->type, dFirstSpaceClass, dLastSpaceClass + 1)

#define CHECK_NOT_LOCKED(space) \
    dUASSERT ((space) == NULL || (space)->lock_count == 0, \
        "Invalid operation for locked space")


//****************************************************************************
// geometry object base class


// geom flags.
//
// GEOM_DIRTY means that the space data structures for this geom are
// potentially not up to date. NOTE THAT all space parents of a dirty geom
// are themselves dirty. this is an invariant that must be enforced.
//
// GEOM_AABB_BAD means that the cached AABB for this geom is not up to date.
// note that GEOM_DIRTY does not imply GEOM_AABB_BAD, as the geom might
// recalculate its own AABB but does not know how to update the space data
// structures for the space it is in. but GEOM_AABB_BAD implies GEOM_DIRTY.
// the valid combinations are: 
//		0
//		GEOM_DIRTY
//		GEOM_DIRTY|GEOM_AABB_BAD
//		GEOM_DIRTY|GEOM_AABB_BAD|GEOM_POSR_BAD

enum {
    GEOM_DIRTY	= 1,    // geom is 'dirty', i.e. position unknown
    GEOM_POSR_BAD = 2,    // geom's final posr is not valid
    GEOM_AABB_BAD	= 4,    // geom's AABB is not valid
    GEOM_PLACEABLE = 8,   // geom is placeable
    GEOM_ENABLED = 16,    // geom is enabled
    GEOM_ZERO_SIZED = 32, // geom is zero sized

    GEOM_ENABLE_TEST_MASK = GEOM_ENABLED | GEOM_ZERO_SIZED,
    GEOM_ENABLE_TEST_VALUE = GEOM_ENABLED,

    // Ray specific
    RAY_FIRSTCONTACT = 0x10000,
    RAY_BACKFACECULL = 0x20000,
    RAY_CLOSEST_HIT  = 0x40000
};

enum dxContactMergeOptions {
    DONT_MERGE_CONTACTS,
    MERGE_CONTACT_NORMALS,
    MERGE_CONTACTS_FULLY
};


// geometry object base class. pos and R will either point to a separately
// allocated buffer (if body is 0 - pos points to the dxPosR object) or to
// the pos and R of the body (if body nonzero).
// a dGeomID is a pointer to this object.

struct dxGeom : public dBase {
    int type;		// geom type number, set by subclass constructor
    int gflags;		// flags used by geom and space
    void *data;		// user-defined data pointer
    dBodyID body;		// dynamics body associated with this object (if any)
    dxGeom *body_next;	// next geom in body's linked list of associated geoms
    dxPosR *final_posr;	// final position of the geom in world coordinates
    dxPosR *offset_posr;	// offset from body in local coordinates

    // information used by spaces
    dxGeom *next;		// next geom in linked list of geoms
    dxGeom **tome;	// linked list backpointer
    dxGeom *next_ex;	// next geom in extra linked list of geoms (for higher level structures)
    dxGeom **tome_ex;	// extra linked list backpointer (for higher level structures)
    dxSpace *parent_space;// the space this geom is contained in, 0 if none
    dReal aabb[6];	// cached AABB for this space
    unsigned long category_bits,collide_bits;

    dxGeom (dSpaceID _space, int is_placeable);
    virtual ~dxGeom();

    // Set or clear GEOM_ZERO_SIZED flag
    void updateZeroSizedFlag(bool is_zero_sized) { gflags = is_zero_sized ? (gflags | GEOM_ZERO_SIZED) : (gflags & ~GEOM_ZERO_SIZED); }
    // Get parent space TLS kind
    unsigned getParentSpaceTLSKind() const;

    const dVector3 &buildUpdatedPosition()
    {
        dIASSERT(gflags & GEOM_PLACEABLE);
        
        recomputePosr();
        return final_posr->pos;
    }

    const dMatrix3 &buildUpdatedRotation()
    {
        dIASSERT(gflags & GEOM_PLACEABLE);

        recomputePosr();
        return final_posr->R;
    }

    // recalculate our new final position if needed
    void recomputePosr()
    {
        if (gflags & GEOM_POSR_BAD) {
            computePosr();
            gflags &= ~GEOM_POSR_BAD;
        }
    }

    // calculate our new final position from our offset and body
    void computePosr();

    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
    virtual bool controlGeometry(int controlClass, int controlCode, void *dataValue, int *dataSize);

    virtual void computeAABB()=0;
    // compute the AABB for this object and put it in aabb. this function
    // always performs a fresh computation, it does not inspect the
    // GEOM_AABB_BAD flag.

    virtual int AABBTest (dxGeom *o, dReal aabb[6]);
    // test whether the given AABB object intersects with this object, return
    // 1=yes, 0=no. this is used as an early-exit test in the space collision
    // functions. the default implementation returns 1, which is the correct
    // behavior if no more detailed implementation can be provided.

    // utility functions

    // compute the AABB only if it is not current. this function manipulates
    // the GEOM_AABB_BAD flag.

    void recomputeAABB() {
        if (gflags & GEOM_AABB_BAD) {
            // our aabb functions assume final_posr is up to date
            recomputePosr(); 
            computeAABB();
            gflags &= ~GEOM_AABB_BAD;
        }
    }

    inline void markAABBBad();

    // add and remove this geom from a linked list maintained by a space.

    void spaceAdd (dxGeom **first_ptr) {
        next = *first_ptr;
        tome = first_ptr;
        if (*first_ptr) (*first_ptr)->tome = &next;
        *first_ptr = this;
    }
    void spaceRemove() {
        if (next) next->tome = tome;
        *tome = next;
    }

    // add and remove this geom from a linked list maintained by a body.

    void bodyAdd (dxBody *b) {
        body = b;
        body_next = b->geom;
        b->geom = this;
    }
    void bodyRemove();
};

//****************************************************************************
// the base space class
//
// the contained geoms are divided into two kinds: clean and dirty.
// the clean geoms have not moved since they were put in the list,
// and their AABBs are valid. the dirty geoms have changed position, and
// their AABBs are may not be valid. the two types are distinguished by the
// GEOM_DIRTY flag. all dirty geoms come *before* all clean geoms in the list.

#if dTLS_ENABLED
#define dSPACE_TLS_KIND_INIT_VALUE OTK__DEFAULT
#define dSPACE_TLS_KIND_MANUAL_VALUE OTK_MANUALCLEANUP
#else
#define dSPACE_TLS_KIND_INIT_VALUE 0
#define dSPACE_TLS_KIND_MANUAL_VALUE 0
#endif

struct dxSpace : public dxGeom {
    int count;			// number of geoms in this space
    dxGeom *first;		// first geom in list
    int cleanup;			// cleanup mode, 1=destroy geoms on exit
    int sublevel;         // space sublevel (used in dSpaceCollide2). NOT TRACKED AUTOMATICALLY!!!
    unsigned tls_kind;	// space TLS kind to be used for global caches retrieval

    // cached state for getGeom()
    int current_index;		// only valid if current_geom != 0
    dxGeom *current_geom;		// if 0 then there is no information

    // locking stuff. the space is locked when it is currently traversing its
    // internal data structures, e.g. in collide() and collide2(). operations
    // that modify the contents of the space are not permitted when the space
    // is locked.
    int lock_count;

    dxSpace (dSpaceID _space);
    ~dxSpace();

    void computeAABB();

    void setCleanup (int mode) { cleanup = (mode != 0); }
    int getCleanup() const { return cleanup; }
    void setSublevel(int value) { sublevel = value; }
    int getSublevel() const { return sublevel; }
    void setManulCleanup(int value) { tls_kind = (value ? dSPACE_TLS_KIND_MANUAL_VALUE : dSPACE_TLS_KIND_INIT_VALUE); }
    int getManualCleanup() const { return (tls_kind == dSPACE_TLS_KIND_MANUAL_VALUE) ? 1 : 0; }
    int query (dxGeom *geom) const { dAASSERT(geom); return (geom->parent_space == this); }
    int getNumGeoms() const { return count; }

    virtual dxGeom *getGeom (int i);

    virtual void add (dxGeom *);
    virtual void remove (dxGeom *);
    virtual void dirty (dxGeom *);

    virtual void cleanGeoms()=0;
    // turn all dirty geoms into clean geoms by computing their AABBs and any
    // other space data structures that are required. this should clear the
    // GEOM_DIRTY and GEOM_AABB_BAD flags of all geoms.

    virtual void collide (void *data, dNearCallback *callback)=0;
    virtual void collide2 (void *data, dxGeom *geom, dNearCallback *callback)=0;
};


//////////////////////////////////////////////////////////////////////////

/*inline */
void dxGeom::markAABBBad() {
    gflags |= (GEOM_DIRTY | GEOM_AABB_BAD);
    CHECK_NOT_LOCKED(parent_space);
}


//****************************************************************************
// Initialization and finalization functions

void dInitColliders();
void dFinitColliders();

void dClearPosrCache(void);
void dFinitUserClasses();


#endif