Collision with inclined plane.

hello guys

I trying to implement collision with an inclined plane.
I have some balls that fall within a cube which is already implemented collision with the ball and the cube, gravity and loss of energy.
What I want is to implement collision with an inclined plane and making the balls slip in the plane.As larger and heavier balls should just slip, the smallers should bounce and slipping.
Any idea?

This is the class that draws everything:


package coreEngine;

import geometries.Cubo;
import geometries.Esfera;
import geometries.Rectangle;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.event.KeyEvent;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;
import java.util.Random;

import javax.imageio.ImageIO;

import matematcbase.Matrix4x4;
import matematcbase.Vector3f;

import obj.ObjModel;

import org.lwjgl.BufferUtils;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import org.lwjgl.opengl.EXTTextureFilterAnisotropic;
import org.lwjgl.util.vector.Vector2f;

import org.newdawn.slick.opengl.Texture;
import org.newdawn.slick.opengl.TextureLoader;

import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.util.glu.GLU.*;

/*
 * Created on 21/03/2010
 * Atualizado Para Ver��o 1.0
 * Desenvolvido Por Dennis Kerr Coelho
 * PalmSoft Tecnologia
 */

public class CanvasGame extends PS_3DCanvas {

	private final static double CAMERA_Z = -8.0;
	private final static double FOVY = 45.0; // field-of-view angle around Y

	private final static double NEAR = 0.1; // Z values < NEAR are clipped
	private final static double FAR = 30.0; // Z values > FAR are clipped

	// private GLU glu = new GLU ();

	// Graphics2D dbg = null;

	// Do not generate a rotation increment greater than MAX_ROT_INC degrees.

	private final static float MAX_ROT_INC = 15.0f;

	// Total and increment rotation variables.

	public static float rotAngleX, rotAngleY, rotAngleZ;
	private float incX, incY, incZ;
	private float angTX, angTY, angTZ;
	private float Px, Py, Pz;

	public static Texture[] textures;

	private Vector2f quadPosition;
	private Vector2f quadVelocity;
	private float angle;
	private float angleRotation = 1.0f;
	private static final float MAX_SPEED = 20.0f;

	// Vector3f v = new Vector3f(0,0,1);
	// Vector3f v1 = new Vector3f(0,1,0);
	// Vector3f v2 = new Vector3f(1,0,0);

	public static ArrayList<objeto3d> listadeobjetos = new ArrayList<objeto3d>();

	boolean MatrixOpengl = true;

	ObjModel model1;

	Random rnd = new Random();

	float vel = 0.5f;
	Cubo cubo = new Cubo();
	Rectangle rectangle = new Rectangle(1.0f, 2.5f);

	public CanvasGame() {

		// for(int i = 0; i < 100;i++){
		// listadeobjetos.add(new
		// meuObjeto((float)((Math.random()*8)-4),(float)((Math.random()*8)-4),(float)((Math.random()*8)-4)));
		// }

		model1 = new ObjModel();
		model1.loadObj("/tank.obj");

		for (int i = 0; i < 20; i++) {
			Esfera esfera = new Esfera((float) (-2 + (Math.random() * 4)),
					(float) (-2 + (Math.random() * 4)),
					(float) (-2 + (Math.random() * 4)),
					0.1f + ((float) (0.2 * Math.random())));
			boolean colidiu = false;
			do {
				colidiu = false;
				esfera.X = (float) (-2 + (Math.random() * 4));
				esfera.Y = (float) (-2 + (Math.random() * 4));
				esfera.Z = (float) (-2 + (Math.random() * 4));
				esfera.setCorR((float) Math.random());
				esfera.setCorG((float) Math.random());
				esfera.setCorB((float) Math.random());
				esfera.setVx((vel + rnd.nextFloat() * vel)
						* (rnd.nextFloat() > 0.5 ? 1 : -1));
				// esfera.vy =
				// (vel+rnd.nextFloat()*vel)*(rnd.nextFloat()>0.5?1:-1);
				esfera.setVy((-9.8f));
				esfera.setVz((vel + rnd.nextFloat() * vel)
						* (rnd.nextFloat() > 0.5 ? 1 : -1));

				for (int j = 0; j < listadeobjetos.size(); j++) {
					Esfera es = (Esfera) CanvasGame.listadeobjetos.get(j);
					if (esfera.colideesfera(es)) {
						colidiu = true;
						break;
					}
				}
			} while (colidiu);
			listadeobjetos.add(esfera);
		}

	}

