import damkjer.ocd.*;
import ddf.sds.*;
int currCube;
CompositeMesh cubed;
color cubeColor;
Mesh smoothCubed;
CatmullClark sds;
Camera cam;
boolean drawSmoothCubed = false;
boolean drawWireFrame = true;
static final int SCALE = 0;
static final int ROTX = 1;
static final int ROTY = 2;
static final int ROTZ = 3;
int mode = SCALE;
/**
* Hold down the LEFT mouse button and move the mouse to rotate around the currently selected (red) cube.
* Hold down the RIGHT mouse button and move the mouse up and down to zoom in and out on the currently selected cube.
* Press t to toggle between the cube mesh and the subdivided mesh.
* Press w to toggle the wireframe cubes on and off.
* Press d to move to the previous cube in the structure, press f to move to the next.
* Note: the order of traversal will be the order in which they were created and NOT necessarily the order in which they appear.
*
* When adding a cube, it will be added next to the indicated side of the currently selected cube.
* 8 is +Y, 2 is -Y, 4 is -X, 6 is +X, 9 is -Z, 3 is +Z.
* The newly added cube will become the currently selected cube.
*
* Use the arrow keys to move the currently selected cube along the X and Y axes,
* use the o and l keys to move along the Z axis.
* Note that the camera will remain aimed at the cube as you move it.
* The [ and ] keys to change the currently selected cube's scale or rotation, depending on the current mode.
* ] increases the scale or rotates by a positive angle, [ decreses scale or rotates by a negative angle.
* z switches to scaling mode, x switches to X-rotation mode, c switches to Y-rotation mode,
* and v switches to Z-rotation mode.
* The current mode is always displayed in the upper right hand corner of the applet.
*/
void setup()
{
size(800, 600, P3D);
cubeColor = color(0, 128, 255);
Mesh cube = MeshMaker.makeCube(10, cubeColor);
cubed = new CompositeMesh(cube);
currCube = 0;
sds = new CatmullClark();
cam = new Camera(this, 20, -70, 160, 0, 0, 0);
resubdivide();
textFont(createFont("Arial", 20));
}
void draw()
{
background(0);
noStroke();
lights();
cam.feed();
// coord axes
stroke(0, 255, 0, 128);
fill(0, 255, 0, 128);
line(-200, 0, 0, 200, 0, 0);
line(0, -200, 0, 0, 200, 0);
line(0, 0, -200, 0, 0, 200);
text("+X", 100, 0, 0);
text("-X", -100, 0, 0);
text("+Y", 0, -100, 0);
text("-Y", 0, 100, 0);
text("+Z", 0, 0, 100);
text("-Z", 0, 0, -100);
noStroke();
if ( drawSmoothCubed && smoothCubed != null )
{
smoothCubed.draw(this);
}
else
{
cubed.draw(this);
}
for(int i = 0; drawWireFrame && i < cubed.numMesh(); i++)
{
if ( currCube == i ) cubed.getMesh(i).drawWireFrame(this, color(255, 0, 0));
else cubed.getMesh(i).drawWireFrame(this, color(255));
}
// reset the camera and perspective for text overlay
camera();
perspective();
hint(DISABLE_DEPTH_TEST);
fill(160);
text("Editing Mode: " + modeString(), 10, 30);
text("Use '[' to decrement, ']' to increment.", 10, 60);
noHint(DISABLE_DEPTH_TEST);
}
String modeString()
{
switch(mode)
{
case SCALE: return "Scale";
case ROTX: return "Rotate X";
case ROTY: return "Rotate Y";
case ROTZ: return "Rotate Z";
}
return "?????";
}
void mouseDragged()
{
if ( mouseButton == LEFT )
{
cam.tumble(radians(mouseX - pmouseX), radians(mouseY - pmouseY));
}
if ( mouseButton == RIGHT )
{
cam.zoom(radians(mouseY - pmouseY)/2);
}
}
void keyPressed()
{
if ( keyCode == RIGHT )
{
cubed.getMesh(currCube).translate(5, 0, 0);
resubdivide();
}
if ( keyCode == LEFT )
{
cubed.getMesh(currCube).translate(-5, 0, 0);
resubdivide();
}
if ( keyCode == UP )
{
cubed.getMesh(currCube).translate(0, -5, 0);
resubdivide();
}
if ( keyCode == DOWN )
{
cubed.getMesh(currCube).translate(0, 5, 0);
resubdivide();
}
if ( key == 'o' )
{
cubed.getMesh(currCube).translate(0, 0, 5);
resubdivide();
}
if ( key == 'l' )
{
cubed.getMesh(currCube).translate(0, 0, -5);
resubdivide();
}
if ( key == ']' )
{
Mesh m = cubed.getMesh(currCube);
switch (mode)
{
case SCALE:
m.scale(1.2);
break;
case ROTX:
m.rotateX(0.1);
break;
case ROTY:
m.rotateY(0.1);
break;
case ROTZ:
m.rotateZ(0.1);
break;
}
resubdivide();
}
if ( key == '[' )
{
Mesh m = cubed.getMesh(currCube);
switch (mode)
{
case SCALE:
m.scale(0.8);
break;
case ROTX:
m.rotateX(-0.1);
break;
case ROTY:
m.rotateY(-0.1);
break;
case ROTZ:
m.rotateZ(-0.1);
break;
}
resubdivide();
}
}
void keyReleased()
{
if ( key == 'z' )
{
mode = SCALE;
println("Now in scaling mode.");
}
if ( key == 'x' )
{
mode = ROTX;
println("Now in X-rotation mode.");
}
if ( key == 'c' )
{
mode = ROTY;
println("Now in Y-rotation mode.");
}
if ( key == 'v' )
{
mode = ROTZ;
println("Now in Z-rotation mode.");
}
if ( key == 'f' )
{
currCube += 1;
currCube %= cubed.numMesh();
Mesh c = cubed.getMesh(currCube);
cam.aim(c.center.x, c.center.y, c.center.z);
}
if ( key == 'd' )
{
currCube -= 1;
if ( currCube < 0 ) currCube = cubed.numMesh()-1;
Mesh c = cubed.getMesh(currCube);
cam.aim(c.center.x, c.center.y, c.center.z);
}
if ( key == 'w' )
{
drawWireFrame = !drawWireFrame;
}
if ( key == 't' )
{
drawSmoothCubed = !drawSmoothCubed;
}
if ( key == '2' )
{
Mesh newCube = MeshMaker.makeCube(10, cubeColor);
Mesh cCube = cubed.getMesh(currCube);
newCube.translate(cCube.center.x, cCube.center.y + cCube.scale + 20, cCube.center.z);
if ( cubed.addMesh(newCube, cCube) )
{
resubdivide();
aimCam();
}
}
if ( key == '8' )
{
Mesh newCube = MeshMaker.makeCube(10, cubeColor);
Mesh cCube = cubed.getMesh(currCube);
newCube.translate(cCube.center.x, cCube.center.y - cCube.scale - 20, cCube.center.z);
if ( cubed.addMesh(newCube, cCube) )
{
resubdivide();
aimCam();
}
}
if ( key == '6' )
{
Mesh newCube = MeshMaker.makeCube(10, cubeColor);
Mesh cCube = cubed.getMesh(currCube);
newCube.translate(cCube.center.x + cCube.scale + 20, cCube.center.y, cCube.center.z);
if ( cubed.addMesh(newCube, cCube) )
{
resubdivide();
aimCam();
}
}
if ( key == '4' )
{
Mesh newCube = MeshMaker.makeCube(10, cubeColor);
Mesh cCube = cubed.getMesh(currCube);
newCube.translate(cCube.center.x - cCube.scale - 20, cCube.center.y, cCube.center.z);
if ( cubed.addMesh(newCube, cCube) )
{
resubdivide();
aimCam();
}
}
if ( key == '9' )
{
Mesh newCube = MeshMaker.makeCube(10, cubeColor);
Mesh cCube = cubed.getMesh(currCube);
newCube.translate(cCube.center.x, cCube.center.y, cCube.center.z - cCube.scale - 20);
if ( cubed.addMesh(newCube, cCube) )
{
resubdivide();
aimCam();
}
}
if ( key == '3' )
{
Mesh newCube = MeshMaker.makeCube(10, cubeColor);
Mesh cCube = cubed.getMesh(currCube);
newCube.translate(cCube.center.x, cCube.center.y, cCube.center.z + cCube.scale + 20);
if ( cubed.addMesh(newCube, cCube) )
{
resubdivide();
aimCam();
}
}
}
void aimCam()
{
currCube = cubed.numMesh() - 1;
Mesh c = cubed.getMesh(currCube);
cam.aim(c.center.x, c.center.y, c.center.z);
}
void resubdivide()
{
Mesh c = cubed.getMesh(currCube);
cam.aim(c.center.x, c.center.y, c.center.z);
cubed.mixDown();
smoothCubed = sds.subdivide(cubed, 3);
}