Jirr Physics - ODEJava

Discussion about Irrlicht's Java wrapper
Post Reply
de3000
Posts: 20
Joined: Tue Sep 19, 2006 4:57 pm
Location: South Africa

Jirr Physics - ODEJava

Post by de3000 »

I saw some other Jirr stuff on here so decided to post my question here.

Has anybody using Jirr used ant physics? Only good physics that might work wih Jirr is ODEJava. Does anyone have any examples for Jirr with Physics?

noobs first post :) lol
jestermax
Posts: 17
Joined: Mon Feb 26, 2007 4:36 pm

Java/Jirr + Physics

Post by jestermax »

Hey there, just refreshing this thread as i just got started with Jirr (Java + Irrlicht). i'm looking for a decent physics library just like the previous poster. Any ideas?
jestermax
Posts: 17
Joined: Mon Feb 26, 2007 4:36 pm

Post by jestermax »

WOW, i just replied to my own post, lol.

any updates on those physics?
jirr
Posts: 36
Joined: Sat Feb 19, 2005 8:05 am

Post by jirr »

Well, to make it short: I have not started working with odejava yet (though there is an tutorial for irrlicht and ode: http://irrlicht.sourceforge.net/tut_ode.html)- since it seems development of that one has been stopped. Also I think it is difficult to get the latest working version? Maybe somebody else could help?

Furthermore there exists a new pure java physics engine (alpha or early beta status?) named JOODE ( https://joode.dev.java.net/ ) which is under development and seems to be a port of ode to pure java.

Also I stumbled over JNewton: https://sourceforge.net/projects/jnewton . Sadly the released version 0.1 crashes on my system when it comes to activating gravity.
Nevertheless - after contacting the developer - there is a new version available: 0.2

And by the way: I just tried it out in a simple hacked down example using the new libs. Any required textures and objects can be found in the binary distrbution of jirr.
I know that rotation is in the demo but should be reworked since i am quite sure I am doing it in a wrong way (wrong maths) - so maybe somebody else could fix that in the meantime? A starting point would be http://irrlicht.sourceforge.net/tut_newton.html though it seems to require an update itself.

So just take this as a starting point for further physics :D

Code: Select all

import net.sf.jirr.*;

import java.awt.event.KeyEvent;
import java.util.ArrayList;
import java.nio.FloatBuffer;

import org.jnewton.*;
import org.jnewton.util.BufferUtils;
import org.jnewton.util.math.Inertia;

/**
 * This Tutorial shows how to use JNewton with jirr.
 * The basic concept is to let newton decide the positions of each related ISceneNode
 * <p/>
 * (c) 2007 jirr - https://sourceforge.net/projects/jirr/
 */
public class TestNewton2
{
	static
	{
		System.loadLibrary("irrlicht_wrap");
		System.loadLibrary("Newton");
		System.loadLibrary("JNewton");
	}

	/*
	 * In this tutorial, one of our goals is to move several scene nodes using a physics engine.
	 * But at first we do need some irrlicht related stuff.
	  *
	   * Note: In a real world app you will not always want this variables to be static but who cares in a demo? ;)
	 */

	static IrrlichtDevice device = null;
	static IVideoDriver driver = null;
	static ISceneManager smgr = null;

	static boolean isRunning = true;

	/*
	 * To get events like mouse and keyboard input, or GUI events like
	 * "the OK button has been clicked", we need an object wich is derived from the
	 * IEventReceiver object. There is only one method to override: OnEvent.
	 * This method will be called by the engine when an event happened.
	 * We will use this input to move the scene node with the keys W and S.
	 */
	static class MyEventReceiver extends IEventReceiver
	{
		public boolean OnEvent(SEvent event)
		{
			/*
			ESC will end the demo
			*/
			if (event.getEventType() == EEVENT_TYPE.EET_KEY_INPUT_EVENT &&
			    !event.isKeyInputPressedDown())
			{
				switch (event.getKeyInputChar())
				{
					case KeyEvent.VK_ESCAPE:
						isRunning = false;
				}
			}

			return false;
		}
	}

	/**
	 * Demo title
	 */
	public static final String DEMO_TITLE = "Newton Demo";

	/*
	 * Newton related variables - please keep in mind that irrlicht nodes do not knwo physics related newton nodes
	 * - that is why we are dubbling the numbers of nodes currently. Nevertheless you are free to add own classes
	 * that suit both worlds.
	 */
	static NewtonWorld world;
	static NewtonBody floor;
	static INewtonBodyIterator forimp;

	/*
	 *  Two float buffers
	 */
	private static final FloatBuffer BUFF = BufferUtils.createFloatBuffer(16);
	private static final FloatBuffer BUFF2 = BufferUtils.createFloatBuffer(16);

	/*
	 * Yep, two arrays for carrying both worlds' objects. Newton and irrlicht
	 */
	public static ArrayList<NewtonBody> list = new ArrayList<NewtonBody>();
	public static ArrayList<ISceneNode> nodeList = new ArrayList<ISceneNode>();

	/**
	 * Initialise the demo
	 *
	 * @throws Exception if init fails
	 */
	protected static void init() throws Exception
	{
		// Create a window with mouse and keyboard inputs.
		// just in case you want to watch this in fullscreen resolution
		boolean fullscreen = false;

		TestNewton2.MyEventReceiver receiver = new TestNewton2.MyEventReceiver();
		device = Jirr.createDevice(E_DRIVER_TYPE.EDT_OPENGL, new dimension2di(640, 480), 16, fullscreen, false, false, receiver);

		driver = device.getVideoDriver();
		smgr = device.getSceneManager();

		ICameraSceneNode cameraSceneNode = smgr.addCameraSceneNodeFPS(null, 100.0f, 100.0f);
		cameraSceneNode.setPosition(new vector3df(-10, 0, -10));
		cameraSceneNode.setTarget(new vector3df(0, 0, 0));

		// anyone wanting a visible floor?
		ISceneNode n = smgr.addCubeSceneNode();
		n.setMaterialTexture(0, driver.getTexture("../media/t351sml.jpg"));
		n.setMaterialFlag(E_MATERIAL_FLAG.EMF_LIGHTING, false);
		n.setPosition(new vector3df(0, -5, 0));
		n.setScale(new vector3df(10, 0.1f, 10));

		// Set the name of the game - err - demo
		device.setWindowCaption(DEMO_TITLE);

		// It is a newton world
		world = JNewton.NewtonCreate();
		NewtonCollision col = JNewton.NewtonCreateBox(world, 1f, 1f, 1f, null);

		JNewton.NewtonSetMinimumFrameRate(world, 60f);
		JNewton.NewtonSetSolverModel(world, 2);
		JNewton.NewtonSetFrictionModel(world, 1);
		BUFF.clear();
		BUFF2.clear();
		BUFF.put(new float[]{-100f, -100f, -100f}).rewind();
		BUFF2.put(new float[]{100f, 100f, 100f}).rewind();
		JNewton.NewtonSetWorldSize(world, BUFF, BUFF2);

		/**
		 * Hey, Newton is nothing without mass and graviy
		 */
		INewtonApplyForceAndTorque imp = new INewtonApplyForceAndTorque()
		{
			private final FloatBuffer buff = BufferUtils.createFloatBuffer(4);

			public void NewtonApplyForceAndTorque(NewtonBody body)
			{
				JNewton.NewtonBodyGetMassMatrix(body, buff);
				float g = buff.get(0) * -9.8f;
				buff.put(0, 0f).put(1, g).put(2, 0f).put(3, 0f).rewind();
				JNewton.NewtonBodyAddForce(body, buff);
			}
		};

		// creating some nodes is fun - always! So let's prepare a simple iterator for setting random positions	
		forimp = new INewtonBodyIterator()
		{
			private final FloatBuffer buff = BufferUtils.createFloatBuffer(4);

			public void NewtonBodyIterator(NewtonBody body)
			{
				buff.put(0, (float) Math.random() * 5f);
				buff.put(1, (float) Math.random() * 5f);
				buff.put(2, (float) Math.random() * 5f);
				buff.rewind();

				JNewton.NewtonBodySetOmega(body, buff);
			}
		};

		// Collisions - anyone listening to collisions? - Not integrated into this demo currently ...
		INewtonCollisionIterator coliter = new INewtonCollisionIterator()
		{
			public void NewtonCollisionIterator(NewtonBody body, int vertexCount, FloatBuffer faceArray, int faceId)
			{
				System.out.println("" + vertexCount + " " + BufferUtils.toString(faceArray) + " " + faceId);
			}
		};

		// creating some nodes is fun - always!
		NewtonBody body;
		int max = 5;
		float offset = 0f;
		float[] inert = Inertia.getCubeInertia(1f, 2f);
		for (float x = -max; x < max; x += 2)
		{
			for (float y = -max; y < max; y += 2)
			{
				for (float z = -max; z < max; z += 2)
				{
					body = JNewton.NewtonCreateBody(world, col);
					BUFF.clear();
					BUFF.put(
							new float[]{1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
							            x, y + 5f, z + offset, 1}).rewind();
					JNewton.NewtonBodySetMatrix(body, BUFF);
					JNewton.NewtonBodySetMassMatrix(body, 2f, inert[0], inert[1], inert[2]);
					JNewton.NewtonBodySetForceAndTorqueCallback(body, imp);

					//   Someone wanting to transform anything?
					//   - Then just finish this part and mail the result to the jirr project, please!
					//JNewton.NewtonBodySetTransformCallback(body, imptrans);

					JNewton.NewtonBodySetAutoFreeze(body, 1);

					list.add(body);

					// happy irrlicht nodes
					ISceneNode node = smgr.addCubeSceneNode();
					node.setPosition(new vector3df(x, y, z));
					node.setMaterialTexture(0, driver.getTexture("../media/wall.jpg"));
					node.setMaterialFlag(E_MATERIAL_FLAG.EMF_LIGHTING, false);
					node.setMaterialType(E_MATERIAL_TYPE.EMT_TRANSPARENT_VERTEX_ALPHA);
					node.setScale(new vector3df(0.1f, 0.1f, 0.1f));
					nodeList.add(node);
				}
				offset += .1f;
			}
		}
		JNewton.NewtonReleaseCollision(world, col);
		JNewton.NewtonWorldForEachBodyDo(world, forimp);

		col = JNewton.NewtonCreateBox(world, 100f, 2f, 100f, null);
		floor = JNewton.NewtonCreateBody(world, col);
		JNewton.NewtonBodySetMassMatrix(floor, 0f, 0f, 0f, 0f);

		BUFF.clear();
		BUFF.put(
				new float[]{1, 0, 0, 0,
				            0, 1, 0, 0,
				            0, 0, 1, 0,
				            0, -5, 0, 1}).flip();
		JNewton.NewtonBodySetMatrix(floor, BUFF);

		JNewton.NewtonReleaseCollision(world, col);
		//JNewton.NewtonBodyForEachPolygonDo(floor, coliter);
	}

	/**
	 * Runs the demo (the "main loop")
	 */
	private static void run()
	{
		while (isRunning && device.run())
		{
			if (device.isWindowActive())
			{
				// The window is in the foreground, so we should play the scenes
				update();
				driver.beginScene(true, true, new SColor(255, 113, 113, 133));
				smgr.drawAll();
				driver.endScene();
				render();
			}
			else
			{
				// The window is not in the foreground, so we can allow other stuff to run and
				// infrequently update
				try
				{
					Thread.sleep(100);
				}
				catch (InterruptedException e)
				{
				}
				update();
				driver.beginScene(true, true, new SColor(255, 113, 113, 133));
				smgr.drawAll();
				driver.endScene();
				render();
			}
		}

		device.drop();
	}

	/**
	 * Do any demo-specific cleanup
	 */
	private static void cleanup()
	{
		JNewton.NewtonDestroy(world);
		System.exit(0);
	}

	static long start = System.currentTimeMillis();
	static long fps = System.currentTimeMillis();
	static int fpscount = 0;

	private static void update()
	{
		JNewton.NewtonUpdate(world, (float) (System.currentTimeMillis() - start));
		start = System.currentTimeMillis();
	}

	/**
	 * Render the current frame
	 */

	private static void render()
	{
		for (int i = 0; i < list.size(); i++)
		{
			JNewton.NewtonBodyGetMatrix(list.get(i), BUFF2);
			renderIrrlichtNode(BUFF2, nodeList.get(i));
		}

		fpscount++;
		if (System.currentTimeMillis() - fps >= 1000L)
		{
			fps = System.currentTimeMillis();
			System.out.println("FPS: " + fpscount);
			fpscount = 0;
		}
	}


	/* Two helper vars -just to reduce memory allocation and garbage collection overheads (speeds up by 15%)
	 *	Warning: This solution is not thread safe!
	 */
	static vector3df tempVectorPos = new vector3df();
	static vector3df tempVectorRot = new vector3df();

	/**
	 * rendering the irrlicht nodes
	 * @param aFloatBuffer a buffer containing 16 float elements (4x4 matrix)
	 * @param aISceneNode the irrlicht node to be drawn
	 */
	protected static void renderIrrlichtNode(FloatBuffer aFloatBuffer, ISceneNode aISceneNode)
	{
		// reusing of temp vector3df is faster than creating a new one
		tempVectorPos.setX(aFloatBuffer.get(12));
		tempVectorPos.setY(aFloatBuffer.get(13));
		tempVectorPos.setZ(aFloatBuffer.get(14));
		aISceneNode.setPosition(tempVectorPos);

		tempVectorRot.setX(90 * aFloatBuffer.get(0));
		tempVectorRot.setY(90 * aFloatBuffer.get(5));
		tempVectorRot.setZ(90 * aFloatBuffer.get(10));
		aISceneNode.setRotation(tempVectorRot);

// simpler but slower:
//			aNode.setPosition(new vector3df(m[12], m[13], m[14]));
//			aNode.setRotation(new vector3df(90*m[0], 90*m[5], 90*m[10]));
	}

	/**
	 * Application init - here we go on now!
	 *
	 * @param args Commandline args
	 */
	public static void main(String[] args)
	{
		try
		{
			init();
			run();
		}
		catch (Exception e)
		{
			e.printStackTrace(System.err);
			System.err.println(DEMO_TITLE + "An error occured and the demo will exit.");
		}
		finally
		{
			cleanup();
		}

		System.exit(0);
	}
}
jirr
Posts: 36
Joined: Sat Feb 19, 2005 8:05 am

Post by jirr »

Seems like I am contributing to the predecessors law: answering my own question. As I told you in my prior post the rotation needs some rework.

Ok.

Replace the nodes' rotation in the previous code

Code: Select all

//		tempVectorRot.setX(90 * aFloatBuffer.get(0));
//		tempVectorRot.setY(90 * aFloatBuffer.get(5));
//		tempVectorRot.setZ(90 * aFloatBuffer.get(10));
//		aISceneNode.setRotation(tempVectorRot);

		if (aFloatBuffer.hasArray())
		{
			aISceneNode.setRotation(getRotationDegrees(aFloatBuffer.array()));
		}
		else
		{
                        // Floatbuffer do not contain arrays in any case => do it by hand
			float array[] = new float[16];
			for (int i = 0; i < array.length; i++)
			{
				 array[i] = aFloatBuffer.get(i);				
			}
			aISceneNode.setRotation(getRotationDegrees(array));
		}
Second: Add a constant and a helper method (required because float M[] is private member of matrix4 in irrlicht 1.3 and a setter will not be available before 1.4):

Code: Select all

	final static double RADTODEG64 = 180.0 / Math.PI;

	static vector3df getRotationDegrees(float mat[])
	{

		double Y = -Math.asin(mat[0*4 + 2]);
		double C = Math.cos(Y);
		Y *= RADTODEG64;

		double rotx, roty, X, Z;

		if (Math.abs(C)>0.0005f)
		{
			rotx = mat[2*4 + 2] / C;
			roty = mat[1*4 + 2] / C;
			X = Math.atan2( roty, rotx ) * RADTODEG64;
			rotx = mat[0*4 + 0] / C;
			roty = mat[0*4 + 1] / C;
			Z = Math.atan2( roty, rotx ) * RADTODEG64;
		}
		else
		{
			X = 0.0f;
			rotx = mat[1*4 + 1];
			roty = -mat[1*4 + 0];
			Z = Math.atan2( roty, rotx ) * RADTODEG64;
		}

		// fix values that get below zero
		// before it would set (!) values to 360
		// that where above 360:
		if (X < 0.0) X += 360.0;
		if (Y < 0.0) Y += 360.0;
		if (Z < 0.0) Z += 360.0;

		return new vector3df((float)X,(float)Y,(float)Z);
	}
That's it for correct rotations ;)
jestermax
Posts: 17
Joined: Mon Feb 26, 2007 4:36 pm

Post by jestermax »

wow, thanks for the code :) i'll have to give this stuff another wack and see what i can come up with

Edit: when i get a chance, i plan on checking out that irrlicht + ode tutorial. i'll see if i can convert it to jirr + jode :)
Post Reply