⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 z3d.c

📁 A very small LISP implementation with several packages and demo programs.
💻 C
字号:
/* 18aug04abu * (c) Software Lab. Alexander Burger */#include "pico.h"#define SCL 1000000.0typedef struct {double x, y, z;} vector;typedef struct {vector a, b, c;} matrix;static bool Snap;static int SnapD, Snap1h, Snap1v, Snap2h, Snap2v;static double FocLen, PosX, PosY, PosZ, Pos6, Pos9, SnapX, SnapY, SnapZ;static double Coeff1, Coeff2, Coeff4, Coeff5, Coeff6, Coeff7, Coeff8, Coeff9;static any getVector(any lst, vector *dst) {   dst->x = numToDouble(car(lst)) / SCL,  lst = cdr(lst);   dst->y = numToDouble(car(lst)) / SCL,  lst = cdr(lst);   dst->z = numToDouble(car(lst)) / SCL;   return cdr(lst);}static any putVector(vector *src, any lst) {   car(lst) = doubleToNum(src->x * SCL),  lst = cdr(lst);   car(lst) = doubleToNum(src->y * SCL),  lst = cdr(lst);   car(lst) = doubleToNum(src->z * SCL);   return cdr(lst);}static any getMatrix(any lst, matrix *dst) {   return getVector(getVector(getVector(lst, &dst->a), &dst->b), &dst->c);}static any putMatrix(matrix *src, any lst) {   return putVector(&src->c, putVector(&src->b, putVector(&src->a, lst)));}static void xrot(matrix *p, double ca, double sa) {   matrix m = *p;   p->b.x = ca * m.b.x - sa * m.c.x;   p->b.y = ca * m.b.y - sa * m.c.y;   p->b.z = ca * m.b.z - sa * m.c.z;   p->c.x = sa * m.b.x + ca * m.c.x;   p->c.y = sa * m.b.y + ca * m.c.y;   p->c.z = sa * m.b.z + ca * m.c.z;}// (z3d:Xrot 'angle 'model) -> Tany Xrot(any ex) {   any x;   double a;   matrix m;   a = evDouble(ex, x = cdr(ex)) / SCL;   x = EVAL(cadr(x));   Touch(ex,x);   x = cdddr(val(x));   getMatrix(x, &m),  xrot(&m, cos(a), sin(a)),  putMatrix(&m, x);   return T;}static void yrot(matrix *p, double ca, double sa) {   matrix m = *p;   p->a.x = ca * m.a.x + sa * m.c.x;   p->a.y = ca * m.a.y + sa * m.c.y;   p->a.z = ca * m.a.z + sa * m.c.z;   p->c.x = ca * m.c.x - sa * m.a.x;   p->c.y = ca * m.c.y - sa * m.a.y;   p->c.z = ca * m.c.z - sa * m.a.z;}// (z3d:Yrot 'angle 'model) -> Tany Yrot(any ex) {   any x;   double a;   matrix m;   a = evDouble(ex, x = cdr(ex)) / SCL;   x = EVAL(cadr(x));   Touch(ex,x);   x = cdddr(val(x));   getMatrix(x, &m),  yrot(&m, cos(a), sin(a)),  putMatrix(&m, x);   return T;}static void zrot(matrix *p, double ca, double sa) {   matrix m = *p;   p->a.x = ca * m.a.x + sa * m.b.x;   p->a.y = ca * m.a.y + sa * m.b.y;   p->a.z = ca * m.a.z + sa * m.b.z;   p->b.x = ca * m.b.x - sa * m.a.x;   p->b.y = ca * m.b.y - sa * m.a.y;   p->b.z = ca * m.b.z - sa * m.a.z;}// (z3d:Zrot 'angle 'model) -> Tany Zrot(any ex) {   any x;   double a;   matrix m;   a = evDouble(ex, x = cdr(ex)) / SCL;   x = EVAL(cadr(x));   Touch(ex,x);   x = cdddr(val(x));   getMatrix(x, &m),  zrot(&m, cos(a), sin(a)),  putMatrix(&m, x);   return T;}// (z3d:Arot 'angle 'model) -> Tany Arot(any ex) {   any x;   double a, n;   matrix m;   vector pt;   a = evDouble(ex, x = cdr(ex)) / SCL;   x = EVAL(cadr(x));   Touch(ex,x);   x = cdddr(val(x));   getVector(cddar(getMatrix(x, &m)), &pt);   n = sqrt(pt.x*pt.x + pt.y*pt.y + pt.z*pt.z);   pt.x /= n,  pt.y /= n,  pt.z /= n;  // Axis unit vector   if ((n = sqrt(pt.y*pt.y + pt.z*pt.z)) == 0.0)  // Axis parallel to x-axis      a *= pt.x,  xrot(&m, cos(a), sin(a));   else {      xrot(&m, pt.z/n, -pt.y/n);      yrot(&m, n, pt.x);      zrot(&m, cos(a), sin(a));      yrot(&m, n, -pt.x);      xrot(&m, pt.z/n, pt.y/n);   }   putMatrix(&m, x);   return T;}// (z3d:Rotate 'X 'Y 'Z 'model 'varX 'varY 'varZ ['flg]) -> Tany Rotate(any ex) {   any x;   double vx, vy, vz;   matrix m;   cell c1, c2, c3;   vx = evDouble(ex, x = cdr(ex)) / SCL;   vy = evDouble(ex, x = cdr(x)) / SCL;   vz = evDouble(ex, x = cdr(x)) / SCL;   x = cdr(x),  getMatrix(cdddr(val(EVAL(car(x)))), &m);   x = cdr(x),  Push(c1, EVAL(car(x)));   NeedVar(ex,data(c1));   x = cdr(x),  Push(c2, EVAL(car(x)));   NeedVar(ex,data(c2));   x = cdr(x),  Push(c3, EVAL(car(x)));   NeedVar(ex,data(c3));   if (isNil(EVAL(cadr(x)))) {      if (!isNil(data(c1)))         val(data(c1)) = doubleToNum((vx * m.a.x + vy * m.b.x + vz * m.c.x) * SCL);      if (!isNil(data(c2)))         val(data(c2)) = doubleToNum((vx * m.a.y + vy * m.b.y + vz * m.c.y) * SCL);      if (!isNil(data(c3)))         val(data(c3)) = doubleToNum((vx * m.a.z + vy * m.b.z + vz * m.c.z) * SCL);   }   else {      if (!isNil(data(c1)))         val(data(c1)) = doubleToNum((vx * m.a.x + vy * m.a.y + vz * m.a.z) * SCL);      if (!isNil(data(c2)))         val(data(c2)) = doubleToNum((vx * m.b.x + vy * m.b.y + vz * m.b.z) * SCL);      if (!isNil(data(c3)))         val(data(c3)) = doubleToNum((vx * m.c.x + vy * m.c.y + vz * m.c.z) * SCL);   }   drop(c1);   return T;}static void _approach(any ex, double d, any dst, any src) {   any l1, l2;   int i;   double n;   Touch(ex,dst);   l1 = val(dst);   Fetch(ex,src);   l2 = val(src);   for (i = 0;  i < 12;  ++i) {      n = numToDouble(car(l1)) / SCL;      car(l1) = doubleToNum((n + d * (numToDouble(car(l2)) / SCL - n)) * SCL);      l1 = cdr(l1),  l2 = cdr(l2);   }   do {      while (!isSym(car(l1)))         if (!isCell(l1 = cdr(l1)))            return;      while (!isSym(car(l2)))         if (!isCell(l2 = cdr(l2)))            return;      _approach(ex, d, car(l1), car(l2));   } while (isCell(l1 = cdr(l1))  &&  isCell(l2 = cdr(l2)));}// (z3d:Approach 'num 'model 'model) -> Tany Approach(any ex) {   any x;   long n;   cell c1, c2;   n = evCnt(ex, x = cdr(ex));   x = cdr(x),  Push(c1, EVAL(car(x)));   x = cdr(x),  Push(c2, EVAL(car(x)));   _approach(ex, 1.0 / (double)n, data(c1), data(c2));   drop(c1);   return T;}// (z3d:Spot 'dx 'dy 'dz ['x 'y 'z]) -> (yaw . pitch)any Spot(any ex) {   any x;   double dx, dy, dz;   cell c1;   dx = evDouble(ex, x = cdr(ex)) / SCL;   dy = evDouble(ex, x = cdr(x)) / SCL;   dz = evDouble(ex, x = cdr(x)) / SCL;   if (isCell(x = cdr(x))) {      dx -= evDouble(ex, x) / SCL;      dy -= evDouble(ex, x = cdr(x)) / SCL;      dz -= evDouble(ex, x = cdr(x)) / SCL;   }   Push(c1, doubleToNum(atan2(dy,dx) * SCL));   dx = sqrt(dx*dx + dy*dy + dz*dz);   data(c1) = cons(data(c1), doubleToNum(dx==0.0? 0.0 : asin(dz/dx)*SCL));   return Pop(c1);}static void rotate(vector *src, matrix *p, vector *dst) {   dst->x = src->x * p->a.x + src->y * p->b.x + src->z * p->c.x;   dst->y = src->x * p->a.y + src->y * p->b.y + src->z * p->c.y;   dst->z = src->x * p->a.z + src->y * p->b.z + src->z * p->c.z;}#if 0/* (lst -- x y z) */void Locate(void) {   any lst;   vector pos, v, w;   matrix rot, r;   lst = Tos;   getMatrix(getVector(car(lst), &pos), &rot);   while (isCell(lst = cdr(lst))) {      getMatrix(getVector(car(lst), &v), &r);      rotate(&v, &rot, &w);      pos.x += w.x,  pos.y += w.y,  pos.z += w.z;      v = r.a,  rotate(&v, &rot, &r.a);      v = r.b,  rotate(&v, &rot, &r.b);      v = r.c,  rotate(&v, &rot, &r.c);      rot = r;   }   Tos = doubleToNum(pos.x) * SCL;   push(doubleToNum(pos.y)) * SCL;   push(doubleToNum(pos.z)) * SCL;}#endifstatic void shadowPt(double vx, double vy) {   double z;   z = Coeff7 * vx + Coeff8 * vy - Pos9;   prn((int)(FocLen * (Coeff1 * vx + Coeff2 * vy) / z));   prn((int)(FocLen * (Coeff4 * vx + Coeff5 * vy - Pos6) / z));   prn(num(1000.0 * z));}static void transPt(double vx, double vy, double vz) {   double x, y, z;   int h, v, dh, dv, d;   x = Coeff1 * vx + Coeff2 * vy;   y = Coeff4 * vx + Coeff5 * vy + Coeff6 * vz;   z = Coeff7 * vx + Coeff8 * vy + Coeff9 * vz;   prn(h = (int)(FocLen * x/z));   prn(v = (int)(FocLen * y/z));   prn(num(1000.0 * z));   if (Snap) {      if ((dh = h - Snap1h) < 0)         dh = -dh;      if ((dv = v - Snap1v) < 0)         dv = -dv;      if ((d = dh>dv? dh+dv*41/100-dh/24 : dv+dh*41/100-dv/24) < SnapD) {         SnapD = d;         Snap2h = h;  Snap2v = v;         SnapX = vx;  SnapY = vy;  SnapZ = vz;      }   }}static void doDraw(any ex, any mdl, matrix *r, double x, double y, double z) {   any face, c1, c2, txt;   long n, pix;   double dx, dy, dz;   vector pos, pt1, pt2, pt3, v, w, nv;   matrix rot;   Fetch(ex,mdl);   mdl = getMatrix(getVector(val(mdl), &pos), &rot);   if (!r)      r = &rot;   else {      v = pos,  rotate(&v, r, &pos);      pos.x += x,  pos.y += y,  pos.z += z;      v = rot.a,  rotate(&v, r, &rot.a);      v = rot.b,  rotate(&v, r, &rot.b);      v = rot.c,  rotate(&v, r, &rot.c);   }   dx = pos.x - PosX;   dy = pos.y - PosY;   dz = pos.z - PosZ;   if ((z = Coeff7*dx + Coeff8*dy + Coeff9*dz) < 0.1)      return;   if (z < fabs(Coeff1*dx + Coeff2*dy))      return;   if (z < fabs(Coeff4*dx + Coeff5*dy + Coeff6*dz))      return;   while (isCell(mdl)) {      face = car(mdl),  mdl = cdr(mdl);      if (isSym(face))         doDraw(ex, face, &rot, pos.x, pos.y, pos.z);      else {         c1 = car(face),  face = cdr(face);         c2 = car(face),  face = cdr(face);         if (!isSym(car(face)))            txt = Nil;         else            txt = car(face),  face = cdr(face);         face = getVector(getVector(face, &v), &w);         if ((v.x || v.y || v.z) && (w.x || w.y || w.z))            r = &rot,  rotate(&v, r, &pt1),  rotate(&w, r, &pt2);         else            rotate(&v, r, &pt1),  rotate(&w, r, &pt2),  r = &rot;         face = getVector(face, &v),  rotate(&v, r, &pt3);         if (c2 == T) {            n = length(face) / 3;            prn(n+2);            shadowPt(pt1.x + dx + pt1.z + pos.z, pt1.y + dy);            pr(txt);            shadowPt(pt2.x + dx + pt2.z + pos.z, pt2.y + dy);            shadowPt(pt3.x + dx + pt3.z + pos.z, pt3.y + dy);            while (--n >= 0) {               face = getVector(face, &v),  rotate(&v, r, &pt1);               shadowPt(pt1.x + dx + pt1.z + pos.z, pt1.y + dy);            }            prn(0);         }         else {            v.x = pt1.x - pt2.x;            v.y = pt1.y - pt2.y;            v.z = pt1.z - pt2.z;            w.x = pt3.x - pt2.x;            w.y = pt3.y - pt2.y;            w.z = pt3.z - pt2.z;            nv.x = v.y * w.z - v.z * w.y;            nv.y = v.z * w.x - v.x * w.z;            nv.z = v.x * w.y - v.y * w.x;            pt1.x += dx,  pt1.y += dy,  pt1.z += dz;            if (isNil(c1) && isNil(c2))               pix = -1;  // Transparent            else {               if (pt1.x * nv.x + pt1.y * nv.y + pt1.z * nv.z >= 0.0) {                  if (isNil(c1))                     continue;  // Backface culling                  pix = unDig(c1) / 2;                  n = 80 - num(14.14 * (nv.z-nv.x) / sqrt(nv.x*nv.x + nv.y*nv.y + nv.z*nv.z));               }               else {                  if (isNil(c2))                     continue;  // Backface culling                  pix = unDig(c2) / 2;                  n = 80 + num(14.14 * (nv.z-nv.x) / sqrt(nv.x*nv.x + nv.y*nv.y + nv.z*nv.z));               }               pix = ((pix >> 16) & 255) * n / 100 << 16  |                     ((pix >> 8) & 255) * n / 100 << 8  |  (pix & 255) * n / 100;            }            n = length(face) / 3;            prn(n+2);            transPt(pt1.x, pt1.y, pt1.z);            pr(txt);            transPt(pt2.x + dx, pt2.y + dy, pt2.z + dz);            transPt(pt3.x + dx, pt3.y + dy, pt3.z + dz);            while (--n >= 0) {               face = getVector(face, &v),  rotate(&v, r, &pt1);               transPt(pt1.x + dx, pt1.y + dy, pt1.z + dz);            }            prn(pix);         }      }   }}// (z3d:Draw 'foc 'yaw 'pitch 'x 'y 'z 'sky 'gnd ['h 'v]) -> NIL// (z3d:Draw 'sym) -> NIL// (z3d:Draw 'NIL) -> lstany Draw(any ex) {   any x, y;   double a, sinY, cosY, sinP, cosP;   x = cdr(ex);   if (isNil(y = EVAL(car(x)))) {      cell c1;      prn(0);      if (!Snap) {         prn(32767);         return Nil;      }      prn(Snap2h),  prn(Snap2v);      Push(c1, doubleToNum(SnapZ * SCL));      data(c1) = cons(doubleToNum(SnapY * SCL), data(c1));      data(c1) = cons(doubleToNum(SnapX * SCL), data(c1));      return Pop(c1);   }   if (isSym(y)) {      doDraw(ex, y, NULL, 0.0, 0.0, 0.0);      return Nil;   }   FocLen = numToDouble(y) / SCL;   a = evDouble(ex, x = cdr(x)) / SCL,  sinY = sin(a),  cosY = cos(a);   a = evDouble(ex, x = cdr(x)) / SCL,  sinP = sin(a),  cosP = cos(a);   PosX = evDouble(ex, x = cdr(x)) / SCL;   PosY = evDouble(ex, x = cdr(x)) / SCL;   PosZ = evDouble(ex, x = cdr(x)) / SCL;   Coeff1 = -sinY;   Coeff2 = cosY;   Coeff4 = cosY * sinP;   Coeff5 = sinY * sinP;   Coeff6 = -cosP;   Coeff7 = cosY * cosP;   Coeff8 = sinY * cosP;   Coeff9 = sinP;   Pos6 = Coeff6 * PosZ;   Pos9 = Coeff9 * PosZ;   if (cosP == 0.0)      prn(sinP > 0.0? +16383 : -16384);   else if ((a = FocLen * sinP/cosP) > +16383.0)      prn(+16383);   else if (a < -16384.0)      prn(-16384);   else      prn(num(a));   prn(evCnt(ex, x = cdr(x)));   prn(evCnt(ex, x = cdr(x)));   x = cdr(x);   if (Snap = !isNil(y = EVAL(car(x)))) {      SnapD = 32767;      Snap1h = (int)xCnt(ex,y);      Snap1v = (int)evCnt(ex,cdr(x));   }   return Nil;}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -