1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package net.jbeans.j3d.modeler.geometry.util;
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.io.*;
27 import java.util.*;
28 import javax.media.j3d.*;
29 import javax.vecmath.*;
30
31
32 import net.jbeans.util.debug.*;
33
34
35
36
37 /***
38 * generally describe NormalGenerator in here
39 *
40 * @version $Revision: 1.3 $
41 * @author Masahiro Takatsuka (masa@jbeans.net)
42 * @see com.sun.j3d.utils.geometry.NormalGenerator
43 */
44
45 public class NormalGenerator extends com.sun.j3d.utils.geometry.NormalGenerator {
46 private static final boolean DEBUG = Debug.getDebugFlag(NormalGenerator.class);
47
48
49
50 private transient Vector3f[] facetNorms;
51 private transient ArrayList tally;
52 private transient IndexedGeometryArray geomArray;
53 private transient int[] coordInds;
54 private transient int[] normalInds;
55 private transient Vector3f[] normalRef;
56 private transient EdgeTable edgetable;
57 private transient boolean reset = true;
58 private transient int indexCount = -1;
59
60
61
62 private transient Vector3f workv3f0 = new Vector3f();
63 private transient Vector3f workv3f1 = new Vector3f();
64 private transient int[] ai;
65 private transient float cos;
66 private transient Edge edge = new Edge();
67 private transient Vector3f[] commonNormals;
68 private transient Vector3f[] newNormals;
69
70 public NormalGenerator() {
71 super();
72 }
73
74 public NormalGenerator(double d) {
75 super(d);
76 }
77
78 private int createHardEdges() {
79 if (DEBUG) {
80 System.out.println("Creating Hard Edges...");
81 }
82 if (reset) {
83 this.edgetable = new EdgeTable(this.coordInds);
84 this.tally = new ArrayList();
85 this.ai = new int[this.coordInds.length];
86 this.cos = (float)Math.cos(getCreaseAngle());
87 } else {
88 this.tally.clear();
89 }
90 for (int j = 0; j < this.coordInds.length; j++) {
91 ai[j] = 0x7fffffff;
92 }
93 int i = 1;
94 for (int k = 0; k < this.coordInds.length; k++) {
95 if (ai[k] == 0x7fffffff) {
96 ArrayList arraylist = new ArrayList();
97 this.tally.add(arraylist);
98 arraylist.add(new Integer(k));
99 ai[k] = this.tally.size() - 1;
100 boolean flag1 = true;
101 this.edge.set(this.coordInds[k], this.coordInds[(k + 1) % 3 != 0 ? k + 1 : k - 2]);
102 int l = this.coordInds[k % 3 != 0 ? k - 1 : k + 2];
103 int i1 = k;
104 boolean flag;
105 do {
106 Integer integer = this.edgetable.get(this.edge.v2, this.edge.v1);
107 if (integer == null) {
108 flag = false;
109 } else {
110 int j1 = integer.intValue();
111 float f = this.facetNorms[i1 / 3].dot(this.facetNorms[j1 / 3]);
112 flag = f > cos;
113 if (flag) {
114 int k1 = (((j1 + 1) % 3) != 0) ?
115 (j1 + 1) : (j1 - 2);
116 if (this.coordInds[k] != this.coordInds[k1]) {
117 k1 = ((j1 % 3) != 0) ? (j1 - 1) : (j1 + 2);
118 }
119 if (ai[k1] != 0x7fffffff) {
120 flag = false;
121 } else {
122 ai[k1] = this.tally.size() - 1;
123 arraylist.add(new Integer(k1));
124 if (arraylist.size() > i) {
125 i = arraylist.size();
126 }
127 i1 = j1;
128 if (flag1) {
129 edge.v2 = this.coordInds[i1];
130 } else {
131 edge.v1 = this.coordInds[i1];
132 }
133 }
134 }
135 }
136 if (!flag && flag1) {
137 flag1 = false;
138 flag = true;
139 i1 = k;
140 this.edge.set(this.coordInds[k % 3 != 0 ? k - 1 : k + 2], this.coordInds[k]);
141 }
142 } while(flag && (flag1 && edge.v2 != l || !flag1));
143 }
144 }
145 return i;
146 }
147
148 private void calculateVertexNormalsForGeometryArray(int totalNum) {
149 if (DEBUG) {
150 System.out.println("calculating vertex normals...");
151 }
152 boolean recycle = true;
153
154 if (getCreaseAngle() != 0.0D) {
155
156 if (reset || (this.commonNormals.length < totalNum)) {
157 this.commonNormals = new Vector3f[totalNum];
158 }
159 if (reset || (this.newNormals.length < this.tally.size())) {
160 this.newNormals = new Vector3f[this.tally.size()];
161 recycle = false;
162 }
163
164 if (DEBUG) {
165 System.out.println("going through tally.");
166 }
167 for (int l = 0; l < this.tally.size(); l++) {
168 ArrayList arraylist = (ArrayList)this.tally.get(l);
169 int k = 0;
170 if (!recycle) {
171 this.newNormals[l] = new Vector3f();
172 }
173 for (int j1 = 0; j1 < arraylist.size(); j1++) {
174 int k1 = ((Integer)arraylist.get(j1)).intValue();
175 if (k1 != -1) {
176 int j = k1 / 3;
177 if (!Float.isNaN(this.facetNorms[j].x)) {
178 int l1;
179 for (l1 = 0; l1 < k; l1++) {
180 if (this.commonNormals[l1].equals(this.facetNorms[j])) {
181 break;
182 }
183 }
184
185 this.normalInds[k1] = l;
186 if (l1 == k) {
187 this.newNormals[l].add(this.facetNorms[j]);
188 this.commonNormals[k++] = this.facetNorms[j];
189 }
190 }
191 }
192 }
193
194 this.newNormals[l].normalize();
195 if (Float.isNaN(this.newNormals[l].x)) {
196 this.newNormals[l].x = 1.0F;
197 this.newNormals[l].y = this.newNormals[l].z = 0.0F;
198 }
199 }
200 } else {
201 this.newNormals = this.facetNorms;
202
203 for (int i1 = 0; i1 < this.facetNorms.length; i1++) {
204 this.normalInds[i1 * 3] = i1;
205 this.normalInds[i1 * 3 + 1] = i1;
206 this.normalInds[i1 * 3 + 2] = i1;
207 }
208
209 }
210 if (DEBUG) {
211 System.out.println("new index count = " + this.normalInds.length);
212 System.out.println("new num of normalref = " + this.newNormals.length);
213 }
214 for (int i = 0; i < this.normalInds.length; i++) {
215 this.normalRef[i] = this.newNormals[this.normalInds[i]];
216 }
217 if (DEBUG) {
218 System.out.println("set new normals.");
219 }
220 }
221
222 private void calculatefacetNormalsForGeometryArray(Point3f[] apoint3f) {
223 if (DEBUG) {
224 System.out.println("calculating facet normals...");
225 }
226 if (DEBUG) {
227 System.out.println("apoint3f length = " + apoint3f.length);
228 }
229 if (reset) {
230 this.facetNorms = new Vector3f[this.coordInds.length / 3];
231 }
232 for (int i = 0; i < this.coordInds.length; i += 3) {
233 workv3f0.sub(apoint3f[this.coordInds[i + 2]], apoint3f[this.coordInds[i + 1]]);
234 workv3f1.sub(apoint3f[this.coordInds[i]], apoint3f[this.coordInds[i + 1]]);
235 if (reset) {
236 this.facetNorms[i / 3] = new Vector3f();
237 }
238 this.facetNorms[i / 3].cross(workv3f0, workv3f1);
239 this.facetNorms[i / 3].normalize();
240 if (Float.isNaN(this.facetNorms[i / 3].x)) {
241 this.facetNorms[i / 3].x = 1.0F;
242 this.facetNorms[i / 3].y = this.facetNorms[i / 3].z = 0.0F;
243 }
244 }
245 }
246
247 /***
248 * Computes naive normals.
249 */
250 public synchronized void generateNormals(GeometryArray geom, Point3f[] coords) {
251 if (! checkIndexedGeometryArray(geom)) {
252 return;
253 }
254 this.normalRef = geom.getNormalRef3f();
255 this.geomArray = (IndexedGeometryArray) geom;
256 int idxCount = this.geomArray.getIndexCount();
257 if (this.indexCount != idxCount) {
258 reset = true;
259 this.indexCount = idxCount;
260 } else {
261 reset = false;
262 }
263 if (reset) {
264 this.coordInds = new int[this.indexCount];
265 this.geomArray.getCoordinateIndices(0, this.coordInds);
266 this.normalInds = new int[this.indexCount];
267 this.geomArray.getNormalIndices(0, this.normalInds);
268 }
269 calculatefacetNormalsForGeometryArray(coords);
270 int i = createHardEdges();
271 calculateVertexNormalsForGeometryArray(i);
272 }
273
274 private boolean checkIndexedGeometryArray(GeometryArray geom) {
275 if (! (geom instanceof IndexedTriangleArray ||
276 geom instanceof IndexedTriangleFanArray ||
277 geom instanceof IndexedTriangleStripArray)) {
278 return false;
279 }
280 return true;
281 }
282 }