/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. ***********************************************************************/
  18. package org.mt4j.components.bounds;
  19. import org.mt4j.components.MTComponent;
  20. import org.mt4j.components.TransformSpace;
  21. import org.mt4j.components.visibleComponents.shapes.AbstractShape;
  22. import org.mt4j.util.camera.IFrustum;
  23. import org.mt4j.util.math.Matrix;
  24. import org.mt4j.util.math.Ray;
  25. import org.mt4j.util.math.ToolsGeometry;
  26. import org.mt4j.util.math.Vector3D;
  27. import processing.core.PGraphics;
  28. /**
  29. * Bounding rectangle for 2D shapes that are parallel to the Z=0 plane.
  30. *
  31. * @author Christopher Ruff
  32. */
  33. public class BoundsZPlaneRectangle implements IBoundingShape {
  34. // /** The peer component. */
  35. private MTComponent peerComponent;
  36. /** The bounding points local. */
  37. private Vector3D[] boundingPointsLocal;
  38. /** The I n_ plan e_ tolerance. */
  39. public static float IN_PLANE_TOLERANCE = 0.015f;
  40. private Vector3D centerPointLocal;
  41. private Vector3D[] worldVecs;
  42. private boolean worldVecsDirty;
  43. private Vector3D centerPointWorld;
  44. private boolean centerWorldDirty;
  45. //TODO checken ob punkte wirklich in ebene liegen
  46. //-> point in plane test
  47. /**
  48. * Instantiates a new bounds z plane rectangle.
  49. *
  50. * @param peerComponent the peer component
  51. */
  52. public BoundsZPlaneRectangle(AbstractShape peerComponent) {
  53. this(peerComponent, peerComponent.getVerticesLocal());
  54. }
  55. /**
  56. * Instantiates a new bounds z plane rectangle.
  57. *
  58. * @param peerComponent the peer component
  59. * @param x the x
  60. * @param y the y
  61. * @param width the width
  62. * @param height the height
  63. */
  64. public BoundsZPlaneRectangle(MTComponent peerComponent, float x, float y, float width, float height) {
  65. this(peerComponent, new Vector3D[]{new Vector3D(x,y), new Vector3D(x+width,y), new Vector3D(x+width,y+height), new Vector3D(x,y+height)});
  66. }
  67. /**
  68. * Instantiates a new bounds z plane rectangle.
  69. *
  70. * @param peerComponent the peer component
  71. * @param vertices the vertices
  72. */
  73. public BoundsZPlaneRectangle(MTComponent peerComponent, Vector3D[] vertices) {
  74. super();
  75. this.peerComponent = peerComponent;
  76. this.boundingPointsLocal = this.getBoundingRectVertices(vertices);
  77. this.centerPointLocal = this.calcCenterPointLocal();
  78. this.worldVecsDirty = true;
  79. this.centerWorldDirty = true;
  80. // this.worldVecs = this.getVectorsGlobal();
  81. // this.centerPointWorld = this.getCenterPointGlobal();
  82. }
  83. public void setGlobalBoundsChanged(){
  84. this.worldVecsDirty = true;
  85. this.centerWorldDirty = true;
  86. }
  87. /**
  88. * Calculates the bounding rectangles vertices and returns them.
  89. *
  90. * @param vertices the vertices
  91. *
  92. * @return a Vector3D array containing the vertices of the bounding rectangle
  93. */
  94. private Vector3D[] getBoundingRectVertices(Vector3D[] vertices){
  95. float[] minMax = ToolsGeometry.getMinXYMaxXY(vertices);
  96. float minX = minMax[0];
  97. float minY = minMax[1];
  98. float maxX = minMax[2];
  99. float maxY = minMax[3];
  100. float z = vertices[0].z;
  101. if (peerComponent != null && peerComponent instanceof AbstractShape){
  102. z = ((AbstractShape)peerComponent).getCenterPointLocal().z;
  103. }
  104. return (new Vector3D[]{
  105. new Vector3D(minX, minY,z),
  106. new Vector3D(maxX, minY,z),
  107. new Vector3D(maxX, maxY,z),
  108. new Vector3D(minX, maxY,z),
  109. // new Vector3D(minX, minY,z)
  110. });
  111. }
  112. public void drawBounds(final PGraphics g){
  113. g.pushMatrix();
  114. g.pushStyle();
  115. g.fill(150,180);
  116. g.beginShape();
  117. g.vertex(this.boundingPointsLocal[0].x, this.boundingPointsLocal[0].y, this.boundingPointsLocal[0].z);
  118. g.vertex(this.boundingPointsLocal[1].x, this.boundingPointsLocal[1].y, this.boundingPointsLocal[1].z);
  119. g.vertex(this.boundingPointsLocal[2].x, this.boundingPointsLocal[2].y, this.boundingPointsLocal[2].z);
  120. g.vertex(this.boundingPointsLocal[3].x, this.boundingPointsLocal[3].y, this.boundingPointsLocal[3].z);
  121. g.endShape();
  122. g.popStyle();
  123. g.popMatrix();
  124. // g.pushMatrix();
  125. // g.pushStyle();
  126. // g.fill(150,180);
  127. //
  128. // Vector3D[] v = this.getVectorsGlobal();
  129. // float[] minMax = Tools3D.getMinXYMaxXY(v);
  130. //
  131. // g.beginShape();
  132. // g.vertex(minMax[0], minMax[1], 0);
  133. // g.vertex(minMax[2], minMax[1], 0);
  134. // g.vertex(minMax[2], minMax[3], 0);
  135. // g.vertex(minMax[0], minMax[3], 0);
  136. // g.endShape();
  137. ////
  138. // g.popStyle();
  139. // g.popMatrix();
  140. }
  141. public boolean containsPointLocal(Vector3D testPoint) {
  142. return testPoint.x >= this.boundingPointsLocal[0].x
  143. && testPoint.x <= this.boundingPointsLocal[1].x
  144. && testPoint.y >= this.boundingPointsLocal[0].y
  145. && testPoint.y <= this.boundingPointsLocal[2].y
  146. && Math.abs(testPoint.z - this.boundingPointsLocal[0].z) < IN_PLANE_TOLERANCE;
  147. }
  148. public boolean intersects(BoundsZPlaneRectangle boundingRect){
  149. //TODO actually we would have to check all rectangle
  150. //line segments against each other instead of the points
  151. Vector3D[] globalBoundingVectorsR2 = boundingRect.getVectorsGlobal();
  152. Vector3D globalCenterR2 = boundingRect.getCenterPointGlobal();
  153. boolean colliding = false;
  154. //Check if rectangle points lie inside of this rectangle
  155. for (Vector3D aGlobalBoundingVectorsR2 : globalBoundingVectorsR2) {
  156. Vector3D localVectorR2 = peerComponent.globalToLocal(aGlobalBoundingVectorsR2);
  157. if (this.containsPointLocal(localVectorR2)) {
  158. colliding = true;
  159. }
  160. }
  161. //Check rectangle center
  162. if (this.containsPointLocal(peerComponent.globalToLocal(globalCenterR2))){
  163. colliding = true;
  164. }
  165. //System.out.println("Colliding: " + colliding);
  166. return colliding;
  167. }
  168. /** The rect normal. */
  169. private Vector3D rectNormal = new Vector3D(0,0,1);
  170. public Vector3D getIntersectionLocal(Ray ray) {
  171. Vector3D[] verts = this.boundingPointsLocal;
  172. // rectNormal= this.getNormalObjSpace();
  173. //Normal should actually always be (0,0,1)!
  174. Vector3D testPoint = ToolsGeometry.getRayPlaneIntersection(ray, rectNormal, verts[0]);
  175. if (testPoint == null){
  176. return null;
  177. }
  178. return (this.containsPointLocal(testPoint) ? testPoint : null);
  179. }
  180. /**
  181. * Gets the normal obj space.
  182. *
  183. * @return the normal obj space
  184. */
  185. private Vector3D getNormalLocal() {
  186. return ToolsGeometry.getNormal(this.boundingPointsLocal[0], this.boundingPointsLocal[1], this.boundingPointsLocal[2], true);
  187. }
  188. private Vector3D calcCenterPointLocal(){
  189. Vector3D tmp0 = this.boundingPointsLocal[0].getCopy();
  190. Vector3D tmp1 = this.boundingPointsLocal[1].getSubtracted(this.boundingPointsLocal[0]);
  191. tmp1.scaleLocal(0.5f);
  192. Vector3D tmp2 = this.boundingPointsLocal[3].getSubtracted(this.boundingPointsLocal[0]);
  193. tmp2.scaleLocal(0.5f);
  194. tmp0.addLocal(tmp1);
  195. tmp0.addLocal(tmp2);
  196. return tmp0;
  197. }
  198. public Vector3D getCenterPointLocal() {
  199. // Vector3D tmp0 = this.boundingPointsLocal[0].getCopy();
  200. // Vector3D tmp1 = this.boundingPointsLocal[1].getSubtracted(this.boundingPointsLocal[0]);
  201. // tmp1.scaleLocal(0.5f);
  202. //
  203. // Vector3D tmp2 = this.boundingPointsLocal[3].getSubtracted(this.boundingPointsLocal[0]);
  204. // tmp2.scaleLocal(0.5f);
  205. //
  206. // tmp0.addLocal(tmp1);
  207. // tmp0.addLocal(tmp2);
  208. // return tmp0;
  209. return this.centerPointLocal.getCopy();
  210. }
  211. public Vector3D getCenterPointGlobal() {
  212. if (centerWorldDirty){
  213. Vector3D tmp = this.getCenterPointLocal();
  214. tmp.transform(this.peerComponent.getGlobalMatrix());
  215. // tmp = peerComponent.localToGlobal(tmp);
  216. this.centerPointWorld = tmp;
  217. this.centerWorldDirty = false;
  218. return this.centerPointWorld;
  219. }
  220. else{
  221. return this.centerPointWorld;
  222. }
  223. }
  224. public Vector3D[] getVectorsLocal() {
  225. return this.boundingPointsLocal;
  226. }
  227. //FIXME also cache?
  228. public Vector3D[] getVectorsRelativeToParent(){
  229. Vector3D[] vecs = Vector3D.getDeepVertexArrayCopy(this.boundingPointsLocal);
  230. Vector3D.transFormArrayLocal(this.peerComponent.getLocalMatrix(), vecs);
  231. return vecs;
  232. }
  233. public Vector3D[] getVectorsGlobal() {
  234. if (this.worldVecsDirty){
  235. Vector3D[] vecs = Vector3D.getDeepVertexArrayCopy(this.boundingPointsLocal);
  236. Vector3D.transFormArrayLocal(this.peerComponent.getGlobalMatrix(), vecs);
  237. this.worldVecs = vecs;
  238. this.worldVecsDirty = false;
  239. return this.worldVecs;
  240. }else{
  241. return this.worldVecs;
  242. }
  243. // Vector3D[] vecs = Vector3D.getDeepVertexArrayCopy(this.boundingPointsLocal);
  244. // Vector3D.transFormArrayLocal(this.peerComponent.getAbsoluteLocalToWorldMatrix(), vecs);
  245. // return vecs;
  246. }
  247. public float getHeightXY(TransformSpace transformSpace) {
  248. switch (transformSpace) {
  249. case LOCAL:
  250. return this.getHeightXYLocal();
  251. case RELATIVE_TO_PARENT:
  252. return this.getHeightXYRelativeToParent();
  253. case GLOBAL:
  254. return this.getHeightXYGlobal();
  255. default:
  256. return -1;
  257. }
  258. }
  259. /**
  260. * Gets the height xy obj space.
  261. *
  262. * @return the height xy obj space
  263. */
  264. private float getHeightXYLocal() {
  265. return this.getHeightXYVectLocal().length();
  266. }
  267. /**
  268. * Gets the height xy relative to parent.
  269. *
  270. * @return the height xy relative to parent
  271. */
  272. private float getHeightXYRelativeToParent() {
  273. Vector3D p = this.getHeightXYVectLocal();
  274. Matrix m = new Matrix(this.peerComponent.getLocalMatrix());
  275. m.removeTranslationFromMatrix();
  276. p.transform(m);
  277. return p.length();
  278. // Vector3D[] v = this.getVectorsRelativeToParent();
  279. // float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
  280. // return minMax[3] - minMax[1];
  281. }
  282. /**
  283. * Gets the height xy global.
  284. *
  285. * @return the height xy global
  286. */
  287. private float getHeightXYGlobal() {
  288. Vector3D p = this.getHeightXYVectLocal();
  289. Matrix m = new Matrix(this.peerComponent.getGlobalMatrix());
  290. m.removeTranslationFromMatrix();
  291. p.transform(m);
  292. return p.length();
  293. // Vector3D[] v = this.getVectorsGlobal();
  294. // float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
  295. // return minMax[3] - minMax[1];
  296. }
  297. /**
  298. * Gets the "height vector". The vector is calculated from the bounds vectors,
  299. * representing a vector with the height as its length in object space.
  300. *
  301. * @return the height xy vect obj space
  302. *
  303. * vector representing the height of the boundingshape of the shape
  304. */
  305. public Vector3D getHeightXYVectLocal() {
  306. Vector3D[] boundRectVertsLocal = this.getVectorsLocal();
  307. Vector3D height = boundRectVertsLocal[2].getSubtracted(boundRectVertsLocal[1]);
  308. return height;
  309. }
  310. public float getWidthXY(TransformSpace transformSpace) {
  311. switch (transformSpace) {
  312. case LOCAL:
  313. return this.getWidthXYLocal();
  314. case RELATIVE_TO_PARENT:
  315. return this.getWidthXYRealtiveToParent();
  316. case GLOBAL:
  317. return this.getWidthXYGlobal();
  318. default:
  319. return -1;
  320. }
  321. }
  322. /**
  323. * Gets the width xy obj space.
  324. *
  325. * @return the width xy obj space
  326. */
  327. private float getWidthXYLocal() {
  328. return this.getWidthXYVectLocal().length();
  329. }
  330. /**
  331. * Gets the width xy realtive to parent.
  332. *
  333. * @return the width xy realtive to parent
  334. */
  335. private float getWidthXYRealtiveToParent() {
  336. //This calculates the width aligned/relative to the object
  337. Vector3D p = this.getWidthXYVectLocal();
  338. Matrix m = new Matrix(this.peerComponent.getLocalMatrix());
  339. m.removeTranslationFromMatrix();
  340. p.transform(m);
  341. return p.length();
  342. //This calculates the dimension relative to the screen axis (here X-axis)
  343. // Vector3D[] v = this.getVectorsRelativeToParent();
  344. // float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
  345. // return minMax[2] - minMax[0];
  346. }
  347. /**
  348. * Gets the width xy global.
  349. *
  350. * @return the width xy global
  351. */
  352. private float getWidthXYGlobal() {
  353. Vector3D p = this.getWidthXYVectLocal();
  354. Matrix m = new Matrix(this.peerComponent.getGlobalMatrix());
  355. m.removeTranslationFromMatrix();
  356. p.transform(m);
  357. return p.length();
  358. // Vector3D[] v = this.getVectorsGlobal();
  359. // float[] minMax = ToolsGeometry.getMinXYMaxXY(v);
  360. // return minMax[2] - minMax[0];
  361. }
  362. /**
  363. * Gets the "Width vector". The vector is calculated from the bounds vectors,
  364. * representing a vector with the Width as its length in object space.
  365. *
  366. * @return the width xy vect obj space
  367. *
  368. * vector representing the Width of the boundingshape of the shape
  369. */
  370. //@Override
  371. public Vector3D getWidthXYVectLocal() {
  372. Vector3D[] boundRectVertsLocal = this.getVectorsLocal();
  373. Vector3D width = boundRectVertsLocal[1].getSubtracted(boundRectVertsLocal[0]);
  374. // System.out.println("Width of " + this.getName()+ " :" + width);
  375. return width;
  376. }
  377. public boolean isContainedInFrustum(IFrustum frustum) {
  378. Vector3D[] points = this.getVectorsGlobal();
  379. for (Vector3D vector3D : points) {
  380. int test = frustum.isPointInFrustum(vector3D);
  381. if (test == IFrustum.INSIDE
  382. || test == IFrustum.INTERSECT
  383. ) {
  384. return true;
  385. }
  386. }
  387. //Also check if center point is in frustum
  388. Vector3D center = this.getCenterPointGlobal();
  389. int test = frustum.isPointInFrustum(center);
  390. return test == IFrustum.INSIDE
  391. || test == IFrustum.INTERSECT;
  392. }
  393. }