PageRenderTime 67ms CodeModel.GetById 40ms app.highlight 21ms RepoModel.GetById 1ms app.codeStats 0ms

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