	@Override
	public void init() {

		Px = 0;
		Py = 0;
		Pz = 0;

		glEnable(GL_DEPTH_TEST);

		glEnable(GL_LIGHTING);

		// Initialize rotation accumulator and increment variables.

		rotAngleX = rotAngleY = rotAngleZ = 0.0f;

		rotAngleX = 0.0f;

		Random rand = new Random();
		incX = 1;// rand.nextFloat ()*MAX_ROT_INC;
		incY = 1;// rand.nextFloat ()*MAX_ROT_INC;
		incZ = 1;// rand.nextFloat ()*MAX_ROT_INC;

		angTX = angTY = angTZ = 0;

		// Load six 2D textures to decal the cube. If the image file on which
		// the
		// texture is based does not exist, load() returns null.
		textures = new Texture[2];
		// try {
		//
		// textures [0] = TextureLoader.getTexture("PNG",
		// this.getClass().getResourceAsStream("LogoUNIVALI.png"));
		// textures [1] = TextureLoader.getTexture("PNG",
		// this.getClass().getResourceAsStream("textura-tanque.png"));
		// } catch (FileNotFoundException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// } catch (IOException e) {
		// // TODO Auto-generated catch block
		// e.printStackTrace();
		// }
		//
		// textures [0].bind();
		//

		// int twidth = (int)textures [0].getImageWidth();
		// int theight = (int)textures [0].getImageHeight();
		//
		// System.out.println("twidth "+twidth+" theight "+theight+" texdata ");

		// ByteBuffer buffer = BufferUtils.createByteBuffer((textures
		// [0].hasAlpha() ? 4 : 3) * twidth * theight);
		// //System.out.println("buffer.capacity() "+buffer.capacity());
		// glGetTexImage(GL_TEXTURE_2D, 0, textures [0].hasAlpha() ? GL_RGBA :
		// GL_RGB, GL_UNSIGNED_BYTE, buffer);

		// int components = textures [0].hasAlpha() ? 4 : 3;
		//
		// System.out.println("components "+components);
		// gluBuild2DMipmaps(GL_TEXTURE_2D, components, twidth, theight,
		// components==3 ? GL_RGB : GL_RGBA, GL_UNSIGNED_BYTE,buffer);
		//
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);

		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);// GL_LINEAR_MIPMAP_LINEAR);
		// glTexParameteri(GL_TEXTURE_2D,
		// EXTTextureFilterAnisotropic.GL_TEXTURE_MAX_ANISOTROPY_EXT, 8);

		// glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);

		int width = GameMain.instance.display_parent.getWidth();
		int height = GameMain.instance.display_parent.getHeight();

		glMatrixMode(GL_PROJECTION);
		glLoadIdentity();
		float aspect = (float) width / (float) height;
		gluPerspective((float) FOVY, (float) aspect, (float) NEAR, (float) FAR);
		glMatrixMode(GL_MODELVIEW);

		// glMatrixMode(GL_PROJECTION);
		// glLoadIdentity();
		// gluOrtho2D(0, GameMain.instance.display_parent.getWidth(), 0,
		// GameMain.instance.display_parent.getHeight());
		// glMatrixMode(GL_MODELVIEW);
		// glLoadIdentity();
		// glViewport(0, 0, GameMain.instance.display_parent.getWidth(),
		// GameMain.instance.display_parent.getHeight());
		// //set clear color to black
		// glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
		// //sync frame (only works on windows)
		// Display.setVSyncEnabled(true);
		// //System.out.println("Inicio");

	}

	int keytimer = 0;

	@Override
	public void SimulaSe(double diftime) {

		keytimer += diftime;

		if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
			rotAngleX += (diftime / 10.0f);
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
			rotAngleX -= (diftime / 10.0f);
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_LEFT)) {
			rotAngleY += (diftime / 10.0f);
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_RIGHT)) {
			rotAngleY -= (diftime / 10.0f);
		}

		if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
			Py += (diftime / 100.0f);
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
			Py -= (diftime / 100.0f);
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
			Px += (diftime / 100.0f);
		}
		if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
			Px -= (diftime / 100.0f);
		}

		if (Keyboard.isKeyDown(Keyboard.KEY_F1) && keytimer > 200) {
			MatrixOpengl = !MatrixOpengl;
			keytimer = 0;
		}

		for (int i = 0; i < listadeobjetos.size(); i++) {
			listadeobjetos.get(i).simulaSe((int) diftime);
		}

		// if(UP){
		// rotAngleX = (float)(90.0f*diftime/1000.0f);
		// Matrix4x4 m = new Matrix4x4();
		// m.setRotate(rotAngleX, v2.x, v2.y, v2.z);
		// m.transform(v);
		// m.transform(v1);
		// m.transform(v2);
		// v.Normalize();
		// v1.Normalize();
		// v2.Normalize();
		// }
		// if(DOWN){
		// rotAngleX = -(float)(90.0f*diftime/1000.0f);
		// Matrix4x4 m = new Matrix4x4();
		// m.setRotate(rotAngleX, v2.x, v2.y, v2.z);
		// m.transform(v);
		// m.transform(v1);
		// m.transform(v2);
		// v.Normalize();
		// v1.Normalize();
		// v2.Normalize(); }
		//
		//
		//
		// if(RIGHT){
		// rotAngleY =(float)(90.0f*diftime/1000.0f);
		// Matrix4x4 m = new Matrix4x4();
		// m.setRotate(rotAngleY, v1.x, v1.y, v1.z);
		// m.transform(v);
		// m.transform(v1);
		// m.transform(v2);
		// v.Normalize();
		// v1.Normalize();
		// v2.Normalize(); }
		// if(LEFT){
		// rotAngleY = -(float)(90.0f*diftime/1000.0f);
		// Matrix4x4 m = new Matrix4x4();
		// m.setRotate(rotAngleY, v1.x, v1.y, v1.z);
		// m.transform(v);
		// m.transform(v1);
		// m.transform(v2);
		// v.Normalize();
		// v1.Normalize();
		// v2.Normalize();
		// }
		//
		//
		// if(TQ){
		// rotAngleZ =(float)(90.0f*diftime/1000.0f);
		// Matrix4x4 m = new Matrix4x4();
		// m.setRotate(rotAngleZ, v.x, v.y, v.z);
		// m.transform(v);
		// m.transform(v1);
		// m.transform(v2);
		// v.Normalize();
		// v1.Normalize();
		// v2.Normalize(); }
		// if(TE){
		// rotAngleZ = -(float)(90.0f*diftime/1000.0f);
		// Matrix4x4 m = new Matrix4x4();
		// m.setRotate(rotAngleZ, v.x, v.y, v.z);
		// m.transform(v);
		// m.transform(v1);
		// m.transform(v2);
		// v.Normalize();
		// v1.Normalize();
		// v2.Normalize();
		// }
		//
		// if(TW){
		// X+=v.x*4*diftime/1000.0f;
		// Y+=v.y*4*diftime/1000.0f;
		// Z+=v.z*4*diftime/1000.0f;
		// }
		// if(TS){
		// X-=v.x*4*diftime/1000.0f;
		// Y-=v.y*4*diftime/1000.0f;
		// Z-=v.z*4*diftime/1000.0f;
		// }

		// if(TA){
		// X+=v1.x*4*diftime/1000.0f;
		// Y+=v1.y*4*diftime/1000.0f;
		// Z+=v1.z*4*diftime/1000.0f;
		// }
		// if(TD){
		// X-=v1.x*4*diftime/1000.0f;
		// Y-=v1.y*4*diftime/1000.0f;
		// Z-=v1.z*4*diftime/1000.0f;
		// }

	}

	float soma = 0;

	@Override
	public void DesenhaSe() {
		// Compute total rotations around X, Y, and Z axes.
		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

		glLoadIdentity();

		soma += 1.0;

		float[] lightDiffuse = { 1.0f, 1.0f, 1.0f, 1.0f }; // yellow diffuse :
															// color where light
															// hit directly the
															// object's surface
		float[] lightAmbient = { 1.0f, 1.0f, 1.0f, 1.0f }; // red ambient :
															// color applied
															// everywhere
		float[] lightPosition = { 0.0f, 0.0f, (float) 1.0, 1.0f };

		ByteBuffer temp = ByteBuffer.allocateDirect(16);
		temp.order(ByteOrder.nativeOrder());
		glLight(GL_LIGHT0, GL_AMBIENT,
				(FloatBuffer) temp.asFloatBuffer().put(lightAmbient).flip());
		glLight(GL_LIGHT0, GL_DIFFUSE,
				(FloatBuffer) temp.asFloatBuffer().put(lightDiffuse).flip());
		glLight(GL_LIGHT0, GL_POSITION,
				(FloatBuffer) temp.asFloatBuffer().put(lightPosition).flip());

		glEnable(GL_LIGHT0);

		gluLookAt(0.0f, 0.0f, (float) CAMERA_Z, 0.0f, 0.0f, 0.0f, 0.0f, 1.0f,
				0.0f);

		// Perform the rotations.

		if (MatrixOpengl) {
			glRotatef(rotAngleX, 1.0f, 0.0f, 0.0f);
			glTranslatef(0.0f, 0.0f, -Py);
		} else {
			Matrix4x4 m = new Matrix4x4();
			// m.setRotateX(rotX);
			m.setRotate(rotAngleX, 1.0f, 0.0f, 0.0f);
			glMultMatrix(m.toFloatBuffer());
			System.out.println("rodando na unha");
		}
		glRotatef(rotAngleY, 0.0f, 1.0f, 0.0f);
		glRotatef(rotAngleZ, 0.0f, 0.0f, 1.0f);

		// clear background
		// glEnable(GL_COLOR_MATERIAL);
		// glClear(GL_COLOR_BUFFER_BIT);
		// // draw white quad

		glEnable(GL_TEXTURE_2D);

		Texture texture = textures[1];

		// texture.bind ();

		// glPushMatrix();
		// {
		// glScaled(0.04, 0.04, 0.04);
		// model1.desenhase();
		// } glPopMatrix();

		texture = textures[0];

		// texture.bind ();

		// glPushMatrix();
		// {
		//
		// if(MatrixOpengl){
		// glTranslatef(Px, Py, Pz);
		// }else{
		// Matrix4x4 m = new Matrix4x4();
		// m.setIdentity();
		// //m.setRotateX(rotX);
		// m.setTranslate(new Vector3f(Px, Py, Pz));
		// glMultMatrix(m.toFloatBuffer());
		// System.out.println("rodando na unha");
		// }
		//
		//

		glDisable(GL_TEXTURE_2D);
		glEnable(GL_COLOR_MATERIAL);
		// glClear(GL_COLOR_BUFFER_BIT);

		FloatBuffer fb = ByteBuffer.allocateDirect(64).asFloatBuffer();
		glGetFloat(GL_MODELVIEW_MATRIX, fb);

		glLoadIdentity();

		glMultMatrix(fb);

		for (int i = 0; i < listadeobjetos.size(); i++) {
			listadeobjetos.get(i).desenhaSe();
		}

		cubo.desenhase(2.5f, 2.5f, 2.5f);
		glPushMatrix();
		glColor3f(0, 1, 0);
		glTranslatef(0, 0, 1);
		
		glRotatef(60, 0, 1, 0);
		glRotatef(40, 1, 0, 0);
		glTranslatef(0, -0.7f, 0);
		rectangle.drawRectangle2D();
		glPopMatrix();
		glColor3f(1.0f, 1.0f, 1.0f);
		glDisable(GL_COLOR_MATERIAL);
		// glClear(GL_COLOR_BUFFER_BIT);

		// System.out.println("pinta");
	}

	@Override
	public void reshape(int x, int y, int width, int height) {
		// TODO Auto-generated method stub

	}

	// Texture load (String filename,GL gl)
	// {
	// Texture texture = null;
	//
	// try
	// {
	//
	// System.out.println(" "+new
	// File(getClass().getResource(filename).toString()));
	//
	// InputStream stream = getClass().getResourceAsStream(filename);
	// TextureData data = TextureIO.newTextureData(stream, false, "png");
	//
	//
	// data.setMipmap(true);
	//
	// texture = TextureIO.newTexture (data);
	//
	//
	// texture.setTexParameteri (GL_TEXTURE_MAG_FILTER, GL_LINEAR);
	//
	//
	// texture.setTexParameteri (GL_TEXTURE_MIN_FILTER,
	// GL_LINEAR_MIPMAP_NEAREST);
	//
	// }
	// catch (Exception e)
	// {
	// System.out.println ("error loading texture from "+filename);
	// }
	//
	// return texture;
	// }

}

