/* 3D camera rotator (version 2) - no translation -Click and drag the mouse in the Processing window to look around. -This version of z_3Drotate doesn't use the java.awt.Robot class, and thus does not require a signed certificate when running in a web browser! Zachary Seldess, 6/23/08 [http://www.zacharyseldess.com] */ import processing.opengl.*; //---CHANGE THESE VARIABLES TO YOUR LIKING---// float cam[] = {0., 0., 0.}; // set camera coordinates float lookat[] = {0., 0., 1.}; // set lookat coordinates float lookYangle = PI*0.9; // lookat angle constraints (PI == 180 degree rotation, PI*0.5 == 90 degrees) // NOTE: setting lookYangle to PI or greater won't look good. I recommend not exceeding PI*0.9 float easing = 0.05; // set smoothing (0.01 == very smooth, 1. == no smoothing) float dragSpeed = 1.; // set rotation speed int mouseTerritory[] = {800, 600}; // set the pixel boundaries of the cursor - effects rotation speed //-------------------------------------------// float easeX; float easeY; float mX; float mY; float dragX; float dragY; float pdragX; float pdragY; float deltaX; float deltaY; int sizeX; int sizeY; int sizeXedge; int sizeYedge; //////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////// //---functions called during setup()---// void navSetup() { sizeX = width; sizeY = height; checkScreenSize(); sizeXedge = sizeX/10; sizeYedge = sizeY/10; deriveCursor(); checkRotation(); } //--------------------------------------// //---functions called only once during navSetup()---// void checkScreenSize() { if (sizeX >= mouseTerritory[0]) { sizeX = mouseTerritory[0]; } if (sizeY >= mouseTerritory[1]) { sizeY = mouseTerritory[1]; } } void deriveCursor() { float x = lookat[0]-cam[0]; float y = lookat[1]-cam[1]; float z = lookat[2]-cam[2]; float hyp = mag(x,y,z); float sine = y/hyp; float arcsine = asin(sine); float Ymouse = map(arcsine, -lookYangle/2, lookYangle/2, sizeYedge, sizeY-sizeYedge); float atangent = atan2(z,x); float Xmouse = map(atangent, 0, TWO_PI, sizeXedge, sizeX-sizeXedge); if (Xmouse < sizeXedge) { Xmouse = (sizeX-sizeXedge) - (sizeXedge-Xmouse); } if (Xmouse > sizeX-sizeXedge) { Xmouse = (Xmouse-(sizeX-sizeXedge)) + sizeXedge; } if (Ymouse < sizeYedge) { Ymouse = float(sizeYedge); println("lookat vector exceeds bounds of specified lookYangle: " + lookYangle); println("constraining lookat accordingly..."); } if (Ymouse > sizeY-sizeYedge) { Ymouse = float(sizeY-sizeYedge); println("lookat vector exceeds bounds of specified lookYangle: " + lookYangle); println("constraining lookat accordingly..."); } dragX = Xmouse; dragY = Ymouse; pdragX = Xmouse; pdragY = Ymouse; easeX = Xmouse; easeY = Ymouse; } //--------------------------------------// //--- functions called during draw() ---// void navUpdate() { mouseTrack(); mouseEase(); checkRotation(); camera(cam[0], cam[1], cam[2], lookat[0], lookat[1], lookat[2], 0, 1, 0); } void mouseTrack() { if(mousePressed) { deltaX = (mouseX-pmouseX) * dragSpeed; deltaY = (mouseY-pmouseY) * dragSpeed; pdragX = dragX; dragX += deltaX; dragY += deltaY; if (deltaX < 0) { if (dragX < sizeXedge) { dragX = sizeX-sizeXedge; } } if (deltaX > 0) { if (dragX > sizeX-sizeXedge) { } } if (dragY < sizeYedge) { dragY = sizeYedge; } if (dragY > sizeY-sizeYedge) { dragY = sizeY-sizeYedge; } } } void mouseEase() { if (dragX < sizeXedge*2 && pdragX > sizeX-(sizeXedge*2)) { easeX = easeX - (sizeX-(sizeXedge*2)); } if (dragX > sizeX-(sizeXedge*2) && pdragX < sizeXedge*2) { easeX = easeX + (sizeX-(sizeXedge*2)); } float dx = dragX - easeX; if(abs(dx) > 1) { easeX += dx * easing; } float dy = dragY - easeY; if(abs(dy) > 1) { easeY += dy * easing; } } void checkRotation() { mX = ((easeX-sizeXedge)/float(sizeX-(sizeXedge*2)))*TWO_PI; // scale mouseX movement between 0 and 2*PI mY = ((easeY-sizeYedge)/float(sizeY-(sizeYedge*2)))*lookYangle - lookYangle/2; lookat[0] = cam[0] + cos(mX)*cos(mY); lookat[1] = cam[1] + sin(mY); lookat[2] = cam[2] + sin(mX)*cos(mY); } //--------------------------------------//