ftp.nice.ch/pub/next/graphics/3d/geomview.1.4.1.s.tar.gz#/Geomview/src/lib/mg/ri/mgri.c

This is mgri.c in view mode; [Download] [Up]

#include "mgriP.h"
#include "mgrishade.h"
#include <stdio.h>
#include <sys/types.h>
#include <stdlib.h>
#import <appkit/appkit.h>
#include <sys/time.h>
#include <sys/resource.h>		/* For enlarging stack size */

mgcontext * mgri_ctxcreate(int a1, ...);
void	    mgri_ctxset( int a1, ...  );
int	    mgri_feature( int feature );
void	    mgri_ctxdelete( mgcontext *ctx );
int	    mgri_ctxget( int attr, void* valueptr );
int	    mgri_ctxselect( mgcontext *ctx );
void	    mgri_sync( void );
void	    mgri_worldbegin( void );
void	    mgri_worldend( void );
void	    mgri_reshapeviewport( void );
void	    mgri_identity( void );
void	    mgri_transform( Transform T );
void	    mgri_pushtransform( void );
void	    mgri_poptransform( void );
void	    mgri_gettransform( Transform T );
void	    mgri_settransform( Transform T );
void	    mgri_material( struct mgastk *mastk, int merge );
int	    mgri_pushappearance( void );
int	    mgri_popappearance( void );
Appearance  *mgri_setappearance( Appearance* app, int merge );
Appearance  *mgri_getappearance( void );
int	    mgri_setcamera( Camera* cam );
mgricontext *mgri_newcontext( mgricontext *ctx );

extern void  mgri_polygon();
extern void  mgri_mesh();
extern void  mgri_line();
extern void  mgri_polyline();
extern void  mgri_polylist();

void _mgri_ctxset(int a1, va_list *alist);

extern int mgri_nxwindow(int x, int y, int xsize, int ysize,
			char *name, int noborder, unsigned int *globalNum);
extern void mgri_closewindow(mgricontext *thectx);
extern void mgri_display();
extern void mgri_getnxrect(float *f);
extern void mgri_clear();
extern void mgri_flush();
extern RtPointer mgri_vieworigin();
extern void mgri_startdebugcontext();
extern void mgri_stopdebugcontext();
extern void mgri_errorhandler();

WnWindow *mgriwindow(WnWindow *win);

struct mgfuncs mgrifuncs = {
  MGD_RI,
  mgdevice_RI,
  mgri_feature,
  (mgcontext *(*)())mgri_ctxcreate,
  mgri_ctxdelete,
  (void (*)())mgri_ctxset,
  mgri_ctxget,
  mgri_ctxselect,
  mgri_sync,
  mgri_worldbegin,
  mgri_worldend,
  mgri_reshapeviewport,
  mgri_settransform,
  mgri_gettransform,
  mgri_identity,
  mgri_transform,
  mgri_pushtransform,
  mgri_poptransform,
  mgri_pushappearance,
  mgri_popappearance,
  mgri_setappearance,
  mgri_getappearance,
  mgri_setcamera,
  mgri_polygon,
  mgri_polylist,
  mgri_mesh,
  mgri_line,
  mgri_polyline,
  mg_quads,
  mg_bezier,
  };

/* for debugging simplification: */
static mgricontext *MGRI;

/* our renderman<->oogl z axis flip transform */
Transform cam2ri = {{1, 0,0,0}, {0,1,0,0}, {0,0,-1,0},{0,0,0,1}};

/* our QRMAN interface buffers */
RtPoint *ript;		/* points */
RtColor *ricolor;	/* rgb color */
RtPoint *rinormal;	/* normals */
int *rippi;		/* PointsPolygon polygon index array */
int rippis;		/* PointsPolygon polygon index array size */
int *ripvi;		/* PointsPolygon vertex index array */
int ripvis;		/* PointsPolygon vertex index array size */

RtPoint *plpt;		/* verticees for buffered polylines */
RtColor *plcolor;	/* colors for buffered polylines */
RtPoint *plp;  		/* vertices */
RtColor *plc;  		/* colors */
int *plvca;        	/* polyline vertex count array */
int *plvia;    		/* vertex index array */

