Non Physic Collision Detection

Hi, basially I just wanted to ask, if I either realyl misunderstand the concept of the Collision System or if it is extremly limited so far:



I only can collide a geometry with a Ray, or SweepSphere with ray/Geometry?

Also if anyone here has any experience how to do a non physic collision detection it would be nice to share.

Yeah, there's no triangle vs. triangle collision, because that requires advanced handling for the collision response. Why do you not want to use JBullet physics engine to resolve collisions?

You should be able to use the GhostNodes in jbullet to have the objects unaffected by the physics but still deliver collision information.

Well I#m still trying to parent physic objects, wich is why i cant use Jbullet directly and simple.



Imagine a spaceship physica with jbullet, then imagine person running in artifical gravity field inside it, then you know my problem trying to do this with jbullet directly. My idea was to create for the player a kinda pseudo physic, but as it seems while jME2 still has the hascollision stuff in JME3 only ray geometry works fine :confused:



Currently I'm in the process of thinking about ways to make the player without that stuff and kinda stuck.



My minimum target is around 100 spaceships having each a own gravityfield(or in jbullet terms own discretWorld), seems like a really overkill in terms of memory and cpu usage (Non the less, i will try it later today  just to amke sure I don't miss a maybee elegant solution)



So any ideas are welcome :slight_smile:



Minimum requirements:

Player unable to go through walls,

4 or more floors possible in one spaeship, connected via elevators or ramps

Obstacles on the ground.



I already thought about using a 2d engine for each of the floors, but still think about how to implement and generate the collision polygons


Empire Phoenix said:

Well I#m still trying to parent physic objects, wich is why i cant use Jbullet directly and simple.

When you just use GhostNodes parenting should work since the locations are only updated from jme to the physics.

Really? So the positions are updated and i am able to get collisions with like other ghostnodes (eg box on floor of spaceship)?? If so this si the solution :slight_smile: Will test after university stuff is done :slight_smile:

Just wanted to build a proove of concept test, but having one weird problem:



I create 100 boxes wich fall on a large static box, works fine usually,

but always a few like 2-5 are able to teleport through my ground.



public class SolarSystem extends SimplePhysicsApplication {

   public static void main(String[] args){
      SolarSystem lol = new SolarSystem();
      lol.start();
   }

   @Override
   public void simpleInitApp() {
      this.flyCam.setMoveSpeed(50);
      
      Box boxmesh = new Box(Vector3f.ZERO,1000,10f,1000);
      Geometry boxgeom = new Geometry("Box",boxmesh);
      
      Material mat = new Material(manager, "plain_texture.j3md");
        TextureKey key = new TextureKey("Monkey.jpg", true);
        key.setGenerateMips(true);
        Texture tex = manager.loadTexture(key);
        tex.setMinFilter(Texture.MinFilter.Trilinear);
        mat.setTexture("m_ColorMap", tex);
        boxgeom.setMaterial(mat);
      
      PhysicsNode ground = new PhysicsNode(boxgeom,new MeshCollisionShape(boxgeom.getMesh()),0);
      ground.setLocalTranslation(0,-30,0);
      ground.updateModelBound();
      ground.updateGeometricState();
      this.rootNode.attachChild(ground);
      getPhysicsSpace().addQueued(ground);

      
      Box boxmesh2 = new Box(Vector3f.ZERO,1,1,1);
      BoxCollisionShape boxshape = new BoxCollisionShape(new Vector3f(1,1,1));
      int i = 100;
      while(i>0){
         Geometry boxgeom2 = new Geometry("Box2",boxmesh2);
         PhysicsNode box = new PhysicsNode(boxgeom2,boxshape,100);
         box.setLocalTranslation(FastMath.nextRandomFloat()*100-50,20+FastMath.nextRandomFloat()*100,FastMath.nextRandomFloat()*100-50);
         box.setMaterial(mat);
         box.updateModelBound();
         box.updateGeometricState();
         this.rootNode.attachChild(box);
         getPhysicsSpace().addQueued(box);
         i--;
      }
   }
   
 
}

Empire Phoenix said:

I create 100 boxes wich fall on a large static box, works fine usually,

The "large" in that sentence might actually be the problem. Since the CollisionShape of the floor box not of type BoxCollisionShape but MeshCollisionShape dont wonder, meshes with very few vertexes that are far away from each other will almost certainly cause problems. Only use MeshCollisionShape if its really about a mesh, I know the floor in the example is also used as a mesh but it is only to test the functionality.

Edit: Does the collision detection via GhostNodes work btw?

Actually not tested so far, first wanted to find out if I do something terribly wrong, will do next evening, should really sleep now ^^



Ok, tested witha 100x100, no problems anymore, so I probably won't have any problems in real when using 1-1 scale for jme-meters.



Also ca it be that moving objects do not support the MeshCollisionShape?

When i create them like this they always move just through, or do I need to create movingMeshs in another way?



I also wonder why your physicspace uses SimpleBraodphase as standart? Even with the above example but 3k boxes the Axis_Sweep is around 16times faster, even it it is desigend for static interactions. Don#t get me wrong the simple has in termas of memory usage clear advantages, but usually every other is several times faster, so it might be a good idea to set a faster one as default.


package de.empirephoenix;

import com.bulletphysics.collision.shapes.BoxShape;
import com.jme3.app.PhysicsApplication;
import com.jme3.app.SimplePhysicsApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.nodes.PhysicsNode;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.material.Material;
import com.jme3.math.FastMath;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.texture.Texture;



public class SolarSystem extends SimplePhysicsApplication {

   public static void main(String[] args){
      SolarSystem lol = new SolarSystem();
      lol.start();
   }

   @Override
   public void simpleInitApp() {
      this.flyCam.setMoveSpeed(50);
      
      Box boxmesh = new Box(Vector3f.ZERO,100,10f,100);
      Geometry boxgeom = new Geometry("Box",boxmesh);
      
      Material mat = new Material(manager, "plain_texture.j3md");
        TextureKey key = new TextureKey("Monkey.jpg", true);
        key.setGenerateMips(true);
        Texture tex = manager.loadTexture(key);
        tex.setMinFilter(Texture.MinFilter.Trilinear);
        mat.setTexture("m_ColorMap", tex);
        boxgeom.setMaterial(mat);
      
      PhysicsNode ground = new PhysicsNode(boxgeom,new MeshCollisionShape(boxgeom.getMesh()),0);
      ground.setLocalTranslation(0,-30,0);
      ground.updateModelBound();
      ground.updateGeometricState();
      this.rootNode.attachChild(ground);
      getPhysicsSpace().addQueued(ground);

      
      Box lol = new Box(Vector3f.ZERO,1,1,1);
      Geometry boxgeom3 = new Geometry("Box",lol);
      MeshCollisionShape boxshape = new MeshCollisionShape(boxgeom3.getMesh());
      int i = 100;
      while(i>0){
         Geometry boxgeom2 = new Geometry("Box2",lol);
         PhysicsNode box = new PhysicsNode(boxgeom2,boxshape,100);
         box.setLocalTranslation(FastMath.nextRandomFloat()*100-50,20+FastMath.nextRandomFloat()*100,FastMath.nextRandomFloat()*100-50);
         box.setMaterial(mat);
         box.updateModelBound();
         box.updateGeometricState();
         this.rootNode.attachChild(box);
         getPhysicsSpace().addQueued(box);
         i--;
      }
   }
   
  
}

With the latest revision, the DBVT broadphase is used which is better than both simple and axis sweep.

The MeshCollisionShape won't work for dynamic meshes, only static. You gotta generate some kind of more optimized structure if using dynamic physics nodes, maybe normen can elaborate (?). I guess it goes back to the fact that handling triangle vs. triangle collision is extremely difficult, whereas triangle vs. simple shapes or convex meshes is a lot easier.

The broadphase can more easily be changed by the user in the future and for Mesh->Mesh collision you can use GImpact shapes for the movable meshes, should work. Still, as momoko indicated using a CompoundCollisionShape with simple (box,sphere) child shapes to only outline your model will probably yield more performance.

Yay it works kinda:



This works (well it gives a collision dispatcher warning over static static needs dispatcher) but :





package de.empirephoenix;

import com.bulletphysics.collision.shapes.BoxShape;
import com.jme3.app.PhysicsApplication;
import com.jme3.app.SimplePhysicsApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.nodes.PhysicsGhostNode;
import com.jme3.bullet.nodes.PhysicsNode;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.material.Material;
import com.jme3.math.FastMath;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.shape.Box;
import com.jme3.texture.Texture;



public class SolarSystem extends SimplePhysicsApplication {

   public static void main(String[] args){
      SolarSystem lol = new SolarSystem();
      lol.setMultithreaded(false);
      lol.start();
   }

   private PhysicsGhostNode box;

   @Override
   public void simpleInitApp() {
      this.flyCam.setMoveSpeed(50);
      
      Box boxmesh = new Box(Vector3f.ZERO,100,10f,100);
      Geometry boxgeom = new Geometry("Box",boxmesh);
      
      Material mat = new Material(manager, "plain_texture.j3md");
        TextureKey key = new TextureKey("Monkey.jpg", true);
        key.setGenerateMips(true);
        Texture tex = manager.loadTexture(key);
        tex.setMinFilter(Texture.MinFilter.Trilinear);
        mat.setTexture("m_ColorMap", tex);
        boxgeom.setMaterial(mat);
      
      PhysicsNode ground = new PhysicsNode(boxgeom,new BoxCollisionShape(new Vector3f(100,10,100)),0);
      ground.setLocalTranslation(0,-30,0);
      ground.updateModelBound();
      ground.updateGeometricState();
      this.rootNode.attachChild(ground);
      getPhysicsSpace().addQueued(ground);

      
      Box boxmesh2 = new Box(Vector3f.ZERO,1,1,1);
      BoxCollisionShape boxshape = new BoxCollisionShape(new Vector3f(1,1,1));

      Geometry boxgeom2 = new Geometry("Box2",boxmesh2);
      box = new PhysicsGhostNode(boxgeom2,boxshape);
      box.setLocalTranslation(FastMath.nextRandomFloat()*100-50,20+FastMath.nextRandomFloat()*100,FastMath.nextRandomFloat()*100-50);
      box.setMaterial(mat);
      box.updateModelBound();
      box.updateGeometricState();
      this.rootNode.attachChild(box);
      getPhysicsSpace().addQueued(box);
   }
   
   @Override
   public void update(){
      super.update();
      Transform t = box.getTransform();
      Vector3f l = t.getTranslation();
      l.y -= 0.05f;
      t.setTranslation(l);
      box.setTransform(t);
   }
 
}



Parented like this it does not work for some reason:


package de.empirephoenix;

import com.bulletphysics.collision.shapes.BoxShape;
import com.jme3.app.PhysicsApplication;
import com.jme3.app.SimplePhysicsApplication;
import com.jme3.asset.TextureKey;
import com.jme3.bullet.collision.shapes.BoxCollisionShape;
import com.jme3.bullet.collision.shapes.MeshCollisionShape;
import com.jme3.bullet.collision.shapes.SphereCollisionShape;
import com.jme3.bullet.nodes.PhysicsGhostNode;
import com.jme3.bullet.nodes.PhysicsNode;
import com.jme3.font.BitmapFont;
import com.jme3.font.BitmapText;
import com.jme3.material.Material;
import com.jme3.math.FastMath;
import com.jme3.math.Quaternion;
import com.jme3.math.Transform;
import com.jme3.math.Vector3f;
import com.jme3.scene.Geometry;
import com.jme3.scene.Node;
import com.jme3.scene.shape.Box;
import com.jme3.texture.Texture;



public class SolarSystem extends SimplePhysicsApplication {

   public static void main(String[] args){
      SolarSystem lol = new SolarSystem();
      lol.setMultithreaded(false);
      lol.start();
   }

   private PhysicsGhostNode box;
   private Node tester;

   @Override
   public void simpleInitApp() {
      this.flyCam.setMoveSpeed(50);
      
      Box boxmesh = new Box(Vector3f.ZERO,100,10f,100);
      Geometry boxgeom = new Geometry("Box",boxmesh);
      
      Material mat = new Material(manager, "plain_texture.j3md");
        TextureKey key = new TextureKey("Monkey.jpg", true);
        key.setGenerateMips(true);
        Texture tex = manager.loadTexture(key);
        tex.setMinFilter(Texture.MinFilter.Trilinear);
        mat.setTexture("m_ColorMap", tex);
        boxgeom.setMaterial(mat);
      
      PhysicsNode ground = new PhysicsNode(boxgeom,new BoxCollisionShape(new Vector3f(100,10,100)),0);
      ground.setLocalTranslation(0,-30,0);
      ground.updateModelBound();
      ground.updateGeometricState();
      this.rootNode.attachChild(ground);
      getPhysicsSpace().addQueued(ground);

      
      Box boxmesh2 = new Box(Vector3f.ZERO,1,1,1);
      BoxCollisionShape boxshape = new BoxCollisionShape(new Vector3f(1,1,1));

      tester = new Node();
      
      
      
      Geometry boxgeom2 = new Geometry("Box2",boxmesh2);
      box = new PhysicsGhostNode(boxgeom2,boxshape);
      box.setLocalTranslation(0,30,0);
      box.setMaterial(mat);
      box.updateModelBound();
      box.updateGeometricState();
      this.tester.attachChild(box);
      this.rootNode.attachChild(tester);
      
      
      getPhysicsSpace().addQueued(box);
   }
   
   @Override
   public void update(){
      super.update();
      Quaternion bla = tester.getLocalRotation();
      float[] storage = new float[3];
      bla.toAngles(storage);
      storage[0]+=0.001f;
      bla.fromAngles(storage);
      tester.setLocalRotation(bla);
   }
 
}

Does it work when you remove the updateGeometricState() call? Because it is used when the spatial has no parent, it might set wrong values in the physics ghostnode. You should not need it there anyway.

Hm, nope seems ot to help

Empire Phoenix said:

Hm, nope seems ot to help

How does it not work?

Wee it jsut moves through without any inforamtion about the collision:



getPhysicsSpace().addCollisionListener(new CollisionListener(){

@Override

public void collision(CollisionEvent event) {

System.out.println("Event");

}



});

In general, if you use updateGeometricState() in jME3 then you have a bug in your code… Just letting you know.

Empire Phoenix said:

Wee it jsut moves through without any inforamtion about the collision:

So the collisions are reported when you don't have parents and if you do they are not? Then it really seems to be some placement problem. Can you try around a bit more and maybe define the problem a bit more? As said, the ghostnodes should use the world location of the spatials so they should update correctly.

I found it :slight_smile:



The problem is absolutly unrelated to parenting Translation wise.

As it seems when moving the paren as in my example a flag is set to update the Jme side of it, wich prevents the physicside to be run.



Changing the update to this kinda solves my problem:


   @Override
   public void update(){
      super.update();
      
   
      if(tick){
         Quaternion bla = tester.getLocalRotation();
         float[] storage = new float[3];
         bla.toAngles(storage);
         storage[0]+=0.001f;
         bla.fromAngles(storage);
         tester.setLocalRotation(bla);
         tick = false;
      }else{
         tick = true;
      }
   
   }
[code]

[/code]

Empire Phoenix said:

I found it :)
The problem is absolutly unrelated to parenting Translation wise.
As it seems when moving the paren as in my example a flag is set to update the Jme side of it, wich prevents the physicside to be run.

Huh? I dont understand? Where is the flag set? which update do you override?