All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.ode4j.demo.DemoCrash Maven / Gradle / Ivy

/*************************************************************************
 *                                                                       *
 * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith.       *
 * All rights reserved.  Email: [email protected]   Web: www.q12.org          *
 * Open Dynamics Engine 4J, Copyright (C) 2009-2014 Tilmann Zaeschke     *
 * All rights reserved.  Email: [email protected]   Web: www.ode4j.org        *
 *                                                                       *
 * This library is free software; you can redistribute it and/or         *
 * modify it under the terms of EITHER:                                  *
 *   (1) The GNU Lesser General Public License as published by the Free  *
 *       Software Foundation; either version 2.1 of the License, or (at  *
 *       your option) any later version. The text of the GNU Lesser      *
 *       General Public License is included with this library in the     *
 *       file LICENSE.TXT.                                               *
 *   (2) The BSD-style license that is included with this library in     *
 *       the file ODE-LICENSE-BSD.TXT and ODE4J-LICENSE-BSD.TXT.         *
 *                                                                       *
 * This library is distributed in the hope that it will be useful,       *
 * but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files    *
 * LICENSE.TXT, ODE-LICENSE-BSD.TXT and ODE4J-LICENSE-BSD.TXT for more   *
 * details.                                                              *
 *                                                                       *
 *************************************************************************/
package org.ode4j.demo;

import org.ode4j.drawstuff.DrawStuff.dsFunctions;
import org.ode4j.math.DMatrix3;
import org.ode4j.math.DQuaternion;
import org.ode4j.math.DVector3;
import org.ode4j.math.DVector3C;
import org.ode4j.ode.DBox;
import org.ode4j.ode.DFixedJoint;
import org.ode4j.ode.DHinge2Joint;
import org.ode4j.ode.DSapSpace;
import org.ode4j.ode.DSphere;
import org.ode4j.ode.OdeHelper;
import org.ode4j.ode.DBody;
import org.ode4j.ode.DContact;
import org.ode4j.ode.DContactBuffer;
import org.ode4j.ode.DGeom;
import org.ode4j.ode.DJoint;
import org.ode4j.ode.DJointGroup;
import org.ode4j.ode.DMass;
import org.ode4j.ode.DSpace;
import org.ode4j.ode.DWorld;
import org.ode4j.ode.DGeom.DNearCallback;

import static org.ode4j.drawstuff.DrawStuff.*;
import static org.ode4j.ode.OdeMath.*;


/**
 * This is a demo of the QuickStep and StepFast methods,
 * originally by David Whittaker.
 */
class DemoCrash extends dsFunctions {

	// some constants

	private static final float LENGTH = 3.5f;		// chassis length
	private static final float WIDTH = 2.5f;		// chassis width
	private static final float HEIGHT = 1.0f;		// chassis height
	private static final float RADIUS = 0.5f;	// wheel radius
	private static final float STARTZ = 1.0f;	// starting height of chassis
	private static final float CMASS = 1;			// chassis mass
	private static final float WMASS = 1;			// wheel mass
	private static final float COMOFFSET = -5;		// center of mass offset
	private static final float WALLMASS = 1	;	// wall box mass
	private static final float BALLMASS = 1;		// ball mass
	private static final float FMAX = 25;			// car engine fmax
	private static final float ROWS = 1	;		// rows of cars
	private static final float COLS = 1	;		// columns of cars
	private static final int ITERS = 20;		// number of iterations
	private static final float WBOXSIZE = 1.0f;		// size of wall boxes
	private static final float WALLWIDTH = 12;		// width of wall
	private static final float WALLHEIGHT = 10;		// height of wall
	private static final float DISABLE_THRESHOLD = 0.008f;	// maximum velocity (squared) a body can have and be disabled
	private static final float DISABLE_STEPS = 10;	// number of steps a box has to have been disable-able before it will be disabled
	private static final float CANNON_X = -10;		// x position of cannon
	private static final float CANNON_Y = 5	;	// y position of cannon
	private static final float CANNON_BALL_MASS = 10;	// mass of the cannon ball
	private static final float CANNON_BALL_RADIUS = 0.5f;

	private static final DVector3C xunit = new DVector3(1, 0, 0);
	private static final DVector3C yunit = new DVector3(0, 1, 0);
	private static final DVector3C zpunit = new DVector3(0, 0, 1);
	private static final DVector3C zmunit = new DVector3(0, 0, -1);

//	private static boolean BOX = false;
//	private static boolean CARS = true;
//	private static boolean WALL = true;
//	private static boolean BALLS = false;
//	private static boolean BALLSTACK = false;
//	private static boolean ONEBALL = false;
//	private static boolean CENTIPEDE = false;
//	private static boolean CANNON = true;
	private static boolean BOX = false;
	private static boolean CARS = true;
	private static boolean WALL = true;
	private static boolean BALLS = false;
	private static boolean BALLSTACK = false;
	private static boolean ONEBALL = true;
	private static boolean CENTIPEDE = true;
	private static boolean CANNON = true;

	// dynamics and collision objects (chassis, 3 wheels, environment)

	private static DWorld world;
	private static DSpace space;
	private static DBody[] body=new DBody[10000];
	private static int bodies;
	private static DHinge2Joint[] joint=new DHinge2Joint[100000];
	private static int joints;
	private static DJointGroup contactgroup;
	//private static DGeom ground;
	private static DBox[] box=new DBox[10000];
	private static int boxes;
	private static DSphere[] sphere=new DSphere[10000];
	private static int spheres;
	private static DBox[] wall_boxes=new DBox[10000];
	private static DBody[] wall_bodies=new DBody[10000];
	private static DSphere cannon_ball_geom;
	private static DBody cannon_ball_body;
	private static int[] wb_stepsdis=new int[10000];
	private static int wb;
	private static boolean doFast;
	private static DBody b;
	private static DMass m;


	// things that the user controls

	private static float turn = 0, speed = 0;	// user commands
	private static float cannon_angle=0,cannon_elevation=-1.2f;


	private DNearCallback nearCallback = new DNearCallback() {
		@Override
		public void call(Object data, DGeom o1, DGeom o2) {
			nearCallback(data, o1, o2);
		}
	};

	// this is called by dSpaceCollide when two objects in space are
	// potentially colliding.

