# Making a 3D camera

Hello everyone,

I recently started coding a 3d program, some kind of game, but I remain stuck because of one simple thing : how to make a 3d camera ?

In fact, the program generates a cube, but I want it to move when I move my mouse as if it were real life or any game.

So here is what i’ve done so far :

``````float gx, gy, gz;
float rx, ry;
Cube cube1;
Cube cube2;

void setup(){
cube1 = new Cube(0,0,0);
cube2 = new Cube(-200,0,0);
gx = 0;
gy = 0;
gz = 0;

rx = 0;
ry = 0;
size(400, 400, P3D);
frameRate(60);
}

void draw(){
background(100);
cube1.update();
cube2.update();

if (keyPressed == true) {
if (key == 'R' || key == 'r') {
gz = 0;
gx = 0;
gy = 0;
rx = 0;
ry = 0;
} else if (key == 'Z' || key == 'z') {
gz -= 1;
} else if (key == 'S' || key == 's') {
gz += 1;
} else if (key == 'Q' || key == 'q') {
gx -= 1;
} else if (key == 'D' || key == 'd') {
gx += 1;
} else if (key == ' ') {
gy -= 1;
} else if (key == CODED && keyCode == CONTROL) {
gy += 1;
} else {
gy += 0;
}
}

if (mousePressed == true && mouseButton == RIGHT) {

rx += (mouseX-pmouseX);
ry -= (mouseY-pmouseY);
if (ry > 50) {
ry = 50;
} else if (ry < -50) {
ry = -50;
}
if (rx >= 200){
rx = 0+(rx-200);
} else if (rx <= -200){
rx = 0-(rx+200);
}
}

println("rx :" + rx);
println("ry :" + ry);
}

class Cube{
float x,y,z;

Cube(float tempX, float tempY, float tempZ){
x = tempX;
y = tempY;
z = tempZ;
}

void update(){
pushMatrix();
translate((width/2-gx),(height/2-gy),(-width/2-gz));
rotateX(ry/32);
rotateY(rx/32);
stroke(0);
strokeWeight(2);
fill(255);
beginShape();
fill(255);
vertex(x-100,y-100,z+100);
vertex(x+100,y-100,z+100);
vertex(x+100,y+100,z+100);
vertex(x-100,y+100,z+100);
endShape(CLOSE);

beginShape();
vertex(x-100,y-100,z+100);
vertex(x-100,y-100,z-100);
vertex(x-100,y+100,z-100);
vertex(x-100,y+100,z+100);
endShape(CLOSE);

beginShape();
vertex(x+100,y-100,z+100);
vertex(x+100,y-100,z-100);
vertex(x+100,y+100,z-100);
vertex(x+100,y+100,z+100);
endShape(CLOSE);

beginShape();
vertex(x-100,y-100,z-100);
vertex(x+100,y-100,z-100);
vertex(x+100,y+100,z-100);
vertex(x-100,y+100,z-100);
endShape(CLOSE);

beginShape();
vertex(x-100,y+100,z+100);
vertex(x-100,y+100,z-100);
vertex(x+100,y+100,z-100);
vertex(x+100,y+100,z+100);
endShape(CLOSE);

beginShape();
vertex(x-100,y-100,z+100);
vertex(x-100,y-100,z-100);
vertex(x+100,y-100,z-100);
vertex(x+100,y-100,z+100);
endShape(CLOSE);

popMatrix();
}
}
``````

This code makes me able to generates two cubes and to navigate around theme, as they are always the center of my screen.

Now I want to do it differently, instead of having the camera move around the cube, I want the cube to move around the camera to simulate a first person camera. It goes well when it is about moving in a three dimensional space, but when I add rotation (with mouse movement), I just don’t know how to have the cube move as if it were like Minecraft, for those who know the game.

Here what i’ve done :

MOUSE MOVEMENT

``````  if (mousePressed == true && mouseButton == RIGHT) {

rx += (mouseX-pmouseX);
ry -= (mouseY-pmouseY);
if (ry > 50) {
ry = 50;
} else if (ry < -50) {
ry = -50;
}
if (rx >= 200){
rx = 0+(rx-200);
} else if (rx <= -200){
rx = 0-(rx+200);
}
}
``````