and this is the Sphere class


package geometries;

import static org.lwjgl.opengl.GL11.GL_COLOR_MATERIAL;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnable;
import static org.lwjgl.opengl.GL11.glPopMatrix;
import static org.lwjgl.opengl.GL11.glPushMatrix;
import static org.lwjgl.opengl.GL11.glTranslatef;

import org.lwjgl.util.glu.Sphere;

import coreEngine.CanvasGame;
import coreEngine.objeto3d;

public class Esfera extends objeto3d {

	float R;

	private float vx = 0;
	private float vy = 0;
	private float vz = 0;

	public float dy = 0;

	private float corR = 1;
	private float corG = 1;
	private float corB = 1;

	public float getVx() {
		return vx;
	}

	public void setVx(float vx) {
		this.vx = vx;
	}

	public float getVy() {
		return vy;
	}

	public void setVy(float vy) {
		this.vy = vy;
	}

	public float getVz() {
		return vz;
	}

	public void setVz(float vz) {
		this.vz = vz;
	}

	public float getCorR() {
		return corR;
	}

	public void setCorR(float corR) {
		this.corR = corR;
	}

	public float getCorG() {
		return corG;
	}

	public void setCorG(float corG) {
		this.corG = corG;
	}

	public float getCorB() {
		return corB;
	}

