1 /**
  2  * potree.js 
  3  * http://potree.org
  4  *
  5  * Copyright 2012, Markus Sch�tz
  6  * Licensed under the GPL Version 2 or later.
  7  * - http://potree.org/wp/?page_id=7
  8  * - http://www.gnu.org/licenses/gpl-3.0.html
  9  *
 10  */
 11 
 12 /**
 13  * 
 14  * @class
 15  */
 16 function Frustum(){
 17 	this.nearPlane = null;
 18 	this.farPlane = null;
 19 	this.leftPlane = null;
 20 	this.rightPlane =null;
 21 	this.topPlane = null;
 22 	this.bottomPlane = null;
 23 	
 24 	// the 4 coordinates of the near cap. 
 25 	// UL: upper left, UR: upper right, LL: lower left, LR: lower right
 26 	this.pNearUL = null;
 27 	this.pNearUR = null;
 28 	this.pNearLL = null;
 29 	this.pNearLR = null;
 30 
 31 	// the 4 coordinates of the far cap. 
 32 	this.pFarUL =  null;
 33 	this.pFarUR =  null;
 34 	this.pFarLL =  null;
 35 	this.pFarLR =  null;
 36 	
 37 	this.planes = new Array();
 38 }
 39 
 40 Frustum.fromCamera = function(camera){
 41 	var frustum = new Frustum();
 42 	
 43 	var world = camera.globalTransformation;
 44 	
 45 	var heightNear = 2*camera.nearClipPlane*Math.tan(camera.fieldOfView * Math.PI / 360);
 46 	var heightFar =  2*camera.farClipPlane*Math.tan(camera.fieldOfView * Math.PI / 360);
 47 	var widthNear = heightNear * camera.aspectRatio;
 48 	var widthFar = heightFar * camera.aspectRatio;
 49 
 50 	// near and far center coordinates
 51 	var pNearC = [0, 0, -camera.nearClipPlane];
 52 	var pFarC = [0, 0,-camera.farClipPlane];
 53 	
 54 	// the 4 coordinates of the near cap. 
 55 	frustum.pNearUL = V3.add(pNearC, [-widthNear/2, +heightNear/2, 0]); 
 56 	frustum.pNearUR = V3.add(pNearC, [+widthNear/2, +heightNear/2, 0]);
 57 	frustum.pNearLL = V3.add(pNearC, [-widthNear/2, -heightNear/2, 0]);
 58 	frustum.pNearLR = V3.add(pNearC, [+widthNear/2, -heightNear/2, 0]);
 59 	
 60 	// the 4 coordinates of the far cap
 61 	frustum.pFarUL = V3.add(pFarC, [-widthFar/2, +heightFar/2, 0]); 
 62 	frustum.pFarUR = V3.add(pFarC, [+widthFar/2, +heightFar/2, 0]);
 63 	frustum.pFarLL = V3.add(pFarC, [-widthFar/2, -heightFar/2, 0]);
 64 	frustum.pFarLR = V3.add(pFarC, [+widthFar/2, -heightFar/2, 0]);
 65 	
 66 	// transform coordinates into world space
 67 	frustum.pNearUL = V3.transform(frustum.pNearUL, world);
 68 	frustum.pNearUR = V3.transform(frustum.pNearUR, world);
 69 	frustum.pNearLL = V3.transform(frustum.pNearLL, world);
 70 	frustum.pNearLR = V3.transform(frustum.pNearLR, world);
 71 	frustum.pFarUL = V3.transform(frustum.pFarUL, world);
 72 	frustum.pFarUR = V3.transform(frustum.pFarUR, world);
 73 	frustum.pFarLL = V3.transform(frustum.pFarLL, world);
 74 	frustum.pFarLR = V3.transform(frustum.pFarLR, world);
 75 	
 76 	// calculate planes
 77 	frustum.nearPlane = Frustum.calculatePlane(frustum.pNearLL, frustum.pNearUL, frustum.pNearLR);
 78 	frustum.farPlane = Frustum.calculatePlane(frustum.pFarLR, frustum.pFarUR, frustum.pFarLL);
 79 	frustum.leftPlane = Frustum.calculatePlane(frustum.pFarLL, frustum.pFarUL, frustum.pNearLL);
 80 	frustum.rightPlane = Frustum.calculatePlane(frustum.pNearLR, frustum.pNearUR, frustum.pFarLR);
 81 	frustum.topPlane = Frustum.calculatePlane(frustum.pNearUR, frustum.pNearUL, frustum.pFarUR);
 82 	frustum.bottomPlane = Frustum.calculatePlane(frustum.pNearLL, frustum.pNearLR, frustum.pFarLL);
 83 	frustum.planes = [frustum.nearPlane, frustum.farPlane, frustum.leftPlane, 
 84 	                  frustum.rightPlane, frustum.topPlane, frustum.bottomPlane];
 85 	
 86 	
 87 	return frustum;
 88 }
 89 
 90 /**
 91  * calculates a plane from 3 points.
 92  * 
 93  * <pre>
 94  *        p3 
 95  *       / \          normal
 96  *      /   \     .~�
 97  *     /     \.~� 
 98  *   p1     � \
 99  *      `.     \
100  *         `.   \ 
101  *            `  p2
102  *            </pre>
103  */
104 Frustum.calculatePlane = function(point1, point2, point3){
105 	var v1 = V3.direction(point1, point2);
106 	var v2 = V3.direction(point1, point3);
107 	var normal = V3.cross(v1, v2);
108 	var A = normal[0];
109 	var B = normal[1]; 
110 	var C = normal[2];
111 	var x = point1[0];
112 	var y = point1[1];
113 	var z = point1[2];
114 	var distance = -A*x - B*y - C*z;
115 	
116 	return new Plane(distance, normal);
117 }
118 
119 /** 
120  * check whether the aabb is completely outside the frustum or not
121  * 
122  * @param aabb
123  */
124 Frustum.prototype.isOutside = function isOutside(aabb){
125 	
126 	for(var i = 0; i < this.planes.length; i++){
127 		var plane = this.planes[i];
128 		
129 		// is the positive vertex outside?
130 		if (plane.distanceTo(aabb.getPositive(plane.normal)) < 0)
131 			return true;
132 //		// is the negative vertex outside?
133 //		else if (plane.distanceTo(b.getVertexN(pl[i].normal)) > 0)
134 //			result =  INTERSECT;
135 		
136 	}
137 	return false;
138 }