View Javadoc

1   /* -------------------------------------------------------------------
2    * Java source file for the class NormalModeler
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: NormalModeler.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 javax.media.j3d.*;
27  import javax.vecmath.*;
28  
29  import net.jbeans.util.debug.*;
30  
31  /*====================================================================
32                  Implementation of class NormalModeler                 
33  ====================================================================*/
34  /***
35   * NormalModeler generates a set of surface normals from a specified
36   * Geometry object.
37   * 
38   * @version $Revision: 1.3 $
39   * @author Masahiro Takatsuka (masa@jbeans.net)
40   * @see GeometryModeler
41   */
42  
43  public class NormalModeler extends GeometryModeler {
44  	private static final boolean DEBUG = Debug.getDebugFlag(NormalModeler.class);
45  
46  	public static final int UPDATE_ALWAYS = 0;
47  	public static final int UPDATE_ONCE = 1;
48  	
49  	/* ------------------------ not serialized ------------------------ */
50  	transient private GeometryArray sourceGeom;
51  	transient private boolean reset = true;
52  	transient private Point3f[] nvertices;
53  	
54  	/* -------------------------- serialized -------------------------- */
55  	private float scale;
56  	private int updateMode = UPDATE_ALWAYS;
57  
58  	public NormalModeler() {
59  		super();
60  		this.scale = 1.0f;
61  	}
62  
63  	public NormalModeler(float scale) {
64  		this();
65  		setScale(scale);
66  	}
67  
68  	public void setUpdateMode(int mode) {
69  		switch (mode) {
70  		case UPDATE_ALWAYS:
71  		default:
72  			mode = UPDATE_ALWAYS;
73  			break;
74  		case UPDATE_ONCE:
75  			break;
76  		}
77  		this.updateMode = mode;
78  	}
79  
80  	public int getUpdateMode() {
81  		return this.updateMode;
82  	}
83  	
84  	public void setScale(float scale) {
85  		this.scale = scale;
86  	}
87  
88  	public float getScale() {
89  		return this.scale;
90  	}
91  
92  	public void setGeometryArray(Geometry geometry) {
93  		if (! (geometry instanceof GeometryArray)) {
94  			return;
95  		}
96  		GeometryArray geom = (GeometryArray) geometry;
97  			
98  		if (geom != this.sourceGeom || this.updateMode == UPDATE_ALWAYS) {
99  			this.sourceGeom = geom;
100 			this.reset = true;
101 			model();
102 		} else {
103 			update();
104 		}
105 	}
106 
107 	protected void modelGeometry() {
108 		GeometryArray geom;
109 		if (this.sourceGeom instanceof IndexedGeometryArray) {
110 			renderForIndexedGeometryArray((IndexedGeometryArray) this.sourceGeom, this.scale);
111 		} else {
112 			renderForGeometryArray(this.sourceGeom, this.scale);
113 		}
114 		
115 		geom = new LineArray(this.nvertices.length,
116 							 GeometryArray.COORDINATES
117 							 | GeometryArray.BY_REFERENCE);
118 		setCapabilities(geom);
119 		//geom.setCoordinates(0, this.nvertices);
120 		geom.setCoordRef3f(this.nvertices);
121 
122 		// register this new geometry.
123 		setGeometry(geom);
124 	}		
125 
126 	public void updateData(Geometry geom) {
127 		int lineCount = getNumberOfNormals(this.sourceGeom) * 2;
128 
129 		if (lineCount != this.nvertices.length) {
130 			this.reset = true;
131 		} else {
132 			this.reset = false;
133 		}
134 		if (this.sourceGeom instanceof IndexedGeometryArray) {
135 			renderForIndexedGeometryArray((IndexedGeometryArray) this.sourceGeom, this.scale);
136 		} else {
137 			renderForGeometryArray(this.sourceGeom, this.scale);
138 		}
139 		if (this.reset) {
140 			((GeometryArray) geom).setCoordRef3f(this.nvertices);
141 		}
142 	}
143 
144 	private int getNumberOfNormals(GeometryArray geom) {
145 		if (geom instanceof IndexedGeometryArray) {
146 			return ((IndexedGeometryArray) geom).getIndexCount();
147 		}
148 		return geom.getVertexCount();
149 	}
150 	
151 	private Point3f[] renderForIndexedGeometryArray(IndexedGeometryArray geom, float scale) {
152 		Point3f[] vertices;
153 		Vector3f[] normals;
154 		if ((geom.getVertexFormat() & GeometryArray.BY_REFERENCE) != GeometryArray.BY_REFERENCE) {
155 			vertices = new Point3f[geom.getVertexCount()];
156 			normals = new Vector3f[geom.getVertexCount()];
157 			
158 			for (int i = 0; i < geom.getVertexCount(); i++) {
159 				vertices[i] = new Point3f();
160 				normals[i] = new Vector3f();
161 			}		
162 			geom.getCoordinates(0, vertices);
163 			geom.getNormals(0, normals);
164 		} else {
165 			vertices = geom.getCoordRef3f();
166 			normals = geom.getNormalRef3f();
167 		}
168 		if (DEBUG) {
169 			System.out.println("vnum = " + vertices.length);
170 			System.out.println("nnum = " + normals.length);
171 		}
172 		int size = geom.getIndexCount();
173 		int[] coords = new int[size];
174 		int[] normls = new int[size];
175 		if (this.reset) {
176 			this.nvertices = new Point3f[size * 2];
177 		}
178 		geom.getCoordinateIndices(0, coords);
179 		geom.getNormalIndices(0, normls);		
180 		int n = 0;
181 		for (int i = 0; i < size; i++ ) {
182 			this.nvertices[n++] = new Point3f(vertices[coords[i]]);
183 			this.nvertices[n++] = new Point3f(vertices[coords[i]].x +
184 										 scale * normals[normls[i]].x,
185 										 vertices[coords[i]].y +
186 										 scale * normals[normls[i]].y,
187 										 vertices[coords[i]].z +
188 										 scale * normals[normls[i]].z);
189 		}
190 		return this.nvertices;		
191 	}
192 
193 	private Point3f[] renderForGeometryArray(GeometryArray geom, float scale) {
194 		Point3f[] vertices;
195 		Vector3f[] normals;
196 		
197 		if ((geom.getVertexFormat() & GeometryArray.BY_REFERENCE) != GeometryArray.BY_REFERENCE) {
198 			vertices = new Point3f[geom.getVertexCount()];
199 			normals = new Vector3f[geom.getVertexCount()];
200 			
201 			for (int i = 0; i < geom.getVertexCount(); i++) {
202 				vertices[i] = new Point3f();
203 				normals[i] = new Vector3f();
204 			}
205 			geom.getCoordinates(0, vertices);
206 			geom.getNormals(0, normals);
207 		} else {
208 			vertices = geom.getCoordRef3f();
209 			normals = geom.getNormalRef3f();
210 		}
211 		if (this.reset) {
212 			this.nvertices = new Point3f[vertices.length * 2];
213 		}
214 		int n = 0;
215 		for (int i = 0; i < vertices.length; i++ ) {
216 			this.nvertices[n++] = new Point3f(vertices[i]);
217 			this.nvertices[n++] = new Point3f(vertices[i].x + scale * normals[i].x,
218 										 vertices[i].y + scale * normals[i].y,
219 										 vertices[i].z + scale * normals[i].z );
220 		}
221 		return this.nvertices;
222 	}
223 
224 	private void setCapabilities(GeometryArray geom) {
225 		if (geom != null) {
226 			geom.setCapability(GeometryArray.ALLOW_FORMAT_READ);
227 			geom.setCapability(GeometryArray.ALLOW_COUNT_READ);
228 			geom.setCapability(GeometryArray.ALLOW_COORDINATE_READ);
229 			geom.setCapability(GeometryArray.ALLOW_COORDINATE_WRITE);
230 			geom.setCapability(GeometryArray.ALLOW_NORMAL_READ);
231 			geom.setCapability(GeometryArray.ALLOW_NORMAL_WRITE);
232 			geom.setCapability(GeometryArray.ALLOW_REF_DATA_WRITE);
233 		}
234 	}
235  }