#include <rpc/rpc.h>
#include <limits.h>
#include "prog.h"
#include "progspec.h"
#ifdef RAYSHADE40

void reverse_objlist()
{      Geom *tmp,*tmpnext,*oldobj;
       if(!Objects)
               return;
       if(!Objects->next)
               return;
       tmp=Objects;
       oldobj=NULL;
       while(tmp){
               tmpnext=tmp->next;
               tmp->next=oldobj;
               oldobj=tmp;
               Objects=tmp;
               tmp=tmpnext;
       }
}

ExprTab ExprTable[]={
               {NULLEXPR,NULL},
               {SUMEXPR,SumExpr},
               {DIFFEXPR,DiffExpr},
               {MULTEXPR,MultExpr},
               {DIVIDEEXPR,DivideExpr},
               {MODEXPR, ModExpr},
               {NEGATEEXPR,NegateExpr},
               {LINEARTIMEEXPR,LinearTime},
               {COSEXPR,cos},
               {SINEXPR,sin},
               {TANEXPR,tan},
               {SQRTEXPR,sqrt},
               {ACOSEXPR,acos},
               {ASINEXPR,asin},
               {ATANEXPR,atan},
               {HYPOTEXPR,hypot},
               {EXPRTYPEEND,NULL}
       };

bool_t
xdr_rpc_Expr_Ptr(xdrs, objp)
        XDR *xdrs;
        rpc_Expr_Ptr *objp;
{
        if (!xdr_pointer(xdrs, objp, sizeof(rpc_Expr), xdr_rpc_Expr)) {
                return (FALSE);
        }
        return (TRUE);
}

bool_t
xdr_rpc_Expr(xdrs, objp)
        XDR *xdrs;
        rpc_Expr *objp;
{ int i;
        if (!xdr_short(xdrs, &objp->type)) {
                return (FALSE);
        }
        if (!xdr_short(xdrs, &objp->timevary)) {
                return (FALSE);
        }
        if (!xdr_short(xdrs, &objp->symtab)) {
                return (FALSE);
        }
        if (!xdr_short(xdrs, &objp->nparams)) {
                return (FALSE);
        }
        if (!xdr_double(xdrs, &objp->value)) {
                return (FALSE);
        }
        if (!xdr_double(xdrs, &objp->timenow)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_ENCODE){
               for(i=0;EXPRTYPEEND;i++){
                       if(objp->function==ExprTable[i].function){
                               break;
                       }
               }
                if(i>=EXPRTYPEEND){
                       fprintf(stderr,"encoding unknown ExprType\n");
                       exit(1);
                }
               if(!xdr_long(xdrs,&i)){
                       return (FALSE);
               }
               if((!objp->nparams)|| (!objp->params) ){
                       return(TRUE);
               }
       }
       if(xdrs->x_op==XDR_DECODE){
               if(!xdr_long(xdrs,&i)){
                      return (FALSE);
               }
               if(i>=EXPRTYPEEND){
                       fprintf(stderr,"decoding unknown ExprType\n");
                       exit(1);
               }
               objp->function=ExprTable[i].function;
               if((!objp->nparams)){
                       return(TRUE);
               }
               objp->params=NULL;
       }
       i=objp->nparams;
       if (!xdr_array(xdrs,
                       (char **)&objp->params,
                       (int*)&i,
                       5,
                       sizeof(rpc_Expr_Ptr),
                       xdr_rpc_Expr_Ptr )) return(FALSE);
       objp->nparams=i;
/*printf("coded expr %d %d\n",objp->nparams,objp->function);*/
return (TRUE);
}

bool_t
xdr_rpc_SymtabEntry(xdrs, objp)
        XDR *xdrs;
        rpc_SymtabEntry *objp;
{
        long i;
        if (!xdr_nm(xdrs, &objp->name)) {
                return (FALSE);
        }
        if(!xdr_int(xdrs,&objp->type)){
                return(FALSE);
        }

        switch (objp->type) {
               case FLOAT_EXPR:
                  if(!xdr_pointer(xdrs,(char**)&objp->value.expr,sizeof(rpc_Expr),xdr_rpc_Expr)){
                       return(FALSE);
                  }
                  break;

               case BUILTIN_EXPR:
                       if(xdrs->x_op==XDR_ENCODE){
                         for(i=0;i<EXPRTYPEEND;i++){
                            if(ExprTable[i].function==objp->value.fp)
                               break;
                         }
                         if(i>=EXPRTYPEEND){
                               fprintf(stderr,"encoding unknown symtab value function\n");
                               exit(1);
                         }
                         if(!xdr_long(xdrs,&i)){
                               return(FALSE);
                         }
                       }
                       if(xdrs->x_op==XDR_DECODE){
                         if(!xdr_long(xdrs,&i)){
                               return(FALSE);
                         }
                         if(i>=EXPRTYPEEND){
                               fprintf(stderr,"encoding unknown symtab value function\n");
                               exit(1);
                         }
                         objp->value.fp=ExprTable[i].function;
                       }
                 break;

               default:
                  fprintf(stderr,"coding unknown Symtab Value\n");
                  exit(1);
                  break;
        }
        if (!xdr_int(xdrs, &objp->timevary)) {
                return (FALSE);
        }
        if (!xdr_int(xdrs, &objp->params)) {
                return (FALSE);
        }
        if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(rpc_SymtabEntry), xdr_rpc_SymtabEntry)) {
                return (FALSE);
        }
        return (TRUE);
}
bool_t
xdr_rpc_uSurface_Ptr(xdrs, objp)
        XDR *xdrs;
        Surface **objp;
{
        Surface *tmp;
        char *s;
        tmp=(*objp);
        s=NULL;
        if(xdrs->x_op==XDR_ENCODE) {
               if(tmp)
                       s=tmp->name;
               if (!xdr_nm(xdrs,&s)) {
                       return (FALSE);
               }
        }
        if(xdrs->x_op==XDR_DECODE){
               if(!xdr_nm(xdrs,&s)) {
                       return(FALSE);
               }
        if(s)
               (*objp)=SurfaceGetNamed(s);
        else
              *objp=NULL;
        }
        return (TRUE);
}

