Projectile Collision Detection

I have the following code:

            Transform3D localToVWorld = new Transform3D();
            this.getTransform(localToVWorld);  //was getlocalToVWorld();
            bounds = box.getBounds();
            bounds.transform(localToVWorld);

where box is an object that extneds Shape3D and has 24 vertices. It has a BoundingBox shell as well.
then later…

         public boolean hasCollided(GameObject obj) {
            if(bounds.intersect(obj.getShell())) {
                  return true;
            }
            else {
                  return false;
            }
            
      }

where getShell() rerturns the box’s boundingbox.
This code seems to work 50/50. If an opponent moves x distance away, every shot may collide, then another x distance and all shots pass right thru. Rotate 3 degrees and voila, hits again, rotate a littler further and pass thru. AM I not properly updated the boundingbox location? This is true detection and not avoidance.
Thanks

bounds = box.getBounds();
bounds.transform(localToVWorld);

I think that you are stepping on xith3d toes here, by modifying it’s internal bounds. You should create your own copy of bounds and then play with it.

actually it is my own, pure java3d, no xith. I create my opwn bounds, then transform it, then apply it to the actual object shape3d.

From what I see here I cannot guess what might be wrong.

Generally working with bound requires some in-depth thinking. Normally the local bounds of an object it static, so I wonder what you mean by [quote]I create my opwn bounds, then transform it, then apply it to the actual object shape3d.
[/quote]
What kind of bounds does getShell() return? Global, local? With ‘this.getLocalToVWorld()’ … who is ‘this’? And where is it located in the scenegraph with respect to the bounds that is transformed?

My apologies, did kinda skimp on the code details…here is the class:

package server;

import javax.media.j3d.*;
import javax.vecmath.*;

public abstract class GameObject extends TransformGroup {

      float x,y,z;
      double rotation;
      int objID;

      private double adjust = 2.356194490192345;

      private double moveRate = 0.2;
        private double speed = 0.7;

      Transform3D tf;
      Vector3f loc;
      Transform3D rotator;
      Matrix3d m;
      Box box;
      Bounds bounds;
      BranchGroup parent = null;
      boolean parentIsSet = false;
      CollisionDetector cd;
      BoundingSphere cBounds;

      public static ServerUniverseManager universe;

      GameObject(int id, float xx, float yy, float zz, double rot, Box b, int type) {
            objID = id;
            x = xx;
            y = yy;
            z = zz;
            rotation = rot;
            box = b;
            box.setCapability(Shape3D.ALLOW_GEOMETRY_READ);

            this.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
            this.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
            this.setCapability(Node.ALLOW_LOCAL_TO_VWORLD_READ);
            this.addChild(box);
            bounds = box.getBounds();
            //cd = new CollisionDetector(this);
            //cBounds = new BoundingSphere(new Point3d(0.0,0.0,0.0), Double.POSITIVE_INFINITY);
            //cd.setSchedulingBounds(cBounds);

            tf = new Transform3D();
            loc = new Vector3f();
            rotator = new Transform3D();
            m = new Matrix3d();
            universe.addGameObject(this, type);
            //universe.addWorldObject(cd);
            if(this.isLive()) {
                  setLocation(x,y,z,rotation);
            }

      }

      public static void setUniverse(ServerUniverseManager u) {
            universe = u;
      }

      protected void setParent(BranchGroup bg) {
            parent = bg;
            parentIsSet = true;
      }

      protected boolean hasParent() {
            return parentIsSet;
      }

      protected boolean removeMe(int type) {
            if(hasParent()) {
                  parent.detach();
                  System.out.println("detached from parent on server...");
                  universe.removeGameObject(this, type);
                  return true;
            }
            return false;
      }

      protected boolean removeMe(int type, String msg) {
                  if(hasParent()) {
                        parent.detach();
                        System.out.println(msg);
                        universe.removeGameObject(this, type);
                        return true;
                  }
                  return false;
      }

      protected int getObjID() {
            return objID;
      }

      protected boolean match(int id) {
            return id == objID;
      }

      //public TransformGroup getTG() {
      //      return group;
      //}
      public Shape3D getShape() {
            return box;
      }

      public Bounds getShell() {
            return bounds;
      }

      public void setLocation(float x, float y, float z, double rot) {
            rotation = rot;
            rotator.rotY(rot);
            tf.setTranslation(new Vector3f(x,y,z));
            // now rotate the transform
            tf.mul(rotator);
            // aplly to transform group so shape3d is moved for collision detection
            this.setTransform(tf);
            //set new location into Vector3f and Matrix3d
            tf.get(loc);
            tf.get(m);
            //now set the transform to the bounding box
            //getShell().transform(tf);
            Transform3D localToVWorld = new Transform3D();
            this.getTransform(localToVWorld);  //was getlocalToVWorld();
            bounds = box.getBounds();
            bounds.transform(localToVWorld);
            getShell().set(bounds);
            //System.out.println(getShell().toString());
      }

      public float getX() {
            return loc.x;
      }

      public float getY() {
            return loc.y;
      }

      public float getZ() {
            return loc.z;
      }

      public double getRot() {
            //return (double)Math.atan2 (m.m22 - m.m02, m.m20 - m.m00) - adjust;
            return rotation;
      }

      public void doMove(Vector3d theMove) {
            Transform3D toMove = new Transform3D();
            toMove.setTranslation(theMove);
            tf.mul(toMove);
            this.setTransform(tf);
            tf.get(loc);
            tf.get(m);
            //now set the transform to the bounding box
            //getShell().transform(tf);
            Transform3D localToVWorld = new Transform3D();
            this.getTransform(localToVWorld);  //was getlocalToVWorld();
            bounds = box.getBounds();
            bounds.transform(localToVWorld);
            getShell().set(bounds);
            //System.out.println(bounds.toString());
      }

        protected void moveForward()
        {
          doMove(new Vector3d(0.0,0.0, -getMovementRate()));
        }

         protected double getMovementRate()
    {
       return moveRate * speed;
        }

         public void setMovementRate(double meters)
         {
           moveRate = meters; // Travel rate in meters/frame
         }

      public CollisionDetector getCollider() {
            return cd;
      }

         // collision detection???
         public boolean hasCollided(GameObject obj) {
            if(bounds.intersect(obj.getShell())) {
                  return true;
            }
            else {
                  return false;
            }
            //System.out.println("This: " + getX() + " other: " + obj.getX());
            //if(getX() == obj.getX() && getZ() == obj.getZ())
            //      return true;
            //return false;
      }


//eof
}

The code from my first post is call the above class to get the bounds.

Again, Box is a Shape3d that I do this in:

      BoundingPolytope poly = null;
      BoundingBox shell = null;
      shell = new BoundingBox(verts[0], verts[7]); // was 4  16
      poly = new BoundingPolytope(shell);
      setBounds(poly);

from 24 verts of a quadarray.

Did you try slowing down your bullets? Perhaps they move too fast and pass through other objects without collision.

That is not an issue with java3d cause it can detect collisions by expanding a cylinder from the players pos to the new pos. So whatever the speed it takes, if that cylinder collides with anything then its not a free movement.

When talking generally about a different approach, I suggest using the pick utility. Thats the way the FlyingGuns machinegun works.

so you run a short pick ray in front of the projectile?

Yes and no … FlyingGuns bullets are of an ‘immediate hit’ type (highly valuable in network handling!). So I have a long pick ray starting at the weapon.

In any case the pick rays should be longer than the distance a bullet can make during one frame :slight_smile:

long pick ray = if ray crosses target, its a hit?

Projectile should have a ray that is 1 meter long if you move half meter per frame…

[quote]long pick ray = if ray crosses target, its a hit?
[/quote]
Yes. Very easy.

… if the projectile moves half a meter…