	public void setCorB(float corB) {
		this.corB = corB;
	}

	Sphere sphere;

	float grav = 9.8f;
	float perdaDeEnergia = 20;
	float energia = 0;

	public Esfera(float X, float Y, float Z, float R) {
		this.X = X;
		this.Y = Y;
		this.Z = Z;

		this.R = R;

		sphere = new Sphere();

		this.dy = this.energia = 50;

	}

	@Override
	public void desenhaSe() {
		glEnable(GL_COLOR_MATERIAL);
		glColor3f(corR, corG, corB);
		glPushMatrix();
		glTranslatef(X, Y, Z);
		sphere.draw(R, 10, 10);
		glPopMatrix();
	}

	@Override
	public void simulaSe(int diftime) {
		float oldx = X;
		float oldy = Y;
		float oldz = Z;

		// TENTATIVA FRACASSADA
		X += vx * diftime / 1000.0f;
		// Y += vy*diftime/1000.0f;
		Z += vz * diftime / 1000.0f;
		// Y += (vy*diftime/1000.0f)*grav;
		/*
		 * if(energia > 0){ if (this.dy > 0) { Y += (vy*diftime/1000.0f); dy--;
		 * }else{ Y -= (vy*diftime/1000.0f); } }
		 */

		// Gravidade
		float tempo = (float) (diftime / 1000.0f);
		Y -= (vy * tempo) + (grav * (float) Math.pow(tempo, 2)) / 2.0f;
		vy += grav * tempo;
		vy = (vy > 40.0f) ? 40.0f : vy;

		vx = (vx > 40.0f) ? 40.0f : vx;
		vz = (vz > 40.0f) ? 40.0f : vz;

		for (int i = 0; i < CanvasGame.listadeobjetos.size(); i++) {
			Esfera es = (Esfera) CanvasGame.listadeobjetos.get(i);
			if (es != this) {
				if (colideesfera(es)) {
					X = oldx;
					Y = oldy;
					Z = oldz;

					if (vx > 0) {
						vx = vx - (perdaDeEnergia * R);
						vx = -vx;
					} else {
						vx = vx + (perdaDeEnergia * R);
						vx = -vx;
					}

					vy = vy - (perdaDeEnergia * R);
					vy = -vy;

					if (vz > 0) {
						vz = vz - (perdaDeEnergia * R);
						vz = -vz;
					} else {
						vx = vz + (perdaDeEnergia * R);
						vz = -vz;
					}

					break;
				}
			}
		}

		if (X < -2) {
			X = oldx;
			vx = -vx;
		}

		if (X > 2) {
			X = oldx;
			vx = -vx;
		}

		if (Y < -2.2f) {
			Y = oldy;
			vy = vy - (perdaDeEnergia * R);
			vy = -vy;
		}

		if (Y > 2) {
			// Y = oldy;
			// vy = vy - (perdaDeEnergia*R);
			// vy = -vy;
			// energia -= (perdaDeEnergia*R);
			// System.out.println(vy);
		}

		if (Z < -2) {
			Z = oldz;
			vz = -vz;
		}

		if (Z > 2) {
			Z = oldz;
			vz = -vz;
		}
	}

	public boolean colideesfera(Esfera esf) {

		float difx = esf.X - X;
		float dify = esf.Y - Y;
		float difz = esf.Z - Z;

		float dist = difx * difx + dify * dify + difz * difz;

		if (((esf.R + R) * (esf.R + R)) > dist) {
			return true;
		}

		return false;
	}
}