diff options
Diffstat (limited to 'edit3d.c')
-rw-r--r-- | edit3d.c | 474 |
1 files changed, 474 insertions, 0 deletions
diff --git a/edit3d.c b/edit3d.c new file mode 100644 index 0000000..a6eb88f --- /dev/null +++ b/edit3d.c @@ -0,0 +1,474 @@ +/* + + viDOOM - level editor for DOOM + + Copyright (C) 2000 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 + + ------------------------------------------------------------------------- + + _Very_ basic 3D preview + +*/ +static const char rcs_id[]="$Id$"; + +#include "config.h" +#include "globals.h" +#include "editvar.h" +#include "map.h" +#include "gfx.h" + +#include <math.h> +#include <ctype.h> + + +/* ---------------------------------------- LOCAL DATA +*/ +#define POLY 0 +#define SPHERE 1 + +typedef struct + { + int type; + Point p[4]; + Point c; + int r; + int z; + int col; + void *next; + } Poly; + +static int draw_things=FALSE; +static int fade=0; +static int roll; +static int pitch; +static int px,py,pz; + +static Poly *plist=NULL; + + +/* ---------------------------------------- POLY LIST FUNCTIONS +*/ +static void NewPList(void) +{ + Poly *p; + + while (plist) + { + p=plist; + plist=plist->next; + Release(p); + } +} + + +static void AddPList(Poly *p) +{ + Poly *np; + Poly *l; + + if (p->col<0x101010) + return; + + np=Copy(p,sizeof(Poly)); + + if (!plist) + { + plist=np; + np->next=NULL; + return; + } + else + { + if (np->z>=plist->z) + { + np->next=plist; + plist=np; + return; + } + + l=plist; + + while(l) + { + if (np->z<l->z) + { + if (!l->next) + { + l->next=np; + np->next=NULL; + return; + } + } + else + { + np->next=l->next; + l->next=np; + return; + } + + l=l->next; + } + } + + /* It shouldn't be possible to reach here!! + */ + Release(np); +} + + +/* ---------------------------------------- LOCAL FUNCTIONS +*/ +static void Transform (int x, int y, int z, int *rx, int *ry, int *rz) +{ + y=-y; + + *rx=x-px; + *ry=y-py; + *rz=z-pz; + + Rotate(0,0,rx,rz,roll); + Rotate(0,0,ry,rz,pitch); +} + + +static void Project (int x, int y, int z, int to_x, int to_z, Point *p) +{ + double dx,dy,sc; + + if ((z<1)&&(to_z<1)) + { + p->x=-1; + p->y=-1; + } + + if (z<1) + z=1; + + dx=(double)x; + dy=(double)y; + + sc=(double)z/400.0; + + p->x=(int)(dx/sc)+SCRW/2; + p->y=(int)(dy/sc)+SCRH/2; +} + +static int Fade(int col, int z) +{ + int r,g,b,f; + + f=z/(16/fade); + + r=(col&0xff0000)>>16; + g=(col&0xff00)>>8; + b=col&0xff; + + r=MAX(r-f,0); + g=MAX(g-f,0); + b=MAX(b-f,0); + + return(V_RGB(r,g,b)); +} + + +static void DoPoly(EditVert *v1, EditVert *v2, int low, int high) +{ + int x[4],y[4],z[4]; + int zt; + int f; + int ok; + Poly p; + + Transform(v1->v.x,low,v1->v.y,&x[0],&y[0],&z[0]); + Transform(v1->v.x,high,v1->v.y,&x[1],&y[1],&z[1]); + + Transform(v2->v.x,high,v2->v.y,&x[2],&y[2],&z[2]); + Transform(v2->v.x,low,v2->v.y,&x[3],&y[3],&z[3]); + + ok=FALSE; + + for(f=0;f<4;f++) + if (z[f]>0) + ok=TRUE; + + if (ok) + { + p.type=POLY; + + zt=0; + + p.z=999999; + + for(f=0;f<4;f++) + { + Project(x[f],y[f],z[f],x[(f+1)%4],z[(f+1)%4],&p.p[f]); + zt+=z[f]; + p.z=MIN(p.z,z[f]); + } + + if (fade) + p.col=Fade(WHITE,p.z); + else + p.col=WHITE; + + AddPList(&p); + } +} + + + +static void DoThing(EditThing *t,int tz) +{ + int x,y,z; + int r; + Poly p; + Point rp; + int col; + + Transform(t->t.x,tz,t->t.y,&x,&y,&z); + + if (z<1) + return; + + p.type=SPHERE; + + r=ThingRadius(t->t.type,&col); + + Project(x,y-r,z,x,z,&p.c); + Project(x+r,y-r,z,x+r,z,&rp); + + p.r=rp.x-p.c.x; + p.z=z; + + if (p.r<1) + p.r=1; + + if (fade) + p.col=Fade(RED,z); + else + p.col=col; + + AddPList(&p); +} + + + +/* ---------------------------------------- EXPORTED FUNCTIONS +*/ +void EditPreview3D(void) +{ + int done; + int redraw; + GFXKey k; + int rd; + + px=0; + py=0; + pz=0; + roll=0; + pitch=0; + + done=FALSE; + redraw=TRUE; + rd=FALSE; + + while(!done) + { + if ((redraw)||(rd)) + { + EditThing *t; + EditLine *l; + EditSect *s,*sl; + int f; + int low,high; + int sn; + Poly *p; + + rd=FALSE; + + GFX_clear(BLACK); + + NewPList(); + + for(f=0;(f<MapSize(linedef))&&(!rd);f++) + { + if ((l=GETLINE(f))&&(s=GETSECT(l->sr->sector))) + if ((l->sl)&&(sl=GETSECT(l->sl->sector))) + { + if (s->s.floor!=sl->s.floor) + { + low=MIN(s->s.floor,sl->s.floor); + high=MAX(s->s.floor,sl->s.floor); + DoPoly(l->v[0],l->v[1],low,high); + } + + if (s->s.ceiling!=sl->s.ceiling) + { + low=MIN(s->s.ceiling,sl->s.ceiling); + high=MAX(s->s.ceiling,sl->s.ceiling); + DoPoly(l->v[0],l->v[1],low,high); + } + } + else + DoPoly(l->v[0],l->v[1],s->s.floor,s->s.ceiling); + + rd=GFX_key(&k); + } + + if (draw_things) + for(f=0;(f<MapSize(thing))&&(!rd);f++) + { + if ((t=GETTHING(f))) + { + sn=SectorHoldingPoint(t->t.x,t->t.y); + + if ((sn!=-1)&&(s=GETSECT(sn))) + high=s->s.floor; + else + high=0; + + if (hexen_mode) + high+=t->t.z; + + DoThing(t,high); + } + + rd=GFX_key(&k); + } + + p=plist; + + while((p)&&(!rd)) + { + switch(p->type) + { + case POLY: + for(f=0;f<4;f++) + GFX_line(p->p[f].x,p->p[f].y, + p->p[(f+1)%4].x,p->p[(f+1)%4].y,p->col); + break; + + case SPHERE: + GFX_fcircle(p->c.x,p->c.y,p->r,p->col); + break; + } + + p=p->next; + rd=GFX_key(&k); + } + + GFX_frect(0,0,SCRW,FH*2,BLUE); + + GFX_print(0,0,WHITE,"Pos: %d,%d,%d Roll: %d Pitch : %d %s", + px,py,pz,roll,pitch,rd ? "Draw interrupted" : "Draw done"); + + if (fade) + GFX_print(0,FH,WHITE,"Fade: Intensity %d",fade); + else + GFX_print(0,FH,WHITE,"Fade: off"); + + GFX_print(SCRW/2,FH,WHITE,"Things: %s",draw_things ? "On":"Off"); + + GFX_redraw(); + } + + if (!rd) + GFX_waitkey(&k); + + redraw=TRUE; + + if (k.code==GFX_ASCII) + switch(toupper(k.ascii)) + { + case 'T': + draw_things=!draw_things; + break; + + default: + redraw=FALSE; + break; + } + else + switch(k.code) + { + case GFX_ESC: + done=TRUE; + break; + + case GFX_LEFT: + if (k.alt) + { + pz+=(int)(cos(RAD(roll-90))*(k.shift ? 128 : 64)); + px+=(int)(sin(RAD(roll-90))*(k.shift ? 128 : 64)); + } + else + roll=(roll+360-(k.shift ? 15:5))%360; + break; + + case GFX_RIGHT: + if (k.alt) + { + pz+=(int)(cos(RAD(roll+90))*(k.shift ? 128 : 64)); + px+=(int)(sin(RAD(roll+90))*(k.shift ? 128 : 64)); + } + else + roll=(roll+(k.shift ? 15:5))%360; + break; + + case GFX_UP: + pz+=(int)(cos(RAD(roll))*(k.shift ? 128 : 64)); + px+=(int)(sin(RAD(roll))*(k.shift ? 128 : 64)); + break; + + case GFX_DOWN: + pz-=(int)(cos(RAD(roll))*(k.shift ? 128 : 64)); + px-=(int)(sin(RAD(roll))*(k.shift ? 128 : 64)); + break; + + case GFX_END: + pitch=0; + break; + + case GFX_PGDN: + if (k.shift) + pitch=MAX(pitch-5,-90); + else + py-=64; + break; + + case GFX_PGUP: + if (k.shift) + pitch=MIN(pitch+5,90); + else + py+=64; + break; + + case GFX_ENTER: + fade=(fade+1)%3; + break; + + default: + redraw=FALSE; + break; + } + } + + FullRedraw(); +} + + +/* END OF FILE */ |