Panda3D
physicsCollisionHandler.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 physicsCollisionHandler.cxx
10  * @author drose
11  * @date 2002-03-16
12  */
13 
15 #include "collisionNode.h"
16 #include "collisionEntry.h"
17 #include "collisionPolygon.h"
18 #include "config_collide.h"
19 #include "config_physics.h"
20 #include "actorNode.h"
21 #include "dcast.h"
22 
23 using std::cerr;
24 using std::endl;
25 
26 TypeHandle PhysicsCollisionHandler::_type_handle;
27 
28 /**
29  *
30  */
31 PhysicsCollisionHandler::
32 PhysicsCollisionHandler() {
33  _almost_stationary_speed = 0.1f;
34  _static_friction_coef=0.9f;
35  _dynamic_friction_coef=0.5f;
36  set_horizontal(false);
37 }
38 
39 /**
40  *
41  */
42 PhysicsCollisionHandler::
43 ~PhysicsCollisionHandler() {
44 }
45 
46 /**
47  * The vel parameter will be modified in place to account for friction.
48  */
49 void PhysicsCollisionHandler::
50 apply_friction(ColliderDef &def, LVector3& vel, const LVector3& force,
51  PN_stdfloat angle) {
52  if (vel!=LVector3::zero()) {
53  PN_stdfloat friction_coefficient=0.0f;
54  // Determine the friction:
55  if (vel.length()<_almost_stationary_speed) {
56  physics_debug(" static friction");
57  friction_coefficient=_static_friction_coef;
58  } else {
59  physics_debug(" dynamic friction");
60  friction_coefficient=_dynamic_friction_coef;
61  }
62  // Apply the friction:
63  physics_debug(" vel pre friction "<<vel<<" len "<<vel.length());
64  PN_stdfloat friction=friction_coefficient*angle;
65  physics_debug(" friction "<<friction);
66  if (friction<0.0f || friction>1.0f) {
67  cerr<<"\n\nfriction error "<<friction<<endl;
68  friction=1.0f;
69  }
70  #if 0
71  PN_stdfloat dt=ClockObject::get_global_clock()->get_dt();
72  vel *= (1.0f-friction) * dt * dt;
73  #else
74  vel *= 1.0f-friction;
75  #endif
76  physics_debug(" vel post friction "<<vel<<" len "<<vel.length());
77  }
78 }
79 
80 /**
81  *
82  */
83 void PhysicsCollisionHandler::
84 apply_net_shove(ColliderDef &def, const LVector3& net_shove,
85  const LVector3 &force) {
86  CollisionHandlerPusher::apply_net_shove(def, net_shove, force);
87  if (force == LVector3::zero()) {
88  return;
89  }
90  if (def._target.is_empty()) {
91  return;
92  }
93  ActorNode *actor;
94  DCAST_INTO_V(actor, def._target.node());
95  LVector3 vel=actor->get_physics_object()->get_velocity();
96  if (vel == LVector3::zero()) {
97  return;
98  }
99  physics_debug("apply_linear_force() {");
100  physics_debug(" vel "<<vel<<" len "<<vel.length());
101  physics_debug(" net_shove "<<net_shove<<" len "<<net_shove.length());
102  physics_debug(" force "<<force<<" len "<<force.length());
103  LVector3 old_vel=vel;
104 
105  // Copy the force vector while translating it into the physics object
106  // coordinate system:
107  LVector3 adjustment=force;
108  physics_debug(
109  " adjustment set "<<adjustment<<" len "<<adjustment.length());
110 
111  // NodePath np(def._node); CPT(TransformState) trans =
112  // np.get_net_transform(); adjustment=adjustment*trans->get_mat();
113  // physics_debug( " adjustment trn "<<adjustment<<" len
114  // "<<adjustment.length());
115 
116  adjustment=adjustment*actor->get_physics_object()->get_lcs();
117  physics_debug(
118  " adjustment lcs "<<adjustment<<" len "<<adjustment.length());
119 
120  adjustment.normalize();
121  physics_debug(
122  " adjustment nrm "<<adjustment<<" len "<<adjustment.length());
123 
124  PN_stdfloat adjustmentLength=-(adjustment.dot(vel));
125  physics_debug(" adjustmentLength "<<adjustmentLength);
126  PN_stdfloat angle=-normalize(old_vel).dot(normalize(force));
127  physics_debug(" angle "<<angle);
128  // Are we in contact with something:
129  if (angle>0.0f) {
130  physics_debug(" positive contact");
131  #if 0
132  cerr<<"vel "<<vel<<endl;
133  cerr<<"net_shove "<<net_shove<<endl;
134  cerr<<"force "<<force<<endl;
135  actor->get_physics_object()->add_impact(force, -vel);
136  #else
137  adjustment*=adjustmentLength;
138  physics_debug(
139  " adjustment mul "<<adjustment<<" len "<<adjustment.length());
140 
141  // This adjustment to our velocity will not reflect us off the surface,
142  // but will deflect us parallel (or tangent) to the surface:
143  vel+=adjustment;
144  physics_debug(" vel+adj "<<vel<<" len "<<vel.length());
145 
146  apply_friction(def, vel, force, angle);
147  #endif
148  } else if (adjustmentLength==0.0f) {
149  physics_debug(" brushing contact");
150  } else {
151  physics_debug(" negative contact");
152  }
153 
154  #ifndef NDEBUG //[
155  if (IS_THRESHOLD_EQUAL(vel.length(), old_vel.length(), 0.0001f)) {
156  // This is a check to see if vel is staying the same:
157  physics_debug(
158  " vel is about the same length: "
159  <<vel.length()<<" ~ "<<old_vel.length());
160  } else if (vel.length() > old_vel.length()) {
161  // This is a check to avoid adding engergy:
162  physics_debug(
163  " vel got larger "<<vel.length()<<" > "<<old_vel.length());
164  } else {
165  // This is a check to avoid losing engergy:
166  physics_debug(
167  " vel got smaller "<<vel.length()<<" < "<<old_vel.length());
168  }
169  if (vel.length() > 10.0f) {
170  // This is a check to see if the velocity is higher than I expect it to
171  // go. The check value is arbitrary.
172  physics_debug(" vel.length() > 10.0f "<<vel.length());
173  }
174  #endif //]
175 
176  physics_debug(" force "<<force<<" len "<<force.length());
177  physics_debug(" vel "<<vel<<" len "<<vel.length());
178  physics_debug("}");
179  actor->set_contact_vector(adjustment);
180  actor->get_physics_object()->set_velocity(vel);
181 }
182 
183 /**
184  *
185  */
186 void PhysicsCollisionHandler::
187 apply_linear_force(ColliderDef &def, const LVector3 &force) {
188 }
189 
190 /**
191  * Called internally to validate the target passed to add_collider(). Returns
192  * true if acceptable, false otherwise.
193  */
194 bool PhysicsCollisionHandler::
195 validate_target(const NodePath &target) {
196  if (!CollisionHandlerPhysical::validate_target(target)) {
197  return false;
198  }
199  nassertr_always(target.node()->is_of_type(ActorNode::get_class_type()), false);
200  return true;
201 }
static ClockObject * get_global_clock()
Returns a pointer to the global ClockObject.
Definition: clockObject.I:215
void set_velocity(const LVector3 &vel)
Vector velocity assignment.
Definition: physicsObject.I:75
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
LVector3 get_velocity() const
Velocity Query per second.
PandaNode * node() const
Returns the referenced node of the path.
Definition: nodePath.I:227
bool is_of_type(TypeHandle handle) const
Returns true if the current object is or derives from the indicated type.
Definition: typedObject.I:28
TypeHandle is the identifier used to differentiate C++ class types.
Definition: typeHandle.h:81
Like a physical node, but with a little more.
Definition: actorNode.h:26
virtual void add_impact(const LPoint3 &offset_from_center_of_mass, const LVector3 &impulse)
Adds an impulse and/or torque (i.e.
get_dt
Returns the elapsed time for the previous frame: the number of seconds elapsed between the last two c...
Definition: clockObject.h:99
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.
NodePath is the fundamental system for disambiguating instances, and also provides a higher-level int...
Definition: nodePath.h:161
virtual LMatrix4 get_lcs() const
returns a transform matrix to this object's local coordinate system.
PANDA 3D SOFTWARE Copyright (c) Carnegie Mellon University.