/src/org/mt4j/util/camera/MTCamera.java

http://mt4j.googlecode.com/ · Java · 596 lines · 227 code · 80 blank · 289 comment · 5 complexity · de0719c1d01564d731c207a19e27c40f 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.util.camera;
  19. import org.mt4j.util.math.Matrix;
  20. import org.mt4j.util.math.Vector3D;
  21. import processing.core.PApplet;
  22. import processing.core.PGraphics3D;
  23. import processing.core.PMatrix3D;
  24. /**
  25. * The Class MTCamera.
  26. * @author Christopher Ruff
  27. */
  28. public class MTCamera implements Icamera{
  29. /** The pa. */
  30. private PApplet pa;
  31. /** The view center pos. */
  32. private Vector3D viewCenterPos;
  33. /** The cam pos. */
  34. private Vector3D camPos;
  35. /** The x axis up. */
  36. private float xAxisUp;
  37. /** The y axis up. */
  38. private float yAxisUp;
  39. /** The z axis up. */
  40. private float zAxisUp;
  41. /** The zoom min distance. */
  42. private float zoomMinDistance;
  43. private Frustum frustum;
  44. private boolean dirty;
  45. private PMatrix3D cameraMat;
  46. private PMatrix3D cameraInvMat;
  47. private Matrix cameraMatrix;
  48. private Matrix cameraInvMatrix;
  49. private PGraphics3D p3d;
  50. /**
  51. * Instantiates a new mT camera.
  52. *
  53. * @param processingApplet the processing applet
  54. */
  55. public MTCamera(PApplet processingApplet){
  56. this(processingApplet.width/2.0f, processingApplet.height/2.0f, processingApplet.height/2.0f / PApplet.tan(PApplet.PI*60.0f / 360.0f),
  57. processingApplet.width/2.0f, processingApplet.height/2.0f, 0, 0, 1,0, processingApplet);
  58. }
  59. /**
  60. * Instantiates a new mT camera.
  61. *
  62. * @param cameraPosX the camera pos x
  63. * @param cameraPosY the camera pos y
  64. * @param cameraPosZ the camera pos z
  65. * @param camEyePosX the cam eye pos x
  66. * @param camEyePosY the cam eye pos y
  67. * @param camEyePosZ the cam eye pos z
  68. * @param xAxisUp the x axis up
  69. * @param yAxisUp the y axis up
  70. * @param zAxisUp the z axis up
  71. * @param processingApplet the processing applet
  72. */
  73. public MTCamera(float cameraPosX, float cameraPosY, float cameraPosZ,
  74. float camEyePosX, float camEyePosY, float camEyePosZ,
  75. float xAxisUp, float yAxisUp, float zAxisUp,
  76. PApplet processingApplet){
  77. this.pa = processingApplet;
  78. this.camPos = new Vector3D(cameraPosX, cameraPosY, cameraPosZ);
  79. this.viewCenterPos = new Vector3D(camEyePosX, camEyePosY, camEyePosZ);
  80. this.xAxisUp = xAxisUp;
  81. this.yAxisUp = yAxisUp;
  82. this.zAxisUp = zAxisUp;
  83. this.zoomMinDistance = 0;
  84. this.frustum = new Frustum(pa);
  85. this.frustum.setCamDef(this.getPosition(), this.getViewCenterPos(), xAxisUp, -yAxisUp, zAxisUp); //new Vector3D(xAxisUp, -yAxisUp, zAxisUp));
  86. this.p3d = ((PGraphics3D)pa.g);
  87. this.dirty = true;
  88. this.cameraMat = new PMatrix3D();
  89. this.cameraInvMat = new PMatrix3D();
  90. this.cameraMatrix = new Matrix();
  91. this.cameraInvMatrix = new Matrix();
  92. }
  93. /**
  94. * Sets or updates the camera with the values specified in the camera.
  95. * <br> <b>Call this after changing any camera values to take effect!</b>.
  96. * <br><strong>Note:</strong> The current modelview matrices (=all transformations made up to this point) will be reset and replaced by the camera values!
  97. */
  98. public void update(){
  99. /*
  100. pa.camera(camPos.getX(), camPos.getY() , camPos.getZ(), //eyeposition
  101. viewCenterPos.getX(), viewCenterPos.getY(), viewCenterPos.getZ(), //view center
  102. xAxisUp, yAxisUp, zAxisUp); //which axis points up?
  103. this.frustum.setCamDef(this.getPosition(), this.getViewCenterPos(), xAxisUp, -yAxisUp, zAxisUp); //new Vector3D(xAxisUp, -yAxisUp, zAxisUp));
  104. */
  105. // /*
  106. if (this.dirty){
  107. // System.out.println("Calc new camera");
  108. this.calcCameraMatrix(camPos.getX(), camPos.getY() , camPos.getZ(), //eyeposition
  109. viewCenterPos.getX(), viewCenterPos.getY(), viewCenterPos.getZ(), //view center
  110. xAxisUp, yAxisUp, zAxisUp);//which axis points up?
  111. this.setCachedCamMatrices();
  112. this.frustum.setCamDef(this.getPosition(), this.getViewCenterPos(), xAxisUp, -yAxisUp, zAxisUp); //new Vector3D(xAxisUp, -yAxisUp, zAxisUp));
  113. }else{
  114. // System.out.println("Use Cached");
  115. this.setCachedCamMatrices();
  116. }
  117. // */
  118. }
  119. private void setCachedCamMatrices(){
  120. Matrix m = this.cameraMatrix;
  121. Matrix mi = this.cameraInvMatrix;
  122. cameraMat.set(
  123. m.m00, m.m01, m.m02, m.m03,
  124. m.m10, m.m11, m.m12, m.m13,
  125. m.m20, m.m21, m.m22, m.m23,
  126. m.m30, m.m31, m.m32, m.m33);
  127. cameraInvMat.set(
  128. mi.m00, mi.m01, mi.m02, mi.m03,
  129. mi.m10, mi.m11, mi.m12, mi.m13,
  130. mi.m20, mi.m21, mi.m22, mi.m23,
  131. mi.m30, mi.m31, mi.m32, mi.m33);
  132. //cant also set cameraInv..not visible
  133. p3d.camera.set(
  134. m.m00, m.m01, m.m02, m.m03,
  135. m.m10, m.m11, m.m12, m.m13,
  136. m.m20, m.m21, m.m22, m.m23,
  137. m.m30, m.m31, m.m32, m.m33);
  138. //FIXME cannot set p5 cameraInv because its not visible..problem?
  139. p3d.modelview.set(cameraMat);
  140. p3d.modelviewInv.set(cameraInvMat);
  141. }
  142. private void calcCameraMatrix(float eyeX, float eyeY, float eyeZ,
  143. float centerX, float centerY, float centerZ,
  144. float upX, float upY, float upZ
  145. ) {
  146. /*
  147. float z0 = eyeX - centerX;
  148. float z1 = eyeY - centerY;
  149. float z2 = eyeZ - centerZ;
  150. float mag = FastMath.sqrt(z0*z0 + z1*z1 + z2*z2);
  151. if (mag != 0) {
  152. z0 /= mag;
  153. z1 /= mag;
  154. z2 /= mag;
  155. }
  156. float y0 = upX;
  157. float y1 = upY;
  158. float y2 = upZ;
  159. float x0 = y1*z2 - y2*z1;
  160. float x1 = -y0*z2 + y2*z0;
  161. float x2 = y0*z1 - y1*z0;
  162. y0 = z1*x2 - z2*x1;
  163. y1 = -z0*x2 + z2*x0;
  164. y2 = z0*x1 - z1*x0;
  165. mag = FastMath.sqrt(x0*x0 + x1*x1 + x2*x2);
  166. if (mag != 0) {
  167. x0 /= mag;
  168. x1 /= mag;
  169. x2 /= mag;
  170. }
  171. mag = FastMath.sqrt(y0*y0 + y1*y1 + y2*y2);
  172. if (mag != 0) {
  173. y0 /= mag;
  174. y1 /= mag;
  175. y2 /= mag;
  176. }
  177. try {
  178. //just does an apply to the main matrix,
  179. //since that'll be copied out on endCamera
  180. // cameraMat.set(
  181. // x0, x1, x2, 0,
  182. // y0, y1, y2, 0,
  183. // z0, z1, z2, 0,
  184. // 0, 0, 0, 1);
  185. // cameraMat.translate(-eyeX, -eyeY, -eyeZ);
  186. // this.cameraMatrix.set(new float[]{
  187. // x0, x1, x2, -eyeX,
  188. // y0, y1, y2, -eyeY,
  189. // z0, z1, z2, -eyeZ,
  190. // 0, 0, 0, 1
  191. // });
  192. this.cameraMatrix.set(new float[]{
  193. x0, x1, x2, 0,
  194. y0, y1, y2, 0,
  195. z0, z1, z2, 0,
  196. 0, 0, 0, 1
  197. });
  198. this.cameraMatrix.mult(Matrix.getTranslationMatrix(-eyeX, -eyeY, -eyeZ), this.cameraMatrix);
  199. System.out.println("My cammatrix: " + this.cameraMatrix);
  200. // cameraInvMat.reset();
  201. // cameraInvMat.invApply(
  202. // x0, x1, x2, 0,
  203. // y0, y1, y2, 0,
  204. // z0, z1, z2, 0,
  205. // 0, 0, 0, 1);
  206. // cameraInvMat.translate(eyeX, eyeX, eyeZ);
  207. this.cameraInvMatrix = this.cameraMatrix.invert(this.cameraInvMatrix);
  208. // this.cameraInvMatrix.set(new float[]{
  209. // x0, x1, x2, eyeX,
  210. // y0, y1, y2, eyeX,
  211. // z0, z1, z2, eyeZ,
  212. // 0, 0, 0, 1
  213. // });
  214. this.dirty = false;
  215. } catch (Exception e) {
  216. e.printStackTrace();
  217. }
  218. */
  219. // /*
  220. try {
  221. pa.camera(camPos.getX(), camPos.getY() , camPos.getZ(), //eyeposition
  222. viewCenterPos.getX(), viewCenterPos.getY(), viewCenterPos.getZ(), //view center
  223. xAxisUp, yAxisUp, zAxisUp); //which axis points up?
  224. this.cameraMatrix.set(new float[]{
  225. p3d.modelview.m00, p3d.modelview.m01, p3d.modelview.m02, p3d.modelview.m03,
  226. p3d.modelview.m10, p3d.modelview.m11, p3d.modelview.m12, p3d.modelview.m13,
  227. p3d.modelview.m20, p3d.modelview.m21, p3d.modelview.m22, p3d.modelview.m23,
  228. p3d.modelview.m30, p3d.modelview.m31, p3d.modelview.m32, p3d.modelview.m33
  229. });
  230. // System.out.println("p5 camMatrix: " + this.cameraMatrix);
  231. this.cameraInvMatrix.set(new float[]{
  232. p3d.modelviewInv.m00, p3d.modelviewInv.m01, p3d.modelviewInv.m02, p3d.modelviewInv.m03,
  233. p3d.modelviewInv.m10, p3d.modelviewInv.m11, p3d.modelviewInv.m12, p3d.modelviewInv.m13,
  234. p3d.modelviewInv.m20, p3d.modelviewInv.m21, p3d.modelviewInv.m22, p3d.modelviewInv.m23,
  235. p3d.modelviewInv.m30, p3d.modelviewInv.m31, p3d.modelviewInv.m32, p3d.modelviewInv.m33
  236. });
  237. this.dirty = false;
  238. } catch (Exception e) {
  239. e.printStackTrace();
  240. }
  241. // */
  242. }
  243. /**
  244. * Gets the camera matrix.
  245. *
  246. * @return the camera matrix
  247. */
  248. public Matrix getCameraMatrix(){
  249. if (this.dirty){
  250. this.calcCameraMatrix(camPos.getX(), camPos.getY() , camPos.getZ(), //eyeposition
  251. viewCenterPos.getX(), viewCenterPos.getY(), viewCenterPos.getZ(), //view center
  252. xAxisUp, yAxisUp, zAxisUp);//which axis points up?
  253. this.setCachedCamMatrices();
  254. this.frustum.setCamDef(this.getPosition(), this.getViewCenterPos(), xAxisUp, -yAxisUp, zAxisUp); //new Vector3D(xAxisUp, -yAxisUp, zAxisUp));
  255. }else{
  256. this.setCachedCamMatrices();
  257. }
  258. return this.cameraMatrix;
  259. }
  260. /**
  261. * Gets the camera inv matrix.
  262. *
  263. * @return the camera inv matrix
  264. */
  265. public Matrix getCameraInvMatrix(){
  266. if (this.dirty){
  267. this.calcCameraMatrix(camPos.getX(), camPos.getY() , camPos.getZ(), //eyeposition
  268. viewCenterPos.getX(), viewCenterPos.getY(), viewCenterPos.getZ(), //view center
  269. xAxisUp, yAxisUp, zAxisUp);//which axis points up?
  270. this.setCachedCamMatrices();
  271. this.frustum.setCamDef(this.getPosition(), this.getViewCenterPos(), xAxisUp, -yAxisUp, zAxisUp); //new Vector3D(xAxisUp, -yAxisUp, zAxisUp));
  272. }else{
  273. this.setCachedCamMatrices();
  274. }
  275. return this.cameraInvMatrix;
  276. }
  277. /**
  278. * Zooms from the camera to the eye location by the given factor.
  279. *
  280. * @param factor the factor
  281. */
  282. public void zoomFactor(float factor){
  283. factor = 1/factor;
  284. Vector3D dirToCamVect = camPos.getSubtracted(viewCenterPos);
  285. dirToCamVect.scaleLocal(factor);
  286. if (dirToCamVect.length() > zoomMinDistance){
  287. Vector3D toCam = viewCenterPos.getAdded(dirToCamVect);
  288. camPos.setXYZ(toCam.getX(), toCam.getY(), toCam.getZ());
  289. this.dirty = true;
  290. }
  291. }
  292. /**
  293. * changes the distance from the eye to the camera location by the given amount
  294. * negative values will increase the distance, positive values will decrease it.
  295. *
  296. * @param amount the amount
  297. */
  298. public void zoomAmount(float amount){
  299. amount*=-1;
  300. //Get direction vector from eye to camera
  301. Vector3D dirToCamVect = camPos.getSubtracted(viewCenterPos);
  302. //get the length of that vector
  303. float mag = dirToCamVect.length();
  304. //normalize the vector
  305. dirToCamVect.normalizeLocal();
  306. //scale the normalized vector with the original amount + the zoom amount
  307. dirToCamVect.scaleLocal(mag + amount);
  308. if (dirToCamVect.length() > zoomMinDistance){
  309. //Get the Vector to the camera from origin
  310. Vector3D toCam = viewCenterPos.getAdded(dirToCamVect);
  311. //set the new camPos
  312. camPos.setXYZ(toCam.getX(), toCam.getY(), toCam.getZ());
  313. this.dirty = true;
  314. }
  315. }
  316. /**
  317. * prevent zooming the cam to the center too close
  318. * set the minimal distance between the cam and the center.
  319. *
  320. * @param minDistance the min distance
  321. */
  322. public void setZoomMinDistance(float minDistance){
  323. this.zoomMinDistance = minDistance;
  324. }
  325. /**
  326. * Gets the zoom min distance.
  327. *
  328. * @return the zoom min distance
  329. */
  330. public float getZoomMinDistance() {
  331. return zoomMinDistance;
  332. }
  333. // /**
  334. // * sets the position of the camera.
  335. // *
  336. // * @param x the x
  337. // * @param y the y
  338. // * @param z the z
  339. // */
  340. // public void setCamPosition(float x, float y, float z){
  341. // camPos.setXYZ(x, y, z);
  342. // this.dirty = true;
  343. // }
  344. /**
  345. * Move cam.
  346. *
  347. * @param directionX the direction x
  348. * @param directionY the direction y
  349. * @param directionZ the direction z
  350. */
  351. public void moveCam(float directionX, float directionY, float directionZ){
  352. camPos.setXYZ(camPos.getX() + directionX, camPos.getY() + directionY, camPos.getZ() + directionZ);
  353. this.dirty = true;
  354. }
  355. /**
  356. * sets the position of the center view point.
  357. *
  358. * @param x the x
  359. * @param y the y
  360. * @param z the z
  361. */
  362. public void setViewCenterPosition(float x, float y, float z){
  363. viewCenterPos.setXYZ(x, y, z);
  364. this.dirty = true;
  365. }
  366. /**
  367. * moves the view center location by the given values in the given directions.
  368. *
  369. * @param directionX the direction x
  370. * @param directionY the direction y
  371. * @param directionZ the direction z
  372. */
  373. public void moveViewCenter(float directionX, float directionY, float directionZ){
  374. viewCenterPos.setXYZ(viewCenterPos.getX() + directionX, viewCenterPos.getY() + directionY, viewCenterPos.getZ() + directionZ);
  375. this.dirty = true;
  376. }
  377. /**
  378. * moves both the view center and the camera location by the given values in the given directions.
  379. *
  380. * @param directionX the direction x
  381. * @param directionY the direction y
  382. * @param directionZ the direction z
  383. */
  384. public void moveCamAndViewCenter(float directionX, float directionY, float directionZ){
  385. moveCam(directionX, directionY, directionZ);
  386. moveViewCenter(directionX, directionY, directionZ);
  387. this.dirty = true;
  388. }
  389. /**
  390. * Gets the cam view center distance.
  391. *
  392. * @return the cam view center distance
  393. */
  394. public float getCamViewCenterDistance(){
  395. return Vector3D.distance(getPosition(), getViewCenterPos());
  396. }
  397. /**
  398. * Reset to default.
  399. */
  400. public void resetToDefault(){
  401. this.camPos = new Vector3D((float)(pa.width/2.0), (float)(pa.height/2.0), (float)(pa.height/2.0) / PApplet.tan((float)(PApplet.PI*60.0 / 360.0)));
  402. this.viewCenterPos = new Vector3D((float)(pa.width/2.0), (float)(pa.height/2.0), 0) ;
  403. this.xAxisUp = 0;
  404. this.yAxisUp = 1;
  405. this.zAxisUp = 0;
  406. this.dirty = true;
  407. }
  408. /* (non-Javadoc)
  409. * @see util.camera.Icamera#getPosition()
  410. */
  411. public Vector3D getPosition() {
  412. return new Vector3D(camPos);
  413. }
  414. /* (non-Javadoc)
  415. * @see util.camera.Icamera#setPosition(util.math.Vector3D)
  416. */
  417. public void setPosition(Vector3D camPos) {
  418. this.camPos = camPos;
  419. this.dirty = true;
  420. }
  421. /* (non-Javadoc)
  422. * @see util.camera.Icamera#getViewCenterPos()
  423. */
  424. public Vector3D getViewCenterPos() {
  425. return viewCenterPos;
  426. }
  427. /* (non-Javadoc)
  428. * @see util.camera.Icamera#setViewCenterPos(util.math.Vector3D)
  429. */
  430. public void setViewCenterPos(Vector3D eyePos) {
  431. this.viewCenterPos = eyePos;
  432. this.dirty = true;
  433. }
  434. /**
  435. * Gets the x axis up.
  436. *
  437. * @return the x axis up
  438. */
  439. public float getXAxisUp() {
  440. return xAxisUp;
  441. }
  442. /**
  443. * Sets the x axis up.
  444. *
  445. * @param axisUp the new x axis up
  446. */
  447. public void setXAxisUp(float axisUp) {
  448. xAxisUp = axisUp;
  449. this.dirty = true;
  450. }
  451. /**
  452. * Gets the y axis up.
  453. *
  454. * @return the y axis up
  455. */
  456. public float getYAxisUp() {
  457. return yAxisUp;
  458. }
  459. /**
  460. * Sets the y axis up.
  461. *
  462. * @param axisUp the new y axis up
  463. */
  464. public void setYAxisUp(float axisUp) {
  465. yAxisUp = axisUp;
  466. this.dirty = true;
  467. }
  468. /**
  469. * Gets the z axis up.
  470. *
  471. * @return the z axis up
  472. */
  473. public float getZAxisUp() {
  474. return zAxisUp;
  475. }
  476. /**
  477. * Sets the z axis up.
  478. *
  479. * @param axisUp the new z axis up
  480. */
  481. public void setZAxisUp(float axisUp) {
  482. zAxisUp = axisUp;
  483. this.dirty = true;
  484. }
  485. public Frustum getFrustum() {
  486. return frustum;
  487. }
  488. public int isSphereInFrustum(Vector3D p, float radius){
  489. return this.getFrustum().isSphereInFrustum(p, radius);
  490. }
  491. public int isPointInFrustum(Vector3D p) {
  492. return this.getFrustum().isPointInFrustum(p);
  493. }
  494. // public boolean contains(IBoundingShape bounds){
  495. // if (bounds != null){
  496. //
  497. //
  498. // }else{
  499. // return true;
  500. // }
  501. // }
  502. //TODO setFrustum(float near, float far, float left, float right, float top, float bottom);
  503. //TODO setFrustumPerspective(float fovY, float aspect, float near, float far);
  504. }