/* element.h: Galerkin finite elements: one structure for both surface and cluster * elements. */ #ifndef _ELEMENT_H_ #define _ELEMENT_H_ #ifdef __cplusplus extern "C" { #endif #include "patch.h" #include "interactionlist.h" #include "transform.h" #include "polygon.h" #include "elementlist.h" typedef union FloatOrColorPtr { float f; COLOR *c; } FloatOrColorPtr; typedef union PatchOrGeomPtr { PATCH *patch; GEOM *geom; } PatchOrGeomPtr; /* the Galerkin radiosity specific data to be kept with every surface or * cluster element. A flag indicates whether a given element is a cluster or * surface elements. There are only a few differences between surface and cluster * elements: cluster elements always have a constant basis on them, they contain * a pointer to the GEOM to which they are associated, while a surface element has * a pointer to the PATCH to which is belongs, they have only irregular subelements, * and no uptrans. */ typedef struct ELEMENT { int id; /* unique ID number for the element */ PatchOrGeomPtr pog; /* The PATCH/GEOM to which the surface/cluster element * belongs. */ COLOR Ed, Rd; /* diffuse emittance and reflectance */ COLOR *radiance, /* total radiance on the element as computed so far */ *received_radiance, /* radiance received during iteration */ *unshot_radiance; /* for progressive refinement radiosity */ /* #ident <<< WMP */ #ifdef WMP_WEIGHTS COLOR *direct_radiance; /* direct radiance on the element as computed so far */ COLOR *flux; /* flux for bidirectional radiosity */ COLOR *F; #endif /* #ident <<< WMP */ FloatOrColorPtr potential, received_potential, unshot_potential, direct_potential; /* total potential of the element, potential * received during the last iteration and unshot * potential (progressive refinement radiosity). */ INTERACTIONLIST *interactions; /* links with other patches: when using * a shooting algorithm, the links are kept * with the source element. When doing gathering, * the links are kept with the receiver element. */ struct ELEMENT *parent; /* parent element in a hierarchy, or * a NULL pointer if there is no parent. */ struct ELEMENT **regular_subelements; /* a NULL pointer if there are no * regular sub-elements, or an array containing * exactly 4 pointers to the sub-elements. */ struct ELEMENTLIST *irregular_subelements; /* NULL pointer or pointer to * the list of irregular subelements. */ TRANSFORM2D *uptrans; /* if non-null, transforms (u,v) coordinates on * a subelement to the (u,v) coordinates of the * same point on the parent surface element. It is NULL * if the element is a toplevel element for a patch or * a cluster element. If non-null it is a subelement on * a patch. */ float area; /* area of a surface element or sum of the areas * of the surfaces in a cluster element. */ float minarea; /* equal to area for a surface element or the area * of the smallest surface element in a cluster. */ float bsize; /* Equivalent blocker size for multiresoltuin visibility */ int nrpatches; /* number of patches in a cluster */ int tmp; /* for occasional use */ char childnr; /* rang nr of regular subelement in parent */ char basis_size; /* nr of coefficients to represent radiance ... */ char basis_used; /* nr of coefficients effectively used (<=basis_size) */ unsigned char flags; /* various flags, see below */ } ELEMENT; /* element flags: */ #define INTERACTIONS_CREATED 0x01 /* set when all interactions have * been created for a toplevel element. */ #define IS_CLUSTER 0x10 /* if set, indicates that the element is * a cluster element. If not set, the element is * a surface element. */ #define IS_LIGHT_SOURCE 0x20 /* whether or not the element is * or contains surfaces emitting * light spontaneously. */ #define IsCluster(element) (element->flags & IS_CLUSTER) #define IsLightSource(element) (element->flags & IS_LIGHT_SOURCE) /* calls 'routine' for every regular subelement of the element (if there * are any). 'routine' should have one argument: an ELEMENT *. */ #define ITERATE_REGULAR_SUBELEMENTS(element, routine) \ if ((element)->regular_subelements) { \ int i; \ for (i=0; i<4; i++) \ (routine)((element)->regular_subelements[i]); \ } /* same, but for the irregular subelements. */ #define ITERATE_IRREGULAR_SUBELEMENTS(element, routine) \ ElementListIterate(element->irregular_subelements, routine) #define ForAllRegularSubelements(child, elem) { \ if ((elem)->regular_subelements) { \ int i; \ for (i=0; i<4; i++) { \ ELEMENT *child = (elem)->regular_subelements[i] ; \ #define ForAllIrregularSubelements(child, elem) { \ if ((elem)->irregular_subelements) { \ ELEMENTLIST *ellist; \ for (ellist = (elem)->irregular_subelements; ellist; ellist=ellist->next) {\ ELEMENT *child = ellist->element; \ /* returns the total number of elements in use */ extern int GetNumberOfElements(void); extern int GetNumberOfClusters(void); extern int GetNumberOfSurfaceElements(void); /* creates the toplevel element for the patch */ extern ELEMENT *CreateToplevelElement(PATCH *patch); /* creates a cluster element for the given GEOM. The average projected area still * needs to be determined. */ extern ELEMENT *CreateClusterElement(GEOM *geom); /* Regularly subdivides the given element. A pointer to an array of * 4 pointers to subelements is returned. Only for surface elements. */ extern ELEMENT **RegularSubdivideElement(ELEMENT *element); /* position and orientation of the regular subelements is fully * determined by the following transforms, that transform (u,v) * parameters of a point on a subelement to the (u',v') parameters * of the same point on the parent element. */ extern TRANSFORM2D quadupxfm[4], triupxfm[4]; /* prints the element data to the file 'out' */ extern void PrintElement(FILE *out, ELEMENT *element); /* prints element patch id and the chain of child numbers of an element * in a hierarchy */ extern void PrintElementId(FILE *out, ELEMENT *elem); /* destroys the toplevel surface element and it's subelements (recursive) */ extern void DestroyToplevelElement(ELEMENT *element); /* destroys the cluster element, not recursive. */ extern void DestroyClusterElement(ELEMENT *element); /* Computes the transform relating a surface element to the toplevel element in the * hierarchy by concatenaing the up-transforms of the element and all parent * alements. If the element is a toplevel element, (TRANSFORM *)NULL is * returned and nothing is filled in in xf (no trnasform is necessary * to transform points on the element to the corresponding point on the toplevel * element). In the other case, the composed transform is filled in in xf and * xf (pointer to the transform) is returned. */ extern TRANSFORM2D *ElementToTopTransform(ELEMENT *element, TRANSFORM2D *xf); /* Determines the regular subelement at point (u,v) of the given parent * surface element. Returns the parent element itself if there are no regular * subelements. The point is transformed to the corresponding point on the subelement. */ extern ELEMENT *RegularSubelementAtPoint(ELEMENT *parent, double *u, double *v); /* Returns the leaf regular subelement of 'top' at the point (u,v) (uniform * coordinates!). (u,v) is transformed to the coordinates of the corresponding * point on the leaf element. 'top' is a surface element. */ extern ELEMENT *RegularLeafElementAtPoint(ELEMENT *top, double *u, double *v); /* draws element outline in the current outline color */ extern void DrawElementOutline(ELEMENT *elem); extern void DrawElementOutlineStrong(ELEMENT *elem); /* renders a surface element flat shaded based on its radiance. */ extern void RenderElement(ELEMENT *elem); /* (re)allocates storage for the coefficients to represent radiance, received radiance * and unshot radiance on the element. */ extern void ElementReallocCoefficients(ELEMENT *elem); /* Computes the vertices of a surface element (3 or 4 vertices) or * cluster element (8 vertices). The number of vertices is returned. */ extern int ElementVertices(ELEMENT *elem, POINT *p); /* Computes a bounding box for the element. */ extern float *ElementBounds(ELEMENT *elem, float *bounds); /* Computes the midpoint of the element. */ extern POINT ElementMidpoint(ELEMENT *elem); /* Computes a polygon description for shaft culling for the element. */ extern POLYGON *ElementPolygon(ELEMENT *elem, POLYGON *poly); /* Call func for each leaf element of top */ extern void ForAllLeafElements(ELEMENT *top, void (*func)(ELEMENT *)); /* Call func for each element in the hierarchy with given 'top' */ extern void ForAllElements(ELEMENT *top, void (*func)(ELEMENT *)); #ifdef __cplusplus } #endif #endif /*_ELEMENT_H_*/