TransMethods * NullTrans();
TransMethods * NullTrans(){return NULL;}
TransTab TransTable[]={
               {NULLTRANS,           NullTrans,       xdr_void,  NULL},
               {SCALETRANS,          ScaleMethods,    xdr_rpc_Vector,sizeof(rpc_Vector) },
               {TRANSLATETRANS,      TranslateMethods,xdr_rpc_Vector,sizeof(rpc_Vector) },
               {ROTATETRANS,         RotateMethods,   xdr_rpc_Rotate,sizeof(rpc_Rotate) },
               {TRANSTYPEEND,          NULL,          xdr_void,    NULL}
        };

bool_t
xdr_rpc_Trans(xdrs, objp)
        XDR *xdrs;
        rpc_Trans *objp;

{       u_long k,i,numoffassocs,l; Float *a; rpc_ExprAssoc tmpassoc,*curassoc;
        if (!xdr_short(xdrs, &objp->animated)) {
                return (FALSE);
        }
        if (!xdr_rpc_RSMatrix(xdrs, &objp->trans)) {
                return (FALSE);
        }
        if (!xdr_rpc_RSMatrix(xdrs, &objp->itrans)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_ENCODE) {
               for(i=0;i<=TRANSTYPEEND;i++)
                       if(objp->methods==TransTable[i].methods())
                               break;
               if(i>=TRANSTYPEEND){
                       fprintf(stderr,"unknown TransType %8x transl %8x rot %8x scal %8x\n",objp->methods,
                                                                           TranslateMethods(),
                                                                           RotateMethods(),
                                                                          ScaleMethods());
                       exit(1);
               }
              if(!xdr_long(xdrs,&TransTable[i].type)){
                      return (FALSE);
               }
               if(!xdr_pointer(xdrs,&objp->tr,TransTable[i].size,TransTable[i].xdrproc)){
                       return(FALSE);
               }
              l=0;	
              if(i==ROTATETRANS)
                       l=4;
               if(i==TRANSLATETRANS || i==SCALETRANS)
                       l=3;
               numoffassocs=NULL;curassoc = (rpc_ExprAssoc*) objp->assoc;
               while(curassoc){
                       numoffassocs++;
                       curassoc=curassoc->next;
               }
               if(!xdr_u_long(xdrs,&numoffassocs)){
                      return(FALSE);
               }
               curassoc=(rpc_ExprAssoc*)objp->assoc;
               while(numoffassocs--){
                       bcopy(curassoc,&tmpassoc,sizeof(rpc_ExprAssoc));
                       a=(Float*)objp->tr;
                       for(k=0;k<l;k++){
                               if(curassoc->lhs==(u_long)&a[k]){
                                      tmpassoc.lhs=k;
                                       break;
                               }
                       }
                       if(k==l){
                               fprintf(stderr," ExprAssoc has no lhs\n");
                               exit(1);
                       }
                       if(!xdr_rpc_ExprAssoc(xdrs,&tmpassoc)){
                               return (FALSE);
                       }
                       curassoc=curassoc->next;
               }
       }
       if(xdrs->x_op==XDR_DECODE) {
               if(!xdr_u_long(xdrs,&i)){
                       return (FALSE);
               }
               if(i>TRANSTYPEEND){
                       fprintf(stderr,"unknown TransType \n");
                       exit(1);
               }
               objp->methods=TransTable[i].methods();
               if(!xdr_pointer(xdrs,&objp->tr,TransTable[i].size,TransTable[i].xdrproc)){
                       return(FALSE);
               }
               objp->next=NULL;
               if(!xdr_u_long(xdrs,&numoffassocs)){
                       return(FALSE);
               }
               objp->assoc=NULL;
               if(numoffassocs){
                       if(!xdr_reference(xdrs,&objp->assoc,sizeof(rpc_ExprAssoc),xdr_rpc_ExprAssoc)){
                               return (FALSE);
                       }
                       curassoc=(rpc_ExprAssoc *) objp->assoc;
                       while(TRUE){
                               a=(Float*)objp->tr;
                               curassoc->lhs=(u_long)&(a[curassoc->lhs]);
                               curassoc->next=NULL;
                               numoffassocs--;
                               if(!numoffassocs)
                                       break;
                               if(!xdr_reference(xdrs,&curassoc->next,sizeof(rpc_ExprAssoc),xdr_rpc_ExprAssoc)){
                                       return (FALSE);
                               }
                               curassoc=curassoc->next;
                       }


               }
       }

       if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(rpc_Trans), xdr_rpc_Trans)) {
               return (FALSE);
       }
       if(xdrs->x_op==XDR_DECODE){
               if(objp->next){
                       objp->next->prev=objp;
               }
       }
       return (TRUE);
}  

