Back to index

radiance  4R0+20100331
instance.c
Go to the documentation of this file.
00001 #ifndef lint
00002 static const char RCSid[] = "$Id: instance.c,v 2.11 2004/02/12 18:55:50 greg Exp $";
00003 #endif
00004 /*
00005  *  instance.c - routines for octree objects.
00006  */
00007 
00008 #include "copyright.h"
00009 
00010 #include  "rtmath.h"
00011 #include  "rterror.h"
00012 #include  "rtio.h"
00013 #include  "paths.h"
00014 
00015 #include  "octree.h"
00016 #include  "object.h"
00017 #include  "instance.h"
00018 
00019 #define  IO_ILLEGAL  (IO_FILES|IO_INFO)
00020 
00021 static SCENE  *slist = NULL;              /* list of loaded octrees */
00022 
00023 
00024 SCENE *
00025 getscene(sname, flags)                    /* get new octree reference */
00026 char  *sname;
00027 int  flags;
00028 {
00029        char  *pathname;
00030        register SCENE  *sc;
00031 
00032        flags &= ~IO_ILLEGAL;              /* not allowed */
00033        for (sc = slist; sc != NULL; sc = sc->next)
00034               if (!strcmp(sname, sc->name))
00035                      break;
00036        if (sc == NULL) {
00037               sc = (SCENE *)malloc(sizeof(SCENE));
00038               if (sc == NULL)
00039                      error(SYSTEM, "out of memory in getscene");
00040               sc->name = savestr(sname);
00041               sc->nref = 0;
00042               sc->ldflags = 0;
00043               sc->scube.cutree = EMPTY;
00044               sc->scube.cuorg[0] = sc->scube.cuorg[1] =
00045                             sc->scube.cuorg[2] = 0.;
00046               sc->scube.cusize = 0.;
00047               sc->firstobj = sc->nobjs = 0;
00048               sc->next = slist;
00049               slist = sc;
00050        }
00051        if ((pathname = getpath(sname, getrlibpath(), R_OK)) == NULL) {
00052               sprintf(errmsg, "cannot find octree file \"%s\"", sname);
00053               error(USER, errmsg);
00054        }
00055        flags &= ~sc->ldflags;             /* skip what's already loaded */
00056        if (flags & IO_SCENE)
00057               sc->firstobj = nobjects;
00058        if (flags)
00059               readoct(pathname, flags, &sc->scube, NULL);
00060        if (flags & IO_SCENE)
00061               sc->nobjs = nobjects - sc->firstobj;
00062        sc->ldflags |= flags;
00063        sc->nref++;                 /* increase reference count */
00064        return(sc);
00065 }
00066 
00067 
00068 INSTANCE *
00069 getinstance(o, flags)                     /* get instance structure */
00070 register OBJREC  *o;
00071 int  flags;
00072 {
00073        register INSTANCE  *ins;
00074 
00075        flags &= ~IO_ILLEGAL;              /* not allowed */
00076        if ((ins = (INSTANCE *)o->os) == NULL) {
00077               if ((ins = (INSTANCE *)malloc(sizeof(INSTANCE))) == NULL)
00078                      error(SYSTEM, "out of memory in getinstance");
00079               if (o->oargs.nsargs < 1)
00080                      objerror(o, USER, "bad # of arguments");
00081               if (fullxf(&ins->x, o->oargs.nsargs-1,
00082                             o->oargs.sarg+1) != o->oargs.nsargs-1)
00083                      objerror(o, USER, "bad transform");
00084               if (ins->x.f.sca < 0.0) {
00085                      ins->x.f.sca = -ins->x.f.sca;
00086                      ins->x.b.sca = -ins->x.b.sca;
00087               }
00088               ins->obj = NULL;
00089               o->os = (char *)ins;
00090        }
00091        if (ins->obj == NULL)
00092               ins->obj = getscene(o->oargs.sarg[0], flags);
00093        else if ((flags &= ~ins->obj->ldflags)) {
00094               if (flags & IO_SCENE)
00095                      ins->obj->firstobj = nobjects;
00096               if (flags)
00097                      readoct(getpath(o->oargs.sarg[0], getrlibpath(), R_OK),
00098                                    flags, &ins->obj->scube, NULL);
00099               if (flags & IO_SCENE)
00100                      ins->obj->nobjs = nobjects - ins->obj->firstobj;
00101               ins->obj->ldflags |= flags;
00102        }
00103        return(ins);
00104 }
00105 
00106 
00107 void
00108 freescene(sc)        /* release a scene reference */
00109 SCENE *sc;
00110 {
00111        SCENE  shead;
00112        register SCENE  *scp;
00113 
00114        if (sc == NULL)
00115               return;
00116        if (sc->nref <= 0)
00117               error(CONSISTENCY, "unreferenced scene in freescene");
00118        sc->nref--;
00119        if (sc->nref)               /* still in use? */
00120               return;
00121        shead.next = slist;         /* else remove from our list */
00122        for (scp = &shead; scp->next != NULL; scp = scp->next)
00123               if (scp->next == sc) {
00124                      scp->next = sc->next;
00125                      sc->next = NULL;
00126                      break;
00127               }
00128        if (sc->next != NULL)              /* can't be in list anymore */
00129               error(CONSISTENCY, "unlisted scene in freescene");
00130        slist = shead.next;
00131        freestr(sc->name);          /* free memory */
00132        octfree(sc->scube.cutree);
00133        freeobjects(sc->firstobj, sc->nobjs);
00134        free((void *)sc);
00135 }
00136 
00137 
00138 void
00139 freeinstance(o)             /* free memory associated with instance */
00140 OBJREC  *o;
00141 {
00142        if (o->os == NULL)
00143               return;
00144        freescene((*(INSTANCE *)o->os).obj);
00145        free((void *)o->os);
00146        o->os = NULL;
00147 }