Panda3D
bulletCharacterControllerNode.cxx
1 // Filename: bulletCharacterControllerNode.cxx
2 // Created by: enn0x (21Nov10)
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 "bulletCharacterControllerNode.h"
16 
17 #if BT_BULLET_VERSION >= 285
18 static const btVector3 up_vectors[3] = {btVector3(1.0f, 0.0f, 0.0f), btVector3(0.0f, 1.0f, 0.0f), btVector3(0.0f, 0.0f, 1.0f)};
19 #endif
20 
21 TypeHandle BulletCharacterControllerNode::_type_handle;
22 
23 ////////////////////////////////////////////////////////////////////
24 // Function: BulletCharacterControllerNode::Constructor
25 // Access: Published
26 // Description:
27 ////////////////////////////////////////////////////////////////////
28 BulletCharacterControllerNode::
29 BulletCharacterControllerNode(BulletShape *shape, PN_stdfloat step_height, const char *name) : BulletBaseCharacterControllerNode(name) {
30 
31  // Synchronised transform
32  _sync = TransformState::make_identity();
33  _sync_disable = false;
34 
35  // Initial transform
36  btTransform trans = btTransform::getIdentity();
37 
38  // Get convex shape (for ghost object)
39  if (!shape->is_convex()) {
40  bullet_cat.error() << "a convex shape is required!" << endl;
41  return;
42  }
43 
44  btConvexShape *convex = (btConvexShape *)(shape->ptr());
45 
46  // Ghost object
47  _ghost = new btPairCachingGhostObject();
48  _ghost->setUserPointer(this);
49 
50  _ghost->setWorldTransform(trans);
51  _ghost->setInterpolationWorldTransform(trans);
52  _ghost->setCollisionShape(convex);
53  _ghost->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
54 
55  // Up axis
56  _up = get_default_up_axis();
57 
58  // Initialise movement
59  _linear_movement_is_local = false;
60  _linear_movement.set(0.0f, 0.0f, 0.0f);
61  _angular_movement = 0.0f;
62 
63  // Character controller
64 #if BT_BULLET_VERSION >= 285
65  _character = new btKinematicCharacterController(_ghost, convex, step_height, up_vectors[_up]);
66  _character->setGravity(up_vectors[_up] * -(btScalar)9.81f);
67 #else
68  _character = new btKinematicCharacterController(_ghost, convex, step_height, _up);
69  _character->setGravity((btScalar)9.81f);
70 #endif
71 
72  // Retain a pointer to the shape
73  _shape = shape;
74 
75  // Default collide mask
76  // TODO set_into_collide_mask(CollideMask::all_on());
77 }
78 
79 ////////////////////////////////////////////////////////////////////
80 // Function: BulletCharacterControllerNode::set_linear_movement
81 // Access: Published
82 // Description:
83 ////////////////////////////////////////////////////////////////////
84 void BulletCharacterControllerNode::
85 set_linear_movement(const LVector3 &movement, bool is_local) {
86 
87  nassertv(!movement.is_nan());
88 
89  _linear_movement = movement;
90  _linear_movement_is_local = is_local;
91 }
92 
93 ////////////////////////////////////////////////////////////////////
94 // Function: BulletCharacterControllerNode::set_angular_movement
95 // Access: Published
96 // Description:
97 ////////////////////////////////////////////////////////////////////
98 void BulletCharacterControllerNode::
99 set_angular_movement(PN_stdfloat omega) {
100 
101  _angular_movement = omega;
102 }
103 
104 ////////////////////////////////////////////////////////////////////
105 // Function: BulletCharacterControllerNode::sync_p2b
106 // Access: Public
107 // Description:
108 ////////////////////////////////////////////////////////////////////
109 void BulletCharacterControllerNode::
110 sync_p2b(PN_stdfloat dt, int num_substeps) {
111 
112  // Synchronise global transform
113  transform_changed();
114 
115  // Angular rotation
116  btScalar angle = dt * deg_2_rad(_angular_movement);
117 
118  btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
119  btVector3 up = m[_up];
120 
121  m *= btMatrix3x3(btQuaternion(up, angle));
122 
123  _ghost->getWorldTransform().setBasis(m);
124 
125  // Linear movement
126  LVector3 vp = _linear_movement / (btScalar)num_substeps;
127 
128  btVector3 v;
129  if (_linear_movement_is_local) {
130  btTransform xform = _ghost->getWorldTransform();
131  xform.setOrigin(btVector3(0.0f, 0.0f, 0.0f));
132  v = xform(LVecBase3_to_btVector3(vp));
133  }
134  else {
135  v = LVecBase3_to_btVector3(vp);
136  }
137 
138  //_character->setVelocityForTimeInterval(v, dt);
139  _character->setWalkDirection(v * dt);
140  _angular_movement = 0.0f;
141 }
142 
143 ////////////////////////////////////////////////////////////////////
144 // Function: BulletCharacterControllerNode::sync_b2p
145 // Access: Public
146 // Description:
147 ////////////////////////////////////////////////////////////////////
148 void BulletCharacterControllerNode::
149 sync_b2p() {
150 
151  NodePath np = NodePath::any_path((PandaNode *)this);
152  LVecBase3 scale = np.get_net_transform()->get_scale();
153 
154  btTransform trans = _ghost->getWorldTransform();
155  CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);
156 
157  LMatrix4 m_sync = _sync->get_mat();
158  LMatrix4 m_ts = ts->get_mat();
159 
160  if (!m_sync.almost_equal(m_ts)) {
161  _sync = ts;
162  _sync_disable = true;
163  np.set_transform(NodePath(), ts);
164  _sync_disable = false;
165  }
166 }
167 
168 ////////////////////////////////////////////////////////////////////
169 // Function: BulletCharacterControllerNode::transform_changed
170 // Access: Protected
171 // Description:
172 ////////////////////////////////////////////////////////////////////
173 void BulletCharacterControllerNode::
174 transform_changed() {
175 
176  if (_sync_disable) return;
177 
178  NodePath np = NodePath::any_path((PandaNode *)this);
179  CPT(TransformState) ts = np.get_net_transform();
180 
181  LMatrix4 m_sync = _sync->get_mat();
182  LMatrix4 m_ts = ts->get_mat();
183 
184  if (!m_sync.almost_equal(m_ts)) {
185  _sync = ts;
186 
187  // Get translation, heading and scale
188  LPoint3 pos = ts->get_pos();
189  PN_stdfloat heading = ts->get_hpr().get_x();
190  LVecBase3 scale = ts->get_scale();
191 
192  // Set translation
193  _character->warp(LVecBase3_to_btVector3(pos));
194 
195  // Set Heading
196  btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
197  btVector3 up = m[_up];
198 
199  m = btMatrix3x3(btQuaternion(up, deg_2_rad(heading)));
200 
201  _ghost->getWorldTransform().setBasis(m);
202 
203  // Set scale
204  _shape->set_local_scale(scale);
205  }
206 }
207 
208 ////////////////////////////////////////////////////////////////////
209 // Function: BulletCharacterControllerNode::get_shape
210 // Access: Published
211 // Description:
212 ////////////////////////////////////////////////////////////////////
213 BulletShape *BulletCharacterControllerNode::
214 get_shape() const {
215 
216  return _shape;
217 }
218 
219 ////////////////////////////////////////////////////////////////////
220 // Function: BulletCharacterControllerNode::is_on_ground
221 // Access: Published
222 // Description:
223 ////////////////////////////////////////////////////////////////////
224 bool BulletCharacterControllerNode::
225 is_on_ground() const {
226 
227  return _character->onGround();
228 }
229 
230 ////////////////////////////////////////////////////////////////////
231 // Function: BulletCharacterControllerNode::can_jump
232 // Access: Published
233 // Description:
234 ////////////////////////////////////////////////////////////////////
235 bool BulletCharacterControllerNode::
236 can_jump() const {
237 
238  return _character->canJump();
239 }
240 
241 ////////////////////////////////////////////////////////////////////
242 // Function: BulletCharacterControllerNode::do_jump
243 // Access: Published
244 // Description:
245 ////////////////////////////////////////////////////////////////////
246 void BulletCharacterControllerNode::
247 do_jump() {
248 
249  _character->jump();
250 }
251 
252 ////////////////////////////////////////////////////////////////////
253 // Function: BulletCharacterControllerNode::set_fall_speed
254 // Access: Published
255 // Description:
256 ////////////////////////////////////////////////////////////////////
257 void BulletCharacterControllerNode::
258 set_fall_speed(PN_stdfloat fall_speed) {
259 
260  _character->setFallSpeed((btScalar)fall_speed);
261 }
262 
263 ////////////////////////////////////////////////////////////////////
264 // Function: BulletCharacterControllerNode::set_jump_speed
265 // Access: Published
266 // Description:
267 ////////////////////////////////////////////////////////////////////
268 void BulletCharacterControllerNode::
269 set_jump_speed(PN_stdfloat jump_speed) {
270 
271  _character->setJumpSpeed((btScalar)jump_speed);
272 }
273 
274 ////////////////////////////////////////////////////////////////////
275 // Function: BulletCharacterControllerNode::set_max_jump_height
276 // Access: Published
277 // Description:
278 ////////////////////////////////////////////////////////////////////
279 void BulletCharacterControllerNode::
280 set_max_jump_height(PN_stdfloat max_jump_height) {
281 
282  _character->setMaxJumpHeight((btScalar)max_jump_height);
283 }
284 
285 ////////////////////////////////////////////////////////////////////
286 // Function: BulletCharacterControllerNode::set_max_slope
287 // Access: Published
288 // Description:
289 ////////////////////////////////////////////////////////////////////
290 void BulletCharacterControllerNode::
291 set_max_slope(PN_stdfloat max_slope) {
292 
293  _character->setMaxSlope((btScalar)max_slope);
294 }
295 
296 ////////////////////////////////////////////////////////////////////
297 // Function: BulletCharacterControllerNode::get_max_slope
298 // Access: Published
299 // Description:
300 ////////////////////////////////////////////////////////////////////
301 PN_stdfloat BulletCharacterControllerNode::
302 get_max_slope() const {
303 
304  return (PN_stdfloat)_character->getMaxSlope();
305 }
306 
307 ////////////////////////////////////////////////////////////////////
308 // Function: BulletCharacterControllerNode::get_gravity
309 // Description:
310 ////////////////////////////////////////////////////////////////////
311 PN_stdfloat BulletCharacterControllerNode::
312 get_gravity() const {
313 #if BT_BULLET_VERSION >= 285
314  return -(PN_stdfloat)_character->getGravity()[_up];
315 #else
316  return (PN_stdfloat)_character->getGravity();
317 #endif
318 }
319 
320 ////////////////////////////////////////////////////////////////////
321 // Function: BulletCharacterControllerNode::set_gravity
322 // Description:
323 ////////////////////////////////////////////////////////////////////
324 void BulletCharacterControllerNode::
325 set_gravity(PN_stdfloat gravity) {
326 #if BT_BULLET_VERSION >= 285
327  _character->setGravity(up_vectors[_up] * -(btScalar)gravity);
328 #else
329  _character->setGravity((btScalar)gravity);
330 #endif
331 }
332 
333 
334 ////////////////////////////////////////////////////////////////////
335 // Function: BulletCharacterControllerNode::set_use_ghost_sweep_test
336 // Description:
337 ////////////////////////////////////////////////////////////////////
338 void BulletCharacterControllerNode::
339 set_use_ghost_sweep_test(bool value) {
340 
341  return _character->setUseGhostSweepTest(value);
342 }
343 
A basic node of the scene graph or data graph.
Definition: pandaNode.h:72
This is the base class for all three-component vectors and points.
Definition: lvecBase3.h:105
bool almost_equal(const LMatrix4f &other, float threshold) const
Returns true if two matrices are memberwise equal within a specified tolerance.
Definition: lmatrix.cxx:879
This is a three-component vector distance (as opposed to a three-component point, which represents a ...
Definition: lvector3.h:100
This is a three-component point in space (as opposed to a three-component vector, which represents a ...
Definition: lpoint3.h:99
bool is_nan() const
Returns true if any component of the vector is not-a-number, false otherwise.
Definition: lvecBase3.h:464
void set_transform(const TransformState *transform, Thread *current_thread=Thread::get_current_thread())
Changes the complete transform object on this node.
Definition: nodePath.I:718
static NodePath any_path(PandaNode *node, Thread *current_thread=Thread::get_current_thread())
Returns a new NodePath that represents any arbitrary path from the root to the indicated node...
Definition: nodePath.I:77
This is a 4-by-4 transform matrix.
Definition: lmatrix.h:451
LVecBase3 get_scale() const
Retrieves the scale component of the transform.
Definition: nodePath.cxx:1331
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:85
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:165