Path: utzoo!attcan!uunet!lll-winken!lll-lcc!lll-tis!ames!amdcad!amdahl!nsc!gates From: gates@nsc.nsc.com (Tim Gates) Newsgroups: comp.graphics Subject: Re: 3d Graphics Summary: simple conversion from 3D to 2D Message-ID: <8062@nsc.nsc.com> Date: 26 Nov 88 00:41:15 GMT References: <1648511648@andrew.cmu.edu> <16400001@ugun21> Reply-To: gates@nsc.nsc.com.UUCP (Tim Gates) Organization: National Semiconductor, Sunnyvale, CA. (Mesa Group) Lines: 108 To convert from 3D (x,y,z) to 2D (h,v): Address your screen via two variables h (horiz) and v (vert). On this flat screen you have three lines: 1) a vertical line (represents z axis) 2) a diagonal line higher on left than right (represents y axis) 3) a diagonal line lower on left than right (represents x axis) Phi is the angle of line 2 from horizontal. Theta is the angle of line 3 from horizontal. Phi and Theta determine the "tilt" of the projection. Small angles make the x-y plane appear to be perpendicular to your screen. Larger angles tilt the x-y plane. I like 30 degrees (0.52 radians) for both phi and theta. Next Calculate 4 constants: sin_y = -sin(phi); cos_y = cos(phi); sin_x = -sin(theta); cos_x = cos(theta); The conversion from 3D to 2D is: v = z + (y * sin_y) + (x * sin_x); /* double flat_v(x,y,z); */ h = (y * cos_y) - (x * cos_x); /* double flat_h(x,y); */ I suggest doing the conversion as a macro: #define flat_v(x,y,z) ((z) + ((y) * sin_y) + ((x) * sin_x)) #define flat_h(x,y) (((y) * cos_y) - ((x) * cos_x)) Notice that h and v are floating point values; they should be scaled to convert them to screen pixel cooridinates: Assume that max_x, max_y, max_z, min_x, min_y, min_z are the limits of 3-Space you will be dealing with. Now to calculate the limits of 2-space: double max_x, max_y, min_x, min_y; max_v = flat_v(min_x,min_y,max_z); min_v = flat_v(max_x,max_y,min_z); max_h = flat_h(max_x,min_y); min_h = flat_h(min_x,max_y); Determine the scaling amounts: Assume that max_c is the number of horizontal pixels (columns) on the screen. Assume that max_r is the number of vertical pixels (rows) on the screen. Lower left corner of screen is 0,0. double max_c = 799.0; /* screen is 800x600 */ double max_r = 599.0; double scl_c, scl_r, off_c, off_r; /* scaling parameters */ off_c = min_h; scl_c = (max_c + 1.0) / (max_h - min_h); off_r = min_v; scl_r = (max_r + 1.0) / (max_v - min_v); The Scaling functions are: int scale_c(horz) double horz; { int c; double t; t = (horz - off_c) * scl_c; if(t < 0.0) t = 0.0; if(t > max_c) t = max_c; c = t + 0.5; /* round off */ return(c); } int scale_r(vert) double vert; { int r; double t; t = (vert - off_r) * scl_cr if(t < 0.0) t = 0.0; if(t > max_r) t = max_r; r = t + 0.5; /* round off */ return(r); } To plot a pixel: Assume that the function set_pix(c,r,color) sets the pixel in row r, column c to color. The 3-space pixel plotting is: void set_pix3(x,y,z,c) double x,y,z; int c; /* color */ { set_pix( scale_c( flat_h(x,y)), scale_r( flat_v(x,y,z)), c); } Speedups: In the scaling routines: Convert to int, then bounds check. Convert set_pix3 to a macro. I hope you have fun with this... Standard discalmer: Use at your own risk. I entered this from memory. -- Tim Gates National Semiconductor {amdahl|decwrl|hplabs|nscpdc|pyramid|sun|voder}!nsc!gates "Where the men are men, and the computers run scared."