How can i make 'Perfectly elastic collision'

Started by nilotic, February 20, 2012, 01:42:45 PM

Previous topic - Next topic

nilotic

Hello.
First, My English is not good, so I ask for your understanding regarding this matter.

I want to make 'perfectly elastic collision' between marble   in cube.
So, When collision occurs, I want to control the vector of marble.

But, I don't know How can i control the vector when collison occurs.

I already read all document about collision and sample Code, etc... (in JPCT Wiki).
And I'm testing in sample code. But, This code shows only slip between sphere.

Can i get some tips?

package com.threed.jpct.example;


import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;

import android.app.Activity;
//import android.content.res.Resources;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

import com.threed.jpct.Camera;
//import com.threed.jpct.CollisionListener;
import com.threed.jpct.Config;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
//import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;



public class CollisionOfHelloWorld extends Activity {


//public class HelloWorld_col extends Activity {

   // Used to handle pause and resume...
   private static CollisionOfHelloWorld master = null;
   private GLSurfaceView mGLView;
   private MyRenderer renderer = null;
   private FrameBuffer fb = null;
   private World world = null;

   private Light sun = null;
   private RGBColor back = new RGBColor(50, 50, 100);


   private Object3D sphere1 = null;
   private Object3D sphere2 = null;

   
  // private SimpleVector move = new SimpleVector(0,0.3,1);
   private SimpleVector move2 = new SimpleVector(0, -1, 0);
  // private SimpleVector ellips = new SimpleVector(7,7,7);
   private SimpleVector tmp = new SimpleVector();
   private SimpleVector sunV = new SimpleVector(30,20, -150);
   

   protected void onCreate(Bundle savedInstanceState) {
      Logger.log("onCreate");

      if (master != null) {
         
      }

      super.onCreate(savedInstanceState);
      mGLView = new GLSurfaceView(getApplication());

      mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
            // Ensure that we get a 16bit framebuffer. Otherwise, we'll fall
            // back to Pixelflinger on some device (read: Samsung I7500)
            int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
            EGLConfig[] configs = new EGLConfig[1];
            int[] result = new int[1];
            egl.eglChooseConfig(display, attributes, configs, 1, result);
            return configs[0];
         }
      });

      renderer = new MyRenderer();
      mGLView.setRenderer(renderer);
      setContentView(mGLView);
   }

   

   protected void onStop() {
      Logger.log("onStop");
      super.onStop();
   }


   class MyRenderer implements GLSurfaceView.Renderer {

      private int fps = 0;
      private long time = System.currentTimeMillis();

      private boolean stop = false;

      public MyRenderer() {
         Config.maxPolysVisible = 500;
         Config.farPlane = 1500;
         Config.glTransparencyMul = 0.1f;
         Config.glTransparencyOffset = 0.1f;
         Config.useVBO=true;
         
         Texture.defaultToMipmapping(false);
         Texture.defaultTo4bpp(true);
      }

      public void stop() {
         stop = true;
      }

      public void onSurfaceChanged(GL10 gl, int w, int h) {
         if (fb != null) {
            fb.dispose();
         }

         fb = new FrameBuffer(gl, w, h);

         if (master == null) {
            world = new World();
                       
            sphere1 =  Primitives.getSphere(5);
            sphere1.setAdditionalColor(RGBColor.RED);
         
           
            sphere2 = sphere1.cloneObject();
            sphere2.setAdditionalColor(RGBColor.GREEN);
           
           
            sphere1.translate(0,-20,0);
            sphere2.translate(0, 40, 0);
           
           
           
            world.addObject(sphere1);
            world.addObject(sphere2);
         
                       
            // Setup collision modes
            sphere1.setCollisionMode(Object3D.COLLISION_CHECK_SELF | Object3D.COLLISION_CHECK_OTHERS);
            sphere2.setCollisionMode(Object3D.COLLISION_CHECK_SELF | Object3D.COLLISION_CHECK_OTHERS);
           
            world.setAmbientLight(20, 20, 20);
         
            sun = new Light(world);
            sun.setIntensity(250,250,250);
            sun.setPosition(sunV);
           
            world.buildAllObjects();

           
            Camera cam = world.getCamera();
            cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
            cam.moveCamera(Camera.CAMERA_MOVEUP, 60);
            cam.lookAt(sphere1.getTransformedCenter());

            MemoryHelper.compact();
           
         }
      }

      public void onSurfaceCreated(GL10 gl, EGLConfig config) {
         
        // gl.glEnable(GL10.GL_BLEND);
         //gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
      }

      public void onDrawFrame(GL10 gl) {

         try {
            if (!stop) {
               
            // Do collision dections
            SimpleVector trsn = sphere2.checkForCollisionSpherical(move2, 5);
            sphere2.translate(trsn);
            Logger.log("Vector is "  + trsn);
           
           
            if (sphere2.getTranslation(tmp).z>100) {
            // Restart at the beginning...
            sphere2.clearTranslation();
            sphere2.translate(10, -40, -30);
            }else if (sphere2.getTranslation(tmp).y>100 || sphere2.getTranslation(tmp).y<-100) {
            // Restart at the beginning...
            sphere2.clearTranslation();
            sphere2.translate(0, 40, 0);
            }
           
               fb.clear(back);
               world.renderScene(fb);
               world.draw(fb);

               fb.display();

               fps++;
               
               if (System.currentTimeMillis()-time>=1000) {
               System.out.println(fps+"fps");
               fps=0;
               time=System.currentTimeMillis();
               }
            } else {
               if (fb != null) {
                  fb.dispose();
                  fb = null;
               }
            }
         } catch (Exception e) {
            e.printStackTrace();
            Logger.log("Drawing thread terminated!", Logger.MESSAGE);
         }
      }

     
   }

}

