#include #include #include #include #include #include #include #include #include #include using namespace std; static int COLS,LINES; static int EC,EL,EC2,EL3,wx,wy; static char *Field, *Color, *efi; static void Init(void) { EC=COLS&~1, EL=LINES, EC2=EC*2, EL3=EL*3; Field = (char *)calloc(EC, EL3); Color = (char *)calloc(EC, EL); if(!efi) efi = (char *)calloc(EC, EL); } static void UpDown(char *s, int oldy,int newy) { /***/if(newy == oldy-1)sprintf(s, "\33[A"); else if(newy == oldy+1)sprintf(s, "\33[B"); else if(newy < oldy)sprintf(s, "\33[%dA", oldy-newy); else if(newy > oldy)sprintf(s, "\33[%dB", newy-oldy); else *s=0; } static void LeftRight(char *s, int oldx,int newx) { /***/if(newx == oldx+1)sprintf(s, "\33[C"); else if(newx == oldx-1)sprintf(s, "\33[D"); else if(newx < oldx)sprintf(s, "\33[%dD", oldx-newx); else if(newx > oldx)sprintf(s, "\33[%dC", newx-oldx); else *s=0; } /* This is not thread safe!! */ static char *LocationDiff(int oldx,int oldy, int newx,int newy) { static char Buff[24]; char *s = Buff; Buff[0]=0; if(newx==oldx && newy==oldy)return Buff; if(!newx) { if(oldx)strcpy(Buff, "\r"); s++; if(newy==oldy+4) return strcat(Buff, "\n\n\n\n"); if(newy==oldy+3) return strcat(Buff, "\n\n\n"); if(newy==oldy+2) return strcat(Buff, "\n\n"); if(newy==oldy+1) return strcat(Buff, "\n"); UpDown(s, oldy,newy); return Buff; } if(newx==oldx-1) { *s++ = '\b'; UpDown(s, oldy,newy); return Buff; } if(newy == oldy) { LeftRight(s, oldx,newx); return Buff; } sprintf(Buff, "\33[%d;%dH", newy+1, newx+1); return Buff; } static int TextAttr = 7; static int OldAttr; static const int AnsiOpt=1; static const int Colors=1; static void SetAttr(int newattr) { TextAttr = newattr; } static void FlushSetAttr(void) { if(TextAttr == OldAttr)return; if(!Colors)goto Ret; #ifdef DJGPP textattr(TextAttr); #else printf("\33["); if(TextAttr != 7) { static char Swap[] = "04261537"; if(AnsiOpt) { int pp=0; if((OldAttr&0x80) > (TextAttr&0x80) || (OldAttr&0x08) > (TextAttr&0x08)) { putchar('0'); pp=1; OldAttr = 7; } if((TextAttr&0x08) && !(OldAttr&0x08)){if(pp)putchar(';');putchar('1');pp=1;} if((TextAttr&0x80) && !(OldAttr&0x80)){if(pp)putchar(';');putchar('5');pp=1;} if((TextAttr&0x70) != (OldAttr&0x70)) { if(pp)putchar(';'); putchar('4'); putchar(Swap[(TextAttr>>4)&7]); pp=1; } if((TextAttr&7) != (OldAttr&7)) { if(pp)putchar(';'); putchar('3'); putchar(Swap[TextAttr&7]); } } else printf("0%s%s;4%c;3%c", (TextAttr&8)?";1":"", (TextAttr&0x80)?";5":"", Swap[(TextAttr>>4)&7], Swap[TextAttr&7]); } putchar('m'); #endif Ret:OldAttr = TextAttr; } class Banner { private: const char *ban; int banlen; int linelen; int pos; public: Banner(void) : ban( "___ . _ _ _ _ _ _ _ . _ _ _ _ _ . _ ___ _ _ _ _ _ _ _ . _ _ .___ _____ _ . . _ . _ _ .___ " " | |_||(_` |_)|_)/ !/ _|_)|_||!/| |(_` / / !|_)!_/|_)|/ _|_| | (C) |(_)(_) _) |(_)(_)(_) |_)|(_`/ !| || | / |_| | | |_). // ||/| / |_)|(_`/ !| || | / !" " | | ||._) | | !!_/!_/| !| || | |._) !_!_/| | | !|!_/| | | | _) _)(_ / | _) _) _) |_)|._)!_X|/!|| | ! | | | | | . // ||!| / |_)|._)!_X|/!|| | / /") { banlen = strlen(ban); linelen = banlen/3; pos = -linelen; } void Update(char *&e) { SetAttr(0x03); for(int y=0; y<3; y++) { int nx, x; for(nx=pos, x=0; x=0 && nx= linelen) pos = -EC; } } Banner; static void Done(void) { if(EC==COLS && EL==LINES) { /* ab */ /* cd d */ /* ef c d ddc */ /* b ccb ddb dccb */ /* aba caba daba caba */ char Buf[] = " ~~\"""-'^*" "-^'*""-\\/\"" /* */ ".;;P" ",|/P" ",>/?" "r}/P" /* e */ ".::M"",\\?@[\]^_{|}~ */ int x,y; const char *s = Field; const char *c = Color; char *e = efi; Banner.Update(e); for(y=3; y=EC2||y>=EL3-9)return 0; Field[EC * y + (x>>1)] |= 1 << (x&1); return 1; } inline void PSet(float x,float y, int c) { register int X = int(x*(EC2)); register int Y = int(y*(EL3)); if(SetP(X, Y)) Color[EC * (Y/3) + (X>>1)] = c; } static void Line(float X1,float Y1, float X2,float Y2) { int x1,y1, x2,y2; x1=int(X1*(EC2)); x2=int(X2*(EC2)); y1=int(Y1*(EL3)); y2=int(Y2*(EL3)); int i, DeltaX, DeltaY, NumPixels, d, dinc1, dinc2, x, xinc1, xinc2, y, yinc1, yinc2; /* Calculate DeltaX and DeltaY for init */ DeltaX = abs(x2 - x1); DeltaY = abs(y2 - y1); /* Initialize all vars based on which is the independent variable k1 */ if(DeltaX >= DeltaY) { /* x is independent variable */ NumPixels = DeltaX + 1; d = (DeltaY << 1) - DeltaX; dinc1 = DeltaY << 1; dinc2 = (DeltaY - DeltaX) << 1; yinc1 = 0, xinc1 = xinc2 = yinc2 = 1; } else { /* y is independent variable */ NumPixels = DeltaY + 1; d = (DeltaX << 1) - DeltaY; dinc1 = DeltaX << 1; dinc2 = (DeltaX - DeltaY) << 1; xinc1 = 0, yinc1 = yinc2 = xinc2 = 1; } /* Make sure x and y move in the right directions */ if(x1 > x2) {xinc1 = -xinc1; xinc2 = -xinc2;} if(y1 > y2) {yinc1 = -yinc1; yinc2 = -yinc2;} /* Start drawing at */ x = x1; y = y1; /* Draw the pixels */ for(i=1; i>1)] = 0; if(d<0) d += dinc1, x += xinc1, y += yinc1; else d += dinc2, x += xinc2, y += yinc2; } } static void GetSize(void) { struct winsize ws; if(ioctl(1, TIOCGWINSZ, &ws) >= 0) { LINES = ws.ws_row; COLS = ws.ws_col; } if(!LINES || !COLS)LINES=24, COLS=80; if(efi) { free(efi); efi = NULL; } wx=wy=0; printf("\33[H"); } static void Refresh(int d) { d=d; GetSize(); printf("\33[J\33[?25l"); wx=wy=0; OldAttr=-1; } class Matrix { private: typedef float matx[4][4]; matx dah; public: Matrix(float ax,float ay,float az) { matx m[3]; register int i, j; memset(&m, 0, sizeof(m)); m[0][1][1]=m[0][2][2]=cos(ax); m[0][2][1]=-(m[0][1][2]=sin(ax)); m[1][0][0]=m[1][2][2]=cos(ay); m[1][0][2]=-(m[1][2][0]=sin(ay)); m[2][0][0]=m[2][1][1]=cos(az); m[2][1][0]=-(m[2][0][1]=sin(az)); m[0][0][0] = m[0][3][3] = 1; m[1][1][1] = m[1][3][3] = 1; m[2][2][2] = m[2][3][3] = 1; for(i=0; i<4; i++) { float m2[4]; for(j=0; j<4; j++) m2[j] = m[1][i][0] * m[0][0][j] + m[1][i][1] * m[0][1][j] + m[1][i][2] * m[0][2][j] + m[1][i][3] * m[0][3][j]; for(j=0; j<4; j++) dah[i][j] = m2[0] * m[2][0][j] + m2[1] * m[2][1][j] + m2[2] * m[2][2][j] + m2[3] * m[2][3][j]; } } void RotatePoint(float &x,float &y,float &z) { register float tx = x*dah[0][0] + y*dah[1][0] + z*dah[2][0] + dah[3][0]; register float ty = x*dah[0][1] + y*dah[1][1] + z*dah[2][1] + dah[3][1]; z = x*dah[0][2] + y*dah[1][2] + z*dah[2][2] + dah[3][2]; y = ty; x = tx; } }; class line { float x1,y1,z1, x2,y2,z2; int isline, color; public: line(float X1,float Y1,float Z1, float X2,float Y2,float Z2) : isline(1) { x1 = (X1/31 - 0.5) * 20; y1 = (Y1/11 - 0.5) * 20; z1 = Z1; x2 = (X2/31 - 0.5) * 20; y2 = (Y2/11 - 0.5) * 20; z2 = Z2; } line(float x,float y,float z, int c) : x1(x),y1(y),z1(z),isline(0),color(c) { } void Draw(float cx,float cy,float cz, Matrix &m) { if(isline) { float X1=x1, Y1=y1, Z1=z1; float X2=x2, Y2=y2, Z2=z2; m.RotatePoint(X1,Y1,Z1); m.RotatePoint(X2,Y2,Z2); X1-=cx; Y1-=cy; Z1-=cz; X2-=cx; Y2-=cy; Z2-=cz; if(Z1 > 0 && Z2 > 0) Line(0.5+X1/Z1, 0.5+Y1/Z1, 0.5+X2/Z2, 0.5+Y2/Z2); } else { float x = x1, y = y1, z = z1; m.RotatePoint(x,y,z); x-=cx, y-=cy, z-=cz; if(z > 0) PSet(0.5+x/z, 0.5+y/z, color); } } }; class World { private: vector lines; public: typedef vector::iterator iterator; void Insert(line *Line) { lines.insert(lines.end(), Line); } void AddPoly(int x,int y, ...) { va_list ap; va_start(ap, y); float x1=x/10.0, y1=y/10.0; for(;;) { int X = va_arg(ap, int); int Y = va_arg(ap, int); float x2 = X / 10.0; float y2 = Y / 10.0; Insert(new line(x1,y1,0, x2,y2,0)); Insert(new line(x1,y1,1, x2,y2,1)); Insert(new line(x1,y1,0, x1,y1,1)); Insert(new line(x2,y2,0, x2,y2,1)); if(X==x && Y==y)break; x1=x2, y1=y2; } va_end(ap); } iterator begin(void) { return lines.begin(); } iterator end(void) { return lines.end(); } } World; static int Quitti=0; static void Term(int dummy) { dummy=dummy; Quitti++; } int main(void) { for(int i=0; i<1000; i++) { float x,y,z; do { x = 1000.0*rand()/(double)RAND_MAX - 500.0; y = 1000.0*rand()/(double)RAND_MAX - 500.0; z = 1000.0*rand()/(double)RAND_MAX - 500.0; } while(sqrt(x*x+y*y+z*z) < 300.0); World.Insert(new line(x,y,z, i%10 ? 1 : 2)); } World.AddPoly( 0, 0, 30, 0, 40,10, 40,30, 30,40, 40,50, 40,70, 30,80, 0,80, 0,00); World.AddPoly(10,10, 30,10, 30,30, 10,30, 10,10); World.AddPoly(10,50, 30,50, 30,70, 10,70, 10,50); World.AddPoly(60,20, 70,20, 65,10, 60,20); World.AddPoly(50,40, 70,30, 70,70, 80,70, 80,80, 50,80, 50,70, 60,70, 60,40, 50,40); World.AddPoly(100,30, 120,30, 130,40, 120,50, 120,40, 100,40, 100,50, 130,60, 130,70, 120,80, 100,80, 90,70, 100,60, 100,70, 120,70, 120,60, 90,50, 90,40, 100,30); World.AddPoly(150,30, 180,30, 180,110,140,70, 140,40, 150,30); World.AddPoly(150,40, 170,40, 170,70, 150,70, 150,40); World.AddPoly(190,30, 200,50, 220,50, 230,30, 230,80, 210,60, 190,80, 190,30); World.AddPoly(240,40, 260,30, 260,70, 270,70, 270,80, 240,80, 240,70, 250,70, 250,40, 240,40); World.AddPoly(250,20, 260,20, 255,10, 250,20); World.AddPoly(290,20, 300,20, 300,30, 310,30, 310,40, 300,40, 310,80, 290,80, 290,40, 280,40, 280,30, 290,30, 290,20); GetSize(); signal(SIGWINCH, Refresh); signal(SIGINT, Term); signal(SIGTERM, Term); float ax,ay,az; float cx,cy,cz; ax=-0.005*60; ay=-0.008*60; az=-0.009*60; cx=cy=0.0; cz=-20; while(!Quitti) { Init(); World::iterator i; Matrix m(ax,ay,az); for(i=World.begin(); iDraw(cx,cy,cz, m); ax += 0.005; ay += 0.008; az += 0.009; Done(); usleep(20000); } Init(); SetAttr(7); Done(); SetAttr(7); FlushSetAttr(); printf("\33[?25h\n\n\n"); return 0; }