And my cube class is basically the same as the one specified in the first script, except i changed the translation :

``````translate(x-gx,y-gy+ry*4,z-gz);
``````

But it doesn’t work well, and I can’t find how to do it.

Can anybody help me ?

2 Likes

Libraries

Okay, there are 2 libraries, Peasycam and QueasyCam

Command camera()

But you can also do manually what they do.

Look at the `camera()` command in the reference.

It comes with 9 parameters, but only the first 6 are interesting:

• 3 for position of the camera (eye) and
• 3 for lookAt (center)

https://www.processing.org/reference/camera_.html

Regards, Chrisir

3 Likes

a 3rd. option is still how you started,

and i could understand that,
even it might be not so comfortable like camera or a library
it has advantages, like you have full control over the code and function.
that is also the reason why i not retired my PTZ function, what actually is older
as today processing 3D view options.

you can take a look here

4 Likes

PTZ = pan tilt and zoom

1 Like

Thanks a lot ! Finally I used camera(), which seems to be simpler to use. But now I am facing another problem… I still want to make my 3d camera as if I were rotating my head. So I know I just have to change the lookAt positions.

But this is mainly a math problem, and I think I might have solved it using trigonometry, or at least I might have started solving it.

So for my Z-axis, I want the lookAt point to be exactly in front of my “eyes” when I move my mouse (well the camera moves with this point, so I want it to move on a sphere around my camera point so that I can look everywhere easily).

So I want to use cos(x) for my Z-axis, and I expect x to be equal to 0 when I’m looking straight ahead, so that the program returns 1 for cos(x). It works well. Now, when I look up or down, I want the lookAt point to move up or down, and of course to be perfectly parallel with my camera sticking point (on the z-axis).

Here is a simple drawing of what I want to do.

Horizontal axis : Z-Axis - Vertical axis : Y-Axis

The big red circle symbolizes the camera, the little black one symbolizes the initial lookAt point, and the green point symbolizes the lookAt point I want to get. As you can see, the green point is perfectly aligned with my camera, so I want its Z-position to be equal to cos(PI/2) which should be 0. Now, when I do it, it returns “-4.371139E-8” instead of 0, and I don’t know why. Cosinus with PI fractions seems to be not working.

Do you know a way to solve that problem ? Or do you know a simpler way to do what I want ?

Thank you very much

1 Like

I just tried to program this but I couldn’t upload it.

In 3D, normally the height above the surface is y, the left/right is x and the depth on the stage (in the room) is z. So the floor is in the x/z plane, walls go up y.

So you want

``````lookAtX = posX + cos(angle) * 10;
lookAtY = 500;
lookAtZ = posY + sin(angle) * 10;

angle = map (mouseX, 0, width, 0, 3*PI);
``````

camera(posX,posY…
lookAtX,lookAtY…
0,1,0);

1 Like
``````

// CONSTANT: the floor / field (y value)
final int GENERAL_Y_HEIGHT = 500-66;

// Classes: The camera
CameraClass cam;

// The scene (background, field, boxes...)
Scene scene = new Scene();

// minor tools
Tools tools = new Tools();

// angle
float angle;

// -----------------------------------------------------

void setup() {
size (1400, 800, P3D);

// setup camera
cam = new CameraClass (  313,
GENERAL_Y_HEIGHT,
113 );

// avoid clipping : https : // forum.processing.org/two/discussion/4128/quick-q-how-close-is-too-close-why-when-do-3d-objects-disappear
perspective(PI/3.0, (float) width/height, 1, 1000000);
} // func

void draw() {
// set Canvas and Environment
scene.setCanvasAndEnvironment();

angle=map(mouseX, 0, width, 0, 3*PI);

// camera
cam.setLookAt();   //
cam.set();    // apply the values of the class cam to the real camera

// display the scene with the boxes and HUD text
scene.displayScene();
//
} // func draw

// ---------------------------------------------------

void keyPressed() {
switch(key) {
case 'e':
//
break;
}
}

// =================================================================
// classes

class Scene {

// cubes
float angleCubes=45; // angle for the cubes in the scene

void setCanvasAndEnvironment() {
// set Canvas and Environment

// clear canvas
background(111);

// apply lights
lights();
}

void displayScene() {

// Drawing of the scene / decoration

// Drawing of the red field  ----
fill(255, 2, 2);//RED
noStroke();
tools.mySphere(500, GENERAL_Y_HEIGHT, 500, 20);
tools.mySphere(100, GENERAL_Y_HEIGHT, 100, 20);
tools.mySphere(100, GENERAL_Y_HEIGHT, 500, 20);
tools.mySphere(500, GENERAL_Y_HEIGHT, 100, 20);

// rect of lines
stroke(255, 2, 2);//RED
// using 3D lines:
line(500, GENERAL_Y_HEIGHT, 500, 500, GENERAL_Y_HEIGHT, 100);  // up |
line(500, GENERAL_Y_HEIGHT, 100, 100, GENERAL_Y_HEIGHT, 100);  // left <-
line(100, GENERAL_Y_HEIGHT, 100, 100, GENERAL_Y_HEIGHT, 500 ); // down |
line(100, GENERAL_Y_HEIGHT, 500, 500, GENERAL_Y_HEIGHT, 500 ); // right ->

// one small wall of boxes
stroke(0);
int z = -60;
for (int x = 10; x < 600; x+= 100) {
fill(x/3, 2, 2);
for (int y = 410; y < 600; y+= 100) {
tools.myBox(x, y, z, 24, angleCubes);
}
}

// a few additional blue boxes
fill(0, 0, 255);
z=-400;
tools.myBox(220, 10, z, 24, angleCubes);
tools.myBox(600, 10, z, 24, angleCubes);
z=-400;
tools.myBox(220, 510, z, 24, angleCubes);
tools.myBox(600, 510, z, 24, angleCubes);
z=399;
tools.myBox(220, 510, z, 24, angleCubes);
tools.myBox(600, 510, z, 24, angleCubes);
z=900;
tools.myBox(220, 510, z, 24, angleCubes);
tools.myBox(600, 510, z, 24, angleCubes);
angleCubes++;
//

// text upper left corner (HUD)
fill(0, 255, 0);
cam.HUD_text("Test " );  //
}
//
} // class

// =================================================================

class CameraClass {

// capsules the normal camera() command and its vectors

PVector camPos;     // its vectors
PVector camLookAt;
PVector camUp;

PVector camPosInitial;     // its vectors - the default (unchanged)
PVector camLookAtInitial;
PVector camUpInitial;

float angleForCamerasUpAndDownMovement=0;   // angle for the slight up and down movement of the camera

// constructor I - without parameters
CameraClass() {
// constr
// set vectors
camPos    = new PVector(width/2.0, height/2.0, 990);
camLookAt = new PVector(width/2.0, height/2.0, -600);
camUp     = new PVector( 0, 1, 0 );
// save the initial values
camPosInitial    = camPos.copy();
camLookAtInitial = camLookAt.copy();
camUpInitial     = camUp.copy();
}  // constr I

// constructor II - with parameters for POS
CameraClass (float x1, float y1, float z1) {
// constr
// set vectors
camPos    = new PVector(x1, y1, z1);
camLookAt = new PVector(width/2.0, height/2.0, -600);
camUp     = new PVector( 0, 1, 0 );
// save the initial values
camPosInitial    = camPos.copy();
camLookAtInitial = camLookAt.copy();
camUpInitial     = camUp.copy();

camPos = new PVector(x1, y1, z1);
}  // constr II

// ----------------------------------------

void set() {
// apply internal class vectors to actual camera
camera (camPos.x, camPos.y, camPos.z,
camLookAt.x, camLookAt.y, camLookAt.z,
camUp.x, camUp.y, camUp.z);
}

void setPos (float x1, float y1, float z1) {
camPos = new PVector(x1, y1, z1);
}

void setLookAt () {
// from angle
float x1 = camPos.x+ cos(angle) *10 ;
float y1 = GENERAL_Y_HEIGHT;
float z1 = camPos.z + sin(angle) *10 ;
camLookAt.set(x1, y1, z1);
}

void HUD_text (String a1) {
// HUD text upper left corner - this must be called at the very end of draw()
// this is a 2D HUD
camera();
hint(DISABLE_DEPTH_TEST);
noLights();
// ------------------
textSize(16);
text (a1, 20, 20);
// ------------------
// reset all parameters to defaults
textAlign(LEFT, BASELINE);
rectMode(CORNER);
textSize(32);
hint(ENABLE_DEPTH_TEST); // no HUD anymore
lights();
} // method
//
} // class

