Panda3D
odeSpace.cxx
1 // Filename: odeSpace.cxx
2 // Created by: joswilso (27Dec06)
3 //
4 ////////////////////////////////////////////////////////////////////
5 //
6 // PANDA 3D SOFTWARE
7 // Copyright (c) Carnegie Mellon University. All rights reserved.
8 //
9 // All use of this software is subject to the terms of the revised BSD
10 // license. You should have received a copy of this license along
11 // with this source code in a file named "LICENSE."
12 //
13 ////////////////////////////////////////////////////////////////////
14 
15 #include "config_ode.h"
16 #include "odeSpace.h"
17 #include "odeGeom.h"
18 #include "odeCollisionEntry.h"
19 #include "odeSimpleSpace.h"
20 #include "odeQuadTreeSpace.h"
21 #include "odeHashSpace.h"
22 
23 #include "throw_event.h"
24 
25 TypeHandle OdeSpace::_type_handle;
26 // this data is used in auto_collide
27 const int OdeSpace::MAX_CONTACTS = 16;
28 OdeWorld* OdeSpace::_static_auto_collide_world;
29 OdeSpace* OdeSpace::_static_auto_collide_space;
30 dJointGroupID OdeSpace::_static_auto_collide_joint_group;
31 
32 OdeSpace::
33 OdeSpace(dSpaceID id) :
34  _id(id) {
35  _auto_collide_world = NULL;
36  _auto_collide_joint_group = NULL;
37 }
38 
39 OdeSpace::
40 ~OdeSpace() {
41 }
42 
43 void OdeSpace::
44 destroy() {
45  nassertv(_id);
46  dSpaceDestroy(_id);
47 }
48 
49 int OdeSpace::
50 query(const OdeGeom& geom) const {
51  nassertr(_id, 0);
52  return dSpaceQuery(_id, geom.get_id());
53 }
54 
55 int OdeSpace::
56 query(const OdeSpace& space) const {
57  nassertr(_id, 0);
58  return dSpaceQuery(_id, (dGeomID)space.get_id());
59 }
60 
61 void OdeSpace::
62 add(OdeSpace& space) {
63  nassertv(_id);
64  dSpaceAdd(_id, (dGeomID)space.get_id());
65 }
66 
67 void OdeSpace::
68 remove(OdeSpace& space) {
69  nassertv(_id);
70  dSpaceRemove(_id, (dGeomID)space.get_id());
71 }
72 
73 void OdeSpace::
74 add(OdeGeom& geom) {
75  nassertv(_id);
76  dSpaceAdd(_id, geom.get_id());
77 }
78 
79 void OdeSpace::
80 remove(OdeGeom& geom) {
81  nassertv(_id);
82  dSpaceRemove(_id, geom.get_id());
83 }
84 
85 void OdeSpace::
86 clean() {
87  nassertv(_id);
88  dSpaceClean(_id);
89 }
90 
91 OdeGeom OdeSpace::
92 get_geom(int i) {
93  nassertr(_id, OdeGeom(0));
94  return OdeGeom(dSpaceGetGeom(_id, i));
95 }
96 
97 
98 void OdeSpace::
99 write(ostream &out, unsigned int indent) const {
100  out.width(indent); out << "" << get_type() << "(id = " << _id << ")";
101 }
102 
103 OdeSpace::
104 operator bool () const {
105  return (_id != NULL);
106 }
107 
108 void OdeSpace::
109 set_auto_collide_world(OdeWorld &world) {
110  _auto_collide_world = &world;
111 }
112 
113 void OdeSpace::
114 set_auto_collide_joint_group(OdeJointGroup &joint_group) {
115  _auto_collide_joint_group = joint_group.get_id();
116 }
117 
118 void OdeSpace::
119 auto_collide() {
120  if (_auto_collide_world == NULL) {
121  odespace_cat.error() << "No collide world has been set!\n";
122  } else {
123  nassertv(_id != NULL);
124  _static_auto_collide_space = this;
125  _static_auto_collide_world = _auto_collide_world;
126  _static_auto_collide_joint_group = _auto_collide_joint_group;
127  dSpaceCollide(_id, this, &auto_callback);
128  }
129 }
130 
131 void OdeSpace::
132 auto_callback(void *data, dGeomID o1, dGeomID o2) {
133 // uses data stored on the world to resolve collisions so you don't have to use near_callbacks in python
134  int i;
135  dBodyID b1 = dGeomGetBody(o1);
136  dBodyID b2 = dGeomGetBody(o2);
137 
138  dContact contact[OdeSpace::MAX_CONTACTS];
139 
140  int surface1 = _static_auto_collide_space->get_surface_type(o1);
141  int surface2 = _static_auto_collide_space->get_surface_type(o2);
142 
143  nassertv(_static_auto_collide_world != NULL);
144  sSurfaceParams collide_params;
145  collide_params = _static_auto_collide_world->get_surface(surface1, surface2);
146 
147  for (i=0; i < OdeSpace::MAX_CONTACTS; i++) {
148  contact[i].surface.mode = collide_params.colparams.mode;
149  contact[i].surface.mu = collide_params.colparams.mu;
150  contact[i].surface.mu2 = collide_params.colparams.mu2;
151  contact[i].surface.bounce = collide_params.colparams.bounce;
152  contact[i].surface.bounce_vel = collide_params.colparams.bounce_vel;
153  contact[i].surface.soft_cfm = collide_params.colparams.soft_cfm;
154  }
155 
156  static int numc = 0;
157  numc = dCollide(o1, o2, OdeSpace::MAX_CONTACTS, &contact[0].geom, sizeof(dContact));
158 
159  if (numc) {
160  odespace_cat.debug() << "collision between geoms " << o1 << " and " << o2 << "\n";
161  odespace_cat.debug() << "collision between body " << b1 << " and " << b2 << "\n";
162  odespace_cat.debug() << "surface1= "<< surface1 << " surface2=" << surface2 << "\n";
163 
164  PT(OdeCollisionEntry) entry;
165  if (!_static_auto_collide_space->_collision_event.empty()) {
166  entry = new OdeCollisionEntry;
167  entry->_geom1 = o1;
168  entry->_geom2 = o2;
169  entry->_body1 = b1;
170  entry->_body2 = b2;
171  entry->_num_contacts = numc;
172  entry->_contact_geoms = new OdeContactGeom[numc];
173  }
174 
175  for(i=0; i < numc; i++) {
176  dJointID c = dJointCreateContact(_static_auto_collide_world->get_id(), _static_auto_collide_joint_group, contact + i);
177  if ((_static_auto_collide_space->get_collide_id(o1) >= 0) && (_static_auto_collide_space->get_collide_id(o2) >= 0)) {
178  dJointAttach(c, b1, b2);
179  }
180  if (!_static_auto_collide_space->_collision_event.empty()) {
181  entry->_contact_geoms[i] = contact[i].geom;
182  }
183  }
184  _static_auto_collide_world->set_dampen_on_bodies(b1, b2, collide_params.dampen);
185 
186  if (!_static_auto_collide_space->_collision_event.empty()) {
187  throw_event(_static_auto_collide_space->_collision_event, EventParameter(entry));
188  }
189  }
190 }
191 
192 OdeSimpleSpace OdeSpace::
193 convert_to_simple_space() const {
194  nassertr(_id != 0, OdeSimpleSpace((dSpaceID)0));
195  nassertr(get_class() == OdeGeom::GC_simple_space, OdeSimpleSpace((dSpaceID)0));
196  return OdeSimpleSpace(_id);
197 }
198 
199 OdeHashSpace OdeSpace::
200 convert_to_hash_space() const {
201  nassertr(_id != 0, OdeHashSpace((dSpaceID)0));
202  nassertr(get_class() == OdeGeom::GC_hash_space, OdeHashSpace((dSpaceID)0));
203  return OdeHashSpace(_id);
204 }
205 
206 OdeQuadTreeSpace OdeSpace::
207 convert_to_quad_tree_space() const {
208  nassertr(_id != 0, OdeQuadTreeSpace((dSpaceID)0));
209  nassertr(get_class() == OdeGeom::GC_quad_tree_space, OdeQuadTreeSpace((dSpaceID)0));
210  return OdeQuadTreeSpace(_id);
211 }
212 
213 
214 void OdeSpace::
215 set_surface_type( int surfaceType, dGeomID id){
216  _geom_surface_map[id]= surfaceType;
217 }
218 
219 void OdeSpace::
220 set_surface_type(OdeGeom& geom, int surfaceType){
221  dGeomID id = geom.get_id();
222  set_surface_type(surfaceType, id);
223 }
224 
225 int OdeSpace::
226 get_surface_type(dGeomID id) {
227  GeomSurfaceMap::iterator iter = _geom_surface_map.find(id);
228  if (iter != _geom_surface_map.end()) {
229  return iter->second;
230  }
231  return 0;
232 }
233 
234 int OdeSpace::
235 get_surface_type(OdeGeom& geom) {
236  dGeomID id = geom.get_id();
237  return get_surface_type(id);
238 }
239 
240 
241 int OdeSpace::
242 set_collide_id( int collide_id, dGeomID id) {
243  _geom_collide_id_map[id]= collide_id;
244  return _geom_collide_id_map[id];
245 }
246 
247 int OdeSpace::
248 set_collide_id( OdeGeom& geom, int collide_id) {
249  dGeomID id = geom.get_id();
250  return set_collide_id(collide_id, id);
251 }
252 
253 int OdeSpace::
254 get_collide_id(OdeGeom& geom) {
255  dGeomID id = geom.get_id();
256  return get_collide_id(id);
257 }
258 
259 
260 int OdeSpace::
261 get_collide_id(dGeomID id) {
262  GeomCollideIdMap::iterator iter = _geom_collide_id_map.find(id);
263  if (iter != _geom_collide_id_map.end()) {
264  return iter->second;
265  }
266  return 0;
267 }
dSpaceID get_id() const
Returns the underlying dSpaceID.
Definition: odeSpace.I:34
An optional parameter associated with an event.
dGeomID get_id() const
Returns the underlying dGeomID.
Definition: odeGeom.I:34
A class used to hold information about a collision that has occurred.
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85