1 /*
  2   Copyright (c) 2008 Seneca College
  3   Licenced under the MIT License (http://www.c3dl.org/index.php/mit-license/)
  4 */
  5 
  6 
  7 /**
  8 	@class c3dl.Camera is a base class for c3dl.OrbitCamera and c3dl.FreeCamera. 
  9 */
 10 c3dl.Camera = function()
 11 {
 12 	// Raw Position Values
 13 	this.left	= [1.0, 0.0, 0.0]; // Camera Left vector
 14 	this.up	= [0.0, 1.0, 0.0]; // Camera Up vector
 15 	this.dir	= [0.0, 0.0, 1.0]; // The direction its looking at
 16 	this.pos	= [0.0, 0.0, 0.0]; // Camera eye position
 17 		
 18 	this.projectionTransform = null;
 19 	this.projMatrix;
 20 	this.viewMatrix;
 21 
 22 	this.fieldOfView = c3dl.DEFAULT_FIELD_OF_VIEW;
 23 	this.nearClippingPlane = c3dl.DEFAULT_NEAR_CLIPPING_PLANE;
 24 	this.farClippingPlane = c3dl.DEFAULT_FAR_CLIPPING_PLANE;
 25 }
 26 
 27 
 28 /**
 29 	@private
 30 	
 31 	Create the projection matrix.
 32 
 33 	Places the view matrix at the bottom of the matrix stack.
 34 */
 35 c3dl.Camera.prototype.applyToWorld = function(aspectRatio)
 36 {	
 37 	// set the bottom matrix of the matrix stack to the viewmatrix
 38 	c3dl.loadMatrix(c3dl.lookAt(this.pos,c3dl.addVectors(this.pos,this.dir), this.up));
 39 	c3dl.translate(-this.pos[0], -this.pos[1], -this.pos[2]);
 40 	this.viewMatrix = c3dl.peekMatrix();
 41 	
 42   // Create a projection matrix and store it inside a globally accessible place.
 43 	this.projMatrix = c3dl.makePerspective(this.fieldOfView, aspectRatio, this.nearClippingPlane, this.farClippingPlane);  
 44 	c3dl.matrixMode(c3dl.PROJECTION);
 45 	c3dl.loadMatrix(this.projMatrix);
 46 	c3dl.matrixMode(c3dl.MODELVIEW);
 47 }
 48 
 49 
 50 /**
 51 	Get the direction of the camera.
 52 	
 53 	@returns {Array} vector
 54 */
 55 c3dl.Camera.prototype.getDir = function()
 56 {
 57 	return [this.dir[0], this.dir[1], this.dir[2]];
 58 }
 59 
 60 
 61 /**
 62 	Get the far clipping plane.
 63 
 64 	@returns {float} far clipping plane value.
 65 */
 66 c3dl.Camera.prototype.getFarClippingPlane = function()
 67 {
 68 	return this.farClippingPlane;
 69 }
 70 
 71 
 72 /**
 73 	Get the vertical field of view for this camera in degrees.
 74 	
 75 	@returns {float} field of view is greater than 0 and less than 180.
 76 */
 77 c3dl.Camera.prototype.getFieldOfView = function()
 78 {
 79 	return this.fieldOfView;
 80 }
 81 
 82 
 83 /**
 84 	Get the left vector of the camera.
 85 	
 86 	@returns {Array} vector
 87 */
 88 c3dl.Camera.prototype.getLeft = function()
 89 {
 90 	return [this.left[0], this.left[1], this.left[2]];
 91 }
 92 
 93 
 94 /**
 95 	Get the near clipping plane.
 96 
 97 	@returns {float} near clipping plane value.
 98 */
 99 c3dl.Camera.prototype.getNearClippingPlane = function()
