📄 line3d.c
字号:
*/
int _fastcall targa_color(int x,int y,int color)
{
unsigned long H, S, V;
BYTE RGB[3];
if (FILLTYPE == 2 || glassestype==1 || glassestype==2)
Real_Color = color; /* So Targa gets interpolated color */
RGB[0] = dacbox [Real_Color] [0] << 2; /* Move color space to */
RGB[1] = dacbox [Real_Color] [1] << 2; /* 256 color primaries */
RGB[2] = dacbox [Real_Color] [2] << 2; /* from 64 colors */
/* Now lets convert it to HSV */
R_H(RGB[0], RGB[1], RGB[2], &H, &S, &V);
/* Modify original S and V components */
if (FILLTYPE > 4 && !(glassestype==1 || glassestype==2)) /* Adjust for Ambient */
V = (V * (65535 - (unsigned)(color * IAmbient))) / 65535;
if (haze)
{
S = (unsigned long)(S * HAZE_MULT) / 100; /* Haze lowers sat of colors */
if (V >= 32640) /* Haze reduces contrast */
{
V = V - 32640;
V = (unsigned long)((V * HAZE_MULT) / 100);
V = V + 32640;
}
else
{
V = 32640 - V;
V = (unsigned long)((V * HAZE_MULT) / 100);
V = 32640 - V;
}
}
/* Now lets convert it back to RGB. Original Hue, modified Sat and Val */
H_R(&RGB[0], &RGB[1], &RGB[2], H, S, V);
if (Real_V)
V = (35 * (int)RGB[0] + 45 * (int)RGB[1] + 20 * (int)RGB[2]) / 100;
/* Now write the color triple to its transformed location */
/* on the disk. */
targa_writedisk (x+sxoffs, y+syoffs, RGB[0], RGB[1], RGB[2]);
return(255-V);
}
static int set_pixel_buff(BYTE *pixels,BYTE far *fraction,unsigned linelen)
{
int i;
if ((evenoddrow++ & 1) == 0) /* even rows are color value */
{
for(i=0;i<linelen;i++) /* add the fractional part in odd row */
fraction[i] = pixels[i];
return(1);
}
else /* swap */
{
BYTE tmp;
for(i=0;i<linelen;i++) /* swap so pixel has color */
{
tmp = pixels[i];
pixels[i]=fraction[i];
fraction[i]=tmp;
}
}
return(0);
}
/* cross product - useful because cross is perpendicular to v and w */
/**** PB commented this out - it is unused
static int chk_cross_product (int col, int row,VECTOR v, VECTOR w, VECTOR cross, VECTOR crossavg)
{
static start = 1;
static FILE *fp;
if(start)
{
fp = fopen("blob","w");
start = 0;
}
fprintf(fp,"row %+4d col %+4d v1 %+8.3e %+8.3e %+8.3e v2 %+8.3e %+8.3e %+8.3e cross %+8.3e %+8.3e %+8.3e crossavg %+8.3e %+8.3e %+8.3e \n",
row,col,v[0],v[1],v[2],w[0],w[1],w[2],cross[0],cross[1],cross[2],crossavg[0],crossavg[1],crossavg[2]);
return(0);
}
***/
/**************************************************************************
Common routine for printing error messages to the screen for Targa
and other files
**************************************************************************/
#ifndef XFRACT
static char f[] = "%Fs%Fs";
static char fff[] = "%Fs%Fs%Fs";
#else
static char f[] = "%s%s";
static char fff[] = "%s%s%s";
#endif
static char far OOPS[] = {"OOPS, "};
static char far E1[] = {"can't handle this type of file.\n"};
static char far str1[] = {"couldn't open < "};
static char far str3[] = {"image wrong size\n"};
static char far temp1[] = {"ran out of disk space. < "};
static void File_Error (char *File_Name1, int ERROR)
{
char msgbuf[200];
error = ERROR;
switch(ERROR)
{
case 1: /* Can't Open */
#ifndef XFRACT
sprintf(msgbuf,"%Fs%Fs%s >", OOPS, str1, File_Name1);
#else
sprintf(msgbuf,"%s%s%s >", OOPS, str1, File_Name1);
#endif
break;
case 2: /* Not enough room */
#ifndef XFRACT
sprintf(msgbuf,"%Fs%Fs%s >", OOPS, temp1, File_Name1);
#else
sprintf(msgbuf,"%s%s%s >", OOPS, temp1, File_Name1);
#endif
break;
case 3: /* Image wrong size */
sprintf(msgbuf, f, OOPS, str3);
break;
case 4: /* Wrong file type */
sprintf(msgbuf, f, OOPS, E1);
break;
}
stopmsg(0,msgbuf);
return;
}
/************************************************************************/
/* */
/* This function opens a TARGA_24 file for reading and writing. If */
/* its a new file, (overlay == 0) it writes a header. If it is to */
/* overlay an existing file (overlay == 1) it copies the original */
/* header whose lenght and validity was determined in */
/* Targa_validate. */
/* */
/* It Verifies there is enough disk space, and leaves the file */
/* at the start of the display data area. */
/* */
/* If this is an overlay, closes source and copies to "targa_temp" */
/* If there is an error close the file. */
/* */
/* **********************************************************************/
static int startdisk1 (char *File_Name2, FILE *Source, int overlay)
{
int i,j,k, inc;
FILE *fps;
/* Open File for both reading and writing */
if ((fps=fopen(File_Name2,"w+b"))==NULL)
{
File_Error(File_Name2, 1);
return(-1); /* Oops, somethings wrong! */
}
inc = 1; /* Assume we are overlaying a file */
/* Write the header */
if (overlay) /* We are overlaying a file */
for (i=0;i<T_header_24;i++) /* Copy the header from the Source */
fputc(fgetc(Source),fps);
else
{ /* Write header for a new file */
/* ID field size = 0, No color map, Targa type 2 file */
for (i=0;i<12;i++)
{
if (i == 2)
fputc(i,fps);
else
fputc(0,fps);
}
/* Write image size */
for (i=0;i<4;i++)
fputc(upr_lwr[i],fps);
fputc(T24,fps); /* Targa 24 file */
fputc(T32,fps); /* Image at upper left */
inc = 3;
}
/* Finished with the header, now lets work on the display area */
for (i=0;i<ydots;i++) /* "clear the screen" (write to the disk) */
{
for (j=0;j<line_length1;j=j+inc)
{
if (overlay)
fputc(fgetc(Source), fps);
else
for (k=2;k>-1;k--)
fputc(back_color[k], fps); /* Targa order (B, G, R) */
}
if (ferror (fps))
{
/* Almost certainly not enough disk space */
fclose (fps);
fclose (Source);
remove (File_Name2);
File_Error(File_Name2, 2);
return(-2);
}
if (check_key()) return(-3);
}
if (targa_startdisk(fps, T_header_24) != 0)
{
enddisk();
remove (File_Name2);
return(-4);
}
return(0);
}
/**************************************************************************
**************************************************************************/
int targa_validate(char *File_Name)
{
FILE *fp;
int i, j = 0;
/* Attempt to open source file for reading */
if ((fp=fopen(File_Name,"rb"))==NULL)
{
File_Error(File_Name, 1);
return(-1); /* Oops, file does not exist */
}
T_header_24 += fgetc(fp); /* Check ID field and adjust header size */
if (fgetc(fp)) /* Make sure this is an unmapped file */
{
File_Error(File_Name, 4);
return(-1);
}
if (fgetc(fp)!=2) /* Make sure it is a type 2 file */
{
File_Error(File_Name, 4);
return(-1);
}
/* Skip color map specification */
for (i=0;i<5;i++)
fgetc(fp);
for (i=0;i<4;i++)
{
/* Check image origin */
fgetc(fp);
if(j != 0)
{
File_Error(File_Name, 4);
return(-1);
}
}
/* Check Image specs */
for (i=0;i<4;i++)
if(fgetc(fp) != upr_lwr[i])
{
File_Error(File_Name,3);
return(-1);
}
if(fgetc(fp) != T24) error=4; /* Is it a targa 24 file? */
if(fgetc(fp) != T32) error=4; /* Is the origin at the upper left? */
if (error == 4)
{
File_Error(File_Name,4);
return(-1);
}
rewind(fp);
/* Now that we know its a good file, create a working copy */
if (startdisk1(targa_temp, fp, 1))
return(-1);
fclose(fp); /* Close the source */
T_Safe=1; /* Original file successfully copied to targa_temp */
return(0);
}
static int R_H (R, G, B, H, S, V)
BYTE R,G,B;
unsigned long *H, *S, *V;
{
unsigned long R1, G1, B1, DENOM;
BYTE MIN;
*V = R;
MIN = G;
if (R < G)
{
*V = G;
MIN = R;
if (G < B) *V = B;
if (B < R) MIN = B;
}
else
{
if (B < G) MIN = B;
if (R < B) *V = B;
}
DENOM = *V - MIN;
if (*V != 0 && DENOM !=0)
{
*S = ((DENOM << 16) / *V) - 1;
}
else *S = 0;/* Color is black! and Sat has no meaning */
if(*S == 0) /* R=G=B => shade of grey and Hue has no meaning */
{
*H = 0;
*V = *V << 8;
return(1); /* v or s or both are 0 */
}
if (*V == MIN)
{
*H = 0;
*V = *V << 8;
return(0);
}
R1 = (((*V - R) * 60) << 6) / DENOM; /* distance of color from red */
G1 = (((*V - G) * 60) << 6) / DENOM; /* distance of color from green */
B1 = (((*V - B) * 60) << 6) / DENOM; /* distance of color from blue */
if(*V == R)
if (MIN == G) *H = (300 << 6) + B1;
else *H = (60 << 6) - G1;
if(*V == G)
if (MIN == B) *H = (60 << 6) + R1;
else *H = (180 << 6) - B1;
if(*V == B)
if(MIN == R) *H = (180 << 6) + G1;
else *H = (300 << 6) - R1;
*V = *V << 8;
return(0);
}
static int H_R (R, G, B, H, S, V)
BYTE *R, *G, *B;
unsigned long H, S, V;
{
unsigned long P1, P2, P3;
int RMD, I;
if(H >= 23040) H = H % 23040; /* Makes h circular */
I = H / 3840;
RMD = H % 3840; /* RMD = fractional part of H */
P1 = ((V * (65535 - S)) / 65280) >> 8;
P2 = (((V * (65535 - (S * RMD) / 3840)) / 65280) - 1) >> 8;
P3 = (((V * (65535 - (S * (3840 - RMD)) / 3840)) / 65280)) >> 8;
V = V >> 8;
switch (I)
{
case 0:
*R = V;
*G = P3;
*B = P1;
break;
case 1:
*R = P2;
*G = V;
*B = P1;
break;
case 2:
*R = P1;
*G = V;
*B = P3;
break;
case 3:
*R = P1;
*G = P2;
*B = V;
break;
case 4:
*R = P3;
*G = P1;
*B = V;
break;
case 5:
*R = V ;
*G = P1;
*B = P2;
break;
}
return(0);
}
/***************************************************************************/
/* */
/* EB & DG fiddled with outputs for Rayshade so they work. with v4.x. */
/* EB == eli brandt. ebrandt@jarthur.claremont.edu */
/* DG == dan goldwater. daniel_goldwater@brown.edu & dgold@math.umass.edu */
/* (NOTE: all the stuff we fiddled with is commented with "EB & DG" (plus even some extra bonus comments!) */
/* general raytracing code info/notes: */
/* */
/* ray == 0 means no raytracer output ray == 7 is for dxf */
/* ray == 1 is for dkb/pov ray == 4 is for mtv */
/* ray == 2 is for vivid ray == 5 is for rayshade */
/* ray == 3 is for raw ray == 6 is for acrospin */
/* */
/* rayshade needs counterclockwise triangles. raytracers that support */
/* the 'heightfield' primitive include rayshade and pov. anyone want to write */
/* code to make heightfields? they are *MUCH* faster to trace than triangles */
/* when doing landscapes... */
/* */
/* stuff EB & DG changed: */
/* made the rayshade output create a "grid" aggregate object (one of rayshade's primitives), instead */
/* of a global grid. as a result, the grid can be optimized based on the number of triangles. */
/* the z component of the grid can always be 1 since the surface formed by the triangles is flat */
/* (ie, it doesnt curve over itself). this is a major optimization. the x and y grid size is */
/* also optimized for a 4:3 aspect ratio image, to get the fewest possible traingles in each grid square. */
/* also, we fixed the rayshade code so it actually produces output that works with rayshade. */
/* (maybe the old code was for a really old version of rayshade?). */
/* */
/* */
/***************************************************************************/
/********************************************************************/
/* */
/* This routine writes a header to a ray tracer data file. It */
/* Identifies the version of FRACTINT which created it an the */
/* key 3D paramete
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -