z3d.l (19454B)
1 # 13apr13abu 2 # (c) Software Lab. Alexander Burger 3 4 (load "@lib/native.l") 5 6 ### Z-Buffer 3D library ### 7 (gcc "rcsim" '("-L/usr/X11R6/lib" "-lXext" "-lX11") 8 (z3dX (M X) z3dX NIL M (cons X 1.0)) 9 (z3dY (M Y) z3dY NIL M (cons Y 1.0)) 10 (z3dZ (M Z) z3dZ NIL M (cons Z 1.0)) 11 (z3dDX (M DX) z3dDX NIL M (cons DX 1.0)) 12 (z3dDY (M DY) z3dDY NIL M (cons DY 1.0)) 13 (z3dDZ (M DZ) z3dDZ NIL M (cons DZ 1.0)) 14 (z3dXrot (M A) z3dXrot NIL M (cons A 1.0)) 15 (z3dYrot (M A) z3dYrot NIL M (cons A 1.0)) 16 (z3dZrot (M A) z3dZrot NIL M (cons A 1.0)) 17 (z3dArot (M A) z3dArot NIL M (cons A 1.0)) 18 (z3dRotate (M X Y Z VarX VarY VarZ Flg) z3dRotate NIL 19 M 20 (cons X 1.0) 21 (cons Y 1.0) 22 (cons Z 1.0) 23 (if VarX (list @ (8 . 1.0)) 0) 24 (if VarY (list @ (8 . 1.0)) 0) 25 (if VarZ (list @ (8 . 1.0)) 0) 26 (if Flg 1 0) ) 27 (z3dSpot (VarX VarY X Y Z) z3dSpot NIL 28 (list VarX (8 . 1.0)) 29 (list VarY (8 . 1.0)) 30 (cons X 1.0) 31 (cons Y 1.0) 32 (cons Z 1.0) ) 33 (z3dWindow (Ttl DX DY) z3dWindow 'S Ttl DX DY) 34 (z3dCamera (Foc Yaw Pitch X Y Z Sky Gnd) z3dCamera NIL 35 (cons Foc 1.0) 36 (cons Yaw 1.0) 37 (cons Pitch 1.0) 38 (cons X 1.0) 39 (cons Y 1.0) 40 (cons Z 1.0) 41 Sky 42 Gnd ) 43 (z3dDraw (M) z3dDraw NIL M) 44 (z3dPut () z3dPut) 45 (z3dText (X Y S) z3dText NIL X Y S) 46 (z3dSync () z3dSync) ) 47 48 #include <stdint.h> 49 #include <stdlib.h> 50 #include <unistd.h> 51 #include <string.h> 52 #include <math.h> 53 54 #include <X11/Xlib.h> 55 #include <X11/Xutil.h> 56 #include <sys/shm.h> 57 #include <X11/extensions/XShm.h> 58 59 #define SCL 1000000.0 60 61 typedef struct {double x, y, z;} vector; 62 typedef struct {vector a, b, c;} matrix; 63 64 typedef struct face { 65 int col1, col2; // Foreground and background color 66 int cnt, _x_; // Number of points 67 vector pt[1]; // Points 68 } face; 69 70 typedef struct model { 71 vector pos; // Position 72 matrix rot; // Orientation 73 void *lst[1]; // List of faces and submodels 74 } model; 75 76 typedef struct { 77 int h[2]; // Horizontal 78 unsigned z[2]; // Depth 79 } edge; 80 81 static double FocLen, PosX, PosY, PosZ, Pos6, Pos9; 82 static double Coeff1, Coeff2, Coeff4, Coeff5, Coeff6, Coeff7, Coeff8, Coeff9; 83 84 static Display *Disp; 85 static int Scrn; 86 static Colormap Cmap; 87 static int Dpth; 88 static int PixSize; 89 static GC Gc; 90 static Window Win; 91 92 static int SizX, SizY, OrgX, OrgY; 93 static unsigned *Zbuff; 94 static edge *Edges; 95 static XImage *Img; 96 static XShmSegmentInfo Info; 97 98 // (z3dX 'model 'x) 99 void z3dX(model *p, double x) { 100 p->pos.x = x; 101 } 102 103 // (z3dY 'model 'y) 104 void z3dY(model *p, double y) { 105 p->pos.y = y; 106 } 107 108 // (z3dZ 'model 'z) 109 void z3dZ(model *p, double z) { 110 p->pos.z = z; 111 } 112 113 // (z3dDX 'model 'dx) 114 void z3dDX(model *p, double dx) { 115 p->pos.x += dx; 116 } 117 118 // (z3dDY 'model 'dy) 119 void z3dDY(model *p, double dy) { 120 p->pos.y += dy; 121 } 122 123 // (z3dDZ 'model 'dz) 124 void z3dDZ(model *p, double dz) { 125 p->pos.z += dz; 126 } 127 128 static void xrot(matrix *p, double ca, double sa) { 129 matrix m = *p; 130 131 p->b.x = ca * m.b.x - sa * m.c.x; 132 p->b.y = ca * m.b.y - sa * m.c.y; 133 p->b.z = ca * m.b.z - sa * m.c.z; 134 p->c.x = sa * m.b.x + ca * m.c.x; 135 p->c.y = sa * m.b.y + ca * m.c.y; 136 p->c.z = sa * m.b.z + ca * m.c.z; 137 } 138 139 static void yrot(matrix *p, double ca, double sa) { 140 matrix m = *p; 141 142 p->a.x = ca * m.a.x + sa * m.c.x; 143 p->a.y = ca * m.a.y + sa * m.c.y; 144 p->a.z = ca * m.a.z + sa * m.c.z; 145 p->c.x = ca * m.c.x - sa * m.a.x; 146 p->c.y = ca * m.c.y - sa * m.a.y; 147 p->c.z = ca * m.c.z - sa * m.a.z; 148 } 149 150 static void zrot(matrix *p, double ca, double sa) { 151 matrix m = *p; 152 153 p->a.x = ca * m.a.x + sa * m.b.x; 154 p->a.y = ca * m.a.y + sa * m.b.y; 155 p->a.z = ca * m.a.z + sa * m.b.z; 156 p->b.x = ca * m.b.x - sa * m.a.x; 157 p->b.y = ca * m.b.y - sa * m.a.y; 158 p->b.z = ca * m.b.z - sa * m.a.z; 159 } 160 161 // (z3dXrot 'model 'angle) 162 void z3dXrot(model *p, double a) { 163 xrot(&p->rot, cos(a), sin(a)); 164 } 165 166 // (z3dYrot 'model 'angle) 167 void z3dYrot(model *p, double a) { 168 yrot(&p->rot, cos(a), sin(a)); 169 } 170 171 // (z3dZrot 'model 'angle) 172 void z3dZrot(model *p, double a) { 173 zrot(&p->rot, cos(a), sin(a)); 174 } 175 176 // (z3dArot 'model 'angle) 177 void z3dArot(model *p, double a) { 178 double n; 179 vector *v; 180 181 v = ((face*)p->lst[0])->pt; 182 n = sqrt(v->x * v->x + v->y * v->y + v->z * v->z); 183 v->x /= n, v->y /= n, v->z /= n; // Axis unit vector 184 if ((n = sqrt(v->y * v->y + v->z * v->z)) < 1.0/SCL) // Axis parallel to x-axis 185 a *= v->x, xrot(&p->rot, cos(a), sin(a)); 186 else { 187 xrot(&p->rot, v->z / n, -v->y / n); 188 yrot(&p->rot, n, v->x); 189 zrot(&p->rot, cos(a), sin(a)); 190 yrot(&p->rot, n, -v->x); 191 xrot(&p->rot, v->z / n, v->y / n); 192 } 193 } 194 195 // (z3dRotate 'model 'X 'Y 'Z 'varX 'varY 'varZ ['flg]) 196 void z3dRotate(model *p, double vx, double vy, double vz, 197 double *xp, double *yp, double *zp, int flg) { 198 if (!flg) { 199 if (xp) 200 *xp = vx * p->rot.a.x + vy * p->rot.b.x + vz * p->rot.c.x; 201 if (yp) 202 *yp = vx * p->rot.a.y + vy * p->rot.b.y + vz * p->rot.c.y; 203 if (zp) 204 *zp = vx * p->rot.a.z + vy * p->rot.b.z + vz * p->rot.c.z; 205 } 206 else { 207 if (xp) 208 *xp = vx * p->rot.a.x + vy * p->rot.a.y + vz * p->rot.a.z; 209 if (yp) 210 *yp = vx * p->rot.b.x + vy * p->rot.b.y + vz * p->rot.b.z; 211 if (zp) 212 *zp = vx * p->rot.c.x + vy * p->rot.c.y + vz * p->rot.c.z; 213 } 214 } 215 216 // (z3dSpot 'varX 'varY 'dx 'dy 'dz) 217 void z3dSpot(double *xp, double *yp, double dx, double dy, double dz) { 218 double d = sqrt(dx*dx + dy*dy + dz*dz); 219 220 *xp = atan2(dy,dx); 221 *yp = d < 1.0/SCL? 0.0 : asin(dz/d); 222 } 223 224 // (z3dWindow 'ttl 'dx 'dy) -> str 225 char *z3dWindow(char *ttl, int dx, int dy) { 226 XPixmapFormatValues *pmFormat; 227 int n, i; 228 229 if ((Disp = XOpenDisplay(NULL)) == NULL) 230 return "Can't open Display"; 231 Scrn = DefaultScreen(Disp); 232 Cmap = DefaultColormap(Disp,Scrn); 233 Dpth = PixSize = 0; 234 pmFormat = XListPixmapFormats(Disp, &n); 235 for (i = 0; i < n; i++) { 236 if (pmFormat[i].depth == 24) { 237 Dpth = 24; 238 if (PixSize != 4) 239 PixSize = (pmFormat[i].bits_per_pixel + 7) / 8 & ~8; 240 } 241 else if (pmFormat[i].depth == 16 && (PixSize < 3 || PixSize > 4)) { 242 Dpth = 16; 243 PixSize = (pmFormat[i].bits_per_pixel + 7) / 8 & ~8; 244 } 245 else if (pmFormat[i].depth == 8 && (PixSize < 2 || PixSize > 4)) { 246 Dpth = 8; 247 PixSize = (pmFormat[i].bits_per_pixel + 7) / 8 & ~8; 248 } 249 } 250 if (!Dpth) 251 return "Bad Display Depth"; 252 Gc = XCreateGC(Disp,RootWindow(Disp,Scrn), 0, NULL); 253 254 OrgX = (SizX = dx) / 2; 255 OrgY = (SizY = dy) / 2; 256 257 /* Create Window */ 258 Win = XCreateSimpleWindow(Disp, RootWindow(Disp,Scrn), 0, 0, SizX, SizY, 259 1, BlackPixel(Disp,Scrn), WhitePixel(Disp,Scrn) ); 260 XStoreName(Disp, Win, ttl); 261 XMapWindow(Disp, Win); 262 263 /* Create Image */ 264 SizX = SizX + 3 & ~3; 265 SizY = SizY + 3 & ~3; 266 if ((Zbuff = malloc(SizX * SizY * sizeof(unsigned))) == NULL || 267 (Edges = malloc(SizY * sizeof(edge))) == NULL ) 268 return "No memory"; 269 if (!XShmQueryExtension(Disp) || 270 !(Img = XShmCreateImage(Disp, DefaultVisual(Disp, Scrn), 271 Dpth, ZPixmap, NULL, &Info, SizX, SizY )) || 272 (Info.shmid = shmget(IPC_PRIVATE, 273 SizX * SizY * PixSize, IPC_CREAT | 0777 )) < 0 || 274 (Info.shmaddr = Img->data = 275 shmat(Info.shmid, 0, 0) ) == (char*)-1 || 276 !XShmAttach(Disp, &Info) ) 277 return "Can't create XImage"; 278 return NULL; 279 } 280 281 // (z3dCamera 'foc 'yaw 'pitch 'x 'y 'z 'sky 'gnd ['h 'v]) 282 void z3dCamera(double foc, double yaw, double pitch, 283 double x, double y, double z, int sky, int gnd) { 284 double a, sinY, cosY, sinP, cosP; 285 int i, v, hor, pix; 286 char *frame; 287 288 FocLen = foc; 289 290 sinY = sin(yaw), cosY = cos(yaw); 291 sinP = sin(pitch), cosP = cos(pitch); 292 Coeff1 = -sinY; 293 Coeff2 = cosY; 294 Coeff4 = cosY * sinP; 295 Coeff5 = sinY * sinP; 296 Coeff6 = -cosP; 297 Coeff7 = cosY * cosP; 298 Coeff8 = sinY * cosP; 299 Coeff9 = sinP; 300 301 PosX = x; 302 PosY = y; 303 PosZ = z; 304 Pos6 = Coeff6 * PosZ; 305 Pos9 = Coeff9 * PosZ; 306 307 if (cosP > - 1.0/SCL && cosP < 1.0/SCL) 308 hor = sinP > 0.0? +16383 : -16384; 309 else if ((a = FocLen * sinP/cosP) > +16383.0) 310 hor = +16383; 311 else if (a < -16384.0) 312 hor = -16384; 313 else 314 hor = (int)a; 315 316 for (v = 0; v < SizY; ++v) { 317 pix = v < hor? sky : gnd; 318 frame = Img->data + v * SizX * PixSize; 319 switch (PixSize) { 320 case 1: 321 memset(frame, pix, SizX); 322 break; 323 case 2: 324 pix |= pix<<16; 325 i = 0; 326 do 327 *(int*)frame = pix, frame += 4; 328 while ((i+=2) < SizX); 329 break; 330 case 3: 331 i = 0; 332 do { 333 frame[0] = pix; 334 frame[1] = (pix >> 8); 335 frame[2] = (pix >> 16); 336 frame += 3; 337 } while (++i < SizX); 338 break; 339 case 4: 340 i = 0; 341 do 342 *(int*)frame = pix, frame += 4; 343 while (++i < SizX); 344 break; 345 } 346 } 347 memset(Zbuff, 0xFF, SizX * SizY * sizeof(unsigned)); 348 } 349 350 static void rotate(vector *src, matrix *p, vector *dst) { 351 dst->x = src->x * p->a.x + src->y * p->b.x + src->z * p->c.x; 352 dst->y = src->x * p->a.y + src->y * p->b.y + src->z * p->c.y; 353 dst->z = src->x * p->a.z + src->y * p->b.z + src->z * p->c.z; 354 } 355 356 static void shadowPt(double vx, double vy, int *xp, int *yp, int *zp) { 357 double z; 358 359 z = Coeff7 * vx + Coeff8 * vy - Pos9; 360 *xp = (int)(FocLen * (Coeff1 * vx + Coeff2 * vy) / z); 361 *yp = (int)(FocLen * (Coeff4 * vx + Coeff5 * vy - Pos6) / z); 362 *zp = (int)(1000.0 * z); 363 } 364 365 static void transPt(double vx, double vy, double vz, int *xp, int *yp, int *zp) { 366 double z; 367 368 z = Coeff7 * vx + Coeff8 * vy + Coeff9 * vz; 369 *xp = (int)(FocLen * (Coeff1 * vx + Coeff2 * vy) / z); 370 *yp = (int)(FocLen * (Coeff4 * vx + Coeff5 * vy + Coeff6 * vz) / z); 371 *zp = (int)(1000.0 * z); 372 } 373 374 static int getColor(int c) { 375 XColor col; 376 377 col.red = c >> 8 & 0xFF00; 378 col.green = c & 0xFF00; 379 col.blue = (c & 0xFF) << 8; 380 col.flags = DoRed | DoGreen | DoBlue; 381 XAllocColor(Disp, Cmap, &col); 382 return col.pixel; 383 } 384 385 static void mkEdge(int x1, int y1, int z1, int x2, int y2, int z2) { 386 int a, dx, dy, dz, sx, xd, xe, sz, zd, ze; 387 edge *p; 388 389 if (y2 < y1) { 390 a = x1, x1 = x2, x2 = a; 391 a = y1, y1 = y2, y2 = a; 392 a = z1, z1 = z2, z2 = a; 393 } 394 if (y1 > OrgY || ((y2 += OrgY) <= 0)) 395 return; 396 if ((dy = y2 - (y1 += OrgY)) == 0) 397 return; 398 dx = x2 - x1, dz = z2 - z1; 399 if (y1 < 0) { 400 x1 += -y1 * dx / dy; 401 z1 += -y1 * dz / dy; 402 y1 = 0; 403 if ((dy = y2) == 0) 404 return; 405 dx = x2 - x1, dz = z2 - z1; 406 } 407 if (y2 > SizY) { 408 x2 += (SizY - y2) * dx / dy; 409 z2 += (SizY - y2) * dz / dy; 410 y2 = SizY; 411 if ((dy = y2 - y1) == 0) 412 return; 413 dx = x2 - x1, dz = z2 - z1; 414 } 415 sx = 0; 416 if (dx > 0) 417 sx = 1; 418 else if (dx < 0) 419 dx = -dx, sx = -1; 420 xd = 0; 421 if (dx > dy) 422 xd = dx/dy, dx -= xd*dy, xd *= sx; 423 xe = (dx *= 2) - dy; 424 sz = 0; 425 if (dz > 0) 426 sz = 1; 427 else if (dz < 0) 428 dz = -dz, sz = -1; 429 zd = 0; 430 if (dz > dy) 431 zd = dz/dy, dz -= zd*dy, zd *= sz; 432 ze = (dz *= 2) - dy; 433 dy *= 2; 434 x1 += OrgX; 435 p = Edges + y1; 436 do { 437 if ((a = x1) < 0) 438 a = 0; 439 else if (a > SizX) 440 a = SizX; 441 if (a < p->h[1]) { 442 p->h[0] = a; 443 p->z[0] = z1; 444 } 445 else { 446 p->h[0] = p->h[1]; 447 p->z[0] = p->z[1]; 448 p->h[1] = a; 449 p->z[1] = z1; 450 } 451 ++p; 452 x1 += xd; 453 if (xe >= 0) 454 x1 += sx, xe -= dy; 455 xe += dx; 456 z1 += zd; 457 if (ze >= 0) 458 z1 += sz, ze -= dy; 459 ze += dz; 460 } while (++y1 < y2); 461 } 462 463 static void zDots(int i, int h, int h2, unsigned z, unsigned z2) { 464 char *frame; 465 unsigned *zbuff; 466 467 i = i * SizX + h; 468 frame = Img->data + i * PixSize; 469 zbuff = Zbuff + i; 470 i = h2 - h; 471 switch (PixSize) { 472 case 1: 473 if (z < *zbuff) 474 *zbuff = z, *frame = 0; 475 if (z2 < *(zbuff += i)) 476 *zbuff = z2, *(frame + i) = 0; 477 break; 478 case 2: 479 if (z < *zbuff) 480 *zbuff = z, *(short*)frame = (short)0; 481 if (z2 < *(zbuff += i)) 482 *zbuff = z2, *(short*)(frame + 2 * i) = (short)0; 483 break; 484 case 3: 485 if (z < *zbuff) { 486 *zbuff = z; 487 frame[0] = 0; 488 frame[1] = 0; 489 frame[2] = 0; 490 } 491 if (z2 < *(zbuff += i)) { 492 *zbuff = z2; 493 frame += 3 * i; 494 frame[0] = 0; 495 frame[1] = 0; 496 frame[2] = 0; 497 } 498 break; 499 case 4: 500 if (z < *zbuff) 501 *zbuff = z, *(int*)frame = 0; 502 if (z2 < *(zbuff += i)) 503 *zbuff = z2, *(int*)(frame + 4 * i) = 0; 504 break; 505 } 506 } 507 508 static void zLine(int pix, int v, int h, int h2, unsigned z, unsigned z2) { 509 char *frame; 510 unsigned *zbuff; 511 int d, e, dh, dz, sz; 512 513 if (dh = h2 - h) { 514 v = v * SizX + h; 515 frame = Img->data + v * PixSize; 516 zbuff = Zbuff + v; 517 sz = 0; 518 if ((dz = z2 - z) > 0) 519 sz = 1; 520 else if (dz < 0) 521 dz = -dz, sz = -1; 522 d = 0; 523 if (dz > dh) 524 d = dz/dh, dz -= d*dh, d *= sz; 525 e = (dz *= 2) - dh; 526 dh *= 2; 527 switch (PixSize) { 528 case 1: 529 do { 530 if (z < *zbuff) 531 *zbuff = z, *frame = pix; 532 z += d; 533 if (e >= 0) 534 z += sz, e -= dh; 535 ++zbuff, ++frame; 536 e += dz; 537 } while (++h < h2); 538 break; 539 case 2: 540 do { 541 if (z < *zbuff) 542 *zbuff = z, *(short*)frame = (short)pix; 543 z += d; 544 if (e >= 0) 545 z += sz, e -= dh; 546 ++zbuff, frame += 2; 547 e += dz; 548 } while (++h < h2); 549 break; 550 case 3: 551 do { 552 if (z < *zbuff) { 553 *zbuff = z; 554 frame[0] = pix; 555 frame[1] = (pix >> 8); 556 frame[2] = (pix >> 16); 557 } 558 z += d; 559 if (e >= 0) 560 z += sz, e -= dh; 561 ++zbuff, frame += 3; 562 e += dz; 563 } while (++h < h2); 564 break; 565 case 4: 566 do { 567 if (z < *zbuff) 568 *zbuff = z, *(int*)frame = pix; 569 z += d; 570 if (e >= 0) 571 z += sz, e -= dh; 572 ++zbuff, frame += 4; 573 e += dz; 574 } while (++h < h2); 575 break; 576 } 577 } 578 } 579 580 static void doDraw(model *p, matrix *r, double x, double y, double z) { 581 int i, n, pix, x0, y0, z0, x1, y1, z1, x2, y2, z2; 582 double dx, dy, dz; 583 vector pos, pt1, pt2, pt3, v, w, nv; 584 matrix rot; 585 void **q; 586 edge *e; 587 588 pos = p->pos; 589 rot = p->rot; 590 if (!r) 591 r = &rot; 592 else { 593 v = pos, rotate(&v, r, &pos); 594 pos.x += x, pos.y += y, pos.z += z; 595 v = rot.a, rotate(&v, r, &rot.a); 596 v = rot.b, rotate(&v, r, &rot.b); 597 v = rot.c, rotate(&v, r, &rot.c); 598 } 599 dx = pos.x - PosX; 600 dy = pos.y - PosY; 601 dz = pos.z - PosZ; 602 /* Rough clipping */ 603 if ((z = Coeff7*dx + Coeff8*dy + Coeff9*dz) < 0.1) 604 return; 605 if (z < fabs(Coeff1*dx + Coeff2*dy)) 606 return; 607 if (z < fabs(Coeff4*dx + Coeff5*dy + Coeff6*dz)) 608 return; 609 /* Faces */ 610 for (q = p->lst; *(face**)q; ++q) { 611 face *f = *(face**)q; 612 613 if ((f->pt[0].x || f->pt[0].y || f->pt[0].z) && (f->pt[1].x || f->pt[1].y || f->pt[1].z)) 614 r = &rot, rotate(f->pt, r, &pt1), rotate(f->pt + 1, r, &pt2); 615 else 616 rotate(f->pt, r, &pt1), rotate(f->pt + 1, r, &pt2), r = &rot; 617 rotate(f->pt + 2, r, &pt3); 618 memset(Edges, 0, SizY * sizeof(edge)); 619 if (f->col2 == 0x2000000) { 620 shadowPt(pt1.x + dx + pt1.z + pos.z, pt1.y + dy, &x0, &y0, &z0); 621 shadowPt(pt2.x + dx + pt2.z + pos.z, pt2.y + dy, &x1, &y1, &z1); 622 mkEdge(x0, y0, z0, x1, y1, z1); 623 for (i = 2;;) { 624 shadowPt(pt3.x + dx + pt3.z + pos.z, pt3.y + dy, &x2, &y2, &z2); 625 mkEdge(x1, y1, z1, x2, y2, z2); 626 if (++i == f->cnt) 627 break; 628 rotate(f->pt + i, r, &pt3); 629 x1 = x2, y1 = y2, z1 = z2; 630 } 631 mkEdge(x2, y2, z2, x0, y0, z0); 632 i = 0, e = Edges; 633 pix = getColor(0); // Face color black 634 do 635 if (e->h[1]) 636 zLine(pix, i, e->h[0], e->h[1], e->z[0], e->z[1]); 637 while (++e, ++i < SizY); 638 } 639 else { 640 v.x = pt1.x - pt2.x; 641 v.y = pt1.y - pt2.y; 642 v.z = pt1.z - pt2.z; 643 w.x = pt3.x - pt2.x; 644 w.y = pt3.y - pt2.y; 645 w.z = pt3.z - pt2.z; 646 nv.x = v.y * w.z - v.z * w.y; 647 nv.y = v.z * w.x - v.x * w.z; 648 nv.z = v.x * w.y - v.y * w.x; 649 pt1.x += dx, pt1.y += dy, pt1.z += dz; 650 if (f->col1 == 0x1000000 && f->col2 == 0x1000000) 651 pix = -1; // Transparent 652 else { 653 if (pt1.x * nv.x + pt1.y * nv.y + pt1.z * nv.z >= 0.0) { 654 if (f->col1 == 0x1000000) 655 continue; // Backface culling 656 pix = f->col1; 657 n = 80 - (int)(14.14 * (nv.z-nv.x) / sqrt(nv.x*nv.x + nv.y*nv.y + nv.z*nv.z)); 658 } 659 else { 660 if (f->col2 == 0x1000000) 661 continue; // Backface culling 662 pix = f->col2; 663 n = 80 + (int)(14.14 * (nv.z-nv.x) / sqrt(nv.x*nv.x + nv.y*nv.y + nv.z*nv.z)); 664 } 665 pix = ((pix >> 16) & 255) * n / 100 << 16 | 666 ((pix >> 8) & 255) * n / 100 << 8 | (pix & 255) * n / 100; 667 } 668 transPt(pt1.x, pt1.y, pt1.z, &x0, &y0, &z0); 669 transPt(pt2.x + dx, pt2.y + dy, pt2.z + dz, &x1, &y1, &z1); 670 mkEdge(x0, y0, z0, x1, y1, z1); 671 for (i = 2;;) { 672 transPt(pt3.x + dx, pt3.y + dy, pt3.z + dz, &x2, &y2, &z2); 673 mkEdge(x1, y1, z1, x2, y2, z2); 674 if (++i == f->cnt) 675 break; 676 rotate(f->pt + i, r, &pt3); 677 x1 = x2, y1 = y2, z1 = z2; 678 } 679 mkEdge(x2, y2, z2, x0, y0, z0); 680 i = 0, e = Edges; 681 if (pix < 0) { 682 do // Transparent 683 if (e->h[1]) 684 zDots(i, e->h[0], e->h[1], e->z[0], e->z[1]); 685 while (++e, ++i < SizY); 686 } 687 else { 688 pix = getColor(pix); // Face color 689 do 690 if (e->h[1]) 691 zLine(pix, i, e->h[0], e->h[1], e->z[0], e->z[1]); 692 while (++e, ++i < SizY); 693 } 694 } 695 } 696 /* Submodels */ 697 while (*(model**)++q) 698 doDraw(*(model**)q, &rot, pos.x, pos.y, pos.z); 699 } 700 701 // (z3dDraw ['model]) 702 void z3dDraw(model *p) { 703 doDraw(p, NULL, 0.0, 0.0, 0.0); 704 } 705 706 // (z3dPut) 707 void z3dPut(void) { 708 XShmPutImage(Disp, Win, Gc, Img, 0, 0, 0, 0, SizX, SizY, False); 709 } 710 711 // (z3dText 'x 'y 'str) 712 void z3dText(int x, int y, char *str) { 713 XDrawString(Disp, Win, Gc, x, y, str, strlen(str)); 714 } 715 716 // (z3dSync) 717 void z3dSync(void) { 718 XSync(Disp,False); 719 } 720 721 /**/ 722 723 # vi:et:ts=3:sw=3