1 /**
  2  * @fileOverview Plugins for tQuery.Geometry: tool box to play with geometry
  3 */
  4 
  5 (function(){	// TODO why is there a closure here ?
  6 
  7 //////////////////////////////////////////////////////////////////////////////////
  8 //		Size functions							//
  9 //////////////////////////////////////////////////////////////////////////////////
 10 
 11 tQuery.Geometry.registerInstance('computeAll', function(){
 12 	this.each(function(tGeometry){
 13 		tGeometry.computeBoundingBox();
 14 		//tGeometry.computeCentroids();
 15 		tGeometry.computeFaceNormals();
 16 		//tGeometry.computeVertexNormals();
 17 		//tGeometry.computeTangents();
 18 	});
 19 
 20 	// return this, to get chained API	
 21 	return this;
 22 });
 23 
 24 /**
 25  * zoom a geometry
 26  *
 27  * @name zoom
 28  * @methodOf tQuery.Geometry
 29 */
 30 tQuery.Geometry.registerInstance('scaleBy', function(vector3){
 31 	// handle parameters
 32 	if( typeof vector3 === "number" && arguments.length === 1 ){
 33 		vector3	= new THREE.Vector3(vector3, vector3, vector3);
 34 	}else if( typeof vector3 === "number" && arguments.length === 3 ){
 35 		vector3	= new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
 36 	}
 37 	console.assert(vector3 instanceof THREE.Vector3, "Geometry.vector3 parameter error");
 38 
 39 	// change all geometry.vertices
 40 	this.each(function(geometry){
 41 		for(var i = 0; i < geometry.vertices.length; i++) {
 42 			var vertex	= geometry.vertices[i];
 43 			vertex.multiplySelf(vector3); 
 44 		}
 45 		// mark the vertices as dirty
 46 		geometry.verticesNeedUpdate = true;
 47 		geometry.computeBoundingBox();
 48 	})
 49 
 50 	// return this, to get chained API	
 51 	return this;
 52 });
 53 
 54 tQuery.Geometry.registerInstance('size', function(){
 55 	// only on zero-or-one element
 56 	console.assert(this.length <= 1)
 57 	// if no element, return undefined
 58 	if( this.length === 0 )	return undefined
 59 
 60 	// else measure the size of the element
 61 	var geometry	= this.get(0);
 62 	// compute middle
 63 	var size= new THREE.Vector3()
 64 	size.x	= geometry.boundingBox.max.x - geometry.boundingBox.min.x;
 65 	size.y	= geometry.boundingBox.max.y - geometry.boundingBox.min.y;
 66 	size.z	= geometry.boundingBox.max.z - geometry.boundingBox.min.z;
 67 
 68 	// return the just computed middle
 69 	return size;	
 70 });
 71 
 72 /**
 73 */
 74 tQuery.Geometry.registerInstance('normalize', function(){
 75 	// change all geometry.vertices
 76 	this.each(function(geometry){
 77 		var node	= tQuery(geometry);
 78 		var size	= node.size();
 79 		if( size.x >= size.y && size.x >= size.z ){
 80 			node.zoom(1/size.x);
 81 		}else if( size.y >= size.x && size.y >= size.z ){
 82 			node.zoom(1/size.y);
 83 		}else{
 84 			node.zoom(1/size.z);
 85 		}
 86 	});
 87 	// return this, to get chained API	
 88 	return this;
 89 });
 90 
 91 
 92 //////////////////////////////////////////////////////////////////////////////////
 93 //										//
 94 //////////////////////////////////////////////////////////////////////////////////
 95 
 96 
 97 tQuery.Geometry.registerInstance('middlePoint', function(){
 98 	// only on zero-or-one element
 99 	console.assert(this.length <= 1)
100 	// if no element, return undegined
101 	if( this.length === 0 )	return undefined
102 	// else measure the size of the element
103 	var geometry	= this.get(0);
104 	// compute middle
105 	var middle	= new THREE.Vector3()
106 	middle.x	= ( geometry.boundingBox.max.x + geometry.boundingBox.min.x ) / 2;
107 	middle.y	= ( geometry.boundingBox.max.y + geometry.boundingBox.min.y ) / 2;
108 	middle.z	= ( geometry.boundingBox.max.z + geometry.boundingBox.min.z ) / 2;
109 
110 	// return the just computed middle
111 	return middle;
112 });
113 
114 //////////////////////////////////////////////////////////////////////////////////
115 //		move functions							//
116 //////////////////////////////////////////////////////////////////////////////////
117 
118 tQuery.Geometry.registerInstance('translate', function(delta){
119 	// handle parameters
120 	if( typeof delta === "number" && arguments.length === 3 ){
121 		delta	= new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
122 	}
123 	console.assert(delta instanceof THREE.Vector3, "Geometry.translate parameter error");
124 
125 	// change all geometry.vertices
126 	this.each(function(geometry){
127 		// change all geometry.vertices
128 		for(var i = 0; i < geometry.vertices.length; i++) {
129 			var vertex	= geometry.vertices[i];
130 			vertex.addSelf(delta); 
131 		}
132 		// mark the vertices as dirty
133 		geometry.verticesNeedUpdate = true;
134 		geometry.computeBoundingBox();
135 	})
136 
137 	// return this, to get chained API	
138 	return this;
139 });
140 
141 tQuery.Geometry.registerInstance('rotate', function(angles, order){
142 	// handle parameters
143 	if( typeof angles === "number" && arguments.length === 3 ){
144 		angles	= new THREE.Vector3(arguments[0], arguments[1], arguments[2]);
145 	}
146 	console.assert(angles instanceof THREE.Vector3, "Geometry.rotate parameter error");
147 
148 	// set default rotation order if needed
149 	order	= order	|| 'XYZ';
150 	// compute transformation matrix
151 	var matrix	= new THREE.Matrix4();
152 	matrix.setRotationFromEuler(angles, order);
153 
154 	// change all geometry.vertices
155 	this.each(function(geometry){
156 		// apply the matrix
157 		geometry.applyMatrix( matrix );
158 	
159 		// mark the vertices as dirty
160 		geometry.verticesNeedUpdate = true;
161 		geometry.computeBoundingBox();
162 	});
163 
164 	// return this, to get chained API	
165 	return this;
166 });
167 
168 /**
169 */
170 tQuery.Geometry.registerInstance('center', function(noX, noY, noZ){
171 	// change all geometry.vertices
172 	this.each(function(tGeometry){
173 		var geometry	= tQuery(tGeometry);
174 		// compute delta
175 		var delta 	= geometry.middlePoint().negate();
176 		if( noX )	delta.x	= 0;
177 		if( noY )	delta.y	= 0;
178 		if( noZ )	delta.z	= 0;
179 
180 		return geometry.translate(delta)
181 	});
182 	// return this, to get chained API	
183 	return this;
184 });
185 
186 /**
187  * Smooth the geometry using catmull-clark
188  *
189  * @param {Number} subdivision the number of subdivision to do
190 */
191 tQuery.Geometry.registerInstance('smooth', function(subdivision){
192 	// init the modifier
193 	var modifier	= new THREE.SubdivisionModifier( subdivision );
194 	// apply it to each geometry
195 	this.each(function(geometry){
196 		// apply it
197 		modifier.modify( geometry )
198 	
199 		// mark the vertices as dirty
200 		geometry.verticesNeedUpdate = true;
201 		geometry.computeBoundingBox();
202 	});
203 	// return this, to get chained API	
204 	return this;
205 });
206 
207 // some shortcuts
208 tQuery.Geometry.registerInstance('translateX'	, function(delta){ return this.translate(delta, 0, 0);	});
209 tQuery.Geometry.registerInstance('translateY'	, function(delta){ return this.translate(0, delta, 0);	});
210 tQuery.Geometry.registerInstance('translateZ'	, function(delta){ return this.translate(0, 0, delta);	});
211 tQuery.Geometry.registerInstance('rotateX'	, function(angle){ return this.rotate(angle, 0, 0);	});
212 tQuery.Geometry.registerInstance('rotateY'	, function(angle){ return this.rotate(0, angle, 0);	});
213 tQuery.Geometry.registerInstance('rotateZ'	, function(angle){ return this.rotate(0, 0, angle);	});
214 tQuery.Geometry.registerInstance('scaleXBy'	, function(ratio){ return this.scaleBy(ratio, 1, 1);	});
215 tQuery.Geometry.registerInstance('scaleYBy'	, function(ratio){ return this.scaleBy(1, ratio, 1);	});
216 tQuery.Geometry.registerInstance('scaleZBy'	, function(ratio){ return this.scaleBy(1, 1, ratio);	});
217 
218 // backward compatibility
219 tQuery.Geometry.registerInstance('zoom'		, function(value){return this.scaleBy(value);		});
220 tQuery.Geometry.registerInstance('zoomX'	, function(ratio){ return this.zoom(ratio, 1, 1);	});
221 tQuery.Geometry.registerInstance('zoomY'	, function(ratio){ return this.zoom(1, ratio, 1);	});
222 tQuery.Geometry.registerInstance('zoomZ'	, function(ratio){ return this.zoom(1, 1, ratio);	});
223 
224 
225 })();	// closure function end
226