bool_t  xdr_rpc_Hf(xdrs, objp)
        XDR *xdrs;
        rpc_Hf *objp;
{       int i,j;
        if (!xdr_int(xdrs, &objp->size)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_DECODE) objp->data=NULL;
        if(!xdr_array(xdrs,&objp->data,&objp->size,objp->size,sizeof(float*),xdr_u_long)){
               return(FALSE);
        }
        if(xdrs->x_op==XDR_DECODE) bzero(objp->data,objp->size*sizeof(float*));
        for(i=0;i<objp->size;i++){
               if(!xdr_array(xdrs,&objp->data[i],&objp->size,objp->size,sizeof(float),xdr_float)){
                       return (FALSE);
               }
        }
        if (!xdr_float(xdrs, &objp->minz)) {
                return (FALSE);
        }
        if (!xdr_float(xdrs, &objp->maxz)) {
                return (FALSE);
        }
        if (!xdr_float(xdrs, &objp->BestSize)) {
                return (FALSE);
        }
        if (!xdr_float(xdrs, &objp->iBestSize)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_DECODE){
               rpc_Hf *hf; float *minptr,*maxptr;
               hf=objp;
               /*
                * Allocate levels of grid.  hf->levels = log base BestSize of hf->size
                */
               for (i = hf->size, hf->levels = 0; i > hf->BestSize; i /= hf->BestSize,
                                hf->levels++)
                       ;
              hf->levels++;
               hf->qsize = CACHESIZE;
               hf->q = (hfTri **)Calloc((unsigned)hf->qsize, sizeof(hfTri *));
               hf->qtail = 0;
               hf->lsize = (int *)share_malloc(hf->levels * sizeof(int));
               hf->spacing = (float *)share_malloc(hf->levels * sizeof(float));
               hf->boundsmax = (float ***)share_malloc(hf->levels * sizeof(float **));
               hf->boundsmin = (float ***)share_malloc(hf->levels * sizeof(float **));
      
               hf->spacing[0] = hf->size -1;
               hf->lsize[0] = (int)hf->spacing[0];
               hf->boundsmax[0] = (float **)share_malloc(hf->lsize[0]*sizeof(float *));
             hf->boundsmin[0] = (float **)share_malloc(hf->lsize[0]*sizeof(float *));
               /*
               * Compute initial bounding boxes
              */
               for (i = 0; i < hf->lsize[0]; i++) {
                       hf->boundsmax[0][i]=(float *)share_malloc(hf->lsize[0]*sizeof(float));
                       hf->boundsmin[0][i]=(float *)share_malloc(hf->lsize[0]*sizeof(float));
                       maxptr = hf->boundsmax[0][i];
                       minptr = hf->boundsmin[0][i];
                       for (j = 0; j < hf->lsize[0]; j++) {
                               *maxptr++ = maxalt(i, j, hf->data) + EPSILON;
                               *minptr++ = minalt(i, j, hf->data) - EPSILON;
                      }
               }
              for (i = 1; i < hf->levels; i++) {
                        hf->spacing[i] = hf->spacing[i-1] * hf->iBestSize;
                        hf->lsize[i] = (int)hf->spacing[i];
                        if ((Float)hf->lsize[i] != hf->spacing[i])
                                hf->lsize[i]++;
                        hf->boundsmax[i]=(float **)share_malloc(hf->lsize[i]*sizeof(float *));
                        hf->boundsmin[i]=(float **)share_malloc(hf->lsize[i]*sizeof(float *));
                        for (j = 0; j < hf->lsize[i]; j++) {
                                hf->boundsmax[i][j] = (float *)share_malloc(hf->lsize[i] *
                                                        sizeof(float));
                                hf->boundsmin[i][j] = (float *)share_malloc(hf->lsize[i] *
                                                               sizeof(float));
                        }
                        integrate_grid(hf, i);
                }
                hf->boundbox[LOW][X] = hf->boundbox[LOW][Y] = 0;
                hf->boundbox[HIGH][X] = hf->boundbox[HIGH][Y] = 1;
                hf->boundbox[LOW][Z] = hf->minz;
                hf->boundbox[HIGH][Z] = hf->maxz;
       }
       return (TRUE);
}

bool_t
xdr_rpc_Blob(xdrs, objp)
        XDR *xdrs;
        rpc_Blob *objp;
{
        if (!xdr_double(xdrs, &objp->T)) {
                return (FALSE);
        }
        if (!xdr_int(xdrs, &objp->num)) {
                return (FALSE);
       }
        if (!xdr_array(xdrs, (char **)&objp->list, &objp->num,ULONG_MAX,sizeof(rpc_MetaVector),xdr_rpc_MetaVector)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_DECODE){
               objp->ilist = (MetaInt *)Malloc( 2 * objp->num * sizeof(MetaInt));
               objp->iarr = (MetaInt **)Malloc( 2 * objp->num * sizeof(MetaInt *));
        }
        return (TRUE);
}

