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