/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

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