From 45d55fd925d307e3ad249e77acbf658db24239aa Mon Sep 17 00:00:00 2001 From: Ian C Date: Tue, 8 Jun 2004 23:12:51 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r2, which included commits to RCS files with non-trunk default branches. --- xd.c | 3425 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 3425 insertions(+) create mode 100644 xd.c (limited to 'xd.c') diff --git a/xd.c b/xd.c new file mode 100644 index 0000000..cc2502f --- /dev/null +++ b/xd.c @@ -0,0 +1,3425 @@ +/* + + xd - X11 demo framefork + + Copyright (C) 2002 Ian Cowburn (ianc@noddybox.demon.co.uk) + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + + ------------------------------------------------------------------------- + +*/ +static const char id[]="$Id$"; + +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include + +/* ---------------------------------------- HANDY MACROS +*/ +#ifndef TRUE +#define TRUE True +#endif + +#ifndef FALSE +#define FALSE False +#endif + +#ifndef M_PI +# define M_PI 3.14159265358979323846 +#endif + +#define RAD(x) ((x)*M_PI/180.0) + +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define MAX(a,b) ((a)>(b)?(a):(b)) + +#define LIMIT(v,m,l) MIN((m),MAX((v),(l))) + +#define RND(x) (rand()%(x)) +#define RND2(h,l) ((rand()%((h)-(l)))+(l)) + +/* ---------------------------------------- TYPES +*/ +typedef enum {UsesImage, UsesPixmap} DType; + +typedef enum {MousePress, MouseRelease, MouseMove} Mouse; + +typedef struct + { + const char *name; + void (*draw)(void); + DType type; + } DemoInfo; + +typedef struct + { + double x,y,z; + } Point3D; + +#define MAX_POLY_POINTS 32 + +typedef struct + { + int p[MAX_POLY_POINTS]; + int no; + int col; + } Poly3D; + +typedef struct + { + int no_points; + int no_poly; + + Point3D origin; + + Point3D *ps; + Poly3D *poly; + + Point3D *workp3; + XPoint *workxp; + + int x_rot; + int y_rot; + int z_rot; + + int mode; + + int col; + + int cull; + } Obj3D; + +#define MODE_SOLID 0 +#define MODE_WIRE 1 +#define MODE_EDGE 2 + +typedef struct + { + Point3D origin; + int radius; + int mode; + unsigned long col; + } Sphere3D; + +typedef struct + { + Point3D origin; + int w,h; + int mode; + unsigned long col; + } Rect3D; + +typedef struct + { + Point3D origin; + unsigned long col; + } Particle3D; + +typedef enum {eObj, eSphere, eRect, eParticle} ObjType; + +typedef struct + { + ObjType type; + void *p; + } WorldObj; + +/* ---------------------------------------- DEMO PROTOS +*/ +static void AutoDropDemo(void); +static void DropDemo(void); +static void FastDropDemo(void); +static void TrailDemo(void); +static void TunnelDemo(void); +static void StarDemo(void); +static void StarSphereDemo(void); +static void Test3DDemo(void); +static void ColScapeDemo(void); +static void FluidDemo(void); +static void ParticleDropDemo(void); +static void PolyDropDemo(void); +static void CraterDemo(void); +static void TriangleDemo(void); +static void TriangleDemo2(void); + +/* ---------------------------------------- GLOBAL VARS +*/ +#define NO_DEMOS 15 + +static int demo=NO_DEMOS-1; + +static int cycle=FALSE; + +static DemoInfo demotbl[NO_DEMOS]= + { + { + "Z-Buffered Pyramids", + TrailDemo, + UsesPixmap + }, + { + "Auto Drops", + AutoDropDemo, + UsesPixmap + }, + { + "Drops (LMB to drop, RMB to toggle clear)", + DropDemo, + UsesPixmap + }, + { + "Fast Drops (LMB to drop, RMB to toggle clear)", + FastDropDemo, + UsesPixmap + }, + { + "Tunnel (RMB to toggle clear)", + TunnelDemo, + UsesPixmap + }, + { + "Starfield (RMB to toggle warp)", + StarDemo, + UsesPixmap + }, + { + "Star Sphere", + StarSphereDemo, + UsesPixmap + }, + { + "Test3DDemo", + Test3DDemo, + UsesPixmap + }, + { + "Column Landscape", + ColScapeDemo, + UsesPixmap + }, + { + "Fluid Particles", + FluidDemo, + UsesPixmap + }, + { + "Fluid Drops", + ParticleDropDemo, + UsesPixmap + }, + { + "Polygon Water", + PolyDropDemo, + UsesPixmap + }, + { + "Crater Landscape", + CraterDemo, + UsesPixmap + }, + { + "Triangle Trench", + TriangleDemo, + UsesPixmap + }, + { + "Triangle Wavy Trench", + TriangleDemo2, + UsesPixmap + }, + }; + +/* ---------------------------------------- X11 VARS +*/ +static int use_root=FALSE; +static Window win=None; +static Pixmap pix=None; +static Pixmap saved=None; +static GC gc=None; +static Display *disp=NULL; +static XVisualInfo visual; +static XFontStruct *font=NULL; +static int width; +static int height; +static int centre_x; +static int centre_y; + +static unsigned long black; +static unsigned long white; +static unsigned long red; +static unsigned long green; +static unsigned long blue; + +static int mouse_x; +static int mouse_y; +static int mouse_b; + +static double sintab[3600]; +static double costab[3600]; + +#define FONTW (font->max_bounds.rbearing - \ + font->min_bounds.lbearing) +#define FONTH (font->max_bounds.descent + \ + font->max_bounds.ascent + 1) + +/* ---------------------------------------- PROTOS +*/ +static void OpenX(void); + +static unsigned long GetCol(unsigned long, unsigned long, unsigned long); +static void SetCol(unsigned long col); + +static void Cls(void); +static void ClsCol(unsigned long col); +static void Redraw(void); + +static void UpdateDisplay(void); + +static void Line(int x1,int y1,int x2,int y2,int col); +static void LineP(XPoint *p1,XPoint *p2,int col); +static void Plot(int x,int y,int col); +static void Circle(int x,int y,int r,int col); +static void FCircle(int x,int y,int r,int col); +static void Print(int x,int y,int col,char *fmt,...); +static void Rect(int x,int y,int w,int h,int col); +static void FRect(int x,int y,int w,int h,int col); +static void Polygon(XPoint pts[], int no, int col); +static void FPolygon(XPoint pts[], int no, int col); + +static int AngToCol(int ang, int no_col); + +static double Distance(Point3D *a, Point3D *b); + +static int Project(double x,double y,double z,XPoint *xp); +static void RotateX(double cx, double cy, double cz, + double ix, double iy, double iz, + double *x, double *y, double *z, + int a); +static void RotateY(double cx, double cy, double cz, + double ix, double iy, double iz, + double *x, double *y, double *z, + int a); +static void RotateZ(double cx, double cy, double cz, + double ix, double iy, double iz, + double *x, double *y, double *z, + int a); + +static void DrawObj(Obj3D *o, unsigned long cmap[]); + +static void DrawList(WorldObj *w, int no, unsigned long cmap[], + int inv_z_order, int do_sort); +static void DrawSubList(Obj3D *o, int obj_no, + Sphere3D *s, int sphere_no, + Rect3D *r, int rect_no, + Particle3D *p, int particle_no, + unsigned long cmap[], + int inv_z_order, int do_sort); + +static void HandleKey(XKeyEvent *key); +static void HandleMouse(int x, int y, int b, Mouse mode); + +/* ---------------------------------------- MAIN +*/ +int main(int argc, char *argv[]) +{ + XEvent ev; + int f; + + for(f=1;f=width) + { + *ix=-(*ix); + *x+=*ix; + } + + if (*y<0 || *y>=height) + { + *iy=-(*iy); + *y+=*iy; + } +} + + +/* ---------------------------------------- X11 UTILS +*/ +static void OpenX(void) +{ + XGCValues gc_val; + XSizeHints hint; + int f; + + /* Open display and find an appropriate visual + */ + if (!(disp=XOpenDisplay(NULL))) + Error("Couldn't open X display"); + + if (!XMatchVisualInfo(disp,DefaultScreen(disp),32,TrueColor,&visual) && + !XMatchVisualInfo(disp,DefaultScreen(disp),24,TrueColor,&visual) && + !XMatchVisualInfo(disp,DefaultScreen(disp),16,TrueColor,&visual) && + !XMatchVisualInfo(disp,DefaultScreen(disp),15,TrueColor,&visual)) + Error("Couldn't find a visual\n"); + + font=XLoadQueryFont(disp,"fixed"); + + if (!font) + Error("Couldn't load font fixed"); + + width=640; + height=480; + + if (!use_root) + win=XCreateWindow(disp,DefaultRootWindow(disp), + 0,0,width,height,0, + visual.depth, + InputOutput, + visual.visual, + 0,NULL); + else + { + win=DefaultRootWindow(disp); + width=DisplayWidth(disp,DefaultScreen(disp)); + height=DisplayHeight(disp,DefaultScreen(disp)); + } + + centre_x=width/2; + centre_y=height/2; + + /* + XSelectInput + (disp,win, + KeyPressMask|ButtonPressMask|ButtonReleaseMask| + PointerMotionMask|ExposureMask); + */ + XSelectInput(disp,win,KeyPressMask); + + XStoreName(disp,win,demotbl[demo].name); + + hint.width=hint.min_width=hint.max_width=width; + hint.height=hint.min_height=hint.max_height=height; + hint.flags=PSize|PMinSize|PMaxSize; + + XSetWMNormalHints(disp,win,&hint); + + pix=XCreatePixmap(disp,win,width,height,visual.depth); + saved=XCreatePixmap(disp,win,width,height,visual.depth); + + gc_val.function=GXcopy; + gc_val.plane_mask=AllPlanes; + gc_val.line_width=0; + gc_val.line_style=LineSolid; + gc_val.graphics_exposures=False; + gc_val.foreground=WhitePixel(disp,DefaultScreen(disp)); + gc_val.background=BlackPixel(disp,DefaultScreen(disp)); + + gc=XCreateGC(disp,pix, + GCFunction|GCPlaneMask|GCLineWidth|GCForeground|GCBackground| + GCLineStyle|GCGraphicsExposures, + &gc_val); + + if (use_root) + { + /* + XSetCloseDownMode(disp,RetainTemporary); + XSetWindowBackgroundPixmap(disp,win,pix); + */ + } + + + /* TODO: XImage creation */ + + Cls(); + Redraw(); +} + + +static void Cls() +{ + SetCol(black); + XFillRectangle(disp,pix,gc,0,0,width,height); +} + + +static void ClsCol(unsigned long col) +{ + SetCol(col); + XFillRectangle(disp,pix,gc,0,0,width,height); +} + + +static void Redraw(void) +{ + if (demotbl[demo].type==UsesPixmap) + XCopyArea(disp,pix,win,gc,0,0,width,height,0,0); + else + { + /* TODO: XImage copy */ + } + /* XFlush(disp); */ + XSync(disp,FALSE); +} + + +static void Line(int x1,int y1,int x2,int y2,int col) +{ + SetCol(col); + XDrawLine(disp,pix,gc,x1,y1,x2,y2); +} + + +static void LineP(XPoint *p1, XPoint *p2, int col) +{ + SetCol(col); + XDrawLine(disp,pix,gc,p1->x,p1->y,p2->x,p2->y); +} + + +static void Plot(int x,int y,int col) +{ + SetCol(col); + XDrawPoint(disp,pix,gc,x,y); +} + + +static void Circle(int x,int y,int r,int col) +{ + if (r<1) + { + Plot(x,y,col); + return; + } + + SetCol(col); + XDrawArc(disp,pix,gc,x-r,y-r,r*2,r*2,0,64*360); +} + + +static void FCircle(int x,int y,int r,int col) +{ + if (r<1) + { + Plot(x,y,col); + return; + } + + SetCol(col); + XFillArc(disp,pix,gc,x-r,y-r,r*2,r*2,0,64*360); +} + + +static void Print(int x,int y,int col,char *fmt,...) +{ + char s[1024]; + va_list va; + size_t len; + + va_start(va,fmt); + vsprintf(s,fmt,va); + va_end(va); + + len=strlen(s); + + y+=FONTH-1; + + SetCol(col); + XDrawString(disp,pix,gc,x,y,s,len); +} + + +static void Rect(int x,int y,int w,int h,int col) +{ + if (w==0 && h==0) + { + Plot(x,y,col); + return; + } + + SetCol(col); + XDrawRectangle(disp,pix,gc,x,y,w,h); +} + + +static void FRect(int x,int y,int w,int h,int col) +{ + if (w==0 && h==0) + { + Plot(x,y,col); + return; + } + + SetCol(col); + XFillRectangle(disp,pix,gc,x,y,w,h); +} + + +static void Polygon(XPoint p[], int no, int col) +{ + int f; + + for(f=0;f1800) + ang=1800-(ang-1800); + + d=(int)((no_col/1800.0)*(double)ang); + + return MIN(d,no_col-1); +} + + +static double Distance(Point3D *a, Point3D *b) +{ + double x,y,z; + + x=a->x-b->x; + y=a->y-b->y; + z=a->z-b->z; + + return sqrt((x*x)+(y*y)+(z*z)); +} + + +static int Project(double x,double y,double z,XPoint *xp) +{ + if (z<10.0) + return False; + + z=z/800.0; + + xp->x=centre_x+(int)(x/z); + xp->y=centre_y+(int)(y/z); + + return True; +} + + +static void RotateX(double cx, double cy, double cz, + double ix, double iy, double iz, + double *x, double *y, double *z, + int a) +{ + double dy,dz,si,co; + + while(a<0) + a+=3600; + + a%=3600; + + if (a==0) + { + *x=ix; + *y=iy; + *z=iz; + return; + } + + dy=iy-cy; + dz=iz-cz; + *x=ix; + + si=sintab[a]; + co=costab[a]; + + *y=cy+(dz*si+dy*co); + *z=cz+(dz*co-dy*si); +} + + +static void RotateY(double cx, double cy, double cz, + double ix, double iy, double iz, + double *x, double *y, double *z, + int a) +{ + double dx,dz,si,co; + + while(a<0) + a+=3600; + + a%=3600; + + if (a==0) + { + *x=ix; + *y=iy; + *z=iz; + return; + } + + dx=ix-cx; + dz=iz-cz; + *y=iy; + + si=sintab[a]; + co=costab[a]; + + *x=cy+(dz*si+dx*co); + *z=cz+(dz*co-dx*si); +} + + +static void RotateZ(double cx, double cy, double cz, + double ix, double iy, double iz, + double *x, double *y, double *z, + int a) +{ + double dy,dx,si,co; + + while(a<0) + a+=3600; + + a%=3600; + + if (a==0) + { + *x=ix; + *y=iy; + *z=iz; + return; + } + + dy=iy-cy; + dx=ix-cx; + *z=iz; + + si=sintab[a]; + co=costab[a]; + + *y=cy+(dx*si+dy*co); + *x=cx+(dx*co-dy*si); +} + + +static void DrawObj(Obj3D *o, unsigned long cmap[]) +{ + int f; + + for(f=0;fno_points;f++) + { + RotateX(0,0,0, + o->ps[f].x,o->ps[f].y,o->ps[f].z, + &o->workp3[f].x,&o->workp3[f].y,&o->workp3[f].z, + o->x_rot); + + RotateY(0,0,0, + o->workp3[f].x,o->workp3[f].y,o->workp3[f].z, + &o->workp3[f].x,&o->workp3[f].y,&o->workp3[f].z, + o->y_rot); + + RotateZ(0,0,0, + o->workp3[f].x,o->workp3[f].y,o->workp3[f].z, + &o->workp3[f].x,&o->workp3[f].y,&o->workp3[f].z, + o->z_rot); + + Project(o->origin.x+o->workp3[f].x, + o->origin.y+o->workp3[f].y, + o->origin.z+o->workp3[f].z, + o->workxp+f); + } + + for(f=0;fno_poly;f++) + { + static XPoint p[MAX_POLY_POINTS]; + int r; + int c=-1; + int col; + + for(r=0;rpoly[f].no;r++) + p[r]=o->workxp[o->poly[f].p[r]]; + + if (o->cull) + c=(p[0].x-p[1].x)*(p[2].y-p[1].y)-(p[0].y-p[1].y)*(p[2].x-p[1].x); + + if (o->col!=-1) + col=cmap[o->col]; + else + col=cmap[o->poly[f].col]; + + if (c<0) + switch(o->mode) + { + case MODE_SOLID: + FPolygon(p,o->poly[f].no,col); + break; + case MODE_EDGE: + FPolygon(p,o->poly[f].no,black); + Polygon(p,o->poly[f].no,col); + break; + case MODE_WIRE: + default: + Polygon(p,o->poly[f].no,col); + break; + } + } +} + + +static int ZSort(const void *p1, const void *p2) +{ + double z1,z2; + const WorldObj *o1, *o2; + + o1=p1; + o2=p2; + + switch(o1->type) + { + case eObj: + z1=((const Obj3D *)o1->p)->origin.z; + break; + case eSphere: + z1=((const Sphere3D *)o1->p)->origin.z; + break; + case eRect: + z1=((const Rect3D *)o1->p)->origin.z; + break; + case eParticle: + z1=((const Particle3D *)o1->p)->origin.z; + break; + default: + z1=-1; + break; + } + + switch(o2->type) + { + case eObj: + z2=((const Obj3D *)o2->p)->origin.z; + break; + case eSphere: + z2=((const Sphere3D *)o2->p)->origin.z; + break; + case eRect: + z2=((const Rect3D *)o2->p)->origin.z; + break; + case eParticle: + z2=((const Particle3D *)o2->p)->origin.z; + break; + default: + z2=-1; + break; + } + + return (int)(z2-z1); +} + + +static int InvZSort(const void *p1, const void *p2) +{ + double z1,z2; + const WorldObj *o1, *o2; + + o1=p1; + o2=p2; + + switch(o1->type) + { + case eObj: + z1=((const Obj3D *)o1->p)->origin.z; + break; + case eSphere: + z1=((const Sphere3D *)o1->p)->origin.z; + break; + case eRect: + z1=((const Rect3D *)o1->p)->origin.z; + break; + case eParticle: + z1=((const Particle3D *)o1->p)->origin.z; + break; + default: + z1=-1; + break; + } + + switch(o2->type) + { + case eObj: + z2=((const Obj3D *)o2->p)->origin.z; + break; + case eSphere: + z2=((const Sphere3D *)o2->p)->origin.z; + break; + case eRect: + z2=((const Rect3D *)o2->p)->origin.z; + break; + case eParticle: + z2=((const Particle3D *)o2->p)->origin.z; + break; + default: + z2=-1; + break; + } + + return (int)(z1-z2); +} + + +static void DrawList(WorldObj *w, int no, unsigned long cmap[], + int inv_z_order,int do_sort) +{ + int f; + XPoint xp,xp2; + Particle3D *p; + Sphere3D *s; + Rect3D *r; + + if (do_sort) + { + if (inv_z_order) + qsort(w,no,sizeof(WorldObj),InvZSort); + else + qsort(w,no,sizeof(WorldObj),ZSort); + } + + for(f=0;forigin.x,s->origin.y,s->origin.z,&xp)) + if (Project(s->origin.x+s->radius,s->origin.y, + s->origin.z,&xp2)) + switch(s->mode) + { + case MODE_SOLID: + FCircle(xp.x,xp.y,xp2.x-xp.x,cmap[s->col]); + break; + case MODE_WIRE: + Circle(xp.x,xp.y,xp2.x-xp.x,cmap[s->col]); + break; + case MODE_EDGE: + FCircle(xp.x,xp.y,xp2.x-xp.x,black); + Circle(xp.x,xp.y,xp2.x-xp.x,cmap[s->col]); + break; + } + break; + + case eRect: + r=w[f].p; + + if (Project(r->origin.x,r->origin.y,r->origin.z,&xp)) + if (Project(r->origin.x+r->w,r->origin.y+r->h, + r->origin.z,&xp2)) + { + int w,h; + + w=xp2.x-xp.x; + h=xp2.y-xp.y; + + switch(r->mode) + { + case MODE_SOLID: + FRect(xp.x,xp.y,w,h,cmap[r->col]); + break; + case MODE_WIRE: + Rect(xp.x,xp.y,w,h,cmap[r->col]); + break; + case MODE_EDGE: + FRect(xp.x,xp.y,w,h,black); + Rect(xp.x,xp.y,w,h,cmap[r->col]); + break; + } + } + break; + + case eParticle: + p=w[f].p; + + if (Project(p->origin.x,p->origin.y,p->origin.z,&xp)) + Plot(xp.x,xp.y,cmap[p->col]); + + break; + + default: + break; + } + } +} + + +static void DrawSubList(Obj3D *o, int obj_no, + Sphere3D *s, int sphere_no, + Rect3D *r, int rect_no, + Particle3D *p, int particle_no, + unsigned long cmap[], int inv_z_order, int do_sort) +{ + WorldObj *w; + int no; + int f; + int i; + + no=obj_no+sphere_no+rect_no+particle_no; + + w=Grab(sizeof(WorldObj)*no); + + i=0; + + for(f=0;fx=mouse_x; + new->y=mouse_y; + new->r=3; + new->c=0; + new->next=NULL; + + if (!head) + head=tail=new; + else + { + tail->next=new; + tail=new; + } + + last=time(NULL); + } + + if (clr) + Cls(); + + d=head; + + while(d) + { + if (d->c>=256) + { + Drop *t; + + if (d->next) + head=d->next; + else + head=tail=NULL; + + t=d; + d=d->next; + + Release(t); + } + else + { + Circle(d->x,d->y,d->r,col[d->c]); + d->r+=scale; + d->c+=speed; + d=d->next; + } + } +} + + +/* ---------------------------------------- AUTO DROP DEMO +*/ +static void AutoDropDemo(void) +{ + static const int speed=1; + static const int scale=1; + static const int num=10; + static int init=FALSE; + static unsigned long col[256]; + static time_t last=0; + + typedef struct Drop + { + int x,y,r,c; + int speed; + int scale; + struct Drop *next; + } Drop; + + static Drop *head=NULL; + static Drop *tail=NULL; + + Drop *d; + int f; + + if (!init) + { + int f; + + for(f=0;f<256;f++) + col[f]=GetCol(MAX(255-f*2,0),MAX(255-f*2,0),255-f); + + init=TRUE; + } + + if (last!=time(NULL) && !head) + { + int x,y,sc; + + x=RND(width); + y=RND(height); + sc=scale; + + for(f=0;fx=x+RND(num); + new->y=y+RND(num); + new->r=3; + new->c=0; + new->scale=sc; + new->speed=speed; + new->next=NULL; + + if (!head) + head=tail=new; + else + { + tail->next=new; + tail=new; + } + } + + last=time(NULL); + } + + /* Cls(); */ + d=head; + + while(d) + { + if (d->c>=256) + { + Drop *t; + + if (d->next) + head=d->next; + else + head=tail=NULL; + + t=d; + d=d->next; + + Release(t); + } + else + { + Circle(d->x,d->y,d->r,col[d->c]); + d->r+=d->scale; + d->c+=d->speed; + d=d->next; + } + } +} + + +/* ---------------------------------------- FAST DROP DEMO +*/ +static void FastDropDemo(void) +{ + static const int speed=30; + static const int scale=2; + static int init=FALSE; + static int clr=TRUE; + static unsigned long col[256]; + static time_t last=0; + + typedef struct Drop + { + int x,y,r,c; + struct Drop *next; + } Drop; + + static Drop *head=NULL; + static Drop *tail=NULL; + + Drop *d; + + if (!init) + { + int f; + + for(f=0;f<256;f++) + col[f]=GetCol(255-f,255-f,255-f); + + init=TRUE; + } + + if (mouse_b&Button3Mask) + { + static time_t bounce=0; + + if (bounce!=time(NULL)) + { + clr=!clr; + bounce=time(NULL); + } + } + + if (mouse_b&Button1Mask /*&& (last!=time(NULL))*/) + { + Drop *new; + + new=Grab(sizeof *new); + + new->x=mouse_x; + new->y=mouse_y; + new->r=3; + new->c=0; + new->next=NULL; + + if (!head) + head=tail=new; + else + { + tail->next=new; + tail=new; + } + + last=time(NULL); + } + + if (clr) + Cls(); + + d=head; + + while(d) + { + if (d->c>=256) + { + Drop *t; + + if (d->next) + head=d->next; + else + head=tail=NULL; + + t=d; + d=d->next; + + Release(t); + } + else + { + Rect(d->x-d->r/2,d->y-d->r/2,d->r,d->r,col[d->c]); + d->r+=scale; + d->c+=speed; + d=d->next; + } + } +} + + +/* ---------------------------------------- TRAIL DEMO +*/ +static void TrailDemo(void) +{ + static const int NO=20; + static const int speed=20; + static const int scale=10; + static int init=FALSE; + static unsigned long col[256]; + + static struct + { + int x,y,xi,yi; + } *p; + + typedef struct Drop + { + int x,y,r,c; + struct Drop *next; + } Drop; + + static Drop *head=NULL; + static Drop *tail=NULL; + Drop *new; + Drop *d; + int f; + + if (!init) + { + for(f=0;f<256;f++) + col[f]=GetCol(255-f,255-f,255-f); + + p=Grab(sizeof(*p)*NO); + + for(f=0;fx=p[f].x; + new->y=p[f].y; + new->r=3; + new->c=0; + new->next=NULL; + + if (!head) + head=tail=new; + else + { + tail->next=new; + tail=new; + } + + Bounce(&p[f].x,&p[f].y,&p[f].xi,&p[f].yi); + } + + /* Cls(); */ + d=head; + + while(d) + { + if (d->c>=256) + { + Drop *t; + + if (d->next) + head=d->next; + else + head=tail=NULL; + + t=d; + d=d->next; + + Release(t); + } + else + { + FRect(d->x-d->r/2,d->y-d->r/2,d->r,d->r,col[d->c]); + d->r+=scale; + d->c+=speed; + d=d->next; + } + } +} + + +/* ---------------------------------------- TUNNEL DEMO +*/ +static void TunnelDemo(void) +{ + static const int speed=100; + static const int radius=1000; + static const int points=10; + static const int max_z=50000; + static const int delay=20; + + static double *si; + static double *co; + + static int init=FALSE; + static int clr=TRUE; + static unsigned long col[256]; + static time_t last=0; + static int create=0; + + typedef struct Drop + { + double x[points]; + double y[points]; + double z; + int r,c; + int ang; + struct Drop *next; + } Drop; + + static Drop *head=NULL; + static Drop *tail=NULL; + + Drop *d; + int f; + + if (!init) + { + for(f=0;f<256;f++) + col[f]=GetCol(255-f,255-f,255-f); + + si=Grab(sizeof(double)*points); + co=Grab(sizeof(double)*points); + + for(f=0;fx[f]=(RND(radius>>1)+radius>>1)*si[f]; + new->y[f]=(RND(radius>>1)+radius>>1)*co[f]; + } + + new->r=radius; + new->z=max_z; + new->c=255; + + new->ang=RND(20)-10; + + if (new->ang<0) + new->ang+=3600; + + new->next=NULL; + + if (!head) + head=tail=new; + else + { + tail->next=new; + tail=new; + } + + create=delay; + } + else + create--; + + if (clr) + Cls(); + + d=head; + + while(d) + { + if (d->z<10) + { + Drop *t; + + if (d->next) + head=d->next; + else + head=tail=NULL; + + t=d; + d=d->next; + + Release(t); + } + else + { + XPoint p[points]; + + if (d->c) + d->c=MAX(0,d->c-10); + + for(f=0;fz, + d->x[f],d->y[f],d->z, + &d->x[f],&d->y[f],&d->z, + d->ang); + + Project(d->x[f],d->y[f],d->z,p+f); + } + + for(f=0;fc]); + + d->z-=speed; + d=d->next; + } + } +} + + +/* ---------------------------------------- STAR DEMO +*/ +static void StarDemo(void) +{ +# define TYPE Particle3D +# undef ISSPHERE + + static const int no_points=4; + static const int no_poly=4; + + static Point3D pset[4]= + { + {-100,50,100}, + {100,50,100}, + {0,-50,100}, + {0,0,-300}, + }; + + static Poly3D plist[4]= + { + { + {0,3,1}, + 3, + 0 + }, + { + {0,1,2}, + 3, + 0 + }, + { + {0,2,3}, + 3, + 0 + }, + { + {1,3,2}, + 3, + 0 + }, + }; + + static Obj3D *obj; + +#ifdef ISSPHERE + static const int no=200; +#else + static const int no=2000; +#endif + + static const int no_obj=3; + static const int radius=25000; + static const int max_z=50000; + static const double max_speed=50.0; + static const double min_speed=1.0; + static const double speed_inc=0.1; + + static int init=FALSE; + static unsigned long col[256]; + static int clr=TRUE; + static time_t last=0; + static double speed=1.0; + + static TYPE *star; + int fg,bg; + int f; + + if (!init) + { + for(f=0;f<256;f++) + col[f]=GetCol(255-f,255-f,255-f); + + star=Grab(sizeof(TYPE)*no); + + for(f=0;fmin_speed) + speed-=speed_inc; + } + + Cls(); + + for(f=0;fmin_speed) + { + XPoint p; + XPoint p2; + + Project(star[f].origin.x,star[f].origin.y,star[f].origin.z,&p); + Project(star[f].origin.x,star[f].origin.y,star[f].origin.z+speed*speed,&p2); + LineP(&p,&p2,col[star[f].col]); + } + + star[f].origin.z-=20*speed; + + if (star[f].col) + star[f].col--; + } + } + + for(f=0;fmin_speed) + speed-=speed_inc; + } + + Cls(); + + for(f=0;fMODE_EDGE) + obj.mode=MODE_SOLID; + + bounce=time(NULL); + } + } + + Cls(); + + for(f=0;fradius) + p[f].origin.y=-radius; + } + + switch(rot) + { + case 0: + Print(0,20,white,"Y rotation"); + obj.y_rot+=10; + break; + case 1: + Print(0,20,white,"X rotation"); + obj.x_rot+=10; + break; + case 2: + Print(0,20,white,"Z rotation"); + obj.z_rot+=10; + break; + default: + break; + } + + Print(0,30,white,"Mode : %d Culling: %s",obj.mode,obj.cull ? "on":"off"); + + DrawList(w,no_particle+1,col,False,False); +} + + +/* ---------------------------------------- COL SCAPE DEMO +*/ +static void ColScapeDemo(void) +{ + static const int gap=200; + static const int no_pt=8; + static const int no_poly=6; + static const int no_x=20; + static const int no_z=20; + static const int no=400; + static const int z_off=1000; + static const double y_range=200.0; + static const double y_base=100.0; + + static Point3D pset[8]= + { + {-50,-20,50}, + {50,-20,50}, + {50,-20,-50}, + {-50,-20,-50}, + + {50,20,50}, + {-50,20,50}, + {-50,20,-50}, + {50,20,-50}, + }; + + static Poly3D plist[6]= + { + { + {0,1,2,3}, + 4, + 0 + }, + { + {4,5,6,7}, + 4, + 0 + }, + { + {0,5,4,1}, + 4, + 0 + }, + { + {2,1,4,7}, + 4, + 0 + }, + { + {3,2,7,6}, + 4, + 0 + }, + { + {0,3,6,5}, + 4, + 0 + }, + }; + + static Obj3D *obj; + + static WorldObj *w; + + static int ang=0; + + static int init=FALSE; + static unsigned long col[4]; + + int f,a; + + if (!init) + { + int x,z; + + col[0]=white; + col[1]=red; + col[2]=green; + col[3]=blue; + + init=TRUE; + + obj=Grab(sizeof(Obj3D)*no); + w=Grab(sizeof(WorldObj)*no); + + x=-(no_x/2)*gap; + z=(no_z)*gap+z_off; + a=0; + + for(f=0;fy_base) + { + amp=init_amp; + ang=0; + dist=1; + ctr=drop.origin; + + drop.origin.x=RND2(max_x,min_x); + drop.origin.z=RND2(max_z,min_z); + drop.origin.y=drop_y; + } + + if (amp>0.0) + { + int a; + + if (ang<0) + ang+=3600; + + a=ang; + + for(f=0;fy_base) + { + amp=init_amp; + ang=0; + dist=1; + ctr=drop.origin; + + drop.origin.x=RND2(max_x,min_x); + drop.origin.z=RND2(max_z,min_z); + drop.origin.y=drop_y; + } + + if (amp>0.0) + { + int a; + + if (ang<0) + ang+=3600; + + a=ang; + + for(f=0;fMODE_EDGE) + obj.mode=MODE_SOLID; + + bounce=time(NULL); + } + } + + Cls(); + + if (view) + { + obj.x_rot=MAX(2700,MIN(3599,2700+mouse_y*3)); + + obj.y_rot=(centre_x-mouse_x)*3; + obj.y_rot=MAX(-900,MIN(obj.y_rot,900)); + } + else + { + drop.origin.y+=drop_speed*speed; + speed+=0.1; + + if (drop.origin.y>y_base) + { + int a; + + speed=1.0; + + ctr=drop.origin; + + drop.origin.z=RND2(max_z,min_z)/gap*gap; + drop.origin.x=RND2((int)drop.origin.z,(int)-drop.origin.z)/gap*gap; + drop.origin.y=drop_y; + + for(f=0;f=gap) + { + for(f=no-1;f>=no_x;f--) + pt[f].y=pt[f-no_x].y; + + for(f=0;f=gap) + { + for(f=no-1;f>=no_x;f--) + pt[f].y=pt[f-no_x].y; + + for(f=0;f