📄 line3d.c
字号:
/******************************************************************************/
/* This file contains a 3D replacement for the out_line function called */
/* by the decoder. The purpose is to apply various 3D transformations */
/* before displaying points. Called once per line of the input file. */
/* */
/* This module is linked as an overlay, use ENTER_OVLY and EXIT_OVLY. */
/* */
/* Original Author Tim Wegner, with extensive help from Marc Reinig. */
/*****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
#ifndef XFRACT
#include <dos.h>
#endif
#include "fractint.h"
#include "prototyp.h"
struct point
{
int x;
int y;
int color;
};
/* routines in this module */
static void _fastcall vdraw_line(double *,double *,int);
static void (_fastcall *fillplot)(int,int,int);
static void (_fastcall *normalplot)(int,int,int);
static void _fastcall putminmax(int x,int y,int color);
static void _fastcall clipcolor(int x,int y,int color);
static void _fastcall T_clipcolor(int x,int y,int color);
static void _fastcall interpcolor(int x,int y,int color);
static void corners(),draw_light_box();
static void _fastcall putatriangle(struct point pt1,struct point pt2,
struct point pt3,int color);
static int _fastcall offscreen(struct point pt);
static int H_R(),R_H();
static int startdisk1(char *File_Name2, FILE *Source, int overlay);
static int set_pixel_buff();
static void line3d_cleanup();
extern int glassestype, whichimage;
void (_fastcall *standardplot)(int,int,int);
static int line_length1;
static int T_header_24 = 18; /* Size of current Targa-24 header */
extern BYTE dacbox[256][3];
MATRIX m; /* transformation matrix */
void (*mult_vec)(VECTOR) = mult_vec_c;
extern int iit; /* iit flag */
static FILE *File_Ptr1 = NULL;
int Ambient;
static unsigned int IAmbient;
int RANDOMIZE;
static int rand_factor;
int haze;
static int HAZE_MULT;
int Real_V = 0; /* mrr Actual value of V for fillytpe>4 monochrome images */
char light_name[80] = "fract001";
int Targa_Overlay, error;
extern int Targa_Out;
char targa_temp[14] = "fractemp.tga";
static void File_Error (char *File_Name1, int ERROR);
static BYTE T24=24;
static BYTE T32=32;
static BYTE upr_lwr[4];
static int T_Safe; /* Original Targa Image successfully copied to targa_temp */
int P = 250; /* Perspective dist used when viewing light vector */
static void draw_rect (VECTOR V0, VECTOR V1, VECTOR V2, VECTOR V3, int color,
int rect);
static VECTOR light_direction;
BYTE back_color[3];
static BYTE Real_Color; /* Actual color of cur pixel */
extern int dotmode; /* video access method, 11 if really disk video */
extern int calc_status;
extern long calctime;
extern int got_status,currow;
static int RO, CO, CO_MAX; /* For use in Acrospin support */
static char far acro_s1[] =
{"Set Layer 1\nSet Color 2\nEndpointList X Y Z Name\n"};
static char far acro_s2[] = {"LineList From To\n"};
static char far s3[] = {"{ Created by FRACTINT Ver. "};
static char far s3a[] = {" }\n\n"};
#ifndef XFRACT
static char banner[] ="%Fs%#4.2f%Fs";
#else
static char banner[] ="%s%#4.2f%s";
#endif
char ray_name[80] = "fract001";
char preview = 0;
char showbox = 0;
static int localpreviewfactor;
int previewfactor = 20;
int xadjust = 0;
int yadjust = 0;
int xxadjust;
int yyadjust;
int xshift;
int yshift;
extern int overflow;
extern int filetype;
extern char usr_floatflag;
extern int xdots, ydots, colors, sxoffs, syoffs;
extern int debugflag;
extern SEGTYPE extraseg;
extern unsigned height;
extern int rowcount; /* in general.asm */
extern int init3d[]; /* 3D arguments (FRACTINT.C) */
extern long far *lx0;
extern int transparent[2]; /* transparency min/max */
extern int pot16bit;
extern int filecolors;
extern void (*outln_cleanup)();
static int zcoord = 256;
static double aspect; /* aspect ratio */
static int evenoddrow;
static float far *sinthetaarray; /* all sine thetas go here */
static float far *costhetaarray; /* all cosine thetas go here */
static double rXrscale; /* precalculation factor */
static int persp; /* flag for indicating perspective transformations */
int bad_value = -10000; /* set bad values to this */
int bad_check = -3000; /* check values against this to determine if good */
/* this array remembers the previous line */
struct point far *lastrow;
static struct point p1,p2,p3;
struct f_point
{
float x;
float y;
float color;
}
far *f_lastrow;
int RAY = 0; /* Flag to generate Ray trace compatible files in 3d */
int BRIEF = 0; /* 1 = short ray trace files */
extern int release; /* Current release level of Fractint */
static int _fastcall RAY_Header(void);
static void _fastcall triangle_bounds(float pt_t[3][3]);
static int _fastcall out_triangle(struct f_point pt1, struct f_point pt2,
struct f_point pt3, int c1, int c2, int c3);
static float min_xyz[3], max_xyz[3]; /* For Raytrace output */
static int _fastcall start_object(void);
static int _fastcall end_object(int triout);
extern unsigned numcolors; /* number of colors in original GIF */
static long num_tris; /* number of triangles output to ray trace file */
/* array of min and max x values used in triangle fill */
struct minmax
{
int minx;
int maxx;
}
far *minmax_x;
VECTOR view; /* position of observer for perspective */
VECTOR cross;
VECTOR tmpcross;
struct point oldlast =
{
0, 0, 0
}; /* old pixels */
void line3d_overlay() {
} /* for restore_active_ovly */
int line3d(BYTE *pixels, unsigned linelen)
{
int tout; /* triangle has been sent to ray trace file */
int RND;
float f_water; /* transformed WATERLINE for ray trace files */
/* these values come from FRACTINT.C */
/* These variables must preserve their values across calls */
static float deltaphi; /* increment of latitude, longitude */
static double rscale; /* surface roughness factor */
static long xcenter,ycenter; /* circle center */
double r0;
int xcenter0,ycenter0; /* Unfudged versions */
static double sclx,scly,sclz; /* scale factors */
static double R; /* radius values */
static double Rfactor; /* for intermediate calculation */
MATRIX lightm; /* m w/no trans, keeps obj. on screen */
static LMATRIX lm; /* "" */
static LVECTOR lview; /* for perspective views */
static double zcutoff; /* perspective backside cutoff value */
static float twocosdeltaphi;
static float cosphi,sinphi; /* precalculated sin/cos of longitude */
static float oldcosphi1,oldsinphi1;
static float oldcosphi2,oldsinphi2;
double r; /* sphere radius */
double xval,yval,zval; /* rotation values */
float costheta,sintheta; /* precalculated sin/cos of latitude */
float twocosdeltatheta;
int next; /* used by preview and grid */
int col; /* current column (original GIF) */
struct point cur; /* current pixels */
struct point old; /* old pixels */
static struct point bad; /* out of range value */
struct f_point f_cur;
struct f_point f_old;
static struct f_point f_bad; /* out of range value */
static BYTE far *fraction;/* float version of pixels array */
VECTOR v; /* double vector */
VECTOR v1,v2;
VECTOR crossavg;
char crossnotinit; /* flag for crossavg init indication */
double v_length;
VECTOR origin, direct, tmp;
LVECTOR lv; /* long equivalent of v */
LVECTOR lv0; /* long equivalent of v */
/* corners of transformed xdotx by ydots x colors box */
double xmin, ymin, zmin, xmax, ymax, zmax;
int i,j;
int lastdot;
long fudge;
ENTER_OVLY(OVLY_LINE3D);
fudge = 1L<<16;
if(transparent[0] || transparent[1])
plot = normalplot = T_clipcolor; /* Use transparent plot function */
else /* Use the usual FRACTINT plot function with clipping */
plot = normalplot = clipcolor;
currow = rowcount; /* use separate variable to allow for pot16bit files */
if (pot16bit)
currow >>= 1;
/************************************************************************/
/* This IF clause is executed ONCE per image. All precalculations are */
/* done here, with out any special concern about speed. DANGER - */
/* communication with the rest of the program is generally via static */
/* or global variables. */
/************************************************************************/
if(rowcount++ == 0)
{
long check_extra;
float theta,theta1,theta2; /* current,start,stop latitude */
float phi1,phi2; /* current start,stop longitude */
float deltatheta; /* increment of latitude */
outln_cleanup = line3d_cleanup;
calctime = evenoddrow = 0;
/* mark as in-progress, and enable <tab> timer display */
calc_status = 1;
IAmbient = (unsigned int) (255 * (float)(100 - Ambient) / 100.0);
if (IAmbient < 1) IAmbient = 1;
tout = 0;
num_tris = 0;
/* Open file for RAY trace output and write header */
if (RAY)
{
RAY_Header();
xxadjust = yyadjust = 0; /* Disable shifting in ray tracing */
xshift = yshift = 0;
}
CO_MAX=CO=RO=0;
upr_lwr[0] = xdots & 0xff;
upr_lwr[1] = xdots >> 8;
upr_lwr[2] = ydots & 0xff;
upr_lwr[3] = ydots >> 8;
line_length1 = 3 * xdots; /* line length @ 3 bytes per pixel */
error = 0;
if (whichimage < 2)
T_Safe = 0; /* Not safe yet to mess with the source image */
if (Targa_Out && !((glassestype==1 || glassestype==2) && whichimage==2))
{
if (Targa_Overlay)
{
/* Make sure target file is a supportable Targa File */
if(targa_validate (light_name))
return(-1);
}
else
{
check_writefile(light_name,".tga");
if (startdisk1(light_name, NULL, 0)) /* Open new file */
return(-1);
}
}
rand_factor = 14 - RANDOMIZE;
zcoord = filecolors;
crossavg[0] = 0;
crossavg[1] = 0;
crossavg[2] = 0;
/*********************************************************************/
/* Memory allocation - assumptions - a 64K segment starting at */
/* extraseg has been grabbed. It may have other purposes elsewhere, */
/* but it is assumed that it is totally free for use here. Our */
/* strategy is to assign all the far pointers needed here to various*/
/* spots in the extra segment, depending on the pixel dimensions of */
/* the video mode, and check whether we have run out. There is */
/* basically one case where the extra segment is not big enough */
/* -- SPHERE mode with a fill type that uses putatriangle() (array */
/* minmax_x) at the largest legal resolution of MAXPIXELSxMAXPIXELS or */
/* thereabouts. In that case we use farmemalloc to grab memory */
/* for minmax_x. This memory is never freed. */
/*********************************************************************/
/* lastrow stores the previous row of the original GIF image for
the purpose of filling in gaps with triangle procedure */
lastrow = MK_FP(extraseg,0);
check_extra = sizeof(*lastrow)*xdots;
if(SPHERE)
{
sinthetaarray = (float far *)(lastrow+xdots);
check_extra += sizeof(*sinthetaarray)*xdots;
costhetaarray = (float far *)(sinthetaarray+xdots);
check_extra += sizeof(*costhetaarray)*xdots;
f_lastrow = (struct f_point far *)(costhetaarray+xdots);
}
else
f_lastrow = (struct f_point far *)(lastrow+xdots);
check_extra += sizeof(*f_lastrow)*(xdots);
if(pot16bit)
{
fraction = (BYTE far *)(f_lastrow+xdots);
check_extra += sizeof(*fraction)*xdots;
}
minmax_x = (struct minmax *)NULL;
/* these fill types call putatriangle which uses minmax_x */
if( FILLTYPE == 2 || FILLTYPE == 3 || FILLTYPE == 5 || FILLTYPE == 6)
{
/* end of arrays if we use extra segement */
check_extra += sizeof(struct minmax)*ydots;
if(check_extra > (1L<<16)) /* run out of extra segment? */
{
static struct minmax far *got_mem = NULL;
/* not using extra segment so decrement check_extra */
check_extra -= sizeof(struct minmax)*ydots;
if(got_mem == NULL)
got_mem = (struct minmax far *)(farmemalloc(MAXPIXELS *
sizeof(struct minmax)));
if(got_mem)
minmax_x = got_mem;
else
{
EXIT_OVLY;
return(-1);
}
}
else /* ok to use extra segment */
{
if(pot16bit)
minmax_x = (struct minmax far *)(fraction+xdots);
else
minmax_x = (struct minmax far *)(f_lastrow+xdots);
}
}
if(debugflag == 2222 || check_extra > (1L<<16))
{
char tmpmsg[70];
static char far extramsg[] = {" of extra segment"};
#ifndef XFRACT
sprintf(tmpmsg,"used %ld%Fs", check_extra, extramsg);
#else
sprintf(tmpmsg,"used %ld%s", check_extra, extramsg);
#endif
stopmsg(4,tmpmsg);
}
/* get scale factors */
sclx = XSCALE/100.0;
scly = YSCALE/100.0;
if (ROUGH)
sclz = -ROUGH/100.0;
else
rscale = sclz = -0.0001; /* if rough=0 make it very flat but plot something */
/* aspect ratio calculation - assume screen is 4 x 3 */
aspect = (double)xdots*.75/(double)ydots;
if(SPHERE==FALSE) /* skip this slow stuff in sphere case */
{
/*********************************************************************/
/* What is done here is to create a single matrix, m, which has */
/* scale, rotation, and shift all combined. This allows us to use */
/* a single matrix to transform any point. Additionally, we create */
/* two perspective vectors. */
/* */
/* Start with a unit matrix. Add scale and rotation. Then calculate */
/* the perspective vectors. Finally add enough translation to center */
/* the final image plus whatever shift the user has set. */
/*********************************************************************/
/* start with identity */
identity (m);
identity (lightm);
/* translate so origin is in center of box, so that when we rotate */
/* it, we do so through the center */
trans ( (double)xdots/(-2.0),(double)ydots/(-2.0),
(double)zcoord/(-2.0),m);
trans ( (double)xdots/(-2.0),(double)ydots/(-2.0),
(double)zcoord/(-2.0),lightm);
/* apply scale factors */
scale(sclx,scly,sclz,m);
scale(sclx,scly,sclz,lightm);
/* rotation values - converting from degrees to radians */
xval = XROT / 57.29577;
yval = YROT / 57.29577;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -