This repository has been archived on 2023-10-09. You can view files and clone it, but cannot push or open issues or pull requests.
Files
blender-archive/source/blender/render/intern/source/edgeRender.c
Kent Mein d0e346d544 updated .c files to include:
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

Just need to finish cpp files now :)

Kent
--
mein@cs.umn.edu
2002-11-25 12:02:15 +00:00

957 lines
25 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): none yet.
*
* ***** END GPL/BL DUAL LICENSE BLOCK *****
* Add enhanced edges on a rendered image (toon shading, edge shading).
*/
/*
* Edge rendering: use a mask to weigh the depth of neighbouring
* pixels, and do a colour correction.
*
* We need:
* - a buffer to store the depths (ints)
* - a function that alters the colours in R.rectot (copy edge_enhance?)
* The max. z buffer depth is 0x7FFF.FFFF (7 F's)
*
* - We 'ignore' the pixels falling outside the regular buffer (we fill)
* these with the max depth. This causes artefacts when rendering in
* parts.
*/
/* ------------------------------------------------------------------------- */
/* enable extra bounds checking and tracing */
/* #define RE_EDGERENDERSAFE */
/* disable the actual edge correction */
/* #define RE_EDGERENDER_NO_CORRECTION */
#include <stdlib.h>
#include <math.h>
#include <limits.h> /* INT_MIN,MAX are used here */
#include <stdio.h>
#include "MEM_guardedalloc.h"
#include "MTC_vectorops.h"
#include "RE_callbacks.h"
#include "edgeRender.h"
#include "render.h"
#include "render_intern.h"
#include "zbuf.h" /* for zbufclipwire and zbufclip */
#include "jitter.h"
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#ifdef RE_EDGERENDERSAFE
char edgeRender_h[] = EDGERENDER_H;
char edgeRender_c[] = "$Id$";
#include "errorHandler.h"
#endif
/* ------------------------------------------------------------------------- */
/* the lazy way: */
#define MIN2(x,y) ( (x)<(y) ? (x) : (y) )
/* ------------------------------------------------------------------------- */
/* These function pointers are used for z buffer filling. */
extern void (*zbuffunc)(float *, float *, float *);
extern void (*zbuflinefunc)(float *v1, float *v2);
extern float Zmulx, Zmuly; /* Some kind of scale? */
extern float Zjitx,Zjity; /* The x,y values for jitter offset */
extern unsigned int Zvlnr; /* Face rendering pointer and counter: these */
extern VlakRen *Zvlr; /* are used for 'caching' render results. */
/* ------------------------------------------------------------------------- */
/* exp: */
static Material** matBuffer; /* buffer with material indices */
static Material* mat_cache; /* material of the face being buffered */
static char* colBuffer; /* buffer with colour correction */
static int *edgeBuffer; /* buffer with distances */
static int bufWidth; /* x-dimension of the buffer */
static int bufHeight; /* y-dimension of the buffer */
static int imWidth; /* x-dimension of the image */
static int imHeight; /* y-dimension of the image */
static int osaCount; /* oversample count */
static int maskBorder; /* size of the mask border */
static short int intensity; /* edge intensity */
static short int same_mat_redux; /* intensity reduction for boundaries with the same material */
static int compatible_mode; /* edge positioning compatible with old rederer */
static int selectmode; /* 0: only solid faces, 1: also transparent f's */
static int Aminy; /* y value of first line in the accu buffer */
static int Amaxy; /* y value of last line in the accu buffer */
/* -also used to clip when zbuffering */
static char edgeR; /* Colour for the edges. The edges will receive */
static char edgeG; /* this tint. The colour is fully used! */
static char edgeB;
/* static float edgeBlend; */ /* Indicate opaqueness of the edge colour. */
/* Local functions --------------------------------------------------------- */
/**
* Initialise the edge render buffer memory.
*/
void initEdgeRenderBuffer(void);
/**
* Release buffer memory.
*/
void freeEdgeRenderBuffer(void);
/**
* Set all distances in the distance buffer to the maximum distance.
*/
void resetDistanceBuffer(void);
/**
* Insert this distance at these pixel coordinates.
*/
void insertInEdgeBuffer(int x, int y, int dist);
/**
* Renders enhanced edges. Distances from distRect are used to
* determine a correction on colourRect
*/
void renderEdges(char * colourRect);
/**
* Buffer an edge between these two vertices in the e.r. distance buffer.
*/
void fillEdgeRenderEdge(float *vec1, float *vec2);
/**
* Buffer a face between these two vertices in the e.r. distance buffer.
*/
void fillEdgeRenderFace(float *v1, float *v2, float *v3);
/**
* Compose the edge render colour buffer.
*/
void calcEdgeRenderColBuf(char * tarbuf);
/**
* Loop over all objects that need to be edge rendered. This loop determines
* which objects get to be elected for edge rendering.
*/
int zBufferEdgeRenderObjects(void);
/**
* Add edge pixels to the original image. It blends <bron> over <doel>.
*/
void addEdgeOver(char *doel, char *bron);
/* ------------------------------------------------------------------------- */
void addEdges(
char * targetbuf,
int iw, int ih,
int osanr,
short int intens, short int intens_redux,
int compat, int mode,
float r, float g, float b
)
{
float rf, gf ,bf;
/* render parameters */
selectmode = mode;
imWidth = iw;
imHeight = ih;
compatible_mode = compat;
osaCount = osanr;
intensity = intens;
/* Reduction doesn't exceed intensity. */
same_mat_redux = ((intens_redux < intensity)? intens_redux : intensity);
rf = r * 255.0;
if (rf > 255) edgeR = 255; else edgeR = rf;
gf = g * 255.0;
if (gf > 255) edgeG = 255; else edgeG = gf;
bf = b * 255.0;
if (bf > 255) edgeB = 255; else edgeB = bf;
/* Go! */
initEdgeRenderBuffer();
calcEdgeRenderColBuf(targetbuf);
freeEdgeRenderBuffer();
} /* end of void addEdges(char *, int, int, int, short int , int) */
/* ------------------------------------------------------------------------- */
void initEdgeRenderBuffer()
{
char *ptr;
int i;
maskBorder = 1; /* for 3 by 3 mask*/
bufWidth = imWidth + (2 * maskBorder);
bufHeight = imHeight + (2 * maskBorder);
/* Experimental: store the material indices. */
if (same_mat_redux) {
matBuffer = MEM_callocN(sizeof(Material*)
* bufWidth * bufHeight, "matBuffer");
}
edgeBuffer = MEM_callocN(sizeof(int) * bufWidth * bufHeight, "edgeBuffer");
colBuffer = MEM_callocN(sizeof(char) * 4 * imWidth * imHeight, "colBuffer");
if ((edgeR != 0) || (edgeG != 0) || (edgeB != 0)) {
/* Set all colbuf pixels to the edge colour. Leave alpha channel */
/* cleared. Actually, we could blend in any image here... */
ptr = colBuffer;
for (i = 0; i < imWidth * imHeight; i++, ptr+=4)
{
ptr[0] = edgeR;
ptr[1] = edgeG;
ptr[2] = edgeB;
ptr[3] = 0;
}
}
#ifdef RE_EDGERENDERSAFE
if (!edgeBuffer || !colBuffer) {
char *fname = "initEdgeRenderBuffer";
RE_error(RE_CANNOT_ALLOCATE_MEMORY, fname);
}
#endif
} /* end of void initEdgeRenderBuffer(void) */
/* ------------------------------------------------------------------------- */
void freeEdgeRenderBuffer(void)
{
if(edgeBuffer) MEM_freeN(edgeBuffer);
if(colBuffer) MEM_freeN(colBuffer);
if(matBuffer) MEM_freeN(matBuffer);
} /* end of void freeEdgeRenderBuffer(void) */
/* ------------------------------------------------------------------------- */
void resetDistanceBuffer(void)
{
int i;
for(i = 0; i < bufWidth * bufHeight; i++) edgeBuffer[i] = 0x7FFFFFFF;
} /* end of void resetDistanceBuffer(void) */
/* ------------------------------------------------------------------------- */
void insertInEdgeBuffer(int x, int y, int dist)
{
int index;
#ifdef RE_EDGERENDERSAFE
char *fname = "insertInEdgeBuffer";
if ((x < 0) || (x > imWidth ) ||
(y < 0) || (y > (imHeight-1) ) ) {
RE_error(RE_EDGERENDER_WRITE_OUTSIDE_BUFFER, fname);
return;
}
#endif
/* +1? */
index = (y * bufWidth) + x + maskBorder;
/*exp: just dump a single index here. Maybe we can do more
* sophisticated things later on. */
if (same_mat_redux) {
matBuffer[index] = mat_cache;
}
if (edgeBuffer[index] >dist ) edgeBuffer[index] = dist;
} /* end of void insertInEdgeBuffer(int x, int y, int dist) */
/* ------------------------------------------------------------------------- */
/* Modelled after rendercore.c/edge_enhance() */
void renderEdges(char *colourRect)
{
/* use zbuffer to define edges, add it to the image */
int val, y, x, col, *rz, *rz1, *rz2, *rz3;
char *cp;
int targetoffset, heightoffset;
int i;
int matdif; /* For now: just a bogus int, 0 when all materials
* under the mask are the same, non-0 otherwise*/
int *matptr_low = 0, *matptr_cent = 0, *matptr_high = 0;
int matdiffac = 0;
#ifdef RE_EDGERENDER_NO_CORRECTION
return; /* no edge correction */
#endif
#ifdef RE_EDGERENDERSAFE
fprintf(stderr, "\n*** Activated full error trace on "
"edge rendering using:\n\t%s\n\t%s"
"\n*** Rendering edges at %d intensity",
edgeRender_c, edgeRender_h, intensity);
#endif
/* Old renderer uses wrong positions! With the compat switch on, the po- */
/* sitions will be corrected to be offset in the same way. */
if (compatible_mode) {
targetoffset = 4 * (imWidth - 1);
heightoffset = -1;
} else {
targetoffset = 0;
heightoffset = 0;
}
/* Fill edges with some default values. We just copy what is in the edge */
/* This looks messy, but it appears to be ok. */
edgeBuffer[0] = edgeBuffer[bufWidth + 1];
edgeBuffer[bufWidth - 1] = edgeBuffer[(2 * bufWidth) - 2];
edgeBuffer[bufWidth * (bufHeight - 1)] =
edgeBuffer[bufWidth * (bufHeight - 2) + 1];
edgeBuffer[(bufWidth * bufHeight) - 1] =
edgeBuffer[(bufWidth * (bufHeight - 1)) - 2];
for (i = 1; i < bufWidth - 1; i++) { /* lieing edges */
edgeBuffer[i] = edgeBuffer[bufWidth + i]; /* bottom*/
edgeBuffer[((bufHeight - 1)*bufWidth) + i]
= edgeBuffer[((bufHeight - 2)*bufWidth) + i]; /* top */
}
for (i = 1; i < bufHeight - 2; i++) { /* standing edges */
edgeBuffer[i * bufWidth] = edgeBuffer[(i * bufWidth) + 1]; /* left */
edgeBuffer[((i + 1) * bufWidth) - 1] =
edgeBuffer[((i + 1) * bufWidth) - 2]; /* right */
}
/* same hack for the materials: */
if (same_mat_redux) {
matBuffer[0] = matBuffer[bufWidth + 1];
matBuffer[bufWidth - 1] = matBuffer[(2 * bufWidth) - 2];
matBuffer[bufWidth * (bufHeight - 1)] =
matBuffer[bufWidth * (bufHeight - 2) + 1];
matBuffer[(bufWidth * bufHeight) - 1] =
matBuffer[(bufWidth * (bufHeight - 1)) - 2];
for (i = 1; i < bufWidth - 1; i++) { /* lieing mats */
matBuffer[i] = matBuffer[bufWidth + i]; /* bottom*/
matBuffer[((bufHeight - 1)*bufWidth) + i]
= matBuffer[((bufHeight - 2)*bufWidth) + i]; /* top */
}
for (i = 1; i < bufHeight - 2; i++) { /* standing mats */
matBuffer[i * bufWidth] = matBuffer[(i * bufWidth) + 1]; /* left */
matBuffer[((i + 1) * bufWidth) - 1] =
matBuffer[((i + 1) * bufWidth) - 2]; /* right */
}
}
/* alle getallen in zbuffer 3 naar rechts shiften */
rz = edgeBuffer;
if(rz==0) return;
for(y=0; y < bufHeight * bufWidth; y++, rz++) {
(*rz)>>= 3;
}
/* Distance pointers */
rz1= edgeBuffer;
rz2= rz1 + bufWidth;
rz3= rz2 + bufWidth;
if (same_mat_redux) {
matptr_low = matBuffer;
matptr_cent = matptr_low + bufWidth;
matptr_high = matptr_cent + bufWidth;
}
if (osaCount == 1) {
cp = colourRect + targetoffset;
} else {
cp = colBuffer + targetoffset;
}
i = 0;
for(y = 0; y < (imHeight + heightoffset) ; y++) {
/* All these indices are a bit silly. I need to
* rewrite this, so all buffers use the same
* indexing. */
for(x = 0;
x < imWidth;
x++, rz1++, rz2++, rz3++, cp+=4,
matptr_low++,
matptr_cent++,
matptr_high++) {
col= abs( - rz1[0] - 2*rz1[1] - rz1[2]
- 2*rz2[0] + 12*rz2[1] - 2*rz2[2]
- rz3[0] - 2*rz3[1] - rz3[2]) / 3;
/* Several options for matdif:
*
* - suppress all boundaries with 0 dif
*
* - weaken col dif? Or decrease intensity by
* a factor when non 0 dif??
*/
/* exp: matdif is non-0 if the mask-center
* material differs from any of the
* corners. */
if (same_mat_redux) {
matdif = abs (matptr_cent[1] - matptr_low[0])
+ abs (matptr_cent[1] - matptr_low[1])
+ abs (matptr_cent[1] - matptr_low[2])
+ abs (matptr_cent[1] - matptr_cent[0])
+ abs (matptr_cent[1] - matptr_low[2])
+ abs (matptr_cent[1] - matptr_high[0])
+ abs (matptr_cent[1] - matptr_high[1])
+ abs (matptr_cent[1] - matptr_high[2]);
matdiffac = (matdif ? 0 : same_mat_redux);
}
col= ((intensity - matdiffac) * col)>>14;
if(col>255) col= 255;
/* Colour edge if
*
* 1. there is an appreciable, non-uniform
* gradient,
*
* 2. there are different materials bordering
* on the center pixel
*/
if( (col>0)
/* && (matdif != 0) */) {
if(osaCount > 1) {
/* Currently done by tweaking alpha. The colBuffer is */
/* filled with pixels of the colour appropriate for the */
/* edges. This colour is alpha-blended over the image. */
/* This calculation determines how much colour each pixel */
/* gets. */
col/= osaCount;
val= cp[3]+col;
if(val>255) cp[3]= 255; else cp[3]= val;
}
else {
/* the pixel is blackened when col is too big */
val = cp[0] - col;
if(val<=0) {
cp[0]= edgeR;
} else {
cp[0]= val;
}
val = cp[1] - col;
if(val<=0) {
cp[1]= edgeG;
}else {
cp[1]= val;
}
val = cp[2] - col;
if(val<=0) {
cp[2]= edgeB;
} else {
cp[2]= val;
}
}
}
}
rz1+= 2;
rz2+= 2;
rz3+= 2;
if (same_mat_redux) {
matptr_low += 2;
matptr_cent += 2;
matptr_high += 2;
}
}
} /* end of void renderEdges() */
/* ------------------------------------------------------------------------- */
void addEdgeOver(char *doel, char *bron) /* telt bron bij doel */
{
float c;
int mul;
if( bron[3] == 0) return;
if( bron[3] == 255) { /* is getest, scheelt */
*((unsigned int *)doel)= *((unsigned int *)bron);
return;
}
/* This must be a special blend-mode, because we get a 'weird' data */
/* input format now. With edge = (c_e, a_e), picture = (c_p, a_p), we */
/* get: result = ( c_e*a_e + c_p(1 - a_e), a_p ). */
mul = 255 - bron[3];
/* Not sure if the conversion to float is really necessary here... I will*/
/* think about it another day. */
c = ((mul * doel[0] + bron[0] * bron[3])/255.0);
if(c>255) {doel[0]=255;} else { doel[0]= c;}
c = ((mul * doel[1] + bron[1] * bron[3])/255.0);
if(c>255) {doel[1]=255;} else { doel[1]= c;}
c = ((mul * doel[2] + bron[2] * bron[3])/255.0);
if(c>255) {doel[2]=255;} else { doel[2]= c;}
}
void calcEdgeRenderColBuf(char* colTargetBuffer)
{
/* int part; */
int keepLooping = 1;
int sample;
/* zbuffer fix: here? */
Zmulx= ((float) imWidth)/2.0;
Zmuly= ((float) imHeight)/2.0;
/* use these buffer fill functions */
zbuffunc = fillEdgeRenderFace;
zbuflinefunc = fillEdgeRenderEdge;
/* always buffer the max. extent */
Aminy = 0;
Amaxy = imHeight;
sample = 0; /* Zsample is used internally ! */
while ( (sample < osaCount) && keepLooping ) {
/* jitter */
Zjitx= -jit[sample][0];
Zjity= -jit[sample][1];
/* should reset dis buffer here */
resetDistanceBuffer();
/* kick all into a z buffer */
keepLooping = zBufferEdgeRenderObjects();
/* do filtering */
renderEdges(colTargetBuffer);
if(RE_local_test_break()) keepLooping = 0;
sample++;
}
/* correction for osa-sampling...*/
if( osaCount != 1) {
char *rp, *rt;
int a;
rt= colTargetBuffer;
rp= colBuffer;
for(a = imWidth * imHeight; a>0; a--, rt+=4, rp+=4) {
/* there seem to be rounding errors here... */
addEdgeOver(rt, rp);
}
}
} /*End of void calcEdgeRenderZBuf(void) */
/* ------------------------------------------------------------------------- */
/* Clip flags etc. should still be set. When called in the span of 'normal' */
/* rendering, this should be ok. */
int zBufferEdgeRenderObjects(void)
{
int keepLooping;
int faceCounter; /* counter for face number */
Material *ma;
keepLooping = 1;
ma = NULL;
faceCounter = 0;
while ( (faceCounter < R.totvlak) && keepLooping) {
if((faceCounter & 255)==0) { Zvlr= R.blovl[faceCounter>>8]; }
else Zvlr++;
ma= Zvlr->mat;
/*exp*/
mat_cache = ma;
/* face number is used in the fill functions */
Zvlnr = faceCounter + 1;
if(Zvlr->flag & R_VISIBLE) {
/* here we cull all transparent faces if mode == 0 */
if (selectmode || !(ma->mode & MA_ZTRA)) {
/* here we can add all kinds of extra selection criteria */
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; /* in a sense, the 'adjoint' face */
zbufclip(Zvlr->v1->ho, Zvlr->v3->ho, Zvlr->v4->ho,
Zvlr->v1->clip, Zvlr->v3->clip, Zvlr->v4->clip);
}
}
}
};
if(RE_local_test_break()) keepLooping = 0;
faceCounter++;
}
return keepLooping;
} /* End of int zBufferEdgeRenderObjects(void) */
/* ------------------------------------------------------------------------- */
void fillEdgeRenderFace(float *v1, float *v2, float *v3)
{
/* Coordinates of the vertices are specified in ZCS */
double z0; /* used as temp var*/
double xx1;
double zxd,zyd,zy0, tmp;
float *minv,*maxv,*midv;
int zverg,x;
int my0,my2,sn1,sn2,rectx,zd;
int y,omsl,xs0,xs1,xs2,xs3, dx0,dx1,dx2/* , mask */;
int linex, liney, xoffset, yoffset; /* pointers to the pixel number */
/* These used to be doubles. We may want to change them back if the */
/* loss of accuracy proves to be a problem? There does not seem to be */
/* any performance issues here, so I'll just keep the doubles. */
/* float vec0[3], vec1[3], vec2[3]; */
double vec0[3], vec1[3], vec2[3];
/* MIN MAX */
/* sort vertices for min mid max y value */
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]);
/* outside the current z buffer slice: clip whole face */
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 */
MTC_diff3DFF(vec1, v1, v2);
MTC_diff3DFF(vec2, v2, v3);
MTC_cross3Double(vec0, vec1, vec2);
/* cross product of two of the sides is 0 => this face is too small */
if(vec0[2]==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= (vec0[0]*v1[0]+vec0[1]*v1[1])/vec0[2]+v1[2];
zxd= -vec0[0]/vec0[2];
zyd= -vec0[1]/vec0[2];
zy0= my2*zyd+xx1;
zd= (int)CLAMPIS(zxd, INT_MIN, INT_MAX);
/* start-ofset in rect */
/* rectx= R.rectx; */
/* I suspect this var needs very careful setting... When edge rendering */
/* is on, this is strange */
rectx = imWidth;
yoffset = my2;
xoffset = 0;
xs3= 0; /* flag */
if(dx0>dx1) {
MTC_swapInt(&xs0, &xs1);
MTC_swapInt(&dx0, &dx1);
xs3= 1; /* flag */
}
liney = yoffset;
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);
if ((sn1 < 0) || (sn1>imWidth) ) printf("\n sn1 exceeds line");
linex = xoffset + sn1;
liney = yoffset;
x= sn2-sn1;
while(x>=0) {
insertInEdgeBuffer(linex , liney, zverg); /* line y not needed here */
zverg+= zd;
linex++;
x--;
}
zy0-= zyd;
yoffset--;
}
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);
linex = sn1;
liney = yoffset;
x= sn2-sn1;
while(x>=0) {
insertInEdgeBuffer(linex, liney, zverg); /* line y not needed here */
zverg+= zd;
linex++;
x--;
}
zy0-=zyd;
yoffset--;
}
} /* end of void fillEdgeRenderFace(float *v1, float *v2, float *v3) */
/* ------------------------------------------------------------------------- */
void fillEdgeRenderEdge(float *vec1, float *vec2)
{
int start, end, x, y, oldx, oldy, ofs;
int dz, vergz/* , mask */;
float dx, dy;
float v1[3], v2[3];
int linex, liney;
int xoffset, yoffset;
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 >= imWidth) end = imWidth - 1;
oldy= floor(v1[1]);
dy/= dx;
vergz= v1[2];
dz= (v2[2]-v1[2])/dx;
yoffset = oldy;
xoffset = start;
if(dy<0) ofs= -imWidth;
else ofs= imWidth;
liney = yoffset;
linex = xoffset;
for(x= start; x<=end; x++, xoffset++) {
y= floor(v1[1]);
if(y!=oldy) {
oldy= y;
liney++;
}
if(x>=0 && y>=Aminy && y<=Amaxy) {
insertInEdgeBuffer(linex , liney, vergz);
}
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];
dz= (v2[2]-v1[2])/dy;
yoffset = start;
xoffset = oldx;
if(dx<0) ofs= -1;
else ofs= 1;
linex = xoffset;
liney = yoffset;
for(y= start; y<=end; y++, liney++) {
x= floor(v1[0]);
if(x!=oldx) {
oldx= x;
linex += ofs;
}
if(x>=0 && y>=Aminy && (x < imWidth)) {
insertInEdgeBuffer(linex, liney, vergz);
}
v1[0]+= dx;
vergz+= dz;
}
}
} /* End of void fillEdgeRenderEdge(float *vec1, float *vec2) */
/* ------------------------------------------------------------------------- */
/* eof edgeRender.c */