# First-person camera (3D)

**URL:** <https://discourse.processing.org/t/first-person-camera-3d/42082>\
**Category:** Coding Questions\
**Created:** [May 26, 2023, 6:31pm UTC](https://discourse.processing.org/t/first-person-camera-3d/42082 "2023-05-26T18:31:58Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![09husky](https://avatars.discourse-cdn.com/v4/letter/0/4af34b/32.png) [@09husky](https://discourse.processing.org/u/09husky)\
**Post date:** [May 26, 2023, 6:31pm UTC](https://discourse.processing.org/t/first-person-camera-3d/42082/1 "2023-05-26T18:31:58Z")

</div>

My first-person camera code is having the following problems: changing the [starting] position of the camera makes the reference sphere disappear, replaced by a white screen; when playing around with the commented-out “box crosshair” code at the bottom, I discovered the point I’m looking at is getting closer and farther from me based on where I’m looking up or down, instead of a perfect sphere of distance as it should be, and the push and pop matrix code at the bottom just completely breaks everything if both are running:

```plaintext
PVector pos = new PVector(w/2, h/2, 50);
PVector lookDir = new PVector(0, pos.z);

void setup() {
  background(240);
}

void settings(){
  size(w, h, P3D);
}

void look(){
  if(keyPressed){
    if(key == CODED){
      if(keyCode == RIGHT){
        if (lookDir.x == 359){
          lookDir.x = 0;
        }
        else{
          lookDir.x += 1;
        }
        println("right");
      }
      if(keyCode == LEFT){
        if (lookDir.x == 0){
          lookDir.x = 359;
        }
        else{
          lookDir.x -= 1;
        }
        println("left");
      }
      if(keyCode == UP){
        if (lookDir.y == 89){
          lookDir.y = 89;
        }
        else{
          lookDir.y += 1;
        }
        print(lookDir.y);
        println("up");
    }
    if(keyCode == DOWN){
        if (lookDir.y == -269){
          lookDir.y = -269;
        }
        else{
          lookDir.y -= 1;
        }
        print(lookDir.y);
        println("down");
      }
    }
  }
}

void draw() {
  background(240);
  pushMatrix();
  translate(width/2, height/2);
  stroke(20);
  sphere(200);
  popMatrix();
  look();
  perspective(PI/3.0, width/height, pos.z, pos.z*10);
  //pushMatrix();
  camera(pos.x, pos.y, pos.z, pos.x+cos(radians(lookDir.x))*(10-sin(radians(lookDir.y))*10), pos.y+sin(radians(lookDir.x))*(10-sin(radians(lookDir.y))*10), pos.z+cos(radians(lookDir.y))*10, 0, 0, -1);
  //translate(pos.x+cos(radians(lookDir.x))*(10-sin(radians(lookDir.y))*10), pos.y+sin(radians(lookDir.x))*(10-sin(radians(lookDir.y))*10), pos.z+cos(radians(lookDir.y))*10);
  //box(3);
  //popMatrix();
}

```

If anyone can help me with any of this, that would be amazing. Thanks!

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [May 26, 2023, 9:05pm UTC](https://discourse.processing.org/t/first-person-camera-3d/42082/2 "2023-05-26T21:05:10Z")

</div>

USE w and s and mouse

you run where you look (so steer with the mouse)

```auto

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

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

int w = 1200;
int h = 900;

PVector pos = new PVector(300, GENERAL_Y_HEIGHT, 250);

float lookAngleLeftAndRight, // angle 
   lookAngleUpAndDown; // not an angle 

void setup() {
  background(240);
  // noCursor();
  mouseX=width/10*12;
}

void settings() {
  size(w, h, P3D);
}

void draw() {
  background(240);
  avoidClipping();
  lights();

  lookAngleLeftAndRight = map(mouseX,
    0, width,
    -470, 580);

  lookAngleUpAndDown = map(mouseY,
    0, height,
    GENERAL_Y_HEIGHT - 22 - 13, GENERAL_Y_HEIGHT -22 + 13 );

  camera(pos.x, GENERAL_Y_HEIGHT-22, pos.z,
    pos.x+cos(radians(lookAngleLeftAndRight))*3, lookAngleUpAndDown, pos.z+sin(radians(lookAngleLeftAndRight))*3,
    0, 1, 0);

  scene();

  readkeysThroughout();

  // Init 2D part: ------------------------------------------------------------------
  hint(DISABLE_DEPTH_TEST);
  camera();
  noLights();
  // 2D part:
  stroke(0);
  line(width/2, height/2-22,
    width/2, height/2+22);
  line(width/2-22, height/2,
    width/2+22, height/2);
  hint(ENABLE_DEPTH_TEST); // reset to 3D
}

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

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

  if (key != CODED) {
    switch(key) {
    case 'w':
      pos.x+=cos(radians(lookAngleLeftAndRight))*3;
      pos.z+=sin(radians(lookAngleLeftAndRight))*3;
      break;
    case 's':
      pos.x-=cos(radians(lookAngleLeftAndRight))*3;
      pos.z-=sin(radians(lookAngleLeftAndRight))*3;
      break;
    case'a':
      // to do
      break;
    case'd':
      // to do
      break;
    }//switch
    //
    return; // leave
  }//if

  // from now on all is coded ---------------------

  if (keyCode == RIGHT) {
    println("right");
  } else if (keyCode == LEFT) {
    println("left");
  } else if (keyCode == UP) {
    println("up");
  } else if (keyCode == DOWN) {
    println("down");
  }
}

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

void scene() {

  // scene
  // 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) {
      myBox(x, y, z, 24, angleLeftRightCubes);
    }
  }

  pushMatrix();
  translate(width/2, GENERAL_Y_HEIGHT-22, height/2);
  //stroke(20);
  noStroke();
  fill( 0, 222, 0); // green
  sphere(22);
  popMatrix();

  pushMatrix();
  translate(0, GENERAL_Y_HEIGHT-22, 0);
  //stroke(20);
  noStroke();
  fill( 0, 0, 222); // blue
  sphere(22);
  popMatrix();

  pushMatrix();
  translate(width/2, GENERAL_Y_HEIGHT-22, 0);
  //stroke(20);
  noStroke();
  fill( 222, 0, 0); // red
  sphere(22);
  popMatrix();
}

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);
  rotateY(radians(angleLeftRightCube));
  rotateX(radians(45));
  box(size1);
  popMatrix();
}

void avoidClipping() {
  // avoid clipping (at camera):
  // 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
//

```

---

<div class="post-metadata">

**Author:** ![Chrisir](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/chrisir/32/45_2.png) [@Chrisir](https://discourse.processing.org/u/Chrisir)\
**Post date:** [May 26, 2023, 9:08pm UTC](https://discourse.processing.org/t/first-person-camera-3d/42082/3 "2023-05-26T21:08:49Z")

</div>

**Remarks 1**

- Check out library QuasyCam
- Problem that the mouse gets over the screen border left or right: There is a Robot class to handle this. I dunno.

**Remarks 2**

I removed `perspective()` command

I used the default camera orientation _0, 1, 0_ from [camera() / Reference / Processing.org](https://processing.org/reference/camera_.html)

- so Y is up (above the red floor rectangle) (when you would jump)

- and x and z is the plane where we run around (right/left and forward backward)

- `translate()` needs 3 parameters in 3D, `line()` needs 6

- cross hair is drawn in a HUD (a 2D section in a 3D Sketch, see also Wikipedia) - see #9: “ **9. combining 2D and 3D drawing** ” of [25 life-saving tips for Processing | Amnon P5 - Experiments with Processing by Amnon Owed](https://amnonp5.wordpress.com/2012/01/28/25-life-saving-tips-for-processing/)

> [@09husky](#):
>
> changing the [starting] position of the camera makes the reference sphere disappear, replaced by a white screen

Probably you’ve been inside the sphere. Sphere too big.

---

<div class="post-metadata">

**Author:** ![scudly](https://yyz2.discourse-cdn.com/flex036/user_avatar/discourse.processing.org/scudly/32/5597_2.png) [@scudly](https://discourse.processing.org/u/scudly)\
**Post date:** [May 27, 2023, 12:08am UTC](https://discourse.processing.org/t/first-person-camera-3d/42082/4 "2023-05-27T00:08:28Z")

</div>

You are not using `perspective()` quite correctly. The 3rd and 4th parameters are the near and far clipping distances which are relative to the camera. If you had them set to say, 1 and 10 then you would only see geometry that is between 1 and 10 units away in front of whatever direction the camera is facing – anything closer or further away is cut off.

In your case, setting the near clipping distance to the camera z position means that anything between you and the origin is cut off which is likely not what you want. If your camera is 50 away from the origin, then try setting the near distance to 1 and the far to 500.

In theory, we would like the near and far distances to be 0 and infinity, but the graphics hardware has to map the pixels of the triangles that are drawn with depth values that are between the near and far to integer values stored in the depth buffer. If you give too big of a near-far range, the integer mapping loses precision and triangles at different distances start flickering through each other which is called z-fighting. It’s usually safe to make the far distance pretty big, but try to avoid making the near too small. Just be sure the near is small enough that it stays less than the distance from your camera to the nearest objects as you move around.