int
mgdevice_RI()
{
  _mgf = mgrifuncs;
  if (_mgc != NULL && _mgc->devno != MGD_RI)
    _mgc = NULL;

  return(0);
}

/*-----------------------------------------------------------------------
 * Function:	mgri_ctxcreate
 * Date:	Thu Jul 18 18:55:18 1991
 * Author:	mbp
 * Notes:	see mg.doc for rest of spec
 */
mgcontext *
mgri_ctxcreate(int a1, ...)
{
  va_list alist;
  struct rlimit rl;

   /* Since we depend on alloca() for copying some OOGL data structures,
    * ensure we're allowed a reasonable amount of stack space.
    * NeXT default seems to be .5MB, not enough.
    */
  getrlimit(RLIMIT_STACK, &rl);
  if(rl.rlim_cur < 24*1024*1024) {
    rl.rlim_cur = 24*1024*1024;
    setrlimit(RLIMIT_STACK, &rl);
  }

  _mgc =
    (mgcontext*)(MGRI = mgri_newcontext( OOGLNewE(mgricontext, "mgri_ctxcreate") ));

  /* Ensure some sensible default Window */
  WnSet(_mgc->win, WN_XSIZE, 500, WN_YSIZE, 400, WN_END);

  va_start(alist, a1);
  _mgri_ctxset(a1, &alist);
  va_end(alist);
  return _mgc;
}

/*-----------------------------------------------------------------------
 * Function:	_mgri_ctxset
 * Description:	internal ctxset routine
 * Args:	a1: first attribute
 *		*alist: rest of attribute-value list
 * Returns:	nothing
 * Author:	mbp, wisdom
 * Date:	Fri Sep 20 11:08:13 1991
 * Notes:	mgri_ctxcreate() and mgri_ctxset() call this to actually
 *		parse and interpret the attribute list.
 */
void
_mgri_ctxset(int a1, va_list *alist)
{
  int attr;
  char *name;
  
  for (attr = a1; attr != MG_END; attr = va_arg (*alist, int)) {
    switch (attr) {
    case MG_ApSet:
      {
	Appearance *ap;

	ap = _ApSet(NULL, va_arg(*alist, int), alist);
	mgri_setappearance(ap, MG_MERGE);
	ApDelete(ap);
      }
      break;
    case MG_WnSet:
	_WnSet( _mgc->win, va_arg(*alist, int), alist);
	if(_mgc->shown) {
	  WnGet(_mgc->win, WN_NAME, &name);
	  if(_mgric->born)
	      if(name)
		  [(id)_mgric->nxwindow setTitle:name]; //wintitle(name);
	  }
        break;
    case MG_CamSet:
      _CamSet( _mgc->cam, va_arg(*alist, int), alist);
      break;
    case MG_APPEAR:
      mgsetappearance(va_arg(*alist, Appearance *), MG_SET);
      break;
    case MG_WINDOW:
      if (_mgc->win) WnDelete(_mgc->win);
      _mgc->win = va_arg(*alist, WnWindow*);
      RefIncr((Ref*) (_mgc->win));
      break;
    case MG_CAMERA:
      mgri_setcamera( va_arg(*alist, Camera*) );
      break;
    case MG_SETOPTIONS:
      _mgc->opts |= va_arg(*alist, int);
    case MG_UNSETOPTIONS:
      _mgc->opts &= ~va_arg(*alist, int);
      break;
    case MG_SHOW:
      _mgc->shown = va_arg(*alist, int);
      break;
    case MG_PARENT:
      _mgc->parent = va_arg(*alist, mgcontext*);
      break;
    case MG_BACKGROUND:
      _mgc->background = *va_arg(*alist, ColorA*);
      break;
    case MG_ZNUDGE:
      _mgc->zfnudge = va_arg(*alist, double);
      break;

    case MG_SPACE:
    {
	int space = va_arg(*alist, int);
	_mgc->space = space; 
	if(! ((space & TM_EUCLIDEAN) || (space & TM_HYPERBOLIC) ||
	     (space & TM_SPHERICAL)))
	fprintf(stderr, "_mgri_ctxset: Illegal space value %1d\n", space);
   }
   break;

    case MG_SHADER: mgri_setshader( va_arg(*alist, mgshadefunc) ); break;
    case MG_SHADERDATA: _mgc->astk->shaderdata = va_arg(*alist, void*); break;
    case MG_NDINFO: _mgc->NDinfo = va_arg(*alist, void *); break;
    case MG_NDMAP:  _mgc->NDmap = va_arg(*alist, mgmapfunc); break;

    /* NeXT specific */
    case MG_NXWINDOW:
        _mgric->nxwindow = va_arg(*alist, char *);
	break;	
    case MG_NXVIEW:
        _mgric->nxview = va_arg(*alist, char *);
	break;
    case MG_RICALLBACK:
        _mgric->callback = va_arg(*alist, void *);
	break;
    case MG_RISTANDALONE:
        _mgric->standalone = va_arg(*alist, int);
	break;
    default:
    	OOGLError (0, "_mgri_ctxset: undefined option: %d\n", attr);
    	return;
    	break;
    }
  }

  if (_mgc->shown && !_mgric->born) {

    /* open the window */
    mgriwindow(_mgc->win);

    /* rib state is *not* in accordance with appearance state:
       don't set the appearance until worldbegin time */

  }
}


/*-----------------------------------------------------------------------
 * Function:	mgri_ctxget
 * Description:	get a context attribute value
 * Args:	attr: the attribute to get
 *		value: place to write attr's value
 * Returns:	1 for success; -1 if attr is invalid
 * Author:	mbp, wisdom
 * Date:	Fri Sep 20 11:50:25 1991
 * Notes:
 */
int
mgri_ctxget(int attr, void* value)
{
#define VALUE(type) ((type*)value)

  switch (attr) {

  /* Attributes common to all MG contexts: */
  case MG_APPEAR:
    *VALUE(Appearance*) = &(_mgc->astk->ap);
    break;
  case MG_CAMERA:
    *VALUE(Camera*) = _mgc->cam;
    break;
  case  MG_WINDOW:
    if(_mgric->born) {
      WnPosition wp;
      float theRect[4]; /* origin.x, origin.y, size.width, size.height */

      mgri_getnxrect(theRect);
      
      wp.xmin = theRect[0];
      wp.xmax = theRect[0]+theRect[2]-1;
      wp.ymin = theRect[1];
      wp.ymax = theRect[1]+theRect[3]-1;
      WnSet(_mgc->win, WN_CURPOS, &wp, WN_END);
    }
    *VALUE(WnWindow*) = _mgc->win;
    break;
  case MG_PARENT:
    *VALUE(mgcontext*) = _mgc->parent;
    break;
  case MG_SETOPTIONS:
  case MG_UNSETOPTIONS:
    *VALUE(int) = _mgc->opts;
    break;
  case MG_BACKGROUND:
    *VALUE(ColorA) = _mgc->background;
    break;
  case MG_SPACE:
    *VALUE(int) = _mgc->space;
    break;
  case MG_ZNUDGE:
    *VALUE(float) = _mgc->zfnudge;
    break;
  case MG_SHADER: *VALUE(mgshadefunc) = _mgc->astk->shader; break;
  case MG_SHADERDATA: *VALUE(void *) = _mgc->astk->shaderdata; break;
  case MG_NDINFO: *VALUE(void *) = _mgc->NDinfo; break;
  case MG_NDMAP: *VALUE(mgmapfunc) = _mgc->NDmap; break;
    
  /* Attributes specific to RI contexts: */
  case MG_RIWINID:
    *VALUE(int) = _mgric->win;
    break;
    
  /* specific to NeXT */
  case MG_NXWINDOW:
     *VALUE(char *) = _mgric->nxwindow;
     break;
  case MG_NXVIEW:
     *VALUE(char *) = _mgric->nxview;
     break;
  case MG_RICALLBACK:
     *VALUE(void *) = _mgric->callback;
     break;
  case MG_RISTANDALONE:
     *VALUE(int) = _mgric->standalone;
     break;
  default:
    OOGLError (0, "mgri_ctxget: undefined option: %d\n", attr);
    return -1;

  }
  return 1;

#undef VALUE
}

/*-----------------------------------------------------------------------
 * Function:	mgriwindow
 * Description:	create an RI window
 * Args:	*win: the WnWindow structure to realize
 * Returns:	win if success, NULL if not
 * Author:	wisdom, gunn
 * Date:	Thu May 21 15:04:42 CDT 1992
 * Notes:	makes the RI calls necessary to create an RI window
 *		  corresponding to *win.
 */
WnWindow *
mgriwindow(WnWindow *win)
{
  WnPosition pos;
  int xsize, ysize, flag, reconstrain;
  char *name;
  char gver[80];
  double pxloc, pyloc, pxsize, pysize;
  int noborder=0;
  unsigned int globalNum;
   
    /* interpret window ...*/
        
    if(WnGet(win, WN_PREFPOS, (void*)&pos) == 1){
	pxloc = pos.xmin;
	pyloc = pos.ymin;
	pxsize = pos.xmax - pos.xmin;
	pysize = pos.ymax - pos.ymin;
    } else if ((WnGet(win, WN_XSIZE, (void*)&xsize) == 1)
    && (WnGet(win, WN_YSIZE, (void*)&ysize) == 1) ) {
	pxsize = xsize;
	pysize = ysize;
    }
    
    WnGet(win, WN_NOBORDER, &flag);
    if (flag) noborder=1;
    
    WnGet(win, WN_NAME, &name);
    
    mgri_nxwindow(pxloc, pyloc, pxsize, pysize, name, noborder, &globalNum);
    
    /* creat the renderman context */
    _mgric->qrmContext = RiBegin(RI_NULL, RI_NULL);
    RiHider(RI_HIDDEN,RI_NULL);
    RiErrorHandler((RtFunc)mgri_errorhandler);
    _mgric->windowresource = RiResource("Generic", RI_IMAGE,
        RI_WINDOWID, (RtPointer)&globalNum, RI_NULL);
    
    _mgric->born = 1;
    return(win);
}

/*-----------------------------------------------------------------------
 * Function:	mgri_ctxset
 * Description:	set some context attributes
 * Args:	a1, ...: list of attribute-value pairs
 * Returns:	nothing
 * Author:	mbp
 * Date:	Fri Sep 20 12:00:18 1991
 */
void mgri_ctxset( int a1, ...  )
{
  va_list alist;

  va_start( alist, a1 );
  _mgri_ctxset(a1, &alist);
  va_end(alist);
}


/*-----------------------------------------------------------------------
 * Function:	mgri_feature
 * Description:	report whether the GL device has a particular feature
 * Args:	feature: the feature to report on
 * Returns:	an int giving info about feature
 * Author:	mbp
 * Date:	Fri Sep 20 12:00:58 1991
 * Notes:	-1 means the feature is not present.
 *
 *		NO FEATURES SUPPORTED YET.  ALWAYS RETURNS -1.
 */
int mgri_feature( int feature )
{
  return(-1);
}

/*-----------------------------------------------------------------------
 * Function:	mgri_ctxdelete
 * Description:	delete a GL context
 * Args:	*ctx: context to delete
 * Returns:	nothing
 * Author:	slevy
 * Date:	Tue Nov 12 10:29:04 CST 1991
 * Notes:	Deleting the current context leaves the current-context
 *		pointer set to NULL.
 */
void mgri_ctxdelete( mgcontext *ctx )
{
  if(ctx->devno != MGD_RI) {
    mgcontext *was = _mgc;
    mgctxselect(ctx);
    mgctxdelete(ctx);
    if(was != ctx)
	mgctxselect(was);
  } else {
    if(((mgricontext *)ctx)->born) {
	mgricontext *current = _mgric;
	RiContext(((mgricontext *)ctx)->qrmContext, RI_NULL);
	RiEnd();
	/* no context active now, choose what was active if we can */
	if(current!=((mgricontext *)ctx))
	    RiContext(current->qrmContext, RI_NULL);
	mgri_closewindow((mgricontext *)ctx);
    }
    mg_ctxdelete(ctx);
    if(ctx == _mgc)
	_mgc = NULL;
  }
}

/*-----------------------------------------------------------------------
 * Function:	mgri_ctxselect
 * Description:	select an RI context --- make it current
 * Args:	*ctx: the context to become current
 * Returns:	0
 * Author:	mbp, wisdom
 * Date:	Fri Sep 20 12:04:41 1991
 */
int
mgri_ctxselect( mgcontext *ctx )
{
  if(ctx == NULL || ctx->devno != MGD_RI) {
    return mg_ctxselect(ctx);
  }

  _mgc = ctx;
  MGRI = (mgricontext *)ctx;

  if(_mgric->born)
     RiContext(_mgric->qrmContext,RI_NULL);

  return(0);
}

/*-----------------------------------------------------------------------
 * Function:	mgri_sync
 * Description:	flush buffered commands
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Wed May 13 14:34:02 CDT 1992
 * Notes:
 */
void
mgri_sync( void )
{
    /* qrman docs say RI_WAIT performs a flush, but net reports*/
    /* indicate that this is not the case, so we flush before  */
    /* we wait. this may not be a necessary for NS3.1 or higher*/

    RiSynchronize(RI_FLUSH);
    RiSynchronize(RI_WAIT);

    mgri_flush();
}

/*-----------------------------------------------------------------------
 * Function:	mgri_worldbegin
 * Description:	prepare to draw a frame
 * Returns:	nothing
 * Author:	gunn, wisdom
 * Date:	Sat Mar  7 16:28:35 GMT-0600 1992
 */
void
mgri_worldbegin( void )
{
  int persp;
  RtFloat fov, aspect, near, far;
  WnWindow *win;
  WnPosition wp;
  int xsize, ysize;
  Transform T;
  
  static Transform *O2SP, *W2SP;	/* to ease gdb'ing */

  /* NOTE 1: Regarding cam2ri transform; in mgrib, we use an identity matrix
   * with a -1 value in the z position to mirror the z axis. QuickRenderman,
   * however, considers this matrix as non isometric (an error). Therefore, we
   * also mirror the y axis (-1 in y pos) to retain the isometric property.
   * reversing the y components of RiScreenWindow from -1,0,1.0 to 1.0,-1.0
   * effectively mirrors that change back, and QRM is happy. sw7/92
   */
   
   /* debug, if necessary */
   if(_mgric->debug) {
       mgri_startdebugcontext();
   }
    /* Interpret Options...(none exist now) */

    /* Interpret Camera ...*/
    
    /* the halfyfield is so confusing that I'm going to ignore it and use fov*/
    /* (gunn) */
    CamGet( _mgc->cam, CAM_ASPECT, &aspect);
    
    /* this may break it */
    WnGet(_mgc->win, WN_CURPOS, &wp);
    xsize = wp.xmax - wp.xmin + 1;
    ysize = wp.ymax - wp.ymin + 1;

    CamGet( _mgc->cam, CAM_NEAR, &near);
    CamGet( _mgc->cam, CAM_FAR, &far);
    
    RiClipping(near, far);

    if(_mgric->debug)
	RiDisplay(_mgric->debugResource, RI_FILE, RI_RGBA,RI_NULL);
    else
	RiDisplay(_mgric->windowresource, RI_FRAMEBUFFER, RI_RGBAZ,
	    RI_ORIGIN, (RtPointer)(_mgric->mgvorigin), RI_NULL);

    RiFrameBegin(1);

    RiFormat(xsize,ysize,1.0);

    RiScreenWindow(-aspect, aspect, -1.0, 1.0);
        
    CamGet( _mgc->cam, CAM_PERSPECTIVE, &persp);
    CamGet( _mgc->cam, CAM_FOV, &fov);
    if(persp) {
	RiProjection("perspective", "fov", &fov, RI_NULL);
    } else {
        RiProjection("orthographic",RI_NULL);
    }
        
    RiTransform(cam2ri); //acts as our initial (twisted) identity matrix

    CamGet(_mgc->cam, CAM_W2C, _mgc->W2C);
    CamGet(_mgc->cam, CAM_C2W, _mgc->C2W);
    _mgric->hascpos = _mgc->xstk->hasinv = 0;
    
    RiConcatTransform(_mgc->W2C);

    /* RiWorldBegin...*/
    mgri_clear();
    RiWorldBegin();

    /* bring ri state into accordance with appearance state */
    {
      Appearance *ap = ApCopy( &(_mgc->astk->ap), NULL );
      mgri_setappearance( ap, MG_SET );
      ApDelete(ap);
    }

    /* Build camera->screen matrix */

    CamView(_mgc->cam, _mgric->W2S);	/* world to {-1 .. +1} cube */
    TmTranslate(T, 1.0, 1.0, 0);
    TmConcat(_mgric->W2S,T, _mgric->W2S); /* world to {0..2, 0..2, -1..+1} */

    mgri_ctxget(MG_WINDOW, &win);		/* Gets size of drawing area */
    WnGet(_mgc->win, WN_XSIZE, &xsize);
    WnGet(_mgc->win, WN_YSIZE, &ysize);


    TmScale(T, (double)xsize*.5, (double)ysize*.5, 1.0);
    TmConcat(_mgric->W2S,T, _mgric->W2S);	 /* world to window */

    TmCopy(_mgric->W2S, _mgric->O2S);	/* initially world == object space */

}

/*-----------------------------------------------------------------------
 * Function:	mgri_worldend
 * Description:	finish drawing a frame
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Sat Mar  7 14:47:40 GMT-0600 1992
 */
void
mgri_worldend( void )
{
    /* check for any remaining buffered polylines */
    if(_mgric->plni) mgri_plflush();

    RiWorldEnd();
    RiFrameEnd();
    mgri_sync();

    /* debugging */
    if(_mgric->debug) mgri_stopdebugcontext();
        
    /* if the main program doesn't use the appkit (standalone=1), then
     * any events are processed here. if events must be processed but mg
     * isn't being called to update the window, mgri_processevents() can be
     * called directly.
     */
 
    /* if necessary, process events */
    if(MGRI->standalone) mgri_processevents();

}

/*-----------------------------------------------------------------------
 * Function:	mgri_reshapeviewport
 * Description:	adjust to a new window size
 * Returns:	nothing
 * Author:	mbp
 * Date:	Fri Sep 20 12:08:30 1991
 * Notes:
 */
void
mgri_reshapeviewport( void )
{
    WnWindow *win;
    WnPosition wp;
    int xsize, ysize;

    mgri_ctxget(MG_WINDOW, &win);	/* Get window; force it to ask
					 * NeXTStep how big the window is
					 */
    WnGet(win, WN_CURPOS, &wp);
    xsize = wp.xmax - wp.xmin + 1;
    ysize = wp.ymax - wp.ymin + 1;

    CamSet(_mgc->cam, CAM_ASPECT, (double)xsize/(double)ysize, CAM_END);

}

/*-----------------------------------------------------------------------
 * Function:	mgri_identity
 * Description:	set the current object xform to identity
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Tue Sep 15 14:24:24 CDT 1992
 * Notes:
 *
 */
void
mgri_identity( void )
{
    if(_mgric->plni) mgri_plflush();
    RiIdentity();
    mg_identity();
}

/*-----------------------------------------------------------------------
 * Function:	mgri_transform
 * Description:	premultiply the object xform by T
 * Args:	T
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Tue Sep 15 14:24:24 CDT 1992
 * Notes:	
 *
 */
void
mgri_transform( Transform T )
{
    if(_mgric->plni) mgri_plflush();
    mg_transform(T);
    RiTransform(_mgc->xstk->T);
     
     _mgric->hascpos = _mgc->xstk->hasinv = 0;

}

/*-----------------------------------------------------------------------
 * Function:	mgri_pushtransform
 * Description:	push the object xform stack
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Tue Sep 15 14:24:24 CDT 1992
 * Notes:	
 *
 */
void
mgri_pushtransform( void )
{
    if(_mgric->plni) mgri_plflush();
    RiTransformBegin();
    mg_pushtransform();
}

/*-----------------------------------------------------------------------
 * Function:	mgri_popransform
 * Description:	pop the object xform stack
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Tue Sep 15 14:24:24 CDT 1992
 * Notes:	
 *
 */
void
mgri_poptransform( void )
{
    if(_mgric->plni) mgri_plflush();
    RiTransformEnd();
    mg_poptransform();
    _mgric->hascpos = 0;
}

/*-----------------------------------------------------------------------
 * Function:	mgri_gettransform
 * Description:	get the current object xform
 * Args:	T: place to write the current object xform
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Tue Sep 15 17:16:35 CDT 1992
 * Notes:	
 *
 */
void
mgri_gettransform( Transform T )
{
    TmCopy(_mgc->xstk->T, T);
}

/*-----------------------------------------------------------------------
 * Function:	mgri_settransform
 * Description:	set the current object xform to T
 * Args:	T
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Tue Sep 15 17:06:51 CDT 1992
 * Notes:	
 *
 */
void
mgri_settransform( Transform T )
{
    if(_mgric->plni) mgri_plflush();
    RiTransform(T);
    mg_settransform( T );

    _mgric->hascpos = _mgc->xstk->hasinv = 0;
    
}

/*-----------------------------------------------------------------------
 * Function:	mgri_pushappearance
 * Description:	push the MG context appearance stack
 * Returns:	nothing
 * Author:	wisdom
 * Date:	Fri Sep 20 12:54:19 1991
 */
int
mgri_pushappearance( void )
{
  mg_pushappearance();
  RiAttributeBegin();
}

/*-----------------------------------------------------------------------
 * Function:	mgri_popappearance
 * Description:	pop the MG context appearance stack
 * Returns:	nothing
 * Author:	munzner? wisdom?
 * Date:	?
 * Note:
 */
int
mgri_popappearance( void )
{
  register struct mgastk *mastk = _mgc->astk;
  register struct mgastk *mastk_next;

  if (! (mastk_next=mastk->next)) {
    OOGLError(0, "mgri_popappearance: appearance stack has only 1 entry.\n");
    return;
  }

  RiAttributeEnd();
  mg_popappearance();


}

/*-----------------------------------------------------------------------
 * Function:	mgri_setappearance
 * Author:	munzner, mbp
 * Date:	Wed Aug  7 01:08:07 1991
 * Notes:
 */
Appearance *
mgri_setappearance( Appearance* ap, int mergeflag )
{
  int changed, mat_changed, lng_changed;
  struct mgastk *mastk = _mgc->astk;
  Appearance *ma;
  static float nullarray[] = { 0.0 };

  ma = &(mastk->ap);

  /* Decide what changes */
  if (mergeflag == MG_MERGE) {
    changed = ap->valid & ~(ma->override &~ ap->override);
    mat_changed =
      ap->mat ? ap->mat->valid & ~(ma->mat->override &~ ap->mat->override) : 0;
    lng_changed =
      ap->lighting ? ap->lighting->valid &
		~(ma->lighting->override &~ ap->lighting->override) : 0;
  }
  else {
    changed = ap->valid;
    mat_changed = ap->mat ? ap->mat->valid : 0;
    lng_changed = ap->lighting ? ap->lighting->valid : 0;
  }

  mg_setappearance( ap, mergeflag );

  /* here is where everything gets set (sort of) */

  if(_mgric->born) {
    mgri_appearance( mastk, changed);

    /* interpret lights ... */
    mgri_lighting(_mgc->astk, lng_changed);

    if (ap->mat) mgri_material( mastk, mat_changed );
  }

}


/*-----------------------------------------------------------------------
 * Function:	mgri_getappearance
 * Description:	return a ptr to current appearance
 * Returns:	ptr to current appearance
 * Author:	mbp
 * Date:	Fri Sep 20 13:00:41 1991
 * Notes:	Applications should not modify the returned appearance
 *		in any way.
 */
Appearance *
mgri_getappearance()
{
    return &(_mgc->astk->ap);
}

/*-----------------------------------------------------------------------
 * Function:	mgri_setcamera
 * Description:	set the context's camera (pointer)
 * Args:	*cam: the camera to use
 * Returns:	nothing
 * Author:	mbp
 * Date:	Fri Sep 20 13:07:31 1991
 * Notes:	The context stores a pointer to the camera, not a copy
 *		of it.
 */
int
mgri_setcamera( Camera* cam )
{
  if (_mgc->cam) CamDelete(_mgc->cam);
  _mgc->cam = cam;
  RefIncr((Ref*) cam);
}

/*-----------------------------------------------------------------------
 * Function:	mgri_newcontext
 * Description:	initialize a new mgricontext structure
 * Args:	*ctx: the struct to initialize
 * Returns:	ctx
 * Author:	wisdom (mbp)
 * Date:	Fri Nov  5 14:29:45 CST 1993
 */
mgricontext *
mgri_newcontext( mgricontext *ctx )
{
  static int first = 1; /* mgri must do housekeeping first time around */
			/* does this belong in mgdevice_RI() ?         */
  
  mg_newcontext(&(ctx->mgctx));
  ctx->mgctx.devfuncs = &mgrifuncs;
  ctx->mgctx.devno = MGD_RI;
  ctx->mgctx.astk->ap_seq = 1;
  ctx->mgctx.astk->mat_seq = 1;
  ctx->mgctx.astk->light_seq = 1;
  ctx->born = 0;
  ctx->dying = 0;
  ctx->drawsfaces = 0;
  ctx->nxwindow = 0;
  ctx->nxview = 0;
  ctx->callback = NULL;
  TmIdentity( ctx->W2C );
  TmIdentity( ctx->C2W );

#ifdef NS_3_X_FAST
  ctx->polymode = MGRI_POINTSPOLYGONS;
  ctx->fflushlimit = ctx->lflushlimit = 1e4;
  ctx->plbuffsize = 1e4;
#endif
  
#ifdef NS_3_0_SLOW
  ctx->polymode = MGRI_DEVIDEDPOLYLIST;
  ctx->plbuffsize = 400;
#endif

  if(first) {
    /* perform general mgri housekeeping for initial context */

    first = 0;
  
    /* setup the scratch buffers */
    ript = (RtPoint *)malloc(SCRATCHSIZE*sizeof(RtPoint));
    ricolor = (RtColor *)malloc(SCRATCHSIZE*sizeof(RtColor));
    rinormal = (RtPoint *)malloc(SCRATCHSIZE*sizeof(RtPoint));
    rippis = 1000; /* start at 1000 polygons limit - will adjust if needed */
    rippi = (int *)malloc(rippis*sizeof(int));
    ripvis = rippis*6;
    ripvi = (int *)malloc(ripvis*sizeof(int));

    plp = (RtPoint *)malloc((ctx->plbuffsize+100)*sizeof(RtPoint));
    plc = (RtColor *)malloc((ctx->plbuffsize+100)*sizeof(RtColor));
    plvca = (int *)malloc(ctx->plbuffsize*sizeof(int));
    plvia = (int *)malloc((ctx->plbuffsize+100)*sizeof(int));
  }
  
  ctx->debug = 0;
  ctx->debugContext = 0;
  ctx->plni = 0;
  ctx->plvi = 0;
  
  return ctx;
}

/*-----------------------------------------------------------------------
 * Function:	mgri_findctx
 * Description: Given an nxwindow , returns the associated mg context.
 * Returns:	mgcontext * for success, NULL if none exists.
 * Author:	wisdom
 * Date:	Wed May 20 19:22:53 CDT 1992
 * Notes:	This is a public routine.
 */
mgcontext *
mgri_findctx(char *winid)
{
  register struct mgcontext *mgc;

  for(mgc = _mgclist; mgc != NULL; mgc = mgc->next) {
    if(mgc->devno == MGD_RI && ((mgricontext *)mgc)->nxwindow == winid)
	return mgc;
  }
  return NULL;
}

These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.