Author Topic: small collision detection problem  (Read 3733 times)

Offline manumoi

  • long
  • ***
  • Posts: 121
    • View Profile
    • http://www.iro.umontreal.ca/~blanchae
small collision detection problem
« on: December 13, 2005, 10:48:45 pm »
Hello, long time i haven t post anything... I m back on my jpct project and try to fix some small bugs.

I have this one:
When i want to have some gravity effects, I use this lines (more or less taken from one of JPCT demos
Code: [Select]

public void placeModel(){
SimpleVector dropDown = this.getYAxis();
Matrix rotMat = this.getRotationMatrix();
rotMat.setIdentity();
this.setRotationMatrix(rotMat);
this.rotateY(yRot);
distanceToGround = terrain.calcMinDistance(this.getTransformedCenter(), new SimpleVector(0,1,0), 4*30);
if (distanceToGround!= Object3D.COLLISION_NONE){
   dropDown.scalarMul(distanceToGround+LEG_SIZE);
   
}
this.translate(dropDown);
    }


It makes me the model fit perfectly with the ground but  it also affects my movements (i.e. whether i push forward or backward,  i always go in the same direction)

Here are my forward and backward functions :

Code: [Select]

private void moveForward(){
SimpleVector a = this.getZAxis();
a.scalarMul(5f);
a = this.checkForCollisionEllipsoid(a,ELLIPSOID_RADIUS, 5);
this.translate(a);
animating=true;
    }

    private void moveBackward(){
SimpleVector a = this.getZAxis();
a.scalarMul(-3f);
a = this.checkForCollisionEllipsoid(a,ELLIPSOID_RADIUS, 5);
this.translate(a);
animating = true;
    }



When i suppress the following lines from my placeModel function, i have no problem with my movements, but (of course) no gravity. Do you see where my mistake is?

Code: [Select]

terrain.calcMinDistance(this.getTransformedCenter(), new SimpleVector(0,1,0), 4*30);
if (distanceToGround!= Object3D.COLLISION_NONE){
   dropDown.scalarMul(distanceToGround+LEG_SIZE);
   
}

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11745
    • View Profile
    • http://www.jpct.net
Re: small collision detection problem
« Reply #1 on: December 14, 2005, 01:04:48 am »
Quote from: "manumoi"
i.e. whether i push forward or backward,  i always go in the same direction
Which direction is that? I can't see something obviously wrong in your code ATM.

Offline manumoi

  • long
  • ***
  • Posts: 121
    • View Profile
    • http://www.iro.umontreal.ca/~blanchae
small collision detection problem
« Reply #2 on: December 14, 2005, 04:46:31 am »
hello egon, thanks for answering so quickly...(must be midnight in germany :? )
The direction is the south compared to the first orientation of the model...
I can rotate the model without problem, and this rotation will affect the direction but whether i push forward or backward, the model will always go more or less south (depending on the z axis of the object)...
Here is the constructor. Maybe it can help:

Code: [Select]

public Player(Object3D obj, WorldInterface worldInterface, String playerName){
super(obj); // the md2 object
this.setCollisionMode(Object3D.COLLISION_CHECK_SELF|Object3D.COLLISION_CHECK_OTHERS);
this.setCollisionOptimization(Object3D.COLLISION_DETECTION_OPTIMIZED);
this.rotateY((float)Math.PI*1.5f);
this.rotateMesh();
this.build();
this.setRotationMatrix(new Matrix());

this.worldInterface = worldInterface;
this.playerName = playerName;

this.keyMapper = worldInterface.getKeyMapper();
this.terrain = worldInterface.getTerrain();
this.theWorld = worldInterface.getTheWorld();
theWorld.addObject(this);
this.placeModel();
this.setSelectable(Object3D.MOUSE_SELECTABLE);
SimpleVector v = this.getTransformedCenter();
v.add(lightShift);
this.myLight = theWorld.addLight(v, 0f,0f,0f);
}


And here is the code i call in my game loop to update the model

Code: [Select]

[...]
if (mainPlayer){
   theWorld.setLightIntensity(myLight,50,50,50);
   x = this.getTransformedCenter().x;
   z = this.getTransformedCenter().z;  
   poll();
   moveModel(); // basically it calls the correct function depending on the keys pressed detected in poll()
}
[...]
placeModel(); // in my previous post
[...]

Maybe it is related with getTransformedCenter().z?

Manu

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11745
    • View Profile
    • http://www.jpct.net
small collision detection problem
« Reply #3 on: December 14, 2005, 08:52:21 pm »
Yes, midnight...but that's not a problem. I'm only sleeping around 5-6 hours during the week anyway... :wink:

To your problem: I can't spot anything wrong in the code you've posted (that doesn't mean that there isn't, of course). So i did a quick and dirty modification of another example to mimic this behaviour and it works fine for me. Here is the code (maybe it's helpful to find out what's wrong with your code):

Code: [Select]
import com.threed.jpct.*;
import org.lwjgl.opengl.*;
import java.awt.event.*;
import com.threed.jpct.util.*;

public class MoveTest {

  public static void main(String[] args) throws Exception {
    MoveTest mt = new MoveTest();
    mt.doIt();
  }

  private void doIt() throws Exception {
    FrameBuffer fb = new FrameBuffer(640, 480,
                                     FrameBuffer.SAMPLINGMODE_HARDWARE_ONLY);
    fb.disableRenderer(IRenderer.RENDERER_SOFTWARE);
    fb.enableRenderer(IRenderer.RENDERER_OPENGL);

    World w = new World();
    w.setAmbientLight(255, 255, 255);

    TextureManager tm = TextureManager.getInstance();
    Texture base = new Texture("base.jpg");
    Texture decal = new Texture("decal.jpg");

    tm.addTexture("base", base);
    tm.addTexture("decal", decal);

    int bid = tm.getTextureID("base");
    int did = tm.getTextureID("decal");

    Object3D plane = new Object3D(9);
    plane.setCulling(Object3D.CULLING_DISABLED);

    int bs = 0;

    // Base texture only
    TextureInfo tInf1 = new TextureInfo(bid, -1, -1, 2, -1, -1, 2);
    TextureInfo tInf2 = new TextureInfo(bid, 2, -1, 2, 2, -1, 2);
    plane.addTriangle(new SimpleVector( -10, -10, 30),
                      new SimpleVector( -10, 0, 30),
                      new SimpleVector(0, -10, 30), tInf1);
    plane.addTriangle(new SimpleVector( -10, 0, 30), new SimpleVector(0, 0, 25),
                      new SimpleVector(0, -10, 30), tInf2);

    // 2nd stage used, modulate
    tInf1 = new TextureInfo(bid, 0, 0, 1, 0, 0, 1);
    tInf1.add(did, 0, 0, 1, 0, 0, 1, TextureInfo.MODE_MODULATE);
    tInf2 = new TextureInfo(bid, 1, 0, 1, 1, 0, 1);
    tInf2.add(did, 1, 0, 1, 1, 0, 1, TextureInfo.MODE_MODULATE);
    plane.addTriangle(new SimpleVector(0, -10, 30), new SimpleVector(0, 0, 25),
                      new SimpleVector(10, -10, 30), tInf1);
    plane.addTriangle(new SimpleVector(0, 0, 25), new SimpleVector(10, 0, 30),
                      new SimpleVector(10, -10, 30), tInf2);

    // 2nd stage used, add
    tInf1 = new TextureInfo(bid, 0, 0, 1, 0, 0, 1);
    tInf1.add(did, 0, 0, 1, 0, 0, 1, TextureInfo.MODE_ADD);
    tInf2 = new TextureInfo(bid, 1, 0, 1, 1, 0, 1);
    tInf2.add(did, 1, 0, 1, 1, 0, 1, TextureInfo.MODE_ADD);
    plane.addTriangle(new SimpleVector( -10, 0, 30),
                      new SimpleVector( -10, 10, 30), new SimpleVector(0, 0, 25),
                      tInf1);
    plane.addTriangle(new SimpleVector( -10, 10, 30),
                      new SimpleVector(0, 10, 30), new SimpleVector(0, 0, 25),
                      tInf2);

    // 2nd stage used, blend
    tInf1 = new TextureInfo(bid, 0, 0, 1, 0, 0, 1);
    tInf1.add(did, 0, 0, 1, 0, 0, 1, TextureInfo.MODE_BLEND);
    tInf2 = new TextureInfo(bid, 1, 0, 1, 1, 0, 1);
    tInf2.add(did, 1, 0, 1, 1, 0, 1, TextureInfo.MODE_BLEND);
    plane.addTriangle(new SimpleVector(0, 0, 25), new SimpleVector(0, 10, 30),
                      new SimpleVector(10, 0, 30), tInf1);
    plane.addTriangle(new SimpleVector(0, 10, 30), new SimpleVector(10, 10, 30),
                      new SimpleVector(10, 0, 30), tInf2);

    plane.rotateX( (float) Math.PI / 2f);
    plane.rotateMesh();
    plane.setRotationMatrix(new Matrix());
    w.addObject(plane);
    plane.build();

    Object3D o2 = Primitives.getCone(0.25f);
    o2.rotateX( (float) Math.PI / 2f);
    o2.rotateMesh();
    o2.setRotationMatrix(new Matrix());

    w.addObject(o2);
    o2.setOrigin(plane.getTransformedCenter());
    o2.translate(0, -10, 0);
    o2.build();

    plane.setCollisionMode(Object3D.COLLISION_CHECK_OTHERS);
    o2.setCollisionMode(Object3D.COLLISION_CHECK_SELF);

    w.getCamera().moveCamera(Camera.CAMERA_MOVEOUT, 10);
    w.getCamera().moveCamera(Camera.CAMERA_MOVEDOWN, 10);
    w.getCamera().lookAt(o2.getOrigin());

    KeyMapper km = new KeyMapper();
    float yRot = 0;
    SimpleVector elr = new SimpleVector(0.25f, 0.25f, 0.25f);

    while (!Display.isCloseRequested()) {
      int key = 0;
      KeyState keys = null;

      // place
      SimpleVector dd = new SimpleVector(0, 1, 0);
      float dist = plane.calcMinDistance(o2.getTransformedCenter(), dd, 40);
      if (dist != Object3D.COLLISION_NONE) {
        dd.scalarMul(dist - 0.5f);
        o2.translate(dd);
      }

      // rotateY
      o2.getRotationMatrix().setIdentity();
      o2.rotateY(yRot);

      if ( (bs & 1) == 1) {
        yRot += 0.1f;
      }
      if ( (bs & 2) == 2) {
        yRot -= 0.1f;
      }

      //move
      if ( (bs & 4) == 4) {
        SimpleVector a = o2.getZAxis();
        a.scalarMul(0.25f);
        a = o2.checkForCollisionEllipsoid(a, elr, 5);
        o2.translate(a);
      }

      if ( (bs & 8) == 8) {
        SimpleVector a = o2.getZAxis();
        a.scalarMul( -0.25f);
        a = o2.checkForCollisionEllipsoid(a, elr, 5);
        o2.translate(a);
      }

      do {
        keys = km.poll();
        if (keys != KeyState.NONE) {
          key = keys.getKeyCode();
          if (key == KeyEvent.VK_W) {
            bs ^= 4;
          }
          if (key == KeyEvent.VK_S) {
            bs ^= 8;
          }
          if (key == KeyEvent.VK_A) {
            bs ^= 2;
          }
          if (key == KeyEvent.VK_D) {
            bs ^= 1;
          }
        }
      }
      while (keys != KeyState.NONE);

      fb.clear();
      w.renderScene(fb);
      w.draw(fb);
      fb.displayGLOnly();

      Thread.sleep(10);
    }

    km.destroy();
    fb.disableRenderer(IRenderer.RENDERER_OPENGL);
    System.exit(0);
  }
}

Offline manumoi

  • long
  • ***
  • Posts: 121
    • View Profile
    • http://www.iro.umontreal.ca/~blanchae
small collision detection problem
« Reply #4 on: December 15, 2005, 11:20:16 pm »
Hello Egon, thanks to your example, i finally found what caused the bug,
It was the COLLISION_ELLIPSOID parameter that is in my call to checkForCollisionEllipsoid. I changed it for a SimpleVector i defined myself and the problem is no more. But i don t understand why it resulted in a so strange behaviour. Any idea?

Manu

Offline manumoi

  • long
  • ***
  • Posts: 121
    • View Profile
    • http://www.iro.umontreal.ca/~blanchae
small collision detection problem
« Reply #5 on: December 15, 2005, 11:25:52 pm »
oups, by COLLISION_ELLIPSOID, i wanted to say ELLIPSOID_RADIUS :?

manu

Offline EgonOlsen

  • Administrator
  • quad
  • *****
  • Posts: 11745
    • View Profile
    • http://www.jpct.net
small collision detection problem
« Reply #6 on: December 15, 2005, 11:30:34 pm »
Maybe it was so large, that it intersected with the floor after applying the gravity translation (maybe because you are adding the LEG_SIZE instead of subtracting it...or is it negative?). An ellipsoid should never intersect any geometry when calling the method. The ellipsoid collision detection is a collision avoidance algorithm...it isn't very good in moving out of an existing collision. Maybe the strange movement that you've experienced was it's pityful attempt to move you of this intersection!?

Offline manumoi

  • long
  • ***
  • Posts: 121
    • View Profile
    • http://www.iro.umontreal.ca/~blanchae
small collision detection problem
« Reply #7 on: December 16, 2005, 12:02:18 am »
yes LEG_SIZE was negative (in fact i made it positive to make everything more understandable).
I think also it was something like what you said... Anyway, it works just fine and that's cool :P

Thanks

Manu