Bug 111 : polygons perpendicular to z axis are sometimes not filling properly in P3D
Last modified: 2007-04-18 16:29




Status:
RESOLVED
Resolution:
FIXED -
Priority:
P2
Severity:
normal

 

Reporter:
fry
Assigned To:
fry

Attachment Type Created Size Actions

Description:   Opened: 2005-07-28 05:54
http://processing.org/discourse/yabb_beta/YaBB.cgi?board=SoftwareBugs;action=display;num=1114158993

seems to be a bug in tesselation, because triangles work fine:

import processing.opengl.*;

float rotX;
float rotY;

void setup()
{
size(200, 200, OPENGL);
framerate(30);
}

void draw()
{
background(51);
fill(200);
stroke(200);
lights();

pushMatrix();
translate(width/2, height/2, 0);
rotateX(rotY);
rotateY(rotX);

//a polygon perpendicular to z-axis
beginShape(POLYGON);
vertex(0.0, -50.0, -50.0);
vertex(0.0, 50.0, 50.0);
vertex(0.0,50.0, -50.0);
endShape();

// not perpendicular
beginShape(POLYGON);
vertex(-50.0, -50.0, 0.0);
vertex(50.0, -50.0, 0.0);
vertex(-50.0,50.0, 0.0);
endShape();

popMatrix();
}

void mouseDragged(){
rotX += (mouseX - pmouseX) * 0.01;
rotY += (mouseY - pmouseY) * 0.01;
}
Additional Comment #1 From fry 2006-11-05 06:09
found and fixed for 0120. the triangulation code wasn't taking Z into
account, therefore the area was being calculated based on just X and Y.
more notes in the code.
Additional Comment #2 From ewjordan 2007-04-13 12:39
I don't know if this is the same bug or not, but it seems similar (and is still present in
0124). It appears that in some cases triangle fills are being skipped altogether in both P3D
and OPENGL modes. Try moving your mouse around in the following sketch to see:


import processing.opengl.*;

float distFromZero = 500;
float xCam = 0;
float yCam = 0;
float zCam = 0;
float xCamDir = 0;
float yCamDir = 0;
float zCamDir = 1;
float xLookAt = 0;
float yLookAt = 0;
float zLookAt = 0;
float sensFactor = 2.5;

void setup()
{
//size(640,480, P3D);
size(640, 480, OPENGL);
frameRate(30);
noStroke();
}

void draw()
{
background(200);
float mouseX2 = mouseX;
float mouseY2 = mouseY;
float theta = -sensFactor*(mouseX2-width/2)*PI/width;
float rho = -(mouseY2-height/2)*PI/height;
xCam = sin(theta)*distFromZero*cos(rho);
yCam = distFromZero*sin(rho);
zCam = cos(theta)*distFromZero*cos(rho);
float fov = PI/3.0;
float cameraZ = (height/2.0) / tan(PI * fov / 360.0);
camera(xCam,yCam,zCam, 0, 0, 0, 0, 1, 0);
fill(50);
beginShape();
vertex(10, 25, 0);
vertex(10, 26, 100);
vertex(9+floor(3*mouseY/height), 125, 100);
endShape();
}


If you move your mouse into the middle third of the screen (vertically) then all x coordinates
become 10 and the whole triangle disappears. I haven't been able to track down the precise
source of the problem, though - if you change the vertex x coordinates to 0, 0, and
floor(3*mouseY/height), the problem doesn't show up at all, so it's not just that they are all
equal that is causing it. Notice that in the above test case the triangle isn't perpendicular to
any axis, which makes this extra confusing. Perhaps this is actually a different bug?
Additional Comment #3 From fry 2007-04-13 15:05
nah, i'm guessing that's a clipping issue--that the clipping planes in P3D
are pretty hokey (try switching to OpenGL for better clipping). the z=0 bug
was just a quirk in the tesselation code that's been fixed.
Additional Comment #4 From ewjordan 2007-04-14 07:40
I don't think it's just a clipping issue - the behavior is the same in both
OPENGL and P3D, so it's happening before clipping planes really have a
chance to mess things up. Here's a minimal sketch that exhibits the
problem quite clearly:


import processing.opengl.*;

void setup() {
size(640, 480, OPENGL);
frameRate(30);
}

void draw() {
background(255);
fill(50); stroke(255,0,0);
if (!keyPressed){ beginShape(POLYGON); }
else {beginShape(TRIANGLES);}
if (mousePressed){vertex(mouseX+.0001, mouseY, 0);}
else{ vertex(mouseX, mouseY, 0); }
vertex(mouseX, mouseY+100, -100);
vertex(mouseX, mouseY, -100);
endShape(CLOSE);
}


Move the mouse around - you'll just see the outline of the triangle moving
with it. But if you either hit any key (thus switching from POLYGON to
TRIANGLES mode) or press the mouse button (displacing the x coordinate by
.0001, which should not do much of anything), the fill appears as expected.
You might also try moving the mouse to the leftmost pixel on the screen -
for some reason this also lets the fill complete. If I get a chance I'll
take a look through the polygon code and see if it's depending on the
x-extent of the polygons in a bad way or something like that...

Actually, that was easier to find than I thought - I just recompiled a
version with some debugging stuff in it, and the P3D version of that test
case is reaching the "screw it, this polygon is just f-ed up" section of
triangulate_polygon (somewhere around line 1500 in PGraphics3d.java).
Here's the relevant code so you don't have to look it up:

if (area == 0) {
// figure out which dimension is the perpendicular axis
boolean foundValidX = false;
boolean foundValidY = false;
for (int i = vertex_start; i < vertex_end; i++) {
if (vertices[i][MX] != 0) foundValidX = true;
if (vertices[i][MY] != 0) foundValidY = true;
}
if (foundValidX && !foundValidY) {
//d1 = MX; // already the case
d2 = MZ;

} else if (!foundValidX && foundValidY) {
// ermm.. which is the proper order for cw/ccw here?
d1 = MY;
d2 = MZ;

} else {
// screw it, this polygon is just f-ed up
return;
}

Ah! I think I got it - notice that if both foundValidX AND foundValidY are
true, we fall through to the "screw it" section (which was presumably meant
primarily to catch and discard the degenerate polygons in which neither is
true); this is what's going wrong in my test case, since neither the x or y
coordinates are zero, though the triangle does have zero volume in the XY
plane. I think we need to be checking whether all X or Y coordinates are
equal to each other, not equal to zero - is that right? I still don't
quite understand all the stuff happening in that function, so I could be
mistaken.
Additional Comment #5 From fry 2007-04-18 09:14
yeah, that's embarassing. at a glance i think it just needs to be wrapping
in a "if (!foundValidX || !foundValidY) block, so something like:

if (foundValidX) {
if (foundValidY) {
// polygon is ok
} else { // !foundValidY
//d1 = MX; // already the case
d2 = MZ;
}
} else { // !foundValidX
if (foundValidY) {
// ermm.. which is the proper order for cw/ccw here?
d1 = MY;
d2 = MZ;
} else { // !foundValidY
// screw it, this polygon is just f-ed up
return;
}
}

should be correct.. i can't believe this actually worked the way it had
been implemented. that makes me concerned that i'm missing something.

so this is a regression from the fix for this bug, technically this is
better to file as a separate report and we can just link the two as necessary.
Additional Comment #6 From ewjordan 2007-04-18 16:29
Reported as bug 547 with a note linking back here.