// ======================================

class Tools {
// tools

void myBox(float x, float y, float z,
float size1,
float angleCube) {
// one nice wrapper for build in box-command
pushMatrix();
translate(x, y, z);
box(size1);
popMatrix();
}

void mySphere(float x, float y, float z,
float size1) {
// one nice wrapper for build in sphere-command
pushMatrix();
translate(x, y, z);
sphere(size1);
popMatrix();
}
}//class
//
``````
1 Like

and a version with wasd keys for moving the player (like in a first person shooter, FPS)

``````// CONSTANT: the floor / field (y value)
final int GENERAL_Y_HEIGHT = 500;

// Classes: The camera
CameraClass cam;

// The scene (background, field, boxes...)
Scene scene = new Scene();

// minor tools
Tools tools = new Tools();

// angles
float angleLeftRight;
float angleUpDown=GENERAL_Y_HEIGHT-66;  // not a real angle!!!

// -----------------------------------------------------

void setup() {
size (1400, 800, P3D);

// setup camera
cam = new CameraClass (313,
GENERAL_Y_HEIGHT - 66,
113);

// avoid clipping : https : // forum.processing.org/two/discussion/4128/quick-q-how-close-is-too-close-why-when-do-3d-objects-disappear
perspective(PI/3.0, (float) width/height, 1, 1000000);
} // func

void draw() {
// set Canvas and Environment
scene.setCanvasAndEnvironment();

angleLeftRight=map(mouseX, 0, width, 0, 3*PI);
//  angleUpDown=map(mouseY, 0, height, GENERAL_Y_HEIGHT-150, GENERAL_Y_HEIGHT+150);// not a real angle!!!
if (pmouseY<mouseY-5)
angleUpDown += .21;
else if (pmouseY>mouseY+5)
angleUpDown += -.21;

// camera
cam.setLookAt();   //
cam.set();    // apply the values of the class cam to the real camera

// display the scene with the boxes and HUD text
scene.displayScene();

cam.keyPressed();
//
} // func draw

// ---------------------------------------------------

void keyPressed() {
//
if (key=='r') {
angleUpDown=GENERAL_Y_HEIGHT-66;  // not a real angle!!!
}
}

// =================================================================
// classes

class Scene {

// cubes
float angleLeftRightCubes=45; // angleLeftRight for the cubes in the scene

void setCanvasAndEnvironment() {
// set Canvas and Environment

// clear canvas
background(111);

// apply lights
lights();
}

void displayScene() {

// Drawing of the scene / decoration

// Drawing of the red field  ----
fill(255, 2, 2);//RED
noStroke();
tools.mySphere(500, GENERAL_Y_HEIGHT, 500, 20);
tools.mySphere(100, GENERAL_Y_HEIGHT, 100, 20);
tools.mySphere(100, GENERAL_Y_HEIGHT, 500, 20);
tools.mySphere(500, GENERAL_Y_HEIGHT, 100, 20);

// rect of lines
stroke(255, 2, 2);//RED
// using 3D lines:
line(500, GENERAL_Y_HEIGHT, 500, 500, GENERAL_Y_HEIGHT, 100);  // up |
line(500, GENERAL_Y_HEIGHT, 100, 100, GENERAL_Y_HEIGHT, 100);  // left <-
line(100, GENERAL_Y_HEIGHT, 100, 100, GENERAL_Y_HEIGHT, 500 ); // down |
line(100, GENERAL_Y_HEIGHT, 500, 500, GENERAL_Y_HEIGHT, 500 ); // right ->

// one small wall of boxes
stroke(0);
int z = -60;
for (int x = 10; x < 600; x+= 100) {
fill(x/3, 2, 2);
for (int y = 410; y < 600; y+= 100) {
tools.myBox(x, y, z, 24, angleLeftRightCubes);
}
}

// a few additional blue boxes
fill(0, 0, 255);
z=-400;
tools.myBox(220, 10, z, 24, angleLeftRightCubes);
tools.myBox(600, 10, z, 24, angleLeftRightCubes);
z=-400;
tools.myBox(220, 510, z, 24, angleLeftRightCubes);
tools.myBox(600, 510, z, 24, angleLeftRightCubes);
z=399;
tools.myBox(220, 510, z, 24, angleLeftRightCubes);
tools.myBox(600, 510, z, 24, angleLeftRightCubes);
z=900;
tools.myBox(220, 510, z, 24, angleLeftRightCubes);
tools.myBox(600, 510, z, 24, angleLeftRightCubes);
angleLeftRightCubes++;
//

// text upper left corner (HUD)
fill(0, 255, 0);
cam.HUD_text("Test " );  //
}
//
} // class

// =================================================================

class CameraClass {

// capsules the normal camera() command and its vectors

PVector camPos;     // its vectors
PVector camLookAt;
PVector camUp;

PVector camPosInitial;     // its vectors - the default (unchanged)
PVector camLookAtInitial;
PVector camUpInitial;

//  float angleLeftRightForCamerasUpAndDownMovement=0;   // angleLeftRight for the slight up and down movement of the camera

// constructor I - without parameters
CameraClass() {
// constr
// set vectors
camPos    = new PVector(width/2.0, height/2.0, 990);
camLookAt = new PVector(width/2.0, height/2.0, -600);
camUp     = new PVector( 0, 1, 0 );
// save the initial values
camPosInitial    = camPos.copy();
camLookAtInitial = camLookAt.copy();
camUpInitial     = camUp.copy();
}  // constr I

// constructor II - with parameters for POS
CameraClass (float x1, float y1, float z1) {
// constr
// set vectors
camPos    = new PVector(x1, y1, z1);
camLookAt = new PVector(width/2.0, height/2.0, -600);
camUp     = new PVector( 0, 1, 0 );
// save the initial values
camPosInitial    = camPos.copy();
camLookAtInitial = camLookAt.copy();
camUpInitial     = camUp.copy();

camPos = new PVector(x1, y1, z1);
}  // constr II

// ----------------------------------------

void set() {
// apply internal class vectors to actual camera
camera (camPos.x, camPos.y, camPos.z,
camLookAt.x, camLookAt.y, camLookAt.z,
camUp.x, camUp.y, camUp.z);
}

void setPos (float x1, float y1, float z1) {
camPos = new PVector(x1, y1, z1);
}

void setLookAt () {
// from angleLeftRight
float x1 = camPos.x + cos(angleLeftRight) *10;
float y1 = angleUpDown;   // GENERAL_Y_HEIGHT;
float z1 = camPos.z + sin(angleLeftRight) *10;
camLookAt.set(x1, y1, z1);
}

void keyPressed() {
if (!keyPressed)
return;

switch(key) {

case 'w':
// run forward / running towards lookat
float x1 = camPos.x + cos(angleLeftRight) *1;
float z1 = camPos.z + sin(angleLeftRight) *1;
camPos.set(x1, camPos.y, z1);
break;

case 's':
// run backward
x1 = camPos.x - cos(angleLeftRight) *1;
z1 = camPos.z - sin(angleLeftRight) *1;
camPos.set(x1, camPos.y, z1);
break;

case 'a':
// left / sideways
x1 = camPos.x + cos(angleLeftRight-HALF_PI) * 1;
z1 = camPos.z + sin(angleLeftRight-HALF_PI) * 1;
camPos.set(x1, camPos.y, z1);
break;

case 'd':
// right
x1 = camPos.x - cos(angleLeftRight-HALF_PI) * 1;
z1 = camPos.z - sin(angleLeftRight-HALF_PI) * 1;
camPos.set(x1, camPos.y, z1);
break;
}//switch
}// method

void HUD_text (String text_) {
// HUD text upper left corner - this must be called at the very end of draw()
// this is a 2D HUD
camera();
hint(DISABLE_DEPTH_TEST);
noLights();
// ------------------
textSize(16);
text (text_, 20, 20);
// ------------------
// reset all parameters to defaults
textAlign(LEFT, BASELINE);
rectMode(CORNER);
textSize(32);
hint(ENABLE_DEPTH_TEST); // no HUD anymore
lights();
} // method
//
} // class

// ======================================

class Tools {
// tools

void myBox(float x, float y, float z,
float size1,
float angleLeftRightCube) {
// one nice wrapper for build in box-command
pushMatrix();
translate(x, y, z);
box(size1);
popMatrix();
}

void mySphere(float x, float y, float z,
float size1) {
// one nice wrapper for build in sphere-command
pushMatrix();
translate(x, y, z);
sphere(size1);
popMatrix();
}
}//class
//
``````
2 Likes

Thank you so much . It will take some time to try to understand everything you wrote but it works perfectly.
One very last question, do you know how to lock the mouse inside the window ?

So that you can move your camera without having the mouse come out of the window and stopping the movement. I’ve seen some people using the Robot class, but I didn’t find anything well-working.

I think that the robot class is the way to go

1 Like

Will use it ! Thank you for everything

in this new version you can either

• look around (FPS) with mouse and “wasd” keys OR
• let the camera fly around a spot in front of you (denoted by a green sphere)

Toggle with r

Chrisir

``````// CONSTANT: the floor / field (y value)
final int GENERAL_Y_HEIGHT = 500;

// rotate around itself (player, FPS) OR around a point
boolean modeCamRotatesAroundPoint = false;

// Classes: The camera
CameraClass cam;

// The scene (background, field, boxes...)
Scene scene = new Scene();

// minor tools
Tools tools = new Tools();

// angles
float angleLeftRight;
float angleUpDown=GENERAL_Y_HEIGHT-66;  // not a real angle!!!

float modeCamRotatesAroundPointAngle;
PVector spherePosPV=new PVector(0, GENERAL_Y_HEIGHT-500, 0);
float prevAngle;

// -----------------------------------------------------

void setup() {
size (1400, 800, P3D);

// setup camera
cam = new CameraClass (313,
GENERAL_Y_HEIGHT - 66,
113);

// avoid clipping : https : // forum.processing.org/two/discussion/4128/quick-q-how-close-is-too-close-why-when-do-3d-objects-disappear
perspective(PI/3.0, (float) width/height, 1, 1000000);
} // func

void draw() {
// set Canvas and Environment
scene.setCanvasAndEnvironment();

if (modeCamRotatesAroundPoint) {
// show Cam Rotates Around Point
showModeCamRotatesAroundPoint();
} else {
// first person shooter perspective (FPS)
showFPS();
}//else

// display the scene with the boxes and HUD text
scene.displayScene();
//
} // func draw

// ---------------------------------------------------

void showModeCamRotatesAroundPoint() {
// rotate around a point
cam.setPosAngle(modeCamRotatesAroundPointAngle);
cam.set();    // apply the values of the class cam to the real camera

tools.mySphere(spherePosPV.x, spherePosPV.y, spherePosPV.z,
7);

if (spherePosPV.y >= GENERAL_Y_HEIGHT) {
spherePosPV.y=GENERAL_Y_HEIGHT;
modeCamRotatesAroundPointAngle+=.032;
} else {
// sphere falls
spherePosPV.y+=10;
}//
}

void showFPS() {
// rotate around itself (player, FPS)
angleLeftRight=map(mouseX, 0, width, 0, 3*PI);
//  angleUpDown=map(mouseY, 0, height, GENERAL_Y_HEIGHT-150, GENERAL_Y_HEIGHT+150);// not a real angle!!!
if (pmouseY<mouseY-5)
angleUpDown += .21;
else if (pmouseY>mouseY+5)
angleUpDown += -.21;

// camera
cam.setLookAtAngle(angleLeftRight);   //
cam.set();    // apply the values of the class cam to the real camera

// sphere disappears
if (spherePosPV.y < GENERAL_Y_HEIGHT-310) {
// do nothing
} else {
// sphere
spherePosPV.y-=10;
tools.mySphere(spherePosPV.x, spherePosPV.y, spherePosPV.z,
7);
}//else
cam.keyPressedThroughout();
}//func

// ---------------------------------------------------

