From 247e79cccedd8a0c31a39d6b7eca50b9cd1e6e59 Mon Sep 17 00:00:00 2001 From: Dave Schuyler Date: Fri, 12 May 2006 23:13:15 +0000 Subject: [PATCH] work in progress --- direct/src/controls/ShipPilot2.py | 69 ++++++++++- panda/src/collide/collisionSphere.cxx | 158 +++++++++++++++++--------- 2 files changed, 168 insertions(+), 59 deletions(-) diff --git a/direct/src/controls/ShipPilot2.py b/direct/src/controls/ShipPilot2.py index fec676f968..09aeb000f0 100755 --- a/direct/src/controls/ShipPilot2.py +++ b/direct/src/controls/ShipPilot2.py @@ -29,6 +29,8 @@ class ShipPilot2(PhysicsWalker): 'want-avatar-physics-indicator', 0) useBowSternSpheres = 1 + useOneSphere = 0 + useDSSolid = 0 useLifter = 0 useHeightRay = 0 @@ -73,7 +75,7 @@ class ShipPilot2(PhysicsWalker): self.avatarControlRotateSpeed=rotate def getSpeeds(self): - #assert(self.debugPrint("getSpeeds()")) + #assert self.debugPrint("getSpeeds()") return (self.__speed, self.__rotationSpeed) def setAvatar(self, ship): @@ -91,7 +93,7 @@ class ShipPilot2(PhysicsWalker): if not hasattr(ship, "acceleration"): self.ship.acceleration = 60 self.ship.maxSpeed = 14 - self.ship.reverseAcceleration = 10 + self.ship.reverseAcceleration = 30 self.ship.maxReverseSpeed = 2 self.ship.turnRate = 3 self.ship.maxTurn = 30 @@ -235,6 +237,55 @@ class ShipPilot2(PhysicsWalker): shipCollWall = self.avatarNodePath.hull.find("**/collision_hull") if not shipCollWall.isEmpty(): shipCollWall.stash() + elif self.useOneSphere: + # Front sphere: + self.cSphere = CollisionSphere(0.0, 0.0, -5.0, avatarRadius) + cSphereNode = CollisionNode('SP.cSphereNode') + cSphereNode.addSolid(self.cSphere) + self.cSphereNodePath = self.avatarNodePath.attachNewNode( + cSphereNode) + if 1: + self.cSphereNodePath.show() + self.cSphereNodePath.showBounds() + + cSphereNode.setFromCollideMask(self.cSphereBitMask) + cSphereNode.setIntoCollideMask(BitMask32.allOff()) + + self.cSphereNode = cSphereNode + + self.pusher.addCollider( + self.cSphereNodePath, self.avatarNodePath) + + # hide other things on my ship that these spheres might collide + # with and which I dont need anyways... + shipCollWall = self.avatarNodePath.hull.find("**/collision_hull") + if not shipCollWall.isEmpty(): + shipCollWall.stash() + elif self.useDSSolid: + # DSSolid: + self.cHull = CollisionDSSolid( + Point3(-160, 0, 0), 200, Point3(160, 0, 0), 200, + Plane(Vec3(0, 0, 1), Point3(0, 0, 50)), + Plane(Vec3(0, -1, 0), Point3(0, -90, 0))) + cHullNode = CollisionNode('SP.cHullNode') + cHullNode.addSolid(self.cHull) + self.cHullNodePath = self.avatarNodePath.attachNewNode( + cHullNode) + self.cHullNodePath.show() + + cHullNode.setFromCollideMask(bitmask) + cHullNode.setIntoCollideMask(BitMask32.allOff()) + + self.cHullNode = cHullNode + + self.pusher.addCollider( + self.cHullNodePath, self.avatarNodePath) + + # hide other things on my ship that these spheres might collide + # with and which I dont need anyways... + shipCollWall = self.avatarNodePath.hull.find("**/collision_hull") + if not shipCollWall.isEmpty(): + shipCollWall.stash() def takedownPhysics(self): assert self.debugPrint("takedownPhysics()") @@ -366,7 +417,7 @@ class ShipPilot2(PhysicsWalker): print "failed load of physics indicator" def avatarPhysicsIndicator(self, task): - #assert(self.debugPrint("avatarPhysicsIndicator()")) + #assert self.debugPrint("avatarPhysicsIndicator()") # Velocity: self.physVelocityIndicator.setPos(self.avatarNodePath, 0.0, 0.0, 6.0) physObject=self.actorNode.getPhysicsObject() @@ -392,9 +443,12 @@ class ShipPilot2(PhysicsWalker): self.collisionsActive = active if active: if self.useBowSternSpheres: - #self.cTrav.addCollider(self.cSphereNodePath, self.pusher) self.cTrav.addCollider(self.cBowSphereNodePath, self.pusher) self.cTrav.addCollider(self.cSternSphereNodePath, self.pusher) + elif self.useOneSphere: + self.cTrav.addCollider(self.cSphereNodePath, self.pusher) + elif self.useDSSolid: + self.cTrav.addCollider(self.cHullNodePath, self.pusher) if self.useHeightRay: if self.useLifter: self.cTrav.addCollider(self.cRayNodePath, self.lifter) @@ -402,9 +456,12 @@ class ShipPilot2(PhysicsWalker): self.cTrav.addCollider(self.cRayNodePath, self.cRayQueue) else: if self.useBowSternSpheres: - #self.cTrav.removeCollider(self.cSphereNodePath) self.cTrav.removeCollider(self.cBowSphereNodePath) self.cTrav.removeCollider(self.cSternSphereNodePath) + elif self.useOneSphere: + self.cTrav.removeCollider(self.cSphereNodePath) + elif self.useDSSolid: + self.cTrav.removeCollider(self.cHullNodePath) if self.useHeightRay: self.cTrav.removeCollider(self.cRayNodePath) # Now that we have disabled collisions, make one more pass @@ -520,7 +577,7 @@ class ShipPilot2(PhysicsWalker): base.localAvatar.getPos().pPrintValues(),)) onScreenDebug.append("localAvatar hpr = %s\n"%( base.localAvatar.getHpr().pPrintValues(),)) - #assert(self.debugPrint("handleAvatarControls(task=%s)"%(task,))) + #assert self.debugPrint("handleAvatarControls(task=%s)"%(task,)) physObject=self.actorNode.getPhysicsObject() contact=self.actorNode.getContactVector() diff --git a/panda/src/collide/collisionSphere.cxx b/panda/src/collide/collisionSphere.cxx index 74e68f2223..6c6128dc39 100644 --- a/panda/src/collide/collisionSphere.cxx +++ b/panda/src/collide/collisionSphere.cxx @@ -136,7 +136,7 @@ PT(BoundingVolume) CollisionSphere:: compute_internal_bounds() const { return new BoundingSphere(_center, _radius); } -#define USE_DS_SOLID_PLANES 0 +#define USE_DS_SOLID_PLANES 1 //////////////////////////////////////////////////////////////////// // Function: CollisionSphere::test_intersection_from_ds_solid // Access: Public, Virtual @@ -149,7 +149,6 @@ test_intersection_from_ds_solid(const CollisionEntry &entry) const { cerr<<"CollisionSphere::test_intersection_from_ds_solid\n"; CPT(TransformState) wrt_space = entry.get_wrt_space(); - const LMatrix4f &wrt_mat = wrt_space->get_mat(); LPoint3f into_center = get_center(); @@ -180,72 +179,125 @@ test_intersection_from_ds_solid(const CollisionEntry &entry) const { } #if USE_DS_SOLID_PLANES - float pa_distance = ds_solid->dist_to_plane_a(into_center); - if (pa_distance > into_radius) { + CPT(TransformState) inv_wrt_space = entry.get_inv_wrt_space(); + const LMatrix4f &inv_wrt_mat = inv_wrt_space->get_mat(); + + LPoint3f inv_into_center = get_center() * inv_wrt_mat; + float inv_into_radius = length( + LVector3f(get_radius(), 0.0f, 0.0f) * inv_wrt_mat); + + float pa_distance = + ds_solid->dist_to_plane_a(inv_into_center) - inv_into_radius; + if (pa_distance > 0.0f) { // No intersection. return NULL; } - float pb_distance = ds_solid->dist_to_plane_b(into_center); - if (pb_distance > into_radius) { + float pb_distance = + ds_solid->dist_to_plane_b(inv_into_center) - inv_into_radius; + if (pb_distance > 0.0f) { // No intersection. return NULL; } #endif + LVector3f lens_center = ds_solid->get_collision_origin() * wrt_mat; + float lens_radius = length( + LVector3f(ds_solid->get_lens_radius(), 0.0f, 0.0f) * wrt_mat); + LVector3f lens_vec = lens_center - into_center; + float lens_distance_squared = dot(lens_vec, lens_vec); + + LVector3f surface_normal; // into + //LPoint3f surface_point; // into + LPoint3f interior_point; // from + float sa_distance = sqrtf(sa_distance_squared) - sa_radius; + float sb_distance = sqrtf(sb_distance_squared) - sb_radius; + pa_distance = ds_solid->dist_to_plane_a(inv_into_center); + pb_distance = ds_solid->dist_to_plane_b(inv_into_center); + #if USE_DS_SOLID_PLANES + cerr + <<" sa_distance:"< pa_distance && sa_distance > pb_distance) || + (sb_distance > pa_distance && sb_distance > pb_distance)) { + #else + cerr + <<" sa_distance:"< sb_distance) { + // sphere_a is the furthest + cerr<<"sphere_a is the furthest\n"; + primary_vec = &sa_vec; + primary_center = &sa_center; + primary_radius = sa_radius; + secondary_center = &sb_center; + secondary_radius = sb_radius; + } else { + // sphere_b is the furthest + cerr<<"sphere_b is the furthest\n"; + primary_vec = &sb_vec; + primary_center = &sb_center; + primary_radius = sb_radius; + secondary_center = &sa_center; + secondary_radius = sa_radius; + } + + float vec_length = primary_vec->length(); + if (IS_NEARLY_ZERO(vec_length)) { + // The centers are coincident, use an arbitrary normal. + surface_normal.set(1.0, 0.0, 0.0); + } else { + // Lens face + surface_normal = *primary_vec / vec_length; + } + interior_point = *primary_center - surface_normal * primary_radius; + + float temp_length_squared = + (interior_point - *secondary_center).length_squared(); + if (temp_length_squared > (secondary_radius * secondary_radius)) { + cerr<<"foo\n"; + LVector3f a = (*primary_center - lens_center).normalize(); + LVector3f b = + cross(cross(a, (into_center - lens_center).normalize()), a).normalize(); + interior_point = lens_center + b * lens_radius; + surface_normal = (interior_point - into_center).normalize(); + } + #if USE_DS_SOLID_PLANES + } else { + if (pa_distance > pb_distance) { + // plane_a is the furthest + cerr<<"plane_a is the furthest\n"; + surface_normal = -(ds_solid->get_plane_a().get_normal() * wrt_mat); + float d = length( + LVector3f(pa_distance, 0.0f, 0.0f) * wrt_mat); + interior_point = into_center + surface_normal * d; + } else { + // plane_b is the furthest + cerr<<"plane_b is the furthest\n"; + //surface_normal = -(ds_solid->get_plane_b().get_normal() * wrt_mat); + surface_normal = -ds_solid->get_plane_b().get_normal(); + surface_normal = surface_normal * wrt_mat; + float d = length( + LVector3f(pb_distance, 0.0f, 0.0f) * wrt_mat); + interior_point = into_center + surface_normal * d; + } + } + #endif + if (collide_cat.is_debug()) { collide_cat.debug() << "intersection detected from " << entry.get_from_node_path() << " into " << entry.get_into_node_path() << "\n"; } - LVector3f surface_normal; // into - LPoint3f surface_point; // into - LPoint3f interior_point; // from - float spheres = sqrtf(sa_distance_squared) - sqrtf(sb_distance_squared); - #if USE_DS_SOLID_PLANES - float planes = pa_distance - pb_distance; - if (spheres > planes) { - #endif - if (spheres > 0) { - // sphere_a is the furthest - cerr<<"sphere_a is the furthest"<<"\n"; - float vec_length = sa_vec.length(); - if (IS_NEARLY_ZERO(vec_length)) { - // The centers are coincident, use an arbitrary normal. - surface_normal.set(1.0, 0.0, 0.0); - } else { - surface_normal = sa_vec / vec_length; - } - interior_point = sa_center - surface_normal * sa_radius; - } else { - // sphere_b is the furthest - cerr<<"sphere_b is the furthest"<<"\n"; - float vec_length = sb_vec.length(); - if (IS_NEARLY_ZERO(vec_length)) { - // The centers are coincident, use an arbitrary normal. - surface_normal.set(1.0, 0.0, 0.0); - } else { - surface_normal = sb_vec / vec_length; - } - interior_point = sb_center - surface_normal * sb_radius; - } - #if USE_DS_SOLID_PLANES - } else { - if (planes > 0) { - // plane_a is the furthest - cerr<<"plane_a is the furthest"<<"\n"; - surface_normal = ds_solid->get_plane_a().get_normal(); - interior_point = into_center - surface_normal * pa_distance; - } else { - // plane_b is the furthest - cerr<<"plane_b is the furthest"<<"\n"; - surface_normal = ds_solid->get_plane_b().get_normal(); - interior_point = into_center - surface_normal * pb_distance; - } - } - #endif - PT(CollisionEntry) new_entry = new CollisionEntry(entry); new_entry->set_surface_normal(surface_normal); new_entry->set_surface_point(into_center + surface_normal * into_radius);