backface culling and peasycam
in
Contributed Library Questions
•
14 days ago
I'm making a stereoscopic image.
Therefor i don't need backfaces to be drawn.
I'm using some code from the processing wiki:
Only instead of making a vector class i use PVector.
The thing is i need an export to pdf, so opengl backface culling is no option.
It works pretty good but pretty often certain faces don't appear.
Why is this, and what can be done about it?
- import peasy.*;
- PeasyCam cam;
- void setup() {
- size(1024, 768, OPENGL);
- cam = new PeasyCam(this, 400);
- }
- void draw() {
- background(255);
- // first red
- noFill();
- stroke(255, 0, 0);
- drawBoxes();
- // stereoscopic
- float offsetX = map(mouseX, 0, width, -50, 50);
- cam.pan(offsetX, 0);
- stroke(0, 0, 255);
- drawBoxes();
- // reset else things animate out of screen
- cam.pan(-offsetX, 0);
- }
- void drawBoxes() {
- randomSeed(1);
- int nBoxes = 100;
- for (int i = 0; i < nBoxes; i++) {
- pushMatrix();
- translate(random(-width, width), random(-width, width), random(-width, width));
- float[] pos = cam.getPosition();
- PVector camPos = new PVector(pos[0], pos[1], pos[2]);
- //box(random(10, 100));
- rgbBox(random(10, 100), camPos);
- popMatrix();
- }
- }
- void rgbBox(float size, PVector camPos) {
- rgbBox(size, size, size, camPos);
- }
- void rgbBox(float w, float h, float d, PVector camPos) {
- float x1 = -w/2f;
- float x2 = w/2f;
- float y1 = -h/2f;
- float y2 = h/2f;
- float z1 = -d/2f;
- float z2 = d/2f;
- PVector a = new PVector();
- PVector b = new PVector();
- PVector c = new PVector();
- PVector[] face = new PVector[3];
- face[0] = a;
- face[1] = b;
- face[2] = c;
- // 3 doesnt exist
- int mode = 3;
- // front
- if (mode == 1) {
- fill(255, 0, 0);
- }
- else if (mode == 2) {
- fill(nextColor());
- }
- a.set(x1, y1, z1);
- b.set(x2, y1, z1);
- c.set(x2, y2, z1);
- if (!visible(camPos, face)) {
- beginShape();
- normal(0, 0, 1);
- vertex(x1, y1, z1);
- vertex(x2, y1, z1);
- vertex(x2, y2, z1);
- vertex(x1, y2, z1);
- endShape(CLOSE);
- }
- // right
- if (mode == 1) {
- fill(0, 255, 0);
- }
- else if (mode == 2) {
- fill(nextColor());
- }
- a.set(x2, y1, z1);
- b.set(x2, y1, z2);
- c.set(x2, y2, z2);
- if (!visible(camPos, face)) {
- beginShape();
- normal(1, 0, 0);
- vertex(x2, y1, z1);
- vertex(x2, y1, z2);
- vertex(x2, y2, z2);
- vertex(x2, y2, z1);
- endShape(CLOSE);
- }
- // back
- if (mode == 1) {
- fill(255, 0, 0);
- }
- else if (mode == 2) {
- fill(nextColor());
- }
- a.set(x2, y1, z2);
- b.set(x1, y1, z2);
- c.set(x1, y2, z2);
- if (!visible(camPos, face)) {
- beginShape();
- normal(0, 0, -1);
- vertex(x2, y1, z2);
- vertex(x1, y1, z2);
- vertex(x1, y2, z2);
- vertex(x2, y2, z2);
- endShape(CLOSE);
- }
- // left
- if (mode == 1) {
- fill(0, 255, 0);
- }
- else if (mode == 2) {
- fill(nextColor());
- }
- a.set(x1, y1, z2);
- b.set(x1, y1, z1);
- c.set(x1, y2, z1);
- if (!visible(camPos, face)) {
- beginShape();
- normal(-1, 0, 0);
- vertex(x1, y1, z2);
- vertex(x1, y1, z1);
- vertex(x1, y2, z1);
- vertex(x1, y2, z2);
- endShape(CLOSE);
- }
- // top
- if (mode == 1) {
- fill(0, 0, 255);
- }
- else if (mode == 2) {
- fill(nextColor());
- }
- a.set(x1, y1, z2);
- b.set(x2, y1, z2);
- c.set(x2, y1, z1);
- if (!visible(camPos, face)) {
- beginShape();
- normal(0, 1, 0);
- vertex(x1, y1, z2);
- vertex(x2, y1, z2);
- vertex(x2, y1, z1);
- vertex(x1, y1, z1);
- endShape(CLOSE);
- }
- // bottom
- if (mode == 1) {
- fill(0, 0, 255);
- }
- else if (mode == 2) {
- fill(nextColor());
- }
- a.set(x1, y2, z1);
- b.set(x2, y2, z1);
- c.set(x2, y2, z2);
- if (!visible(camPos, face)) {
- beginShape();
- normal(0, -1, 0);
- vertex(x1, y2, z1);
- vertex(x2, y2, z1);
- vertex(x2, y2, z2);
- vertex(x1, y2, z2);
- endShape(CLOSE);
- }
- }
- // . . . . . . . . . . . . . . . . . . . . . .
- int c_red = 0;
- int c_green = 0;
- int c_blue = 0;
- color nextColor() {
- color c = color(c_red, c_green, c_blue);
- // calculate color for next time
- c_blue++;
- if (c_blue == 255) {
- c_green++;
- c_blue = 0;
- if (c_green == 255) {
- c_red++;
- c_green = 0;
- }
- }
- return c;
- }
- // . . . . . . . . . . . . . . . . . . . . . .
- /** checks if the given face is visible from the given camera position */
- boolean visible(PVector cameraPosition, PVector[] face) {
- if (face.length!=3) {
- println("This only works with faces with 3 corners");
- return false;
- }
- // this works out the vector from the camera to the face.
- PVector cameraToFace = new PVector(cameraPosition.x-face[0].x,
- cameraPosition.y-face[0].y,
- cameraPosition.z-face[0].z);
- // we need to find out what direction the face is pointing,
- // known as the normal. to do this we need to do a cross
- // product of two of the sides of the face.
- // side 1
- PVector ab = new PVector(face[1].x-face[0].x,
- face[1].y-face[0].y,
- face[1].z-face[0].z);
- PVector cb = new PVector(face[1].x-face[2].x,
- face[1].y-face[2].y,
- face[1].z-face[2].z);
- PVector faceNormal = new PVector();
- PVector.cross(cb, ab, faceNormal);
- // so that we can draw the normal later on outside of this function.
- PVector triangleNormal = faceNormal;
- // We now know the vector from the camera to the face,
- // and the vector that describes which direction the face
- // is pointing, so we just need to do a dot-product and
- // based on that we can tell if it's facing the camera or not
- float result = PVector.dot(cameraToFace, faceNormal);
- // if the result is positive, then it is facing the camera.
- return result > 0;
- }
1