EgonOlsen

You can get the ids of the polygons that have been touched by the collision by implementing a collision listener (and adding it...). With that id, you can get the normals of the touched polygons and that might help to calculate the reflection vector. However, if may be worth considering to use something like JBullet instead.

Thomas.

jBullet is very slow on Android devices (you can try my simple demo), if you need just sphere, I recommend write your own physics engine.

EgonOlsen

I still don't think that your test was "very slow". I think that JBullet delivers performance "good enough" for a large number of applications. It might not be sufficient for all applications and it might be possible to tweak it, but that's true for all VM-based solutions.


nilotic

I'm trying   Jbullet + JPCT.  But something,, I can't understand
I just added Jbullet-code in tutorial. But it didn't work.

So, i checked line by line.
Then, I confirmed problem that is AxisSweep3.

Error message is
The source attachment does not contain the source for the file GLSurfaceView.class.
You can change the source attachment by clicking Change Attacted Source below.

I thought that something wrong in code. So i searched all day.. but, I couldn't know problem..
Is there anything i missed ?

package com.threed.jpct.example;


import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

import javax.microedition.khronos.egl.EGL10;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.egl.EGLDisplay;
import javax.microedition.khronos.opengles.GL10;
import javax.vecmath.Vector3f;

import android.app.Activity;
//import android.content.res.Resources;
import android.opengl.GLSurfaceView;
import android.os.Bundle;

import com.threed.jpct.Camera;
//import com.threed.jpct.CollisionListener;
import com.threed.jpct.Config;
import com.threed.jpct.FrameBuffer;
import com.threed.jpct.Light;
import com.threed.jpct.Logger;
import com.threed.jpct.Object3D;
import com.threed.jpct.Primitives;
import com.threed.jpct.RGBColor;
import com.threed.jpct.SimpleVector;
import com.threed.jpct.Texture;
//import com.threed.jpct.TextureManager;
import com.threed.jpct.World;
import com.threed.jpct.util.MemoryHelper;

import com.bulletphysics.collision.broadphase.AxisSweep3;
import com.bulletphysics.collision.broadphase.BroadphaseInterface;
import com.bulletphysics.collision.dispatch.CollisionDispatcher;
import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration;
import com.bulletphysics.collision.shapes.BoxShape;
import com.bulletphysics.collision.shapes.CollisionShape;
import com.bulletphysics.collision.shapes.SphereShape;
import com.bulletphysics.dynamics.DiscreteDynamicsWorld;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.dynamics.RigidBodyConstructionInfo;
import com.bulletphysics.dynamics.constraintsolver.ConstraintSolver;
import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver;
import com.threed.jpct.example.JPCTBulletMotionState;
import com.bulletphysics.linearmath.Clock;
import com.bulletphysics.linearmath.DefaultMotionState;
import com.bulletphysics.linearmath.Transform;


public class CollisionOfHelloWorld extends Activity {


//public class HelloWorld_col extends Activity {

   // Used to handle pause and resume...
   public int numSpheres = 10;

private static CollisionOfHelloWorld master = null;
   private GLSurfaceView mGLView;
   private MyRenderer renderer = null;
   private FrameBuffer fb = null;
   private World world = null;

   private Light sun = null;
   private RGBColor back = new RGBColor(50, 50, 100);

   
   // Jbullet
   public DiscreteDynamicsWorld dynamicWorld;
   public int maxSubSteps;
   public float timeStep, fixedTimeStep;
   protected Clock clock = new Clock();
   
