sagemath / sage

Main repository of SageMath. Now open for Issues and Pull Requests.
https://www.sagemath.org
Other
1.19k stars 411 forks source link

Bug in polygons3d and IndexFaceSet #31812

Open yuan-zhou opened 3 years ago

yuan-zhou commented 3 years ago

polygons3d calls sage.plot.plot3d.index_face_set.IndexFaceSetIndexFaceSet, which should show the same graphic as calling polygon3d repeatedly.

sage: points = [(0, 0, 0), (1, 0, 0), (-1, 0, 0), (0, 0, 1), (0, 1, 0), (1, 0, 1), (1, 1, 0), (-1, 0, 1), 
....: (-1, 1, 0)]                                                                                         
sage: faces = [[3, 0, 1, 5], [0, 4, 6, 1], [3, 0, 2, 7], [0, 4, 8, 2]]                                    
sage: polygons3d(faces, points, color='blue')                                
Graphics3d Object

This gives all black faces, instead of blue. It is different than

sage: sum(polygon3d([points[i] for i in face], color='blue') for face in faces)
Graphics3d Object

CC: @jcamp0x2a @mkoeppe @paulmasson @slel

Component: graphics

Issue created by migration from https://trac.sagemath.org/ticket/31812

mkoeppe commented 3 years ago
comment:1

works for me (with the default viewer) - it's blue.

sheerluck commented 3 years ago
comment:2
polygons3d(faces, points, color='blue')

all black faces, but

polygons3d(faces, points, color='blue', viewer='jmol')

all blue

yuan-zhou commented 3 years ago
comment:3

Replying to @sheerluck:

polygons3d(faces, points, color='blue')

all black faces, but

polygons3d(faces, points, color='blue', viewer='jmol')

all blue

Same behavior here.

Blue with viewer='jmol' or 'tachyon' but black with default viewer='threejs'.

Mysteriously, if I call viewer='threejs' after viewer='jmol' was used, then it shows blue.

p = polygons3d(faces, points, color='blue')
p.show()   # default is threejs, black
p.show(viewer='jmol') # blue
p.show(viewer='threejs') # now this mysteriously becomes blue

In any case, this is not a bug in polygons3d or IndexFaceSet then.

slel commented 3 years ago
comment:4

cc-ing three.js experts

21c3cf6e-6c50-4e8b-9831-5a03f9a599c1 commented 3 years ago
comment:5

I think the reason using viewer='jmol' first fixes it is because the IndexFaceSet.jmol_repr method has a side effect, defined here. Looks like it duplicates vertices so that each face has its own unique set, similar to what you get summing polygon3d, which also shows the correct color.

I'm not sure why the polygons3d version is showing up all black, though. The color is being passed to the template correctly. Interestingly, while rotating the camera around in Edge, it will occasionally flash the correct color blue for a split second. Doesn't happen in Firefox. Also, using threejs_flat_shading=True fixes it, so perhaps something related to lighting/normals?

yuan-zhou commented 3 years ago
comment:6

It is related to the orientation of the vertices in a face. In the following example, the first face and the last face in faces_a have opposite orientations, while the two in faces_b have the same. The plot is black using faces_a and is blue using faces_b.

sage: points = [(0, 0, 0), (1, 0, 0), (-1, 0, 0), (0, 0, 1), (0, 1, 0), (1, 0, 1), (1, 1, 0), (-1, 0, 1)]               
sage: faces_a = [[3, 0, 1, 5], [0, 4, 6, 1], [3, 0, 2, 7]]  
sage: faces_b =  [[3, 0, 1, 5], [0, 4, 6, 1], [7, 2, 0, 3]] 
sage: polygons3d(faces_a, points, color='blue') # shows black
sage: polygons3d(faces_b, points, color='blue') # shows blue

Replying to @jcamp0x2a:

I think the reason using viewer='jmol' first fixes it is because the IndexFaceSet.jmol_repr method has a side effect, defined here. Looks like it duplicates vertices so that each face has its own unique set, similar to what you get summing polygon3d, which also shows the correct color.

I'm not sure why the polygons3d version is showing up all black, though. The color is being passed to the template correctly. Interestingly, while rotating the camera around in Edge, it will occasionally flash the correct color blue for a split second. Doesn't happen in Firefox. Also, using threejs_flat_shading=True fixes it, so perhaps something related to lighting/normals?