mplisp

miniPicoLisp with FFI and modules for Buddy BDD library, OpenGL, Gtk and GMP
git clone https://logand.com/git/mplisp.git/
Log | Files | Refs

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 }