PageRenderTime 77ms CodeModel.GetById 31ms app.highlight 39ms RepoModel.GetById 2ms app.codeStats 0ms

/extensions/org/mt4jx/util/extension3D/ComponentHelper.java

http://mt4j.googlecode.com/
Java | 318 lines | 149 code | 37 blank | 132 comment | 50 complexity | dbbb04054f8d179f2356134e7f48df7c MD5 | raw file
  1package org.mt4jx.util.extension3D;
  2
  3import org.mt4j.components.MTComponent;
  4import org.mt4j.components.PickInfo;
  5import org.mt4j.components.PickResult;
  6import org.mt4j.components.PickResult.PickEntry;
  7import org.mt4j.components.clipping.Clip;
  8import org.mt4j.components.interfaces.IMTComponent3D;
  9import org.mt4j.util.math.Ray;
 10import org.mt4j.util.math.Tools3D;
 11import org.mt4j.util.math.Vector3D;
 12
 13import processing.core.PApplet;
 14
 15public class ComponentHelper {
 16	
 17	/**
 18	 * this is a different version of pickRecursive of MTComponent used to get the correct object when dealing with the Cluster 3D techniques
 19	 * Checks which object lies under the specified screen coordinates.
 20	 * The the results are stored in the returned PickResult object. This component and
 21	 * its children will be checked. 
 22	 * 
 23	 * @param x the x
 24	 * @param y the y
 25	 * @param onlyPickables check the only pickable components
 26	 * 
 27	 * @return the pick result
 28	 */
 29	public static PickResult pick(MTComponent comp,float x, float y, boolean onlyPickables){ //ADDTOMT4J change name
 30		PickResult pickResult = new PickResult();
 31		PickInfo pickInfo = new PickInfo(x,y, Tools3D.getCameraPickRay(comp.getRenderer(), comp, x, y));
 32		pickRecursive(comp,pickInfo, pickResult, Float.MAX_VALUE, pickInfo.getPickRay(), onlyPickables);
 33//		pickResult.printList();
 34		return pickResult;
 35	}
 36	
 37	/**
 38	 * this is a different version of pickRecursive of MTComponent used to get the correct object when dealing with the Cluster 3D techniques
 39	 * @param comp
 40	 * @param pickInfo
 41	 * @param pickResult
 42	 * @param currObjDist
 43	 * @param currentRay
 44	 * @param onlyPickables
 45	 * @return
 46	 */
 47	private static float pickRecursive(MTComponent comp,PickInfo pickInfo, PickResult pickResult, float currObjDist, Ray currentRay, boolean onlyPickables){//ADDTOMT4J change name
 48		Vector3D interSP	= null;
 49		float objDistance 	= 0;
 50		//TEST, Wenns probleme gibt das wieder aktivieren
 51//		currObjDist = pickResult.getDistanceNearestPickObj();
 52		
 53//		System.out.println("At: " + comp.getName() + " Current Distance: " + currObjDist);
 54		if (comp.isVisible() && 
 55			((onlyPickables && comp.isPickable()) || !onlyPickables) 
 56		){
 57			//Get the real ray for comp obj, takes the viewing camera and viewport of comp obj into account
 58			//-> changes rayStartPoint and point in ray direction
 59			if (comp.getAttachedCamera() != null){
 60				currentRay	= getChangedCameraPickRay(comp.getRenderer(), comp, pickInfo);
 61			}
 62			
 63			Ray invertedRay;
 64			if (comp.getGlobalInverseMatrix().isIdentity()){
 65				invertedRay = currentRay;
 66			}else{
 67				invertedRay = comp.globalToLocal(currentRay);
 68			}
 69			
 70			/*
 71			//FIXME REMOVE!!!!! 
 72			//comp adds lines indicating the world ray and the local object ray used for ray-test
 73			MTLine l1 = new MTLine(comp.getRenderer(), new Vertex(currentRay.getRayStartPoint()), new Vertex(currentRay.getPointInRayDirection()));
 74			comp.getAncestor().addChild(l1);
 75			MTLine l2 = new MTLine(comp.getRenderer(), new Vertex(invertedRay.getRayStartPoint()), new Vertex(invertedRay.getPointInRayDirection()));
 76			l2.setStrokeColor(255, 10, 10, 255);
 77			comp.getAncestor().addChild(l2);
 78			*/
 79			
 80			//Check if component is clipped and only proceed if the ray intersects the clip shape
 81			Clip clip = comp.getClip();
 82			if (clip == null || (clip != null && clip.getClipShapeIntersectionLocal(invertedRay) != null)){
 83				interSP = comp.getIntersectionLocal(invertedRay);
 84				if (interSP != null){
 85					//FIXME TRIAL - muss für die distance messung der world ray genommen
 86					//werden oder geht der invertierte ray? -> musss wohl der world ray sein
 87					interSP.transform(comp.getGlobalMatrix());
 88					// Get distance from raystart to the intersecting point
 89					objDistance = interSP.getSubtracted(currentRay.getRayStartPoint()).length();
 90					//System.out.println("Pick found: " + comp.getName() + " InterSP: " + interSP +  " ObjDist: " + objDistance +  " Mouse Pos: " + pickInfo.getScreenXCoordinate() + "," + pickInfo.getScreenYCoordinate() + " InvRay RS:" + invertedRay.getRayStartPoint() + ",RE: " + invertedRay.getPointInRayDirection());
 91
 92//					//If the distance is the smallest yet = closest to the raystart: replace the returnObject and current distanceFrom
 93//					if ( (objDistance - HIT_TOLERANCE) <= currObjDist /*|| comp.isAlwaysDrawnOnTop()*/){//take isDrawnOnTop into account here?? -> OBJDistance auf 0 setzen?
 94//					currObjDist = objDistance;
 95//					pickResult.addPickedObject(comp, interSP, objDistance);
 96////					System.out.println("-> Now nearest: " + comp.getName());
 97//					}
 98
 99					//FIXME TEST - ADD ALL PICKED OBJECTS - SORT LATER
100					pickResult.addPickedObject(comp, interSP, objDistance);
101				}
102			}
103			
104			//Check for child clipping shape intersection, if not intersecting -> dont try to pick children
105			Clip childClip = comp.getChildClip();
106			if (childClip != null && childClip.getClipShapeIntersectionLocal(invertedRay) == null){
107				return currObjDist;
108			}
109		}
110		
111		/* recursively check all children now */
112		MTComponent[] childComponents = comp.getChildren();
113		for (int i = 0; i < childComponents.length; i++) {
114			MTComponent child = childComponents[i];
115			if (child.isVisible()) { 
116				if (comp.isComposite()){					
117					//Start a new picking with a new Pickresult obj from here
118					PickResult compositePickRes = new PickResult();
119					float compDistance = pickRecursive(child,pickInfo, compositePickRes, Float.MAX_VALUE, currentRay, onlyPickables);
120
121					//Add the composites picks to the overall picks
122					if (compositePickRes.getNearestPickResult() != null){
123//						System.out.println("In: " + comp.getName() + " Composites child picked, pick resultDistance: " + compDistance);
124						/*//TODO müsste diese hier nach distanz geordnet in insgesamt pickresult einfügen..
125						ArrayList<MTBaseComponent> pickList = compositePickRes.getPickList();
126						for(MTBaseComponent comp : pickList){
127							pickResult.addPickedObject(comp, compositePickRes.getInterSectionPointOfPickedObj(comp), compositePickRes.getDistanceOfPickedObj(comp));
128						}  
129						*/ 
130						//Add comp composite as the last one picked with the distance of the last one picked in the composite pick
131//						pickResult.addPickedObjects(compositePickRes.getPickList());
132//						pickResult.addPickedObject(comp, compositePickRes.getInterSectionPointNearestPickedObj(), compositePickRes.getDistanceNearestPickObj());
133						
134//						if (//compDistance <= currObjDist 
135//							(compDistance - HIT_TOLERANCE) <= currObjDist
136//						){
137////							System.out.println("Composites child picked and now nearest: " + comp.getName()+ " dist: " + compDistance);
138//							pickResult.addPickedObject(comp, compositePickRes.getInterSectionPointNearestPickedObj(), compositePickRes.getDistanceNearestPickObj());
139//							currObjDist = compDistance;
140//						}
141						
142						//FIXME TEST - ADD ALL PICKED OBJECTS - SORT LATER
143						PickEntry nearestPickEntry = compositePickRes.getNearestPickEntry();						
144						pickResult.addPickedObject(nearestPickEntry.hitObj, nearestPickEntry.intersectionPoint, nearestPickEntry.cameraDistance);
145						
146					}
147				}else{
148					currObjDist = pickRecursive(child,pickInfo, pickResult, currObjDist, currentRay, onlyPickables);
149				}
150			}
151		}
152		
153		return currObjDist;
154	}
155	
156	/**
157	 * Calculates the "real" picking ray for the object.
158	 * <br>If the obj has a custom camera attached to it, this camera's position is the new ray origin and
159	 * the point in the ray direction is the unprojected x,y, coordinates while this camera is active.
160	 * 
161	 * @param pa the papplet
162	 * @param obj the obj
163	 * @param ray the ray
164	 * 
165	 * @return the real pick ray
166	 * 
167	 * the new calculated ray, or the original ray, if the obj has no custom camera attached to it.
168	 */
169	private static Ray getChangedCameraPickRay(PApplet pa, IMTComponent3D obj, Ray ray){
170		Vector3D pointInRayDirection = ray.getPointInRayDirection();
171		Vector3D projected = Tools3D.project(pa, obj.getViewingCamera(), pointInRayDirection);
172//		Vector3D projected = Tools3D.project(pa, pointInRayDirection);
173		return getChangedCameraPickRay(pa, obj, new PickInfo(
174				projected.x,
175				projected.y,
176				ray));
177	}
178	
179	/**
180	 * Calculates the "real" pickray for the object.
181	 * <br>If the obj has a custom camera attached to it, this cameras position is the new ray origin and
182	 * the point in the ray direction is the unprojected x,y, coordinates while this camera is active.
183	 * 
184	 * @param pa the pa
185	 * @param obj the obj
186	 * @param pickInfo the pick info
187	 * @return the real pick ray
188	 * 
189	 * the new calculated ray, or the original ray, if the obj has no custom camera attached to it.
190	 */
191	private static Ray getChangedCameraPickRay(PApplet pa, IMTComponent3D obj, PickInfo pickInfo){
192		if (obj.getViewingCamera() != null){ //FIXME TEST
193			//Re-Project unprojected world coords to projected viewport screen coords (Tuio INput)
194			float x = pickInfo.getScreenXCoordinate(); 
195			float y = pickInfo.getScreenYCoordinate(); 
196			
197			return Tools3D.getCameraPickRay(pa, obj, x, y);
198		}else{
199			return pickInfo.getPickRay();
200		}
201		/*//FIXME disabled for performance for now!
202		if (obj.hasCustomViewPort()){
203			//Take VIEWPORT changes into account, too
204			ViewportSetting customViewPort 		   = obj.getCustomViewportSetting();
205			ViewportSetting defaultViewPortSetting = obj.getDefaultViewportSetting();
206			rayStartPoint.setX(customViewPort.getStartX() + (rayStartPoint.getX() * (customViewPort.getWidth()/defaultViewPortSetting.getWidth())));
207			rayStartPoint.setY(customViewPort.getStartY() + (rayStartPoint.getY() * (customViewPort.getHeight()/defaultViewPortSetting.getHeight())));
208			pointInRayDirection.setX(customViewPort.getStartX() + (pointInRayDirection.getX() * (customViewPort.getWidth()/defaultViewPortSetting.getWidth())));
209			pointInRayDirection.setY(customViewPort.getStartY() + (pointInRayDirection.getY() * (customViewPort.getHeight()/defaultViewPortSetting.getHeight())));
210			/////
211		}
212		 */
213//		return new Ray(rayStartPoint, pointInRayDirection);
214	}
215	
216	/* (non-Javadoc)
217	 * this is a different version of getIntersectionGlobal of MTComponent used to deal with collision engine
218	 * @see org.mt4j.components.interfaces.IMTComponent3D#getIntersectionGlobalSpace(util.math.Ray)
219	 */
220	public static Vector3D getIntersectionGlobal(MTComponent comp,Ray ray){ //ADDTOMT4J Chris fragen, wegen pickable {
221		float currentDistance = Float.MAX_VALUE; //high value so that the first time a object is found comp distance is exchanged with his
222		float objDistance 		= 0;
223		Vector3D returnPoint 	= null;
224		Vector3D interSP 		= null;
225		
226		if (comp.isVisible()) { 
227			//Get the real ray for comp obj, takes the custom camera and viewport of comp obj into account
228			//-> changes rayStartPoint and point in ray direction
229			if (comp.getAttachedCamera() != null){
230				ray	= getChangedCameraPickRay(comp.getRenderer(), comp, ray);
231			}
232			
233			//Transforms the ray into local object space 
234			Ray invertedRay = comp.globalToLocal(ray);
235			
236			//Check if component is clipped and only proceed if the ray intersects the clip shape
237			Clip clip = comp.getClip();
238			if (clip == null || (clip != null && clip.getClipShapeIntersectionLocal(invertedRay) != null)){
239				interSP = comp.getIntersectionLocal(invertedRay);
240				if (interSP != null){
241					//FIXME TRIAL - muss für die distance messung der world ray genommen
242					//werden oder geht der invertierte ray?
243					interSP.transform(comp.getGlobalMatrix());
244					//Get distance from raystart to the intersecting point
245					objDistance = interSP.getSubtracted(ray.getRayStartPoint()).length();
246
247					//If the distance is the smalles yet = closest to the raystart replace the returnObject and current distanceFrom
248					if ((objDistance - PickResult.HIT_TOLERANCE) < currentDistance ){
249						returnPoint = interSP;
250						currentDistance = objDistance;
251					}
252				}
253			}
254
255			//Check for child clip intersection, if not intersecting, dont try to pick children
256			Clip childClip = comp.getChildClip();
257			if (childClip != null && childClip.getClipShapeIntersectionLocal(invertedRay) == null){
258				return returnPoint;
259			}
260			
261	}
262		
263		/* Go through all Children */
264//		for (int i = childComponents.size()-1; i >= 0; i--) {
265		MTComponent[] childComponents = comp.getChildren();
266		for (int i = 0; i < childComponents.length; i++) {	
267			MTComponent child = childComponents[i];
268				//Get the intersectionpoint ray/object if there is one
269				interSP = getIntersectionGlobal(child,ray);
270				
271				if (interSP != null ){ //if ray intersects object at a point
272					//System.out.println("Intersection at: " + interSP);
273					//Get distance from raystart to the intersecting point
274					objDistance = interSP.getSubtracted(ray.getRayStartPoint()).length();
275					//If the distance is the smalles yet = closest to the raystart replace the returnObject and current distanceFrom
276					if (objDistance < currentDistance ){
277						returnPoint = interSP;
278						currentDistance = objDistance;
279					}
280				}//if intersection!=null
281		}// for
282		return returnPoint;
283	}
284	
285
286	public static Vector3D getCenterPointGlobal(MTComponent comp) {
287		
288		MTComponent[] children = comp.getChildren();
289		if(children.length==0)
290		{
291			if(comp.hasBounds())
292			{
293				return comp.getBounds().getCenterPointGlobal();
294			}else
295			{
296				return null;
297			}
298		}else
299		{
300			//float massSum = 0.0f;
301			Vector3D vecSum = new Vector3D();
302			for(MTComponent compChild : children)
303			{	
304				if(getCenterPointGlobal(compChild)!=null)
305				{
306					Vector3D vec = getCenterPointGlobal(compChild);					
307					vecSum.addLocal(vec);
308					
309					//massSum += compChild.getMass();
310					
311				}
312			}			
313			
314			return vecSum.getScaled(1.f/children.length);
315		}	
316	}
317	
318}