One-sided ellipse?

edited December 2014 in How To...

Hi all,

It seems that ellipses, either drawn with ellipse(...) or createShape(ELLIPSE...) are two-sided. ie. they display if they are facing towards or away from the camera.

I see PShape has a setNormal() method that may be used to control the rendering of the shape, but it's unclear how to use it to hide/cull the backface as changing it still causes both faces to render.

int rot = 0;
PShape myEllipse;
void setup() {
  size(200, 200, P3D);

  myEllipse = createShape(ELLIPSE, 0, 0, 50, 50);
  ellipseMode(CENTER);
  shapeMode(CENTER);
  fill(255);
}
void draw() {
  background(0);
  translate(width/2, 50);
  rotateY(radians(rot));
  ellipse(0, 0, 50, 50);
  translate(0, 60);
  shape(myEllipse, 0, 0);

  rot+=1;
}

any tips?

Thanks! ak

Answers

  • what do you expect to see from the back? a hollow curve? blackness? a ring can always be seen from both sides.

  • In 3d modeling programs, typically a plane only is visible from one side, it's just transparent from the other. The normal defines which side reflects light, the other simply is invisible.

    In this example, it would just be black, or the background.

  • The real issue I'm having is when two circles are positioned on top of each other, the depth test gives some undesired artifacts:

    int rot = 0;
    PShape myEllipse;
    void setup() {
      size(200, 200, P3D);
      ellipseMode(CENTER);
      shapeMode(CENTER);
      noStroke();
    
      myEllipse = createShape(ELLIPSE, 0, 0, 50, 50);
      int verts = myEllipse.getVertexCount();
      for (int v = 0; v < verts; v++) {
        println(v + " before: " + myEllipse.getNormal(v));
        myEllipse.setNormal(v, -1.0, 0.0, -1.0);
        println("after" + myEllipse.getNormal(v));
      }
      myEllipse.setFill(color(0, 0, 255, 100));
    }
    void draw() {
      background(0);
      //hint(DISABLE_DEPTH_TEST);
      translate(width/2, 100, 0);
      rotateY(radians(rot));
    
      fill(0, 150, 0);
      sphere(45);
      translate(0, 0, 50);
    
      fill(255, 0, 0, 100);
      ellipse(0, 0, 50, 50);
      shape(myEllipse, 0, 0);
    
      rot+=1;
    }
    

    Kinda funky and crazy, but I'd like to be able to have control over it. Ideally the two would blend together to create a purple.

    If I uncomment the hint(DISABLE_DEPTH_TEST); it seems to work correctly, but then the ellipse is always drawn on top of the sphere.

    Backface culling would allow the ellipse to be one sided, so I could disable the depth testing and allow them to rotate around other objects.

    Or am I thinking about this all wrong? Thanks! ak

  • Also, line 13 doesn't seem to have any effect. It seems like that may be the key to controlling the normal visibility, but I'm not sure how it works.

  • edited December 2014

    I never got a satisfactory answer either...

    http://forum.processing.org/one/topic/disable-backface-culling.html

  • edited December 2014 Answer ✓

    Hey TfGuy, Thanks for the response, I found the solution: http://forum.processing.org/one/topic/how-to-enable-backface-culling-in-opengl-to-speed-3d-model-fps

    here's how it works in my example:

    import processing.opengl.*;
    
    int rot = 0;
    PShape myEllipse;
    void setup() {
      size(200, 200, P3D);
      ellipseMode(CENTER);
      shapeMode(CENTER);
      noStroke();
    
      myEllipse = createShape(ELLIPSE, 0, 0, 50, 50);
      myEllipse.setFill(color(0, 0, 255, 100));
    }
    void draw() {
      background(0);
      hint(DISABLE_DEPTH_TEST);
      translate(width/2, 100, 0);
      rotateY(radians(rot));
    
      fill(0, 150, 0);
      sphere(45);
      translate(0, 0, 50);
    
      PGL pgl = beginPGL();
      pgl.enable(PGL.CULL_FACE);
      // draw your geometry, using either Processing calls or GL calls...
      fill(255, 0, 0, 100);
      ellipse(0, 0, 50, 50);
      shape(myEllipse, 0, 0);
      endPGL(); // restores the GL defaults for Processing
    
      rot+=1;
    }
    

    Seems to work great! the only downside is that it's reset each frame so you've got to reenable it each draw loop.

    Thanks! ak

    EDIT: I'm not sure how to accept your own answer, but this solved it for me.

Sign In or Register to comment.