small collision detection problem

Started by manumoi, December 13, 2005, 10:48:45 PM

Previous topic - Next topic

manumoi

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

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 :


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?


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

EgonOlsen

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.

manumoi

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:


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


[...]
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

EgonOlsen

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):

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);
 }
}

manumoi

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

manumoi

oups, by COLLISION_ELLIPSOID, i wanted to say ELLIPSOID_RADIUS :?

manu

EgonOlsen

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!?

manumoi

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