00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "bulletCharacterControllerNode.h"
00016
00017 TypeHandle BulletCharacterControllerNode::_type_handle;
00018
00019
00020
00021
00022
00023
00024 BulletCharacterControllerNode::
00025 BulletCharacterControllerNode(BulletShape *shape, PN_stdfloat step_height, const char *name) : BulletBaseCharacterControllerNode(name) {
00026
00027
00028 _sync = TransformState::make_identity();
00029 _sync_disable = false;
00030
00031
00032 btTransform trans = btTransform::getIdentity();
00033
00034
00035 if (!shape->is_convex()) {
00036 bullet_cat.error() << "a convex shape is required!" << endl;
00037 return;
00038 }
00039
00040 btConvexShape *convex = (btConvexShape *)(shape->ptr());
00041
00042
00043 _ghost = new btPairCachingGhostObject();
00044 _ghost->setUserPointer(this);
00045
00046 _ghost->setWorldTransform(trans);
00047 _ghost->setInterpolationWorldTransform(trans);
00048 _ghost->setCollisionShape(convex);
00049 _ghost->setCollisionFlags(btCollisionObject::CF_CHARACTER_OBJECT);
00050
00051
00052 _up = get_default_up_axis();
00053
00054
00055 _linear_movement_is_local = false;
00056 _linear_movement.set(0.0f, 0.0f, 0.0f);
00057 _angular_movement = 0.0f;
00058
00059
00060 _character = new btKinematicCharacterController(_ghost, convex, step_height, _up);
00061 _character->setGravity((btScalar)9.81f);
00062
00063
00064 _shape = shape;
00065
00066
00067
00068 }
00069
00070
00071
00072
00073
00074
00075 void BulletCharacterControllerNode::
00076 set_linear_movement(const LVector3 &movement, bool is_local) {
00077
00078 nassertv(!movement.is_nan());
00079
00080 _linear_movement = movement;
00081 _linear_movement_is_local = is_local;
00082 }
00083
00084
00085
00086
00087
00088
00089 void BulletCharacterControllerNode::
00090 set_angular_movement(PN_stdfloat omega) {
00091
00092 _angular_movement = omega;
00093 }
00094
00095
00096
00097
00098
00099
00100 void BulletCharacterControllerNode::
00101 sync_p2b(PN_stdfloat dt, int num_substeps) {
00102
00103
00104 transform_changed();
00105
00106
00107 btScalar angle = dt * deg_2_rad(_angular_movement);
00108
00109 btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
00110 btVector3 up = m[_up];
00111
00112 m *= btMatrix3x3(btQuaternion(up, angle));
00113
00114 _ghost->getWorldTransform().setBasis(m);
00115
00116
00117 LVector3 vp = _linear_movement / (btScalar)num_substeps;
00118
00119 btVector3 v;
00120 if (_linear_movement_is_local) {
00121 btTransform xform = _ghost->getWorldTransform();
00122 xform.setOrigin(btVector3(0.0f, 0.0f, 0.0f));
00123 v = xform(LVecBase3_to_btVector3(vp));
00124 }
00125 else {
00126 v = LVecBase3_to_btVector3(vp);
00127 }
00128
00129
00130 _character->setWalkDirection(v * dt);
00131 _angular_movement = 0.0f;
00132 }
00133
00134
00135
00136
00137
00138
00139 void BulletCharacterControllerNode::
00140 sync_b2p() {
00141
00142 NodePath np = NodePath::any_path((PandaNode *)this);
00143 LVecBase3 scale = np.get_net_transform()->get_scale();
00144
00145 btTransform trans = _ghost->getWorldTransform();
00146 CPT(TransformState) ts = btTrans_to_TransformState(trans, scale);
00147
00148 LMatrix4 m_sync = _sync->get_mat();
00149 LMatrix4 m_ts = ts->get_mat();
00150
00151 if (!m_sync.almost_equal(m_ts)) {
00152 _sync = ts;
00153 _sync_disable = true;
00154 np.set_transform(NodePath(), ts);
00155 _sync_disable = false;
00156 }
00157 }
00158
00159
00160
00161
00162
00163
00164 void BulletCharacterControllerNode::
00165 transform_changed() {
00166
00167 if (_sync_disable) return;
00168
00169 NodePath np = NodePath::any_path((PandaNode *)this);
00170 CPT(TransformState) ts = np.get_net_transform();
00171
00172 LMatrix4 m_sync = _sync->get_mat();
00173 LMatrix4 m_ts = ts->get_mat();
00174
00175 if (!m_sync.almost_equal(m_ts)) {
00176 _sync = ts;
00177
00178
00179 LPoint3 pos = ts->get_pos();
00180 PN_stdfloat heading = ts->get_hpr().get_x();
00181 LVecBase3 scale = ts->get_scale();
00182
00183
00184 _character->warp(LVecBase3_to_btVector3(pos));
00185
00186
00187 btMatrix3x3 m = _ghost->getWorldTransform().getBasis();
00188 btVector3 up = m[_up];
00189
00190 m = btMatrix3x3(btQuaternion(up, heading));
00191
00192 _ghost->getWorldTransform().setBasis(m);
00193
00194
00195 _shape->set_local_scale(scale);
00196 }
00197 }
00198
00199
00200
00201
00202
00203
00204 BulletShape *BulletCharacterControllerNode::
00205 get_shape() const {
00206
00207 return _shape;
00208 }
00209
00210
00211
00212
00213
00214
00215 bool BulletCharacterControllerNode::
00216 is_on_ground() const {
00217
00218 return _character->onGround();
00219 }
00220
00221
00222
00223
00224
00225
00226 bool BulletCharacterControllerNode::
00227 can_jump() const {
00228
00229 return _character->canJump();
00230 }
00231
00232
00233
00234
00235
00236
00237 void BulletCharacterControllerNode::
00238 do_jump() {
00239
00240 _character->jump();
00241 }
00242
00243
00244
00245
00246
00247
00248 void BulletCharacterControllerNode::
00249 set_fall_speed(PN_stdfloat fall_speed) {
00250
00251 _character->setFallSpeed((btScalar)fall_speed);
00252 }
00253
00254
00255
00256
00257
00258
00259 void BulletCharacterControllerNode::
00260 set_jump_speed(PN_stdfloat jump_speed) {
00261
00262 _character->setJumpSpeed((btScalar)jump_speed);
00263 }
00264
00265
00266
00267
00268
00269
00270 void BulletCharacterControllerNode::
00271 set_max_jump_height(PN_stdfloat max_jump_height) {
00272
00273 _character->setMaxJumpHeight((btScalar)max_jump_height);
00274 }
00275
00276
00277
00278
00279
00280
00281 void BulletCharacterControllerNode::
00282 set_max_slope(PN_stdfloat max_slope) {
00283
00284 _character->setMaxSlope((btScalar)max_slope);
00285 }
00286
00287
00288
00289
00290
00291
00292 PN_stdfloat BulletCharacterControllerNode::
00293 get_max_slope() const {
00294
00295 return (PN_stdfloat)_character->getMaxSlope();
00296 }
00297
00298
00299
00300
00301
00302 PN_stdfloat BulletCharacterControllerNode::
00303 get_gravity() const {
00304
00305 return (PN_stdfloat)_character->getGravity();
00306 }
00307
00308
00309
00310
00311
00312 void BulletCharacterControllerNode::
00313 set_gravity(PN_stdfloat gravity) {
00314
00315 _character->setGravity((btScalar)gravity);
00316 }
00317
00318
00319
00320
00321
00322
00323 void BulletCharacterControllerNode::
00324 set_use_ghost_sweep_test(bool value) {
00325
00326 return _character->setUseGhostSweepTest(value);
00327 }
00328