Package com.bulletphysics.demos.concave

Source Code of com.bulletphysics.demos.concave.ConcaveDemo

/*
* Java port of Bullet (c) 2008 Martin Dvorak <jezek2@advel.cz>
*
* Bullet Continuous Collision Detection and Physics Library
* Copyright (c) 2003-2008 Erwin Coumans  http://www.bulletphysics.com/
*
* This software is provided 'as-is', without any express or implied warranty.
* In no event will the authors be held liable for any damages arising from
* the use of this software.
*
* Permission is granted to anyone to use this software for any purpose,
* including commercial applications, and to alter it and redistribute it
* freely, subject to the following restrictions:
*
* 1. The origin of this software must not be misrepresented; you must not
*    claim that you wrote the original software. If you use this software
*    in a product, an acknowledgment in the product documentation would be
*    appreciated but is not required.
* 2. Altered source versions must be plainly marked as such, and must not be
*    misrepresented as being the original software.
* 3. This notice may not be removed or altered from any source distribution.
*/

package com.bulletphysics.demos.concave;

import com.bulletphysics.util.ObjectArrayList;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import com.bulletphysics.BulletGlobals;
import com.bulletphysics.BulletStats;
import com.bulletphysics.ContactAddedCallback;
import com.bulletphysics.collision.broadphase.BroadphaseInterface;
import com.bulletphysics.collision.broadphase.DbvtBroadphase;
import com.bulletphysics.collision.dispatch.CollisionDispatcher;
import com.bulletphysics.collision.dispatch.CollisionFlags;
import com.bulletphysics.collision.dispatch.CollisionObject;
import com.bulletphysics.collision.dispatch.DefaultCollisionConfiguration;
import com.bulletphysics.collision.narrowphase.ManifoldPoint;
import com.bulletphysics.collision.shapes.BoxShape;
import com.bulletphysics.collision.shapes.BvhTriangleMeshShape;
import com.bulletphysics.collision.shapes.CollisionShape;
import com.bulletphysics.collision.shapes.CompoundShape;
import com.bulletphysics.collision.shapes.CylinderShapeX;
import com.bulletphysics.collision.shapes.OptimizedBvh;
import com.bulletphysics.collision.shapes.TriangleIndexVertexArray;
import com.bulletphysics.demos.opengl.DemoApplication;
import com.bulletphysics.demos.opengl.GLDebugDrawer;
import com.bulletphysics.demos.opengl.IGL;
import com.bulletphysics.demos.opengl.LWJGL;
import com.bulletphysics.dynamics.DiscreteDynamicsWorld;
import com.bulletphysics.dynamics.RigidBody;
import com.bulletphysics.dynamics.constraintsolver.ConstraintSolver;
import com.bulletphysics.dynamics.constraintsolver.SequentialImpulseConstraintSolver;
import com.bulletphysics.linearmath.QuaternionUtil;
import com.bulletphysics.linearmath.Transform;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.zip.GZIPInputStream;
import java.util.zip.GZIPOutputStream;
import javax.vecmath.Quat4f;
import javax.vecmath.Vector3f;
import org.lwjgl.LWJGLException;
import static com.bulletphysics.demos.opengl.IGL.*;

// JAVA TODO: update for 2.70b1

/**
*
* @author jezek2
*/
public class ConcaveDemo extends DemoApplication {

  // enable to test serialization of BVH to speedup loading:
  private static final boolean TEST_SERIALIZATION = false;
  // set to false to read the BVH from disk (first run the demo once to create the BVH):
  private static final boolean SERIALIZE_TO_DISK  = true;

  private static final boolean USE_BOX_SHAPE = false;

  // keep the collision shapes, for deletion/cleanup
  private ObjectArrayList<CollisionShape> collisionShapes = new ObjectArrayList<CollisionShape>();
  private TriangleIndexVertexArray indexVertexArrays;
  private BroadphaseInterface broadphase;
  private CollisionDispatcher dispatcher;
  private ConstraintSolver solver;
  private DefaultCollisionConfiguration collisionConfiguration;
  private boolean animatedMesh = false;
 
  private static ByteBuffer gVertices;
  private static ByteBuffer gIndices;
  private static BvhTriangleMeshShape trimeshShape;
  private static RigidBody staticBody;
  private static float waveheight = 5.f;

