22 TypeHandle CollisionHandlerFluidPusher::_type_handle;
27 CollisionHandlerFluidPusher::
28 CollisionHandlerFluidPusher() {
29 _wants_all_potential_collidees =
true;
38 nassertv(entry !=
nullptr);
45 if (entry->
get_from()->is_tangible() &&
59 bool CollisionHandlerFluidPusher::
103 FromEntries::iterator fei;
104 for (fei = _from_entries.begin(); fei != _from_entries.end(); ++fei) {
105 NodePath from_node_path = fei->first;
106 Entries *orig_entries = &fei->second;
108 Colliders::iterator ci;
109 ci = _colliders.
find(from_node_path);
110 if (ci == _colliders.end()) {
114 <<
"CollisionHandlerFluidPusher doesn't know about "
115 << from_node_path <<
", disabling.\n";
118 ColliderDef &def = (*ci).second;
124 Entries entries(*orig_entries);
133 const LPoint3 orig_pos(from_node_path.
get_pos(wrt_node));
135 const LPoint3 orig_prev_pos(prev_trans->get_pos());
139 DCAST_INTO_R(sphere, entries.front()->get_from(),
false);
141 from_node_path.set_pos(wrt_node, 0,0,0);
142 LPoint3 sphere_offset = (sphere->get_center() *
144 from_node_path.set_pos(wrt_node, orig_pos);
147 LPoint3 candidate_final_pos(orig_pos);
149 LPoint3 uncollided_pos(candidate_final_pos);
152 LVector3 reverse_vec(-M);
153 reverse_vec.normalize();
163 Entries::const_iterator cei;
164 for (cei = entries.begin(); cei != entries.end(); ++cei) {
166 nassertr(entry !=
nullptr,
false);
180 LVector3 contact_normal;
183 collide_cat.warning()
184 <<
"Cannot shove on " << from_node_path <<
" for collision into "
189 contact_pos -= sphere_offset;
191 uncollided_pos = candidate_final_pos;
192 candidate_final_pos = contact_pos;
194 LVector3 proj_surface_normal(contact_normal);
196 LVector3 norm_proj_surface_normal(proj_surface_normal);
197 norm_proj_surface_normal.normalize();
199 LVector3 blocked_movement(uncollided_pos - contact_pos);
201 PN_stdfloat push_magnitude(-blocked_movement.dot(proj_surface_normal));
202 if (push_magnitude < 0.0f) {
204 candidate_final_pos = contact_pos;
208 candidate_final_pos = uncollided_pos + (norm_proj_surface_normal * push_magnitude);
211 from_node_path.set_pos(wrt_node, candidate_final_pos);
213 prev_trans = prev_trans->set_pos(contact_pos);
214 from_node_path.set_prev_transform(wrt_node, prev_trans);
226 Entries::iterator ei;
228 for (ei = entries.begin(); ei != entries.end(); ++ei) {
230 nassertr(entry !=
nullptr,
false);
233 entry->_from_node_path = from_node_path;
236 if (result !=
nullptr && result !=
nullptr) {
237 new_entries.push_back(result);
241 entries.swap(new_entries);
245 from_node_path.set_pos(wrt_node, orig_pos);
248 prev_trans = prev_trans->set_pos(orig_prev_pos);
249 from_node_path.set_prev_transform(wrt_node, prev_trans);
251 LVector3 net_shove(candidate_final_pos - orig_pos);
252 LVector3 force_normal(net_shove);
253 force_normal.normalize();
256 def._target.set_pos(wrt_node, candidate_final_pos);
260 apply_net_shove(def, net_shove, force_normal);
261 apply_linear_force(def, force_normal);