summaryrefslogtreecommitdiff
path: root/edit3d.c
diff options
context:
space:
mode:
Diffstat (limited to 'edit3d.c')
-rw-r--r--edit3d.c474
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 */