bool_t
xdr_rpc_hfTri(xdrs, objp)
        XDR *xdrs;
        rpc_hfTri *objp;
{       static rpc_hfTri *prev=NULL;
        if (!xdr_rpc_Vector(xdrs, &objp->v1)) {
                return (FALSE);
        }
        if (!xdr_rpc_Vector(xdrs, &objp->v2)) {
                return (FALSE);
        }
        if (!xdr_rpc_Vector(xdrs, &objp->v3)) {
                return (FALSE);
        }
        if (!xdr_rpc_Vector(xdrs, &objp->norm)) {
                return (FALSE);
        }
       if (!xdr_double(xdrs, &objp->d)) {
                return (FALSE);
        }
        if (!xdr_char(xdrs, &objp->type)) {
                return (FALSE);
        }
        if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(rpc_hfTri), xdr_rpc_hfTri)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_DECODE){
               objp->prev=prev;
               prev=objp;
               if(!objp->next){
                        prev=NULL;
               }
        }

        return (TRUE);
}
GeomTab GeomTable[]={
               {BLOB,          BlobMethods,     xdr_rpc_Blob,    sizeof(rpc_Blob)},
               {BOX,           BoxMethods,      xdr_rpc_Box,     sizeof(rpc_Box)},
               {CONE,          ConeMethods,     xdr_rpc_Cone,    sizeof(rpc_Cone)},
               {CSG,           CsgMethods,      xdr_rpc_Csg,     sizeof(rpc_Csg)},
               {CYLINDER,      CylinderMethods, xdr_rpc_Cylinder,sizeof(rpc_Cylinder)},
               {DISC,          DiscMethods,     xdr_rpc_Disc,    sizeof(rpc_Disc)},
               {GRID,          GridMethods,     xdr_rpc_Grid,    sizeof(rpc_Grid)},
               {HF,            HfMethods,       xdr_rpc_Hf,      sizeof(rpc_Hf)},
               {INSTANCE,      InstanceMethods, xdr_rpc_Instance,sizeof(rpc_Instance)},
               {LIST,          ListMethods,     xdr_rpc_List,    sizeof(rpc_List)},
               {PLANE,         PlaneMethods,    xdr_rpc_Plane,   sizeof(rpc_Plane)},
               {POLYGON,       PolygonMethods,  xdr_rpc_Polygon, sizeof(rpc_Polygon)},
               {SPHERE,        SphereMethods,   xdr_rpc_Sphere,  sizeof(rpc_Sphere)},
               {TORUS,         TorusMethods,    xdr_rpc_Torus,   sizeof(rpc_Torus)},
               {TRIANGLE,      TriangleMethods, xdr_rpc_Triangle,sizeof(rpc_Triangle)},
               {GEOMTYPEEND,   NULL,            xdr_void,        NULL}
       };
#define EINSCHUB /*{j=col;while(j--) fprintf(stderr,"      ");}*/
bool_t
xdr_rpc_Geom(xdrs, objp)
        XDR *xdrs;
        rpc_Geom *objp;
{       rpc_Geom *obj;
        static int col=0;
        u_long i;
        if(!xdr_nm(xdrs,&objp->name)){
               return(FALSE);
        }
        if (!xdr_u_long(xdrs, &objp->prims)) {
               return (FALSE);
        }
        if (!xdr_vector(xdrs, (char *)objp->bounds, 6, sizeof(double), xdr_double)) {
                return (FALSE);
        }
        if (!xdr_double(xdrs, &objp->timenow)) {
                return (FALSE);
        }
        if (!xdr_short(xdrs, &objp->animtrans)) {
                return (FALSE);
        }
        if (!xdr_short(xdrs, &objp->frame)) {
                return (FALSE);
        }
        if (!xdr_rpc_uSurface_Ptr(xdrs, &objp->surf)) {
                return (FALSE);
        }
        if (!xdr_pointer(xdrs, (char **)&objp->trans, sizeof(rpc_Trans), xdr_rpc_Trans)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_DECODE){
               Trans *tail;
               tail=objp->trans;
               if(tail){
                       while(tail->next){
                               tail=tail->next;
                       }
               }
               objp->transtail=tail;
        }

        if (!xdr_pointer(xdrs, (char **)&objp->texture, sizeof(rpc_Texture), xdr_rpc_Texture)) {
                return (FALSE);
        }
        if (!xdr_u_long(xdrs, &objp->counter)) {
                return (FALSE);
        }
        if (!xdr_bool(xdrs, &objp->next)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_ENCODE) {
               for(i=0;i<GEOMTYPEEND;i++){
                       if(objp->methods==GeomTable[i].getmethods())
                               break;
               }
               if(i>=GEOMTYPEEND){
                       fprintf(stderr,"unknown GeomType %20s %20s\n",objp->name ? objp->name : "kein" ,objp->methods->name());
                       exit(1);
               }
              if(!xdr_long(xdrs,&i)){
                       return (FALSE);
              }
             switch (i) {
                       case INSTANCE:{
                               if(!xdr_pointer(xdrs,(char**)&(objp->obj),
                                               sizeof(rpc_uInstance),xdr_rpc_uInstance)){
                                       return(FALSE);
                               }
                               if(!xdr_nm(xdrs,(char**)&((Instance*)(objp->obj))->obj->name)){
                                       return(FALSE);
                               }
                               break;
                       }
                       default:{
                               if(!xdr_pointer(xdrs,&objp->obj,GeomTable[i].size,GeomTable[i].xdrproc)){
                                       return(FALSE);
                               }
                               break;
                       }
               }
       }
       if(xdrs->x_op==XDR_DECODE) {
               if(!xdr_u_long(xdrs,&i)){
                       return (FALSE);
               }
               if(i>GEOMTYPEEND){
                       fprintf(stderr,"unknown GeomType %20s %20s\n",objp->name ? objp->name : "kein" ,
				objp->methods->name());
                       exit(1);
               }
               objp->methods=GeomTable[i].getmethods();
               switch (i) {
                       case INSTANCE:{ rpc_Instance *inst;char *s;
                               if(!xdr_pointer(xdrs,(char**)&(objp->obj),sizeof(rpc_uInstance),xdr_rpc_uInstance)){
                                       return(FALSE);
                               }
                               inst=(rpc_Instance*)objp->obj;
                              if(!xdr_nm(xdrs,(char**)&s)){
                                       return(FALSE);
                               }
                               if(!(obj=(rpc_Geom*)GeomGetNamed(s))){
                                       fprintf(stderr,"instance %s not found in object list %d\n",s,Objects);
                                       exit(1);
                               }
                               inst->obj=obj;
                               break;
                       }
                       default:{
                               if(!xdr_pointer(xdrs,&objp->obj,GeomTable[i].size,GeomTable[i].xdrproc)){
                                       return(FALSE);
                               }
                               break;
                       }
               }

      }
       if(xdrs->x_op==XDR_DECODE)objp->next=0;
       if(!xdr_pointer(xdrs,(char**) &objp->next,sizeof(rpc_Geom),xdr_rpc_Geom)){
               return (FALSE);
       }
       if(IsAggregate(objp)){
               col--;/*EINSCHUB;fprintf(stderr,"END%s\n",objp->methods->name())*/;
       }
       return (TRUE);
}
xdr_rpc_Csg(xdrs, objp)
        XDR *xdrs;
        rpc_Csg *objp;
{
        if (!xdr_char(xdrs, &objp->operator)) {
                return (FALSE);
        }
	if(xdrs->x_op==XDR_DECODE) {
		switch (objp->operator) {
			case CSG_UNION:
				objp->intmeth=CsgUnionInt;
				break;
			case CSG_INTERSECT:   
				objp->intmeth=CsgIntersectInt;
				break;
			case CSG_DIFFERENCE:
				objp->intmeth=CsgDifferenceInt;
				break;
		default:
			fprintf(stderr,"Decoding unknown CSG-Type\n");
			return FALSE;
		}
	}
        if (!xdr_pointer(xdrs, (char **)&objp->obj1, sizeof(struct rpc_Geom), xdr_rpc_Geom)) {
                return (FALSE);
        }
        if (!xdr_pointer(xdrs, (char **)&objp->obj2, sizeof(struct rpc_Geom), xdr_rpc_Geom)) {
                return (FALSE);
        }
        if (!xdr_vector(xdrs, (char *)objp->bounds, 6, sizeof(double), xdr_double)) {
                return (FALSE);
        }
        return (TRUE);
}
bool_t
xdr_rpc_Polygon(xdrs, objp)
        XDR *xdrs;
        rpc_Polygon *objp;
{
        if (!xdr_rpc_Vector(xdrs, &objp->norm)) {
                return (FALSE);
        }
        if (!xdr_double(xdrs, &objp->d)) {
                return (FALSE);
        }
        if (!xdr_char(xdrs, &objp->index)) {
                return (FALSE);
        }
	if(!xdr_array(xdrs,(char**)&objp->points,&objp->npoints,ULONG_MAX,sizeof(rpc_Vector),xdr_rpc_Vector)){
		return FALSE;
	} 
        return (TRUE);
}


