[net.sources] AMIGA: source to "amiga3d":, file 4 of 4

bart@amiga.UUCP (02/27/86)

< eat this line... please! >

/***************************************************************/
objectallocate.c
/***************************************************************/
#include <exec/types.h>
#include <exec/memory.h>
#include "threed.h"


allocateobjectinfolist(view,screen,window,firstobjectinfo,firstobject)
struct View *view;
struct Screen *screen;
struct Window *window;
struct Objectinfo **firstobjectinfo;
struct Object *firstobject;
{
	struct Object *ob;
	int error = FALSE;

	/* allocate objectinfo structures */

	/* for all the objects in this objectsegment */

	for (ob = firstobject; ob; ob = ob->nextobject)
	{
	    struct Objectinfo *thisobjectinfo;

#ifdef CAMERADEBUG
	    printf("test3d: allocate objectinfo for object(%lx) ",ob);
#endif

	    /* allocate an objectinfo structure for the current object */

	    if ((thisobjectinfo = (struct Objectinfo *)AllocMem(sizeof(struct Objectinfo),MEMF_PUBLIC|MEMF_CLEAR)) == NULL) 
	    {
		error = TRUE;
		return(error); 
	    }

#ifdef CAMERADEBUG
	    printf("= %lx\n",thisobjectinfo);
#endif
	    /* initialize the buffers for the current 3d object */

	    if(!objectinit(view,screen,window,thisobjectinfo,ob))
	    {
		error = TRUE;
	        return(error);
	    }

	    /* make this objectinfo last on the objectinfo list */
	    {
		struct Objectinfo **oipp;

		oipp =  firstobjectinfo;
		while (*oipp)
		{
		    oipp = &((*oipp)->nextobjectinfo);
		}
		*oipp = thisobjectinfo;
		 thisobjectinfo->nextobjectinfo = NULL;
	    }

	}

}


deallocateobjectinfolist(view,screen,window,firstobjectinfo)
struct View *view;
struct Screen *screen;
struct Window *window;
struct Objectinfo **firstobjectinfo;
{

    /* deallocate objectinfo structures */

#ifdef ODEBUG
    printf("test3d: deallocate the active objectinfo structures...\n");
#endif

    while( (*firstobjectinfo) )
    {
	struct Objectinfo *oip;

	/* delink the first objectinfo from the objectinfo list */

	oip = *firstobjectinfo;

	(*firstobjectinfo) = (*firstobjectinfo)->nextobjectinfo;

	/* deallocate the buffers dependent on the current objectinfo */

#ifdef ODEBUG
    printf("    deallocate objectinfo(%lx)\n",oip);
#endif

	objectdeallocate(view,screen,window,oip);

	/* deallocate this objectinfo structure itself */

	FreeMem(oip,sizeof(struct Objectinfo));
    }

}
/***************************************************************/
startgfxdos.c
/***************************************************************/
#define MAXPOINTS 64

#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <graphics/gfx.h>
#include <graphics/gfxbase.h>
#include <graphics/clip.h>
#include <graphics/rastport.h>
#include <graphics/view.h>
#include <graphics/text.h>
#include <graphics/gfxmacros.h>

#include <graphics/layers.h>
#include <intuition/intuition.h>
#include <exec/memory.h>
#include <exec/ports.h>
#include <exec/libraries.h>
#include <exec/interrupts.h>
#include <graphics/copper.h>
#include <hardware/dmabits.h>
#include <hardware/custom.h>
#include <graphics/gfxmacros.h>
 
#include <devices/timer.h>

#include "threed.h"

#define IS_PAL (((struct GfxBase *)GfxBase)->DisplayFlags & PAL)

long TimerBase;
struct timerequest *timerio;
extern struct Custom custom;

/* #define DEBUG */
/* #define TICKDEBUG */

long GfxBase = 0;
long LayersBase = 0;
long IntuitionBase = 0;
long DosBase = 0;

struct  AreaInfo areainfo;
UWORD   areafill[(MAXPOINTS/2)*5];

int gettime()
{
	int ticks;
	DoIO(timerio);
	ticks = timerio->tr_time.tv_secs*60;
	ticks += (timerio->tr_time.tv_micro*60)/1000000;
	return(ticks);
}

inittimer(usrproc,view,screen, window)
int  (*usrproc)();
struct View *view;
struct Screen *screen;
struct Window *window;
{
	int error = FALSE;

	/* allocate a timerequest structure */

	timerio = (APTR)AllocMem(sizeof(struct timerequest),MEMF_CLEAR);

	/* open the timer device */

	TimerBase = OpenDevice("timer.device",UNIT_VBLANK,timerio,0);

	/* initialize stuff to read timer value back */

	timerio->tr_node.io_Command = TR_GETSYSTIME;

	error = (*usrproc)(view,screen,window);

	/* close timer device */

	CloseDevice(timerio);

	/* clean up */

	FreeMem(timerio,sizeof(struct timerequest));

	return(error);
}

timeproc(usrproc,view,screen, window)
int  (*usrproc)();
struct View *view;
struct Screen *screen;
struct Window *window;
{
	int error = FALSE;
	int starttime;

	starttime = gettime();

	error = (*usrproc)(view,screen,window);

	if (!error)
	{
	    return(gettime() - starttime);
	}
	else 
	{
	    return(error);
	}

}

startgfxdos(x,y,height,width,n_bit_planes,usrproc,s,flags,tmpras,sbitmap)
WORD x,y;
UWORD height, width, n_bit_planes;
int (*usrproc)();
UBYTE *s;
ULONG flags;
struct TmpRas *tmpras;
struct BitMap *sbitmap;
{
	struct Screen *screen;
	struct Window *window;
	struct RastPort *w;
	struct View *view;
	short idcmp;
	struct NewWindow nw;
	struct NewScreen ns;
        int error = FALSE;

#ifdef DEBUG
	printf("startgfxdos: opening graphics lib...\n");
#endif
	
	if ( (!GfxBase) && ( (GfxBase = OpenLibrary("graphics.library",0) ) == NULL) )
	{
#ifdef DEBUG
		printf("startgfxdos: can't open graphics lib...\n");
#endif
		return((int)-1);
	}

#ifdef DEBUG
	printf("startgfxdos: opening layers lib...\n");
#endif
	
	if ( (LayersBase = OpenLibrary("layers.library",0)) == NULL)
	{
#ifdef DEBUG
		printf("startgfxdos: can't open layers lib...\n");
#endif
		return((int)-1);
	}

#ifdef DEBUG
	printf("startgfxdos: opening intuition lib...\n");
#endif

	if ( (IntuitionBase = OpenLibrary("intuition.library",0)) == NULL)
	{
#ifdef DEBUG
		printf("startgfxdos: can't open intuition lib...\n");
#endif
		return((int)-1);
	}

	ns.LeftEdge = x;
	ns.TopEdge = 0;
	ns.Width = width;
	ns.Height = ((height>(IS_PAL?PAL_MAXHINOLACE:NTSC_MAXHINOLACE))?(IS_PAL?PAL_MAXHILACE:NTSC_MAXHILACE):(IS_PAL?PAL_MAXHINOLACE:NTSC_MAXHINOLACE));
	ns.Depth = n_bit_planes;
	ns.DetailPen = -1;
	ns.BlockPen = -1;
	ns.ViewModes = ( 0 | ((width > 320)?HIRES:0) | ((height>(IS_PAL?PAL_MAXHINOLACE:NTSC_MAXHINOLACE))?LACE:0) );
	ns.Type = CUSTOMSCREEN;
	ns.Font = NULL;
	ns.DefaultTitle = NULL;
	ns.Gadgets = NULL;

#ifdef DEBUG
	printf("startgfxdos: opening a custom screen...\n");
#endif

	if ( (screen = (struct Screen *)OpenScreen(&ns)) == NULL)
	{
#ifdef DEBUG
	    printf("startgfxdos: can't open a custom screen...\n");
#endif
	    return((int)-1);
	}

        screen->ViewPort.DxOffset = x;

#ifdef DEBUG
	printf("startgfxdos: calling makescreen, rethinkdisplay...\n");
#endif

	MakeScreen(screen);
	RethinkDisplay();

	ShowTitle(screen,FALSE); /* let backdrop window title bars show */

	idcmp = CLOSEWINDOW;

	nw.LeftEdge = 0;
	nw.TopEdge = y;
	nw.Width = width;
	nw.Height = height;
	nw.DetailPen = -1;
	nw.BlockPen = -1;
	nw.IDCMPFlags = idcmp;
	nw.Flags = WINDOWCLOSE|flags;
	nw.FirstGadget = NULL;
	nw.CheckMark = NULL;
	nw.Title = s;
	nw.Screen = screen;
	nw.BitMap = sbitmap;
	nw.MinWidth = width;
	nw.MinHeight = height;
	nw.MaxWidth = width;
	nw.MaxHeight = height;
	nw.Type = CUSTOMSCREEN;

#ifdef DEBUG
	printf("startgfxdos: opening a window in the custom screen...\n");
#endif

	if ( (window = (struct Window *)OpenWindow(&nw)) == NULL )
	{
#ifdef DEBUG
	    printf("startgfxdos: can't open a new window...\n");
#endif
	    return((int)-1);
	}

	if(window->RPort)
	{
#ifdef DEBUG
	    printf("startgfxdos: initialize and link areainfo to this window's rastport...\n");
#endif
	    InitArea(&areainfo,areafill,MAXPOINTS);
	    window->RPort->AreaInfo = &areainfo;
	}
	else
	{
#ifdef DEBUG
	    printf("startgfxdos: null window rastport pointer...\n");
#endif
	    return((int)-1);
	}

#ifdef DEBUG
	printf("startgfxdos: trying to find the view adress...\n");
#endif

	if ( (view = (struct View *)ViewAddress()) == NULL) 
	{
#ifdef DEBUG
	    printf("startgfxdos: can't get view address...\n");
#endif
	    return((int)-1);
	}

	window->RPort->TmpRas = tmpras;

#ifdef DEBUG
	printf("startgfxdos: calling the usrproc routine ...\n");
#endif

#ifdef TICKDEBUG

#ifdef DEBUG
	printf("though the inittimer routine ...\n");
#endif
	error = inittimer(usrproc,view,window->WScreen,window);
#else
	error = (*usrproc)(view,window->WScreen,window);
#endif

#ifdef DEBUG
	printf("startgfxdos: returnted from the usrproc with error = %lx...\n",error);
#endif

#ifdef DEBUG
	printf("startgfxdos: close the window...\n");
#endif
	CloseWindow(window);     

#ifdef DEBUG
	printf("startgfxdos: close the screen...\n");
#endif
	CloseScreen(screen);

	return(error);
}
/***************************************************************/
subdisplay.c
/***************************************************************/
#include <exec/types.h>
#include <exec/nodes.h>
#include <exec/lists.h>
#include <exec/memory.h>
#include <hardware/blit.h>
#include <hardware/custom.h>
#include <graphics/gfx.h>
#include <graphics/clip.h>
#include <graphics/rastport.h>
#include <graphics/view.h>
#include <graphics/text.h>
#include <graphics/gfxmacros.h>

#include <graphics/layers.h>
#include <intuition/intuition.h>
#include <libraries/dos.h>
#include "threed.h"

#define FIXEDILLUMINATION

extern UBYTE title[] ;

extern struct Custom custom;
 
extern struct TmpRas tmpras;

extern struct BitMap bitmap0;
extern struct BitMap bitmap1;

extern struct RastPort r[2];
extern struct RastPort *rp[2];

extern struct RasInfo ri[2];
extern struct RasInfo *rip[2];

extern struct RasInfo *irip;

extern WORD pcount ;
extern WORD vcount ;

extern UWORD frametoggle ;

extern BPTR objectsegment ;

extern struct Object *Amiga ;

extern long GfxBase;
extern long DosBase;

extern int (*subroutines[])();

/******************************************************************************/

subdisplayuniverse(view,screen,window,cameraobjectinfo,objectinfo,subobjectinfo)
struct View *view;
struct Screen *screen;
struct Window *window;
struct Objectinfo *cameraobjectinfo;
struct Objectinfo *objectinfo;
struct Objectinfo *subobjectinfo;
{
    int argc = 0;
    char *argv[MAXNUMARGS];
    struct Objectinfo *thisobjectinfo; 

/* set up parameter passing information for this display */

    argv[0] = &thisobjectinfo;
    argv[1] = subroutines;

    argc = 2;

/* PROCESS ALL THE OBJECTS IN THE LIST POINTED TO BY OBJECTINFO */

    thisobjectinfo = subobjectinfo;

    while(thisobjectinfo)
    {
   int thisobjecterror = FALSE;

   /* process this object */

   if(thisobjectinfo->objectprocedure)
   {
       int (*function)();

       /* call the object's procedure */

#ifdef ODEBUG
       printf("do3d: object(%lx) procedure = %lx\n",
          thisobjectinfo,thisobjectinfo->objectprocedure);
#endif
       function = thisobjectinfo->objectprocedure;
       thisobjecterror = (*function)(argc,argv);

   }

   /* concatenate this submatrix with the next higher level display matrix */

        {
       struct UV uv;

       uv = *thisobjectinfo->objectmatrix;

       transpose(&uv);

       cat(thisobjectinfo->displaymatrix,&uv,objectinfo->displaymatrix);

       transpose(thisobjectinfo->displaymatrix);

   }

      
   /* convert this object's position to the next higher lever display frame-of-reference */

   matrix(thisobjectinfo->displayposition,thisobjectinfo->objectposition,
      objectinfo->displaymatrix);

   /* then determine this subobjects's universal reference position */
   
   addvect(thisobjectinfo->displayposition,objectinfo->displayposition,
      thisobjectinfo->displayposition);

   /* process any subobjects dependent on this object before displaying it */

   {
       struct Objectinfo *nextsubobjectinfo;

       nextsubobjectinfo = thisobjectinfo->subobjectinfo;

       while(nextsubobjectinfo)
       {
      /* subdisplay each next subobject */

      subdisplayuniverse(view,screen,window,cameraobjectinfo,thisobjectinfo,nextsubobjectinfo);

      nextsubobjectinfo = nextsubobjectinfo->nextobjectinfo;

       }

   }

   {
       
       struct Coordinate centerpoint;

       /* concatenate this object's matrix with the camera matrix for display through camera viewpoint */
 
       {
      struct UV uv1, uv2;

      subvect(cameraobjectinfo->objectposition,thisobjectinfo->displayposition,&centerpoint);

      uv1 = *thisobjectinfo->displaymatrix;

      uv2 = *cameraobjectinfo->objectmatrix;

      transpose(&uv1);

      /*transpose(&uv2);*/

      cat(thisobjectinfo->displaymatrix,&uv2,&uv1);

      /*transpose(thisobjectinfo->displaymatrix);*/
      
      matrix(&centerpoint,&centerpoint,cameraobjectinfo->objectmatrix);


       }
       
       if ( (centerpoint.z > 0)
          &&
          (( (centerpoint.z) - ( (centerpoint.x < 0) ? -centerpoint.x : centerpoint.x )) > 0)
          &&
          (( (centerpoint.z) - ( (centerpoint.y < 0) ? -centerpoint.y : centerpoint.y )) > 0) )
       {


      /* rotate the 3d normals*/

#ifdef DEBUG
      printf("do3d: rotate the 3d normals\n");
#endif

      rotate(thisobjectinfo->displaymatrix,thisobjectinfo->objectnumnormals,
         thisobjectinfo->objectnormals,thisobjectinfo->objectbufnormals);

      /* rotate, translate, and perspect the 3d points */

      dopoints(thisobjectinfo->displaymatrix,&centerpoint,
         thisobjectinfo->objectnumpoints,thisobjectinfo->objectpoints,
         thisobjectinfo->objectbufpoints);

       }
       else
       {
      
      /* this object out of 45 degree frustrum */

           thisobjectinfo = thisobjectinfo->nextobjectinfo;

           /* so process the next object */

           continue;
       }

   }

    /* draw the polygons by traversing the polygon list */

    {
   WORD polycount = 0;
   WORD *nextcolor;
   struct Coordinate **nextn;
   struct Coordinate **nextp;
   struct Coordinate *lastn = 0;
   WORD endflag = FALSE;

   /* intialize buffer pointers */

   nextcolor = thisobjectinfo->colorbuf;
   nextn = thisobjectinfo->nptrbuf;
   nextp = thisobjectinfo->pptrbuf;

   for(polycount = 0; polycount < thisobjectinfo->objectnumpolys; polycount++)
   {
       struct Polygon **np;
       WORD vc;
       struct Coordinate **v;
       struct Coordinate *n;
       struct Coordinate *c0;
       struct Coordinate *c1;
       struct Coordinate *c2;
       WORD bright;
       WORD firstx, firsty;

#ifdef DEBUG
       printf("poly %lx: \n",polycount);
#endif
       np = (thisobjectinfo->objectpolys+polycount);

#ifdef DEBUG
       printf("np = %lx\n",np);
#endif

#ifdef DEBUG
       printf("vertexcount = %lx\n",(*np)->vertexcount);
#endif

#ifdef DRAWDEBUG
       printf("poly %lx: color = %lx\n",polycount,*nextcolor);
#endif

       /* backface removal */

       /* first, simple clip */
       if (((*nextn)->z) > 0) 
       {
      nextcolor++;
      nextn++;
      nextp = (nextp+((*np)->vertexcount));
      continue;
       }
       
       /* now, test z component of dynamically computed polygon normal */
       
       c0 = (struct Coordinate *)(*(nextp));
       c1 = (struct Coordinate *)(*(nextp+1));
       c2 = (struct Coordinate *)(*(nextp+2));

       /* if polygon's normal faces away from the screen, or is perpendicular, ignore it */

#ifdef DRAWDEBUG
       printf("c0->x = %lx c0->y = %lx\n",c0->x,c0->y); 
       printf("c1->x = %lx c1->y = %lx\n",c1->x,c1->y); 
       printf("c2->x = %lx c2->y = %lx\n",c2->x,c2->y); 
#endif

       /* fine clipping */

       if (((smuls(((c1->x)-(c0->x)),((c2->y)-(c1->y))))-(smuls(((c2->x)-(c1->x)),((c1->y)-(c0->y))))) >= 0)
       {
      nextcolor++;
      nextn++;
      nextp = (nextp+((*np)->vertexcount));
      continue;
       }

       /* illumination */

#ifndef FIXEDILLUMINATION

       bright = (((-(((*nextn)->x+(*nextn)->y))>>1)+(0x4000))>>11);
#else

       bright = (WORD)*nextcolor;
#endif
       /* ceiling */

       bright = (bright > 0xF)?0xF:bright;

#ifdef DRAWDEBUG
       printf("poly %lx: bright = %lx\n",polycount,bright);
#endif

            for(vc = 0; vc < (*np)->vertexcount; vc++)
       {
      WORD x,y;
#ifdef DRAWDEBUG
      printf("vertex %lx : (thisobjectinfo->objectbufpoints+poff) = %lx\n",vc,*nextp);
#endif

#ifdef DRAWDEBUG
      printf("(thisobjectinfo->objectbufpoints+poff)->x = %lx\n",(*nextp)->x);
      printf("(thisobjectinfo->objectbufpoints+poff)->y = %lx\n",(*nextp)->y);
      printf("(thisobjectinfo->objectbufpoints+poff)->z = %lx\n",(*nextp)->z);
#endif

      /* draw stuff in */

#ifdef DRAWDEBUG
      printf("SetAPen = bright\n");
#endif
      SetAPen(rp[frametoggle ^ 0x0001],bright);

      if(vc == 0)
      {

          /* open this polygon */
#ifdef DRAWDEBUG
          printf("call areamove...\n");
#endif
          x = (((*nextp)->x)+(TMPWIDTH>>1));
          y = (((*nextp)->y)+(TMPHEIGHT>>1));

          if (x<0) x = 0;
          if (y<0) y = 0;
          if (x>TMPWIDTH-1) x = TMPWIDTH-1;
          if (y>TMPHEIGHT-1) y = TMPHEIGHT-1;

          x -= ( ( TMPWIDTH  - (window->RPort->BitMap->BytesPerRow<<3) ) >> 1 );
          y -= ( ( TMPHEIGHT - (window->RPort->BitMap->Rows) ) >> 1 );

          firstx = x;
          firsty = y;

          /* move into the raster that we're NOT subdisplaying */

#ifndef FIXEDILLUMINATION
          if( (lastn != *nextn) && (endflag) )
          {
              AreaEnd(rp[frametoggle ^ 0x0001]);
         endflag = FALSE;
          }
#endif

          AreaMove(rp[frametoggle ^ 0x0001],x,y);

      }
      else
      {

          /* continue this polygon */
#ifdef DRAWDEBUG
          printf("call areadraw...\n");
#endif
          x = (((*nextp)->x)+(TMPWIDTH>>1));
          y = (((*nextp)->y)+(TMPHEIGHT>>1));

          if (x<0) x = 0;
          if (y<0) y = 0;
          if (x>TMPWIDTH-1) x = TMPWIDTH-1;
          if (y>TMPHEIGHT-1) y = TMPHEIGHT-1;

          x -= ( ( TMPWIDTH  - (window->RPort->BitMap->BytesPerRow<<3) ) >> 1 );
          y -= ( ( TMPHEIGHT - (window->RPort->BitMap->Rows) ) >> 1 );

          /* draw into the raster that we're NOT subdisplaying */

          AreaDraw(rp[frametoggle ^ 0x0001],x,y);

      }

      /* increment the nextp pointer */

      nextp++;

        }

       /* close this polygon */

#ifdef DRAWDEBUG
       printf("call areaend...\n");
#endif
       /* end raster that we're NOT subdisplaying (or continue collecting polygons) */

       /* last polygon subdisplayed is this one */

       lastn = *nextn;

#ifndef FIXEDILLUMINATION
       if(lastn  == *(nextn+1))
       {
      /* last polygon subdisplayed has same normal as next polygon to be subdisplayed */

#ifdef DRAWDEBUG
      printf("last poly subdisplayed has same normal as next polygon to be subdisplayed...draw\n");
#endif
      /* draw, but do not terminate this polygon in this sequence */

      /* note : need graphics 28.5 or greater to do following trick ! */

      AreaDraw(rp[frametoggle ^ 0x0001],firstx,firsty);
      endflag = TRUE;

      /* if graphics 28.4 or less  do this standard thing */

      /* AreaEnd(rp[frametoggle ^ 0x0001]); */
      /* endflag = FALSE; */
       }
       else
       {
      /* last polygon subdisplayed has different normal from next polygon to be subdisplayed */

#ifdef DRAWDEBUG
      printf("last poly subdisplayed has deffernt normal from next polygon to be subdisplayed...end\n");
#endif
      /* terminate this polygon sequence */

      AreaEnd(rp[frametoggle ^ 0x0001]);
      endflag = FALSE;

       }
#else
       {
      /* terminate this polygon sequence */

      AreaEnd(rp[frametoggle ^ 0x0001]);
      endflag = FALSE;

       }
#endif

       /* increment nextcolor, nextn pointers */

       nextcolor++;
       nextn++;
       
   }

   if(endflag)
   {
       /* terminate series of "same normal" polygons after polyloop exit */

#ifdef DRAWDEBUG
       printf("close last polygon in series...\n");
#endif
       AreaEnd(rp[frametoggle ^ 0x0001]);
   }
   
    }

    thisobjectinfo = thisobjectinfo->nextobjectinfo;

    } /* end while (thisobject) */

}
/* END OF PROCESSING ALL THE OBJECTS */
/***************************************************************/