void keyPressed() {

//
if (key=='r') {
// Toggle: FPS OR cam rotates AROUND a point
modeCamRotatesAroundPoint =
! modeCamRotatesAroundPoint;  // toggle

// modeCamRotatesAroundPoint has a new value now,
// it's a new mode so we can set some start conditions for the new mode.
if (modeCamRotatesAroundPoint) {
// starting mode: modeCamRotatesAroundPoint

prevAngle=angleLeftRight;
modeCamRotatesAroundPointAngle=angleLeftRight-PI;
// define camera
float x1 = cam.camPos.x + cos(angleLeftRight) *300;
float y1 = angleUpDown;   // GENERAL_Y_HEIGHT;
float z1 = cam.camPos.z + sin(angleLeftRight) *300;
cam.setLookAt(x1, y1, z1);
// define sphere
spherePosPV=cam.camLookAt.copy();
spherePosPV.y=GENERAL_Y_HEIGHT-310;
} else {
// starting mode PVS
angleLeftRight=modeCamRotatesAroundPointAngle;
float x1 = cam.camLookAt.x - cos(prevAngle) *300;
float y1 = angleUpDown;   // GENERAL_Y_HEIGHT;
float z1 = cam.camLookAt.z - sin(prevAngle) *300;
cam.camPos.set(x1, y1, z1); // =cam.camLookAt.copy();
}
//
} else if (key==ESC) {
modeCamRotatesAroundPoint = false;
key=0; // kill ESC
}// else if
}//func

// =================================================================
// classes

class Scene {

// cubes
float angleLeftRightCubes=45; // angleLeftRight for the cubes in the scene

void setCanvasAndEnvironment() {
// set Canvas and Environment

// clear canvas
background(111);

// apply lights
lights();
}

void displayScene() {

// Drawing of the scene / decoration

// Drawing of the red field  ----
fill(255, 2, 2);//RED
noStroke();
tools.mySphere(500, GENERAL_Y_HEIGHT, 500, 20);
tools.mySphere(100, GENERAL_Y_HEIGHT, 100, 20);
tools.mySphere(100, GENERAL_Y_HEIGHT, 500, 20);
tools.mySphere(500, GENERAL_Y_HEIGHT, 100, 20);

// rect of lines  / floor / field
stroke(255, 2, 2);//RED
// using 3D lines:
line(500, GENERAL_Y_HEIGHT, 500, 500, GENERAL_Y_HEIGHT, 100);  // up |
line(500, GENERAL_Y_HEIGHT, 100, 100, GENERAL_Y_HEIGHT, 100);  // left <-
line(100, GENERAL_Y_HEIGHT, 100, 100, GENERAL_Y_HEIGHT, 500 ); // down |
line(100, GENERAL_Y_HEIGHT, 500, 500, GENERAL_Y_HEIGHT, 500 ); // right ->

// one small wall of boxes
stroke(0);
int z = -60;
for (int x = 10; x < 600; x+= 100) {
fill(map(x, 10, 600, 111, 255), 2, 2);
for (int y = 410; y < 600; y+= 100) {
tools.myBox(x, y, z, 24, angleLeftRightCubes);
}
}

// a few additional blue boxes
fill(0, 0, 255);
z=-400;
tools.myBox(220, 10, z, 24, angleLeftRightCubes);
tools.myBox(600, 10, z, 24, angleLeftRightCubes);
z=-400;
tools.myBox(220, 510, z, 24, angleLeftRightCubes);
tools.myBox(600, 510, z, 24, angleLeftRightCubes);
z=399;
tools.myBox(220, 510, z, 24, angleLeftRightCubes);
tools.myBox(600, 510, z, 24, angleLeftRightCubes);
z=900;
tools.myBox(220, 510, z, 24, angleLeftRightCubes);
tools.myBox(600, 510, z, 24, angleLeftRightCubes);
angleLeftRightCubes++;
//

// text upper left corner (HUD)
fill(0, 255, 0);
cam.HUD_text("Use Mouse. Click r to toggle mode. " );  //
}
//
} // class

// =================================================================