  private static final float TRIANGLE_SIZE=8.f;
  private static int NUM_VERTS_X = 30;
  private static int NUM_VERTS_Y = 30;
  private static int totalVerts = NUM_VERTS_X*NUM_VERTS_Y;

  public ConcaveDemo(IGL gl) {
    super(gl);
  }

  public void setVertexPositions(float waveheight, float offset) {
    int i;
    int j;
    Vector3f tmp = new Vector3f();

    for (i = 0; i < NUM_VERTS_X; i++) {
      for (j = 0; j < NUM_VERTS_Y; j++) {
        tmp.set(
            (i - NUM_VERTS_X * 0.5f) * TRIANGLE_SIZE,
            //0.f,
            waveheight * (float) Math.sin((float) i + offset) * (float) Math.cos((float) j + offset),
            (j - NUM_VERTS_Y * 0.5f) * TRIANGLE_SIZE);

        int index = i + j * NUM_VERTS_X;
        gVertices.putFloat((index*3 + 0) * 4, tmp.x);
        gVertices.putFloat((index*3 + 1) * 4, tmp.y);
        gVertices.putFloat((index*3 + 2) * 4, tmp.z);
      }
    }
  }

  @Override
  public void keyboardCallback(char key, int x, int y, int modifiers) {
    if (key == 'g') {
      animatedMesh = !animatedMesh;
      if (animatedMesh) {
        staticBody.setCollisionFlags(staticBody.getCollisionFlags() | CollisionFlags.KINEMATIC_OBJECT);
        staticBody.setActivationState(CollisionObject.DISABLE_DEACTIVATION);
      }
      else {
        staticBody.setCollisionFlags(staticBody.getCollisionFlags() & ~CollisionFlags.KINEMATIC_OBJECT);
        staticBody.forceActivationState(CollisionObject.ACTIVE_TAG);
      }
    }

    super.keyboardCallback(key, x, y, modifiers);
  }

