George Aroush, instructor
(Do at lest one of the following)
- Create your own three dimensional object as a set of vertices and edges in arrays. Display the object, rotate it, move it and scale it in a 3D space.
- Modify CubeFour.java or your own three dimensional display program and have the program display two or more objects moving and/or rotating in space all independent of each other.
Back to the top of this page. | Back to main Index |
Notes on 3D
The demo program CubeFour.java has a complete set of 3D transformations -- scaling, rotating on all three axes, translation and projection. It depicts a domino-shaped object moving toward the viewer, rotating and bobbing around. The program keeps the data for the "cube" in an arrays called oCoord[][3]. The "o" stands for "original" -- the data in these arrays are never changed. Instead the data are copied to an array called, x[], y[], and z[], which undergo all the transformations. For each frame of the display, the cube's data are copied to the transformation arrays, re-scaled, re-rotated on z, x and y-axes, re-moved to current position, re-projected and re-displayed. Then the variables which control the transformations are altered to create movement and spinning. Scaling and rotation are both done with the object centered at the origin. Scaling is done by multiplying each x, y, and z coordinate by a corresponding sx, sy, and sz variables or with a 2D array, by an array called s[3] with a scaling value for the x, y, and z component of each vertex. When coordinates get larger, they move away form the origin -- when they get smaller, they approach it. If the object's center is at the origin, it will be at the origin after the scaling.
3D Rotation
There are three kinds of rotation -- each about an axis. X-axis rotation is like that of a wheel on an axle. Y-axis rotation is like that of dancer turning around. Z-axis rotation is like that of an electric fan. If the object being rotated is not centered at the origin, it will appear to be orbiting around the axis, rather than rotating around itself. The order of the rotations is important. If we rotate an object the same amounts of angles, say N, around its x, then y, then z-axis, it will look different from the way it would appear after rotation about y, then z and then x-axis with the same angle N. One rotation on each axis should be enough to orient an object in any way desired.
Rotation is done with a single Rotate() method that is identical to the 2D rotation method discussed earlier. In fact, the 2D Rotate() method does rotations around "z-axis" of 3D forms.
When an object is rotated about an axis, the coordinates in that axis are not changed. So the method needs the arrays of coordinates from the other two axes. Thus, to do z-axis rotation with Rotate(), we pass it the x[] and y[] arrays. To do x-axis rotation, we pass it the y[] and z[] arrays, and to do y-axis rotation, it needs the z[] and x[] (note that the order must be as stated):
1st index 2st index X-axis rotation 1 (Y) 2 (Z) Y-axis rotation 2 (Z) 0 (X) Z-axis rotation 0 (X) 1 (Y) Thus, to use the rotation method we need to specify the following parameters:
Rotate3D(coord, c1, c2, np, angle);
coord the three-dimensional array c1 1st index c2 2nd index np number of points angle the angle of rotation in radius Translation, scaling and projection are the same here as we discussed them earlier in the last lecture, and there is full detail about them in the earlier hand outs.
This concludes discussion of wire-frame 3D (but it is only the beginning.) The next step in 3D computer graphics is to define faces or polygons out of the vertices of the object. If the location of a light source is known, the object can be drawn with filled in areas shaded according to the amount of light hitting them. This usually takes a longer time to compute and display, so wire-frame displays are used by computer animators in the early stages of their work to design shapes, positions, movements, etc. before producing a final animation. (We will look into this next lecture.)
Back to the top of this page. | Back to main Index |
ThreeDRot.java
/* * Program: ThreeDRot.java * Purpose: 3D Rotation * Author: George Aroush * Date: 1/1/1998 * Change Log: None * * Full description of Program: * Shows how to do rotation in 3D. */ import java.applet.*; import java.awt.*; public class ThreeDRot extends Applet { final int TIME_DELAY = 25; final int NP = 4; /* number of points */ final int NE = 4; /* number of edges */ final int CX = 320; /* center of screen */ final int CY = 240; final int X = 0; final int Y = 1; final int Z = 2; public void paint(Graphics g) { /* coordinates of rectangle */ float oCoord[][] = {{50, 150, 0}, {-50, 150, 0}, {-50, -150, 0}, {50, -150, 0}}; /* 9th vertex added for center of cube */ float coord[][] = new float[NP][3]; /* index numbers of coordinates for endpoints of edges */ int edge[][] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}}; /* holds the projected 3D object */ int proj[][] = new int [NP][2]; /* the object location in the 3D space */ float trans[] = {0, 0, 500}; float sd = 300; /* screen distance */ float angle; /* Copy rectangle from unchanging, original arrays, rotate around */ /* each three axes, project it on screen, & display its edges. */ angle = 0; do /* rotation around x-axes */ { Copy3D(oCoord, coord, NP); angle += 0.05f; Rotate3D(coord, Y, Z, NP, angle); Translate3D(coord, trans, NP); Project3D(coord, proj, NP, sd); g.clearRect(0, 0, 640, 480); Display3D(proj, edge, NE, g); Delay(TIME_DELAY); } while (angle <= 6 * Math.PI); angle = 0; do /* rotation around y-axes */ { Copy3D(oCoord, coord, NP); angle += 0.05f; Rotate3D(coord, Z, X, NP, angle); Translate3D(coord, trans, NP); Project3D(coord, proj, NP, sd); g.clearRect(0, 0, 640, 480); Display3D(proj, edge, NE, g); Delay(TIME_DELAY); } while (angle <= 6 * Math.PI); angle = 0; do /* rotation around z-axes */ { Copy3D(oCoord, coord, NP); angle += 0.05f; Rotate3D(coord, X, Y, NP, angle); Translate3D(coord, trans, NP); Project3D(coord, proj, NP, sd); g.clearRect(0, 0, 640, 480); Display3D(proj, edge, NE, g); Delay(TIME_DELAY); } while (angle <= 6 * Math.PI); angle = 0; do /* rotation around all three axes */ { Copy3D(oCoord, coord, NP); angle += 0.05f; Rotate3D(coord, Y, Z, NP, angle); Rotate3D(coord, Z, X, NP, angle); Rotate3D(coord, X, Y, NP, angle); Translate3D(coord, trans, NP); Project3D(coord, proj, NP, sd); g.clearRect(0, 0, 640, 480); Display3D(proj, edge, NE, g); Delay(TIME_DELAY); } while (angle <= 6 * Math.PI); } /* * void Project3D() * * Projects coordinate array onto screen at given screen distance * storing result as x and y coordinates in proj[][2] array. */ void Project3D(float coord[][], int proj[][], int np, float sd) { int i; for (i = 0; i < np; i++) { proj[i][X] = CX + (int) (coord[i][X] * sd / coord[i][Z]); proj[i][Y] = CY + (int) (coord[i][Y] * sd / coord[i][Z]); } } /* * void Translate3D() * * Add three values of trans[3] to each vertex in coord[][3] thus * moving vertices along all three axes */ void Translate3D(float coord[][], float trans[], int np) { int i, j; for (i = 0; i < np; i++) /* loop in the array */ { for (j = 0; j < 3; j++) /* loop in the vertex */ coord[i][j] += trans[j]; } } /* * void Copy3D() * * Copy X, Y & Z coordinates from original arrays to temp arrays */ void Copy3D(float orig[][], float coord[][], int np) { int i, j; for (i = 0; i < np; i++) { for (j = 0; j < 3; j++) coord[i][j] = orig[i][j]; } } /* * void Rotate3D() * * Rotate vertices around an axis by number of radians in angle: * for X axis rotation: c1 = Y and c2 = Z * for Y axis rotation: c1 = Z and c2 = X * for Z axis rotation: c1 = X and c2 = Y */ void Rotate3D(float coord[][], int c1, int c2, int np, float angle) { int i; float t, s, c; s = (float) Math.sin(angle); c = (float) Math.cos(angle); for (i = 0; i < np; i++) { /* temporarily store new value of coordinate 1 */ t = c * coord[i][c1] + s * coord[i][c2]; coord[i][c2] = c * coord[i][c2] - s * coord[i][c1]; coord[i][c1] = t; } } /* * void Display3D() * * Displays wire frame of object. Uses values in edge[][2] to find starting and * ending vertex for each edge */ void Display3D(int proj[][], int edge[][], int ne, Graphics g) { int e; int s, f; int x1, y1, x2, y2; for (e = 0; e < ne; e++) { s = edge[e][0]; /* s -- is the starting vertex */ f = edge[e][1]; /* f -- is the ending vertex */ x1 = proj[s][X]; /* stating point of a line */ y1 = proj[s][Y]; x2 = proj[f][X]; /* ending point of a line */ y2 = proj[f][Y]; g.drawLine(x1, y1, x2, y2); } } /* * void Delay() * * Simply pauses for some time */ public void Delay(int delayTime) { try { Thread.sleep(delayTime); /* call Java's sleep method */ } catch (InterruptedException e) { /* when the sleep() call above is over, Java will */ /* be interuppted and we fall into this block of code */ /* because our intention is simply slow down things */ /* wed do nothing in our exception code and just get out */ } } }ThreeDRot.htm
<html> <head> <title>
ThreeDRot</title> </head> <body> <hr> <applet code=
ThreeDRotwidth=640 height=480></applet> <hr> </body> </html>
CubeFour.java
/* * Program: CubeFour.java * Purpose: 3D Rotation * Author: George Aroush * Date: 1/1/1998 * Change Log: None * * Full description of Program: * Shows how to do scaling and rotation of a 3D objects. */ import java.applet.*; import java.awt.*; public class CubeFour extends Applet { final int TIME_DELAY = 50; final int NP = 9; /* number of points */ final int NE = 12; /* number of edges */ final int CX = 320; /* center of screen */ final int CY = 240; final int X = 0; final int Y = 1; final int Z = 2; public void paint(Graphics g) { /* coordinates of rectangle */ float oCoord[][] = {{ 75, 75, -75}, { 75, -75, -75}, {-75, -75, -75}, {-75, 75, -75}, { 75, 75, 75}, { 75, -75, 75}, {-75, -75, 75}, {-75, 75, 75}, { 0, 0, 0}}; /* 9th vertex added for center of cube */ float coord[][] = new float[NP][3]; /* index numbers of coordinates for endpoints of edges */ int edge[][] = {{0, 1}, {1, 2}, {2, 3}, {3, 0}, {0, 4}, {1, 5}, {2, 6}, {3, 7}, {4, 5}, {5, 6}, {6, 7}, {7, 4}}; /* holds the projected 3D object */ int proj[][] = new int [NP][2]; /* the object location in the 3D space */ float trans[] = {0, 0, 900}; /* velocity along X, Y, & Z axes*/ float vel[] = {20, 20, 20}; /* these scaling give the cube a domino-like shape */ float scal[] = {0.618f, 1.0f, 1.618f}; /* current angles of rotation of object */ float angle[] = {0, 0, 0}; /* rates of rotation of object: x, y & z angle */ float angInc[] = {0.08f, 0.05f, 0.0722f}; /* minimum and maximum X Y & Z values for vertex 0 */ float limits[][] = { {-400, 400}, /* x limits */ {-400, 400}, /* y limits */ {500, 5000} /* z limits */ }; float sd = 300; /* screen distance */ int i; /* * Copy cube from unchanging, original arrays, scale and rotate around * three axes move it, project it on screen, & display its edges */ do { Copy3D(oCoord, coord, NP); Scale3D(coord, scal, NP); Rotate3D(coord, Y, Z, NP, angle[X]); Rotate3D(coord, Z, X, NP, angle[Y]); Rotate3D(coord, X, Y, NP, angle[Z]); Translate3D(coord, trans, NP); /* test center of cube and reverse direction */ /* of velocity if it has crossed a limit */ for (i = X; i <= Z; i++) { if (coord[NP - 1][i] < limits[i][0] || coord[NP - 1][i] > limits[i][1]) vel[i] *= -1.0; trans[i] += vel[i]; /* change location of object */ angle[i] += angInc[i]; /* change angles of rotation */ if (angle[i] > 2.0 * Math.PI) angle[i] -= 2.0 * Math.PI; } Project3D(coord, proj, NP, sd); g.clearRect(0, 0, 640, 480); Display3D(proj, edge, NE, g); Delay(TIME_DELAY); } while (true); } /* * void Project3D() * * Projects coordinate array onto screen at given screen distance * storing result as x and y coordinates in proj[][2] array. */ void Project3D(float coord[][], int proj[][], int np, float sd) { int i; for (i = 0; i < np; i++) { proj[i][X] = CX + (int) (coord[i][X] * sd / coord[i][Z]); proj[i][Y] = CY + (int) (coord[i][Y] * sd / coord[i][Z]); } } /* * void Translate3D() * * Add three values of trans[3] to each vertex in coord[][3] thus * moving vertices along all three axes */ void Translate3D(float coord[][], float trans[], int np) { int i, j; for (i = 0; i < np; i++) /* loop in the array */ { for (j = 0; j < 3; j++) /* loop in the vertex */ coord[i][j] += trans[j]; } } /* * void Copy3D() * * Copy X, Y & Z coordinates from original arrays to temp arrays */ void Copy3D(float orig[][], float coord[][], int np) { int i, j; for (i = 0; i < np; i++) { for (j = 0; j < 3; j++) coord[i][j] = orig[i][j]; } } /* * void Scale3D() * * Multiplies each X, Y & Z coordinate by corresponding element in the array s[] */ void Scale3D(float coord[][], float s[], int np) { int i, j; for (i = 0; i < np; i++) { for (j = 0; j < 3; j++) coord[i][j] *= s[j]; } } /* * void Rotate3D() * * Rotate vertices around an axis by number of radians in angle: * for X axis rotation: c1 = Y and c2 = Z * for Y axis rotation: c1 = Z and c2 = X * for Z axis rotation: c1 = X and c2 = Y */ void Rotate3D(float coord[][], int c1, int c2, int np, float angle) { int i; float t, s, c; s = (float) Math.sin(angle); c = (float) Math.cos(angle); for (i = 0; i < np; i++) { /* temporarily store new value of coordinate 1 */ t = c * coord[i][c1] + s * coord[i][c2]; coord[i][c2] = c * coord[i][c2] - s * coord[i][c1]; coord[i][c1] = t; } } /* * void Display3D() * * Displays wire frame of object. Uses values in edge[][2] to find starting and * ending vertex for each edge */ void Display3D(int proj[][], int edge[][], int ne, Graphics g) { int e; int s, f; int x1, y1, x2, y2; for (e = 0; e < ne; e++) { s = edge[e][0]; /* s -- is the starting vertex */ f = edge[e][1]; /* f -- is the ending vertex */ x1 = proj[s][X]; /* stating point of a line */ y1 = proj[s][Y]; x2 = proj[f][X]; /* ending point of a line */ y2 = proj[f][Y]; g.drawLine(x1, y1, x2, y2); } } /* * void Delay() * * Simply pauses for some time */ public void Delay(int delayTime) { try { Thread.sleep(delayTime); /* call Java's sleep method */ } catch (InterruptedException e) { /* when the sleep() call above is over, Java will */ /* be interuppted and we fall into this block of code */ /* because our intention is simply slow down things */ /* wed do nothing in our exception code and just get out */ } } }CubeFour.htm
<html> <head> <title>
CubeFour</title> </head> <body> <hr> <applet code=
CubeFourwidth=640 height=480></applet> <hr> </body> </html>
Back to the top of this page. | Back to main Index. |