home *** CD-ROM | disk | FTP | other *** search
- /**********************************************************************/
- /* adj.c: */
- /* */
- /* Calculate vertex and patch / element adjacency and "group" */
- /* together patches, elements and meshes that are "close" to each */
- /* other. Also routines to perform bilinar subdivision. */
- /* */
- /* Copyright (C) 1992, Bernard Kwok */
- /* All rights reserved. */
- /* Revision 1.0 */
- /* May, 1992 */
- /**********************************************************************/
- #include <stdio.h>
- #include <string.h>
- #include <math.h>
- #include "geo.h"
- #include "struct.h"
- #include "io.h"
- #include "rad.h"
- #include "adj.h"
-
- extern OptionType Option;
- extern RadParams ReadLog;
-
- Vertex_tree *vtree = 0; /* global vertex octree */
- unsigned long vtree_size = 0; /* Number of vertices in tree */
- Vertex_list *vlist = 0;
- Vertex_list *vlist_tail = 0;
- unsigned long vlist_size = 0;
- extern RadParams ReadLog; /* Radiosity parameters */
-
- /**********************************************************************/
- /* If we run out of memory... */
- /**********************************************************************/
- void MemError()
- { fprintf(stderr,"No more space to allocate\n"); exit(1); }
-
- /*====================================================================*/
- /* Vertex octree routines */
- /*====================================================================*/
- /**********************************************************************/
- /* Create dummy vertex tree root as "center of the world" */
- /**********************************************************************/
- Vertex_tree *VTree_Create(params)
- RadParams params;
- {
- int s;
- Vertex_tree *optr;
-
- if ((optr = (Vertex_tree *) malloc(sizeof(Vertex_tree))) == 0)
- MemError();
- if ((optr->vtx = (Vertex *) malloc(sizeof(Vertex))) == 0)
- MemError();
-
- /* Vertex is at the center of the world */
- optr->vtx->pos = *vmiddle(¶ms.worldbox.min, ¶ms.worldbox.max);
- optr->vtx->id = -1;
- optr->vtx->name = "World Center";
-
- /* No polys for imaginary vertex */
- optr->vtx->polylist = optr->vtx->polyhead.front =
- optr->vtx->polyhead.front = 0;
- optr->vtx->polyhead.num_polys = 0;
-
- for (s=0;s<num_octants;s++)
- optr->child[s] = 0;
-
- return optr;
- }
-
- /*************************************************************************/
- /* Create vertex tree node with center of octant = vertex */
- /*************************************************************************/
- Vertex_tree *VTree_NodeCreate(v,father)
- Vertex *v;
- Vertex_tree *father;
- {
- int i;
- Vertex_tree *new_vtptr;
-
- if ((new_vtptr = (Vertex_tree *) malloc(sizeof(Vertex_tree))) == 0)
- MemError();
- new_vtptr->vtx = v;
- for (i=0;i<num_octants;i++)
- new_vtptr->child[i] = 0;
- new_vtptr->father = father;
-
- vtree_size++;
- return (new_vtptr);
- }
-
- /**********************************************************************/
- /* Add child to appropriate octant of a vertex-tree node */
- /**********************************************************************/
- void VTree_NodeAddChild(vtx,father,octant)
- Vertex *vtx;
- Vertex_tree *father;
- int octant;
- {
- Vertex_tree *new_vtptr;
-
- /* Allocate space for new vertex tree node */
- new_vtptr = VTree_NodeCreate(vtx,father);
- father->child[octant] = new_vtptr;
- }
-
- /**********************************************************************/
- /* Find which octant of a given tree node, a vector belongs to */
- /* and which octants a cube, centered around the vector */
- /* and within distance (VTX_TOLERANCE) of the vector, belongs to */
- /**********************************************************************/
- int Vtree_VectorOctant(vptr,mid,octants)
- Vector *vptr;
- Vector *mid;
- int octants[num_octants];
- {
- int i,j,k;
- float u,v,w;
- Vector tolerance_cube[num_octants];
- int octant;
-
- u = -1; v = -1; w = -1;
- for(i=0;i<2;i++) {
- for(j=0;j<2;j++) {
- for(k=0;k<2;k++) {
- tolerance_cube[(4*i+2*j+k)].x = vptr->x + u * VTX_TOLERANCE;
- tolerance_cube[(4*i+2*j+k)].y = vptr->y + v * VTX_TOLERANCE;
- tolerance_cube[(4*i+2*j+k)].z = vptr->z + w * VTX_TOLERANCE;
- u = -u;
- }
- v = -v;
- }
- w = -w;
- }
-
- /* Find octants that intersect tolerance cube for vertex */
- for(i=0;i<num_octants;i++) {
- octant = 0; octants[i] = 0;
- if (tolerance_cube[i].x > mid->x) octant++;
- if (tolerance_cube[i].z < mid->z) octant += 2;
- if (tolerance_cube[i].y < mid->y) octant += 4;
- octants[octant] = 1;
- }
- /* Find octant vertex belongs to */
- octant = 0;
- if (vptr->x > mid->x) octant++;
- if (vptr->z < mid->z) octant += 2;
- if (vptr->y < mid->y) octant += 4;
- octants[octant] = 1;
- return octant;
- }
-
- /**********************************************************************/
- /* Find if vertex exist in tree, if does return tree node found in, */
- /* else return not found, and tree node to create */
- /**********************************************************************/
- int VTree_NodeFind(v,vt,pptr,vertex_num)
- Vector v;
- Vertex_tree *vt;
- Polygon *pptr;
- int vertex_num;
- {
- int octants[num_octants]; /* vertex cube octants to search */
- int voctant; /* octant of vertex to search */
- int i, found;
-
- if (vsame(&(vt->vtx->pos), &v, VTX_TOLERANCE)) {
- /* Vertex already exists, just link poly to vertex, and
- vertex to poly */
- LinkPoly_ToVertex(vt->vtx, pptr);
- pptr->vert[vertex_num] = vt->vtx;
- return 1;
-
- } else {
- /* Find which octants to traverse */
- voctant = Vtree_VectorOctant(&v,&(vt->vtx->pos),octants);
-
- found = 0; i=0;
- while((i<num_octants) && (found == 0)) {
-
- /* Search path of vertex -- not used */
- /* if (vt->child[voctant] != 0)
- found = VTree_NodeFind(v,vt->child[voctant],pptr,vertex_num);
- else if (found == 0) {
- pptr->vert[vertex_num] = Vertex_Create(v,pptr);
- VTree_NodeAddChild(pptr->vert[vertex_num],vt,voctant);
- return 1;
- }
- */
-
- /* Search path of vertex tolerance cube */
- if (!found && octants[i]) {
- if (vt->child[i] != 0)
- found = VTree_NodeFind(v,vt->child[i],pptr,vertex_num);
- else if (found == 0) { /* If NOT found, create ONCE */
- pptr->vert[vertex_num] = Vertex_Create(v,pptr);
- VTree_NodeAddChild(pptr->vert[vertex_num],vt,i);
- return 1;
- }
- }
- i++;
- }
- }
- return(found);
- }
-
- /**********************************************************************/
- /* Create new vertex structure, associate a polygon with it */
- /**********************************************************************/
- Vertex *Vertex_Create(position, adjpoly)
- Vector position;
- Polygon *adjpoly;
- {
- Vertex *v;
-
- if ((v = (Vertex *) malloc(sizeof(Vertex))) == 0)
- MemError();
- if ((v->polylist = (PolyList *) malloc(sizeof(PolyList))) == 0)
- MemError();
-
- v->id = vlist_size;
- v->name = "Vertex";
- v->pos = position;
- v->polylist->patch = adjpoly;
- v->polyhead.num_polys = 1;
- v->polyhead.front = v->polyhead.back = v->polylist;
- v->polylist->next = 0;
- return(v);
- }
-
- /**********************************************************************/
- /* Create new polygon for poly list of vertex, update back of list */
- /**********************************************************************/
- void LinkPoly_ToVertex(v, p)
- Vertex *v;
- Polygon *p;
- {
- PolyList *pl;
-
- if ((pl = (PolyList *) malloc(sizeof(PolyList))) == 0)
- MemError();
- pl->patch = p;
- pl->next = 0;
- v->polyhead.back->next = pl;
- v->polyhead.num_polys++;
- v->polyhead.back = pl;
- }
-
- /**********************************************************************/
- /* Vertex v belongs to patch p in position vnum */
- /**********************************************************************/
- void LinkVertex_ToPoly(p, v, vnum)
- Polygon *p;
- Vertex *v;
- int vnum;
- { p->vert[vnum] = v; }
-
- /*====================================================================*/
- /* Bilinear subdivision code */
- /*====================================================================*/
- /**********************************************************************/
- /* Create children for current poly, and assign appropriate values */
- /* and pointers */
- /**********************************************************************/
- void Create_Children(p)
- Polygon *p;
- {
- int i,j,k;
- Polygon *ch;
- char *str = " ";
-
- for(i=0;i<MAX_PATCH_CHILDREN;i++) {
- ReadLog.totpoly++;
- if ((p->child[i] = (Polygon *) malloc(sizeof(Polygon))) == 0)
- MemError();
- ch = p->child[i];
- ch->id = ReadLog.totpoly;
- sprintf(str,"%s_child", p->name);
- ch->name = str;
- ch->class = p->class; /* Preserve shape */
- for(j=0;j<MAX_PATCH_VTX;j++) {
- ch->vert[j] = (Vertex *)NULL;
- ch->normal[j] = p->normal[j];
- }
- ch->changingNormal = 0;
- ch->area = p->area / /* Assume that area is divided
- evenly. */
- (double)(MAX_PATCH_CHILDREN);
- ch->numVert = p->numVert;
- for(k=0;k<MAX_PATCH_CHILDREN;k++)
- ch->child[k] = (Polygon *)NULL;
- ch->d = p->d; /* On same plane */
- ch->level = p->level+1; /* Push down 1 level */
- ch->Mfather = p->Mfather; /* Same mesh */
- if (p->Pfather != NULL) /* Check if root poly or not */
- ch->Pfather = p->Pfather;
- else
- ch->Pfather = p;
- ch->Links = (PolyList *)NULL; /* No form factor links */
- ch->polyhead.front = ch->polyhead.back = ch->Links;
- ch->polyhead.num_polys = 0;
- ch->next = (Polygon *)NULL;
- }
- }
-
- /**********************************************************************/
- /* Create four new points created by subdivision of quad or triangle */
- /* Assume counter clockwise ordering of vertices, from lower left */
- /**********************************************************************/
- void Create_Subdivision_Points(v,nv,num_vert)
- Vector v[4]; /* Poly vertitces */
- Vector nv[5]; /* New poly child vertices */
- int num_vert;
- {
- int i;
-
- if (num_vert == 4) { /* bilinear subdivide a rectangle */
- /* 4 side midpoints, counter-clockwise, and then middle point */
- for(i=0;i<num_vert;i++)
- nv[i] = *vmiddle(&v[i], &v[(i + 1) % 4]);
- nv[num_vert] = *vmiddle(vmiddle(&nv[0], &nv[2]),
- vmiddle(&nv[1], &nv[3]));
-
- } else { /* bilinearly subdivide a triangle */
- /* 3 side midpoints, counter-clockwise */
- for(i=0;i<num_vert;i++)
- nv[i] = *vmiddle(&v[i], &v[(i + 1) % 3]);
- }
- }
-
- /**********************************************************************/
- /* Create children for patch, assign vertices, and adjacency info, */
- /* set radiosity values per vertex and patch */
- /**********************************************************************/
- void Subdivide_Polygon(p)
- Polygon *p;
- {
- int c,s,v,vv;
- int num_vert;
- Vector vert[MAX_PATCH_VTX]; /* Poly vertices */
- Vector new_vert[5]; /* New poly child vertices */
- Spectra corner_B[MAX_PATCH_VTX];
- Spectra new_B[5];
- static int dud = 0;
-
- num_vert = p->numVert;
-
- /* Create new children */
- Create_Children(p);
-
- /* Assign radiosity values for new children: Patch
- (total and unshot) and vertex (total) radiosities. */
- for (s=0;s<MAX_SPECTRA_SAMPLES;s++)
- new_B[num_vert].samples[s] = 0.0;
- for(v=0;v<num_vert;v++) {
- vv = (v+1) % num_vert;
- for (s=0;s<MAX_SPECTRA_SAMPLES;s++) {
- corner_B[v].samples[s] = p->vtx_B[v].samples[s];
- new_B[v].samples[s] = (corner_B[v].samples[s] +
- p->vtx_B[vv].samples[s]) / 2.0;
- new_B[num_vert].samples[s] += (corner_B[v].samples[s] / num_vert);
- }
- }
- for (c=0;c<MAX_PATCH_CHILDREN;c++) {
- for (s=0;s<MAX_SPECTRA_SAMPLES;s++) {
- p->child[c]->unshot_B.samples[s] = p->unshot_B.samples[s];
- p->child[c]->B.samples[s] = p->B.samples[s];
- }
- }
- if (p->class == PATCH)
- for (s=0;s<MAX_SPECTRA_SAMPLES;s++) {
- p->child[0]->vtx_B[0].samples[s] = corner_B[0].samples[s];
- p->child[0]->vtx_B[1].samples[s] = new_B[0].samples[s];
- p->child[0]->vtx_B[2].samples[s] = new_B[4].samples[s];
- p->child[0]->vtx_B[3].samples[s] = new_B[3].samples[s];
-
- p->child[1]->vtx_B[0].samples[s] = new_B[0].samples[s];
- p->child[1]->vtx_B[1].samples[s] = corner_B[1].samples[s];
- p->child[1]->vtx_B[2].samples[s] = new_B[1].samples[s];
- p->child[1]->vtx_B[3].samples[s] = new_B[4].samples[s];
-
- p->child[2]->vtx_B[0].samples[s] = new_B[4].samples[s];
- p->child[2]->vtx_B[1].samples[s] = new_B[1].samples[s];
- p->child[2]->vtx_B[2].samples[s] = corner_B[2].samples[s];
- p->child[2]->vtx_B[3].samples[s] = new_B[2].samples[s];
-
- p->child[3]->vtx_B[0].samples[s] = new_B[3].samples[s];
- p->child[3]->vtx_B[1].samples[s] = new_B[4].samples[s];
- p->child[3]->vtx_B[2].samples[s] = new_B[2].samples[s];
- p->child[3]->vtx_B[3].samples[s] = corner_B[3].samples[s];
- }
- else /* Is a triangle */
- for (s=0;s<MAX_SPECTRA_SAMPLES;s++) {
- p->child[0]->vtx_B[0].samples[s] = corner_B[0].samples[s];
- p->child[0]->vtx_B[1].samples[s] = new_B[0].samples[s];
- p->child[0]->vtx_B[2].samples[s] = new_B[2].samples[s];
-
- p->child[1]->vtx_B[0].samples[s] = new_B[0].samples[s];
- p->child[1]->vtx_B[1].samples[s] = new_B[1].samples[s];
- p->child[1]->vtx_B[2].samples[s] = new_B[2].samples[s];
-
- p->child[2]->vtx_B[0].samples[s] = new_B[0].samples[s];
- p->child[2]->vtx_B[1].samples[s] = corner_B[1].samples[s];
- p->child[2]->vtx_B[2].samples[s] = new_B[1].samples[s];
-
- p->child[3]->vtx_B[0].samples[s] = new_B[2].samples[s];
- p->child[3]->vtx_B[1].samples[s] = new_B[1].samples[s];
- p->child[3]->vtx_B[2].samples[s] = corner_B[2].samples[s];
- }
-
- /* Find points to subdivide along */
- for (v=0;v<num_vert;v++)
- vert[v] = (p->vert[v]->pos);
- Create_Subdivision_Points(vert,new_vert,p->numVert);
-
- if (p->class == PATCH) { /* is a quad */
- /* Child 0 */
- if (vtree == 0) { /* Empty vertex tree */
- p->child[0]->vert[0] = Vertex_Create(vert[0],p->child[0]);
- vtree = VTree_NodeCreate(p->child[0]->vert[0],(Vertex_tree *)NULL);
- } else {
- (void) VTree_NodeFind(vert[0],vtree,p->child[0],0);
- }
- (void) VTree_NodeFind(new_vert[0],vtree,p->child[0],1);
- (void) VTree_NodeFind(new_vert[4],vtree,p->child[0],2);
- (void) VTree_NodeFind(new_vert[3],vtree,p->child[0],3);
-
- /* Child 1 */
- (void) VTree_NodeFind(new_vert[0],vtree,p->child[1],0);
- (void) VTree_NodeFind( vert[1],vtree,p->child[1],1);
- (void) VTree_NodeFind(new_vert[1],vtree,p->child[1],2);
- (void) VTree_NodeFind(new_vert[4],vtree,p->child[1],3);
-
- /* Child 2 */
- (void) VTree_NodeFind(new_vert[4],vtree,p->child[2],0);
- (void) VTree_NodeFind(new_vert[1],vtree,p->child[2],1);
- (void) VTree_NodeFind( vert[2],vtree,p->child[2],2);
- (void) VTree_NodeFind(new_vert[2],vtree,p->child[2],3);
-
- /* Child 3 */
- (void) VTree_NodeFind(new_vert[3],vtree,p->child[3],0);
- (void) VTree_NodeFind(new_vert[4],vtree,p->child[3],1);
- (void) VTree_NodeFind(new_vert[2],vtree,p->child[3],2);
- (void) VTree_NodeFind( vert[3],vtree,p->child[3],3);
-
- } else { /* is a triangle */
-
- /* Child 0 */
- if (vtree == 0) { /* Empty vertex tree */
- p->child[0]->vert[0] = Vertex_Create(vert[0],p->child[0]);
- vtree = VTree_NodeCreate(p->child[0]->vert[0],(Vertex_tree *)NULL);
- } else {
- (void) VTree_NodeFind(vert[0],vtree,p->child[0],0);
- }
- /* (void) VTree_NodeFind(vert[0],vtree,p->child[0],0); */
- (void) VTree_NodeFind(new_vert[0],vtree,p->child[0],1);
- (void) VTree_NodeFind(new_vert[2],vtree,p->child[0],2);
-
- /* Child 1 */
- (void) VTree_NodeFind(new_vert[0],vtree,p->child[1],0);
- (void) VTree_NodeFind(new_vert[1],vtree,p->child[1],1);
- (void) VTree_NodeFind(new_vert[2],vtree,p->child[1],2);
-
- /* Child 2 */
- (void) VTree_NodeFind(new_vert[0],vtree,p->child[2],0);
- (void) VTree_NodeFind( vert[1],vtree,p->child[2],1);
- (void) VTree_NodeFind(new_vert[1],vtree,p->child[2],2);
-
- /* Child 3 */
- (void) VTree_NodeFind(new_vert[2],vtree,p->child[3],0);
- (void) VTree_NodeFind(new_vert[1],vtree,p->child[3],1);
- (void) VTree_NodeFind( vert[2],vtree,p->child[3],2);
- }
-
- dud++;
- }
-
-