  public void initPhysics() {
    final float TRISIZE = 10f;

    BulletGlobals.setContactAddedCallback(new CustomMaterialCombinerCallback());

    //#define USE_TRIMESH_SHAPE 1
    //#ifdef USE_TRIMESH_SHAPE

    int vertStride = 3 * 4;
    int indexStride = 3 * 4;

    int totalTriangles = 2 * (NUM_VERTS_X - 1) * (NUM_VERTS_Y - 1);

    gVertices = ByteBuffer.allocateDirect(totalVerts * 3 * 4).order(ByteOrder.nativeOrder());
    gIndices = ByteBuffer.allocateDirect(totalTriangles * 3 * 4).order(ByteOrder.nativeOrder());

    int i;

    setVertexPositions(waveheight, 0.f);

    //int index=0;
    gIndices.clear();
    for (i = 0; i < NUM_VERTS_X - 1; i++) {
      for (int j = 0; j < NUM_VERTS_Y - 1; j++) {
        gIndices.putInt(j * NUM_VERTS_X + i);
        gIndices.putInt(j * NUM_VERTS_X + i + 1);
        gIndices.putInt((j + 1) * NUM_VERTS_X + i + 1);

        gIndices.putInt(j * NUM_VERTS_X + i);
        gIndices.putInt((j + 1) * NUM_VERTS_X + i + 1);
        gIndices.putInt((j + 1) * NUM_VERTS_X + i);
      }
    }
    gIndices.flip();

    indexVertexArrays = new TriangleIndexVertexArray(totalTriangles,
        gIndices,
        indexStride,
        totalVerts, gVertices, vertStride);

    boolean useQuantizedAabbCompression = true;

    if (TEST_SERIALIZATION) {
      if (SERIALIZE_TO_DISK) {
        trimeshShape = new BvhTriangleMeshShape(indexVertexArrays, useQuantizedAabbCompression);
        collisionShapes.add(trimeshShape);

        // we can serialize the BVH data
        try {
          ObjectOutputStream out = new ObjectOutputStream(new GZIPOutputStream(new FileOutputStream(new File("bvh.bin"))));
          out.writeObject(trimeshShape.getOptimizedBvh());
          out.close();
        }
        catch (IOException e) {
          e.printStackTrace();
        }
      }
      else {
        trimeshShape = new BvhTriangleMeshShape(indexVertexArrays, useQuantizedAabbCompression, false);

        OptimizedBvh bvh = null;
        try {
          ObjectInputStream in = new ObjectInputStream(new GZIPInputStream(new FileInputStream(new File("bvh.bin"))));
          bvh = (OptimizedBvh)in.readObject();
          in.close();
        }
        catch (Exception e) {
          e.printStackTrace();
        }

        trimeshShape.setOptimizedBvh(bvh);
        trimeshShape.recalcLocalAabb();
      }
    }
    else {
      trimeshShape = new BvhTriangleMeshShape(indexVertexArrays, useQuantizedAabbCompression);
      collisionShapes.add(trimeshShape);
    }

    CollisionShape groundShape = trimeshShape;

    //#else
    //btCollisionShape* groundShape = new btBoxShape(btVector3(50,3,50));
    //m_collisionShapes.push_back(groundShape);
    //#endif //USE_TRIMESH_SHAPE

    collisionConfiguration = new DefaultCollisionConfiguration();

//    //#ifdef USE_PARALLEL_DISPATCHER
//    #ifdef USE_WIN32_THREADING
//
//    int maxNumOutstandingTasks = 4;//number of maximum outstanding tasks
//    Win32ThreadSupport* threadSupport = new Win32ThreadSupport(Win32ThreadSupport::Win32ThreadConstructionInfo(
//                  "collision",
//                  processCollisionTask,
//                  createCollisionLocalStoreMemory,
//                  maxNumOutstandingTasks));
//    #else
//    ///todo other platform threading
//    ///Playstation 3 SPU (SPURS)  version is available through PS3 Devnet
//    ///Libspe2 SPU support will be available soon
//    ///pthreads version
//    ///you can hook it up to your custom task scheduler by deriving from btThreadSupportInterface
//    #endif
//
//    m_dispatcher = new  SpuGatheringCollisionDispatcher(threadSupport,maxNumOutstandingTasks,m_collisionConfiguration);
//    #else
    dispatcher = new CollisionDispatcher(collisionConfiguration);
    //#endif//USE_PARALLEL_DISPATCHER

    Vector3f worldMin = new Vector3f(-1000f, -1000f, -1000f);
    Vector3f worldMax = new Vector3f(1000f, 1000f, 1000f);
    //broadphase = new AxisSweep3(worldMin, worldMax);
    broadphase = new DbvtBroadphase();
    //broadphase = new SimpleBroadphase();
    solver = new SequentialImpulseConstraintSolver();
    dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
    //#ifdef USE_PARALLEL_DISPATCHER
    //m_dynamicsWorld->getDispatchInfo().m_enableSPU=true;
    //#endif //USE_PARALLEL_DISPATCHER

    // JAVA NOTE: added
    dynamicsWorld.setDebugDrawer(new GLDebugDrawer(gl));
   
    float mass = 0f;
    Transform startTransform = new Transform();
    startTransform.setIdentity();
    startTransform.origin.set(0f, -2f, 0f);

    CollisionShape colShape;

    if (USE_BOX_SHAPE) {
      colShape = new BoxShape(new Vector3f(1f, 1f, 1f));
    }
    else {
      colShape = new CompoundShape();
      CollisionShape cylinderShape = new CylinderShapeX(new Vector3f(4, 1, 1));
      CollisionShape boxShape = new BoxShape(new Vector3f(4f, 1f, 1f));
      Transform localTransform = new Transform();
      localTransform.setIdentity();
      ((CompoundShape)colShape).addChildShape(localTransform, boxShape);
      Quat4f orn = new Quat4f();
      QuaternionUtil.setEuler(orn, BulletGlobals.SIMD_HALF_PI, 0f, 0f);
      localTransform.setRotation(orn);
      ((CompoundShape)colShape).addChildShape(localTransform, cylinderShape);
    }

    collisionShapes.add(colShape);

    {
      for (i = 0; i < 10; i++) {
        //btCollisionShape* colShape = new btCapsuleShape(0.5,2.0);//boxShape = new btSphereShape(1.f);
        startTransform.origin.set(2f, 10f + i*2f, 1f);
        localCreateRigidBody(1f, startTransform, colShape);
      }
    }

    startTransform.setIdentity();
    staticBody = localCreateRigidBody(mass, startTransform, groundShape);

    staticBody.setCollisionFlags(staticBody.getCollisionFlags() | CollisionFlags.STATIC_OBJECT);

    // enable custom material callback
    staticBody.setCollisionFlags(staticBody.getCollisionFlags() | CollisionFlags.CUSTOM_MATERIAL_CALLBACK);
  }

