#---------------------------------------------------------------------- # Introduction to 3D projections using a simple Orthographic Projection # # Copyright (C) November 13, 2017 -- Dr. William T. Verts #---------------------------------------------------------------------- #---------------------------------------------------------------------- # Generic helper functions #---------------------------------------------------------------------- def INT (N): # Convert float to nearest int return int(round(N)) def Radians (Degrees): # Convert Degrees to Radians (for sin / cos) return Degrees / 180.0 * pi #---------------------------------------------------------------------- # Orthographic Projection System # # Origin2D and Scale2D are global so that values set by SetOrigin2D # and SetScale2D can be used by Project3D (which is the heart of the # code here). The projection angle is fixed at 30 degrees (which # "looks right"), and precomputed so we don't have to compute the # expensive sine and cosine of the same angle for every point being # transformed. #---------------------------------------------------------------------- Origin2D = [0,0] # Position on the Canvas of 3D point [0,0,0] Scale2D = 1.0 # Pixels per 3D unit Cosine30 = math.sqrt(3)/2.0 # Same as: math.cos(Radians(30.0)) Sine30 = 0.5 # Same as: math.sin(Radians(30.0)) def Project3D (P3D): # P3D is [X,Y,Z], returns a 2D point [X,Y] global Origin2D, Scale2D XOffset = P3D[0] + P3D[2] * Cosine30 YOffset = P3D[1] + P3D[2] * Sine30 X = Origin2D[0] + XOffset * Scale2D Y = Origin2D[1] - YOffset * Scale2D return [X,Y] def SetOrigin2D (P2D): # P2D is [X,Y] indicating location on canvas of [0,0,0] global Origin2D Origin2D = P2D return def SetScale2D (N): # N is number of pixels per 3D Unit global Scale2D Scale2D = N return #---------------------------------------------------------------------- # Start building tools to use the 3D system. # addLine3D draws a line between two 3D points. #---------------------------------------------------------------------- def addLine3D(Canvas, P0, P1, NewColor=black): # P0 and P1 are both [X,Y,Z] points Q0 = Project3D(P0) # Q0 and Q1 are both [X,Y] points Q1 = Project3D(P1) addLine(Canvas, INT(Q0[0]), INT(Q0[1]), INT(Q1[0]), INT(Q1[1]), NewColor) return #---------------------------------------------------------------------- # Test program showing how to use the 3D projection system. # Once the canvas has been set up and the position and scale of # the 3D system have been set, the rest of the program is entirely # expressed in 3D. #---------------------------------------------------------------------- def Main(): Canvas = makeEmptyPicture(400,300) SetOrigin2D([getWidth(Canvas)/2, getHeight(Canvas)/2]) SetScale2D(10.0) addLine3D(Canvas, [-10,0,0], [+10,0,0], red) # X axis addLine3D(Canvas, [0,-10,0], [0,+10,0], green) # Y axis addLine3D(Canvas, [0,0,-10], [0,0,+10], blue) # Z axis show(Canvas) return