1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
|
package tesseract.objects;
import javax.media.j3d.Appearance;
import javax.media.j3d.IndexedQuadArray;
import javax.media.j3d.Material;
import javax.media.j3d.PointArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.geometry.GeometryInfo;
import com.sun.j3d.utils.geometry.NormalGenerator;
/**
* Chain link object.
*
* @author Jesse Morgan
*/
public class ChainLink2 extends PhysicalObject {
/**
* Default link length.
*/
public static final float DEFAULT_LENGTH = 0.15f;
/**
* Default ratio of length to width.
*/
public static final float DEFAULT_WIDTH_RATIO = 0.75f;
/**
* Default ratio of length to link diameter.
*/
public static final float DEFAULT_DIAMETER_RATIO = 0.25f;
/**
* Number of slices to render.
*/
protected static final int SLICE_COUNT = 40;
/**
* Number of points in the circumference of the circle.
*/
protected static final int SLICE_DIVISIONS = 16;
/**
* Construct a chain link.
*
* @param thePosition Position.
* @param mass Mass.
*/
public ChainLink2(final Vector3f thePosition, final float mass) {
this(thePosition, mass, DEFAULT_LENGTH * DEFAULT_DIAMETER_RATIO,
DEFAULT_LENGTH, DEFAULT_LENGTH * DEFAULT_WIDTH_RATIO);
}
/**
* Construct a chain link.
*
* @param thePosition Position.
* @param mass Mass.
* @param length Link length.
* Width and diameter are created from the default ratios.
*/
public ChainLink2(final Vector3f thePosition, final float mass,
final float length) {
this(thePosition, mass, length * DEFAULT_DIAMETER_RATIO,
length, length * DEFAULT_WIDTH_RATIO);
}
/**
* Construct a Chain Link.
*
* @param thePosition Position.
* @param mass Mass.
* @param diameter Diameter of link.
* @param length Length of link.
* @param width Width of link.
*/
public ChainLink2(final Vector3f thePosition, final float mass,
final float diameter, final float length, final float width) {
super(thePosition, mass);
setShape(createShape(SLICE_COUNT, SLICE_DIVISIONS,
diameter, length, width));
}
/**
* Create the shape.
*
* @param sliceCount Number of slices.
* @param sliceDivisions Number of divisions.
* @param diameter Diameter.
* @param length Length.
* @param width Width.
*
* @return Chainlink shape.
*/
public Shape3D createShape(final int sliceCount, final int sliceDivisions,
final float diameter, final float length, final float width) {
Point3f[][] coords = new Point3f[sliceCount][sliceDivisions];
// Design the first circle
double theta = 2 * Math.PI / sliceDivisions;
float radius = diameter / 2.0f;
for (int i = 0; i < sliceDivisions; i++) {
coords[0][i] = new Point3f(
0f,
(float) (radius * Math.cos(i * theta)),
(float) (radius * Math.sin(i * theta)));
}
// Create the arc
radius = (width - radius) / 2.0f;
Transform3D t3d = new Transform3D();
t3d.setIdentity();
t3d.setTranslation(new Vector3f(0, -radius, 0));
Transform3D tmp = new Transform3D();
tmp.rotZ(Math.PI / (sliceCount / 2.0 - 1));
t3d.mul(tmp);
tmp.setIdentity();
tmp.setTranslation(new Vector3f(0, radius, 0));
t3d.mul(tmp);
for (int j = 1; j < sliceCount / 2; j++) {
for (int i = 0; i < sliceDivisions; i++) {
coords[j][i] = new Point3f(coords[j - 1][i]);
t3d.transform(coords[j][i]);
}
}
// Next build second half...
t3d.setIdentity();
t3d.setTranslation(new Vector3f(
-(length / 2.0f - radius / 2.0f),
(width - diameter / 2.0f) / 2.0f,
0));
Transform3D rot = new Transform3D();
rot.rotY(Math.PI);
tmp.setIdentity();
tmp.rotX(Math.PI);
rot.mul(tmp);
for (int j = 0; j < sliceCount / 2; j++) {
for (int i = 0; i < sliceDivisions; i++) {
t3d.transform(coords[j][i]);
coords[j + sliceCount / 2][i] = new Point3f(coords[j][i]);
rot.transform(coords[j + sliceCount / 2][i]);
}
}
// Build Geoemetry
IndexedQuadArray geometry = new IndexedQuadArray(
sliceCount * sliceDivisions,
PointArray.COORDINATES,
4 * sliceDivisions * sliceCount);
for (int i = 0; i < sliceCount; i++) {
geometry.setCoordinates(i * sliceDivisions, coords[i]);
}
int index = 0;
for (int j = 0; j < (sliceCount - 1); j++) {
for (int i = 0; i < sliceDivisions; i++) {
geometry.setCoordinateIndex(index++, j * sliceDivisions + i);
geometry.setCoordinateIndex(index++,
(j + 1) * sliceDivisions + i);
geometry.setCoordinateIndex(index++,
(j + 1) * sliceDivisions + (i + 1) % sliceDivisions);
geometry.setCoordinateIndex(index++,
j * sliceDivisions + (i + 1) % sliceDivisions);
}
}
for (int i = 0; i < sliceDivisions; i++) {
geometry.setCoordinateIndex(index++,
(sliceCount - 1) * sliceDivisions + i);
geometry.setCoordinateIndex(index++,
i);
geometry.setCoordinateIndex(index++,
(i + 1) % sliceDivisions);
geometry.setCoordinateIndex(index++,
(sliceCount - 1) * sliceDivisions
+ (i + 1) % sliceDivisions);
}
GeometryInfo gInfo = new GeometryInfo(geometry);
gInfo.convertToIndexedTriangles();
new NormalGenerator().generateNormals(gInfo);
Shape3D shape = new Shape3D(gInfo.getGeometryArray());
Appearance app = new Appearance();
Material mat = new Material();
mat.setDiffuseColor(1, 0, 0);
app.setMaterial(mat);
shape.setAppearance(app);
return shape;
}
}
|