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  * Axis aligned bounding box
 16  * 
 17  * 
 18  * <pre>
 19  *    7----6        y
 20  *   /    /|        |
 21  *  4----5 |        |
 22  *  | 3--|-2        |______ x  
 23  *  |/   |/       .�
 24  *  0----1       �z
 25  * </pre>
 26  *
 27  * @see http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/
 28  */
 29 function AABB(){
 30 	this.points = 24;
 31 	this.color = [ 1.0, 0.0, 0.0, 1.0];
 32 	
 33 	// transformed minimum and maximum coordinates
 34 	this.min = V3.$(0,0,0);
 35 	this.max = V3.$(0,0,0);
 36 	this.center = null;
 37 	this.radius = null;
 38 	
 39 	this.vbo = null;
 40 	
 41 	this.transform = M4x4.I;
 42 	
 43 	// object space coordinates. of the bounding box. 
 44 	this.p0 = null;
 45 	this.p1 = null;
 46 	this.p2 = null;
 47 	this.p3 = null;
 48 	this.p4 = null;
 49 	this.p5 = null;
 50 	this.p6 = null;
 51 	this.p7 = null;
 52 	this.objectSpaceMin = V3.$(0,0,0);
 53 	this.objectSpaceMax = V3.$(0,0,0);
 54 }
 55 
 56 /**
 57  * set object space coordinates of this bounding box
 58  * 
 59  * @param p0
 60  * @param p1
 61  * @param p2
 62  * @param p3
 63  * @param p4
 64  * @param p5
 65  * @param p6
 66  * @param p7
 67  */
 68 AABB.prototype.setDimension = function(p0, p1, p2, p3, p4, p5, p6, p7) {
 69 	this.p0 = p0;
 70 	this.p1 = p1;
 71 	this.p2 = p2;
 72 	this.p3 = p3;
 73 	this.p4 = p4;
 74 	this.p5 = p5;
 75 	this.p6 = p6;
 76 	this.p7 = p7;
 77 	this.update();
 78 };
 79 
 80 /**
 81  * set object space coordinates by providing the minimum and the maximum vertex of the aabb.
 82  * 
 83  * @param min
 84  * @param max
 85  */
 86 AABB.prototype.setDimensionByMinMax = function(min, max){
 87 	this.p0 = [min[0], min[1], max[2]];
 88 	this.p1 = [max[0], min[1], max[2]];
 89 	this.p2 = [max[0], min[1], min[2]];
 90 	this.p3 = [min[0], min[1], min[2]];
 91 	this.p4 = [min[0], max[1], max[2]];
 92 	this.p5 = [max[0], max[1], max[2]];
 93 	this.p6 = [max[0], max[1], min[2]];
 94 	this.p7 = [min[0], max[1], min[2]];
 95 	this.update();
 96 };
 97 
 98 /**
 99  * transforms the aabb from object space. 
100  * 
101  * @param transform
102  */
103 AABB.prototype.setTransform = function(transform){
104 	this.transform = transform;
105 	
106 	this.update();
107 };
108 
109 
110 AABB.tmpVec = V3.$(0,0,0);
111 /**
112  * calculates min, max, center and radius of the transformed AABB. p0 to p7 will be kept in object space.
113  */
114 AABB.prototype.update = function update(){
115 	
116 	// calculate the minimum of the box
117 	this.objectSpaceMin[0] = Math.min(this.p0[0], this.p1[0], this.p2[0], this.p3[0], this.p4[0], this.p5[0], this.p6[0], this.p7[0]);
118 	this.objectSpaceMin[1] = Math.min(this.p0[1], this.p1[1], this.p2[1], this.p3[1], this.p4[1], this.p5[1], this.p6[1], this.p7[1]);
119 	this.objectSpaceMin[2] = Math.min(this.p0[2], this.p1[2], this.p2[2], this.p3[2], this.p4[2], this.p5[2], this.p6[2], this.p7[2]);
120 	
121 	// calculate maximum of the box
122 	this.objectSpaceMax[0] = Math.max(this.p0[0], this.p1[0], this.p2[0], this.p3[0], this.p4[0], this.p5[0], this.p6[0], this.p7[0]);
123 	this.objectSpaceMax[1] = Math.max(this.p0[1], this.p1[1], this.p2[1], this.p3[1], this.p4[1], this.p5[1], this.p6[1], this.p7[1]);
124 	this.objectSpaceMax[2] = Math.max(this.p0[2], this.p1[2], this.p2[2], this.p3[2], this.p4[2], this.p5[2], this.p6[2], this.p7[2]);
125 	
126 	// calculate transformed box coordinates
127 	var p0 = V3.transform(this.p0, this.transform);
128 	var p1 = V3.transform(this.p1, this.transform);
129 	var p2 = V3.transform(this.p2, this.transform);
130 	var p3 = V3.transform(this.p3, this.transform);
131 	var p4 = V3.transform(this.p4, this.transform);
132 	var p5 = V3.transform(this.p5, this.transform);
133 	var p6 = V3.transform(this.p6, this.transform);
134 	var p7 = V3.transform(this.p7, this.transform);
135 	
136 	// calculate the minimum of the transformed box
137 	this.min[0] = Math.min(p0[0], p1[0], p2[0], p3[0], p4[0], p5[0], p6[0], p7[0]);
138 	this.min[1] = Math.min(p0[1], p1[1], p2[1], p3[1], p4[1], p5[1], p6[1], p7[1]);
139 	this.min[2] = Math.min(p0[2], p1[2], p2[2], p3[2], p4[2], p5[2], p6[2], p7[2]);
140 	
141 	// calculate maximum of the transformed box
142 	this.max[0] = Math.max(p0[0], p1[0], p2[0], p3[0], p4[0], p5[0], p6[0], p7[0]);
143 	this.max[1] = Math.max(p0[1], p1[1], p2[1], p3[1], p4[1], p5[1], p6[1], p7[1]);
144 	this.max[2] = Math.max(p0[2], p1[2], p2[2], p3[2], p4[2], p5[2], p6[2], p7[2]);
145 	
146 	// center
147 	this.center = V3.add(this.min, this.max);
148 	this.center = V3.scale(this.center, 0.5);
149 	
150 	// radius
151 	V3.sub(this.max, this.min, AABB.tmpVec);
152 	this.radius = V3.length(AABB.tmpVec) / 2.0;
153 };
154 
155 
156 /**
157  * returns the distance from minPos to maxPos in projected space
158  */
159 AABB.prototype.getOnScreenSize = function(sceneNode, camera){
160 	var world = sceneNode.globalTransformation;
161 	var view = camera.viewMatrix;
162 	var proj = camera.projectionMatrix;
163 	
164 	var worldViewProj = M4x4.mul(proj, M4x4.mul(view, world));
165 	var min = V3.transform(this.min, worldViewProj);
166 	var max = V3.transform(this.max, worldViewProj);
167 	var diff = V3.sub(min, max);
168 	var length = V3.length(diff);
169 	
170 	return length;
171 	
172 };
173 
174 /**
175  * 
176  * @param {[r,g,b,a]} color each value must be between 0 and 1
177  */
178 AABB.prototype.setColor = function(color){
179 	this.color = color;
180 };
181 
182 AABB.prototype.render = function(sceneNode, camera){
183 	this.material.setColor(this.color);
184 	this.material.render(this, sceneNode, camera);
185 };
186 
187 /**
188  * returns the positive coordinate of the transformed bounding box. 
189  * 
190  * @see http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/
191  * @param normal
192  */
193 AABB.prototype.getPositive = function getPositive(normal){
194 	var min = this.min;
195 	var max = this.max;
196 	var p = [min[0], min[1], min[2]];
197 	if (normal[0] >= 0){
198 		p[0] = max[0];
199 	}
200 	if (normal[1] >=0){
201 		p[1] = max[1];
202 	}
203 	if (normal[2] >= 0){
204 		p[2] = max[2];
205 	}
206 	
207 	return p;
208 };
209 
210 /**
211  * returns the negative coordinate of the transformed bounding box. 
212  * 
213  * @see http://www.lighthouse3d.com/tutorials/view-frustum-culling/geometric-approach-testing-boxes-ii/
214  * @param normal
215  */
216 AABB.prototype.getNegative = function(normal){
217 	var min = this.min;
218 	var max = this.max;;
219 	var p = [max[0], max[1], max[2]];
220 	if (normal[0] >= 0){
221 		p[0] = min[0];
222 	}
223 	if (normal[1] >=0){
224 		p[1] = min[1];
225 	}
226 	if (normal[2] >= 0){
227 		p[2] = min[2];
228 	}
229 	
230 	return p;
231 };
232