/* vertex.c */ #include "vertex.h" #include "patch.h" #include "pools.h" #define NEWVERTEX() (VERTEX *)Alloc(sizeof(VERTEX)) #define DISPOSEVERTEX(ptr) Free((char *)ptr, sizeof(VERTEX)) int nrvertices = 0; /* Create a vertex with given coordinates, normal vector and list of patches * sharing the vertex. Several vertices can share the same coordinates * and normal vector. Several patches can share the same vertex. */ VERTEX *VertexCreate(POINT *point, VECTOR *normal, VECTOR *texCoord, PATCHLIST *patches) { VERTEX *v; v = NEWVERTEX(); v->id = nrvertices++; v->point = point; v->normal = normal; v->texCoord = texCoord; v->patches = patches; RGBSET(v->color, 0., 0., 0.); v->brep_data = (BREP_VERTEX *)NULL; v->radiance_data = (void *)NULL; v->back = (VERTEX *)NULL; return v; } /* destroys the vertex. Does not destroy the coordinate vector and * normal vector, neither the patches sharing the vertex. */ void VertexDestroy(VERTEX *vertex) { PatchListDestroy(vertex->patches); if (vertex->brep_data) BrepDestroyVertex(vertex->brep_data); DISPOSEVERTEX(vertex); nrvertices--; } /* prints the vertex data to the file 'out' */ void VertexPrint(FILE *out, VERTEX *vertex) { fprintf(out, "ID %d: (", vertex->id); VectorPrint(out, *(vertex->point)); fprintf(out, ")"); if (vertex->normal) { fprintf(out, "/("); VectorPrint(out, *(vertex->normal)); fprintf(out, ")"); } else fprintf(out, "/(no normal)"); if (vertex->texCoord) { fprintf(out, "/("); VectorPrint(out, *(vertex->texCoord)); fprintf(out, ")"); } else fprintf(out, "/(no texCoord)"); fprintf(out, " color = ("); RGBPrint(out, vertex->color); fprintf(out, ")," ); fprintf(out, "patches: "); ForAllPatches(P, vertex->patches) { PatchPrintID(out, P); } EndForAll; fprintf(out, "\n"); } /* averages the color of each patch sharing the vertex and assign the * resulting color to the vertex. */ void ComputeVertexColor(VERTEX *vertex) { PATCHLIST *patches; int nrpatches; RGBSET(vertex->color, 0., 0., 0.); nrpatches=0; for (patches=vertex->patches; patches; patches=patches->next) { vertex->color.r += patches->patch->color.r; vertex->color.g += patches->patch->color.g; vertex->color.b += patches->patch->color.b; nrpatches++; } if (nrpatches > 0) { vertex->color.r /= (float)nrpatches; vertex->color.g /= (float)nrpatches; vertex->color.b /= (float)nrpatches; } } /* computes a vertex color for the vertices of the patch */ void PatchComputeVertexColors(PATCH *patch) { int i; for (i=0; inrvertices; i++) ComputeVertexColor(patch->vertex[i]); } static unsigned int vertex_compare_flags = VCMP_LOCATION | VCMP_NORMAL | VCMP_TEXCOORD; unsigned VertexSetCompareFlags(unsigned flags) { unsigned oldflags = vertex_compare_flags; vertex_compare_flags = flags; return oldflags; } /* This routine only compares the location of the two vertices. */ int VertexCompareLocation(VERTEX *v1, VERTEX *v2) { /* two entities intersect if their tolerance region intersects, i.o.w. if * the distance between them is smaller than the sum of the two entity's * tolerances */ float tolerance = VECTORTOLERANCE(*v1->point) + VECTORTOLERANCE(*v2->point); return VectorCompare(v1->point, v2->point, tolerance); } /* This routine only compares the normal of the two vertices. */ int VertexCompareNormal(VERTEX *v1, VERTEX *v2) { int code = VectorCompare(v1->normal, v2->normal, EPSILON); if (code == XYZ_EQUAL && !(vertex_compare_flags & VCMP_NO_NORMAL_IS_EQUAL_NORMAL)) if (v1->normal->x == 0. && v1->normal->y == 0. && v1->normal->z == 0.) return 0; /* no valid normal => not the same vertex */ return code; } /* This routine only compares the texture coordinates of the two vertices. */ int VertexCompareTexCoord(VERTEX *v1, VERTEX *v2) { if (!v1->texCoord) { if (!v2->texCoord) return XYZ_EQUAL; else return 0; /* no coordinate == smaller than any coordinate */ } else { if (!v2->texCoord) return X_GREATER+Y_GREATER+Z_GREATER; /* """""" */ else return VectorCompare(v1->texCoord, v2->texCoord, EPSILON); } } /* Compares two vertices and returns a code useful for ordering vertices * into an octree. Returns 8 if the two vertices are to be considered * the same vertices and 0-7, the index of an octree branch to be expored * further, if not. */ int VertexCompare(VERTEX *v1, VERTEX *v2) { int code = XYZ_EQUAL; /* first compare the coordinates */ if (vertex_compare_flags & VCMP_LOCATION) { code = VertexCompareLocation(v1, v2); if (code != XYZ_EQUAL) return code; } /* same coordinates, test the normals */ if (vertex_compare_flags & VCMP_NORMAL) { code = VertexCompareNormal(v1, v2); if (code != XYZ_EQUAL) return code; } /* same coordinates and same normal, test texture coordinates */ if (vertex_compare_flags & VCMP_TEXCOORD) { code = VertexCompareTexCoord(v1, v2); if (code != XYZ_EQUAL) return code; } return XYZ_EQUAL; }