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