Panda3D
Loading...
Searching...
No Matches
bulletCharacterControllerNode.cxx
Go to the documentation of this file.
1/**
2 * PANDA 3D SOFTWARE
3 * Copyright (c) Carnegie Mellon University. All rights reserved.
4 *
5 * All use of this software is subject to the terms of the revised BSD
6 * license. You should have received a copy of this license along
7 * with this source code in a file named "LICENSE."
8 *
9 * @file bulletCharacterControllerNode.cxx
10 * @author enn0x
11 * @date 2010-11-21
12 */
13
15
16#include "config_bullet.h"
17
18#include "bulletWorld.h"
19
20#if BT_BULLET_VERSION >= 285
21static 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)};
22#endif
23
24TypeHandle BulletCharacterControllerNode::_type_handle;
25
26/**
27 *
28 */
29BulletCharacterControllerNode::
30BulletCharacterControllerNode(BulletShape *shape, PN_stdfloat step_height, const char *name) : BulletBaseCharacterControllerNode(name) {
31
32 // Synchronised transform
33 _sync = TransformState::make_identity();
34 _sync_disable = false;
35
36 // Initial transform
37 btTransform trans = btTransform::getIdentity();
38
39 // Get convex shape (for ghost object)
40 if (!shape->is_convex()) {
41 bullet_cat.error() << "a convex shape is required!" << std::endl;
42 return;
43 }
44
45 btConvexShape *convex = (btConvexShape *)(shape->ptr());
46
47 // Ghost object
48 _ghost = new btPairCachingGhostObject();
49 _ghost->setUserPointer(this);
50
51 _ghost->setWorldTransform(trans);
52 _ghost->setInterpolationWorldTransform(trans);
53 _ghost->setCollisionShape(convex);
54 _ghost->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
55
56 // Up axis
57 _up = get_default_up_axis();
58
59 // Initialise movement
60 _linear_movement_is_local = false;
61 _linear_movement.set(0.0f, 0.0f, 0.0f);
62 _angular_movement = 0.0f;
63
64 // Character controller
65#if BT_BULLET_VERSION >= 285
66 _character = new btKinematicCharacterController(_ghost, convex, step_height, up_vectors[_up]);
67 _character->setGravity(up_vectors[_up] * -(btScalar)9.81f);
68#else
69 _character = new btKinematicCharacterController(_ghost, convex, step_height, _up);
70 _character->setGravity((btScalar)9.81f);
71#endif
72
73 // Retain a pointer to the shape
74 _shape = shape;
75
76 // Default collide mask TODO set_into_collide_mask(CollideMask::all_on());
77}
78
79/**
80 *
81 */
82void BulletCharacterControllerNode::
83set_linear_movement(const LVector3 &movement, bool is_local) {
84 LightMutexHolder holder(BulletWorld::get_global_lock());
85
86 nassertv(!movement.is_nan());
87
88 _linear_movement = movement;
89 _linear_movement_is_local = is_local;
90}
91
92/**
93 *
94 */
95void BulletCharacterControllerNode::
96set_angular_movement(PN_stdfloat omega) {
97 LightMutexHolder holder(BulletWorld::get_global_lock());
98
99 _angular_movement = omega;
100}
101
102/**
103 * Assumes the lock(bullet global lock) is held by the caller
104 */
106do_sync_p2b(PN_stdfloat dt, int num_substeps) {
107
108 // Synchronise global transform
109 do_transform_changed();
110
111 // Angular rotation
112 btScalar angle = dt * deg_2_rad(_angular_movement);
113
114 btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
115 btVector3 up = m[_up];
116
117 m *= btMatrix3x3(btQuaternion(up, angle));
118
119 _ghost->getWorldTransform().setBasis(m);
120
121 // Linear movement
122 LVector3 vp = _linear_movement / (btScalar)num_substeps;
123
124 btVector3 v;
125 if (_linear_movement_is_local) {
126 btTransform xform = _ghost->getWorldTransform();
127 xform.setOrigin(btVector3(0.0f, 0.0f, 0.0f));
128 v = xform(LVecBase3_to_btVector3(vp));
129 }
130 else {
131 v = LVecBase3_to_btVector3(vp);
132 }
133
134 // _character->setVelocityForTimeInterval(v, dt);
135 _character->setWalkDirection(v * dt);
136 _angular_movement = 0.0f;
137}
138
139/**
140 * Assumes the lock(bullet global lock) is held by the caller
141 */
143do_sync_b2p() {
144
146 LVecBase3 scale = np.get_net_transform()->get_scale();
147
148 btTransform trans = _ghost->getWorldTransform();
149 CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);
150
151 LMatrix4 m_sync = _sync->get_mat();
152 LMatrix4 m_ts = ts->get_mat();
153
154 if (!m_sync.almost_equal(m_ts)) {
155 _sync = ts;
156 _sync_disable = true;
157 np.set_transform(NodePath(), ts);
158 _sync_disable = false;
159 }
160}
161
162/**
163 * Assumes the lock(bullet global lock) is held by the caller
164 */
165void BulletCharacterControllerNode::
166do_transform_changed() {
167
168 if (_sync_disable) return;
169
171 CPT(TransformState) ts = np.get_net_transform();
172
173 LMatrix4 m_sync = _sync->get_mat();
174 LMatrix4 m_ts = ts->get_mat();
175
176 if (!m_sync.almost_equal(m_ts)) {
177 _sync = ts;
178
179 // Get translation, heading and scale
180 LPoint3 pos = ts->get_pos();
181 PN_stdfloat heading = ts->get_hpr().get_x();
182 LVecBase3 scale = ts->get_scale();
183
184 // Set translation
185 _character->warp(LVecBase3_to_btVector3(pos));
186
187 // Set Heading
188 btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
189 btVector3 up = m[_up];
190
191 m = btMatrix3x3(btQuaternion(up, deg_2_rad(heading)));
192
193 _ghost->getWorldTransform().setBasis(m);
194
195 // Set scale
196 _shape->do_set_local_scale(scale);
197 }
198}
199
200/**
201 *
202 */
203void BulletCharacterControllerNode::
204transform_changed() {
205
206 if (_sync_disable) return;
207
208 LightMutexHolder holder(BulletWorld::get_global_lock());
209
210 do_transform_changed();
211}
212
213/**
214 *
215 */
216BulletShape *BulletCharacterControllerNode::
217get_shape() const {
218
219 return _shape;
220}
221
222/**
223 *
224 */
225bool BulletCharacterControllerNode::
226is_on_ground() const {
227 LightMutexHolder holder(BulletWorld::get_global_lock());
228
229 return _character->onGround();
230}
231
232/**
233 *
234 */
235bool BulletCharacterControllerNode::
236can_jump() const {
237 LightMutexHolder holder(BulletWorld::get_global_lock());
238
239 return _character->canJump();
240}
241
242/**
243 *
244 */
245void BulletCharacterControllerNode::
246do_jump() {
247 LightMutexHolder holder(BulletWorld::get_global_lock());
248
249 _character->jump();
250}
251
252/**
253 *
254 */
255void BulletCharacterControllerNode::
256set_fall_speed(PN_stdfloat fall_speed) {
257 LightMutexHolder holder(BulletWorld::get_global_lock());
258
259 _character->setFallSpeed((btScalar)fall_speed);
260}
261
262/**
263 *
264 */
265void BulletCharacterControllerNode::
266set_jump_speed(PN_stdfloat jump_speed) {
267 LightMutexHolder holder(BulletWorld::get_global_lock());
268
269 _character->setJumpSpeed((btScalar)jump_speed);
270}
271
272/**
273 *
274 */
275void BulletCharacterControllerNode::
276set_max_jump_height(PN_stdfloat max_jump_height) {
277 LightMutexHolder holder(BulletWorld::get_global_lock());
278
279 _character->setMaxJumpHeight((btScalar)max_jump_height);
280}
281
282/**
283 *
284 */
285void BulletCharacterControllerNode::
286set_max_slope(PN_stdfloat max_slope) {
287 LightMutexHolder holder(BulletWorld::get_global_lock());
288
289 _character->setMaxSlope((btScalar)max_slope);
290}
291
292/**
293 *
294 */
295PN_stdfloat BulletCharacterControllerNode::
296get_max_slope() const {
297 LightMutexHolder holder(BulletWorld::get_global_lock());
298
299 return (PN_stdfloat)_character->getMaxSlope();
300}
301
302/**
303 *
304 */
305PN_stdfloat BulletCharacterControllerNode::
306get_gravity() const {
307 LightMutexHolder holder(BulletWorld::get_global_lock());
308
309#if BT_BULLET_VERSION >= 285
310 return -(PN_stdfloat)_character->getGravity()[_up];
311#else
312 return (PN_stdfloat)_character->getGravity();
313#endif
314}
315
316/**
317 *
318 */
319void BulletCharacterControllerNode::
320set_gravity(PN_stdfloat gravity) {
321 LightMutexHolder holder(BulletWorld::get_global_lock());
322
323#if BT_BULLET_VERSION >= 285
324 _character->setGravity(up_vectors[_up] * -(btScalar)gravity);
325#else
326 _character->setGravity((btScalar)gravity);
327#endif
328}
329
330/**
331 *
332 */
333void BulletCharacterControllerNode::
334set_use_ghost_sweep_test(bool value) {
335 LightMutexHolder holder(BulletWorld::get_global_lock());
336
337 return _character->setUseGhostSweepTest(value);
338}
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
virtual void do_sync_p2b(PN_stdfloat dt, int num_substeps)
Assumes the lock(bullet global lock) is held by the caller.
virtual void do_sync_b2p()
Assumes the lock(bullet global lock) is held by the caller.
Similar to MutexHolder, but for a light mutex.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition nodePath.h:159
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:62
LVecBase3 get_scale() const
Retrieves the scale component of the transform.
const LMatrix4 & get_mat() const
Returns the transform matrix that has been applied to the referenced node, or the identity matrix if ...
Definition nodePath.I:776
void set_transform(const TransformState *transform, Thread *current_thread=Thread::get_current_thread())
Changes the complete transform object on this node.
Definition nodePath.I:565
A basic node of the scene graph or data graph.
Definition pandaNode.h:65
virtual void xform(const LMatrix4 &mat)
Transforms the contents of this PandaNode by the indicated matrix, if it means anything to do so.
Indicates a coordinate-system transform on vertices.
TypeHandle is the identifier used to differentiate C++ class types.
Definition typeHandle.h:81
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.