   private List<CollisionShape> collisionShapes = new ArrayList<CollisionShape>();
   private BroadphaseInterface overlappingPairCache;
   private CollisionDispatcher dispatcher;
   private ConstraintSolver solver;
   private DefaultCollisionConfiguration collisionConfiguration;
   
   private Vector<RigidBody> boxList = new Vector();
   
   
   private Object3D sphere1 = null;
   private Object3D sphere2 = null;

   
  // private SimpleVector move = new SimpleVector(0,0.3,1);
   private SimpleVector move2 = new SimpleVector(0, -1, 0);
 
   private SimpleVector tmp = new SimpleVector();
   private SimpleVector sunV = new SimpleVector(30,20, -150);
   

   protected void onCreate(Bundle savedInstanceState) {
      Logger.log("onCreate");

      if (master != null) {
         
      }

      super.onCreate(savedInstanceState);
      mGLView = new GLSurfaceView(getApplication());

      mGLView.setEGLConfigChooser(new GLSurfaceView.EGLConfigChooser() {
         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {
            // Ensure that we get a 16bit framebuffer. Otherwise, we'll fall
            // back to Pixelflinger on some device (read: Samsung I7500)
            int[] attributes = new int[] { EGL10.EGL_DEPTH_SIZE, 16, EGL10.EGL_NONE };
            EGLConfig[] configs = new EGLConfig[1];
            int[] result = new int[1];
            egl.eglChooseConfig(display, attributes, configs, 1, result);
            return configs[0];
         }
      });

      renderer = new MyRenderer();
      mGLView.setRenderer(renderer);
      setContentView(mGLView);
   }

   

   protected void onStop() {
      Logger.log("onStop");
      super.onStop();
   }


   class MyRenderer implements GLSurfaceView.Renderer {

      private int fps = 0;
      private long time = System.currentTimeMillis();

      private boolean stop = false;

      public MyRenderer() {
         Config.maxPolysVisible = 500;
         Config.farPlane = 1500;
         Config.glTransparencyMul = 0.1f;
         Config.glTransparencyOffset = 0.1f;
         Config.useVBO=true;
         
         Texture.defaultToMipmapping(false);
         Texture.defaultTo4bpp(true);
      }

      public void stop() {
         stop = true;
      }