class CameraClass {

// capsules the normal camera() command and its vectors

PVector camPos;     // its vectors
PVector camLookAt;
PVector camUp;

PVector camPosInitial;     // its vectors - the default (unchanged)
PVector camLookAtInitial;
PVector camUpInitial;

//  float angleLeftRightForCamerasUpAndDownMovement=0;   // angleLeftRight for the slight up and down movement of the camera

// constructor I - without parameters
CameraClass() {
// constr
// set vectors
camPos    = new PVector(width/2.0, height/2.0, 990);
camLookAt = new PVector(width/2.0, height/2.0, -600);
camUp     = new PVector( 0, 1, 0 );
// save the initial values
camPosInitial    = camPos.copy();
camLookAtInitial = camLookAt.copy();
camUpInitial     = camUp.copy();
}  // constr I

// constructor II - with parameters for POS
CameraClass (float x1, float y1, float z1) {
// constr
// set vectors
camPos    = new PVector(x1, y1, z1);
camLookAt = new PVector(width/2.0, height/2.0, -600);
camUp     = new PVector( 0, 1, 0 );
// save the initial values
camPosInitial    = camPos.copy();
camLookAtInitial = camLookAt.copy();
camUpInitial     = camUp.copy();

camPos = new PVector(x1, y1, z1);
}  // constr II

// ----------------------------------------

void set() {
// apply internal class vectors to actual camera
camera (camPos.x, camPos.y, camPos.z,
camLookAt.x, camLookAt.y, camLookAt.z,
camUp.x, camUp.y, camUp.z);
}

// ----------------------------------------

void setPos (float x1, float y1, float z1) {
camPos.set(x1, y1, z1);
}

void setLookAt (float x1, float y1, float z1) {
camLookAt.set(x1, y1, z1);
}

// ----------------------------------------

void setPosAngle (float angle_) {
// look to point while rotating around it
//
float x1 = camLookAt.x + cos(angle_) *300;
float y1 = angleUpDown;   // GENERAL_Y_HEIGHT;
float z1 = camLookAt.z + sin(angle_) *300;
camPos.set(x1, y1, z1);
}

void setLookAtAngle (float angleLeftRight) {
// FPS
// from angleLeftRight
float x1 = camPos.x + cos(angleLeftRight) *10;
float y1 = angleUpDown;   // GENERAL_Y_HEIGHT;
float z1 = camPos.z + sin(angleLeftRight) *10;
camLookAt.set(x1, y1, z1);
}

// ----------------------------------------

void keyPressedThroughout() {

if (!keyPressed)
return;

switch(key) {

case 'w':
// run forward / running towards lookat
float x1 = camPos.x + cos(angleLeftRight) *1;
float z1 = camPos.z + sin(angleLeftRight) *1;
camPos.set(x1, camPos.y, z1);
break;

case 's':
// run backward
x1 = camPos.x - cos(angleLeftRight) *1;
z1 = camPos.z - sin(angleLeftRight) *1;
camPos.set(x1, camPos.y, z1);
break;

case 'a':
// left / sideways
x1 = camPos.x + cos(angleLeftRight-HALF_PI) * 1;
z1 = camPos.z + sin(angleLeftRight-HALF_PI) * 1;
camPos.set(x1, camPos.y, z1);
break;

case 'd':
// right
x1 = camPos.x - cos(angleLeftRight-HALF_PI) * 1;
z1 = camPos.z - sin(angleLeftRight-HALF_PI) * 1;
camPos.set(x1, camPos.y, z1);
break;
}//switch
}// method

void HUD_text (String text_) {
// HUD text upper left corner - this must be called at the very end of draw()
// this is a 2D HUD
camera();
hint(DISABLE_DEPTH_TEST);
noLights();
// ------------------
textSize(16);
text (text_, 20, 20);
// ------------------
// reset all parameters to defaults
textAlign(LEFT, BASELINE);
rectMode(CORNER);
textSize(32);
hint(ENABLE_DEPTH_TEST); // no HUD anymore
lights();
} // method
//
} // class

// ======================================

class Tools {
// tools

void myBox(float x, float y, float z,
float size1,
float angleLeftRightCube) {
// one nice wrapper for build in box-command
pushMatrix();
translate(x, y, z);
box(size1);
popMatrix();
}

void mySphere(float x, float y, float z,
float size1) {
// one nice wrapper for build in sphere-command
pushMatrix();
noStroke();
translate(x, y, z);
sphere(size1);
popMatrix();
}
}//class
//
``````
2 Likes