00001
00002
00003
00004
00005
00006
00007
00008
00009
00039
00040
00041
00042
00043 #ifdef _UNIX_
00044 #include <memory.h>
00045 #else
00046 #include <string.h>
00047 #endif
00048 #include <stdio.h>
00049 #include <stdlib.h>
00050 #include <math.h>
00051
00052 #include "cd.h"
00053 #include "zbf.h"
00054
00055
00056
00057
00058
00061 cdCanvas* Zbf::canvas = NULL;
00062
00065 Zbf::NscPnt* Zbf::poly = NULL;
00066
00069 int Zbf::sizepoly = 0;
00070
00073 int Zbf::npolyverts = 0;
00074
00077 Zbf::Edge* Zbf::poly_edge = NULL;
00078
00081 Zbf::Pixel* Zbf::scanline_vtx = NULL;
00082
00085 long int Zbf::curr_color = 0x0L;
00086
00088 int Zbf::cv_width = 100;
00089
00091 int Zbf::cv_height = 100;
00092
00093
00094 unsigned int* Zbf::zbuff = NULL;
00095
00096
00097
00098
00099
00100
00101
00102 void Zbf::NSCtoRaster( double xnsc, double ynsc, double znsc,
00103 int* xr, int* yr, unsigned int* zr )
00104 {
00105 double zconvfac = (double)((UINT_MAX-1)/2);
00106
00107
00108
00109
00110
00111
00112 *zr = (unsigned int)(zconvfac * (1.0 - znsc));
00113
00114 if ( *xr < 0 ) *xr = 0;
00115 else if( *xr > cv_width-1 ) *xr = cv_width-1;
00116 if ( *yr < 0 ) *yr = 0;
00117 else if( *yr > cv_height-1 ) *yr = cv_height-1;
00118 if ( *zr < 0 ) *zr = 0;
00119 else if( *zr > UINT_MAX ) *zr = UINT_MAX;
00120 }
00121
00122
00123
00124 void Zbf::OrderIntersections( Zbf::Pixel* vtx, int left, int right )
00125 {
00126 int i, j;
00127 int mid;
00128
00129 i = left;
00130 j = right;
00131 mid = vtx[(left + right) / 2].x;
00132
00133 do
00134 {
00135 while( i < right && vtx[i].x < mid )
00136 i++;
00137 while( j > left && mid < vtx[j].x )
00138 j--;
00139 if( i <= j )
00140 {
00141 Pixel aux;
00142
00143 aux = vtx[i];
00144 vtx[i] = vtx[j];
00145 vtx[j] = aux;
00146 i++;
00147 j--;
00148 }
00149 } while( i <= j );
00150
00151 if( left < j )
00152 OrderIntersections( vtx, left, j );
00153 if( i < right )
00154 OrderIntersections( vtx, i, right );
00155 }
00156
00157
00158
00159 void Zbf::ScanLine( Zbf::Pixel* vtx_lft, Zbf::Pixel* vtx_rgt, int ys )
00160 {
00161 unsigned int offset;
00162 int xl = vtx_lft->x + 1;
00163 int xr = vtx_rgt->x;
00164 int dx = vtx_rgt->x - vtx_lft->x;
00165 double z = vtx_lft->z;
00166 double dz;
00167
00168 if( dx == 0 )
00169 return;
00170
00171 dz = (vtx_rgt->z - vtx_lft->z) / dx;
00172 z += dz;
00173 offset = (unsigned int)( cv_width * ys );
00174
00175 while( xl <= xr )
00176 {
00177 if( z >= zbuff[offset+xl] )
00178 {
00179 int x0 = xl;
00180 do
00181 {
00182 zbuff[offset+xl] = (unsigned int)z;
00183 xl++;
00184 z += dz;
00185 } while( xl <= xr && z >= zbuff[offset+xl] );
00186 if( (xl-x0) == 1 )
00187 cdCanvasPixel( canvas, x0, ys, curr_color );
00188 else
00189 cdCanvasLine( canvas, x0, ys, xl-1, ys );
00190 }
00191 else
00192 {
00193 xl++;
00194 z += dz;
00195 }
00196 }
00197 }
00198
00199
00200
00201 int Zbf::MountEdges( Zbf::Edge* edge, int* ymin, int* ymax,
00202 int npoints, Zbf::NscPnt *poly )
00203 {
00204 int i, nedges = 0;
00205 int x0, y0;
00206 unsigned int z0;
00207
00208 NSCtoRaster(poly[0].x, poly[0].y, poly[0].z, &x0, &y0, &z0);
00209 *ymin = y0;
00210 *ymax = y0;
00211 for( i = 0; i < npoints; i++ )
00212 {
00213 int j = (i+1)%npoints;
00214 int xi, yi;
00215 unsigned int zi, zj;
00216 int xj, yj;
00217
00218 NSCtoRaster( poly[i].x, poly[i].y, poly[i].z, &xi, &yi, &zi );
00219 NSCtoRaster( poly[j].x, poly[j].y, poly[j].z, &xj, &yj, &zj );
00220
00221 if( yi != yj )
00222 {
00223 int dy = (yj - yi);
00224 edge[nedges].y_max = MAX(yi, yj);
00225 edge[nedges].y_min = MIN(yi, yj);
00226 edge[nedges].dxs = (double)(xj - xi) / dy;
00227 edge[nedges].dzs = (double)((double)zj - zi) / dy;
00228 if( edge[nedges].y_max == yi )
00229 {
00230 edge[nedges].xs = xi;
00231 edge[nedges].zs = zi;
00232 }
00233 else
00234 {
00235 edge[nedges].xs = xj;
00236 edge[nedges].zs = zj;
00237 }
00238 if( edge[nedges].y_max > *ymax )
00239 *ymax = edge[nedges].y_max;
00240 if( edge[nedges].y_min < *ymin )
00241 *ymin = edge[nedges].y_min;
00242 nedges++;
00243 }
00244 }
00245 return( nedges );
00246 }
00247
00248
00249
00250 int Zbf::MountInt( Zbf::Pixel* vtx, Zbf::Edge* edge, int* nedges, int ys )
00251 {
00252 int i, ninters = 0;
00253
00254 for( i = 0; i < *nedges; i++ )
00255 {
00256
00257 if( edge[i].y_min > ys )
00258 {
00259 edge[i] = edge[*nedges-1];
00260 *nedges = *nedges-1;
00261 }
00262
00263 if( (ys >= edge[i].y_min) && (ys < edge[i].y_max) )
00264 {
00265
00266 edge[i].xs -= edge[i].dxs;
00267 vtx[ninters].x = (int)edge[i].xs;
00268
00269
00270 edge[i].zs -= edge[i].dzs;
00271 vtx[ninters].z = edge[i].zs;
00272
00273 ninters++;
00274 }
00275 }
00276 return( ninters );
00277 }
00278
00279
00280
00281 void Zbf::FillPoly( int npoints, Zbf::NscPnt* poly )
00282 {
00283 static int old_npts = 0;
00284 int ymin, ymax;
00285 int nedges;
00286 int ys;
00287 int ninters;
00288 int i;
00289
00290
00291
00292 if (npoints > old_npts)
00293 {
00294 old_npts = 0;
00295 if( scanline_vtx )
00296 free( scanline_vtx );
00297 if( poly_edge )
00298 free( poly_edge );
00299 scanline_vtx = (Pixel*)malloc( (npoints+1)*sizeof(Pixel) );
00300 poly_edge = (Edge*)malloc( (npoints+1)*sizeof(Edge) );
00301 if( !scanline_vtx || !poly_edge )
00302 return;
00303 old_npts = npoints;
00304 }
00305
00306
00307
00308 nedges = MountEdges( poly_edge, &ymin, &ymax, npoints, poly );
00309
00310
00311
00312 for( ys = ymax; ys >= ymin; ys-- )
00313 {
00314
00315 ninters = MountInt( scanline_vtx, poly_edge, &nedges, ys );
00316
00317
00318 OrderIntersections( scanline_vtx, 0, ninters-1 );
00319
00320
00321 for( i = 0; i < ninters; i += 2 )
00322 {
00323 if( scanline_vtx[i].x < scanline_vtx[i+1].x )
00324 {
00325 ScanLine( &scanline_vtx[i], &scanline_vtx[i+1], ys );
00326 }
00327 }
00328 }
00329 }
00330
00331
00332
00333 void Zbf::Release( void )
00334 {
00335 if( zbuff )
00336 free( zbuff );
00337 zbuff = NULL;
00338
00339 if( poly )
00340 free( poly );
00341 poly = NULL;
00342 sizepoly = 0;
00343 npolyverts = 0;
00344 }
00345
00346
00347
00348 int Zbf::Alloc( void )
00349 {
00350 long int size = (long int)(cv_width*cv_height);
00351
00352 Release( );
00353
00354 zbuff = (unsigned int*)calloc( size, sizeof(unsigned int) );
00355 if( zbuff == NULL )
00356 return( 0 );
00357
00358 sizepoly = 10;
00359 poly = (NscPnt *)calloc( sizepoly, sizeof(NscPnt) );
00360
00361 return( 1 );
00362 }
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372 int Zbf::Init( cdCanvas* cv )
00373 {
00374 canvas = cv;
00375
00376 cdCanvasGetSize( canvas, &cv_width, &cv_height, 0L, 0L );
00377
00378 if( ! Alloc( ) )
00379 return( 0 );
00380
00381
00382
00383 memset( zbuff, 0, cv_width*cv_height*sizeof(unsigned int) );
00384
00385 return( 1 );
00386 }
00387
00388
00389
00390 void Zbf::Close( void )
00391 {
00392 Release( );
00393 cv_width = 0;
00394 cv_height = 0;
00395 }
00396
00397
00398
00399 void Zbf::BeginPoly( long int color )
00400 {
00401 if( ! zbuff )
00402 return;
00403
00404 curr_color = color;
00405 cdCanvasForeground( canvas, curr_color );
00406
00407 npolyverts = 0;
00408 }
00409
00410
00411
00412 void Zbf::Vertex( double x, double y, double z )
00413 {
00414 if( ! zbuff )
00415 return;
00416
00417 if( npolyverts == sizepoly )
00418 {
00419 sizepoly *= 2;
00420 poly = (NscPnt *)realloc( poly, sizepoly * sizeof(NscPnt) );
00421 }
00422
00423 poly[npolyverts].x = x;
00424 poly[npolyverts].y = y;
00425 poly[npolyverts].z = z;
00426 npolyverts++;
00427 }
00428
00429
00430
00431 void Zbf::EndPoly( void )
00432 {
00433 int i;
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443 for( i = 0; i < npolyverts; i++ )
00444 {
00445 if ( poly[i].x < -1.0 )
00446 return;
00447 else if( poly[i].x > 1.0 )
00448 return;
00449 if ( poly[i].y < -1.0 )
00450 return;
00451 else if( poly[i].y > 1.0 )
00452 return;
00453 if ( poly[i].z < -1.0 )
00454 return;
00455 else if( poly[i].z > 1.0 )
00456 return;
00457 }
00458
00459 FillPoly( npolyverts, poly );
00460 }
00461