100 {
101 	return this.nearClippingPlane;
102 }
103 
104 
105 /**
106 	Get the position of the camera.
107 
108 	@returns {Array} A three element array which contains the position of the camera.
109 */
110 c3dl.Camera.prototype.getPosition = function()
111 {
112 	return [this.pos[0], this.pos[1], this.pos[2]];
113 }
114 
115 
116 /**
117 	@private
118 */
119 c3dl.Camera.prototype.getProjectionMatrix = function()
120 {
121 	return c3dl.copyObj(this.projMatrix);
122 }
123 
124 /**
125 	@private
126 */
127 c3dl.Camera.prototype.getViewMatrix = function()
128 {
129 	return c3dl.copyObj(this.viewMatrix);
130 }
131 
132 /**
133 	Get the up vector of the camera.
134 
135 	@returns {Array}
136 */
137 c3dl.Camera.prototype.getUp = function()
138 {
139 	return [this.up[0], this.up[1], this.up[2]];
140 }
141 
142 
143 /**
144 	The far clipping plane should not be set to an extremely large value. This
145 	can create depth buffer precision problems such as z-fighting. see
146 	http://www.opengl.org/resources/faq/technical/depthbuffer.htm for more information.
147 	
148 	@param {float} fcp Must be larger than 0.
149 */
150 c3dl.Camera.prototype.setFarClippingPlane = function(fcp)
151 {
152 	if( fcp > 0 )
153 	{
154 		this.farClippingPlane = fcp;
155 	}
156 }
157 
158 
159 /**
160 	Set the field of view for this camera in degrees.
161 
162 	@param {float} fov Specified in degrees. Must be greater than 0 and less than 180.
163 */
164 c3dl.Camera.prototype.setFieldOfView = function(fov)
165 {
166 	if( fov > 0 && fov < 180)
167 	{
168 		this.fieldOfView = fov;
169 	}
170 }
171 
172 
173 /**
174 	The near clipping plane must be set to a positive value.
175 
176 	@param {float} ncp Must be larger than 0.
177 */
178 c3dl.Camera.prototype.setNearClippingPlane = function(ncp)
179 {
180 	if( ncp > 0)
181 	{
182 		this.nearClippingPlane = ncp;
183 	}
184 }
185 
186 /**
187 	Get a string representation of this camera.
188 	
189 	@param {String} [delimiter=","]  A string used to separate the member
190 	variables of the object.
191 	
192 	@returns {String} a string representation of this class.
193 */
194 c3dl.Camera.prototype.toString = function(delimiter)
195 {	
196 	// make sure user passed up a string if they actually decided
197 	// to specify a delimiter.
198 	if(!delimiter || typeof(delimiter) != "string")
199 	{
200 		delimiter = ",";
201 	}
202 		
203 	return	"c3dl.Camera: " + delimiter +
204 			"left: "				+ this.getLeft()			+ delimiter +
205 			"up: "					+ this.getUp()				+ delimiter +
206 			"direction: "			+ this.getDir()				+ delimiter + 
207 			"position: "			+ this.getPosition()		+ delimiter +
208 			"fied of view: "		+ this.getFieldOfView()		+ delimiter +
209 			"near clipping plane: "	+ this.getNearClippingPlane()	+ delimiter +
210 			"far clipping plane: "	+ this.getFarClippingPlane()	+ delimiter;
211 }
212 
213 /**
214 	@private
215 	
216 	Called automatically.
217 
218 	Update Animation of the camera.
219 
220 	@param {float} timeStep 
221 */
222 c3dl.Camera.prototype.update = function(timeStep)
223 {
224 
225 	if (c3dl.isVectorZero(linVel) && c3dl.isVectorZero(angVel)) return false;
226 	
227 	if (c3dl.vectorLengthSq(linVel) > 0.0)
228 	{
229 		// Add a velocity to the position
230 		velVec = c3dl.makeVector(linVel[0], linVel[1], linVel[2]);
231 		c3dl.multiplyVector(velVec, timeStep, velVec);
232 		
233 		c3dl.addVectors(pos, velVec, pos);
234 	}
235 	
236 	if (c3dl.vectorLengthSq(angVel) > 0.0)
237 	{
238 		// Apply some rotations to the orientation from the angular velocity
239 		this.pitch(angVel[0] * timeStep);
240 		this.yaw(angVel[1] * timeStep);
241 		this.roll(angVel[2] * timeStep);
242 	}	
243 
244 	return true;
245 }
246