home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Club Amiga de Montreal - CAM
/
CAM_CD_1.iso
/
files
/
174.lha
/
BezSurf
/
mapstuff.c
< prev
next >
Wrap
C/C++ Source or Header
|
1988-04-28
|
10KB
|
413 lines
#include <math.h>
#include "mytypes.h"
#include "poly.h"
#include "bezpt.h"
#include "revolve.h"
#include "readilbm.h"
#include "mapstuff.h"
#include "menuexp.h"
#define FarRight 1e6
#define FarLeft -1e6
#define FarTop 0x7fff
#define FarBottom -0x7fff
/*
#ifndef MANX
#include "libraries/mathffp.h"
#define ceil SPCeil
#define floor SPFloor
#define fabs SPAbs
#endif
*/
typedef struct { float left, right; } Hedge;
static float *BezMapping = null,
*RevMapping = null;
static float revmin, revdiff,
bezmin, bezdiff;
/*
* given the ptlist of a polygon, find its vertical range
*/
static void FindVRange(scrnlist, top, bottom)
register ScrnPair *scrnlist;
short *top, *bottom;
{
short i;
short localtop, localbot;
localtop = FarBottom;
localbot = FarTop;
for( i = 4; i--; scrnlist++ ) {
if( localtop < scrnlist->y ) localtop = scrnlist->y;
if( localbot > scrnlist->y ) localbot = scrnlist->y;
}
*top = localtop;
*bottom = localbot;
}
/*
* allocate table to store a quick and dirty representation of the
* quadrilateral segments
*/
static Hedge *InitVRange( depth, tabptr, olddepth )
short depth, *olddepth;
Hedge *tabptr;
{
Hedge *edgel, *tab;
if( *olddepth < depth || !tabptr ) {
if( tabptr ) free( tabptr);
tab = (Hedge *) malloc(sizeof(Hedge)*depth);
*olddepth = depth;
}
else {
tab = tabptr;
}
if( !tab ) return( null);
for( edgel = tab; depth--; edgel++) {
edgel->left = FarRight;
edgel->right = FarLeft;
}
return( tab );
}
/*
* add line to quadrilateral descriptions
*/
static void AddVLine( tab, x1, y1, x2, y2 )
Hedge *tab;
short x1, y1, x2, y2;
{
short dy;
float curx, slope;
/*
* want y1 to have smaller value, ie, y1 below y2
*/
if( y1 > y2 ) {
short temp;
temp = y1; y1 = y2; y2 = temp;
temp = x1; x1 = x2; x2 = temp;
}
dy = y2 - y1;
tab += y1;
if( !dy ) {
if ( x1 < x2 ) {
short tempx;
tempx = x1; x1 = x2; x2 = tempx;
}
if( x2 < tab->left ) tab->left = x2;
if( x1 > tab->right ) tab->right = x1;
return;
}
slope = (float)(x2 - x1)/dy;
curx = x1;
#define ZipIt(xxx) { if( xxx < tab->left) tab->left = xxx; \
if( xxx > tab->right ) tab->right = xxx; }
ZipIt(curx);
while( dy--) {
curx += slope;
tab++;
ZipIt(curx);
}
}
static void AdjMapXY( inx, iny, outpair)
float inx, iny;
ScrnPair *outpair;
{
float outx, outy;
MapXYRatio( inx, iny, &outx, &outy);
outpair->y = MapImageH * (bezmin + bezdiff * outy);
outpair->x = MapImageV * (revmin + revdiff * outx);
/*
if( RevAxis == RevX ) {
outpair->y = MapImageH * (bezmin + bezdiff * outy);
outpair->x = MapImageV * (revmin + revdiff * outx);
} else {
outpair->x = MapImageH * (bezmin + bezdiff * outy);
outpair->y = MapImageV * (revmin + revdiff * outx);
}
*/
}
static void ScanCnvQuad( tab, pt)
Hedge *tab;
ScrnPair pt[];
{
register int i;
ScrnPair *listb, *liste;
liste = pt;
listb = liste + 3;
for ( i = 4; i--;) {
AddVLine( tab, listb->x, listb->y, liste->x, liste->y);
listb = liste++;
}
}
static float AverageShade(pts)
ScrnPair pts[];
{
register Hedge *tab;
static Hedge *tabfree = null;
static short olddepth = 0;
short top, bot;
long shade = 0,
pixcnt = 0;
FindVRange( pts, &top, &bot);
tabfree = tab = InitVRange( top - bot + 1, tabfree, &olddepth);
if(!tabfree) return(0.0);
ScanCnvQuad( tab-bot, pts );
#if DEBUG
if( DebugOn ) {
printf("AverageShade top is %d, bot = %d\n", top, bot );
}
#endif DEBUG
while( bot <= top ) {
register int hori;
int right, left;
#if DEBUG
if( DebugOn ) {
printf("....row %d \t%d -> %d\n", bot, left, right );
}
#endif DEBUG
left = (int) ceil(tab->left - SingleTinyVal);
right = (int)floor(tab->right+ SingleTinyVal);
for( hori= left; hori <= right; hori++ ) {
shade += GetImgPix( bot, hori);
pixcnt++;
}
/*
if( RevAxis == RevX ) {
for( hori= left; hori <= right; hori++ ) {
shade += GetImgPix( bot, hori);
pixcnt++;
}
}
else {
for( hori= left; hori <= right; hori++ ) {
shade += GetImgPix( hori, bot);
pixcnt++;
}
}
*/
tab++;
bot++;
}
return( (float)shade / (pixcnt *(15 *16)) );
}
/*
* mess with the number so truncation doesn't
* do nasty things to a float containing an int
*/
static int NearestInt( afloat )
float afloat;
{
afloat += ( afloat > 0 )? 1e-2 : -1e-2;
return( (int)afloat );
}
static void ShadeQuad(tab, top, bot, intensity)
register Hedge *tab;
short top, bot;
float intensity;
{
short vert;
float rowminl, rowminr,
rowmaxl, rowmaxr;
Hedge *oldtab, *nexttab;
for ( vert = bot;
nexttab = tab+1, vert <= top;
vert++, oldtab = tab, tab++ ) {
float hori;
float colmin, colmax;
float leftmost, rightmost;
int ihori, ileftmost, irightmost;
ScrnPair MpPnts[4];
#define lefttop MpPnts[0]
#define leftbot MpPnts[3]
#define righttop MpPnts[1]
#define rightbot MpPnts[2]
rowminl = (float)vert;
rowmaxr = rowmaxl = rowminr = rowminl;
if( vert > bot && oldtab->left < tab->left ) {
rowminl -= 0.5;
}
if( vert > bot && oldtab->right > tab->right ) {
rowminr -= 0.5;
}
if( vert < top && nexttab->left < tab->left ) {
rowmaxl += 0.5;
}
if( vert < top && nexttab->right > tab->right ) {
rowmaxr += 0.5;
}
irightmost = NearestInt( tab->right );
rightmost = irightmost;
ileftmost = NearestInt( tab->left );
leftmost = ileftmost;
if( irightmost < ileftmost ) {
irightmost = ileftmost;
}
for( ihori = leftmost, hori = leftmost;
ihori <= irightmost;
ihori += 1, hori += 1.0 ) {
if( AbortDraw ) { return; }
colmin = hori - 0.5;
colmax = hori + 0.5;
colmin =(colmin > leftmost)?colmin: tab->left;
colmax =(colmax < rightmost)?colmax: tab->right;
AdjMapXY( colmin, rowmaxl, &lefttop, MP_XMIN| MP_YMAX);
AdjMapXY( colmax, rowmaxr, &righttop, MP_XMAX| MP_YMAX);
AdjMapXY( colmin, rowminl, &leftbot, MP_XMIN| MP_YMIN);
AdjMapXY( colmax, rowminr, &rightbot, MP_XMAX| MP_YMIN);
PaintPoint(ihori, vert, AverageShade(MpPnts) *intensity);
}
}
#undef lefttop
#undef righttop
#undef rightbot
#undef leftbot
}
void DrawRhomMap(mpr)
MapRhomboid *mpr;
{
short top, bottom;
short vrange, hrange;
static Hedge *tab = null;
static short olddepth = 0;
CalcMapConsts( mpr->rhom.pt );
FindVRange( mpr->rhom.pt, &top, &bottom );
tab = InitVRange( top - bottom + 1, tab, &olddepth );
if(!tab) return;
ScanCnvQuad( tab -bottom, mpr->rhom.pt );
bezmin = BezMapping[mpr->bezindex];/* make it global */
bezdiff = BezMapping[mpr->bezindex+1] - bezmin;
revmin = RevMapping[mpr->revindex];
revdiff = RevMapping[mpr->revindex+1] - revmin;
#if DEBUG
if( DebugOn ) {
DBMAP(mpr->rhom.pt, mpr->bezindex, mpr->revindex);
}
#endif DEBUG
ShadeQuad(tab, top, bottom, mpr->rhom.intensity);
}
#ifdef DEBUG
DBMAP(ptlist, bindex, rindex)
ScrnPair ptlist[];
short bindex, rindex;
{
int i;
printf("...................................\n");
for( i = 0; i < 4; i++ ) {
printf("%10d", ptlist[i].x);
};
printf("\n");
for( i = 0; i < 4; i++ ) {
printf("%10d", ptlist[i].y);
};
printf("\n");
printf(" bezmin %f bezdiff %f index = %d \n", bezmin, bezdiff, bindex );
printf(" revmin %f revdiff %f index = %d \n", revmin, revdiff, rindex );
}
#endif DEBUG
/*
* return true if image mappings could not be performed
* false if successful
*/
bool InitMapping() {
float *vfmptr;
float totallen = 0,
scaling;
short numvslices;
if( BezMapping ) free( BezMapping );
if( RevMapping ) free( RevMapping );
/*
* compute width of each bezier segment
*/
numvslices = BezMesh*GetNumSegs() +1;
vfmptr = BezMapping = (float *) malloc(sizeof(float) * numvslices);
if( !BezMapping ) return(true);
*vfmptr++ = totallen = 0.0;
ResetActSeg();
do {
float t, ffromx, ftox, ffromy, ftoy;
int i;
InitCalcBez();
for( i = 1, ffromx = StartPtX(ActSeg), ffromy = StartPtY(ActSeg);
i <= BezMesh; i++, ffromx = ftox, ffromy = ftoy ) {
float diffx, diffy;
t = (float)i/BezMesh;
CalcBezPt( t, &ftox, &ftoy );
diffx = ftox - ffromx;
diffy = ftoy - ffromy;
totallen += sqrt( diffx * diffx + diffy * diffy );
*vfmptr++ = totallen;
}
NextSeg();
} while( ActSeg);
/*
* convert scale floating point values to integer pixel positions
*/
scaling = 1.0 / totallen;
for( vfmptr = BezMapping; numvslices; numvslices--, vfmptr++ ) {
*vfmptr *= scaling;
}
/*
* compute height of each revolution segment
*/
RevMapping = (float *) malloc( sizeof(float) * (RevMesh + 1));
if( !RevMapping ) return( true );
{
short i;
for( i = 0; i <= RevMesh; i++ ) {
RevMapping[i] = ((float) i)/RevMesh;
}
}
return(false);
}