	private void nearCallback (Object data, DGeom o1, DGeom o2)
	{
		int i,n;

		DBody b1 = o1.getBody();
		DBody b2 = o2.getBody();
		if (b1!=null && b2!=null && OdeHelper.areConnected(b1, b2))
			return;

		final int N = 4;
		DContactBuffer contacts = new DContactBuffer(N);
		n = OdeHelper.collide (o1,o2,N,contacts.getGeomBuffer());//[0].geom,sizeof(dContact));
		if (n > 0) {
			for (i=0; i -20; x-=RADIUS*2)
				{
					body[bodies] = OdeHelper.createBody (world);
					body[bodies].setPosition(x, y, STARTZ);
					m.setSphere(1, RADIUS);
					m.adjust(WMASS);
					body[bodies].setMass(m);
					sphere[spheres] = OdeHelper.createSphere (space, RADIUS);
					sphere[spheres++].setBody (body[bodies]);

					joint[joints] = OdeHelper.createHinge2Joint (world,null);
					if (x == -17)
						joint[joints].attach (b,body[bodies]);
					else
						joint[joints].attach (body[bodies-2],body[bodies]);
					DVector3C a = body[bodies++].getPosition ();
					DHinge2Joint j = joint[joints++];
					j.setAnchor (a);
					j.setAxes (zpunit, xunit);
					j.setParamSuspensionERP (1.0);
					j.setParamSuspensionCFM (1e-5);
					j.setParamLoStop (0);
					j.setParamHiStop (0);
					j.setParamVel2 (-10.0);
					j.setParamFMax2 (FMAX);

					body[bodies] = OdeHelper.createBody (world);
					body[bodies].setPosition(-30 - x, y, STARTZ);
					m.setSphere(1, RADIUS);
					m.adjust(WMASS);
					body[bodies].setMass(m);
					sphere[spheres] = OdeHelper.createSphere (space, RADIUS);
					sphere[spheres++].setBody (body[bodies]);

					joint[joints] = OdeHelper.createHinge2Joint (world,null);
					if (x == -17)
						joint[joints].attach (b,body[bodies]);
					else
						joint[joints].attach (body[bodies-2],body[bodies]);
					DVector3C b = body[bodies++].getPosition ();
					j = joint[joints++];
					j.setAnchor (b);
					j.setAxes (zpunit, xunit);
					j.setParamSuspensionERP (1.0);
					j.setParamSuspensionCFM (1e-5);
					j.setParamLoStop (0);
					j.setParamHiStop (0);
					j.setParamVel2 (10.0);
					j.setParamFMax2 (FMAX);
				}
				if (lastb!=null)
				{
					DFixedJoint j = OdeHelper.createFixedJoint(world,null);
					j.attach (b, lastb);
					j.setFixed();
				}
				lastb = b;
			}
		}//#endif
		if (BOX) {//#ifdef BOX
			body[bodies] = OdeHelper.createBody (world);
			body[bodies].setPosition (0,0,HEIGHT/2);
			m.setBox (1,LENGTH,WIDTH,HEIGHT);
			m.adjust (1);
			body[bodies].setMass (m);
			box[boxes] = OdeHelper.createBox (space,LENGTH,WIDTH,HEIGHT);
			box[boxes++].setBody (body[bodies++]);	
		}//#endif
		if (CANNON) {//#ifdef CANNON
			cannon_ball_body = OdeHelper.createBody (world);
			cannon_ball_geom = OdeHelper.createSphere (space,CANNON_BALL_RADIUS);
			m.setSphereTotal (CANNON_BALL_MASS,CANNON_BALL_RADIUS);
			cannon_ball_body.setMass (m);
			cannon_ball_geom.setBody (cannon_ball_body);
			cannon_ball_body.setPosition (CANNON_X,CANNON_Y,CANNON_BALL_RADIUS);
		}//#endif
	}

	// called when a key pressed

	@Override
	public void command (char cmd)
	{
		switch (cmd) {
		case 'a': case 'A':
			speed += 0.3;
			break;
		case 'z': case 'Z':
			speed -= 0.3;
			break;
		case ',':
			turn += 0.1;
			if (turn > 0.3)
				turn = 0.3f;
			break;
		case '.':
			turn -= 0.1;
			if (turn < -0.3)
				turn = -0.3f;
			break;
		case ' ':
			speed = 0;
			turn = 0;
			break;
		case 'f': case 'F':
			doFast = !doFast;
			break;
		case 'r': case 'R':
			shutdownSimulation();
			setupSimulation();
			break;
		case '[':
			cannon_angle += 0.1;
			break;
		case ']':
			cannon_angle -= 0.1;
			break;
		case '1':
			cannon_elevation += 0.1;
			break;
		case '2':
			cannon_elevation -= 0.1;
			break;
		case 'x': case 'X': {
			DMatrix3 R2 = new DMatrix3(), R3 = new DMatrix3(), R4 = new DMatrix3();
			dRFromAxisAndAngle (R2,0,0,1,cannon_angle);
			dRFromAxisAndAngle (R3,0,1,0,cannon_elevation);
			dMultiply0 (R4,R2,R3);
			double[] cpos = {CANNON_X,CANNON_Y,1};
			for (int i=0; i<3; i++) cpos[i] += 3*R4.get(i, 2);//[i*4+2];
			cannon_ball_body.setPosition (cpos[0],cpos[1],cpos[2]);
			double force = 10;
			cannon_ball_body.setLinearVel (force*R4.get(0, 2),force*R4.get(1,2),force*R4.get(2,2));
			cannon_ball_body.setAngularVel (0,0,0);
			break;
		}
		}
	}


	// simulation loop

	private void simLoop (boolean pause)
	{
		int i, j;

		dsSetTexture (DS_TEXTURE_NUMBER.DS_WOOD);

		if (!pause) {
			if (BOX) {
				//dBodyAddForce(body[bodies-1],lspeed,0,0);
				body[bodies-1].addForce(speed,0,0);
			}
			for (j = 0; j < joints; j++)
			{
				DHinge2Joint j2 = joint[j];
				double curturn = j2.getAngle1 ();
				//dMessage (0,"curturn %e, turn %e, vel %e", curturn, turn, (turn-curturn)*1.0);
				j2.setParamVel((turn-curturn)*1.0);
				j2.setParamFMax(dInfinity);
				j2.setParamVel2(speed);
				j2.setParamFMax2(FMAX);
				j2.getBody(0).enable();
				j2.getBody(1).enable();
			}		
			if (doFast)
			{
				space.collide (null,nearCallback);
				world.quickStep (0.05);
				contactgroup.empty ();
			}
			else
			{
				space.collide (null,nearCallback);
				world.step (0.05);
				contactgroup.empty ();
			}

			for (i = 0; i < wb; i++)
			{
				b = wall_boxes[i].getBody();
				if (b.isEnabled()) 
				{
					boolean disable = true;
					DVector3C lvel = b.getLinearVel();
					double lspeed = lvel.lengthSquared();
					if (lspeed > DISABLE_THRESHOLD)
						disable = false;
					DVector3C avel = b.getAngularVel();
					double aspeed = avel.lengthSquared();
					if (aspeed > DISABLE_THRESHOLD)
						disable = false;

					if (disable)
						wb_stepsdis[i]++;
					else
						wb_stepsdis[i] = 0;

					if (wb_stepsdis[i] > DISABLE_STEPS)
					{
						b.disable();
						dsSetColor(0.5f,0.5f,1);
					}
					else
						dsSetColor(1,1,1);

				}
				else
					dsSetColor(0.4f,0.4f,0.4f);
				DVector3 ss = new DVector3();
				wall_boxes[i].getLengths (ss);
				dsDrawBox(wall_boxes[i].getPosition(), wall_boxes[i].getRotation(), ss);
			}
		}
		else
		{
			for (i = 0; i < wb; i++)
			{
				b = wall_boxes[i].getBody();
				if (b.isEnabled())
					dsSetColor(1,1,1);
				else
					dsSetColor(0.4f,0.4f,0.4f);
				DVector3 ss = new DVector3();
				wall_boxes[i].getLengths (ss);
				dsDrawBox(wall_boxes[i].getPosition(), wall_boxes[i].getRotation(), ss);
			}
		}

		dsSetColor (0,1,1);
		DVector3 sides = new DVector3(LENGTH,WIDTH,HEIGHT);
		for (i = 0; i < boxes; i++)
			dsDrawBox (box[i].getPosition(),box[i].getRotation(),sides);
		dsSetColor (1,1,1);
		for (i=0; i< spheres; i++) dsDrawSphere (sphere[i].getPosition(),
				sphere[i].getRotation(),RADIUS);

		// draw the cannon
		dsSetColor (1,1,0);
		DMatrix3 R2 = new DMatrix3(), R3 = new DMatrix3(), R4 = new DMatrix3();
		dRFromAxisAndAngle (R2,0,0,1,cannon_angle);
		dRFromAxisAndAngle (R3,0,1,0,cannon_elevation);
		dMultiply0 (R4,R2,R3);
		DVector3 cpos = new DVector3(CANNON_X,CANNON_Y,1);
		DVector3 csides = new DVector3(2,2,2);
		dsDrawBox (cpos,R2,csides);
		for (i=0; i<3; i++) cpos.add(i,  1.5*R4.get(i, 2));//[i*4+2]);
		dsDrawCylinder (cpos,R4,3f,0.5f);

		// draw the cannon ball
		dsDrawSphere (cannon_ball_body.getPosition(),cannon_ball_body.getRotation(),
				CANNON_BALL_RADIUS);
	}

	public static void main(String[] args) {
		new DemoCrash().demo(args);
	}

	private void demo(String[] args) {
		doFast = true;

		OdeHelper.initODE2(0);

		bodies = 0;
		joints = 0;
		boxes = 0;
		spheres = 0;

		setupSimulation();

		// run simulation
		dsSimulationLoop (args,640,480,this);

		shutdownSimulation();
		OdeHelper.closeODE();
	}


	@Override
	public void step(boolean pause) {
		simLoop(pause);
	}


	@Override
	public void stop() {
		// Nothing
	}
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy