Chase cam that doesn't pass through walls?

Does anyone have a general approach they can describe for making a chase-camera avoid passing through walls, while still following an object?



I have the basic chase-cam working and it follows a spaceship around nicely. The ship has an attachment point set at some units behind it and the camera is attached to that point with a spring to smooth out the ride (the attachment point can also be positioned in front, above, etc for different POV). However, I haven't figured out a decent way to make the camera avoid going through walls (or asteroids). I want to fly through tunnels in the asteriods so it's important that the camera not be obscured by the walls. I'm using physics and collisions for the ship, so I tried a few different things like a physics node around the camera too, but the spring can still drag the camera through an object where it then gets stuck. Or the camera can get stuck around a corner if the ship turns a corner too sharply. Maybe I'm going about this the wrong way…

an easy and common way is to just zoom the camera when something get in the way. cast a ray from the ship to the camera(either with jme collisions or using odephysics) and get the collision point…then interpolate the camera pos to that position…

Thanks, that's just what I needed. It was easy and it works pretty good.  :smiley:



Maybe this snippet will help someone if they search for this someday…


   /**
    * Move camPos closer to subject to avoid obstruction by the scene.
    *
    * @param subject what camera is looking at
    * @param scene the scene root
    * @param camPos translation of camera relative to subject
    * @param pov preferred translation of camera relative to subject
    */
   public void avoidCamObstruction(Node subject, Node scene, Vector3f pov, Vector3f camPos) {
      ray.getOrigin().set(subject.getWorldTranslation());
      ray.getDirection().set(pov);
      ray.getDirection().normalizeLocal();

      pickResults.clear();
      scene.calculatePick(ray, pickResults);
      boolean blocked = false;
      for (int p = 0; p < pickResults.getNumber(); p++) {
         PickData picked = pickResults.getPickData(p);
         Spatial parent = picked.getTargetMesh().getParentGeom().getParent();
         if (parent != subject) {
            if (picked.getDistance() <= pov.length()) {
               camPos.normalizeLocal().multLocal(picked.getDistance() - 0.25f);
               blocked = true;
            }
            break;
         }
      }
      if (! blocked) {
         camPos.set(pov);
      }
   }


This looks like it would work great for my program, not sure quite how to get it working in my program.



Should it be called every update?



Ray is com.jme.math.Ray? and do I have to add anything or can i just initialise

 Ray ray = new ray()





how do it set up the pickresults for usesage in this?


picked.getTargetMesh().getParentGeom().getParent();

does not work for JME2?

Alot of questions, hope they can be answered. or if anyone knows a link to an example of this or somthing that has same/similar results.

Thanks

I have the same problem and tried out the code above. It is not really compatible to JME2, so I tried my best to update it. With more or less afford. I was able to get the PickResults and do something with them. But there is a problem I haven't solved yet: What to to with the camera when I determined the nearest obstacle between player and camera?? I tried several things and they had all something in common: The camera "bounced" from the new location back into the Spatials. Then it was translated to the designated point again and so on… very ugly to look at, btw.



Here is my code, if anyone would have a guess what to do, I would be very happy.


Vector3f camloc = chaser.getCamera().getWorldCoordinates(new Vector2f(320, 240), 0);
Vector3f playloc = player.getNode().getWorldTranslation().clone();
      
Ray ray = new Ray();
ray.origin = playloc;
ray.direction = camloc.clone();
ray.direction.normalizeLocal();
   
PickResults results = new TrianglePickResults();
rootNode.calculatePick(ray, results);
      

float minDist = 1000;
PickData minP = null;
      
for (int i = 0; i < results.getNumber(); i++) {
   PickData p = results.getPickData(i);
   Vector3f pPos = p.getTargetMesh().getWorldTranslation();
   Spatial pParent = p.getTargetMesh().getParent();
   float dist = FastMath.abs(playloc.distance(pPos));         
         
   if (dist < FastMath.abs(camloc.distance(playloc))) {
      if (pParent != player.getNode() && pParent != player.getOrientNode()
         && pParent.getParent() != skyboxNode && !pParent.getName().equals("particles")) {
               
         if (dist < minDist) {
            minDist = dist;
            minP = p;
         }
               
      }
   }
}      
if (minP != null) {
   if (FastMath.abs(camloc.distance(playloc)) > 15f) {
      chaser.getCamera().setLocation(chaser.getCamera().getLocation().normalize().mult(minDist * .5f));
   }
}




The really tricky part seems to be this line:

chaser.getCamera().setLocation(chaser.getCamera().getLocation().normalize().mult(minDist * .5f));

Hi all.I have same problem

              In  which class pickResults is?

Use an IDE that has searching.

Eclipse - CTRL+H

Netbeans - CTRL+F