PageRenderTime 60ms CodeModel.GetById 15ms app.highlight 37ms RepoModel.GetById 3ms app.codeStats 0ms

/src/org/mt4j/components/bounds/BoundsZPlaneRectangle.java

http://mt4j.googlecode.com/
Java | 474 lines | 229 code | 81 blank | 164 comment | 24 complexity | 2ae4d0a6c6eacad196d135bccbe6b92a MD5 | raw file
  1/***********************************************************************
  2 * mt4j Copyright (c) 2008 - 2009, C.Ruff, Fraunhofer-Gesellschaft All rights reserved.
  3 *  
  4 *   This program is free software: you can redistribute it and/or modify
  5 *   it under the terms of the GNU General Public License as published by
  6 *   the Free Software Foundation, either version 3 of the License, or
  7 *   (at your option) any later version.
  8 *
  9 *   This program is distributed in the hope that it will be useful,
 10 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 11 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 12 *   GNU General Public License for more details.
 13 *
 14 *   You should have received a copy of the GNU General Public License
 15 *   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 16 *
 17 ***********************************************************************/
 18package org.mt4j.components.bounds;
 19
 20import org.mt4j.components.MTComponent;
 21import org.mt4j.components.TransformSpace;
 22import org.mt4j.components.visibleComponents.shapes.AbstractShape;
 23import org.mt4j.util.camera.IFrustum;
 24import org.mt4j.util.math.Matrix;
 25import org.mt4j.util.math.Ray;
 26import org.mt4j.util.math.ToolsGeometry;
 27import org.mt4j.util.math.Vector3D;
 28
 29import processing.core.PGraphics;
 30
 31
 32/**
 33 * Bounding rectangle for 2D shapes that are parallel to the Z=0 plane.
 34 * 
 35 * @author Christopher Ruff
 36 */
 37public class BoundsZPlaneRectangle implements IBoundingShape {
 38	
 39//	/** The peer component. */
 40	private MTComponent peerComponent;
 41	
 42	/** The bounding points local. */
 43	private Vector3D[] boundingPointsLocal;
 44	
 45	/** The I n_ plan e_ tolerance. */
 46	public static float IN_PLANE_TOLERANCE = 0.015f;
 47	
 48	private Vector3D centerPointLocal;
 49	
 50	private Vector3D[] worldVecs;
 51	private boolean worldVecsDirty;
 52	private Vector3D centerPointWorld;
 53	private boolean centerWorldDirty;
 54	
 55	
 56	
 57	//TODO checken ob punkte wirklich in ebene liegen
 58	//-> point in plane test
 59	/**
 60	 * Instantiates a new bounds z plane rectangle.
 61	 * 
 62	 * @param peerComponent the peer component
 63	 */
 64	public BoundsZPlaneRectangle(AbstractShape peerComponent) {
 65		this(peerComponent, peerComponent.getVerticesLocal());
 66	}
 67	
 68	
 69	/**
 70	 * Instantiates a new bounds z plane rectangle.
 71	 *
 72	 * @param peerComponent the peer component
 73	 * @param x the x
 74	 * @param y the y
 75	 * @param width the width
 76	 * @param height the height
 77	 */
 78	public BoundsZPlaneRectangle(MTComponent peerComponent, float x, float y, float width, float height) {
 79		this(peerComponent, new Vector3D[]{new Vector3D(x,y), new Vector3D(x+width,y), new Vector3D(x+width,y+height), new Vector3D(x,y+height)});
 80	}
 81	
 82	
 83	/**
 84	 * Instantiates a new bounds z plane rectangle.
 85	 * 
 86	 * @param peerComponent the peer component
 87	 * @param vertices the vertices
 88	 */
 89	public BoundsZPlaneRectangle(MTComponent peerComponent, Vector3D[] vertices) {
 90		super();
 91		this.peerComponent = peerComponent;
 92		
 93		this.boundingPointsLocal = this.getBoundingRectVertices(vertices);
 94		this.centerPointLocal 	= this.calcCenterPointLocal();
 95		this.worldVecsDirty 	= true;
 96		this.centerWorldDirty 	= true;
 97//		this.worldVecs 			= this.getVectorsGlobal();
 98//		this.centerPointWorld 	= this.getCenterPointGlobal();
 99	}
100
101
102	
103	public void setGlobalBoundsChanged(){
104			this.worldVecsDirty = true;
105			this.centerWorldDirty = true;
106	}
107	
108	
109	/**
110	 * Calculates the bounding rectangles vertices and returns them.
111	 * 
112	 * @param vertices the vertices
113	 * 
114	 * @return a Vector3D array containing the vertices of the bounding rectangle
115	 */
116	private Vector3D[] getBoundingRectVertices(Vector3D[] vertices){
117		float[] minMax = ToolsGeometry.getMinXYMaxXY(vertices);
118		float minX = minMax[0];
119		float minY = minMax[1];
120		float maxX = minMax[2];
121		float maxY = minMax[3];
122		float z = vertices[0].z;
123		if (peerComponent != null && peerComponent instanceof AbstractShape){
124			z = ((AbstractShape)peerComponent).getCenterPointLocal().z;
125		}
126		return (new Vector3D[]{
127				new Vector3D(minX, minY,z),
128				new Vector3D(maxX, minY,z),
129				new Vector3D(maxX, maxY,z),
130				new Vector3D(minX, maxY,z),
131//				new Vector3D(minX, minY,z)
132				}); 
133	}
134	
135	
136	public void drawBounds(final PGraphics g){
137		g.pushMatrix();
138		g.pushStyle();
139		g.fill(150,180);
140		
141		g.beginShape();
142		g.vertex(this.boundingPointsLocal[0].x, this.boundingPointsLocal[0].y, this.boundingPointsLocal[0].z);
143		g.vertex(this.boundingPointsLocal[1].x, this.boundingPointsLocal[1].y, this.boundingPointsLocal[1].z);
144		g.vertex(this.boundingPointsLocal[2].x, this.boundingPointsLocal[2].y, this.boundingPointsLocal[2].z);
145		g.vertex(this.boundingPointsLocal[3].x, this.boundingPointsLocal[3].y, this.boundingPointsLocal[3].z);
146		g.endShape();
147		
148		g.popStyle();
149		g.popMatrix();
150		
151		
152//		g.pushMatrix();
153//		g.pushStyle();
154//		g.fill(150,180);
155//		
156//		Vector3D[] v = this.getVectorsGlobal();
157//		float[] minMax = Tools3D.getMinXYMaxXY(v);
158//		
159//		g.beginShape();
160//		g.vertex(minMax[0], minMax[1], 0);
161//		g.vertex(minMax[2], minMax[1], 0);
162//		g.vertex(minMax[2], minMax[3], 0);
163//		g.vertex(minMax[0], minMax[3], 0);
164//		g.endShape();
165////		
166//		g.popStyle();
167//		g.popMatrix();
168	}
169
170
171	
172	public boolean containsPointLocal(Vector3D testPoint) {
173        return testPoint.x >= this.boundingPointsLocal[0].x
174                && testPoint.x <= this.boundingPointsLocal[1].x
175
176                && testPoint.y >= this.boundingPointsLocal[0].y
177                && testPoint.y <= this.boundingPointsLocal[2].y
178
179                && Math.abs(testPoint.z - this.boundingPointsLocal[0].z) < IN_PLANE_TOLERANCE;
180	}
181	
182	
183	public boolean intersects(BoundsZPlaneRectangle boundingRect){
184		//TODO actually we would have to check all rectangle 
185		//line segments against each other instead of the points
186		Vector3D[] globalBoundingVectorsR2 = boundingRect.getVectorsGlobal();
187		Vector3D globalCenterR2 = boundingRect.getCenterPointGlobal();
188		boolean colliding = false;
189		//Check if rectangle points lie inside of this rectangle
190        for (Vector3D aGlobalBoundingVectorsR2 : globalBoundingVectorsR2) {
191            Vector3D localVectorR2 = peerComponent.globalToLocal(aGlobalBoundingVectorsR2);
192            if (this.containsPointLocal(localVectorR2)) {
193                colliding = true;
194            }
195        }
196		//Check rectangle center
197		if (this.containsPointLocal(peerComponent.globalToLocal(globalCenterR2))){
198			colliding = true;
199		}
200		
201		//System.out.println("Colliding: " + colliding);
202		return colliding;
203	}
204	
205	
206	/** The rect normal. */
207	private Vector3D rectNormal = new Vector3D(0,0,1);
208	
209	public Vector3D getIntersectionLocal(Ray ray) {
210		Vector3D[] verts = this.boundingPointsLocal;
211//		rectNormal= this.getNormalObjSpace();
212		//Normal should actually always be (0,0,1)!
213		Vector3D testPoint = ToolsGeometry.getRayPlaneIntersection(ray, rectNormal, verts[0]);
214		
215		if (testPoint == null){
216			return null;
217		}
218		return (this.containsPointLocal(testPoint) ? testPoint : null);
219	}
220	
221	
222	/**
223	 * Gets the normal obj space.
224	 * 
225	 * @return the normal obj space
226	 */
227	private Vector3D getNormalLocal() {
228		return ToolsGeometry.getNormal(this.boundingPointsLocal[0], this.boundingPointsLocal[1], this.boundingPointsLocal[2], true);
229	}
230	
231	private Vector3D calcCenterPointLocal(){
232		Vector3D tmp0 = this.boundingPointsLocal[0].getCopy();
233		Vector3D tmp1 = this.boundingPointsLocal[1].getSubtracted(this.boundingPointsLocal[0]);
234		tmp1.scaleLocal(0.5f);
235		
236		Vector3D tmp2 = this.boundingPointsLocal[3].getSubtracted(this.boundingPointsLocal[0]);
237		tmp2.scaleLocal(0.5f);
238		
239		tmp0.addLocal(tmp1);
240		tmp0.addLocal(tmp2);
241		return tmp0;
242	}
243
244	public Vector3D getCenterPointLocal() {
245//		Vector3D tmp0 = this.boundingPointsLocal[0].getCopy();
246//		Vector3D tmp1 = this.boundingPointsLocal[1].getSubtracted(this.boundingPointsLocal[0]);
247//		tmp1.scaleLocal(0.5f);
248//		
249//		Vector3D tmp2 = this.boundingPointsLocal[3].getSubtracted(this.boundingPointsLocal[0]);
250//		tmp2.scaleLocal(0.5f);
251//		
252//		tmp0.addLocal(tmp1);
253//		tmp0.addLocal(tmp2);
254//		return tmp0;
255		return this.centerPointLocal.getCopy();
256	}
257	
258	
259	public Vector3D getCenterPointGlobal() {
260		if (centerWorldDirty){
261			Vector3D tmp = this.getCenterPointLocal();
262			tmp.transform(this.peerComponent.getGlobalMatrix());
263//			tmp = peerComponent.localToGlobal(tmp);
264			this.centerPointWorld = tmp;
265			this.centerWorldDirty = false;
266			return this.centerPointWorld;
267		}
268		else{
269			return this.centerPointWorld;
270		}
271	}
272	
273	
274	public Vector3D[] getVectorsLocal() {
275		return this.boundingPointsLocal;
276	}
277
278	
279	//FIXME also cache?
280	public Vector3D[] getVectorsRelativeToParent(){
281		Vector3D[] vecs = Vector3D.getDeepVertexArrayCopy(this.boundingPointsLocal);
282		Vector3D.transFormArrayLocal(this.peerComponent.getLocalMatrix(), vecs);
283		return vecs;
284	}
285	
286	public Vector3D[] getVectorsGlobal() {
287		if (this.worldVecsDirty){
288			Vector3D[] vecs = Vector3D.getDeepVertexArrayCopy(this.boundingPointsLocal);
289			Vector3D.transFormArrayLocal(this.peerComponent.getGlobalMatrix(), vecs);
290			this.worldVecs = vecs;
291			this.worldVecsDirty = false;
292			return this.worldVecs;
293		}else{
294			return this.worldVecs;
295		}
296//		Vector3D[] vecs = Vector3D.getDeepVertexArrayCopy(this.boundingPointsLocal);
297//		Vector3D.transFormArrayLocal(this.peerComponent.getAbsoluteLocalToWorldMatrix(), vecs);
298//		return vecs;
299	}
300	
301	
302	
303	public float getHeightXY(TransformSpace transformSpace) {
304		switch (transformSpace) {
305		case LOCAL:
306			return this.getHeightXYLocal();
307		case RELATIVE_TO_PARENT:
308			return this.getHeightXYRelativeToParent();
309		case GLOBAL:
310			return this.getHeightXYGlobal();
311		default:
312			return -1;
313		}
314	}
315	
316	
317	/**
318	 * Gets the height xy obj space.
319	 * 
320	 * @return the height xy obj space
321	 */
322	private float getHeightXYLocal() {
323		return this.getHeightXYVectLocal().length();
324	}
325	
326	/**
327	 * Gets the height xy relative to parent.
328	 * 
329	 * @return the height xy relative to parent
330	 */
331	private float getHeightXYRelativeToParent() {
332		Vector3D p = this.getHeightXYVectLocal();
333		Matrix m = new Matrix(this.peerComponent.getLocalMatrix());
334		m.removeTranslationFromMatrix();
335		p.transform(m);
336		return p.length();
337		
338//		Vector3D[] v = this.getVectorsRelativeToParent();
339//		float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
340//		return minMax[3] - minMax[1];
341	}
342	
343	
344	/**
345	 * Gets the height xy global.
346	 * 
347	 * @return the height xy global
348	 */
349	private float getHeightXYGlobal() {
350		Vector3D p = this.getHeightXYVectLocal();
351		Matrix m = new Matrix(this.peerComponent.getGlobalMatrix());
352		m.removeTranslationFromMatrix();
353		p.transform(m);
354		return p.length();
355		
356//		Vector3D[] v = this.getVectorsGlobal();
357//		float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
358//		return minMax[3] - minMax[1];
359	}
360	
361	
362	/**
363	 * Gets the "height vector". The vector is calculated from the bounds vectors,
364	 * representing a vector with the height as its length in object space.
365	 * 
366	 * @return the height xy vect obj space
367	 * 
368	 * vector representing the height of the boundingshape of the shape
369	 */
370	public Vector3D getHeightXYVectLocal() {
371		Vector3D[] boundRectVertsLocal = this.getVectorsLocal();
372		Vector3D height = boundRectVertsLocal[2].getSubtracted(boundRectVertsLocal[1]);
373		return height;
374	}
375
376	
377	public float getWidthXY(TransformSpace transformSpace) {
378		switch (transformSpace) {
379		case LOCAL:
380			return this.getWidthXYLocal();
381		case RELATIVE_TO_PARENT:
382			return this.getWidthXYRealtiveToParent();
383		case GLOBAL:
384			return this.getWidthXYGlobal();
385		default:
386			return -1;
387		}
388	}
389	
390	
391	/**
392	 * Gets the width xy obj space.
393	 * 
394	 * @return the width xy obj space
395	 */
396	private float getWidthXYLocal() {
397		return this.getWidthXYVectLocal().length();
398	}
399	
400	
401	/**
402	 * Gets the width xy realtive to parent.
403	 * 
404	 * @return the width xy realtive to parent
405	 */
406	private float getWidthXYRealtiveToParent() {
407		//This calculates the width aligned/relative to the object 
408		Vector3D p = this.getWidthXYVectLocal();
409		Matrix m = new Matrix(this.peerComponent.getLocalMatrix());
410		m.removeTranslationFromMatrix();
411		p.transform(m);
412		return p.length();
413		
414		//This calculates the dimension relative to the screen axis (here X-axis)
415//		Vector3D[] v = this.getVectorsRelativeToParent();
416//		float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
417//		return minMax[2] - minMax[0];
418	}
419	
420	/**
421	 * Gets the width xy global.
422	 * 
423	 * @return the width xy global
424	 */
425	private float getWidthXYGlobal() {
426		Vector3D p = this.getWidthXYVectLocal();
427		Matrix m = new Matrix(this.peerComponent.getGlobalMatrix());
428		m.removeTranslationFromMatrix();
429		p.transform(m);
430		return p.length();
431		
432//		Vector3D[] v = this.getVectorsGlobal();
433//		float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
434//		return minMax[2] - minMax[0];
435	}
436	
437	/**
438	 * Gets the "Width vector". The vector is calculated from the bounds vectors,
439	 * representing a vector with the Width as its length in object space.
440	 * 
441	 * @return the width xy vect obj space
442	 * 
443	 * vector representing the Width of the boundingshape of the shape
444	 */
445	//@Override
446	public Vector3D getWidthXYVectLocal() {
447		Vector3D[] boundRectVertsLocal = this.getVectorsLocal();
448		Vector3D width = boundRectVertsLocal[1].getSubtracted(boundRectVertsLocal[0]);
449//		System.out.println("Width of " + this.getName()+ " :" + width);
450		return width;
451	}
452
453
454	public boolean isContainedInFrustum(IFrustum frustum) {
455		Vector3D[] points = this.getVectorsGlobal();
456        for (Vector3D vector3D : points) {
457            int test = frustum.isPointInFrustum(vector3D);
458            if (test == IFrustum.INSIDE
459                    || test == IFrustum.INTERSECT
460                    ) {
461                return true;
462            }
463        }
464		//Also check if center point is in frustum
465		Vector3D center = this.getCenterPointGlobal();
466		int test = frustum.isPointInFrustum(center);
467        return test == IFrustum.INSIDE
468                || test == IFrustum.INTERSECT;
469    }
470
471
472
473	
474}