First, sory for my English

I discover bullet, and in my case jbulle because i use it with java.
I try to do something simple (i supposed).
Like on many video on Youtube i try to put many cube at random position in a world.
I realise this with succes but i have a little problem and i don't know how to do.
I have a ground, i have some cube with texture etc.. The cube fall well, but, not like in reality. They don't "rotate" and stay alway on the same position.
For eg, i can make a staircase juste with cube, and even if a cube is on the edge to another cube, it does not fail to fall.
I hope you understand me
This is the code i try :
So, if someone could explain to me what i ve miss, that would be nice.
Code: Select all
public class Test_jBullet_DemoBasic {
public static final boolean vsync = true;
public boolean fullscreen = false;
private static int fps;
private static long lastFPS;
private static long lastFrame;
private int delta;
public int width = 1024;
public int height = 768;
private static Texture TEXTURE_SOL;
private static Texture TEXTURE_CUBE;
private FreeFlyCamera cam;
public double angleZ = 0;
public double angleX = 0;
private double rX = 0;
private double rY = 0;
private double rZ = 0;
private static Set<RigidBody> rBody = new HashSet<RigidBody>();
private static Sphere sphere = new Sphere();
/*
*
* jBullet Demo Variables
*
*/
// create 125 (5x5x5) dynamic object
private static final int ARRAY_SIZE_X = 5;
private static final int ARRAY_SIZE_Y = 5;
private static final int ARRAY_SIZE_Z = 5;
// maximum number of objects (and allow user to shoot additional boxes)
private static final int MAX_PROXIES = (ARRAY_SIZE_X*ARRAY_SIZE_Y*ARRAY_SIZE_Z + 1024);
private static final int START_POS_X = -5;
private static final int START_POS_Y = -5;
private static final int START_POS_Z = -3;
// keep the collision shapes, for deletion/cleanup
private ObjectArrayList<CollisionShape> collisionShapes = new ObjectArrayList<CollisionShape>();
private BroadphaseInterface broadphase;
private CollisionDispatcher dispatcher;
private ConstraintSolver solver;
private DefaultCollisionConfiguration collisionConfiguration;
/*
*
* Variable issue d'une autre classe
*
*/
protected DynamicsWorld dynamicsWorld = null;
public static void main(String[] args) throws LWJGLException {
Test_jBullet_DemoBasic test_jBullet_DemoBasic = new Test_jBullet_DemoBasic();
}
public Test_jBullet_DemoBasic(){
Init_Display();
Init_GL();
Init_Texture();
initPhysics();
cam = new FreeFlyCamera(new org.lwjgl.util.vector.Vector3f(-10,0,2),new org.lwjgl.util.vector.Vector3f(11,3,2));
cam.init_Cam(new org.lwjgl.util.vector.Vector3f(1,0,0), new org.lwjgl.util.vector.Vector3f(-10,0,2));
cam.setDebug(true);
lastFPS = getTime();
while(!Display.isCloseRequested()){
rY = cam.getAngleH() * Math.PI / 180;
rZ = cam.getAngleV() * Math.PI / 180;
delta = getDelta();
angleZ += 0.05 * delta ;
angleX += 0.05 * delta ;
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT) ;
dynamicsWorld.stepSimulation(1.0f / 60.0f); //mettre à jour la simulation physique à chaque frame
glMatrixMode( GL_MODELVIEW );
glLoadIdentity( );
getIntput();
for (RigidBody body : rBody) {
glPushMatrix();
Vector3f bodyPosition = body.getWorldTransform(new Transform()).origin;
glTranslatef(bodyPosition.x, bodyPosition.y, bodyPosition.z);
//sphere.setDrawStyle(GLU.GLU_SILHOUETTE);
dessiner_Cube();
glColor4f(1, 0, 0, 1);
//sphere.draw(0.5f, 30, 30);
glPopMatrix();
}
glFlush(); //s'assurer que toutes les commandes OpenGL ont été exécutées
updateFPS();
Display.update();
if (vsync) {
Display.sync(60);
}
if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
Display.destroy();
System.exit(0);
}
}
}
public void initPhysics() {
//setCameraDistance(50f);
// collision configuration contains default setup for memory, collision setup
collisionConfiguration = new DefaultCollisionConfiguration();
// use the default collision dispatcher. For parallel processing you can use a diffent dispatcher (see Extras/BulletMultiThreaded)
dispatcher = new CollisionDispatcher(collisionConfiguration);
broadphase = new DbvtBroadphase();
// the default constraint solver. For parallel processing you can use a different solver (see Extras/BulletMultiThreaded)
SequentialImpulseConstraintSolver sol = new SequentialImpulseConstraintSolver();
solver = sol;
// TODO: needed for SimpleDynamicsWorld
//sol.setSolverMode(sol.getSolverMode() & ~SolverMode.SOLVER_CACHE_FRIENDLY.getMask());
dynamicsWorld = new DiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
dynamicsWorld.setGravity(new Vector3f(0f, -10f, 0f));
// create a few basic rigid bodies
CollisionShape groundShape = new BoxShape(new Vector3f(50f, 50f, 50f));
//CollisionShape groundShape = new StaticPlaneShape(new Vector3f(0, 1, 0), 50);
collisionShapes.add(groundShape);
Transform groundTransform = new Transform();
groundTransform.setIdentity();
groundTransform.origin.set(0, -56, 0);
// We can also use DemoApplication::localCreateRigidBody, but for clarity it is provided here:
{
float mass = 0f;
// rigidbody is dynamic if and only if mass is non zero, otherwise static
boolean isDynamic = (mass != 0f);
Vector3f localInertia = new Vector3f(0, 0, 0);
if (isDynamic) {
groundShape.calculateLocalInertia(mass, localInertia);
}
// using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
DefaultMotionState myMotionState = new DefaultMotionState(groundTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, groundShape, localInertia);
RigidBody body = new RigidBody(rbInfo);
// add the body to the dynamics world
dynamicsWorld.addRigidBody(body);
}
{
// create a few dynamic rigidbodies
// Re-using the same collision is better for memory usage and performance
CollisionShape colShape = new BoxShape(new Vector3f(1, 1, 1));
//CollisionShape colShape = new SphereShape(1f);
collisionShapes.add(colShape);
// Create Dynamic Objects
Transform startTransform = new Transform();
startTransform.setIdentity();
float mass = 1f;
// rigidbody is dynamic if and only if mass is non zero, otherwise static
boolean isDynamic = (mass != 0f);
Vector3f localInertia = new Vector3f(0, 0, 0);
if (isDynamic) {
colShape.calculateLocalInertia(mass, localInertia);
}
float start_x = START_POS_X - ARRAY_SIZE_X / 2;
float start_y = START_POS_Y;
float start_z = START_POS_Z - ARRAY_SIZE_Z / 2;
for (int k = 0; k < ARRAY_SIZE_Y; k++) {
for (int i = 0; i < ARRAY_SIZE_X; i++) {
for (int j = 0; j < ARRAY_SIZE_Z; j++) {
startTransform.origin.set(
2f * i + start_x,
10f + 2f * k + start_y,
2f * j + start_z);
// using motionstate is recommended, it provides interpolation capabilities, and only synchronizes 'active' objects
DefaultMotionState myMotionState = new DefaultMotionState(startTransform);
RigidBodyConstructionInfo rbInfo = new RigidBodyConstructionInfo(mass, myMotionState, colShape, localInertia);
RigidBody body = new RigidBody(rbInfo);
body.setActivationState(RigidBody.DISABLE_DEACTIVATION);
rBody.add(body);
dynamicsWorld.addRigidBody(body);
body.setActivationState(RigidBody.DISABLE_DEACTIVATION);
}
}
}
}
//clientResetScene();
}
private void Init_Display() {
try {
if (fullscreen) {
Display.setDisplayModeAndFullscreen(Display.getDesktopDisplayMode());
} else {
Display.setResizable(false);
Display.setDisplayMode(new DisplayMode(width, height));
}
Display.setTitle("Test JBullet");
Display.setVSyncEnabled(vsync);
Display.create();
} catch (LWJGLException ex) {
ex.printStackTrace();
Display.destroy();
System.exit(1);
}
if (!GLContext.getCapabilities().OpenGL11) {
System.err.println("Votre version OpenGL ne prend pas en charge la fonctionnalité requise.");
Display.destroy();
System.exit(1);
}
}
private void Init_GL(){
glMatrixMode( GL_PROJECTION );
glLoadIdentity( );
gluPerspective((float)70,(float)1024/768,1,1000);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
}
private void dessiner_Cube(){
glColor3f(255,255,255); // On neutralise les couleurs utilisé précédement. Pour ce faire on utilise le blanc
glPushMatrix(); // Push et Pop Matrix pour que la rotatin soit faite que sur le cube
// PushMatrix mémorise la matrice, PopMatrice la restitue
// Sans ça, tout les Obect 3D effectuent la rotation
int nIdTexture;
nIdTexture = TEXTURE_CUBE.getTextureID();
glBindTexture(GL_TEXTURE_2D, nIdTexture);
//glPolygonMode( GL_, GL_LINE );
glBegin(GL_QUADS);
//glColor3f(255,0,0); //face rouge
glTexCoord2d(0,1);
glVertex3d(1,1,1);
glTexCoord2d(0,0);
glVertex3d(1,1,-1);
glTexCoord2d(1,0);
glVertex3d(-1,1,-1);
glTexCoord2d(1,1);
glVertex3d(-1,1,1);
//glColor3f(0,255,0); //face verte
glTexCoord2d(0,1);
glVertex3d(1,-1,1);
glTexCoord2d(0,0);
glVertex3d(1,-1,-1);
glTexCoord2d(1,0);
glVertex3d(1,1,-1);
glTexCoord2d(1,1);
glVertex3d(1,1,1);
//glColor3f(0,0,255); //face bleue
glTexCoord2d(0,1);
glVertex3d(-1,-1,1);
glTexCoord2d(0,0);
glVertex3d(-1,-1,-1);
glTexCoord2d(1,0);
glVertex3d(1,-1,-1);
glTexCoord2d(1,1);
glVertex3d(1,-1,1);
//glColor3f(255,255,0); //face jaune
glTexCoord2d(0,1);
glVertex3d(-1,1,1);
glTexCoord2d(0,0);
glVertex3d(-1,1,-1);
glTexCoord2d(1,0);
glVertex3d(-1,-1,-1);
glTexCoord2d(1,1);
glVertex3d(-1,-1,1);
//glColor3f(0,255,255); //face cyan
glTexCoord2d(0,1);
glVertex3d(1,1,-1);
glTexCoord2d(0,0);
glVertex3d(1,-1,-1);
glTexCoord2d(1,0);
glVertex3d(-1,-1,-1);
glTexCoord2d(1,1);
glVertex3d(-1,1,-1);
//glColor3f(255,0,255); //face magenta
glTexCoord2d(0,1);
glVertex3d(1,-1,1);
glTexCoord2d(0,0);
glVertex3d(1,1,1);
glTexCoord2d(1,0);
glVertex3d(-1,1,1);
glTexCoord2d(1,1);
glVertex3d(-1,-1,1);
glEnd();
glPopMatrix();
}
private void Init_Texture(){
try {
// load texture from PNG file
TEXTURE_CUBE = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("res/wood.png"));
TEXTURE_SOL = TextureLoader.getTexture("jpg", ResourceLoader.getResourceAsStream("res/champ2.jpg"));
} catch (IOException e) {
e.printStackTrace();
}
}
private static long getTime() {
return (Sys.getTime() * 1000) / Sys.getTimerResolution();
}
private static int getDelta() {
long time = getTime();
int delta = (int) (time - lastFrame);
lastFrame = time;
return delta;
}
public static void updateFPS() {
if (getTime() - lastFPS > 1000) {
Display.setTitle("FPS: " + fps);
fps = 0; //reset the FPS counter
lastFPS += 1000; //add one second
}
fps++;
}
private void getIntput(){
cam.pollInput(delta);
cam.look();
while (Keyboard.next()) {
if (Keyboard.getEventKeyState()) {
switch (Keyboard.getEventKey()) {
case Keyboard.KEY_F:
System.out.println("A Key Event");
break;
}
}
}
if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)){
System.out.println("SPACE Key Event");
}
}
}