View Javadoc

1   /* -------------------------------------------------------------------
2    * Java source file for the class QuadSurfaceModeler
3    * 
4    * Copyright (c), 2003, Masahiro Takatsuka.
5    * All Rights Researved.
6    * 
7    * Original Author: Masahiro Takatsuka (masa@jbeans.net)
8    * $Author: takatsukam $
9    * 
10   * $Date: 2004/03/03 11:53:05 $
11   * 
12   * $Id: QuadSurfaceModeler.java,v 1.3 2004/03/03 11:53:05 takatsukam Exp $
13   * 
14   * Reference:		Document no:
15   * ___				___
16   * 
17   * To Do:
18   * ___
19   * 
20  ------------------------------------------------------------------- */
21  
22  /* --------------------------- Package ---------------------------- */
23  package net.jbeans.j3d.modeler.geometry;
24  
25  /* ------------------ Import classes (packages) ------------------- *//package-summary/html">class="comment"> ------------------ Import classes (packages) ------------------- *//package-summary.html">class="comment">/* ------------------ Import classes (packages) ------------------- *//package-summary.html">class="comment"> ------------------ Import classes (packages) ------------------- */
26  import java.awt.*;
27  import java.awt.event.*;
28  import java.io.*;
29  import java.lang.reflect.*;
30  import java.util.*;
31  import javax.media.j3d.*;
32  import javax.vecmath.*;
33  import com.sun.j3d.utils.geometry.*;
34  
35  import net.jbeans.util.debug.*;
36  
37  /*====================================================================
38                Implementation of class QuadSurfaceModeler              
39  ====================================================================*/
40  /***
41   * QuadSurfaceModeler generates a suface geometry from the specified data.
42   * 
43   * @version $Revision: 1.3 $
44   * @author Masahiro Takatsuka (masa@jbeans.net)
45   * @see QuadModeler
46   */
47  
48  public class QuadSurfaceModeler extends QuadModeler {
49  	private static final boolean DEBUG = Debug.getDebugFlag(QuadSurfaceModeler.class);
50  	/* ------------------------ not serialized ------------------------ */
51  	transient private int xSize;
52  	transient private int ySize;
53  	transient private int xQSize;
54  	transient private int yQSize;
55  	transient private int[] indices;
56  	transient private boolean useQuadModeler = false;
57  	
58  	/* -------------------------- serialized -------------------------- */
59  	private double voidValue = Double.NaN;
60  	private boolean blanking = false;
61  	
62  	public QuadSurfaceModeler() {
63  		super();
64  	}
65  
66  	public void setBlanking(boolean b) {
67  		this.blanking = b;
68  	}
69  
70  	public boolean getBlanking() {
71  		return this.blanking;
72  	}
73  
74  	public void setVoidValue(double voidvalue) {
75  		this.voidValue = voidvalue;
76  	}
77  
78  	public double getVoidValue() {
79  		return this.voidValue;
80  	}
81  
82  	public void setXSize(int x) {
83  		this.xSize = x;
84  	}
85  
86  	public int getXSize() {
87  		return this.xSize;
88  	}
89  	
90  	public void setYSize(int y) {
91  		this.ySize = y;
92  	}
93  
94  	public int getYSize() {
95  		return this.ySize;
96  	}
97  	
98  	protected boolean checkSize() {
99  		if (this.xSize < 2 || this.ySize < 2) {
100 			return false;
101 		}
102 		return super.checkSize();
103 	}
104 
105 	protected boolean needsModel() {
106 		boolean ret = super.needsModel();
107 		double[] x = (double[]) this.entryArray[XC];
108 		
109 		ret = (ret || (this.xSize * this.ySize != x.length) ||
110 			   (this.xSize != (this.xQSize + 1)) ||
111 			   (this.ySize != (this.yQSize + 1)));
112 		
113 		if (ret || this.blanking) {
114 			ret = true;
115 			computeIndices();
116 		}
117 		return ret;
118 	}
119 
120 	private void computeIndices() {
121 		this.xQSize = this.xSize - 1;
122 		this.yQSize = this.ySize - 1;		
123 		int numQuads = this.xQSize * this.yQSize;
124 		int totalPoints = numQuads * 4;
125 		this.indices = new int[totalPoints];
126 		int tmpidx;
127 		int v0, v1, v2, v3;
128 		double[] z = (double[]) this.entryArray[ZC];
129 		int k = 0;
130 		for (int i = 0; i < this.yQSize; i++) {
131 			for (int j = 0; j < this.xQSize; j++) {
132 				tmpidx = k * 4;
133 				v0 = i * this.xSize + j;
134 				v1 = v0 + 1;
135 				v2 = (i + 1) * this.xSize + (j + 1);
136 				v3 = v2 - 1;
137 				if (this.blanking &&
138 					(z[v0] == this.voidValue ||
139 					 z[v1] == this.voidValue ||
140 					 z[v2] == this.voidValue ||
141 					 z[v3] == this.voidValue)) {
142 					this.useQuadModeler = true;
143 					continue;
144 				}
145 				this.indices[tmpidx    ] = v0;
146 				this.indices[tmpidx + 1] = v1;
147 				this.indices[tmpidx + 2] = v2;
148 				this.indices[tmpidx + 3] = v3;
149 				k++;
150 			}
151 		}
152 		if ((k * 4) < totalPoints) {
153 			int[] tmpIndices = new int[k * 4];
154 			System.arraycopy(this.indices, 0, tmpIndices, 0, tmpIndices.length);
155 			this.indices = tmpIndices;
156 		}
157 	}
158 	
159 	protected synchronized void setData() {
160 		double[] color = (double[]) this.entryArray[CC];
161 		double[][] normal = (double[][]) this.entryArray[NC];
162 		double[][] tCoord = (double[][]) this.entryArray[TC];				
163 		
164 		setCoordinateIndices(this.indices);
165 		
166 		if (color != null) {
167 			setColorIndices(this.indices);
168 		}
169 		
170 		if (normal != null) {
171 			setNormalIndices(this.indices);
172 		}
173 		
174 		if (tCoord != null) {
175 			setTextureCoordinateIndices(this.indices);
176 		}
177 		super.setData();
178 	}
179 
180 	/*
181 	* uncomment the calculateNormals and modelGeometry method in order to
182 	* create geometry without the help of GeometryInfo.
183 	* Masahiro Takatsuka/2002-Feb-06
184 	*/
185 	private void calculateNormals() {
186 		if (DEBUG) {
187 			System.out.println("computing normals.");
188 		}
189         int i = this.coords3f.length;
190         int j = this.indices.length / 4;
191 
192 		if (this.normals3f == null || this.normals3f.length != i) {
193             this.normals3f = new Vector3f[i];
194             for (int k = 0; k < i; k++) {
195                 this.normals3f[k] = new Vector3f();
196 			}
197         } else {
198             for (int l = 0; l < i; l++) {
199                 this.normals3f[l].set(0.0f, 0.0f, 0.0f);
200 			}
201         }
202         for (int i1 = 0; i1 < j; i1++) {
203 			Vector3f vector3f = null;
204 			Point3f p1 = this.coords3f[this.indices[i1 * 4]];
205 			Point3f p2 = this.coords3f[this.indices[i1 * 4 + 1]];
206 			Point3f p3 = this.coords3f[this.indices[i1 * 4 + 2]];
207 
208 			if (!this.blanking ||
209 				(p1.z != this.voidValue &&
210 				 p2.z != this.voidValue &&
211 				 p3.z != this.voidValue)) {
212 				vector3f = SurfaceModeler.geomCalcTriNormals(p1, p2, p3);
213 				for (int k1 = 0; k1 < 3; k1++) {
214 					this.normals3f[this.indices[i1 * 4 + k1]].add(vector3f);
215 				}
216 			}
217 			p2 = p3;
218 			p3 = this.coords3f[this.indices[i1 * 4 + 3]];
219 			if (!this.blanking ||
220 				(p1.z != this.voidValue &&
221 				 p2.z != this.voidValue &&
222 				p3.z != this.voidValue)) {
223 				vector3f = SurfaceModeler.geomCalcTriNormals(p1, p2, p3);
224 				for (int k1 = 0; k1 < 4; k1++) {
225 					if (k1 == 1) {
226 						continue;
227 					}
228 					this.normals3f[this.indices[i1 * 4 + k1]].add(vector3f);
229 				}
230 			}
231         }
232 		
233         for (int j1 = 0; j1 < i; j1++) {
234 			if (this.normals3f[j1].length() != 0) {
235 				this.normals3f[j1].normalize();
236 			}
237 			if (DEBUG) {
238 				System.out.println("normals3f = " + this.normals3f[j1]);
239 			}
240 		}
241     }
242 
243 	/***
244 	 * Construct a javax.media.j3d.GeometryArray object from quad data.
245 	 */
246 // 	protected void modelGeometry() {
247 // 		int size = this.x.length;
248 // 		this.coords3f = new Point3f[size];
249 // 		int format = GeometryArray.BY_REFERENCE | GeometryArray.COORDINATES | GeometryArray.NORMALS;
250 // 		if (this.color != null) {
251 // 			this.hasColors = true;
252 // 			if (this.alpha != null) {
253 // 				format |= GeometryArray.COLOR_4;
254 // 				this.colors4f = new Color4f[size];
255 // 				this.colors3f = null;
256 // 			} else {
257 // 				format |= GeometryArray.COLOR_3;
258 // 				this.colors4f = null;
259 // 				this.colors3f = new Color3f[size];
260 // 			}
261 // 		}
262 // 		if (this.tCoords != null) {
263 // 			this.hasTCoords = true;
264 // 			if (this.tCoords[0].length == 2) {
265 // 				format |= GeometryArray.TEXTURE_COORDINATE_2;
266 // 				this.texCoords2f = new TexCoord2f[size];
267 // 				this.texCoords3f = null;
268 // 			} else {
269 // 				format |= GeometryArray.TEXTURE_COORDINATE_3;
270 // 				this.texCoords2f = null;
271 // 				this.texCoords3f = new TexCoord3f[size];
272 // 			}
273 // 		}
274 
275 // 		IndexedQuadArray geom = new IndexedQuadArray(size, format, this.indices.length);
276 // 		if (DEBUG) {
277 // 			System.out.println("size = " + size);
278 // 			System.out.println("length = " + this.indices.length);
279 // 		}
280 // 		for (int i = 0; i < size; i++) {
281 // 			this.coords3f[i] = new Point3f((float) this.x[i], (float) this.y[i], (float) this.z[i]);
282 // 			if (DEBUG) {
283 // 				System.out.println("coords3f = " + this.coords3f[i]);
284 // 			}
285 // 			//System.out.print("\rPoint3f = " + this.coords3f[i]);
286 // 			if (this.hasColors) {
287 // 				double[] tmp = this.lookupTable.mapValue(this.color[i]);
288 // 				if (this.colors3f != null) {
289 // 					this.colors3f[i] = new Color3f((float) tmp[0], (float) tmp[1], (float) tmp[2]);
290 // 				} else {
291 // 					this.colors4f[i] = new Color4f((float) tmp[0], (float) tmp[1], (float) tmp[2], (float) this.alpha[i]);
292 // 				}
293 // 			}
294 // 			if (this.hasTCoords) {
295 // 				if (this.texCoords2f != null) {
296 // 					this.texCoords2f[i] = new TexCoord2f((float) this.tCoords[i][0], (float) this.tCoords[i][1]);
297 // 				} else {
298 // 					this.texCoords3f[i] = new TexCoord3f((float) this.tCoords[i][0], (float) this.tCoords[i][1], (float) this.tCoords[i][2]);
299 // 				}
300 // 			}
301 // 		}
302 // 		System.out.print("computing normals...");
303 // 		calculateNormals();
304 // 		System.out.println("\rcomputing normals...finished");
305 
306 // 		geom.setCoordRef3f(this.coords3f);
307 // 		geom.setCoordinateIndices(0, this.indices);
308 //  		geom.setNormalRef3f(this.normals3f);
309 //   		geom.setNormalIndices(0, this.indices);
310 // 		if (this.hasColors) {
311 // 			if (this.colors3f != null) {
312 // 				geom.setColorRef3f(this.colors3f);
313 // 			} else {
314 // 				geom.setColorRef4f(this.colors4f);
315 // 			}
316 // 			geom.setColorIndices(0, this.indices);
317 // 		}
318 // 		if (this.hasTCoords) {
319 // 			if (this.texCoords2f != null) {
320 // 				geom.setTexCoordRef2f(0, this.texCoords2f);
321 // 			} else {
322 // 				geom.setTexCoordRef3f(0, this.texCoords3f);
323 // 			}
324 // 			geom.setTextureCoordinateIndices(0, 0, this.indices);
325 // 		}
326 
327 // 		// register this new geometry.
328 // 		setGeometry(geom);
329 // 	}
330 
331 	protected void modelGeometry() {
332 		if (this.useQuadModeler) {
333 			useQuadModeler();
334 		}
335 		super.modelGeometry();
336 	}
337 
338 	protected void setupStripCounts() {
339 		int quadNum = this.indices.length / 4;
340 		int[] stripcounts = new int[quadNum];
341 		for (int i = 0; i < quadNum; i++) {
342 			stripcounts[i] = 4;
343 		}
344 		setStripCounts(stripcounts);
345 	}
346 	
347 	private void useQuadModeler() {
348 		// reset this.{x,y,z,...}.
349 		int verticesNum = this.indices.length;
350 		
351 		double[] x = new double[verticesNum];
352 		double[] y = new double[verticesNum];
353 		double[] z = new double[verticesNum];
354 		double[] color = null;
355 		double[] alpha = null;
356 		double[][] normal = null;
357 		double[][] tCoords = null;
358 		
359 		if (this.color != null) {
360 			color = new double[verticesNum];
361 		}
362 
363 		if (this.alpha != null) {
364 			alpha = new double[verticesNum];
365 		}
366 		
367 		if (this.normal != null) {
368 			normal = new double[verticesNum][];
369 		}
370 		
371 		if (this.tCoords != null) {
372 			tCoords = new double[verticesNum][];
373 		}
374 
375 		for (int i = 0; i < verticesNum; i++) {
376 			int idx = this.indices[i];
377 			x[i] = this.x[idx];
378 			y[i] = this.y[idx];
379 			z[i] = this.z[idx];
380 			if (DEBUG) {
381 				System.out.println("QSM: x, y, z, c = " + x[i] + ", " +  y[i] + ", " +  z[i]);
382 			}
383 			
384 			if (this.color != null) {
385 				color[i] = this.color[idx];
386 			}
387 			
388 			if (this.alpha != null) {
389 				alpha[i] = this.alpha[idx];
390 			}
391 			
392 			if (this.normal != null) {
393 				normal[i] = this.normal[idx];
394 			}
395 		
396 			if (this.tCoords != null) {
397 				tCoords[i] = this.tCoords[idx];
398 			}
399 		}
400 		this.x = x;
401 		this.y = y;
402 		this.z = z;
403 		if (this.color != null) {
404 			this.color = color;
405 		}
406 		if (this.alpha != null) {
407 			this.alpha = alpha;
408 		}
409 		if (this.normal != null) {
410 			this.normal = normal;
411 		}
412 		if (this.tCoords != null) {
413 			this.tCoords = tCoords;
414 		}
415 		this.coordinateIndices = null;
416 		this.colorIndices = null;
417 		this.normalIndices = null;
418 		this.texCoordIndices = null;
419 	}
420 	
421 	public void test() {
422 		double[] x = {441060.0, 441061.0, 441062.0, 441063.0, 441061.0, 441062.0, 441063.0, 441064.0, 441062.0, 441063.0, 441064.0, 441065.0, 441063.0, 441064.0, 441065.0, 441066.0, 441064.0, 441065.0, 441066.0, 441067.0};
423 		double[] y = {561370.0, 561370.0, 561370.0, 561370.0, 561371.0, 561371.0, 561371.0, 561371.0, 561372.0, 561372.0, 561372.0, 561372.0, 561373.0, 561373.0, 561373.0, 561373.0, 561374.0, 561374.0, 561374.0, 561374.0};
424 		double[] z = {0.0, 0.0, 0.0, 0.0, 1.0, 1.0, 1.0, 1.0, 2.0, 2.0, 3.0, 3.0, 4.0, 4.0, 4.0, 4.0, 5.0, 5.0, 5.0, 5.0};
425 		double[] color = {0.0, 0.2, 0.4, 0.6, 0.8, 0.8, 0.8, 0.0, 0.2, 0.4, 0.6, 0.8, 0.8, 0.8, 1.0, 1.0, 0.3, 0.3, 0.3, 0.3};
426 
427 		setBlanking(true);
428 		setVoidValue(3.0);
429 		setXSize(4);
430 		setYSize(5);
431 		setColors(color);
432 		setXCoordinates(x);
433 		setYCoordinates(y);
434 		setZCoordinates(z);
435 	}
436 }
437