2 * DOUBLE BLACK DIAMOND DOUBLE BLACK DIAMOND
5 * ///\\\ ///\\\ ///\\\ ///\\\
6 * \\\/// \\\/// \\\/// \\\///
9 * EXPERTS ONLY!! EXPERTS ONLY!!
11 * Contains the model definitions for the cube structures.
15 * Top-level model of the entire sculpture. This contains a list of
16 * every cube on the sculpture, which forms a hierarchy of faces, strips
19 public static class Model extends LXModel {
21 public final List<Tower> towers;
22 public final List<Cube> cubes;
23 public final List<Face> faces;
24 public final List<Strip> strips;
26 public final Map<String, Cube> cubeTable;
28 private final Cube[] _cubes;
30 public Model(List<Tower> towerList, Cube[] cubeArr) {
31 super(new Fixture(cubeArr));
32 Fixture fixture = (Fixture) this.fixtures.get(0);
36 // Make unmodifiable accessors to the model data
37 List<Cube> cubeList = new ArrayList<Cube>();
38 List<Face> faceList = new ArrayList<Face>();
39 List<Strip> stripList = new ArrayList<Strip>();
40 Map<String, Cube> _cubeTable = new HashMap<String, Cube>();
41 for (Cube cube : _cubes) {
43 _cubeTable.put(cube.id, cube);
45 for (Face face : cube.faces) {
47 for (Strip strip : face.strips) {
54 this.towers = Collections.unmodifiableList(towerList);
55 this.cubes = Collections.unmodifiableList(cubeList);
56 this.faces = Collections.unmodifiableList(faceList);
57 this.strips = Collections.unmodifiableList(stripList);
58 this.cubeTable = Collections.unmodifiableMap(_cubeTable);
61 private static class Fixture extends LXAbstractFixture {
63 private Fixture(Cube[] cubeArr) {
64 for (Cube cube : cubeArr) {
66 for (LXPoint point : cube.points) {
67 this.points.add(point);
75 * TODO(mcslee): figure out better solution
80 public Cube getCubeByRawIndex(int index) {
84 public Cube getCubeById(String id) {
85 return this.cubeTable.get(id);
90 * Model of a set of cubes stacked in a tower
92 public static class Tower extends LXModel {
97 public final String id;
100 * Immutable list of cubes
102 public final List<Cube> cubes;
105 * Immutable list of faces
107 public final List<Face> faces;
110 * Immutable list of strips
112 public final List<Strip> strips;
115 * Constructs a tower model from these cubes
117 * @param cubes Array of cubes
119 public Tower(String id, List<Cube> cubes) {
120 super(cubes.toArray(new Cube[] {}));
124 List<Cube> cubeList = new ArrayList<Cube>();
125 List<Face> faceList = new ArrayList<Face>();
126 List<Strip> stripList = new ArrayList<Strip>();
128 for (Cube cube : cubes) {
130 for (Face face : cube.faces) {
132 for (Strip strip : face.strips) {
133 stripList.add(strip);
137 this.cubes = Collections.unmodifiableList(cubeList);
138 this.faces = Collections.unmodifiableList(faceList);
139 this.strips = Collections.unmodifiableList(stripList);
144 * Model of a single cube, which has an orientation and position on the
145 * car. The position is specified in x,y,z coordinates with rotation. The
146 * x axis is left->right, y is bottom->top, and z is front->back.
148 * A cube's x,y,z position is specified as the left, bottom, front corner.
150 * Dimensions are all specified in real-world inches.
152 public static class Cube extends LXModel {
154 public final static int FACES_PER_CUBE = 4;
155 public static final int POINTS_PER_STRIP = 16;
157 public final static int STRIPS_PER_CUBE = FACES_PER_CUBE*Face.STRIPS_PER_FACE;
158 public final static int POINTS_PER_CUBE = STRIPS_PER_CUBE*POINTS_PER_STRIP;
159 public final static int POINTS_PER_FACE = Face.STRIPS_PER_FACE*POINTS_PER_STRIP;
161 public final static float EDGE_HEIGHT = 21.75f;
162 public final static float EDGE_WIDTH = 24.625f;
163 public final static float CHANNEL_WIDTH = 1.5f;
165 public final static Face.Metrics FACE_METRICS = new Face.Metrics(
166 new Strip.Metrics(EDGE_WIDTH, POINTS_PER_STRIP),
167 new Strip.Metrics(EDGE_HEIGHT, POINTS_PER_STRIP)
170 public final String id;
173 * Immutable list of all cube faces
175 public final List<Face> faces;
178 * Immutable list of all strips
180 public final List<Strip> strips;
183 * Front left corner x coordinate
185 public final float x;
188 * Front left corner y coordinate
190 public final float y;
193 * Front left corner z coordinate
195 public final float z;
198 * Rotation about the x-axis
200 public final float rx;
203 * Rotation about the y-axis
205 public final float ry;
208 * Rotation about the z-axis
210 public final float rz;
212 public Cube(String id, float x, float y, float z, float rx, float ry, float rz) {
213 super(new Fixture(x, y, z, rx, ry, rz));
214 Fixture fixture = (Fixture) this.fixtures.get(0);
218 while (rx < 0) rx += 360;
219 while (ry < 0) ry += 360;
220 while (rz < 0) rz += 360;
232 this.faces = Collections.unmodifiableList(fixture.faces);
233 this.strips = Collections.unmodifiableList(fixture.strips);
236 private static class Fixture extends LXAbstractFixture {
238 private final List<Face> faces = new ArrayList<Face>();
239 private final List<Strip> strips = new ArrayList<Strip>();
241 private Fixture(float x, float y, float z, float rx, float ry, float rz) {
242 LXTransform t = new LXTransform();
243 t.translate(x, y, z);
244 t.rotateX(rx * PI / 180.);
245 t.rotateY(ry * PI / 180.);
246 t.rotateZ(rz * PI / 180.);
248 for (int i = 0; i < FACES_PER_CUBE; i++) {
249 Face face = new Face(FACE_METRICS, (ry + 90*i) % 360, t);
250 this.faces.add(face);
251 for (Strip s : face.strips) {
254 for (LXPoint p : face.points) {
257 t.translate(EDGE_WIDTH, 0, 0);
265 * A face is a component of a cube. It is comprised of four strips forming
266 * the lights on this side of a cube. A whole cube is formed by four faces.
268 public static class Face extends LXModel {
270 public final static int STRIPS_PER_FACE = 4;
272 public static class Metrics {
273 final Strip.Metrics horizontal;
274 final Strip.Metrics vertical;
276 public Metrics(Strip.Metrics horizontal, Strip.Metrics vertical) {
277 this.horizontal = horizontal;
278 this.vertical = vertical;
283 * Immutable list of strips
285 public final List<Strip> strips;
288 * Rotation of the face about the y-axis
290 public final float ry;
292 Face(Metrics metrics, float ry, LXTransform transform) {
293 super(new Fixture(metrics, ry, transform));
294 Fixture fixture = (Fixture) this.fixtures.get(0);
296 this.strips = Collections.unmodifiableList(fixture.strips);
299 private static class Fixture extends LXAbstractFixture {
301 private final List<Strip> strips = new ArrayList<Strip>();
303 private Fixture(Metrics metrics, float ry, LXTransform transform) {
305 transform.translate(0, metrics.vertical.length, 0);
306 for (int i = 0; i < STRIPS_PER_FACE; i++) {
307 boolean isHorizontal = (i % 2 == 0);
308 Strip.Metrics stripMetrics = isHorizontal ? metrics.horizontal : metrics.vertical;
309 Strip strip = new Strip(stripMetrics, ry, transform, isHorizontal);
310 this.strips.add(strip);
311 transform.translate(isHorizontal ? metrics.horizontal.length : metrics.vertical.length, 0, 0);
312 transform.rotateZ(HALF_PI);
313 for (LXPoint p : strip.points) {
323 * A strip is a linear run of points along a single edge of one cube.
325 public static class Strip extends LXModel {
327 public static final float POINT_SPACING = 18.625f / 15.f;
329 public static class Metrics {
331 public final float length;
332 public final int numPoints;
334 public Metrics(float length, int numPoints) {
335 this.length = length;
336 this.numPoints = numPoints;
340 public final Metrics metrics;
343 * Whether this is a horizontal strip
345 public final boolean isHorizontal;
348 * Rotation about the y axis
350 public final float ry;
352 public Object obj1 = null, obj2 = null;
354 Strip(Metrics metrics, float ry, List<LXPoint> points, boolean isHorizontal) {
356 this.isHorizontal = isHorizontal;
357 this.metrics = metrics;
361 Strip(Metrics metrics, float ry, LXTransform transform, boolean isHorizontal) {
362 super(new Fixture(metrics, ry, transform));
363 this.metrics = metrics;
364 this.isHorizontal = isHorizontal;
368 private static class Fixture extends LXAbstractFixture {
369 private Fixture(Metrics metrics, float ry, LXTransform transform) {
370 float offset = (metrics.length - (metrics.numPoints - 1) * POINT_SPACING) / 2.f;
372 transform.translate(offset, -Cube.CHANNEL_WIDTH/2.f, 0);
373 for (int i = 0; i < metrics.numPoints; i++) {
374 LXPoint point = new LXPoint(transform.x(), transform.y(), transform.z());
375 this.points.add(point);
376 transform.translate(POINT_SPACING, 0, 0);