z3dClient.c (13439B)
1 /* 17sep05abu 2 * (c) Software Lab. Alexander Burger 3 */ 4 5 #include <stdio.h> 6 #include <stdlib.h> 7 #include <sys/time.h> 8 #include <unistd.h> 9 #include <string.h> 10 #include <errno.h> 11 12 #include <netdb.h> 13 #include <sys/socket.h> 14 #include <netinet/in.h> 15 #include <arpa/inet.h> 16 17 #include <X11/Xlib.h> 18 #include <X11/Xutil.h> 19 #include <sys/shm.h> 20 #include <X11/extensions/XShm.h> 21 22 23 typedef unsigned char byte; 24 typedef struct {long h[2]; unsigned long z[2];} edge; 25 26 /* Globals */ 27 static int Socket; 28 static Display *Disp; 29 static int Scrn; 30 static int Dpth; 31 static int PixSize; 32 static Colormap Cmap; 33 static GC Gc; 34 static Window Win; 35 static long long Tim; 36 37 /* 3D-Environment */ 38 static int SizX, SizY, OrgX, OrgY, SnapX, SnapY; 39 static unsigned long *Zbuff; 40 static edge *Edges; 41 static XImage *Img; 42 static XShmSegmentInfo Info; 43 44 45 /* Error exit */ 46 static void giveup(char *msg) { 47 fprintf(stderr, "z3dClient: %s\r\n", msg); 48 exit(1); 49 } 50 51 /* Memory allocation */ 52 void *alloc(long siz) { 53 void *p; 54 55 if (!(p = malloc(siz))) 56 giveup("No memory"); 57 return p; 58 } 59 60 static void paint(void) { 61 XEvent ev; 62 63 while (XCheckTypedEvent(Disp, Expose, &ev)); 64 XShmPutImage(Disp, Win, Gc, Img, 0, 0, 0, 0, SizX, SizY, False); 65 if (SnapX != 32767) { 66 XSetFunction(Disp, Gc, GXinvert); 67 XFillRectangle(Disp, Win, Gc, OrgX+SnapX-3, OrgY+SnapY-3, 6, 6); 68 XSetFunction(Disp, Gc, GXcopy); 69 } 70 XSync(Disp,False); 71 } 72 73 static void prLong(long n) { 74 int i; 75 char buf[8]; 76 77 n = n >= 0? n * 2 : -n * 2 + 1; 78 if ((n & 0xFFFFFF00) == 0) 79 i = 2, buf[0] = 1*4, buf[1] = n; 80 else if ((n & 0xFFFF0000) == 0) 81 i = 3, buf[0] = 2*4, buf[1] = n, buf[2] = n>>8; 82 else if ((n & 0xFF000000) == 0) 83 i = 4, buf[0] = 3*4, buf[1] = n, buf[2] = n>>8, buf[3] = n>>16; 84 else 85 i = 5, buf[0] = 4*4, buf[1] = n, buf[2] = n>>8, buf[3] = n>>16, buf[4] = n>>24; 86 if (write(Socket, buf, i) <= 0) 87 giveup("Socket write error"); 88 } 89 90 91 static byte get1(void) { 92 static int n, cnt; 93 static byte buf[1024]; 94 95 while (n == cnt) { 96 int fd; 97 fd_set fdSet; 98 99 fd = ConnectionNumber(Disp); 100 FD_ZERO(&fdSet); 101 FD_SET(fd, &fdSet); 102 FD_SET(Socket, &fdSet); 103 while (select((fd > Socket? fd : Socket) + 1, &fdSet, NULL,NULL,NULL) < 0) 104 if (errno != EINTR) 105 giveup("Select error"); 106 if (FD_ISSET(fd, &fdSet)) { 107 XEvent ev; 108 109 XNextEvent(Disp, &ev); 110 switch (ev.type) { 111 case Expose: 112 paint(); 113 break; 114 case KeyPress: 115 if (((XKeyEvent*)&ev)->state == 37) // Ctrl-Key 116 printf("Ok\n"); //#? 117 break; 118 case KeyRelease: 119 break; 120 case ButtonPress: 121 prLong('c'); // clk 122 prLong(((XButtonEvent*)&ev)->x - OrgX); 123 prLong(((XButtonEvent*)&ev)->y - OrgY); 124 break; 125 case MotionNotify: //#? 126 break; 127 } 128 } 129 if (FD_ISSET(Socket, &fdSet)) { 130 while ((cnt = read(Socket, buf, sizeof(buf))) < 0) 131 if (errno != EINTR) 132 giveup("Socket read error"); 133 if (cnt == 0) 134 exit(0); 135 n = 0; 136 } 137 } 138 return buf[n++]; 139 } 140 141 static long getNum(void) { 142 int cnt = get1() / 4; 143 long n = get1(); 144 int i = 0; 145 146 while (--cnt) 147 n |= get1() << (i += 8); 148 if (n & 1) 149 n = -n; 150 return n / 2; 151 } 152 153 static void skipStr(void) { 154 int cnt = get1() / 4; 155 while (--cnt >= 0) 156 get1(); 157 } 158 159 static long getColor(long c) { 160 XColor col; 161 162 col.red = c >> 8 & 0xFF00; 163 col.green = c & 0xFF00; 164 col.blue = (c & 0xFF) << 8; 165 col.flags = DoRed | DoGreen | DoBlue; 166 if (!XAllocColor(Disp, Cmap, &col)) 167 giveup("Can't allocate color"); 168 return col.pixel; 169 } 170 171 static void mkEdge(int x1, int y1, int z1, int x2, int y2, int z2) { 172 int a, dx, dy, dz, sx, xd, xe, sz, zd, ze; 173 edge *p; 174 175 if (y2 < y1) { 176 a = x1, x1 = x2, x2 = a; 177 a = y1, y1 = y2, y2 = a; 178 a = z1, z1 = z2, z2 = a; 179 } 180 if (y1 > OrgY || ((y2 += OrgY) <= 0)) 181 return; 182 if ((dy = y2 - (y1 += OrgY)) == 0) 183 return; 184 dx = x2 - x1, dz = z2 - z1; 185 if (y1 < 0) { 186 x1 += -y1 * dx / dy; 187 z1 += -y1 * dz / dy; 188 y1 = 0; 189 if ((dy = y2) == 0) 190 return; 191 dx = x2 - x1, dz = z2 - z1; 192 } 193 if (y2 > SizY) { 194 x2 += (SizY - y2) * dx / dy; 195 z2 += (SizY - y2) * dz / dy; 196 y2 = SizY; 197 if ((dy = y2 - y1) == 0) 198 return; 199 dx = x2 - x1, dz = z2 - z1; 200 } 201 sx = 0; 202 if (dx > 0) 203 sx = 1; 204 else if (dx < 0) 205 dx = -dx, sx = -1; 206 xd = 0; 207 if (dx > dy) 208 xd = dx/dy, dx -= xd*dy, xd *= sx; 209 xe = (dx *= 2) - dy; 210 sz = 0; 211 if (dz > 0) 212 sz = 1; 213 else if (dz < 0) 214 dz = -dz, sz = -1; 215 zd = 0; 216 if (dz > dy) 217 zd = dz/dy, dz -= zd*dy, zd *= sz; 218 ze = (dz *= 2) - dy; 219 dy *= 2; 220 x1 += OrgX; 221 p = Edges + y1; 222 do { 223 if ((a = x1) < 0) 224 a = 0; 225 else if (a > SizX) 226 a = SizX; 227 if (a < p->h[1]) { 228 p->h[0] = a; 229 p->z[0] = z1; 230 } 231 else { 232 p->h[0] = p->h[1]; 233 p->z[0] = p->z[1]; 234 p->h[1] = a; 235 p->z[1] = z1; 236 } 237 ++p; 238 x1 += xd; 239 if (xe >= 0) 240 x1 += sx, xe -= dy; 241 xe += dx; 242 z1 += zd; 243 if (ze >= 0) 244 z1 += sz, ze -= dy; 245 ze += dz; 246 } while (++y1 < y2); 247 } 248 249 static void zDots(long i, long h, long h2, unsigned long z, unsigned long z2) { 250 char *frame; 251 unsigned long *zbuff; 252 253 i = i * SizX + h; 254 frame = Img->data + i * PixSize; 255 zbuff = Zbuff + i; 256 i = h2 - h; 257 switch (PixSize) { 258 case 1: 259 if (z < *zbuff) 260 *zbuff = z, *frame = 0; 261 if (z2 < *(zbuff += i)) 262 *zbuff = z2, *(frame + i) = 0; 263 break; 264 case 2: 265 if (z < *zbuff) 266 *zbuff = z, *(short*)frame = (short)0; 267 if (z2 < *(zbuff += i)) 268 *zbuff = z2, *(short*)(frame + 2 * i) = (short)0; 269 break; 270 case 3: 271 if (z < *zbuff) { 272 *zbuff = z; 273 frame[0] = 0; 274 frame[1] = 0; 275 frame[2] = 0; 276 } 277 if (z2 < *(zbuff += i)) { 278 *zbuff = z2; 279 frame += 3 * i; 280 frame[0] = 0; 281 frame[1] = 0; 282 frame[2] = 0; 283 } 284 break; 285 case 4: 286 if (z < *zbuff) 287 *zbuff = z, *(long*)frame = (long)0; 288 if (z2 < *(zbuff += i)) 289 *zbuff = z2, *(long*)(frame + 4 * i) = (long)0; 290 break; 291 } 292 } 293 294 static void zLine(long pix, long v, long h, long h2, 295 unsigned long z, unsigned long z2) { 296 char *frame; 297 unsigned long *zbuff; 298 long d, e, dh, dz, sz; 299 300 if (dh = h2 - h) { 301 v = v * SizX + h; 302 frame = Img->data + v * PixSize; 303 zbuff = Zbuff + v; 304 sz = 0; 305 if ((dz = z2 - z) > 0) 306 sz = 1; 307 else if (dz < 0) 308 dz = -dz, sz = -1; 309 d = 0; 310 if (dz > dh) 311 d = dz/dh, dz -= d*dh, d *= sz; 312 e = (dz *= 2) - dh; 313 dh *= 2; 314 switch (PixSize) { 315 case 1: 316 do { 317 if (z < *zbuff) 318 *zbuff = z, *frame = pix; 319 z += d; 320 if (e >= 0) 321 z += sz, e -= dh; 322 ++zbuff, ++frame; 323 e += dz; 324 } while (++h < h2); 325 break; 326 case 2: 327 do { 328 if (z < *zbuff) 329 *zbuff = z, *(short*)frame = (short)pix; 330 z += d; 331 if (e >= 0) 332 z += sz, e -= dh; 333 ++zbuff, frame += 2; 334 e += dz; 335 } while (++h < h2); 336 break; 337 case 3: 338 do { 339 if (z < *zbuff) { 340 *zbuff = z; 341 frame[0] = pix; 342 frame[1] = (pix >> 8); 343 frame[2] = (pix >> 16); 344 } 345 z += d; 346 if (e >= 0) 347 z += sz, e -= dh; 348 ++zbuff, frame += 3; 349 e += dz; 350 } while (++h < h2); 351 break; 352 case 4: 353 do { 354 if (z < *zbuff) 355 *zbuff = z, *(long*)frame = pix; 356 z += d; 357 if (e >= 0) 358 z += sz, e -= dh; 359 ++zbuff, frame += 4; 360 e += dz; 361 } while (++h < h2); 362 break; 363 } 364 } 365 } 366 367 /*** Main entry point ***/ 368 int main(int ac, char *av[]) { 369 struct sockaddr_in addr; 370 struct hostent *hp; 371 XPixmapFormatValues *pmFormat; 372 long hor, sky, gnd, pix, v; 373 int n, i, x0, y0, z0, x1, y1, z1, x2, y2, z2; 374 char *frame; 375 edge *e; 376 long long t; 377 struct timeval tv; 378 379 if (ac != 3) 380 giveup("Use: <host> <port>"); 381 382 /* Open Connection */ 383 memset(&addr, 0, sizeof(addr)); 384 if ((long)(addr.sin_addr.s_addr = inet_addr(av[1])) == -1) { 385 if (!(hp = gethostbyname(av[1])) || hp->h_length == 0) 386 giveup("Can't get host"); 387 addr.sin_addr.s_addr = ((struct in_addr*)hp->h_addr_list[0])->s_addr; 388 } 389 if ((Socket = socket(AF_INET, SOCK_STREAM, 0)) < 0) 390 giveup("Can't create socket"); 391 addr.sin_family = AF_INET; 392 addr.sin_port = htons(atol(av[2])); 393 if (connect(Socket, (struct sockaddr*)&addr, sizeof(addr)) < 0) 394 giveup("Can't connect"); 395 396 /* Open Display */ 397 if ((Disp = XOpenDisplay(NULL)) == NULL) 398 giveup("Can't open Display"); 399 Scrn = DefaultScreen(Disp); 400 Cmap = DefaultColormap(Disp,Scrn); 401 Dpth = PixSize = 0; 402 pmFormat = XListPixmapFormats(Disp, &n); 403 for (i = 0; i < n; i++) { 404 if (pmFormat[i].depth == 24) { 405 Dpth = 24; 406 if (PixSize != 4) 407 PixSize = (pmFormat[i].bits_per_pixel + 7) / 8 & ~8; 408 } 409 else if (pmFormat[i].depth == 16 && (PixSize < 3 || PixSize > 4)) { 410 Dpth = 16; 411 PixSize = (pmFormat[i].bits_per_pixel + 7) / 8 & ~8; 412 } 413 else if (pmFormat[i].depth == 8 && (PixSize < 2 || PixSize > 4)) { 414 Dpth = 8; 415 PixSize = (pmFormat[i].bits_per_pixel + 7) / 8 & ~8; 416 } 417 } 418 if (!Dpth) 419 giveup("Bad Display Depth"); 420 Gc = XCreateGC(Disp,RootWindow(Disp,Scrn), 0, NULL); 421 422 OrgX = (SizX = getNum()) / 2; 423 OrgY = (SizY = getNum()) / 2; 424 425 /* Create Window */ 426 Win = XCreateSimpleWindow(Disp, RootWindow(Disp,Scrn), 0, 0, SizX, SizY, 427 1, BlackPixel(Disp,Scrn), WhitePixel(Disp,Scrn) ); 428 XStoreName(Disp, Win, "Pico Lisp z3d"); 429 XSelectInput(Disp, Win, 430 ExposureMask | 431 KeyPressMask | KeyReleaseMask | 432 ButtonPressMask | 433 PointerMotionMask ); 434 XMapWindow(Disp, Win); 435 436 /* Create Image */ 437 SizX = SizX + 3 & ~3; 438 SizY = SizY + 3 & ~3; 439 Zbuff = alloc(SizX * SizY * sizeof(unsigned long)); 440 Edges = alloc(SizY * sizeof(edge)); 441 if (!XShmQueryExtension(Disp) || 442 !(Img = XShmCreateImage(Disp, DefaultVisual(Disp, Scrn), 443 Dpth, ZPixmap, NULL, &Info, SizX, SizY )) || 444 (Info.shmid = shmget(IPC_PRIVATE, 445 SizX * SizY * PixSize, IPC_CREAT | 0777 )) < 0 || 446 (Info.shmaddr = Img->data = 447 shmat(Info.shmid, 0, 0) ) == (char*)-1 || 448 !XShmAttach(Disp, &Info) ) 449 giveup("Can't create XImage"); 450 451 /* Main loop */ 452 for (;;) { 453 prLong('o'); // ok 454 hor = getNum() + OrgY; 455 sky = getColor(getNum()); 456 gnd = getColor(getNum()); 457 for (v = 0; v < SizY; ++v) { 458 pix = v < hor? sky : gnd; 459 frame = Img->data + v * SizX * PixSize; 460 switch (PixSize) { 461 case 1: 462 memset(frame, pix, SizX); 463 break; 464 case 2: 465 pix |= pix<<16; 466 i = 0; 467 do 468 *(long*)frame = pix, frame += 4; 469 while ((i+=2) < SizX); 470 break; 471 case 3: 472 i = 0; 473 do { 474 frame[0] = pix; 475 frame[1] = (pix >> 8); 476 frame[2] = (pix >> 16); 477 frame += 3; 478 } while (++i < SizX); 479 break; 480 case 4: 481 i = 0; 482 do 483 *(long*)frame = pix, frame += 4; 484 while (++i < SizX); 485 break; 486 } 487 } 488 memset(Zbuff, 0xFF, SizX * SizY * sizeof(unsigned long)); 489 490 while (n = getNum()) { 491 memset(Edges, 0, SizY * sizeof(edge)); 492 x0 = x1 = getNum(); 493 y0 = y1 = getNum(); 494 z0 = z1 = getNum(); 495 skipStr(); 496 for (;;) { 497 x2 = getNum(); 498 y2 = getNum(); 499 z2 = getNum(); 500 mkEdge(x1, y1, z1, x2, y2, z2); 501 if (--n == 0) 502 break; 503 x1 = x2, y1 = y2, z1 = z2; 504 } 505 mkEdge(x2, y2, z2, x0, y0, z0); 506 i = 0, e = Edges; 507 if ((pix = getNum()) < 0) { 508 do // Transparent 509 if (e->h[1]) 510 zDots(i, e->h[0], e->h[1], e->z[0], e->z[1]); 511 while (++e, ++i < SizY); 512 } 513 else { 514 pix = getColor(pix); // Face color 515 do 516 if (e->h[1]) 517 zLine(pix, i, e->h[0], e->h[1], e->z[0], e->z[1]); 518 while (++e, ++i < SizY); 519 } 520 } 521 if ((SnapX = getNum()) != 32767) 522 SnapY = getNum(); 523 paint(); 524 gettimeofday(&tv,NULL), t = tv.tv_sec * 1000LL + tv.tv_usec / 1000; 525 if (Tim > t) { 526 tv.tv_sec = 0, tv.tv_usec = (Tim - t) * 1000; 527 select(0, NULL, NULL, NULL, &tv); 528 t = Tim; 529 } 530 Tim = t + 40; 531 } 532 }