  private static float offset = 0f;
 
  @Override
  public void clientMoveAndDisplay() {
    gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    float dt = getDeltaTimeMicroseconds() * 0.000001f;

    if (animatedMesh) {
      long t0 = System.nanoTime();
     
      offset += 0.01f;

      setVertexPositions(waveheight, offset);

      // JAVA NOTE: 2.70b1: replace with proper code
      trimeshShape.refitTree(null, null);

      // clear all contact points involving mesh proxy. Note: this is a slow/unoptimized operation.
      dynamicsWorld.getBroadphase().getOverlappingPairCache().cleanProxyFromPairs(staticBody.getBroadphaseHandle(), getDynamicsWorld().getDispatcher());
     
      BulletStats.updateTime = (System.nanoTime() - t0) / 1000000;
    }

    dynamicsWorld.stepSimulation(dt);

    // optional but useful: debug drawing
    dynamicsWorld.debugDrawWorld();

    renderme();

    //glFlush();
    //glutSwapBuffers();
  }

  @Override
  public void displayCallback() {
    gl.glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    renderme();

    // optional but useful: debug drawing
    if (dynamicsWorld != null) {
      dynamicsWorld.debugDrawWorld();
    }
   
    //glFlush();
    //glutSwapBuffers();
  }

  /**
   * User can override this material combiner by implementing gContactAddedCallback
   * and setting body0->m_collisionFlags |= btCollisionObject::customMaterialCallback
   */
  private static float calculateCombinedFriction(float friction0, float friction1) {
    float friction = friction0 * friction1;

    float MAX_FRICTION = 10f;
    if (friction < -MAX_FRICTION) {
      friction = -MAX_FRICTION;
    }
    if (friction > MAX_FRICTION) {
      friction = MAX_FRICTION;
    }
    return friction;
  }

  private static float calculateCombinedRestitution(float restitution0, float restitution1) {
    return restitution0 * restitution1;
  }
 
  private static class CustomMaterialCombinerCallback extends ContactAddedCallback {
    public boolean contactAdded(ManifoldPoint cp, CollisionObject colObj0, int partId0, int index0, CollisionObject colObj1, int partId1, int index1) {
      float friction0 = colObj0.getFriction();
      float friction1 = colObj1.getFriction();
      float restitution0 = colObj0.getRestitution();
      float restitution1 = colObj1.getRestitution();

      if ((colObj0.getCollisionFlags() & CollisionFlags.CUSTOM_MATERIAL_CALLBACK) != 0) {
        friction0 = 1f; //partId0,index0
        restitution0 = 0f;
      }
      if ((colObj1.getCollisionFlags() & CollisionFlags.CUSTOM_MATERIAL_CALLBACK) != 0) {
        if ((index1 & 1) != 0) {
          friction1 = 1f; //partId1,index1
        }
        else {
          friction1 = 0f;
        }
        restitution1 = 0f;
      }

      cp.combinedFriction = calculateCombinedFriction(friction0, friction1);
      cp.combinedRestitution = calculateCombinedRestitution(restitution0, restitution1);

      // this return value is currently ignored, but to be on the safe side: return false if you don't calculate friction
      return true;
    }
  }
 
  public static void main(String[] args) throws LWJGLException {
    ConcaveDemo concaveDemo = new ConcaveDemo(LWJGL.getGL());
    concaveDemo.initPhysics();
    concaveDemo.setCameraDistance(30f);

    LWJGL.main(args, 800, 600, "Static Concave Mesh Demo", concaveDemo);
  }
 
}
TOP

Related Classes of com.bulletphysics.demos.concave.ConcaveDemo

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.