Close range 3d display messed up

前端 未结 1 815
灰色年华
灰色年华 2021-01-25 18:44

I copied a code of YouTube, about displaying 3d cubes on a screen in Python, without the use of external modules (like PyOpenGL). It works fine, but the moment you go between tw

相关标签:
1条回答
  • 2021-01-25 19:23

    The application does not correctly draw the geometry, when apart of a faces (primitive, side of a cube) is behind and the other part in front of the eye position. That happens if the transformed z coordinate (vert_list += [(x,y,z)]) is positive for the some vertices and negative for negative for some other vertices that form primitive (face).

    You can test that behavior with ease, if you skip all the faces, where at least one z coordinate is negative (behind the eye):

    while True:
        # [...]
    
        for obj in objects:
            # [...]
    
            for f in range(len(obj.faces)):
                face = obj.faces[f]
    
                #on_screen = False
                #for i in face:
                #    x,y = screen_coords[i]
                #    if vert_list[i][2]>0 and x>0 and x<w and y>0 and y<h: on_screen = True; break
    
                # draw a face if any projected coordinate (x, y) is in the viewing volume 
                on_screen = False
                for i in face:
                    x,y = screen_coords[i]
                    if x>0 and x<w and y>0 and y<h: on_screen = True; break
                # skip a face if NOT ALL z coordinates are positive
                if on_screen:
                    on_screen = all([vert_list[i][2]>0 for i in face])
    
                if on_screen:
                    # [...]
    


    The issue can be solved by clipping the geometry at hypothetical near plane. See Viewing frustum:

    while True:
        # [...]
    
        for obj in objects:
            # [...]
    
            for f in range(len(obj.faces)):
                face = obj.faces[f]
    
                on_screen = False
                for i in face:
                    x,y = screen_coords[i]
                    if vert_list[i][2]>0 and x>0 and x<w and y>0 and y<h: on_screen = True; break
    
                # clip geometry at near plane
                if on_screen:
                    near = 0.01
                    for i in face:
                        if vert_list[i][2]<0:
                            x, y, z = vert_list[i]
                            nearscale = 200/near
                            x,y = x*nearscale,y*nearscale
                            screen_coords[i] = (cx+int(x),cy+int(y))
    
                if on_screen:
                    coords = [screen_coords[i] for i in face]
                    face_list += [coords]
                    face_color += [obj.colors[f]]
                    depth += [sum(sum(vert_list[j][i]**2 for i in range(3)) for j in face) / len(face)]
    

    0 讨论(0)
提交回复
热议问题