      public void onSurfaceChanged(GL10 gl, int w, int h) {
         if (fb != null) {
            fb.dispose();
         }

         fb = new FrameBuffer(gl, w, h);

         if (master == null) {
            world = new World();
           
            sphere1 =  Primitives.getSphere(5);
            sphere1.setAdditionalColor(RGBColor.RED);
           
            sphere2=sphere1.cloneObject();
            sphere2.setAdditionalColor(RGBColor.GREEN);
           
           
            sphere1.translate(0,-20,0);
            sphere2.translate(0, 40, 0);
               
           
            world.addObject(sphere1);
            world.addObject(sphere2);
                   
           
            // Setup collision modes
           // sphere1.setCollisionMode(Object3D.COLLISION_CHECK_SELF | Object3D.COLLISION_CHECK_OTHERS);
           // sphere2.setCollisionMode(Object3D.COLLISION_CHECK_SELF | Object3D.COLLISION_CHECK_OTHERS);
         
            world.setAmbientLight(20, 20, 20);
         
            sun = new Light(world);
            sun.setIntensity(250,250,250);
            sun.setPosition(sunV);
           
            world.buildAllObjects();
           
            collisionConfiguration = new DefaultCollisionConfiguration();
            dispatcher = new CollisionDispatcher (collisionConfiguration);
            Vector3f worldAabbMin = new Vector3f(-10000, -10000, -10000);
            Vector3f worldAabbmax = new Vector3f(10000, 10000, 10000);
            AxisSweep3 overlappingPairCache = new AxisSweep3(worldAabbMin, worldAabbmax);
           /* SequentialImpulseConstraintSolver solver = new SequentialImpulseConstraintSolver();
           
            dynamicWorld = new DiscreteDynamicsWorld(dispatcher, overlappingPairCache, solver, collisionConfiguration);
            dynamicWorld.setGravity(new Vector3f(0,-10,0));
            dynamicWorld.getDispatchInfo().allowedCcdPenetration = 0f;
           
           CollisionShape groundShape = new BoxShape(new Vector3f(100.f, 50.f, 100.f));
            CollisionShape marbleShape = new SphereShape(10);
            Transform groundTransform = new Transform();
            groundTransform.setIdentity();
            groundTransform.origin.set(new Vector3f(0.f, -56.f, 0.f));
            float mass = 0f;
            Vector3f localInertia = new Vector3f(0,0,0);
            DefaultMotionState myMotionState = new DefaultMotionState(groundTransform);
            RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, groundShape, localInertia);
            RigidBody body = new RigidBody(rbInfo);
            dynamicWorld.addRigidBody(body);
            dynamicWorld.clearForces();*/
               
           
           
           
            Camera cam = world.getCamera();
            cam.moveCamera(Camera.CAMERA_MOVEOUT, 50);
            cam.moveCamera(Camera.CAMERA_MOVEUP, 60);
            cam.lookAt(sphere1.getTransformedCenter());

            MemoryHelper.compact();
           
         }
      }

     
  /* public void initTestObects(){
  Transform transform;
  Object3D boxgfx;
  BoxShape shape = new BoxShape(new Vector3f(2,2,2));
  JPCTBulletMotionState ms;
  float mass = 5;
  Vector3f localInertia = new Vector3f(0,0,0);
  shape.calculateLocalInertia(mass, localInertia);
  RigidBodyConstructionInfo rbInfo;
  RigidBody body;
 
  for(int i = 1; i < numSpheres; i++){
      boxgfx = Primitives.getSphere(2);
    boxgfx.setTexture("box");
    boxgfx.setEnvmapped(Object3D.ENVMAP_ENABLED);
    boxgfx.translate(0, (2+(i * 4)) * -1,(float) 50 - i/3);
    boxgfx.build();
    boxgfx.rotateY((float) Math.PI/4f);
    boxgfx.rotateMesh();
    boxgfx.getRotationMatrix().setIdentity();
    world.addObject(boxgfx);
   
    transform = new Transform();
    transform.setIdentity();
   
    ms = new JPCTBulletMotionState(boxgfx);
   
    rbInfo = new RigidBodyConstructionInfo(mass, ms, shape, localInertia);
    body = new RigidBody(rbInfo);
    body.setRestitution(0.1f);
    body.setFriction(0.50f);
    body.setDamping(0f, 0f);
   
    body.setUserPointer(boxgfx);
    boxList.add(body);
   
    dynamicWorld.addRigidBody(body);
  } // end for loop

}*/
     
     
     
     
     
     
     
     
     
     
     
     
     
      public void onSurfaceCreated(GL10 gl, EGLConfig config) {
         
        // gl.glEnable(GL10.GL_BLEND);
         
         //gl.glBlendFunc(GL10.GL_ONE, GL10.GL_ONE_MINUS_SRC_ALPHA);
      }

      public void onDrawFrame(GL10 gl) {

         try {
            if (!stop) {
               
            // Do collision dections
             //  SimpleVector trsn = sphere2.checkForCollisionSpherical(move2, 5);
            //cube.translate(trsn);
            //sphere2.translate(trsn);
            //Logger.log("Vector is "  + trsn);
           
            /*if (cube.getTranslation(tmp).z>100) {
            // Restart at the beginning...
            cube.clearTranslation();
            cube.translate(10, -40, -30);
            }*/
            if (sphere2.getTranslation(tmp).z>100) {
            // Restart at the beginning...
            sphere2.clearTranslation();
            sphere2.translate(10, -40, -30);
            }else if (sphere2.getTranslation(tmp).y>100 || sphere2.getTranslation(tmp).y<-100) {
            // Restart at the beginning...
            sphere2.clearTranslation();
            sphere2.translate(0, 40, 0);
            }
           
               fb.clear(back);
               world.renderScene(fb);
               world.draw(fb);

               fb.display();

               fps++;
               
               if (System.currentTimeMillis()-time>=1000) {
               System.out.println(fps+"fps");
               fps=0;
               time=System.currentTimeMillis();
               }
            } else {
               if (fb != null) {
                  fb.dispose();
                  fb = null;
               }
            }
         } catch (Exception e) {
            e.printStackTrace();
            Logger.log("Drawing thread terminated!", Logger.MESSAGE);
         }
      }

     
   }

}

K24A3

It looks like there is no object translation or frame update calls to jBullet in onDrawFrame() except for translation boundary resetting. I haven't used jBullet but check if you are missing a jBullet.onFrame() call or CollisionShape.onFrame() calls for each object.


EgonOlsen

QuoteThe source attachment does not contain the source for the file GLSurfaceView.class.
You can change the source attachment by clicking Change Attacted Source below.
...that's not the error. That's your IDE telling you that it can't display the sources for a class that you are trying to access.