📄 line3d.c
字号:
if (ferror (File_Ptr1))
{
fclose (File_Ptr1);
remove (light_name);
File_Error(ray_name, 2);
EXIT_OVLY;
return(-1);
}
}
}
col++;
} /* End of while statement for plotting line */
RO++;
reallythebottom:
/* stuff that HAS to be done, even in preview mode, goes here */
if(SPHERE)
{
/* incremental sin/cos phi calc */
if(currow == 0)
{
sinphi = oldsinphi2;
cosphi = oldcosphi2;
}
else
{
sinphi = twocosdeltaphi*oldsinphi2 - oldsinphi1;
cosphi = twocosdeltaphi*oldcosphi2 - oldcosphi1;
oldsinphi1 = oldsinphi2;
oldsinphi2 = sinphi;
oldcosphi1 = oldcosphi2;
oldcosphi2 = cosphi;
}
}
EXIT_OVLY;
return(0); /* decoder needs to know all is well !!! */
}
/* vector version of line draw */
static void _fastcall vdraw_line(v1,v2,color)
double *v1,*v2;
int color;
{
int x1,y1,x2,y2;
x1 = (int)v1[0];
y1 = (int)v1[1];
x2 = (int)v2[0];
y2 = (int)v2[1];
draw_line(x1,y1,x2,y2,color);
}
static void corners(m,show,pxmin,pymin,pzmin,pxmax,pymax,pzmax)
MATRIX m;
int show; /* turns on box-showing feature */
double *pxmin,*pymin,*pzmin,*pxmax,*pymax,*pzmax;
{
int i,j;
VECTOR S[2][4]; /* Holds the top an bottom points, S[0][]=bottom */
/*
define corners of box fractal is in in x,y,z plane
"b" stands for "bottom" - these points are the corners of the screen
in the x-y plane. The "t"'s stand for Top - they are the top of
the cube where 255 color points hit.
*/
*pxmin = *pymin = *pzmin = (int)INT_MAX;
*pxmax = *pymax = *pzmax = (int)INT_MIN;
for (j = 0; j < 4; ++j)
for (i=0;i<3;i++)
S[0][j][i]=S[1][j][i]=0;
S[0][1][0] = S[0][2][0] = S[1][1][0] = S[1][2][0] = xdots-1;
S[0][2][1] = S[0][3][1] = S[1][2][1] = S[1][3][1] = ydots-1;
S[1][0][2] = S[1][1][2] = S[1][2][2] = S[1][3][2] = zcoord-1;
for (i = 0; i < 4; ++i)
{
/* transform points */
vmult(S[0][i],m,S[0][i]);
vmult(S[1][i],m,S[1][i]);
/* update minimums and maximums */
if (S[0][i][0] <= *pxmin) *pxmin = S[0][i][0];
if (S[0][i][0] >= *pxmax) *pxmax = S[0][i][0];
if (S[1][i][0] <= *pxmin) *pxmin = S[1][i][0];
if (S[1][i][0] >= *pxmax) *pxmax = S[1][i][0];
if (S[0][i][1] <= *pymin) *pymin = S[0][i][1];
if (S[0][i][1] >= *pymax) *pymax = S[0][i][1];
if (S[1][i][1] <= *pymin) *pymin = S[1][i][1];
if (S[1][i][1] >= *pymax) *pymax = S[1][i][1];
if (S[0][i][2] <= *pzmin) *pzmin = S[0][i][2];
if (S[0][i][2] >= *pzmax) *pzmax = S[0][i][2];
if (S[1][i][2] <= *pzmin) *pzmin = S[1][i][2];
if (S[1][i][2] >= *pzmax) *pzmax = S[1][i][2];
}
if(show)
{
if(persp)
{
for (i=0;i<4;i++)
{
perspective(S[0][i]);
perspective(S[1][i]);
}
}
/* Keep the box surrounding the fractal */
for (j=0;j<2;j++)
for (i = 0; i < 4; ++i)
{
S[j][i][0] += xxadjust;
S[j][i][1] += yyadjust;
}
draw_rect(S[0][0],S[0][1],S[0][2],S[0][3],2,1);/* Bottom */
draw_rect(S[0][0],S[1][0],S[0][1],S[1][1], 5, 0); /* Sides */
draw_rect(S[0][2],S[1][2],S[0][3],S[1][3], 6, 0);
draw_rect(S[1][0],S[1][1],S[1][2],S[1][3],8,1); /* Top */
}
}
/* This function draws a vector from origin[] to direct[] and a box
around it. The vector and box are transformed or not depending on
FILLTYPE.
*/
static void draw_light_box (origin, direct, light_m)
double *origin, *direct;
MATRIX light_m;
{
VECTOR S[2][4];
int i,j;
double temp;
S[1][0][0] = S[0][0][0] = origin[0];
S[1][0][1] = S[0][0][1] = origin[1];
S[1][0][2] = direct[2];
for (i=0;i<2;i++)
{
S[i][1][0] = S[i][0][0];
S[i][1][1] = direct[1];
S[i][1][2] = S[i][0][2];
S[i][2][0] = direct[0];
S[i][2][1] = S[i][1][1];
S[i][2][2] = S[i][0][2];
S[i][3][0] = S[i][2][0];
S[i][3][1] = S[i][0][1];
S[i][3][2] = S[i][0][2];
}
/* transform the corners if necessary */
if (FILLTYPE == 6)
for (i=0;i<4;i++)
{
vmult (S[0][i],light_m,S[0][i]);
vmult (S[1][i],light_m,S[1][i]);
}
/* always use perspective to aid viewing */
temp = view[2]; /* save perspective distance for a later restore */
view[2] = - P * 300.0 / 100.0;
for (i=0;i<4;i++)
{
perspective(S[0][i]);
perspective(S[1][i]);
}
view[2] = temp; /* Restore perspective distance*/
/* Adjust for aspect */
for (i=0;i<4;i++)
{
S[0][i][0] = S[0][i][0] * aspect;
S[1][i][0] = S[1][i][0] * aspect;
}
/* draw box connecting transformed points. NOTE order and COLORS */
draw_rect(S[0][0],S[0][1],S[0][2],S[0][3],2,1);
vdraw_line (S[0][0],S[1][2],8);
/* sides */
draw_rect(S[0][0],S[1][0],S[0][1],S[1][1], 4, 0);
draw_rect(S[0][2],S[1][2],S[0][3],S[1][3], 5, 0);
draw_rect(S[1][0],S[1][1],S[1][2],S[1][3],3,1);
/* Draw the "arrow head" */
for (i= -3;i<4;i++)
for (j= -3;j<4;j++)
if (abs(i) + abs(j) < 6)
plot((int)(S[1][2][0]+i),(int)(S[1][2][1]+j),10);
}
static void draw_rect (V0, V1, V2, V3, color, rect)
VECTOR V0, V1, V2, V3;
int color, rect;
{
VECTOR V[4];
int i;
for (i=0;i<2;i++)
{ /* Since V[2] is not used by vdraw_line don't bother setting it */
V[0][i] = V0[i];
V[1][i] = V1[i];
V[2][i] = V2[i];
V[3][i] = V3[i];
}
if (rect) /* Draw a rectangle */
{
for (i=0;i<4;i++)
if (fabs(V[i][0]-V[(i+1)%4][0]) < -2*bad_check &&
fabs(V[i][1]-V[(i+1)%4][1]) < -2*bad_check)
vdraw_line (V[i],V[(i+1)%4],color);
}
else /* Draw 2 lines instead */
{
for(i=0;i<3;i+=2)
if (fabs(V[i][0]-V[i+1][0]) < -2*bad_check &&
fabs(V[i][1]-V[i+1][1]) < -2*bad_check)
vdraw_line (V[i],V[i+1],color);
}
return;
}
/* replacement for plot - builds a table of min and max x's instead of plot */
/* called by draw_line as part of triangle fill routine */
static void _fastcall putminmax(int x,int y,int color)
{
if(y >= 0 && y < ydots)
{
if(x < minmax_x[y].minx) minmax_x[y].minx = x;
if(x > minmax_x[y].maxx) minmax_x[y].maxx = x;
}
}
/*
This routine fills in a triangle. Extreme left and right values for
each row are calculated by calling the line function for the sides.
Then rows are filled in with horizontal lines
*/
#define MAXOFFSCREEN 2 /* allow two of three points to be off screen */
static void _fastcall putatriangle(struct point pt1,struct point pt2,
struct point pt3,int color)
{
extern struct point p1,p2,p3;
int miny,maxy;
int x,y,xlim;
/* Too many points off the screen? */
if(offscreen(pt1) + offscreen(pt2) + offscreen(pt3) > MAXOFFSCREEN)
return;
p1 = pt1; /* needed by interpcolor */
p2 = pt2;
p3 = pt3;
/* fast way if single point or single line */
if (p1.y == p2.y && p1.x == p2.x)
{
plot = fillplot;
if (p1.y == p3.y && p1.x == p3.x)
(*plot)(p1.x, p1.y, color);
else
draw_line(p1.x,p1.y,p3.x,p3.y,color);
plot = normalplot;
return;
}
else if ( (p3.y == p1.y && p3.x == p1.x) || (p3.y == p2.y && p3.x == p2.x) )
{
plot = fillplot;
draw_line(p1.x,p1.y,p2.x,p2.y,color);
plot = normalplot;
return;
}
/* find min max y */
miny = maxy = p1.y;
if(p2.y < miny) miny = p2.y;
else maxy = p2.y;
if(p3.y < miny) miny = p3.y;
else if(p3.y > maxy) maxy = p3.y;
/* only worried about values on screen */
if(miny < 0) miny = 0;
if(maxy >= ydots) maxy = ydots-1;
for(y=miny;y<=maxy;y++)
{
minmax_x[y].minx = (int)INT_MAX;
minmax_x[y].maxx = (int)INT_MIN;
}
/* set plot to "fake" plot function */
plot = putminmax;
/* build table of extreme x's of triangle */
draw_line(p1.x,p1.y,p2.x,p2.y,0);
draw_line(p2.x,p2.y,p3.x,p3.y,0);
draw_line(p3.x,p3.y,p1.x,p1.y,0);
for(y=miny;y<=maxy;y++)
{
xlim = minmax_x[y].maxx;
for(x=minmax_x[y].minx;x<=xlim;x++)
(*fillplot)(x,y,color);
}
plot = normalplot;
}
static int _fastcall offscreen(struct point pt)
{
if(pt.x >= 0)
if(pt.x < xdots)
if(pt.y >= 0)
if(pt.y < ydots)
return(0); /* point is ok */
if (abs(pt.x) > 0-bad_check || abs(pt.y) > 0-bad_check)
return(99); /* point is bad */
return(1); /* point is off the screen */
}
static void _fastcall clipcolor(int x,int y,int color)
{
if(0 <= x && x < xdots &&
0 <= y && y < ydots &&
0 <= color && color < filecolors)
{
standardplot(x,y,color);
if (Targa_Out)
if (!(glassestype==1 || glassestype==2)) /* standardplot modifies color in these types */
targa_color(x, y, color);
}
}
/*********************************************************************/
/* This function is the same as clipcolor but checks for color being */
/* in transparent range. Intended to be called only if transparency */
/* has been enabled. */
/*********************************************************************/
static void _fastcall T_clipcolor(int x,int y,int color)
{
if (0 <= x && x < xdots && /* is the point on screen? */
0 <= y && y < ydots && /* Yes? */
0 <= color && color < colors && /* Colors in valid range? */
/* Lets make sure its not a transparent color */
(transparent[0] > color || color > transparent[1]))
{
standardplot(x,y,color); /* I guess we can plot then */
if (Targa_Out)
if (!(glassestype==1 || glassestype==2)) /* standardplot modifies color in these types */
targa_color(x, y, color);
}
}
/************************************************************************/
/* A substitute for plotcolor that interpolates the colors according */
/* to the x and y values of three points (p1,p2,p3) which are static in */
/* this routine */
/* */
/* In Light source modes, color is light value, not actual color */
/* Real_Color always contains the actual color */
/************************************************************************/
static void _fastcall interpcolor(int x,int y,int color)
{
int D,d1,d2,d3;
/* this distance formula is not the usual one - but it has the virtue
that it uses ONLY additions (almost) and it DOES go to zero as the
points get close.
*/
d1 = abs(p1.x-x)+abs(p1.y-y);
d2 = abs(p2.x-x)+abs(p2.y-y);
d3 = abs(p3.x-x)+abs(p3.y-y);
D = (d1 + d2 + d3) << 1;
if(D)
{ /* calculate a weighted average of colors -
long casts prevent integer overflow. This can evaluate to zero */
color = ((long)(d2+d3)*(long)p1.color +
(long)(d1+d3)*(long)p2.color +
(long)(d1+d2)*(long)p3.color) / D;
}
if(0 <= x && x < xdots &&
0 <= y && y < ydots &&
0 <= color && color < colors &&
(transparent[1] == 0 || Real_Color > transparent[1] ||
transparent[0] > Real_Color))
{
if (Targa_Out)
if (!(glassestype==1 || glassestype==2)) /* standardplot modifies color in these types */
D = targa_color(x, y, color);
if (FILLTYPE >= 5)
if (Real_V && Targa_Out)
color = D;
else
{
color = (1 + (unsigned)color * IAmbient)/256;
if (color == 0)
color = 1;
}
standardplot(x,y,color);
}
}
/*
In non light source modes, both color and Real_Color contain the
actual pixel color. In light source modes, color contains the
light value, and Real_Color contains the origninal color
This routine takes a pixel modifies it for lightshading if appropriate
and plots it in a Targa file. Used in plot3d.c
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -