2334 lines
47 KiB
C
2334 lines
47 KiB
C
/**
|
|
* $Id$
|
|
*
|
|
* ***** BEGIN GPL/BL DUAL LICENSE BLOCK *****
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version. The Blender
|
|
* Foundation also sells licenses for use in proprietary software under
|
|
* the Blender License. See http://www.blender.org/BL/ for information
|
|
* about this.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
* The Original Code is Copyright (C) 2001-2002 by NaN Holding BV.
|
|
* All rights reserved.
|
|
*
|
|
* The Original Code is: all of this file.
|
|
*
|
|
* Contributor(s): Hos, RPW.
|
|
*
|
|
* ***** END GPL/BL DUAL LICENSE BLOCK *****
|
|
*/
|
|
|
|
/*---------------------------------------------------------------------------*/
|
|
/* Common includes */
|
|
/*---------------------------------------------------------------------------*/
|
|
|
|
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <string.h>
|
|
#include "MTC_matrixops.h"
|
|
#include "MEM_guardedalloc.h"
|
|
|
|
#include "BKE_global.h"
|
|
|
|
#include "DNA_lamp_types.h"
|
|
#include "DNA_mesh_types.h"
|
|
|
|
#include "radio_types.h"
|
|
#include "radio.h" /* needs RG, some root data for radiosity */
|
|
|
|
#include "render.h"
|
|
#include "render_intern.h"
|
|
#include "RE_callbacks.h"
|
|
#include "old_zbuffer_types.h"
|
|
/* local includes */
|
|
/* can be removed when the old renderer disappears */
|
|
#include "rendercore.h" /* shade_pixel and count_mask */
|
|
#include "pixelblending.h"
|
|
#include "jitter.h"
|
|
|
|
/* own includes */
|
|
#include "zbuf.h"
|
|
#include "zbuf_int.h"
|
|
|
|
#ifdef HAVE_CONFIG_H
|
|
#include <config.h>
|
|
#endif
|
|
|
|
/* crud */
|
|
#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
|
|
/*-----------------------------------------------------------*/
|
|
/* Globals for this file */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
extern float centLut[16];
|
|
extern char *centmask;
|
|
|
|
float *vlzp[32][3], labda[3][2], vez[400], *p[40];
|
|
|
|
float Zmulx; /* Half the screenwidth, in pixels. (used in render.c, */
|
|
/* zbuf.c) */
|
|
float Zmuly; /* Half the screenheight, in pixels. (used in render.c,*/
|
|
/* zbuf.c) */
|
|
float Zjitx; /* Jitter offset in x. When jitter is disabled, this */
|
|
/* should be 0.5. (used in render.c, zbuf.c) */
|
|
float Zjity; /* Jitter offset in y. When jitter is disabled, this */
|
|
/* should be 0.5. (used in render.c, zbuf.c) */
|
|
|
|
unsigned int Zvlnr, Zsample;
|
|
VlakRen *Zvlr;
|
|
void (*zbuffunc)(float *, float *, float *);
|
|
void (*zbuflinefunc)(float *, float *);
|
|
|
|
APixstr *APixbuf; /* Zbuffer: linked list of face indices */
|
|
unsigned short *Acolrow; /* Zbuffer: colour buffer, one line high */
|
|
int *Arectz; /* Zbuffer: distance buffer, almost obsolete */
|
|
int Aminy; /* y value of first line in the accu buffer */
|
|
int Amaxy; /* y value of last line in the accu buffer */
|
|
int Azvoordeel = 0;
|
|
APixstrMain apsmfirst;
|
|
short apsmteller = 0;
|
|
|
|
/*-----------------------------------------------------------*/
|
|
/* Functions */
|
|
/*-----------------------------------------------------------*/
|
|
|
|
void fillrect(unsigned int *rect, int x, unsigned int y, unsigned int val)
|
|
{
|
|
unsigned int len,*drect;
|
|
|
|
len= x*y;
|
|
drect= rect;
|
|
while(len>0) {
|
|
len--;
|
|
*drect= val;
|
|
drect++;
|
|
}
|
|
}
|
|
|
|
/* ************* ACCU ZBUF ************ */
|
|
|
|
/*-APixstr---------------------------------------------------*/
|
|
|
|
APixstr *addpsmainA()
|
|
{
|
|
APixstrMain *psm;
|
|
|
|
psm= &apsmfirst;
|
|
|
|
while(psm->next) {
|
|
psm= psm->next;
|
|
}
|
|
|
|
psm->next= MEM_mallocN(sizeof(APixstrMain), "addpsmainA");
|
|
|
|
psm= psm->next;
|
|
psm->next=0;
|
|
psm->ps= MEM_callocN(4096*sizeof(APixstr),"pixstr");
|
|
apsmteller= 0;
|
|
|
|
return psm->ps;
|
|
}
|
|
|
|
void freepsA()
|
|
{
|
|
APixstrMain *psm, *next;
|
|
|
|
psm= &apsmfirst;
|
|
|
|
while(psm) {
|
|
next= psm->next;
|
|
if(psm->ps) {
|
|
MEM_freeN(psm->ps);
|
|
psm->ps= 0;
|
|
}
|
|
if(psm!= &apsmfirst) MEM_freeN(psm);
|
|
psm= next;
|
|
}
|
|
|
|
apsmfirst.next= 0;
|
|
apsmfirst.ps= 0;
|
|
apsmteller= 0;
|
|
}
|
|
|
|
APixstr *addpsA(void)
|
|
{
|
|
static APixstr *prev;
|
|
|
|
/* eerste PS maken */
|
|
if((apsmteller & 4095)==0) prev= addpsmainA();
|
|
else prev++;
|
|
apsmteller++;
|
|
|
|
return prev;
|
|
}
|
|
|
|
/* vult kleur in, met windowcoordinaat, van Aminy->Amaxy */
|
|
void zbufinvulAc(float *v1, float *v2, float *v3)
|
|
{
|
|
APixstr *ap, *apofs, *apn;
|
|
double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
|
|
double zxd,zyd,zy0, tmp;
|
|
float *minv,*maxv,*midv;
|
|
int *rz,zverg,x;
|
|
int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
|
|
int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2, mask;
|
|
|
|
/* MIN MAX */
|
|
if(v1[1]<v2[1]) {
|
|
if(v2[1]<v3[1]) {
|
|
minv=v1; midv=v2; maxv=v3;
|
|
}
|
|
else if(v1[1]<v3[1]) {
|
|
minv=v1; midv=v3; maxv=v2;
|
|
}
|
|
else {
|
|
minv=v3; midv=v1; maxv=v2;
|
|
}
|
|
}
|
|
else {
|
|
if(v1[1]<v3[1]) {
|
|
minv=v2; midv=v1; maxv=v3;
|
|
}
|
|
else if(v2[1]<v3[1]) {
|
|
minv=v2; midv=v3; maxv=v1;
|
|
}
|
|
else {
|
|
minv=v3; midv=v2; maxv=v1;
|
|
}
|
|
}
|
|
|
|
if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
|
|
|
|
my0= ceil(minv[1]);
|
|
my2= floor(maxv[1]);
|
|
omsl= floor(midv[1]);
|
|
|
|
if(my2<Aminy || my0> Amaxy) return;
|
|
|
|
if(my0<Aminy) my0= Aminy;
|
|
|
|
/* EDGES : DE LANGSTE */
|
|
xx1= maxv[1]-minv[1];
|
|
if(xx1>2.0/65536.0) {
|
|
z0= (maxv[0]-minv[0])/xx1;
|
|
|
|
tmp= (-65536.0*z0);
|
|
dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
|
|
xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx0= 0;
|
|
xs0= 65536.0*(MIN2(minv[0],maxv[0]));
|
|
}
|
|
/* EDGES : DE BOVENSTE */
|
|
xx1= maxv[1]-midv[1];
|
|
if(xx1>2.0/65536.0) {
|
|
z0= (maxv[0]-midv[0])/xx1;
|
|
|
|
tmp= (-65536.0*z0);
|
|
dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
|
|
xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx1= 0;
|
|
xs1= 65536.0*(MIN2(midv[0],maxv[0]));
|
|
}
|
|
/* EDGES : DE ONDERSTE */
|
|
xx1= midv[1]-minv[1];
|
|
if(xx1>2.0/65536.0) {
|
|
z0= (midv[0]-minv[0])/xx1;
|
|
|
|
tmp= (-65536.0*z0);
|
|
dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
|
|
xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx2= 0;
|
|
xs2= 65536.0*(MIN2(minv[0],midv[0]));
|
|
}
|
|
|
|
/* ZBUF DX DY */
|
|
x1= v1[0]- v2[0];
|
|
x2= v2[0]- v3[0];
|
|
y1= v1[1]- v2[1];
|
|
y2= v2[1]- v3[1];
|
|
z1= v1[2]- v2[2];
|
|
z2= v2[2]- v3[2];
|
|
x0= y1*z2-z1*y2;
|
|
y0= z1*x2-x1*z2;
|
|
z0= x1*y2-y1*x2;
|
|
if(z0==0.0) return;
|
|
|
|
if(midv[1]==maxv[1]) omsl= my2;
|
|
if(omsl<Aminy) omsl= Aminy-1; /* dan neemt ie de eerste lus helemaal */
|
|
|
|
while (my2 > Amaxy) { /* my2 kan groter zijn */
|
|
xs0+=dx0;
|
|
if (my2<=omsl) {
|
|
xs2+= dx2;
|
|
}
|
|
else{
|
|
xs1+= dx1;
|
|
}
|
|
my2--;
|
|
}
|
|
|
|
xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
|
|
|
|
zxd= -x0/z0;
|
|
zyd= -y0/z0;
|
|
zy0= my2*zyd+xx1;
|
|
zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
|
|
|
|
/* start-ofset in rect */
|
|
rectx= R.rectx;
|
|
rectzofs= (int *)(Arectz+rectx*(my2-Aminy));
|
|
apofs= (APixbuf+ rectx*(my2-Aminy));
|
|
mask= 1<<Zsample;
|
|
|
|
xs3= 0; /* flag */
|
|
if(dx0>dx1) {
|
|
xs3= xs0;
|
|
xs0= xs1;
|
|
xs1= xs3;
|
|
xs3= dx0;
|
|
dx0= dx1;
|
|
dx1= xs3;
|
|
xs3= 1; /* flag */
|
|
|
|
}
|
|
|
|
for(y=my2;y>omsl;y--) {
|
|
|
|
sn1= xs0>>16;
|
|
xs0+= dx0;
|
|
|
|
sn2= xs1>>16;
|
|
xs1+= dx1;
|
|
|
|
sn1++;
|
|
|
|
if(sn2>=rectx) sn2= rectx-1;
|
|
if(sn1<0) sn1= 0;
|
|
zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
|
|
rz= rectzofs+sn1;
|
|
ap= apofs+sn1;
|
|
x= sn2-sn1;
|
|
|
|
zverg-= Azvoordeel;
|
|
|
|
while(x>=0) {
|
|
if(zverg< *rz) {
|
|
apn= ap;
|
|
while(apn) { /* loopunrolled */
|
|
if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
|
|
if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
|
|
if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
|
|
if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
|
|
if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
|
|
if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
|
|
if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
|
|
if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
|
|
if(apn->next==0) apn->next= addpsA();
|
|
apn= apn->next;
|
|
}
|
|
}
|
|
zverg+= zd;
|
|
rz++;
|
|
ap++;
|
|
x--;
|
|
}
|
|
zy0-= zyd;
|
|
rectzofs-= rectx;
|
|
apofs-= rectx;
|
|
}
|
|
|
|
if(xs3) {
|
|
xs0= xs1;
|
|
dx0= dx1;
|
|
}
|
|
if(xs0>xs2) {
|
|
xs3= xs0;
|
|
xs0= xs2;
|
|
xs2= xs3;
|
|
xs3= dx0;
|
|
dx0= dx2;
|
|
dx2= xs3;
|
|
}
|
|
|
|
for(; y>=my0; y--) {
|
|
|
|
sn1= xs0>>16;
|
|
xs0+= dx0;
|
|
|
|
sn2= xs2>>16;
|
|
xs2+= dx2;
|
|
|
|
sn1++;
|
|
|
|
if(sn2>=rectx) sn2= rectx-1;
|
|
if(sn1<0) sn1= 0;
|
|
zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
|
|
rz= rectzofs+sn1;
|
|
ap= apofs+sn1;
|
|
x= sn2-sn1;
|
|
|
|
zverg-= Azvoordeel;
|
|
|
|
while(x>=0) {
|
|
if(zverg< *rz) {
|
|
apn= ap;
|
|
while(apn) { /* loopunrolled */
|
|
if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= zverg; apn->mask[0]= mask; break; }
|
|
if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
|
|
if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= zverg; apn->mask[1]= mask; break; }
|
|
if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
|
|
if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= zverg; apn->mask[2]= mask; break; }
|
|
if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
|
|
if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= zverg; apn->mask[3]= mask; break; }
|
|
if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
|
|
if(apn->next==0) apn->next= addpsA();
|
|
apn= apn->next;
|
|
}
|
|
}
|
|
zverg+= zd;
|
|
rz++;
|
|
ap++;
|
|
x--;
|
|
}
|
|
|
|
zy0-=zyd;
|
|
rectzofs-= rectx;
|
|
apofs-= rectx;
|
|
}
|
|
}
|
|
|
|
void zbuflineAc(float *vec1, float *vec2)
|
|
{
|
|
APixstr *ap, *apn;
|
|
unsigned int *rectz;
|
|
int start, end, x, y, oldx, oldy, ofs;
|
|
int dz, vergz, mask;
|
|
float dx, dy;
|
|
float v1[3], v2[3];
|
|
|
|
dx= vec2[0]-vec1[0];
|
|
dy= vec2[1]-vec1[1];
|
|
|
|
if(fabs(dx) > fabs(dy)) {
|
|
|
|
/* alle lijnen van links naar rechts */
|
|
if(vec1[0]<vec2[0]) {
|
|
VECCOPY(v1, vec1);
|
|
VECCOPY(v2, vec2);
|
|
}
|
|
else {
|
|
VECCOPY(v2, vec1);
|
|
VECCOPY(v1, vec2);
|
|
dx= -dx; dy= -dy;
|
|
}
|
|
|
|
start= floor(v1[0]);
|
|
end= start+floor(dx);
|
|
if(end>=R.rectx) end= R.rectx-1;
|
|
|
|
oldy= floor(v1[1]);
|
|
dy/= dx;
|
|
|
|
vergz= v1[2];
|
|
vergz-= Azvoordeel;
|
|
dz= (v2[2]-v1[2])/dx;
|
|
|
|
rectz= (unsigned int *)(Arectz+R.rectx*(oldy-Aminy) +start);
|
|
ap= (APixbuf+ R.rectx*(oldy-Aminy) +start);
|
|
mask= 1<<Zsample;
|
|
|
|
if(dy<0) ofs= -R.rectx;
|
|
else ofs= R.rectx;
|
|
|
|
for(x= start; x<=end; x++, rectz++, ap++) {
|
|
|
|
y= floor(v1[1]);
|
|
if(y!=oldy) {
|
|
oldy= y;
|
|
rectz+= ofs;
|
|
ap+= ofs;
|
|
}
|
|
|
|
if(x>=0 && y>=Aminy && y<=Amaxy) {
|
|
if(vergz<*rectz) {
|
|
|
|
apn= ap;
|
|
while(apn) { /* loopunrolled */
|
|
if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
|
|
if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
|
|
if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
|
|
if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
|
|
if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
|
|
if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
|
|
if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
|
|
if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
|
|
if(apn->next==0) apn->next= addpsA();
|
|
apn= apn->next;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
v1[1]+= dy;
|
|
vergz+= dz;
|
|
}
|
|
}
|
|
else {
|
|
|
|
/* alle lijnen van onder naar boven */
|
|
if(vec1[1]<vec2[1]) {
|
|
VECCOPY(v1, vec1);
|
|
VECCOPY(v2, vec2);
|
|
}
|
|
else {
|
|
VECCOPY(v2, vec1);
|
|
VECCOPY(v1, vec2);
|
|
dx= -dx; dy= -dy;
|
|
}
|
|
|
|
start= floor(v1[1]);
|
|
end= start+floor(dy);
|
|
|
|
if(start>Amaxy || end<Aminy) return;
|
|
|
|
if(end>Amaxy) end= Amaxy;
|
|
|
|
oldx= floor(v1[0]);
|
|
dx/= dy;
|
|
|
|
vergz= v1[2];
|
|
vergz-= Azvoordeel;
|
|
dz= (v2[2]-v1[2])/dy;
|
|
|
|
rectz= (unsigned int *)( Arectz+ (start-Aminy)*R.rectx+ oldx );
|
|
ap= (APixbuf+ R.rectx*(start-Aminy) +oldx);
|
|
mask= 1<<Zsample;
|
|
|
|
if(dx<0) ofs= -1;
|
|
else ofs= 1;
|
|
|
|
for(y= start; y<=end; y++, rectz+=R.rectx, ap+=R.rectx) {
|
|
|
|
x= floor(v1[0]);
|
|
if(x!=oldx) {
|
|
oldx= x;
|
|
rectz+= ofs;
|
|
ap+= ofs;
|
|
}
|
|
|
|
if(x>=0 && y>=Aminy && x<R.rectx) {
|
|
if(vergz<*rectz) {
|
|
|
|
apn= ap;
|
|
while(apn) { /* loopunrolled */
|
|
if(apn->p[0]==0) {apn->p[0]= Zvlnr; apn->z[0]= vergz; apn->mask[0]= mask; break; }
|
|
if(apn->p[0]==Zvlnr) {apn->mask[0]|= mask; break; }
|
|
if(apn->p[1]==0) {apn->p[1]= Zvlnr; apn->z[1]= vergz; apn->mask[1]= mask; break; }
|
|
if(apn->p[1]==Zvlnr) {apn->mask[1]|= mask; break; }
|
|
if(apn->p[2]==0) {apn->p[2]= Zvlnr; apn->z[2]= vergz; apn->mask[2]= mask; break; }
|
|
if(apn->p[2]==Zvlnr) {apn->mask[2]|= mask; break; }
|
|
if(apn->p[3]==0) {apn->p[3]= Zvlnr; apn->z[3]= vergz; apn->mask[3]= mask; break; }
|
|
if(apn->p[3]==Zvlnr) {apn->mask[3]|= mask; break; }
|
|
if(apn->next==0) apn->next= addpsA();
|
|
apn= apn->next;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
v1[0]+= dx;
|
|
vergz+= dz;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* ************* NORMAL ZBUFFER ************ */
|
|
|
|
void hoco_to_zco(float *zco, float *hoco)
|
|
{
|
|
float deler;
|
|
|
|
deler= hoco[3];
|
|
zco[0]= Zmulx*(1.0+hoco[0]/deler)+ Zjitx;
|
|
zco[1]= Zmuly*(1.0+hoco[1]/deler)+ Zjity;
|
|
zco[2]= 0x7FFFFFFF *(hoco[2]/deler);
|
|
}
|
|
|
|
void zbufline(vec1, vec2)
|
|
float *vec1, *vec2;
|
|
{
|
|
unsigned int *rectz, *rectp;
|
|
int start, end, x, y, oldx, oldy, ofs;
|
|
int dz, vergz;
|
|
float dx, dy;
|
|
float v1[3], v2[3];
|
|
|
|
dx= vec2[0]-vec1[0];
|
|
dy= vec2[1]-vec1[1];
|
|
|
|
if(fabs(dx) > fabs(dy)) {
|
|
|
|
/* alle lijnen van links naar rechts */
|
|
if(vec1[0]<vec2[0]) {
|
|
VECCOPY(v1, vec1);
|
|
VECCOPY(v2, vec2);
|
|
}
|
|
else {
|
|
VECCOPY(v2, vec1);
|
|
VECCOPY(v1, vec2);
|
|
dx= -dx; dy= -dy;
|
|
}
|
|
|
|
start= floor(v1[0]);
|
|
end= start+floor(dx);
|
|
if(end>=R.rectx) end= R.rectx-1;
|
|
|
|
oldy= floor(v1[1]);
|
|
dy/= dx;
|
|
|
|
vergz= v1[2];
|
|
dz= (v2[2]-v1[2])/dx;
|
|
|
|
rectz= R.rectz+ oldy*R.rectx+ start;
|
|
rectp= R.rectot+ oldy*R.rectx+ start;
|
|
|
|
if(dy<0) ofs= -R.rectx;
|
|
else ofs= R.rectx;
|
|
|
|
for(x= start; x<=end; x++, rectz++, rectp++) {
|
|
|
|
y= floor(v1[1]);
|
|
if(y!=oldy) {
|
|
oldy= y;
|
|
rectz+= ofs;
|
|
rectp+= ofs;
|
|
}
|
|
|
|
if(x>=0 && y>=0 && y<R.recty) {
|
|
if(vergz<*rectz) {
|
|
*rectz= vergz;
|
|
*rectp= Zvlnr;
|
|
}
|
|
}
|
|
|
|
v1[1]+= dy;
|
|
vergz+= dz;
|
|
}
|
|
}
|
|
else {
|
|
/* alle lijnen van onder naar boven */
|
|
if(vec1[1]<vec2[1]) {
|
|
VECCOPY(v1, vec1);
|
|
VECCOPY(v2, vec2);
|
|
}
|
|
else {
|
|
VECCOPY(v2, vec1);
|
|
VECCOPY(v1, vec2);
|
|
dx= -dx; dy= -dy;
|
|
}
|
|
|
|
start= floor(v1[1]);
|
|
end= start+floor(dy);
|
|
|
|
if(end>=R.recty) end= R.recty-1;
|
|
|
|
oldx= floor(v1[0]);
|
|
dx/= dy;
|
|
|
|
vergz= v1[2];
|
|
dz= (v2[2]-v1[2])/dy;
|
|
|
|
rectz= R.rectz+ start*R.rectx+ oldx;
|
|
rectp= R.rectot+ start*R.rectx+ oldx;
|
|
|
|
if(dx<0) ofs= -1;
|
|
else ofs= 1;
|
|
|
|
for(y= start; y<=end; y++, rectz+=R.rectx, rectp+=R.rectx) {
|
|
|
|
x= floor(v1[0]);
|
|
if(x!=oldx) {
|
|
oldx= x;
|
|
rectz+= ofs;
|
|
rectp+= ofs;
|
|
}
|
|
|
|
if(x>=0 && y>=0 && x<R.rectx) {
|
|
if(vergz<*rectz) {
|
|
*rectz= vergz;
|
|
*rectp= Zvlnr;
|
|
}
|
|
}
|
|
|
|
v1[0]+= dx;
|
|
vergz+= dz;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
void zbufclipwire(VlakRen *vlr)
|
|
{
|
|
float *f1, *f2, *f3, *f4= 0, deler;
|
|
int c1, c2, c3, c4, ec, and, or;
|
|
|
|
/* edgecode: 1= tekenen */
|
|
ec = vlr->ec;
|
|
if(ec==0) return;
|
|
|
|
c1= vlr->v1->clip;
|
|
c2= vlr->v2->clip;
|
|
c3= vlr->v3->clip;
|
|
f1= vlr->v1->ho;
|
|
f2= vlr->v2->ho;
|
|
f3= vlr->v3->ho;
|
|
|
|
if(vlr->v4) {
|
|
f4= vlr->v4->ho;
|
|
c4= vlr->v4->clip;
|
|
|
|
and= (c1 & c2 & c3 & c4);
|
|
or= (c1 | c2 | c3 | c4);
|
|
}
|
|
else {
|
|
and= (c1 & c2 & c3);
|
|
or= (c1 | c2 | c3);
|
|
}
|
|
|
|
if(or) { /* niet in midden */
|
|
if(and) { /* helemaal eruit */
|
|
return;
|
|
}
|
|
else { /* clippen */
|
|
|
|
if(ec & ME_V1V2) {
|
|
QUATCOPY(vez, f1);
|
|
QUATCOPY(vez+4, f2);
|
|
if( clipline(vez, vez+4)) {
|
|
hoco_to_zco(vez, vez);
|
|
hoco_to_zco(vez+4, vez+4);
|
|
zbuflinefunc(vez, vez+4);
|
|
}
|
|
}
|
|
if(ec & ME_V2V3) {
|
|
QUATCOPY(vez, f2);
|
|
QUATCOPY(vez+4, f3);
|
|
if( clipline(vez, vez+4)) {
|
|
hoco_to_zco(vez, vez);
|
|
hoco_to_zco(vez+4, vez+4);
|
|
zbuflinefunc(vez, vez+4);
|
|
}
|
|
}
|
|
if(vlr->v4) {
|
|
if(ec & ME_V3V4) {
|
|
QUATCOPY(vez, f3);
|
|
QUATCOPY(vez+4, f4);
|
|
if( clipline(vez, vez+4)) {
|
|
hoco_to_zco(vez, vez);
|
|
hoco_to_zco(vez+4, vez+4);
|
|
zbuflinefunc(vez, vez+4);
|
|
}
|
|
}
|
|
if(ec & ME_V4V1) {
|
|
QUATCOPY(vez, f4);
|
|
QUATCOPY(vez+4, f1);
|
|
if( clipline(vez, vez+4)) {
|
|
hoco_to_zco(vez, vez);
|
|
hoco_to_zco(vez+4, vez+4);
|
|
zbuflinefunc(vez, vez+4);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
if(ec & ME_V3V1) {
|
|
QUATCOPY(vez, f3);
|
|
QUATCOPY(vez+4, f1);
|
|
if( clipline(vez, vez+4)) {
|
|
hoco_to_zco(vez, vez);
|
|
hoco_to_zco(vez+4, vez+4);
|
|
zbuflinefunc(vez, vez+4);
|
|
}
|
|
}
|
|
}
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
deler= f1[3];
|
|
vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
|
|
vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
|
|
vez[2]= 0x7FFFFFFF *(f1[2]/deler);
|
|
|
|
deler= f2[3];
|
|
vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx;
|
|
vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity;
|
|
vez[6]= 0x7FFFFFFF *(f2[2]/deler);
|
|
|
|
deler= f3[3];
|
|
vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx;
|
|
vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity;
|
|
vez[10]= 0x7FFFFFFF *(f3[2]/deler);
|
|
|
|
if(vlr->v4) {
|
|
deler= f4[3];
|
|
vez[12]= Zmulx*(1.0+f4[0]/deler)+ Zjitx;
|
|
vez[13]= Zmuly*(1.0+f4[1]/deler)+ Zjity;
|
|
vez[14]= 0x7FFFFFFF *(f4[2]/deler);
|
|
|
|
if(ec & ME_V3V4) zbuflinefunc(vez+8, vez+12);
|
|
if(ec & ME_V4V1) zbuflinefunc(vez+12, vez);
|
|
}
|
|
else {
|
|
if(ec & ME_V3V1) zbuflinefunc(vez+8, vez);
|
|
}
|
|
|
|
if(ec & ME_V1V2) zbuflinefunc(vez, vez+4);
|
|
if(ec & ME_V2V3) zbuflinefunc(vez+4, vez+8);
|
|
|
|
|
|
|
|
}
|
|
|
|
void zbufinvulGLinv(v1,v2,v3)
|
|
float *v1,*v2,*v3;
|
|
/* vult in R.rectot de waarde Zvlnr in met R.rectz */
|
|
/* KEERT Z-VERGELIJKING OM: ALLES ACHTER IS ZICHTBAAR */
|
|
{
|
|
double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
|
|
double zxd,zyd,zy0,tmp;
|
|
float *minv,*maxv,*midv;
|
|
unsigned int *rectpofs,*rp;
|
|
int *rz,zverg,zvlak,x;
|
|
int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
|
|
int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
|
|
|
|
/* MIN MAX */
|
|
if(v1[1]<v2[1]) {
|
|
if(v2[1]<v3[1]) {
|
|
minv=v1; midv=v2; maxv=v3;
|
|
}
|
|
else if(v1[1]<v3[1]) {
|
|
minv=v1; midv=v3; maxv=v2;
|
|
}
|
|
else {
|
|
minv=v3; midv=v1; maxv=v2;
|
|
}
|
|
}
|
|
else {
|
|
if(v1[1]<v3[1]) {
|
|
minv=v2; midv=v1; maxv=v3;
|
|
}
|
|
else if(v2[1]<v3[1]) {
|
|
minv=v2; midv=v3; maxv=v1;
|
|
}
|
|
else {
|
|
minv=v3; midv=v2; maxv=v1;
|
|
}
|
|
}
|
|
|
|
my0= ceil(minv[1]);
|
|
my2= floor(maxv[1]);
|
|
omsl= floor(midv[1]);
|
|
|
|
if(my2<0 || my0> R.recty) return;
|
|
|
|
if(my0<0) my0=0;
|
|
|
|
/* EDGES : DE LANGSTE */
|
|
xx1= maxv[1]-minv[1];
|
|
if(xx1>2.0/65536.0) {
|
|
z0= (maxv[0]-minv[0])/xx1;
|
|
|
|
tmp= (-65536.0*z0);
|
|
dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
|
|
xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx0= 0;
|
|
xs0= 65536.0*(MIN2(minv[0],maxv[0]));
|
|
}
|
|
/* EDGES : DE BOVENSTE */
|
|
xx1= maxv[1]-midv[1];
|
|
if(xx1>2.0/65536.0) {
|
|
z0= (maxv[0]-midv[0])/xx1;
|
|
|
|
tmp= (-65536.0*z0);
|
|
dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
|
|
xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx1= 0;
|
|
xs1= 65536.0*(MIN2(midv[0],maxv[0]));
|
|
}
|
|
/* EDGES : DE ONDERSTE */
|
|
xx1= midv[1]-minv[1];
|
|
if(xx1>2.0/65536.0) {
|
|
z0= (midv[0]-minv[0])/xx1;
|
|
|
|
tmp= (-65536.0*z0);
|
|
dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
|
|
xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx2= 0;
|
|
xs2= 65536.0*(MIN2(minv[0],midv[0]));
|
|
}
|
|
|
|
/* ZBUF DX DY */
|
|
x1= v1[0]- v2[0];
|
|
x2= v2[0]- v3[0];
|
|
y1= v1[1]- v2[1];
|
|
y2= v2[1]- v3[1];
|
|
z1= v1[2]- v2[2];
|
|
z2= v2[2]- v3[2];
|
|
x0= y1*z2-z1*y2;
|
|
y0= z1*x2-x1*z2;
|
|
z0= x1*y2-y1*x2;
|
|
|
|
if(z0==0.0) return;
|
|
|
|
if(midv[1]==maxv[1]) omsl= my2;
|
|
if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */
|
|
|
|
while (my2 >= R.recty) { /* my2 kan groter zijn */
|
|
xs0+=dx0;
|
|
if (my2<=omsl) {
|
|
xs2+= dx2;
|
|
}
|
|
else{
|
|
xs1+= dx1;
|
|
}
|
|
my2--;
|
|
}
|
|
|
|
xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
|
|
|
|
zxd= -x0/z0;
|
|
zyd= -y0/z0;
|
|
zy0= my2*zyd+xx1;
|
|
zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
|
|
|
|
/* start-ofset in rect */
|
|
rectx= R.rectx;
|
|
rectzofs= (int *)(R.rectz+rectx*my2);
|
|
rectpofs= (R.rectot+rectx*my2);
|
|
zvlak= Zvlnr;
|
|
|
|
xs3= 0; /* flag */
|
|
if(dx0>dx1) {
|
|
xs3= xs0;
|
|
xs0= xs1;
|
|
xs1= xs3;
|
|
xs3= dx0;
|
|
dx0= dx1;
|
|
dx1= xs3;
|
|
xs3= 1; /* flag */
|
|
|
|
}
|
|
|
|
for(y=my2;y>omsl;y--) {
|
|
|
|
sn1= xs0>>16;
|
|
xs0+= dx0;
|
|
|
|
sn2= xs1>>16;
|
|
xs1+= dx1;
|
|
|
|
sn1++;
|
|
|
|
if(sn2>=rectx) sn2= rectx-1;
|
|
if(sn1<0) sn1= 0;
|
|
zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
|
|
rz= rectzofs+sn1;
|
|
rp= rectpofs+sn1;
|
|
x= sn2-sn1;
|
|
while(x>=0) {
|
|
if(zverg> *rz || *rz==0x7FFFFFFF) {
|
|
*rz= zverg;
|
|
*rp= zvlak;
|
|
}
|
|
zverg+= zd;
|
|
rz++;
|
|
rp++;
|
|
x--;
|
|
}
|
|
zy0-=zyd;
|
|
rectzofs-= rectx;
|
|
rectpofs-= rectx;
|
|
}
|
|
|
|
if(xs3) {
|
|
xs0= xs1;
|
|
dx0= dx1;
|
|
}
|
|
if(xs0>xs2) {
|
|
xs3= xs0;
|
|
xs0= xs2;
|
|
xs2= xs3;
|
|
xs3= dx0;
|
|
dx0= dx2;
|
|
dx2= xs3;
|
|
}
|
|
|
|
for(;y>=my0;y--) {
|
|
|
|
sn1= xs0>>16;
|
|
xs0+= dx0;
|
|
|
|
sn2= xs2>>16;
|
|
xs2+= dx2;
|
|
|
|
sn1++;
|
|
|
|
if(sn2>=rectx) sn2= rectx-1;
|
|
if(sn1<0) sn1= 0;
|
|
zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
|
|
rz= rectzofs+sn1;
|
|
rp= rectpofs+sn1;
|
|
x= sn2-sn1;
|
|
while(x>=0) {
|
|
if(zverg> *rz || *rz==0x7FFFFFFF) {
|
|
*rz= zverg;
|
|
*rp= zvlak;
|
|
}
|
|
zverg+= zd;
|
|
rz++;
|
|
rp++;
|
|
x--;
|
|
}
|
|
|
|
zy0-=zyd;
|
|
rectzofs-= rectx;
|
|
rectpofs-= rectx;
|
|
}
|
|
}
|
|
|
|
void zbufinvulGL(float *v1, float *v2, float *v3) /* vult in R.rectot de waarde Zvlnr in met R.rectz */
|
|
{
|
|
double x0,y0,z0;
|
|
double x1,y1,z1,x2,y2,z2,xx1;
|
|
double zxd,zyd,zy0,tmp;
|
|
float *minv,*maxv,*midv;
|
|
unsigned int *rectpofs,*rp;
|
|
int *rz,zverg,zvlak,x;
|
|
int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
|
|
int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
|
|
|
|
/* MIN MAX */
|
|
if(v1[1]<v2[1]) {
|
|
if(v2[1]<v3[1]) {
|
|
minv=v1; midv=v2; maxv=v3;
|
|
}
|
|
else if(v1[1]<v3[1]) {
|
|
minv=v1; midv=v3; maxv=v2;
|
|
}
|
|
else {
|
|
minv=v3; midv=v1; maxv=v2;
|
|
}
|
|
}
|
|
else {
|
|
if(v1[1]<v3[1]) {
|
|
minv=v2; midv=v1; maxv=v3;
|
|
}
|
|
else if(v2[1]<v3[1]) {
|
|
minv=v2; midv=v3; maxv=v1;
|
|
}
|
|
else {
|
|
minv=v3; midv=v2; maxv=v1;
|
|
}
|
|
}
|
|
|
|
if(minv[1] == maxv[1]) return; /* beveiliging 'nul' grote vlakken */
|
|
|
|
my0= ceil(minv[1]);
|
|
my2= floor(maxv[1]);
|
|
omsl= floor(midv[1]);
|
|
|
|
if(my2<0 || my0> R.recty) return;
|
|
|
|
if(my0<0) my0= 0;
|
|
|
|
/* EDGES : DE LANGSTE */
|
|
xx1= maxv[1]-minv[1];
|
|
if(xx1!=0.0) {
|
|
z0= (maxv[0]-minv[0])/xx1;
|
|
|
|
tmp= -65536.0*z0;
|
|
dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(my2-minv[1]) + minv[0]);
|
|
xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx0= 0;
|
|
xs0= 65536.0*(MIN2(minv[0],maxv[0]));
|
|
}
|
|
/* EDGES : DE BOVENSTE */
|
|
xx1= maxv[1]-midv[1];
|
|
if(xx1!=0.0) {
|
|
z0= (maxv[0]-midv[0])/xx1;
|
|
|
|
tmp= -65536.0*z0;
|
|
dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
|
|
xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx1= 0;
|
|
xs1= 65536.0*(MIN2(midv[0],maxv[0]));
|
|
}
|
|
/* EDGES : DE ONDERSTE */
|
|
xx1= midv[1]-minv[1];
|
|
if(xx1!=0.0) {
|
|
z0= (midv[0]-minv[0])/xx1;
|
|
|
|
tmp= -65536.0*z0;
|
|
dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
|
|
xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx2= 0;
|
|
xs2= 65536.0*(MIN2(minv[0],midv[0]));
|
|
}
|
|
|
|
/* ZBUF DX DY */
|
|
x1= v1[0]- v2[0];
|
|
x2= v2[0]- v3[0];
|
|
y1= v1[1]- v2[1];
|
|
y2= v2[1]- v3[1];
|
|
z1= v1[2]- v2[2];
|
|
z2= v2[2]- v3[2];
|
|
x0= y1*z2-z1*y2;
|
|
y0= z1*x2-x1*z2;
|
|
z0= x1*y2-y1*x2;
|
|
|
|
if(z0==0.0) return;
|
|
|
|
if(midv[1]==maxv[1]) omsl= my2;
|
|
if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */
|
|
|
|
while (my2 >= R.recty) { /* my2 kan groter zijn */
|
|
xs0+=dx0;
|
|
if (my2<=omsl) {
|
|
xs2+= dx2;
|
|
}
|
|
else{
|
|
xs1+= dx1;
|
|
}
|
|
my2--;
|
|
}
|
|
|
|
xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
|
|
|
|
zxd= -x0/z0;
|
|
zyd= -y0/z0;
|
|
zy0= my2*zyd+xx1;
|
|
zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
|
|
|
|
/* start-ofset in rect */
|
|
rectx= R.rectx;
|
|
rectzofs= (int *)(R.rectz+rectx*my2);
|
|
rectpofs= (R.rectot+rectx*my2);
|
|
zvlak= Zvlnr;
|
|
|
|
xs3= 0; /* flag */
|
|
if(dx0>dx1) {
|
|
xs3= xs0;
|
|
xs0= xs1;
|
|
xs1= xs3;
|
|
xs3= dx0;
|
|
dx0= dx1;
|
|
dx1= xs3;
|
|
xs3= 1; /* flag */
|
|
|
|
}
|
|
|
|
for(y=my2;y>omsl;y--) {
|
|
|
|
/* dit is ongevoelig voor endians */
|
|
sn1= xs0>>16;
|
|
xs0+= dx0;
|
|
|
|
sn2= xs1>>16;
|
|
xs1+= dx1;
|
|
|
|
sn1++;
|
|
|
|
if(sn2>=rectx) sn2= rectx-1;
|
|
if(sn1<0) sn1= 0;
|
|
zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
|
|
rz= rectzofs+sn1;
|
|
rp= rectpofs+sn1;
|
|
x= sn2-sn1;
|
|
|
|
while(x>=0) {
|
|
if(zverg< *rz) {
|
|
*rz= zverg;
|
|
*rp= zvlak;
|
|
}
|
|
zverg+= zd;
|
|
rz++;
|
|
rp++;
|
|
x--;
|
|
}
|
|
zy0-=zyd;
|
|
rectzofs-= rectx;
|
|
rectpofs-= rectx;
|
|
}
|
|
|
|
if(xs3) {
|
|
xs0= xs1;
|
|
dx0= dx1;
|
|
}
|
|
if(xs0>xs2) {
|
|
xs3= xs0;
|
|
xs0= xs2;
|
|
xs2= xs3;
|
|
xs3= dx0;
|
|
dx0= dx2;
|
|
dx2= xs3;
|
|
}
|
|
|
|
for(;y>=my0;y--) {
|
|
|
|
sn1= xs0>>16;
|
|
xs0+= dx0;
|
|
|
|
sn2= xs2>>16;
|
|
xs2+= dx2;
|
|
|
|
sn1++;
|
|
|
|
if(sn2>=rectx) sn2= rectx-1;
|
|
if(sn1<0) sn1= 0;
|
|
zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
|
|
rz= rectzofs+sn1;
|
|
rp= rectpofs+sn1;
|
|
x= sn2-sn1;
|
|
while(x>=0) {
|
|
if(zverg< *rz) {
|
|
*rz= zverg;
|
|
*rp= zvlak;
|
|
}
|
|
zverg+= zd;
|
|
rz++;
|
|
rp++;
|
|
x--;
|
|
}
|
|
|
|
zy0-=zyd;
|
|
rectzofs-= rectx;
|
|
rectpofs-= rectx;
|
|
}
|
|
}
|
|
|
|
|
|
void zbufinvulGL_onlyZ(float *v1, float *v2, float *v3) /* vult alleen R.rectz. oneven z= 1x ingevuld */
|
|
{
|
|
double x0,y0,z0,x1,y1,z1,x2,y2,z2,xx1;
|
|
double zxd,zyd,zy0,tmp;
|
|
float *minv,*maxv,*midv;
|
|
int *rz,zverg,x;
|
|
int my0,my2,sn1,sn2,rectx,zd,*rectzofs;
|
|
int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2;
|
|
|
|
/* MIN MAX */
|
|
if(v1[1]<v2[1]) {
|
|
if(v2[1]<v3[1]) {
|
|
minv=v1;
|
|
midv=v2;
|
|
maxv=v3;
|
|
}
|
|
else if(v1[1]<v3[1]) {
|
|
minv=v1;
|
|
midv=v3;
|
|
maxv=v2;
|
|
}
|
|
else {
|
|
minv=v3;
|
|
midv=v1;
|
|
maxv=v2;
|
|
}
|
|
}
|
|
else {
|
|
if(v1[1]<v3[1]) {
|
|
minv=v2;
|
|
midv=v1;
|
|
maxv=v3;
|
|
}
|
|
else if(v2[1]<v3[1]) {
|
|
minv=v2;
|
|
midv=v3;
|
|
maxv=v1;
|
|
}
|
|
else {
|
|
minv=v3;
|
|
midv=v2;
|
|
maxv=v1;
|
|
}
|
|
}
|
|
|
|
my0= ceil(minv[1]);
|
|
my2= floor(maxv[1]);
|
|
omsl= floor(midv[1]);
|
|
|
|
if(my2<0 || my0> R.recty) return;
|
|
|
|
if(my0<0) my0=0;
|
|
|
|
/* EDGES : DE LANGSTE */
|
|
xx1= maxv[1]-minv[1];
|
|
if(xx1!=0.0) {
|
|
z0= (maxv[0]-minv[0])/xx1;
|
|
|
|
tmp= (-65536.0*z0);
|
|
dx0= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(my2-minv[1])+minv[0]);
|
|
xs0= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx0= 0;
|
|
xs0= 65536.0*(MIN2(minv[0],maxv[0]));
|
|
}
|
|
/* EDGES : DE BOVENSTE */
|
|
xx1= maxv[1]-midv[1];
|
|
if(xx1!=0.0) {
|
|
z0= (maxv[0]-midv[0])/xx1;
|
|
|
|
tmp= (-65536.0*z0);
|
|
dx1= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(my2-midv[1])+midv[0]);
|
|
xs1= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx1= 0;
|
|
xs1= 65536.0*(MIN2(midv[0],maxv[0]));
|
|
}
|
|
/* EDGES : DE ONDERSTE */
|
|
xx1= midv[1]-minv[1];
|
|
if(xx1!=0.0) {
|
|
z0= (midv[0]-minv[0])/xx1;
|
|
|
|
tmp= (-65536.0*z0);
|
|
dx2= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
|
|
tmp= 65536.0*(z0*(omsl-minv[1])+minv[0]);
|
|
xs2= CLAMPIS(tmp, INT_MIN, INT_MAX);
|
|
}
|
|
else {
|
|
dx2= 0;
|
|
xs2= 65536.0*(MIN2(minv[0],midv[0]));
|
|
}
|
|
|
|
/* ZBUF DX DY */
|
|
x1= v1[0]- v2[0];
|
|
x2= v2[0]- v3[0];
|
|
y1= v1[1]- v2[1];
|
|
y2= v2[1]- v3[1];
|
|
z1= v1[2]- v2[2];
|
|
z2= v2[2]- v3[2];
|
|
x0= y1*z2-z1*y2;
|
|
y0= z1*x2-x1*z2;
|
|
z0= x1*y2-y1*x2;
|
|
|
|
if(z0==0.0) return;
|
|
|
|
if(midv[1]==maxv[1]) omsl= my2;
|
|
if(omsl<0) omsl= -1; /* dan neemt ie de eerste lus helemaal */
|
|
|
|
while (my2 >= R.recty) { /* my2 kan groter zijn */
|
|
xs0+=dx0;
|
|
if (my2<=omsl) {
|
|
xs2+= dx2;
|
|
}
|
|
else{
|
|
xs1+= dx1;
|
|
}
|
|
my2--;
|
|
}
|
|
|
|
xx1= (x0*v1[0]+y0*v1[1])/z0+v1[2];
|
|
|
|
zxd= -x0/z0;
|
|
zyd= -y0/z0;
|
|
zy0= my2*zyd+xx1;
|
|
zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
|
|
|
|
/* start-ofset in rect */
|
|
rectx= R.rectx;
|
|
rectzofs= (int *)(R.rectz+rectx*my2);
|
|
|
|
xs3= 0; /* flag */
|
|
if(dx0>dx1) {
|
|
xs3= xs0;
|
|
xs0= xs1;
|
|
xs1= xs3;
|
|
xs3= dx0;
|
|
dx0= dx1;
|
|
dx1= xs3;
|
|
xs3= 1; /* flag */
|
|
|
|
}
|
|
|
|
for(y=my2;y>omsl;y--) {
|
|
|
|
sn1= xs0>>16;
|
|
xs0+= dx0;
|
|
|
|
sn2= xs1>>16;
|
|
xs1+= dx1;
|
|
|
|
sn1++;
|
|
|
|
if(sn2>=rectx) sn2= rectx-1;
|
|
if(sn1<0) sn1= 0;
|
|
zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
|
|
rz= rectzofs+sn1;
|
|
|
|
x= sn2-sn1;
|
|
while(x>=0) {
|
|
if(zverg< *rz) {
|
|
*rz= zverg;
|
|
}
|
|
zverg+= zd;
|
|
rz++;
|
|
x--;
|
|
}
|
|
zy0-=zyd;
|
|
rectzofs-= rectx;
|
|
}
|
|
|
|
if(xs3) {
|
|
xs0= xs1;
|
|
dx0= dx1;
|
|
}
|
|
if(xs0>xs2) {
|
|
xs3= xs0;
|
|
xs0= xs2;
|
|
xs2= xs3;
|
|
xs3= dx0;
|
|
dx0= dx2;
|
|
dx2= xs3;
|
|
}
|
|
|
|
for(;y>=my0;y--) {
|
|
|
|
sn1= xs0>>16;
|
|
xs0+= dx0;
|
|
|
|
sn2= xs2>>16;
|
|
xs2+= dx2;
|
|
|
|
sn1++;
|
|
|
|
if(sn2>=rectx) sn2= rectx-1;
|
|
if(sn1<0) sn1= 0;
|
|
zverg= (int) CLAMPIS((sn1*zxd+zy0), INT_MIN, INT_MAX);
|
|
rz= rectzofs+sn1;
|
|
|
|
x= sn2-sn1;
|
|
while(x>=0) {
|
|
if(zverg< *rz) {
|
|
*rz= zverg;
|
|
}
|
|
zverg+= zd;
|
|
rz++;
|
|
x--;
|
|
}
|
|
|
|
zy0-=zyd;
|
|
rectzofs-= rectx;
|
|
}
|
|
}
|
|
|
|
void print3floats(float *v1, float *v2, float *v3)
|
|
{
|
|
printf("1 %f %f %f %f\n", v1[0], v1[1], v1[2], v1[3]);
|
|
printf("2 %f %f %f %f\n", v2[0], v2[1], v2[2], v2[3]);
|
|
printf("3 %f %f %f %f\n", v3[0], v3[1], v3[2], v3[3]);
|
|
}
|
|
|
|
static short cliptestf(float p, float q, float *u1, float *u2)
|
|
{
|
|
float r;
|
|
|
|
if(p<0.0) {
|
|
if(q<p) return 0;
|
|
else if(q<0.0) {
|
|
r= q/p;
|
|
if(r>*u2) return 0;
|
|
else if(r>*u1) *u1=r;
|
|
}
|
|
}
|
|
else {
|
|
if(p>0.0) {
|
|
if(q<0.0) return 0;
|
|
else if(q<p) {
|
|
r= q/p;
|
|
if(r<*u1) return 0;
|
|
else if(r<*u2) *u2=r;
|
|
}
|
|
}
|
|
else if(q<0.0) return 0;
|
|
}
|
|
return 1;
|
|
}
|
|
|
|
int RE_testclip(float *v)
|
|
{
|
|
float abs4; /* LET OP: deze func moet zelfde doen als cliptestf, anders problemen in zbufclip()*/
|
|
short c=0;
|
|
|
|
abs4= fabs(v[3]);
|
|
|
|
if(v[2]< -abs4) c=16; /* hier stond vroeger " if(v[2]<0) ", zie clippz() */
|
|
else if(v[2]> abs4) c+= 32;
|
|
|
|
if( v[0]>abs4) c+=2;
|
|
else if( v[0]< -abs4) c+=1;
|
|
|
|
if( v[1]>abs4) c+=4;
|
|
else if( v[1]< -abs4) c+=8;
|
|
|
|
return c;
|
|
}
|
|
|
|
|
|
static void clipp(float *v1, float *v2, int b1, int *b2, int *b3, int a)
|
|
{
|
|
float da,db,u1=0.0,u2=1.0;
|
|
|
|
labda[b1][0]= -1.0;
|
|
labda[b1][1]= -1.0;
|
|
|
|
da= v2[a]-v1[a];
|
|
db= v2[3]-v1[3];
|
|
|
|
/* volgens het oorspronkelijke artikel van Liang&Barsky, wordt bij het clippen van
|
|
* hoco's met het viewplane, het getal "0" gebruikt ipv "-w" .
|
|
* Dit wijkt af van de andere clipping (links en onder) en vond ik ook niet erg
|
|
* 'homogeen'. Het is dus een fout, wie had dat gedacht van L&B!
|
|
*/
|
|
|
|
if(cliptestf(-da-db, v1[3]+v1[a], &u1,&u2)) {
|
|
if(cliptestf(da-db, v1[3]-v1[a], &u1,&u2)) {
|
|
*b3=1;
|
|
if(u2<1.0) {
|
|
labda[b1][1]= u2;
|
|
*b2=1;
|
|
}
|
|
else labda[b1][1]=1.0; /* u2 */
|
|
if(u1>0.0) {
|
|
labda[b1][0]= u1;
|
|
*b2=1;
|
|
} else labda[b1][0]=0.0;
|
|
}
|
|
}
|
|
}
|
|
|
|
static int clipline(float *v1, float *v2) /* return 0: niet tekenen */
|
|
{
|
|
float dz,dw, u1=0.0, u2=1.0;
|
|
float dx, dy;
|
|
|
|
dz= v2[2]-v1[2];
|
|
dw= v2[3]-v1[3];
|
|
|
|
if(cliptestf(-dz-dw, v1[3]+v1[2], &u1,&u2)) {
|
|
if(cliptestf(dz-dw, v1[3]-v1[2], &u1,&u2)) {
|
|
|
|
dx= v2[0]-v1[0];
|
|
dz= v2[3]-v1[3];
|
|
|
|
if(cliptestf(-dx-dz, v1[0]+v1[3], &u1,&u2)) {
|
|
if(cliptestf(dx-dz, v1[3]-v1[0], &u1,&u2)) {
|
|
|
|
dy= v2[1]-v1[1];
|
|
|
|
if(cliptestf(-dy-dz,v1[1]+v1[3],&u1,&u2)) {
|
|
if(cliptestf(dy-dz,v1[3]-v1[1],&u1,&u2)) {
|
|
|
|
if(u2<1.0) {
|
|
v2[0]= v1[0]+u2*dx;
|
|
v2[1]= v1[1]+u2*dy;
|
|
v2[2]= v1[2]+u2*dz;
|
|
v2[3]= v1[3]+u2*dw;
|
|
}
|
|
if(u1>0.0) {
|
|
v1[0]= v1[0]+u1*dx;
|
|
v1[1]= v1[1]+u1*dy;
|
|
v1[2]= v1[2]+u1*dz;
|
|
v1[3]= v1[3]+u1*dw;
|
|
}
|
|
return 1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
static void maakvertpira(float *v1, float *v2, int *b1, int b2, int *clve)
|
|
{
|
|
float l1,l2,*adr;
|
|
|
|
l1= labda[b2][0];
|
|
l2= labda[b2][1];
|
|
|
|
if(l1!= -1.0) {
|
|
if(l1!= 0.0) {
|
|
adr= vez+4*(*clve);
|
|
p[*b1]=adr;
|
|
(*clve)++;
|
|
adr[0]= v1[0]+l1*(v2[0]-v1[0]);
|
|
adr[1]= v1[1]+l1*(v2[1]-v1[1]);
|
|
adr[2]= v1[2]+l1*(v2[2]-v1[2]);
|
|
adr[3]= v1[3]+l1*(v2[3]-v1[3]);
|
|
} else p[*b1]= v1;
|
|
(*b1)++;
|
|
}
|
|
if(l2!= -1.0) {
|
|
if(l2!= 1.0) {
|
|
adr= vez+4*(*clve);
|
|
p[*b1]=adr;
|
|
(*clve)++;
|
|
adr[0]= v1[0]+l2*(v2[0]-v1[0]);
|
|
adr[1]= v1[1]+l2*(v2[1]-v1[1]);
|
|
adr[2]= v1[2]+l2*(v2[2]-v1[2]);
|
|
adr[3]= v1[3]+l2*(v2[3]-v1[3]);
|
|
(*b1)++;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
void RE_projectverto(float *v1, float *adr)
|
|
{
|
|
/* berekent homogene co van vertex v1 */
|
|
float x,y,z;
|
|
|
|
x= v1[0];
|
|
y= v1[1];
|
|
z= v1[2];
|
|
adr[0]= x*R.winmat[0][0] + z*R.winmat[2][0];
|
|
adr[1]= y*R.winmat[1][1]+ z*R.winmat[2][1];
|
|
adr[2]= z*R.winmat[2][2] + R.winmat[3][2];
|
|
adr[3]= z*R.winmat[2][3] + R.winmat[3][3];
|
|
|
|
} /* end of void RE_projectverto(float *v1, float *adr) */
|
|
|
|
/* ------------------------------------------------------------------------- */
|
|
|
|
void projectvert(float *v1, float *adr)
|
|
{
|
|
/* berekent homogene co van vertex v1 */
|
|
float x,y,z;
|
|
|
|
x= v1[0];
|
|
y= v1[1];
|
|
z= v1[2];
|
|
adr[0]= x*R.winmat[0][0]+ y*R.winmat[1][0]+ z*R.winmat[2][0]+ R.winmat[3][0];
|
|
adr[1]= x*R.winmat[0][1]+ y*R.winmat[1][1]+ z*R.winmat[2][1]+ R.winmat[3][1];
|
|
adr[2]= x*R.winmat[0][2]+ y*R.winmat[1][2]+ z*R.winmat[2][2]+ R.winmat[3][2];
|
|
adr[3]= x*R.winmat[0][3]+ y*R.winmat[1][3]+ z*R.winmat[2][3]+ R.winmat[3][3];
|
|
}
|
|
|
|
|
|
void zbufclip(float *f1, float *f2, float *f3, int c1, int c2, int c3)
|
|
{
|
|
float deler;
|
|
|
|
if(c1 | c2 | c3) { /* niet in midden */
|
|
if(c1 & c2 & c3) { /* helemaal eruit */
|
|
return;
|
|
} else { /* clippen */
|
|
int arg, v, b, clipflag[3], b1, b2, b3, c4, clve=3, clvlo, clvl=1;
|
|
|
|
vez[0]= f1[0]; vez[1]= f1[1]; vez[2]= f1[2]; vez[3]= f1[3];
|
|
vez[4]= f2[0]; vez[5]= f2[1]; vez[6]= f2[2]; vez[7]= f2[3];
|
|
vez[8]= f3[0]; vez[9]= f3[1]; vez[10]= f3[2];vez[11]= f3[3];
|
|
|
|
vlzp[0][0]= vez;
|
|
vlzp[0][1]= vez+4;
|
|
vlzp[0][2]= vez+8;
|
|
|
|
clipflag[0]= ( (c1 & 48) | (c2 & 48) | (c3 & 48) );
|
|
if(clipflag[0]==0) { /* anders opnieuw berekend verderop, na de eerste (z) clip */
|
|
clipflag[1]= ( (c1 & 3) | (c2 & 3) | (c3 & 3) );
|
|
clipflag[2]= ( (c1 & 12) | (c2 & 12) | (c3 & 12) );
|
|
}
|
|
|
|
for(b=0;b<3;b++) {
|
|
|
|
if(clipflag[b]) {
|
|
|
|
clvlo= clvl;
|
|
|
|
for(v=0; v<clvlo; v++) {
|
|
|
|
if(vlzp[v][0]!=0) { /* vlak is er nog */
|
|
b2= b3 =0; /* clipvlaggen */
|
|
|
|
if(b==0) arg= 2;
|
|
else if (b==1) arg= 0;
|
|
else arg= 1;
|
|
|
|
clipp(vlzp[v][0],vlzp[v][1],0,&b2,&b3, arg);
|
|
clipp(vlzp[v][1],vlzp[v][2],1,&b2,&b3, arg);
|
|
clipp(vlzp[v][2],vlzp[v][0],2,&b2,&b3, arg);
|
|
|
|
if(b2==0 && b3==1) {
|
|
/* er helemaal in */;
|
|
} else if(b3==0) {
|
|
vlzp[v][0]=0;
|
|
/* er helemaal uit */;
|
|
} else {
|
|
b1=0;
|
|
maakvertpira(vlzp[v][0],vlzp[v][1],&b1,0,&clve);
|
|
maakvertpira(vlzp[v][1],vlzp[v][2],&b1,1,&clve);
|
|
maakvertpira(vlzp[v][2],vlzp[v][0],&b1,2,&clve);
|
|
|
|
/* als frontclip is gedaan: nu pas clipvlaggen zetten */
|
|
if(b==0) {
|
|
clipflag[1]= clipflag[2]= 0;
|
|
f1= vez;
|
|
for(b3=0; b3<clve; b3++) {
|
|
c4= RE_testclip(f1);
|
|
clipflag[1] |= (c4 & 3);
|
|
clipflag[2] |= (c4 & 12);
|
|
f1+= 4;
|
|
}
|
|
}
|
|
|
|
vlzp[v][0]=0;
|
|
if(b1>2) {
|
|
for(b3=3; b3<=b1; b3++) {
|
|
vlzp[clvl][0]= p[0];
|
|
vlzp[clvl][1]= p[b3-2];
|
|
vlzp[clvl][2]= p[b3-1];
|
|
clvl++;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
/* persp deling */
|
|
/* valt hier nog te optimaliseren door alleen te gebruiken vertices te doen? */
|
|
if(clve>38) printf("clip overflow: clve clvl %d %d\n",clve,clvl);
|
|
f1=vez;
|
|
for(c1=0;c1<clve;c1++) {
|
|
deler= f1[3];
|
|
f1[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
|
|
f1[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
|
|
f1[2]= 0x7FFFFFFF *(f1[2]/deler);
|
|
f1+=4;
|
|
}
|
|
for(b=1;b<clvl;b++) {
|
|
if(vlzp[b][0]) {
|
|
zbuffunc(vlzp[b][0],vlzp[b][1],vlzp[b][2]);
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
}
|
|
|
|
/* persp deling: HCS to ZCS */
|
|
|
|
deler= f1[3];
|
|
vez[0]= Zmulx*(1.0+f1[0]/deler)+ Zjitx;
|
|
vez[1]= Zmuly*(1.0+f1[1]/deler)+ Zjity;
|
|
vez[2]= 0x7FFFFFFF *(f1[2]/deler);
|
|
|
|
deler= f2[3];
|
|
vez[4]= Zmulx*(1.0+f2[0]/deler)+ Zjitx;
|
|
vez[5]= Zmuly*(1.0+f2[1]/deler)+ Zjity;
|
|
vez[6]= 0x7FFFFFFF *(f2[2]/deler);
|
|
|
|
deler= f3[3];
|
|
vez[8]= Zmulx*(1.0+f3[0]/deler)+ Zjitx;
|
|
vez[9]= Zmuly*(1.0+f3[1]/deler)+ Zjity;
|
|
vez[10]= 0x7FFFFFFF *(f3[2]/deler);
|
|
|
|
zbuffunc(vez,vez+4,vez+8);
|
|
}
|
|
|
|
/* ***************** ZBUFFER MAINROUTINES **************** */
|
|
|
|
|
|
void zbufferall(void)
|
|
{
|
|
VlakRen *vlr= NULL;
|
|
Material *ma=0;
|
|
int v;
|
|
short transp=0, env=0, wire=0;
|
|
|
|
Zmulx= ((float)R.rectx)/2.0;
|
|
Zmuly= ((float)R.recty)/2.0;
|
|
|
|
fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF);
|
|
|
|
Zvlnr= 0;
|
|
|
|
zbuffunc= zbufinvulGL;
|
|
zbuflinefunc= zbufline;
|
|
|
|
for(v=0;v<R.totvlak;v++) {
|
|
|
|
if((v & 255)==0) vlr= R.blovl[v>>8];
|
|
else vlr++;
|
|
|
|
if(vlr->flag & R_VISIBLE) {
|
|
if(vlr->mat!=ma) {
|
|
ma= vlr->mat;
|
|
transp= ma->mode & MA_ZTRA;
|
|
env= (ma->mode & MA_ENV);
|
|
wire= (ma->mode & MA_WIRE);
|
|
|
|
if(ma->mode & MA_ZINV) zbuffunc= zbufinvulGLinv;
|
|
else zbuffunc= zbufinvulGL;
|
|
}
|
|
|
|
if(transp==0) {
|
|
if(env) Zvlnr= 0;
|
|
else Zvlnr= v+1;
|
|
|
|
if(wire) zbufclipwire(vlr);
|
|
else {
|
|
zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
|
|
if(vlr->v4) {
|
|
if(Zvlnr) Zvlnr+= 0x800000;
|
|
zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
static int hashlist_projectvert(float *v1, float *hoco)
|
|
{
|
|
static VertBucket bucket[256], *buck;
|
|
|
|
if(v1==0) {
|
|
memset(bucket, 0, 256*sizeof(VertBucket));
|
|
return 0;
|
|
}
|
|
|
|
buck= &bucket[ (((long)v1)/16) & 255 ];
|
|
if(buck->vert==v1) {
|
|
COPY_16(hoco, buck->hoco);
|
|
return buck->clip;
|
|
}
|
|
|
|
projectvert(v1, hoco);
|
|
buck->clip = RE_testclip(hoco);
|
|
buck->vert= v1;
|
|
COPY_16(buck->hoco, hoco);
|
|
return buck->clip;
|
|
}
|
|
|
|
|
|
void RE_zbufferall_radio(struct RadView *vw, RNode **rg_elem, int rg_totelem)
|
|
{
|
|
RNode **re, *rn;
|
|
float hoco[4][4];
|
|
int a;
|
|
int c1, c2, c3, c4= 0;
|
|
unsigned int *rectoto, *rectzo;
|
|
int rectxo, rectyo;
|
|
|
|
if(rg_totelem==0) return;
|
|
|
|
hashlist_projectvert(0, 0);
|
|
|
|
rectxo= R.rectx;
|
|
rectyo= R.recty;
|
|
rectoto= R.rectot;
|
|
rectzo= R.rectz;
|
|
|
|
R.rectx= vw->rectx;
|
|
R.recty= vw->recty;
|
|
R.rectot= vw->rect;
|
|
R.rectz= vw->rectz;
|
|
|
|
Zmulx= ((float)R.rectx)/2.0;
|
|
Zmuly= ((float)R.recty)/2.0;
|
|
|
|
/* needed for projectvert */
|
|
MTC_Mat4MulMat4(R.winmat, vw->viewmat, vw->winmat);
|
|
|
|
fillrect(R.rectz, R.rectx, R.recty, 0x7FFFFFFF);
|
|
fillrect(R.rectot, R.rectx, R.recty, 0xFFFFFF);
|
|
|
|
zbuffunc= zbufinvulGL;
|
|
|
|
re= rg_elem;
|
|
re+= (rg_totelem-1);
|
|
for(a= rg_totelem-1; a>=0; a--, re--) {
|
|
rn= *re;
|
|
if( (rn->f & RAD_SHOOT)==0 ) { /* no shootelement */
|
|
|
|
if( rn->f & RAD_BACKFACE) Zvlnr= 0xFFFFFF;
|
|
else Zvlnr= a;
|
|
|
|
c1= hashlist_projectvert(rn->v1, hoco[0]);
|
|
c2= hashlist_projectvert(rn->v2, hoco[1]);
|
|
c3= hashlist_projectvert(rn->v3, hoco[2]);
|
|
|
|
if(rn->v4) {
|
|
c4= hashlist_projectvert(rn->v4, hoco[3]);
|
|
}
|
|
|
|
zbufclip(hoco[0], hoco[1], hoco[2], c1, c2, c3);
|
|
if(rn->v4) {
|
|
zbufclip(hoco[0], hoco[2], hoco[3], c1, c3, c4);
|
|
}
|
|
}
|
|
}
|
|
|
|
/* restore */
|
|
R.rectx= rectxo;
|
|
R.recty= rectyo;
|
|
R.rectot= rectoto;
|
|
R.rectz= rectzo;
|
|
|
|
}
|
|
|
|
void zbuffershad(LampRen *lar)
|
|
{
|
|
VlakRen *vlr= NULL;
|
|
Material *ma=0;
|
|
int a, ok=1, lay= -1;
|
|
|
|
if(lar->mode & LA_LAYER) lay= lar->lay;
|
|
|
|
Zmulx= ((float)R.rectx)/2.0;
|
|
Zmuly= ((float)R.recty)/2.0;
|
|
Zjitx= Zjity= -.5;
|
|
|
|
fillrect(R.rectz,R.rectx,R.recty,0x7FFFFFFE);
|
|
|
|
zbuffunc= zbufinvulGL_onlyZ;
|
|
|
|
for(a=0;a<R.totvlak;a++) {
|
|
|
|
if((a & 255)==0) vlr= R.blovl[a>>8];
|
|
else vlr++;
|
|
|
|
if(vlr->mat!= ma) {
|
|
ma= vlr->mat;
|
|
ok= 1;
|
|
if((ma->mode & MA_TRACEBLE)==0) ok= 0;
|
|
}
|
|
/* traceble er weer in: automatische verwijdering niet geweldig */
|
|
|
|
if(ok && (vlr->flag & R_VISIBLE) && (vlr->lay & lay)) {
|
|
zbufclip(vlr->v1->ho, vlr->v2->ho, vlr->v3->ho, vlr->v1->clip, vlr->v2->clip, vlr->v3->clip);
|
|
if(vlr->v4) zbufclip(vlr->v1->ho, vlr->v3->ho, vlr->v4->ho, vlr->v1->clip, vlr->v3->clip, vlr->v4->clip);
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
|
|
/* ******************** ABUF ************************* */
|
|
|
|
|
|
void bgnaccumbuf(void)
|
|
{
|
|
|
|
Acolrow= MEM_mallocN(4*sizeof(short)*R.rectx, "Acolrow");
|
|
Arectz= MEM_mallocN(sizeof(int)*ABUFPART*R.rectx, "Arectz");
|
|
APixbuf= MEM_mallocN(ABUFPART*R.rectx*sizeof(APixstr), "APixbuf");
|
|
|
|
Aminy= -1000;
|
|
Amaxy= -1000;
|
|
|
|
apsmteller= 0;
|
|
apsmfirst.next= 0;
|
|
apsmfirst.ps= 0;
|
|
} /* End of void bgnaccumbuf(void) */
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
void endaccumbuf(void)
|
|
{
|
|
|
|
MEM_freeN(Acolrow);
|
|
MEM_freeN(Arectz);
|
|
MEM_freeN(APixbuf);
|
|
freepsA();
|
|
} /* End of void endaccumbuf(void) */
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
void copyto_abufz(int sample)
|
|
{
|
|
PixStr *ps;
|
|
int x, y, *rza;
|
|
long *rd;
|
|
|
|
memcpy(Arectz, R.rectz+ R.rectx*Aminy, 4*R.rectx*(Amaxy-Aminy+1));
|
|
|
|
if( (R.r.mode & R_OSA)==0 || sample==0) return;
|
|
|
|
rza= Arectz;
|
|
rd= (R.rectdaps+ R.rectx*Aminy);
|
|
|
|
sample= (1<<sample);
|
|
|
|
for(y=Aminy; y<=Amaxy; y++) {
|
|
for(x=0; x<R.rectx; x++) {
|
|
|
|
if( IS_A_POINTER_CODE(*rd)) {
|
|
ps= (PixStr *) POINTER_FROM_CODE(*rd);
|
|
|
|
while(ps) {
|
|
if(sample & ps->mask) {
|
|
*rza= ps->z;
|
|
break;
|
|
}
|
|
ps= ps->next;
|
|
}
|
|
}
|
|
|
|
rd++; rza++;
|
|
}
|
|
}
|
|
} /* end of void copyto_abufz(int sample) */
|
|
|
|
|
|
/* ------------------------------------------------------------------------ */
|
|
|
|
void zbuffer_abuf()
|
|
{
|
|
float vec[3], hoco[4], mul, zval, fval;
|
|
Material *ma=0;
|
|
int v, len;
|
|
|
|
Zjitx= Zjity= -.5;
|
|
Zmulx= ((float)R.rectx)/2.0;
|
|
Zmuly= ((float)R.recty)/2.0;
|
|
|
|
/* clear APixstructen */
|
|
len= sizeof(APixstr)*R.rectx*ABUFPART;
|
|
memset(APixbuf, 0, len);
|
|
|
|
zbuffunc= zbufinvulAc;
|
|
zbuflinefunc= zbuflineAc;
|
|
|
|
for(Zsample=0; Zsample<R.osa || R.osa==0; Zsample++) {
|
|
|
|
copyto_abufz(Zsample); /* init zbuffer */
|
|
|
|
if(R.r.mode & R_OSA) {
|
|
Zjitx= -jit[Zsample][0];
|
|
Zjity= -jit[Zsample][1];
|
|
}
|
|
|
|
/* printf("Start facetrace\n"); */
|
|
|
|
for(v=0; v<R.totvlak; v++) {
|
|
if((v & 255)==0) {
|
|
Zvlr= R.blovl[v>>8];
|
|
}
|
|
else Zvlr++;
|
|
|
|
ma= Zvlr->mat;
|
|
|
|
/* printf("Face %d :%x at %f\n", v, ma, Zvlr->v1->ho[3]); */
|
|
|
|
|
|
if(ma->mode & (MA_ZTRA)) {
|
|
|
|
/* voordeeltje voor transp renderen */
|
|
if( ma->zoffs != 0.0) {
|
|
mul= 0x7FFFFFFF;
|
|
zval= mul*(1.0+Zvlr->v1->ho[2]/Zvlr->v1->ho[3]);
|
|
|
|
VECCOPY(vec, Zvlr->v1->co);
|
|
/* z is negatief, wordt anders geclipt */
|
|
vec[2]-= ma->zoffs;
|
|
RE_projectverto(vec, hoco);
|
|
fval= mul*(1.0+hoco[2]/hoco[3]);
|
|
|
|
Azvoordeel= (int) fabs(zval - fval );
|
|
|
|
/* PATCH: als transp en niet transp dicht op elkaar liggen: Zbuf aliasing: eruit! */
|
|
/* Azvoordeel= 0xFFFF; */
|
|
}
|
|
else Azvoordeel= 0;
|
|
/* else Azvoordeel= 0xFFFF; */
|
|
|
|
Zvlnr= v+1;
|
|
|
|
if(Zvlr->flag & R_VISIBLE) {
|
|
|
|
if(ma->mode & (MA_WIRE)) zbufclipwire(Zvlr);
|
|
else {
|
|
zbufclip(Zvlr->v1->ho, Zvlr->v2->ho, Zvlr->v3->ho, Zvlr->v1->clip, Zvlr->v2->clip, Zvlr->v3->clip);
|
|
if(Zvlr->v4) {
|
|
Zvlnr+= 0x800000;
|
|
zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho, Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if(!(v%256)&&RE_local_test_break()) break; /*RPW, HOS */
|
|
}
|
|
|
|
if((R.r.mode & R_OSA)==0) break;
|
|
if(RE_local_test_break()) break;
|
|
}
|
|
|
|
} /* end of void zbuffer_abuf() */
|
|
|
|
|
|
int vergzvlak(const void *a1, const void *a2)
|
|
{
|
|
const int *x1=a1, *x2=a2;
|
|
|
|
if( x1[0] < x2[0] ) return 1;
|
|
else if( x1[0] > x2[0]) return -1;
|
|
return 0;
|
|
}
|
|
|
|
void shadetrapixel(float x, float y, int vlak)
|
|
{
|
|
if( (vlak & 0x7FFFFF) > R.totvlak) {
|
|
printf("error in shadetrapixel nr: %d\n", (vlak & 0x7FFFFF));
|
|
return;
|
|
}
|
|
|
|
shadepixel(x, y, vlak);
|
|
}
|
|
|
|
extern unsigned short usegamtab;
|
|
extern unsigned short shortcol[4];
|
|
void abufsetrow(int y)
|
|
{
|
|
APixstr *ap, *apn;
|
|
float xs, ys;
|
|
int x, part, a, b, zrow[100][3], totvlak, alpha[32], tempgam, nr, intcol[4];
|
|
int sval, tempRf;
|
|
unsigned short *col, tempcol[4], sampcol[16*4], *scol;
|
|
|
|
if(y<0) return;
|
|
if(R.osa>16) {
|
|
printf("abufsetrow: osa too large\n");
|
|
G.afbreek= 1;
|
|
return;
|
|
}
|
|
|
|
tempRf= R.flag;
|
|
R.flag &= ~R_LAMPHALO;
|
|
|
|
/* alpha LUT */
|
|
if(R.r.mode & R_OSA ) {
|
|
x= (65536/R.osa);
|
|
for(a=0; a<=R.osa; a++) {
|
|
alpha[a]= a*x;
|
|
}
|
|
}
|
|
/* moet pixbuf worden gemaakt? */
|
|
if(y<Aminy || y>Amaxy) {
|
|
part= (y/ABUFPART);
|
|
Aminy= part*ABUFPART;
|
|
Amaxy= Aminy+ABUFPART-1;
|
|
if(Amaxy>=R.recty) Amaxy= R.recty-1;
|
|
freepsA();
|
|
zbuffer_abuf();
|
|
}
|
|
|
|
/* render rij */
|
|
col= Acolrow;
|
|
memset(col, 0, 2*4*R.rectx);
|
|
ap= APixbuf+R.rectx*(y-Aminy);
|
|
ys= y;
|
|
tempgam= usegamtab;
|
|
usegamtab= 0;
|
|
|
|
for(x=0; x<R.rectx; x++, col+=4, ap++) {
|
|
if(ap->p[0]) {
|
|
/* sorteer op z */
|
|
totvlak= 0;
|
|
apn= ap;
|
|
while(apn) {
|
|
for(a=0; a<4; a++) {
|
|
if(apn->p[a]) {
|
|
zrow[totvlak][0]= apn->z[a];
|
|
zrow[totvlak][1]= apn->p[a];
|
|
zrow[totvlak][2]= apn->mask[a];
|
|
totvlak++;
|
|
if(totvlak>99) totvlak= 99;
|
|
}
|
|
else break;
|
|
}
|
|
apn= apn->next;
|
|
}
|
|
if(totvlak==1) {
|
|
|
|
if(R.r.mode & R_OSA ) {
|
|
b= centmask[ ap->mask[0] ];
|
|
xs= (float)x+centLut[b & 15];
|
|
ys= (float)y+centLut[b>>4];
|
|
}
|
|
else {
|
|
xs= x; ys= y;
|
|
}
|
|
shadetrapixel(xs, ys, ap->p[0]);
|
|
|
|
nr= count_mask(ap->mask[0]);
|
|
if( (R.r.mode & R_OSA) && nr<R.osa) {
|
|
a= alpha[ nr ];
|
|
col[0]= (shortcol[0]*a)>>16;
|
|
col[1]= (shortcol[1]*a)>>16;
|
|
col[2]= (shortcol[2]*a)>>16;
|
|
col[3]= (shortcol[3]*a)>>16;
|
|
}
|
|
else {
|
|
col[0]= shortcol[0];
|
|
col[1]= shortcol[1];
|
|
col[2]= shortcol[2];
|
|
col[3]= shortcol[3];
|
|
}
|
|
}
|
|
else {
|
|
|
|
if(totvlak==2) {
|
|
if(zrow[0][0] < zrow[1][0]) {
|
|
a= zrow[0][0]; zrow[0][0]= zrow[1][0]; zrow[1][0]= a;
|
|
a= zrow[0][1]; zrow[0][1]= zrow[1][1]; zrow[1][1]= a;
|
|
a= zrow[0][2]; zrow[0][2]= zrow[1][2]; zrow[1][2]= a;
|
|
}
|
|
|
|
}
|
|
else { /* totvlak>2 */
|
|
qsort(zrow, totvlak, sizeof(int)*3, vergzvlak);
|
|
}
|
|
|
|
/* samenvoegen als pixels aanvullen */
|
|
|
|
while(totvlak>0) {
|
|
totvlak--;
|
|
|
|
if(R.r.mode & R_OSA) {
|
|
b= centmask[ zrow[totvlak][2] ];
|
|
xs= (float)x+centLut[b & 15];
|
|
ys= (float)y+centLut[b>>4];
|
|
}
|
|
else {
|
|
xs= x; ys= y;
|
|
}
|
|
shadetrapixel(xs, ys, zrow[totvlak][1]);
|
|
|
|
a= count_mask(zrow[totvlak][2]);
|
|
if( (R.r.mode & R_OSA ) && a<R.osa) {
|
|
if(totvlak>0) {
|
|
memset(sampcol, 0, 4*2*R.osa);
|
|
sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]);
|
|
|
|
/* sval==0: aplha helemaal vol */
|
|
while( (sval != 0) && (totvlak>0) ) {
|
|
a= count_mask(zrow[totvlak-1][2]);
|
|
if(a==R.osa) break;
|
|
totvlak--;
|
|
|
|
b= centmask[ zrow[totvlak][2] ];
|
|
|
|
xs= (float)x+centLut[b & 15];
|
|
ys= (float)y+centLut[b>>4];
|
|
|
|
shadetrapixel(xs, ys, zrow[totvlak][1]);
|
|
sval= addtosampcol(sampcol, shortcol, zrow[totvlak][2]);
|
|
}
|
|
scol= sampcol;
|
|
intcol[0]= scol[0]; intcol[1]= scol[1];
|
|
intcol[2]= scol[2]; intcol[3]= scol[3];
|
|
scol+= 4;
|
|
for(a=1; a<R.osa; a++, scol+=4) {
|
|
intcol[0]+= scol[0]; intcol[1]+= scol[1];
|
|
intcol[2]+= scol[2]; intcol[3]+= scol[3];
|
|
}
|
|
tempcol[0]= intcol[0]/R.osa;
|
|
tempcol[1]= intcol[1]/R.osa;
|
|
tempcol[2]= intcol[2]/R.osa;
|
|
tempcol[3]= intcol[3]/R.osa;
|
|
|
|
addAlphaUnderShort(col, tempcol);
|
|
|
|
}
|
|
else {
|
|
a= alpha[a];
|
|
shortcol[0]= (shortcol[0]*a)>>16;
|
|
shortcol[1]= (shortcol[1]*a)>>16;
|
|
shortcol[2]= (shortcol[2]*a)>>16;
|
|
shortcol[3]= (shortcol[3]*a)>>16;
|
|
addAlphaUnderShort(col, shortcol);
|
|
}
|
|
}
|
|
else addAlphaUnderShort(col, shortcol);
|
|
|
|
if(col[3]>=0xFFF0) break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
usegamtab= tempgam;
|
|
R.flag= tempRf;
|
|
}
|
|
|
|
/* end of zbuf.c */
|
|
|
|
|
|
|
|
|