This is object.c in view mode; [Download] [Up]
/* * object.c * * Copyright (C) 1989, 1991, Craig E. Kolb * All rights reserved. * * This software may be freely copied, modified, and redistributed * provided that this copyright notice is preserved on all copies. * * You may not distribute this software, in whole or in part, as part of * any commercial product without the express consent of the authors. * * There is no warranty or other guarantee of fitness of this software * for any purpose. It is provided solely "as is". * * $Id$ * * $Log$ */ #include "object.h" #include "list.h" Object * ObjCreate(objptr, methods) ObjRef objptr; Methods *methods; { Object *obj; if (objptr == (ObjRef)NULL) return (Object *)NULL; obj = (Object *)share_calloc(1, sizeof(Object)); obj->obj = objptr; obj->methods = methods; #ifdef SHAREDMEM /* * If the counter is in shared memory, processes will * be modifying it left-and-right. So, we cheat and * make counter a pointer to a non-shared location and * store the value there. */ new->counter = (unsigned long *)Malloc(sizeof(unsigned long)); *new->counter = 0; #endif return obj; } /* * Return a copy of the given object. * Note that surface, texturing, and transformation information * is copied by reference. */ Object * ObjectCopy(obj) Object *obj; { Object *new; new = ObjCreate(obj->obj, obj->methods); /* Share texturing, name, #prims, surface info */ new->name = obj->name; new->texture = obj->texture; new->surf = obj->surf; new->prims = obj->prims; new->trans = obj->trans; /* copy bounds */ BoundsCopy(obj->bounds, new->bounds); return new; } /* * Report bounding box and number of primitives in object. */ void AggregatePrintInfo(obj, fp) Object *obj; FILE *fp; { if (fp) { fprintf(fp,"Object \"%s\":\n", obj->name); BoundsPrint(obj->bounds, fp); fprintf(fp,"\t%lu primitive%c\n",obj->prims, obj->prims == 1 ? ' ' : 's'); } } /* * Convert the given object from a linked list of objects to * the desired aggregate type. */ int AggregateConvert(obj, objlist) Object *obj, *objlist; { if (!IsAggregate(obj)) { RLerror(RL_ABORT, "A %s isn't an aggregate.\n", ObjectName(obj)); return 0; } return (*obj->methods->convert)(obj->obj, objlist); } /* * Set "bounds" of object to be the extent of the primitive. */ int ObjectBounds(obj) Object *obj; { if (obj && obj->methods->bounds) { (*obj->methods->bounds) (obj->obj, obj->bounds); } else { RLerror(RL_ABORT, "Can't compute bounds of \"%s\".\n", ObjectName(obj)); return FALSE; } /* * Enlarge by EPSILON in each direction just to * be on the safe side. */ obj->bounds[LOW][X] -= EPSILON; obj->bounds[HIGH][X] += EPSILON; obj->bounds[LOW][Y] -= EPSILON; obj->bounds[HIGH][Y] += EPSILON; obj->bounds[LOW][Z] -= EPSILON; obj->bounds[HIGH][Z] += EPSILON; return TRUE; } char * ObjectName(obj) Object *obj; { if (obj->methods->name) return (*obj->methods->name)(); return "unknown"; } void ObjectStats(obj, tests, hits) Object *obj; unsigned long *tests, *hits; { if (obj && obj->methods->stats) (*obj->methods->stats)(tests, hits); else { *tests = *hits = 0; } } /* * Push an object onto the head of the given stack, returning * the new head. */ ObjList * ObjStackPush(obj, list) Object *obj; ObjList *list; { ObjList *new; /* * Pretty simple. * Make new element point to old head and return new head. */ new = (ObjList *)Malloc(sizeof(ObjList)); new->obj = obj; new->next = list; return new; } /* * Pop the topmost object off of the given stack, returning the new head. * The old head is freed, but the object it points to is not. */ ObjList * ObjStackPop(list) ObjList *list; { ObjList *ltmp; ltmp = list->next; /* Save new head. */ free((voidstar)list); /* Free old head. */ return ltmp; /* Return new head. */ } Methods * MethodsCreate() { return (Methods *)share_calloc(1, sizeof(Methods)); } /* * Call appropriate routine to compute UV and, if non-null, * dpdu and dpdv at given point on the given primitive. The * normal is used to facilitate computation of u, v, and the * partial derivatives. */ void PrimUV(prim, pos, norm, uv, dpdu, dpdv) Object *prim; Vector *pos, *norm, *dpdu, *dpdv; Vec2d *uv; { /* * Call appropriate inverse mapping routine */ if (prim->methods->uv == NULL) { uv->u = uv->v = 0.; if (dpdu) { dpdu->y = dpdu->z = 0.; dpdu->x = 1.; } if (dpdv) { dpdv->x = dpdv->z = 0.; dpdv->y = 1.; } } else (*prim->methods->uv)(prim->obj,pos,norm,uv,dpdu,dpdv); } int PrimNormal(prim, pos, norm, gnorm) Object *prim; Vector *pos, *norm, *gnorm; { /* * Call appropriate normal routine */ return (*prim->methods->normal) (prim->obj, pos, norm, gnorm); } int PrimEnter(obj, ray, mind, hitd) Object *obj; Ray *ray; Float mind, hitd; { /* * Call appropriate enter/leave routine */ if (obj->methods->enter == NULL) { Vector pos, nrm, gnrm; /* * Sleazy method: Use hit point, find normal * and take dot prod with ray */ VecAddScaled(ray->pos, hitd, ray->dir, &pos); PrimNormal(obj, &pos, &nrm, &gnrm); return dotp(&ray->dir, &gnrm) < 0.0; } else return (*obj->methods->enter) (obj->obj, ray, mind, hitd); } /* * Walk through a linked-list of objects. If the object is unbounded, * unlink it it from the list and add it to the 'unbounded' list. * If the object is bounded, enlarge the given bounding box if * necessary. Return pointer to unbounded list. */ Object * BoundsFind(list, bounds, num) Object **list; Float bounds[2][3]; int *num; { Object *ltmp, *prev; Object *unbounded, *nextobj; BoundsInit(bounds); prev = unbounded = (Object *)0; *num = 0; for (ltmp = *list; ltmp; ltmp = nextobj) { nextobj = ltmp->next; *num += ltmp->prims; if (ltmp->bounds[LOW][X] > ltmp->bounds[HIGH][X]) { /* * Object is unbounded -- unlink it... */ if (prev) prev->next = ltmp->next; else *list = ltmp->next; /* * And add it to unbounded object list. */ ltmp->next = unbounded; unbounded = ltmp; } else { /* * Object is bounded. */ BoundsEnlarge(bounds, ltmp->bounds); prev = ltmp; } } return unbounded; }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.