PageRenderTime 48ms CodeModel.GetById 15ms app.highlight 27ms RepoModel.GetById 1ms app.codeStats 1ms

/examples/advanced/physics/physicsShapes/PhysicsRectangle.java

http://mt4j.googlecode.com/
Java | 490 lines | 300 code | 100 blank | 90 comment | 33 complexity | 4a0b35eaeab64c2630914ee9827be662 MD5 | raw file
  1package advanced.physics.physicsShapes;
  2
  3import java.util.List;
  4
  5import javax.media.opengl.glu.GLU;
  6
  7import org.jbox2d.collision.shapes.PolygonDef;
  8import org.jbox2d.common.Vec2;
  9import org.jbox2d.dynamics.Body;
 10import org.jbox2d.dynamics.BodyDef;
 11import org.jbox2d.dynamics.World;
 12import org.mt4j.MTApplication;
 13import org.mt4j.components.MTComponent;
 14import org.mt4j.components.bounds.BoundsArbitraryPlanarPolygon;
 15import org.mt4j.components.bounds.IBoundingShape;
 16import org.mt4j.components.visibleComponents.shapes.GeometryInfo;
 17import org.mt4j.components.visibleComponents.shapes.MTRectangle;
 18import org.mt4j.input.inputProcessors.componentProcessors.rotateProcessor.RotateProcessor;
 19import org.mt4j.input.inputProcessors.componentProcessors.scaleProcessor.ScaleProcessor;
 20import org.mt4j.util.math.Vector3D;
 21import org.mt4j.util.math.Vertex;
 22import org.mt4j.util.opengl.GluTrianglulator;
 23
 24import processing.core.PApplet;
 25import processing.core.PGraphics;
 26import processing.core.PImage;
 27import advanced.physics.util.PhysicsHelper;
 28
 29public class PhysicsRectangle extends MTRectangle implements IPhysicsComponent{
 30	private float angle;
 31	private boolean drawBounds;
 32	
 33	private World world;
 34	private Body body;
 35	private float density;
 36	private float friction;
 37	private float restituion;
 38	
 39	/*
 40	PhysicsRectangle rect = new PhysicsRectangle(new Vector3D(400,200), 100,150, app, world, 0.6f, 0.4f, 0.2f, scale);
 41	rect.setNoStroke(true);
 42	PhysicsHelper.addDragJoint(world, rect, rect.getBody().isDynamic(), scale);
 43	physObjGroup.addChild(rect);
 44	*/
 45	
 46	public PhysicsRectangle(
 47			Vector3D centerPosition, 
 48			float width, float height, PApplet applet,
 49			World world, float density, float friction, float restitution, float scale
 50	) {
 51		super(applet, 0, 0, PhysicsHelper.scaleDown(width, scale), PhysicsHelper.scaleDown(height, scale));
 52		this.angle = 0;
 53		this.drawBounds = false;
 54		this.world = world;
 55		this.density = density;
 56		this.friction = friction;
 57		this.restituion = restitution;
 58		
 59		Vector3D scaledPos = PhysicsHelper.scaleDown(centerPosition.getCopy(), scale);
 60//		PhysicsHelper.scaleDown(centerPosition, scale);
 61//		centerPosition.scaleLocal(1f/scale);
 62		
 63		BodyDef dymBodyDef = new BodyDef();
 64//		dymBodyDef.position = new Vec2(pos.x, pos.y);
 65		dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);//FIXME WORKS?
 66		this.bodyDefB4CreationCallback(dymBodyDef);
 67		this.body = world.createBody(dymBodyDef);
 68		
 69		PolygonDef dymShapeDef = new PolygonDef();
 70		dymShapeDef.setAsBox( (width/2f)/scale, (height/2f)/scale);
 71//		dymShapeDef.setAsBox( (width/2f), (height/2f));
 72		if (density != 0.0f){
 73			dymShapeDef.density 		= density;
 74			dymShapeDef.friction 		= friction;
 75			dymShapeDef.restitution 	= restitution;
 76		}
 77		
 78		this.polyDefB4CreationCallback(dymShapeDef); //FIXME TEST
 79		
 80		body.createShape(dymShapeDef);
 81		body.setMassFromShapes();
 82		
 83		//TEST
 84//		theBody.setBullet(true);
 85		
 86		this.setPositionGlobal(scaledPos); 
 87		body.setUserData(this);
 88		this.setUserData("box2d", body); 
 89		this.setGestureAllowance(ScaleProcessor.class, false);
 90		this.setGestureAllowance(RotateProcessor.class, false);
 91	}
 92	
 93	
 94	
 95	
 96	public PhysicsRectangle(PImage texture, 
 97			Vector3D pos, 
 98			PApplet applet,
 99			Vertex[] physicsVertices,
100			World world, float density, float friction, float restitution, float scale
101	) {
102		super(applet, texture);
103		this.angle = 0;
104		this.drawBounds = false;
105		this.world = world;
106		this.density = density;
107		this.friction = friction;
108		this.restituion = restitution;
109		
110		this.setGestureAllowance(ScaleProcessor.class, false);
111		this.setGestureAllowance(RotateProcessor.class, false);
112		
113		//Scale shape vertices
114//		this.setGeometryInfo(new GeometryInfo(applet, Vertex.scaleVectorArray(this.getGeometryInfo().getVertices(), Vector3D.ZERO_VECTOR, 1f/scale, 1f/scale, 1)));
115//		this.setGeometryInfo(new GeometryInfo(applet, PhysicsHelper.scaleDown(this.getGeometryInfo().getVertices(), scale)));
116		this.setGeometryInfo(new GeometryInfo(applet, PhysicsHelper.scaleDown(Vertex.getDeepVertexArrayCopy(this.getGeometryInfo().getVertices()), scale)));
117		
118		//Scale physics vertics
119//		Vertex.scaleVectorArray(bodyVerts, Vector3D.ZERO_VECTOR, 1f/scale, 1f/scale, 1);
120		PhysicsHelper.scaleDown(physicsVertices, scale);
121		
122		Vector3D scaledPos = PhysicsHelper.scaleDown(pos.getCopy(), scale);
123		//Scale position
124//		pos.scaleLocal(1f/scale); //FIXME REALLY?
125//		PhysicsHelper.scaleDown(pos, scale);
126		
127		this.setGestureAllowance(ScaleProcessor.class, false);
128		this.setGestureAllowance(RotateProcessor.class, false);
129		
130		//Temporarily move the mesh so that we know where the calculated center of the body
131		//would be (the body takes the body.position as the center reference instead of a calculated center) 
132//		//FIXME welchen centerpoint nehmen? -> kommt auch drauf an ob shape schon auf canvas war!?
133		//We have to do this because the anchor point ("position") of the pyhsics shape is the body.position
134		//but the anchor point of our shapes is the point returned from getCenterpoint..()
135		this.translate(scaledPos);
136		Vector3D realBodyCenter = this.getCenterPointGlobal(); //FIXME geht nur if detached from world //rename futurebodycenter?
137		//Reset position
138		this.translate(scaledPos.getScaled(-1));
139		
140		//Now get the position where the global center will be after setting the shape at the desired position
141		this.setPositionGlobal(scaledPos);
142		Vector3D meshCenterAtPosition = this.getCenterPointGlobal();
143
144		//Compute the distance we would have to move the vertices for the body creation
145		//so that the body.position(center) is at the same position as our mesh center
146		Vector3D realBodyCenterToMeshCenter = meshCenterAtPosition.getSubtracted(realBodyCenter);
147		//System.out.println("Diff:" +  realBodyCenterToMeshCenter);
148		
149		//FIXME TEST Needed for level saving the local vertices at the right position 
150		this.setUserData("realBodyCenterToMeshCenter", realBodyCenterToMeshCenter);
151
152		//Move the vertices so the body position is at the center of the shape 
153		Vertex.translateVectorArray(physicsVertices, realBodyCenterToMeshCenter);
154
155		//Create vertex structure for creation of decomposition polygon (use the translated vertices)
156		float xArr[] = new float[physicsVertices.length];
157		float yArr[] = new float[physicsVertices.length];
158		for (int i = 0; i < physicsVertices.length; i++) {
159			Vertex v = physicsVertices[i];
160			xArr[i] = v.x;
161			yArr[i] = v.y;
162		}
163
164		//Create a polygon too see if its simple and eventually decompose it
165		org.jbox2d.util.nonconvex.Polygon myPoly = new org.jbox2d.util.nonconvex.Polygon(xArr, yArr);
166
167		//System.out.println("Polygon is simple! -> Using convex decomposition for physics shape and glu triangulated mesh for display!");
168		PolygonDef pd = new PolygonDef();
169		if (density != 0.0f){
170			pd.density 		= density;
171			pd.friction 	= friction;
172			pd.restitution 	= restituion;
173		}
174
175		//Create polygon body
176		BodyDef dymBodyDef = new BodyDef();
177		dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);
178		this.bodyDefB4CreationCallback(dymBodyDef);
179		this.body = world.createBody(dymBodyDef);
180
181		this.polyDefB4CreationCallback(pd); //FIXME TEST
182		
183		int success = org.jbox2d.util.nonconvex.Polygon.decomposeConvexAndAddTo(myPoly, body, pd); 
184		if (success != -1){
185			System.out.println("-> Ear clipping SUCCESSFUL -> Using triangulated and polygonized shape for b2d.");
186			body.setMassFromShapes();
187			body.setUserData(this);
188			this.setUserData("box2d", body); 
189			//Performance hit! but prevents object from sticking to another sometimes
190//			theBody.setBullet(true);
191		}else{
192			System.out.println("-> Ear clipping had an ERROR - trying again by triangulating shape for b2d with GLU-Triangulator");
193			GluTrianglulator triangulator = new GluTrianglulator(applet);
194			List<Vertex> physicsTris = triangulator.tesselate(physicsVertices, GLU.GLU_TESS_WINDING_NONZERO);
195			Vertex[] triangulatedBodyVerts = physicsTris.toArray(new Vertex[physicsTris.size()]);
196			//System.out.println("GLU tris created: " + triangulatedBodyVerts.length);
197
198			//Cap the max triangles - dont use anymore triangles for the physics body..
199			int cap = 400;
200			if (triangulatedBodyVerts.length > cap){
201				//System.err.println("OVER cap! -> capping!");
202				Vertex[] tmp = new Vertex[cap];
203				System.arraycopy(triangulatedBodyVerts, 0, tmp, 0, cap);
204				triangulatedBodyVerts = tmp;
205			}
206
207			//Create polygon body
208			world.destroyBody(body);
209			dymBodyDef = new BodyDef();
210			dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);
211			this.bodyDefB4CreationCallback(dymBodyDef);
212			body = world.createBody(dymBodyDef);
213			for (int i = 0; i < triangulatedBodyVerts.length/3; i++) {
214				//Create polygon definition
215				PolygonDef polyDef = new PolygonDef();
216				if (density != 0.0f){
217					polyDef.density 		= density;
218					polyDef.friction 		= friction;
219					polyDef.restitution 	= restituion;
220				}
221				//Add triangle vertices
222				Vertex vertex1 = triangulatedBodyVerts[i*3];
223				Vertex vertex2 = triangulatedBodyVerts[i*3+1];
224				Vertex vertex3 = triangulatedBodyVerts[i*3+2];
225				polyDef.addVertex(new Vec2(vertex1.x, vertex1.y));
226				polyDef.addVertex(new Vec2(vertex2.x, vertex2.y));
227				polyDef.addVertex(new Vec2(vertex3.x, vertex3.y));
228				
229				this.polyDefB4CreationCallback(pd); //FIXME TEST
230				
231				//Add poly to body
232				body.createShape(polyDef);
233			}
234			body.setMassFromShapes();
235			//performance hit!?
236			//theBody.setBullet(true);
237			body.setUserData(this);
238			this.setUserData("box2d", body); 
239			triangulator.deleteTess();
240		}
241		
242
243	}
244
245	
246	
247	public void setPhysicsVertices(Vertex[] bodyVerts, 
248			Vector3D pos, 
249			float scale
250		){
251		if (this.body != null && this.world != null){
252			world.destroyBody(this.body);
253		}
254		
255		//Scale physics vertics
256//		Vertex.scaleVectorArray(bodyVerts, Vector3D.ZERO_VECTOR, 1f/scale, 1f/scale, 1);
257		PhysicsHelper.scaleDown(bodyVerts, scale);
258		
259		//Scale position
260//		pos.scaleLocal(1f/scale); //FIXME REALLY?
261//		PhysicsHelper.scaleDown(pos, scale);
262		Vector3D scaledPos = PhysicsHelper.scaleDown(pos.getCopy(), scale);
263		
264		MTComponent parent = this.getParent();
265		this.removeFromParent();
266		
267		//Temporarily move the mesh so that we know where the calculated center of the body
268		//would be (the body takes the body.position as the center reference instead of a calculated center) 
269//		//FIXME welchen centerpoint nehmen? -> kommt auch drauf an ob shape schon auf canvas war!?
270		//We have to do this because the anchor point ("position") of the pyhsics shape is the body.position
271		//but the anchor point of our shapes is the point returned from getCenterpoint..()
272		this.translate(scaledPos);
273		Vector3D realBodyCenter = this.getCenterPointGlobal(); //FIXME geht nur if detached from world //rename futurebodycenter?
274		//Reset position
275		this.translate(scaledPos.getScaled(-1));
276		
277		//Now get the position where the global center will be after setting the shape at the desired position
278		this.setPositionGlobal(scaledPos);
279		Vector3D meshCenterAtPosition = this.getCenterPointGlobal();
280		
281		if (parent != null){
282			parent.addChild(this);//TODO add at same index
283		}
284
285		//Compute the distance we would have to move the vertices for the body creation
286		//so that the body.position(center) is at the same position as our mesh center
287		Vector3D realBodyCenterToMeshCenter = meshCenterAtPosition.getSubtracted(realBodyCenter);
288		//System.out.println("Diff:" +  realBodyCenterToMeshCenter);
289
290		//Move the vertices so the body position is at the center of the shape 
291		Vertex.translateVectorArray(bodyVerts, realBodyCenterToMeshCenter);
292		
293		//FIXME TEST
294		this.setUserData("realBodyCenterToMeshCenter", realBodyCenterToMeshCenter);
295
296		//Create vertex structure for creation of decomposition polygon (use the translated vertices)
297		float xArr[] = new float[bodyVerts.length];
298		float yArr[] = new float[bodyVerts.length];
299		for (int i = 0; i < bodyVerts.length; i++) {
300			Vertex v = bodyVerts[i];
301			xArr[i] = v.x;
302			yArr[i] = v.y;
303		}
304
305		//Create a polygon too see if its simple and eventually decompose it
306		org.jbox2d.util.nonconvex.Polygon myPoly = new org.jbox2d.util.nonconvex.Polygon(xArr, yArr);
307
308		//System.out.println("Polygon is simple! -> Using convex decomposition for physics shape and glu triangulated mesh for display!");
309		PolygonDef pd = new PolygonDef();
310		if (density != 0.0f){
311			pd.density 		= density;
312			pd.friction 	= friction;
313			pd.restitution 	= restituion;
314		}
315
316		//Create polygon body
317		BodyDef dymBodyDef = new BodyDef();
318		dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);
319		this.bodyDefB4CreationCallback(dymBodyDef);
320		this.body = world.createBody(dymBodyDef);
321		
322		this.polyDefB4CreationCallback(pd); //FIXME TEST
323		
324		int success = org.jbox2d.util.nonconvex.Polygon.decomposeConvexAndAddTo(myPoly, body, pd); 
325		if (success != -1){
326			System.out.println("-> Ear clipping SUCCESSFUL -> Using triangulated and polygonized shape for b2d.");
327			body.setMassFromShapes();
328			body.setUserData(this);
329			this.setUserData("box2d", body); 
330			//Performance hit! but prevents object from sticking to another sometimes
331//			theBody.setBullet(true);
332		}else{
333			System.out.println("-> Ear clipping had an ERROR - trying again by triangulating shape for b2d with GLU-Triangulator");
334			GluTrianglulator triangulator = new GluTrianglulator(this.getRenderer());
335			List<Vertex> physicsTris = triangulator.tesselate(bodyVerts, GLU.GLU_TESS_WINDING_NONZERO);
336			Vertex[] triangulatedBodyVerts = physicsTris.toArray(new Vertex[physicsTris.size()]);
337			//System.out.println("GLU tris created: " + triangulatedBodyVerts.length);
338
339			//Cap the max triangles - dont use anymore triangles for the physics body..
340			int cap = 400;
341			if (triangulatedBodyVerts.length > cap){
342				//System.err.println("OVER cap! -> capping!");
343				Vertex[] tmp = new Vertex[cap];
344				System.arraycopy(triangulatedBodyVerts, 0, tmp, 0, cap);
345				triangulatedBodyVerts = tmp;
346			}
347
348			//Create polygon body
349			world.destroyBody(body);
350			dymBodyDef = new BodyDef();
351			dymBodyDef.position = new Vec2(scaledPos.x, scaledPos.y);
352			this.bodyDefB4CreationCallback(dymBodyDef);
353			body = world.createBody(dymBodyDef);
354			for (int i = 0; i < triangulatedBodyVerts.length/3; i++) {
355				//Create polygon definition
356				PolygonDef polyDef = new PolygonDef();
357				if (density != 0.0f){
358					polyDef.density 		= density;
359					polyDef.friction 		= friction;
360					polyDef.restitution 	= restituion;
361				}
362				//Add triangle vertices
363				Vertex vertex1 = triangulatedBodyVerts[i*3];
364				Vertex vertex2 = triangulatedBodyVerts[i*3+1];
365				Vertex vertex3 = triangulatedBodyVerts[i*3+2];
366				polyDef.addVertex(new Vec2(vertex1.x, vertex1.y));
367				polyDef.addVertex(new Vec2(vertex2.x, vertex2.y));
368				polyDef.addVertex(new Vec2(vertex3.x, vertex3.y));
369				
370				this.polyDefB4CreationCallback(polyDef); //FIXME TEST
371				//Add poly to body
372				body.createShape(polyDef);
373			}
374			body.setMassFromShapes();
375			//FIXME TEST - performance hit!?
376			//theBody.setBullet(true);
377			body.setUserData(this);
378			this.setUserData("box2d", body); 
379			triangulator.deleteTess();
380		}
381	}
382	
383	protected void polyDefB4CreationCallback(PolygonDef def){
384		
385	}
386	
387	protected void bodyDefB4CreationCallback(BodyDef def){
388		
389	}
390	
391//	private Vertex[] physicsVertices;
392//	
393//	private Vertex[] getPhysicsVertices(){
394//		return this.physicsVertices;
395//	}
396	
397	
398	
399	
400	//@Override
401	public void drawComponent(PGraphics g) {
402		super.drawComponent(g);
403
404		if (drawBounds){
405			IBoundingShape bounds = this.getBounds();
406			if (bounds instanceof BoundsArbitraryPlanarPolygon){
407				BoundsArbitraryPlanarPolygon bound = (BoundsArbitraryPlanarPolygon)bounds;
408
409				Vector3D[] boundVecs = bound.getVectorsLocal();
410//				app.noFill();
411				g.fill(100);
412				g.stroke(50);
413				g.beginShape();
414                for (Vector3D v : boundVecs) {
415                    //					app.vertex(v.x*scale, v.y*scale, v.z);
416                    g.vertex(v.x, v.y, v.z);
417                }
418				g.endShape();
419			}
420		}
421	}
422	
423	//@Override
424	public void rotateZGlobal(Vector3D rotationPoint, float degree) {
425		angle += degree;
426		super.rotateZGlobal(rotationPoint, degree);
427	} 	
428
429	public float getAngle() {
430		return angle;
431	}
432	
433	public void setCenterRotation(float angle){
434		float degreeAngle = MTApplication.degrees(angle);
435		float oldAngle = this.getAngle();
436		float diff = degreeAngle-oldAngle;
437		//System.out.println("Old angle: " + oldAngle + " new angle:" + degreeAngle + " diff->" +  diff);
438		this.rotateZGlobal(this.getCenterPointGlobal(), diff);
439	}
440	
441	//@Override
442	protected void destroyComponent() {
443		super.destroyComponent();
444		boolean exists = false;
445		for (Body body = world.getBodyList(); body != null; body = body.getNext()) {
446			if (body.equals(this.body))
447				exists = true;//Delete later to avoid concurrent modification
448		}
449		if (exists)
450			world.destroyBody(body);
451	}
452
453
454
455
456	public World getWorld() {
457		return world;
458	}
459
460
461
462
463	public Body getBody() {
464		return body;
465	}
466
467
468
469
470	public float getDensity() {
471		return density;
472	}
473
474
475
476
477	public float getFriction() {
478		return friction;
479	}
480
481
482
483
484	public float getRestituion() {
485		return restituion;
486	}
487	
488	
489
490}