bool_t
xdr_rpc_Grid(xdrs, objp)
        XDR *xdrs;
        rpc_Grid *objp;
{       
        if (!xdr_short(xdrs, &objp->xsize)) {
                return (FALSE);
        }
        if (!xdr_short(xdrs, &objp->ysize)) {
                return (FALSE);
        }
        if (!xdr_short(xdrs, &objp->zsize)) {
                return (FALSE);
        }
        if (!xdr_vector(xdrs, (char *)objp->bounds, 6, sizeof(double), xdr_double)) {
                return (FALSE);
        }
        if (!xdr_vector(xdrs, (char *)objp->voxsize, 3, sizeof(double), xdr_double)) {
                return (FALSE);
        }
        /*if (!xdr_pointer(xdrs, (char **)&objp->unbounded, sizeof(struct rpc_Geom), xdr_rpc_Geom)) {
                return (FALSE);
        }*/
       if (!xdr_pointer(xdrs, (char **)&objp->objects, sizeof(struct rpc_Geom), xdr_rpc_Geom)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_DECODE){
	       objp->unbounded=NULL;
               GridBounds(objp,objp->bounds);
        }
        return (TRUE);
}

LightTab LightTable[]={
               {POINTLIGHT,          PointMethods,    xdr_rpc_Pointlight,    sizeof(rpc_Pointlight)},
               {SPOTLIGHT,           SpotMethods,     xdr_rpc_Spotlight,     sizeof(rpc_Spotlight)},
               {EXTENDEDLIGHT,       ExtendedMethods, xdr_rpc_Extended,      sizeof(rpc_Extended)},
               {JITTEREDLIGHT,       JitteredMethods, xdr_rpc_Jittered,      sizeof(rpc_Jittered)},
               {INFINITELIGHT,        InfiniteMethods, xdr_rpc_Infinite,      sizeof(rpc_Infinite)},
               {LIGHTTYPEEND,   NULL,            xdr_void,        NULL}
        };

bool_t
xdr_rpc_Light(xdrs, objp)
        XDR *xdrs;
        rpc_Light *objp;
{       u_long i;
        if (!xdr_rpc_Color(xdrs, &objp->color)) {
                return (FALSE);
        }
        if (!xdr_int(xdrs, &objp->shadow)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_ENCODE) {
           for(i=0;i<LIGHTTYPEEND;i++){
              if(objp->methods==LightTable[i].getmethods())
                 break;
           }
           if(i>=LIGHTTYPEEND){
              fprintf(stderr,"unknown LightType %20s %20s\n");
              exit(1);
           }
           if(!xdr_long(xdrs,&LightTable[i].type)){
             return (FALSE);
           }
           switch (i) {
	       case 0:
               default:
                   if(!xdr_reference(xdrs,&objp->light,LightTable[i].size,LightTable[i].xdrproc)){
                       return(FALSE);
                   }
                   break;
           }
        }
        if(xdrs->x_op==XDR_DECODE) {
          if(!xdr_u_long(xdrs,&i)){
             return (FALSE);
          }
          if(i>LIGHTTYPEEND){
              fprintf(stderr,"unknown LightType \n");
            exit(1);
          }
          switch (i) {
	       case 0:
               default:
                   if(!xdr_reference(xdrs,&objp->light,LightTable[i].size,LightTable[i].xdrproc)){
                       return(FALSE);
                   }
                   break;
           }
          objp->methods=LightTable[i].getmethods();
        }
        if (!xdr_pointer(xdrs, (char **)&objp->cache, sizeof(rpc_ShadowCache), xdr_rpc_ShadowCache)) {
                return (FALSE);
        }
        if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(struct rpc_Light), xdr_rpc_Light)) {
                return (FALSE);
        }
        return (TRUE);
}

EffectTab EffectTable[]={
       {FOGEFFECT,     FogApply,         xdr_rpc_Fog,          sizeof(struct rpc_Fog)},
       {FOGDECKEFFECT, FogdeckApply,     xdr_rpc_Fogdeck,      sizeof(struct rpc_Fogdeck)},
       {MISTEFFECT,    MistApply,        xdr_rpc_Mist,         sizeof(struct rpc_Mist)},
       {EFFECTTYPEEND, NULL,             NULL,                 NULL}
       };

xdr_rpc_Atmosphere(xdrs, objp)
        XDR *xdrs;
        rpc_Atmosphere *objp;
{
        u_long i;
        if(xdrs->x_op==XDR_ENCODE){
               for(i=0;i<EFFECTTYPEEND;i++){
                       if(objp->method==EffectTable[i].method)
                               break;
               }
               if(i>=EFFECTTYPEEND){
                       fprintf(stderr,"unknown EffectType \n");
                       exit(1);
               }

               if(!xdr_long(xdrs,&EffectTable[i].type)){
                        return (FALSE);
               }
               switch (i) {
		       case 0:
                       default:
                               if(!xdr_reference(xdrs,&objp->data,EffectTable[i].size,EffectTable[i].xdr_proc)){
                                        return(FALSE);
                               }
                               break;
               }
       }
       if(xdrs->x_op==XDR_DECODE) {
               if(!xdr_u_long(xdrs,&i)){
                       return (FALSE);
               }
               if(i>EFFECTTYPEEND){
                       fprintf(stderr,"unknown EffectType %d\n",i);
                       exit(1);
               }
               objp->next=NULL;
               switch (i) {
	              case 0:	
                      default:
                           if(!xdr_reference(xdrs,&objp->data,EffectTable[i].size,EffectTable[i].xdr_proc)){
                               return(FALSE);
                           }
                   break;
               }
               objp->method=EffectTable[i].method;
        }

        if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(rpc_Atmosphere), xdr_rpc_Atmosphere)) {
                return (FALSE);
        }
        return (TRUE);
}

bool_t
xdr_rpc_Image(xdrs, objp)
        XDR *xdrs;
        rpc_Image *objp;
{       u_long i;
        if (!xdr_int(xdrs, &objp->width)) {
                return (FALSE);
        }
        if (!xdr_int(xdrs, &objp->height)) {
                return (FALSE);
        }
        if (!xdr_int(xdrs, &objp->chan)) {
               return (FALSE);
        }
        if (!xdr_int(xdrs, &objp->has_alpha)) {
                return (FALSE);
        }
        if (!xdr_int(xdrs, &objp->totalchan)) {
                return (FALSE);
        }
        if (!xdr_int(xdrs, &objp->chansize)) {
                return (FALSE);
        }
        if(xdrs->x_op==XDR_DECODE) objp->data=NULL;
        i=objp->chansize * objp->totalchan * sizeof(unsigned char);
        if (!xdr_bytes(xdrs, (char **)&objp->data, &i,ULONG_MAX)) {
                return (FALSE);
        }
        if (!xdr_nm(xdrs, &objp->filename)) {
                return (FALSE);
        }
        if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(rpc_Image), xdr_rpc_Image)) {
                return (FALSE);
        }
        return (TRUE);
}
TextureTab TextureTable[]={
       {BLOTCHTEXT,    BlotchApply,      xdr_rpc_Blotch,       sizeof(struct rpc_Blotch)},
       {BUMPTEXT,      BumpApply,        xdr_rpc_Bump,         sizeof(struct rpc_Bump)},
       {CHECKERTEXT,   CheckerApply,     xdr_rpc_Checker,      sizeof(struct rpc_Checker)},
       {CLOUDTEXT,     CloudTextApply,   xdr_rpc_CloudText,    sizeof(struct rpc_CloudText)},
       {FBMTEXT,       FBmApply,         xdr_rpc_FBm,          sizeof(struct rpc_FBm)},
       {FBMBUMPTEXT,   FBmBumpApply,     xdr_rpc_FBm,          sizeof(struct rpc_FBm)},
       {GLOSSTEXT,     GlossApply,       xdr_rpc_Gloss,        sizeof(struct rpc_Gloss)},
       {IMAGETEXT,     ImageTextApply,   xdr_rpc_ImageText,    sizeof(struct rpc_ImageText)},
       {MARBLETEXT,    MarbleApply,      xdr_rpc_Marble,       sizeof(struct rpc_Marble)},
       {MOUNTTEXT,     MountApply,       xdr_rpc_Mount,        sizeof(struct rpc_Mount)},
       {SKYTEXT,       SkyApply,         xdr_rpc_Sky,          sizeof(struct rpc_Sky)},
       {STRIPETEXT,    StripeApply,      xdr_rpc_Stripe,       sizeof(struct rpc_Stripe)},
       {WINDYTEXT,     WindyApply,       xdr_rpc_WindyText,    sizeof(struct rpc_WindyText)},
       {WOODTEXT,      WoodApply,        xdr_void,             NULL		},
       {TEXTURETYPEEND,   NULL,          xdr_void,             NULL}
};
bool_t
xdr_rpc_Texture(xdrs, objp)
        XDR *xdrs;
        rpc_Texture *objp;
{       u_long i;
    
       if(xdrs->x_op==XDR_ENCODE) {
               for(i=0;i<TEXTURETYPEEND;i++){
                       if(objp->method==TextureTable[i].method)
                               break;
               }
               if(i>=TEXTURETYPEEND){
                       fprintf(stderr,"unknown TextType \n");
                       exit(1);
               }
               if(!xdr_long(xdrs,&TextureTable[i].type)){
                       return (FALSE);
               }
               switch (i) {
                       case IMAGETEXT:{
                               if(!xdr_reference(xdrs,&objp->data,TextureTable[i].size,TextureTable[i].xdrproc)){
                                       return(FALSE);
                               }
                               if(!xdr_nm(xdrs,&((rpc_Image*)((rpc_ImageText*)(objp->data))->image)->filename)){
                                       return (FALSE);
                               }
                       break;
                       }
		       case WOODTEXT:
				break;

                       default:
                               if(!xdr_reference(xdrs,&objp->data,TextureTable[i].size,TextureTable[i].xdrproc)){
                                       return(FALSE);
                               }
                               break;
               }
       }
       if(xdrs->x_op==XDR_DECODE) {
               if(!xdr_u_long(xdrs,&i)){
                       return (FALSE);
               }
               if(i>TEXTURETYPEEND){
                       fprintf (stderr, "unknown TextureType %d\n",i);
                       exit(1);
               }
               objp->data=NULL;
               objp->next=NULL;
               switch (i) {
                       case IMAGETEXT: { char s[1000],*sp;
                               sp=s;
                               if(!xdr_reference(xdrs,&objp->data,TextureTable[i].size,TextureTable[i].xdrproc)){
                                       return(FALSE);
                               }
                               if(!xdr_nm(xdrs,&sp)){
                                       return (FALSE);
                               }
                               if(!( ((rpc_ImageText*) (objp->data))->image=(u_long)ImageFind(sp))) {
                                       fprintf(stderr,"can`t find Image %s\n",sp);
                                       exit(1);
                               }
                               break;
                       }
		       case WOODTEXT:
				break;

                       default:
                       if(!xdr_reference(xdrs,&objp->data,TextureTable[i].size,TextureTable[i].xdrproc)){
                               return(FALSE);
                       }
               }
               objp->method=TextureTable[i].method;
       }


       if (!xdr_pointer(xdrs, (char **)&objp->trans, sizeof(rpc_Trans), xdr_rpc_Trans)) {
               return (FALSE);
       }
       if (!xdr_short(xdrs, &objp->animtrans)) {
               return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&objp->next, sizeof(struct rpc_Texture), xdr_rpc_Texture)) {
               return (FALSE);
       }
       return (TRUE);
}


MappingTab MappingTable[]= {
                {UVMAP,        UVMapping,      xdr_void,       NULL },
                {SPHEREMAP,    SphereMapping,  xdr_void,       NULL },
                {CYLMAP,       CylinderMapping,xdr_void,       NULL },
                {LINEARMAP,    LinearMapping,  xdr_void,       NULL },
                {MAPTYPEEND,   NULL,           xdr_void,       NULL }
       };
bool_t
xdr_rpc_Mapping(xdrs, objp)
        XDR *xdrs;
        rpc_Mapping *objp;
{       u_long i;
        if (!xdr_int(xdrs, &objp->flags)) {
                return (FALSE);
        }
        if (!xdr_rpc_Vector(xdrs, &objp->center)) {
                return (FALSE);
        }
        if (!xdr_rpc_Vector(xdrs, &objp->uaxis)) {
                return (FALSE);
        }
        if (!xdr_rpc_Vector(xdrs, &objp->vaxis)) {
                return (FALSE);
        }
        if (!xdr_rpc_Vector(xdrs, &objp->norm)) {
                return (FALSE);
        }
        if (!xdr_double(xdrs, &objp->dist)) {
                return (FALSE);
        }
        if (!xdr_rpc_RSMatrix(xdrs, &objp->m)) {
                return (FALSE);
        }

        if(xdrs->x_op==XDR_ENCODE) {
           for(i=0;i<MAPTYPEEND;i++){
              if(objp->method==MappingTable[i].method)
                 break;
           }
           if(i>=MAPTYPEEND){
              fprintf(stderr,"unknown MAPType \n");
              exit(1);
           }
           if(!xdr_long(xdrs,&MappingTable[i].type)){
             return (FALSE);
           }
        }
        if(xdrs->x_op==XDR_DECODE) {
          if(!xdr_u_long(xdrs,&i)){
             return (FALSE);
          }
          if(i>MAPTYPEEND){
              fprintf(stderr,"unknown MAPType\n");
            exit(1);
          }
          objp->method=MappingTable[i].method;
        }
        return (TRUE);
}
bool_t xdr_RayshadeArg(xdrs,objp)
       XDR *xdrs;
       RayshadeArg *objp;
{
       if(xdrs->x_op==XDR_ENCODE){
               World->next=NULL;
               objp->options = &Options;
               objp->screen  = &Screen;
               objp->camera  = &Camera;
       }
       if(xdrs->x_op==XDR_DECODE){
               bzero(objp,sizeof(*objp));
               Symtab=NULL;
               image_list =NULL;
               Surfaces=NULL;
               AtmosEffects=NULL;
               Lights=NULL;
               Objects=NULL;
               World=NULL;
       }
       if (!xdr_u_long(xdrs, &objp->RRID)) {
              return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&objp->options, sizeof(rpc_RSOptions), xdr_rpc_RSOptions)) {
               return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&objp->screen, sizeof(rpc_RSScreen), xdr_rpc_RSScreen)) {
               return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&objp->camera, sizeof(rpc_RSCamera), xdr_rpc_RSCamera)) {
               return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&Symtab, sizeof(rpc_SymtabEntry),xdr_rpc_SymtabEntry)) {
                return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&image_list, sizeof(rpc_Image), xdr_rpc_Image)) {
               return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&Surfaces, sizeof(rpc_Surface),xdr_rpc_Surface)) {
               return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&AtmosEffects, sizeof(rpc_Atmosphere),xdr_rpc_Atmosphere)) {
               return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&Lights, sizeof(rpc_Light), xdr_rpc_Light)) {
               return (FALSE);
       }
       if(xdrs->x_op==XDR_ENCODE) reverse_objlist();
       if (!xdr_pointer(xdrs, (char **)&Objects, sizeof(rpc_Geom), xdr_rpc_Geom)) {
               return (FALSE);
       }
       if(xdrs->x_op==XDR_ENCODE) reverse_objlist();

       if (!xdr_pointer(xdrs, (char **)&World, sizeof(rpc_Geom), xdr_rpc_Geom)){
               return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&TimeExpr, sizeof(rpc_Expr), xdr_rpc_Expr)){
               return (FALSE);
       }
       if (!xdr_pointer(xdrs, (char **)&FrameExpr, sizeof(rpc_Expr), xdr_rpc_Expr)){
               return (FALSE);
       }
       if(!xdr_rpc_RTable(xdrs,&RTable[0])){
		return(FALSE);
	}
		
       if(xdrs->x_op==XDR_DECODE){
               objp->symtab=Symtab;
               objp->image_list=image_list;
               objp->surfaces=Surfaces;
               objp->atmoseffects=AtmosEffects;
               objp->lights=Lights;
               objp->objects=Objects;
               objp->world=World;
               objp->timeexpr=TimeExpr;
               objp->frameexpr=FrameExpr;
               objp->options->is_rpc_client=FALSE;
               objp->options->is_rpc_server=TRUE;
	       objp->rtable=(Float*)malloc(sizeof(rpc_RTable));
	       if(objp->rtable)
			bcopy(&RTable[0],objp->rtable,sizeof(rpc_RTable));

       }
       return(TRUE);
}
void raywriteline(pixels,frame,line,lenght)
	rpc_Pixel *pixels;
	int frame, line, lenght;
{
	extern void RRAbort();
	PictureWriteLine(pixels);
	if ((line>=Screen.maxy) && (frame>=Options.endframe))
		RRAbort();
	if ((line>=Screen.maxy))
		rraynewframe();
}
void rraynewframe() {
	PictureFrameEnd();
	RSStartFrame(Options.framenum+1);
	if(Options.framenum<=Options.endframe)
		PictureStart(NULL);
}
void remote_rayshade(arg,svc)
	RayshadeArg *arg;
	rpc_square *svc;
{
        bcopy(arg->options,&Options,sizeof(RSOptions));
        bcopy(arg->screen,&Screen,sizeof(RSScreen));
        bcopy(arg->camera,&Camera,sizeof(RSCamera));
   	RSCleanup();
	if(arg->rtable)
		 bcopy(arg->rtable,&RTable[0],sizeof(rpc_RTable));
        Symtab=arg->symtab;
        image_list=arg->image_list;
        Surfaces=arg->surfaces;
        AtmosEffects=arg->atmoseffects;
        Lights=arg->lights;
        Objects=arg->objects;
        World=arg->world;
        TimeExpr=(Expr*)arg->timeexpr;
        FrameExpr=(Expr*)arg->frameexpr;

        Screen.minx=svc->req.minx; Screen.maxx=svc->req.maxx;
        Screen.miny=svc->req.miny; Screen.maxy=svc->req.maxy;
        Screen.xsize=Screen.maxx-Screen.minx+1;
        Screen.ysize = Screen.maxy - Screen.miny + 1;
        SamplingSetOptions(Options.samples, Options.gaussian,Options.filterwidth);
        RSStartFrame(svc->req.frame);
 	raytrace(NULL,NULL);
	fprintf(stderr,"\n");
        return;
}
PlotSquare(square)
	rpc_square *square;
{
	int x,y;
	rpc_Pixel *pixels;
	pixels=square->pixels.pixels_val;
	for(y=square->req.miny; y<square->req.maxy+1; y++){
               for(x=square->req.minx;x<square->req.maxx+1;x++){
                       display_plot(x,Screen.maxy-y,
                               pixels->r,
                               pixels->g,
                               pixels->b);
                               pixels++;
               }
       }
}
#endif

