Makefile000064400105260001753000000004130642540027000137460ustar00stuerzlcompsci00000000000000CFLAGS = -g -Wall #CFLAGS = -O -Wall CC = gcc CCC = gcc .SUFFIXES : .cc .cc.o: $(CCC) $(CFLAGS) -c $< OBJECTS = arena.o quadedge.o mesh.o hs1.o hs.o geom.o LIBNAME = libhs.a $(LIBNAME): $(OBJECTS) ar cvr $(LIBNAME) $(OBJECTS) clean: rm $(OBJECTS) $(LIBNAME) G)“AíVë4V¿README000064400105260001753000000135550636273311400132070ustar00stuerzlcompsci00000000000000Hemisphere projection by Wolfgang Stuerzlinger (c)95-97 After the disk disaster in June I have finally recovered and recoded the lost routines (This time in C++, which made some things easier, and I got lazy and copied a few routines to make things easier e.g. calc_ff). So the code is an odd mixture of C & C++, but it works. The external interface is C though. There are a few possibilities to call this code, using a few pseudo-code-examples I will try to show how to use the code: I assume you have the following data per surface: # of vertices (maximum is something like 20 kMaxPolyPoints) the vertices (convex polygon!) normal (normalized) n_dot_p numeric id (0-0x0FFFFFFF) Intersecting surfaces are not accounted for. If you get funny results, maybe you are using not the correct polygon vertex order (ccw if seen from above). 1) This example shows how to project surfaces onto the HS and the find the formfactors for them. #include "hsphere.h" TPoint3f center; // projection center; TVector3f normal,tangentU,tangentV; // proj normal & tang vec's. double formfactor[# of surfaces]; // here are results TPolygon pol; TPlane plane; InitHS(¢er,&plane,&tangentU,&tangentV,formfactor); for all surfaces..... { pol.n = surface.# of vertices; for all vertices pol.vert[i] = surface.vert[i]; plane.normal = surface.normal; plane.np = surface.n_dot_p; ProjectPolygonHS(&pol,&plane,surface.id,surface.id); } EndHS(0); // release memory.... irradiance = 0; // example usage for all surfaces: irradiance += surface.radiance * formfactor[i]; There is no need to clip a surface at the projection plane, it is done by ProjectPolygon. 2) A little more involved is the case of surfaces which are subdivided in elements. To find the formfactors of the elements we could use method 1) but the visibility is already resolved after projecting the surfaces therefore the follwing is a lot faster... ... same as above ... for all surfaces..... { ... same as above ... ProjectPolygonHS(&pol,&plane,SURFACE_ID + surface.id, SURFACE_ID + surface.id); } EndHS(1); // statistics, do not release memory.... double ff,covered; irradiance = 0; // example usage for all elements..... { pol.n = element.# of vertices; for all vertices pol.vert[i] = element.vert[i]; plane.normal = element.normal; plane.np = element.n_dot_p; ff = TestPolygonHS(&pol,&plane,element.id, SURFACE_ID + element.surface.id,&covered); // ff is the full formfactor (for reference; // covered is the formfactor of the visibile part irradiance += element.radiance * covered; // example usage // another possibility is: formfactor[element.id] = covered // but then: double formfactor[# of elements]! } EndHS(0); // release resources... First all surfaces are projected, then all elements are tested how much is visible of them and their formfactor is returned in the last parameter (covered in the example). ************************************************************************** Now to something completely different: internal details: The underlying datastructure is a quadedge representation of the partition of the hemisphere - and to make thing's a little easier only convex polygons are stored - i.e. nonconvex visible parts are split into (more) convex parts. To speed everything up I used a modified BSP tree (Binary Hemisphere Subdivision Tree = BHSP). Each leaf node points to an edge of an quadedge datastructure. I tried to keep the used algorithms simple & stable, therefore there is some extra splitting going on sometimes. I have already used a scene with 50000+ polygons with this code and it is resonably stable. hsphere.h: include file for external interface hs.cc: main module hs1.cc: support routines, interface to quadedge mesh.*: quadedge (see GGems code by Lischinski) quadedge.*: quadedge (see GGems code by Lischinski) geom.*: support routines and 3d vector macros geom3d.h: C++ 3d vector lib arena.*: simple memory management using C++ features ************************************************************************** How to walk through the whole thing: If you want to iterate over all projected polygon parts your code will have to look like: do_something(BHSP *tree) { // for the fields of tree see hs_int.h Edge *e; e = tree->pol; do { cerr << e->Org()->p; // just print out vertices e = e->Next(); } while (e != tree->pol); } recursive_routine(BHSP *tree) { switch (tree->kind) { case NODE: recursive_routine(tree->before); recursive_routine(tree->behind); break; case IN: if (tree->id != BACKGROUND_ID) // something projected there do_something(tree); break; case KILL: // ignore break; } } interface() { recursive_routine(root); // root is in hs.cc } One use for this code skeleton is the display of the hemisphere to verify things. Just use the vertices of each tree->pol to define a (nonplanar) polygon and display the whole thing, looks quite nice though a little rough due to the polygonalization ;-) ************************************************************************** Usual claimers/disclaimers apply. No warranty whatsoever. (c)95-97 by Wolfgang Stuerzlinger ************************************************************************** in hs.cc } One use for this code skeleton is the display of the hemisphere to verify things. Just use the vertices of each tree->pol to definearena.cc000064400105260001753000000017320601011407700137050ustar00stuerzlcompsci00000000000000/****************************************************************************** * arena.cc * Memory arena management * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #include #include #include "arena.h" const int ARENA_BLOCK_SIZE = 32768; const int ARENA_ALIGN = sizeof(double); #define ALIGN(x) ((((x) - 1) / ARENA_ALIGN + 1) * ARENA_ALIGN) void* Arena::alloc(size_t size) { void *temp; if (! block || offset + size > ARENA_BLOCK_SIZE) { block = calloc(ARENA_BLOCK_SIZE,1); if (! block) error("no more mem for arena"); *(void **)block = list; list = block; offset = ALIGN(sizeof(void **)); cnt++; } temp = (void*) ((char*) block + offset); offset += ALIGN(size); return(temp); } Arena::~Arena() { void *temp; while (list) { temp = *(void**) list; free(list); list = temp; } } void* operator new(size_t size, Arena *arena) { return arena->alloc(size); } mp; if (! block || offset + size > Aarena.h000064400105260001753000000012410601011420400135320ustar00stuerzlcompsci00000000000000/****************************************************************************** * arena.h * Memory Management * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #ifndef ARENA_H #define ARENA_H #include class Arena { private: void *block; void *list; int offset; int cnt; public: Arena() { block = 0; list = 0; offset = 0; cnt = 0; } ~Arena(); void* alloc(size_t size); }; void* operator new(size_t size, Arena* arena); extern Arena* my_arena; extern "C" { // shouldn't be here, but.... /* geom.c */ void message(char const *fmt, ...); void error(char const *fmt, ...); }; #endif ************************************************************/ #ifndef ARENA_H #define ARENA_H #include class Arena { private: void *block; void *list; int offset; int cnt; public: Arena() { block = 0; list = 0; offset = 0; cnt = 0; } ~Arena(); void* alloc(size_t size); }; void* operator new(size_t size, Arena* arena); extern geom.c000064400105260001753000000070450642537736400134320ustar00stuerzlcompsci00000000000000/****************************************************************************** * geom.c * geometric support routines * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #include #include #include #include #include #include #include "geom.h" void error(char const *fmt, ...) { va_list arg_ptr; char buffer[512]; va_start(arg_ptr,fmt); vsprintf(buffer,fmt,arg_ptr); va_end(arg_ptr); fprintf(stderr,"### ERROR: %s\n",buffer); fflush(stderr); abort(); } void message(char const *fmt, ...) { va_list arg_ptr; char buffer[512]; va_start(arg_ptr,fmt); vsprintf(buffer,fmt,arg_ptr); va_end(arg_ptr); fputs(buffer,stdout); fflush(stdout); } double areaPoly(TPoint3f *Q,int nPts) { int i; double area,sum_area; TVector3f u,v,uxv; sum_area = 0.0; SubVector(u,Q[1],Q[0]); for (i = 2; i < nPts; i++) { /* sum up the triangles */ v = u; SubVector(u,Q[i],Q[0]); CrossVector(uxv,u,v); area = LenVector(uxv); sum_area += area; } area = sum_area * 0.5; /* as we use triangles */ if (area < 0.0) error("areaPoly: illegal polygon"); return(area); } /********************** Polygon clipper ***************************/ /* * homogeneous 3-D convex polygon clipper * * Adapted to arbitrary planes by wRZL, Oct 1993 * original by Paul Heckbert 1985, Dec 1989 * * poly_clip_to_plane: Clip the convex polygon p1 to the given plane * using the homogeneous screen coordinates (sx, sy, sz, sw) of each vertex, * If polygon is entirely front of plane, then POLY_CLIP_IN is returned. * If polygon is entirely behind of plane, then POLY_CLIP_OUT is returned. * Otherwise, if the polygon is cut by the plane, p1 is modified and * POLY_CLIP_SPLIT is returned. */ int poly_clip_to_plane(TPolygon *p1,TPolygon *p2,TPlane *plane1,TPlane *plane) { int behind,i; double t, tu, tv; TPoint3f temp; TPoint3f *v, *u; static double ndotp[kMaxPolyPoints + 1]; /* adr: from p1->n downto 1 */ if (PointEqual(plane1->normal,plane->normal)) { if (plane1->np == plane->np) { p2->n = 0; return(POLY_CLIP_BEHIND); } } /* count vertices "behind" with respect to the plane */ behind = 0; for (v = p1->vert, i = p1->n; i > 0; i--, v++) { ndotp[i] = DotVector(*v,plane->normal); if (ndotp[i] < plane->np) behind++; } if (behind == 0) { /* check if all vertices are front */ memcpy(p2, p1, sizeof(TPolygon) - (kMaxPolyPoints-p1->n) * sizeof(TPoint3f)); return (POLY_CLIP_FRONT); } if (behind == p1->n) { /* check if all vertices are behind */ p2->n = 0; return (POLY_CLIP_BEHIND); } /* now clip against the plane */ p2->n = 0; u = &p1->vert[p1->n - 1]; /* start with u=vert[n-1], v=vert[0] */ tu = - ndotp[1] + plane->np; for (v = p1->vert, i = p1->n; i > 0; i--, u = v, tu = tv, v++) { /* on old polygon (p1), u is previous vertex, v is current vertex */ /* tv is negative if vertex v is in */ tv = - ndotp[i] + plane->np; if ((tu <= 0.0) ^ (tv <= 0.0)) { /* edge crosses plane */ t = tu / (tu - tv); /* add intersection point to p2 */ SubVector(temp,*v,*u); /* vert[p2->n] = u+t*(v-u) */ ScaleVector(temp,t); AddVector(p2->vert[p2->n],*u,temp); p2->n++; } if (tv <= 0.0) /* vertex v is in, copy it to p2 */ p2->vert[p2->n++] = *v; } if (p2->n == 0) return (POLY_CLIP_BEHIND); return (POLY_CLIP_SPLIT); } vertex */ /* tv is negative if vertex v is in */ tv = - ndotp[i] + plane->np; if ((tu <= 0.0) ^ (tv <= 0.0)) { /* edge crosses plane */ t = tu / (tu - tv); /* add intersection point to p2 */ SubVector(temp,*v,*u); /* vert[p2->n] = u+t*(v-u) */ ScaleVector(temp,t); AddVector(p2->vert[p2->n],*u,temp); p2->n++; } if (tv <= 0.0) /* vertex v is in, copy it to p2 */ p2->vert[p2->n++] = *v; } if (p2->n == 0) return (POLY_CLIP_BEHIgeom.h000064400105260001753000000506650601011433100134120ustar00stuerzlcompsci00000000000000/****************************************************************************** * geom.h * 2d & 3d Vector routines for C * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #ifndef GEOM_H #define GEOM_H #define DBL (double) #define InitPoint(p,x1,y1,z1) (p).x=x1, (p).y=y1, (p).z=z1 #define ZeroVector(a) (a).x = 0.0, (a).y = 0.0, (a).z = 0.0 #define PointEqual(a,b) ((a).x == (b).x && (a).y == (b).y && (a).z == (b).z) #define NegVector(a) (a).x = (fabs((a).x) != 0.0) ? -(a).x : 0.0, \ (a).y = (fabs((a).y) != 0.0) ? -(a).y : 0.0, \ (a).z = (fabs((a).z) != 0.0) ? -(a).z : 0.0 #define AbsVector(c,a) (c).x=fabs((a).x),(c).y=fabs((a).y),(c).z=fabs((a).z) #define AddVector(c,a,b) (c).x=(a).x+(b).x, (c).y=(a).y+(b).y, (c).z=(a).z+(b).z #define SubVector(c,a,b) (c).x=(a).x-(b).x, (c).y=(a).y-(b).y, (c).z=(a).z-(b).z #define CrossVector(c,a,b) \ (c).x = DBL (a).y*(b).z - DBL (a).z*(b).y, \ (c).y = DBL (a).z*(b).x - DBL (a).x*(b).z, \ (c).z = DBL (a).x*(b).y - DBL (a).y*(b).x #define DotVector(a,b) (DBL (a).x*(b).x + DBL (a).y*(b).y + DBL (a).z*(b).z) #define ScaleVector(c,s) (c).x*=(s), (c).y*=(s), (c).z*=(s) #define NormalizeVector(n,a) ((n)=sqrt(DotVector(a,a)), \ (n)?((a).x/=n, (a).y/=n, (a).z/=n):0.0) #define DistPnt_2(a,b) ((DBL (b).x - (a).x) * (DBL (b).x - (a).x) + \ (DBL (b).y - (a).y) * (DBL (b).y - (a).y) + \ (DBL (b).z - (a).z) * (DBL (b).z - (a).z)) #define DistPnt(a,b) sqrt(DistPnt2(a,b)) #define LenVector(a) sqrt(DotVector(a,a)) #define AvgVector(c,a,b) (c).x=((a).x+(b).x) * 0.5, (c).y=((a).y+(b).y) * 0.5, \ (c).z=((a).z+(b).z) * 0.5 #define VolVector(a,b,c) \ ((a).x*(b).y*(c).z + (a).y*(b).z*(c).x + (a).z*(b).x*(c).y - \ (a).z*(b).y*(c).x - (a).x*(b).z*(c).y - (a).y*(b).x*(c).z) #define DistPt2Plane(p,n,np) (DotVector(n,p) - (np)) #define Inplane(p,n,np) (fabs(DistPt2Plane(p,n,np)) < 1E-14) #define InsideBbox(mini,maxi,p) ((p).x >= (mini).x && (p).x <= (maxi).x && \ (p).y >= (mini).y && (p).y <= (maxi).y && \ (p).z >= (mini).z && (p).z <= (maxi).z) #define MakeBbox(mini,maxi,point) { \ if ((point).x < (mini).x) (mini).x = (point).x; \ if ((point).x > (maxi).x) (maxi).x = (point).x; \ if ((point).y < (mini).y) (mini).y = (point).y; \ if ((point).y > (maxi).y) (maxi).y = (point).y; \ if ((point).z < (mini).z) (mini).z = (point).z; \ if ((point).z > (maxi).z) (maxi).z = (point).z; } #define JoinBbox(min1,max1,min2,max2) { \ if ((min2).x < (min1).x) (min1).x = (min2).x; \ if ((min2).y < (min1).y) (min1).y = (min2).y; \ if ((min2).z < (min1).z) (min1).z = (min2).z; \ if ((max2).x > (max1).x) (max1).x = (max2).x; \ if ((max2).y > (max1).y) (max1).y = (max2).y; \ if ((max2).z > (max1).z) (max1).z = (max2).z; } #define BboxOutside(min1,max1,min2,max2) \ ((min1).x > (max2).x || (min1).y > (max2).y || (min1).z > (max2).z || \ (max1).x < (min2).x || (max1).y < (min2).y || (max1).z < (min2).z) #define FindProject(norm,project) { \ TVector3f _n; \ AbsVector(_n,norm); \ if (_n.x > _n.y && _n.x > _n.z) \ project = ((norm).x >= 0.0) ? 0 : 3; \ else if (_n.y > _n.z) \ project = ((norm).y >= 0.0) ? 4 : 1; \ else \ project = ((norm).z >= 0.0) ? 2 : 5; } #define Project2d(project,d3,d2) switch (project) { \ case 0: (d2).u = (d3).y; (d2).v = (d3).z; break; \ case 1: (d2).u = (d3).x; (d2).v = (d3).z; break; \ case 2: (d2).u = (d3).x; (d2).v = (d3).y; break; \ case 3: (d2).u = -(d3).y; (d2).v = (d3).z; break; \ case 4: (d2).u = -(d3).x; (d2).v = (d3).z; break; \ case 5: (d2).u = -(d3).x; (d2).v = (d3).y; break; } #define Project3d(surf,d2,d3) switch ((surf).project) { \ case 0: (d3).y = (d2).u; (d3).z = (d2).v; \ (d3).x = ((surf).ndotp - (d3).y * (surf).normal.y - \ (d3).z * (surf).normal.z) / (surf).normal.x; break; \ case 1: (d3).x = (d2).u; (d3).z = (d2).v; \ (d3).y = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).z * (surf).normal.z) / (surf).normal.y; break; \ case 2: (d3).x = (d2).u; (d3).y = (d2).v; \ (d3).z = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).y * (surf).normal.y) / (surf).normal.z; break; \ case 3: (d3).y = -(d2).u; (d3).z = (d2).v; \ (d3).x = ((surf).ndotp - (d3).y * (surf).normal.y - \ (d3).z * (surf).normal.z) / (surf).normal.x; break; \ case 4: (d3).x = -(d2).u; (d3).z = (d2).v; \ (d3).y = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).z * (surf).normal.z) / (surf).normal.y; break; \ case 5: (d3).x = -(d2).u; (d3).y = (d2).v; \ (d3).z = ((surf).ndotp - (d3).x * (surf).normal.x - \ (d3).y * (surf).normal.y) / (surf).normal.z; break; } #define InitPoint2(p,x,y) (p).u=x, (p).v=y #define PointEqual2(a,b) ((a).u == (b).u && (a).v == (b).v) #define PointNear2(a,b,eps) (fabs((a).u - (b).u) < (eps) && \ fabs((a).v - (b).v) < (eps)) #define NegVector2(a) (a).u = ((a).u) ? -(a).u : 0.0, \ (a).v = ((a).v) ? -(a).v : 0.0 #define AbsVector2(c,a) (c).u=fabs((a).u),(c).v=fabs((a).v) #define AddVector2(c,a,b) (c).u=(a).u+(b).u, (c).v=(a).v+(b).v #define SubVector2(c,a,b) (c).u=(a).u-(b).u, (c).v=(a).v-(b).v #define ScaleVector2(c,s) (c).u*=(s), (c).v*=(s) #define AvgVector2(c,a,b) (c).u=((a).u+(b).u) * 0.5, (c).v=((a).v+(b).v) * 0.5 #define DotVector2(a,b) ((a).u*(b).u + (a).v*(b).v) #define CrossVector2(a,b) ((a).u*(b).v - (a).v*(b).u) #define DistPnt2_2(a,b) (((b).u - (a).u) * ((b).u - (a).u) + \ ((b).v - (a).v) * ((b).v - (a).v)) #define DistPnt2(a,b) sqrt(DistPnt2_2(a,b)) #define LenVector2(a) sqrt(DotVector2(a,a)) #define NormalizeVector2(n,a) ((n)=sqrt(DotVector2(a,a)), \ (n)?((a).u/=n, (a).v/=n):0.0) #define TurnVector2Left2(c,a) (c).u = ((a).v)?-(a).v:0.0, (c).v = (a).u #define TurnVector2Right2(c,a) (c).u = (a).v, (c).v = ((a).u)?-(a).u:0.0 #define DistPt2Line(p,n,np) (DotVector2(n,p) - (np)) #define RightofPoints2(v1,v2,p) (calc_side(v1,v2,p) > 0.0) #define OutsideBbox2(mini,maxi,p) ((p).u < (mini).u || (p).u > (maxi).u || \ (p).v < (mini).v || (p).v > (maxi).v) #define InsideBbox2(mini,maxi,p) ((p).u >= (mini).u && (p).u <= (maxi).u && \ (p).v >= (mini).v && (p).v <= (maxi).v) #define BboxOutside2(min1,max1,min2,max2) \ ((min1).u > (max2).u || (min1).v > (max2).v || \ (max1).u < (min2).u || (max1).v < (min2).v) #define MakeBbox2(mini,maxi,point) { \ if ((point).u < (mini).u) (mini).u = (point).u; \ if ((point).u > (maxi).u) (maxi).u = (point).u; \ if ((point).v < (mini).v) (mini).v = (point).v; \ if ((point).v > (maxi).v) (maxi).v = (point).v; } #define Projectd1(project,d2) ((project == 0) ? (d2).v : (d2).u) #define FindProject2(d2) ((fabs((d2).u) > fabs((d2).v)) ? 0 : 1) #define Projectd2(project,normal,ndotp,d2,d) if (project == 0) { \ (d2).v = d; (d2).u = (ndotp - (d2).v * (normal).v) / (normal).u; } \ else { (d2).u = d; (d2).v = (ndotp - (d2).u * (normal).u) / (normal).v; } #define Convert3To2(project,p3,p2) \ { int _i; (p2).n = (p3).n; \ for (_i = 0; _i < (p3).n; _i++) \ Project2d(project,(p3).vert[_i],(p2).vert[_i]); } #define Convert2To3(surf,p2,p3) \ { int _i; (p3).n = (p2).n; \ for (_i = 0; _i < (p2).n; _i++) \ Project3d(surf,(p2).vert[_i],(p3).vert[_i]); } #define sign(x) ((x > 0) ? 1 : ((x < 0) ? -1 : 0)) #define v3pmulm(p1,m,p) \ { \ p.x = (p1).x * m[0][0] + (p1).y * m[1][0] + \ (p1).z * m[2][0] + m[3][0]; \ p.y = (p1).x * m[0][1] + (p1).y * m[1][1] + \ (p1).z * m[2][1] + m[3][1]; \ p.z = (p1).x * m[0][2] + (p1).y * m[1][2] + \ (p1).z * m[2][2] + m[3][2]; \ } #define v4pmulm(p1,m,p,w) \ { \ p.x = p1.x * m[0][0] + p1.y * m[1][0] + \ p1.z * m[2][0] + m[3][0]; \ p.y = p1.x * m[0][1] + p1.y * m[1][1] + \ p1.z * m[2][1] + m[3][1]; \ p.z = p1.x * m[0][2] + p1.y * m[1][2] + \ p1.z * m[2][2] + m[3][2]; \ w = p1.x * m[0][3] + p1.y * m[1][3] + \ p1.z * m[2][3] + m[3][3]; \ } #define v3vmulm(v1,m,v) \ { \ v.x = v1.x * m[0][0] + v1.y * m[1][0] + \ v1.z * m[2][0]; \ v.y = v1.x * m[0][1] + v1.y * m[1][1] + \ v1.z * m[2][1]; \ v.z = v1.x * m[0][2] + v1.y * m[1][2] + \ v1.z * m[2][2]; \ } #define m3trans(xt,yt,zt,one,two) \ { \ one[3][0] += xt; \ one[3][1] += yt; \ one[3][2] += zt; \ two[3][0] -= two[0][0] * xt + two[1][0] * yt + \ two[2][0] * zt; \ two[3][1] -= two[0][1] * xt + two[1][1] * yt + \ two[2][1] * zt; \ two[3][2] -= two[0][2] * xt + two[1][2] * yt + \ two[2][2] * zt; \ } #define m3rotx(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][1]; \ one[0][1] = _t * _c - one[0][2] * _s; \ one[0][2] = _t * _s + one[0][2] * _c; \ _t = one[1][1]; \ one[1][1] = _t * _c - one[1][2] * _s; \ one[1][2] = _t * _s + one[1][2] * _c; \ _t = one[2][1]; \ one[2][1] = _t * _c - one[2][2] * _s; \ one[2][2] = _t * _s + one[2][2] * _c; \ _t = one[3][1]; \ one[3][1] = _t * _c - one[3][2] * _s; \ one[3][2] = _t * _s + one[3][2] * _c; \ _t = two[1][0]; \ two[1][0] = _t * _c - two[2][0] * _s; \ two[2][0] = _t * _s + two[2][0] * _c; \ _t = two[1][1]; \ two[1][1] = _t * _c - two[2][1] * _s; \ two[2][1] = _t * _s + two[2][1] * _c; \ _t = two[1][2]; \ two[1][2] = _t * _c - two[2][2] * _s; \ two[2][2] = _t * _s + two[2][2] * _c; \ } #define m3roty(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][0]; \ one[0][0] = _t * _c + one[0][2] * _s; \ one[0][2] = -_t * _s + one[0][2] * _c; \ _t = one[1][0]; \ one[1][0] = _t * _c + one[1][2] * _s; \ one[1][2] = -_t * _s + one[1][2] * _c; \ _t = one[2][0]; \ one[2][0] = _t * _c + one[2][2] * _s; \ one[2][2] = -_t * _s + one[2][2] * _c; \ _t = one[3][0]; \ one[3][0] = _t * _c + one[3][2] * _s; \ one[3][2] = -_t * _s + one[3][2] * _c; \ _t = two[0][0]; \ two[0][0] = _t * _c + two[2][0] * _s; \ two[2][0] = -_t * _s + two[2][0] * _c; \ _t = two[0][1]; \ two[0][1] = _t * _c + two[2][1] * _s; \ two[2][1] = -_t * _s + two[2][1] * _c; \ _t = two[0][2]; \ two[0][2] = _t * _c + two[2][2] * _s; \ two[2][2] = -_t * _s + two[2][2] * _c; \ } #define m3rotz(alpha,one,two) \ { \ double _t; \ double _s = sin(alpha); \ double _c = cos(alpha); \ \ _t = one[0][0]; \ one[0][0] = _t * _c - one[0][1] * _s; \ one[0][1] = _t * _s + one[0][1] * _c; \ _t = one[1][0]; \ one[1][0] = _t * _c - one[1][1] * _s; \ one[1][1] = _t * _s + one[1][1] * _c; \ _t = one[2][0]; \ one[2][0] = _t * _c - one[2][1] * _s; \ one[2][1] = _t * _s + one[2][1] * _c; \ _t = one[3][0]; \ one[3][0] = _t * _c - one[3][1] * _s; \ one[3][1] = _t * _s + one[3][1] * _c; \ _t = two[0][0]; \ two[0][0] = _t * _c - two[1][0] * _s; \ two[1][0] = _t * _s + two[1][0] * _c; \ _t = two[0][1]; \ two[0][1] = _t * _c - two[1][1] * _s; \ two[1][1] = _t * _s + two[1][1] * _c; \ _t = two[0][2]; \ two[0][2] = _t * _c - two[1][2] * _s; \ two[1][2] = _t * _s + two[1][2] * _c; \ } #define m3scale(xs,ys,zs,one,two) \ { \ double _x = 1.0 / (xs); \ double _y = 1.0 / (ys); \ double _z = 1.0 / (zs); \ \ one[0][0] *= xs; \ one[0][1] *= ys; \ one[0][2] *= zs; \ one[1][0] *= xs; \ one[1][1] *= ys; \ one[1][2] *= zs; \ one[2][0] *= xs; \ one[2][1] *= ys; \ one[2][2] *= zs; \ one[3][0] *= xs; \ one[3][1] *= ys; \ one[3][2] *= zs; \ two[0][0] *= _x; \ two[0][1] *= _x; \ two[0][2] *= _x; \ two[1][0] *= _y; \ two[1][1] *= _y; \ two[1][2] *= _y; \ two[2][0] *= _z; \ two[2][1] *= _z; \ two[2][2] *= _z; \ } #ifdef NEVER #define m3mmulm(m1,m2,m)\ {\ m[0][0] =m1[0][0] * m2[0][0] + m1[0][1] * m2[1][0] +\ m1[0][2] * m2[2][0];\ m[0][1] =m1[0][0] * m2[0][1] + m1[0][1] * m2[1][1] +\ m1[0][2] * m2[2][1];\ m[0][2] =m1[0][0] * m2[0][2] + m1[0][1] * m2[1][2] +\ m1[0][2] * m2[2][2];\ m[1][0] =m1[1][0] * m2[0][0] + m1[1][1] * m2[1][0] +\ m1[1][2] * m2[2][0];\ m[1][1] =m1[1][0] * m2[0][1] + m1[1][1] * m2[1][1] +\ m1[1][2] * m2[2][1];\ m[1][2] =m1[1][0] * m2[0][2] + m1[1][1] * m2[1][2] +\ m1[1][2] * m2[2][2];\ m[2][0] =m1[2][0] * m2[0][0] + m1[2][1] * m2[1][0] +\ m1[2][2] * m2[2][0];\ m[2][1] =m1[2][0] * m2[0][1] + m1[2][1] * m2[1][1] +\ m1[2][2] * m2[2][1];\ m[2][2] =m1[2][0] * m2[0][2] + m1[2][1] * m2[1][2] +\ m1[2][2] * m2[2][2];\ m[3][0] =m1[3][0] * m2[0][0] + m1[3][1] * m2[1][0] +\ m1[3][2] * m2[2][0] + m2[3][0];\ m[3][1] =m1[3][0] * m2[0][1] + m1[3][1] * m2[1][1] +\ m1[3][2] * m2[2][1] + m2[3][1];\ m[3][2] =m1[3][0] * m2[0][2] + m1[3][1] * m2[1][2] +\ m1[3][2] * m2[2][2] + m2[3][2];\ } #endif #define m3unit(m)\ { \ m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; \ m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; \ m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; \ m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; \ } #define m3copy(m,m1)\ { \ m1[0][0] = m[0][0]; m1[0][1] = m[0][1]; m1[0][2] = m[0][2]; \ m1[1][0] = m[1][0]; m1[1][1] = m[1][1]; m1[1][2] = m[1][2]; \ m1[2][0] = m[2][0]; m1[3][1] = m[3][1]; m1[2][2] = m[2][2]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; m1[3][2] = m[3][2]; \ } #define m4unit(m)\ { \ m[0][0] = 1.0; m[0][1] = 0.0; m[0][2] = 0.0; m[0][3] = 0.0; \ m[1][0] = 0.0; m[1][1] = 1.0; m[1][2] = 0.0; m[1][3] = 0.0; \ m[2][0] = 0.0; m[2][1] = 0.0; m[2][2] = 1.0; m[2][3] = 1.0; \ m[3][0] = 0.0; m[3][1] = 0.0; m[3][2] = 0.0; m[3][3] = 0.0; \ } #define m4copy(m,m1)\ { \ m1[0][0] = m[0][0]; m1[0][1] = m[0][1]; \ m1[0][2] = m[0][2]; m1[0][3] = m[0][3]; \ m1[1][0] = m[1][0]; m1[1][1] = m[1][1]; \ m1[1][2] = m[1][2]; m1[1][3] = m[1][3]; \ m1[2][0] = m[2][0]; m1[3][1] = m[3][1]; \ m1[2][2] = m[2][2]; m1[2][3] = m[2][3]; \ m1[3][0] = m[3][0]; m1[3][1] = m[3][1]; \ m1[3][2] = m[3][2]; m1[3][3] = m[3][3]; \ } typedef double mat3[4][3]; typedef double mat4[4][4]; typedef struct { float u,v; } TPoint2f; typedef struct { float x, y, z; } TPoint3f; /* to save space */ typedef TPoint2f TVector2f; typedef TPoint3f TVector3f; typedef struct TPlane { TVector3f normal; double np; } TPlane; #define kMaxPolyPoints 20 typedef struct TPolygon { int n; TPoint3f vert[kMaxPolyPoints]; } TPolygon; #define kBigPolyPoints 512 typedef struct TBigPolygon { int n; TPoint3f vert[kBigPolyPoints]; } TBigPolygon; typedef struct TBox2 { TPoint2f min; TPoint2f max; } TBox2; typedef struct TPoly2 { int n; int level; int leaf; TPoint2f vert[kMaxPolyPoints]; } TPoly2; typedef struct { TPoint3f origin; /* ray origin */ TVector3f direction; /* ray direction */ double minDistance; /* min distance */ double maxDistance; /* max distance */ } TRay; /******************************** prototypes ******************************/ /* make it C++ friendly */ #ifdef __cplusplus extern "C" { #endif /* geom.c */ #ifdef NOTNOW int intersect(TRay *ray,TSurface *surf); #endif int RayBoxIntersect(TRay *ray, TPoint3f *mini, TPoint3f *maxi); void randAreas(TPoint3f *Q,int nPts,double *areas); void randPointPoly(TPoint3f *Q,double *areas,int nPts,TPoint3f *rand_point); double calc_side(TPoint2f *v1,TPoint2f *v2,TPoint2f *p2); int isonline(TPoint2f *x,TPoint2f *a,TPoint2f *b); int poly_clip_to_plane(TPolygon *p1,TPolygon *p2,TPlane *plane1,TPlane *plane); #define POLY_CLIP_FRONT 0 #define POLY_CLIP_BEHIND 1 #define POLY_CLIP_SPLIT 2 /* geom1.c */ double areaPoly(TPoint3f *Q,int nPts); void calcCenterPoly(TPoint3f *Q,int nPts,TPoint3f *center); int isConvex(TPoint2f *vert,int nPts,int *reflex_ind); void splitSimplePolInto4(TPoly2 *any,TPoly2 *pol); #ifdef __cplusplus }; #endif #endif (TPoint2f *v1,TPoint2f *v2,TPoint2f *p2); int isonline(TPoint2f *x,TPoint2fgeom3d.h000064400105260001753000000304570601011435700136460ustar00stuerzlcompsci00000000000000/****************************************************************************** * geom3d.h * 3d geometric library * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #ifndef GEOM3d_H #define GEOM3d_H #include #include #include #ifndef ABS #define ABS(a) ((a) >= 0 ? (a) : -(a)) #endif #ifndef MAX #define MAX(a, b) ((a) >= (b) ? (a) : (b)) #define MIN(a, b) ((a) <= (b) ? (a) : (b)) #endif #ifndef TRUE #define FALSE 0 #define TRUE 1 #endif #define EPS 1.0E-6 typedef float Real; #define REAL_MAX FLT_MAX class Matrix3d; // fwd decl class Vector3d { public: Real x, y, z; Vector3d() { x = 0; y = 0; z = 0; } Vector3d(Real c) { x = c; y = c; z = c; } Vector3d(Real a,Real b,Real c) { x = a; y = b; z = c; } Vector3d(const Vector3d& p) { x = p.x; y = p.y; z = p.z; } Real length_2() const; Real norm() const; void normalize(); Real& operator [](int); const Real& operator [](int) const; int operator==(const Vector3d&) const; int operator!=(const Vector3d&) const; Vector3d& operator=(const Vector3d&); Vector3d& operator+=(const Vector3d&); Vector3d& operator-=(const Vector3d&); Vector3d& operator*=(const Vector3d&); Vector3d& operator*=(Real); Vector3d& operator/=(Real); Vector3d operator+() const; // unary + Vector3d operator+(const Vector3d&) const; Vector3d operator-() const; // unary - Vector3d operator-(const Vector3d&) const; Vector3d operator^(const Vector3d&) const; // cross product friend inline Vector3d operator*(Real, const Vector3d&); friend inline Vector3d operator*(const Vector3d&, Real); friend inline Vector3d operator*(const Vector3d&, const Matrix3d&); friend inline Vector3d operator*(const Matrix3d&, const Vector3d&); friend inline Real operator*(const Vector3d&, const Vector3d&); friend inline Vector3d operator/(const Vector3d&, Real); friend inline Matrix3d mprod(const Vector3d&, const Vector3d&); friend inline istream& operator>>(istream&, Vector3d&); friend inline ostream& operator<<(ostream&, const Vector3d&); }; typedef Vector3d Point3d; inline Vector3d& Vector3d::operator=(const Vector3d& v) { x = v.x; y = v.y; z = v.z; return(*this); } inline Vector3d Vector3d::operator-(const Vector3d& v) const { return Vector3d(x - v.x, y - v.y, z - v.z); } class Matrix3d { public: Vector3d v[3]; Matrix3d() { v[0] = Vector3d(0); v[1] = v[0]; v[2] = v[0]; } Matrix3d(Real c) { v[0] = Vector3d(c); v[1] = v[0]; v[2] = v[0]; } Matrix3d(const Vector3d& v0,const Vector3d& v1,const Vector3d& v2) { v[0] = v0; v[1] = v1; v[2] = v2; } Matrix3d(const Matrix3d& p) { v[0] = p.v[0]; v[1] = p.v[1]; v[2] = p.v[2]; } Real determinant() const; Matrix3d transpose() const; Matrix3d adjoint() const; Matrix3d inverse() const; Vector3d& operator [](int); const Vector3d& operator [](int) const; int operator==(const Matrix3d&) const; int operator!=(const Matrix3d&) const; Matrix3d& operator=(const Matrix3d&); Matrix3d& operator+=(const Matrix3d&); Matrix3d& operator-=(const Matrix3d&); Matrix3d& operator*=(const Matrix3d&); Matrix3d& operator*=(Real); Matrix3d& operator/=(Real); Matrix3d operator+() const; // unary + Matrix3d operator+(const Matrix3d&) const; Matrix3d operator-() const; // unary - Matrix3d operator-(const Matrix3d&) const; Matrix3d operator*(const Matrix3d&) const; friend inline Matrix3d operator*(Real, const Matrix3d&); friend inline Matrix3d operator*(const Matrix3d&, Real); friend inline Matrix3d operator/(const Matrix3d&, Real); friend inline istream& operator>>(istream&, Matrix3d&); friend inline ostream& operator<<(ostream&, const Matrix3d&); }; class Plane0 { // Plane through origin public: Plane0() {} Plane0(const Vector3d&); Plane0(const Point3d&, const Point3d&); Real eval(const Point3d&) const; int classify(const Point3d&) const; private: Vector3d n; }; class Plane { // general Plane public: Plane() {} Plane(const Vector3d&, const Point3d&); Plane(const Point3d&, const Point3d&, const Point3d&); Real eval(const Point3d&) const; int classify(const Point3d&) const; private: Vector3d n; Real ndotp; }; ///////////////////////////////////////////////////////////////////////////// // Vector3d: inline Real Vector3d::length_2() const { return (x * x + y * y + z * z); } inline Real Vector3d::norm() const { return sqrt(this->length_2()); } inline void Vector3d::normalize() { Real len; if ((len = this->norm()) == 0.0) cerr << "Vector3d::normalize: Division by 0\n"; else { x /= len; y /= len; z /= len; } } inline Real& Vector3d::operator [](int i) { return((i == 0) ? x : (i == 1) ? y : z); } inline const Real& Vector3d::operator [](int i) const { return((i == 0) ? x : (i == 1) ? y : z); } inline int Vector3d::operator==(const Vector3d& p) const { return ((*this - p).norm() < EPS); } inline int Vector3d::operator!=(const Vector3d& p) const { return (! (*this == p)); } inline Vector3d& Vector3d::operator+=(const Vector3d& v) { x += v.x; y += v.y; z += v.z; return(*this); } inline Vector3d& Vector3d::operator-=(const Vector3d& v) { x -= v.x; y -= v.y; z -= v.z; return(*this); } inline Vector3d& Vector3d::operator*=(const Vector3d& v) { x *= v.x; y *= v.y; z *= v.z; return(*this); } inline Vector3d& Vector3d::operator*=(Real c) { x *= c; y *= c; z *= c; return(*this); } inline Vector3d& Vector3d::operator/=(Real c) { Real c1 = 1.0 / c; x *= c1; y *= c1; z *= c1; return(*this); } inline Vector3d Vector3d::operator+() const { return Vector3d(x,y,z); } inline Vector3d Vector3d::operator+(const Vector3d& v) const { return Vector3d(x + v.x, y + v.y, z + v.z); } inline Vector3d Vector3d::operator-() const { return Vector3d(-x,-y,-z); } inline Vector3d Vector3d::operator^(const Vector3d& v) const { return Vector3d(y * v.z - z * v.y, z * v.x - x * v.z, x * v.y - y * v.x); } inline Vector3d operator*(Real c, const Vector3d& v) { return Vector3d(c * v.x, c * v.y, c * v.z); } inline Vector3d operator*(const Vector3d& v, Real c) { return c * v; } inline Vector3d operator*(const Matrix3d& m, const Vector3d& v) { return(Vector3d(Vector3d(m.v[0].x,m.v[1].x,m.v[2].x) * v, Vector3d(m.v[0].y,m.v[1].y,m.v[2].y) * v, Vector3d(m.v[0].z,m.v[1].z,m.v[2].z) * v)); } inline Vector3d operator*(const Vector3d& v, const Matrix3d& m) { return(Vector3d(v * m.v[0],v * m.v[1],v * m.v[2])); } inline Vector3d operator/(const Vector3d& v, Real c) { Real c1 = 1.0 / c; return Vector3d(v.x / c1, v.y / c1, v.z / c1); } inline Real operator*(const Vector3d& u, const Vector3d& v) { return (u.x * v.x + u.y * v.y + u.z * v.z); } inline Matrix3d mprod(const Vector3d& u, const Vector3d& v) { return (Matrix3d(u * v.x,u * v.y,u * v.z)); } inline ostream& operator<<(ostream& os, const Vector3d& v) { os << '(' << v.x << ", " << v.y << ", " << v.z << ')'; return os; } inline istream& operator>>(istream& is, Vector3d& v) { is >> v.x >> v.y >> v.z; return is; } // Extern Matrix Methods inline Matrix3d identity() { return(Matrix3d(Vector3d(1,0,0),Vector3d(0,1,0),Vector3d(0,0,1))); } inline Matrix3d null() { return(Matrix3d(0)); } // Matrix3d inline Matrix3d Matrix3d::transpose() const { return(Matrix3d(Vector3d(this->v[0].x,v[1].x,v[2].x), Vector3d(v[0].y,v[1].y,v[2].y), Vector3d(v[0].z,v[1].z,v[2].z))); } #define MINOR_(s1,t1,s2,t2) (this->v[s1].t1 * v[s2].t2 - v[s2].t1 * v[s1].t2) inline Real Matrix3d::determinant() const { return (v[0].x * MINOR_(1,y,2,z) - v[0].y * MINOR_(1,x,2,z) + v[0].z * MINOR_(1,x,2,y)); } inline Matrix3d Matrix3d::adjoint() const { return(Matrix3d(Vector3d( MINOR_(1,y,2,z), -MINOR_(0,y,2,z), MINOR_(0,y,1,z)), Vector3d( -MINOR_(1,x,2,z), MINOR_(0,x,2,z), -MINOR_(0,x,1,z)), Vector3d( MINOR_(1,x,2,y), -MINOR_(0,x,2,y), MINOR_(0,x,1,y)))); } #undef MINOR_ inline Matrix3d Matrix3d::inverse() const { Real d = determinant(); if (fabs(d) < 1E-10) { cerr << "determinant == 0\n"; return (null()); } return adjoint() / d; } inline Vector3d& Matrix3d::operator [](int i) { return (v[i]); } inline const Vector3d& Matrix3d::operator [](int i) const { return (v[i]); } inline int Matrix3d::operator==(const Matrix3d& m) const { return (v[0] == m.v[0] && v[1] == m.v[1] && v[2] == m.v[2]); } inline int Matrix3d::operator!=(const Matrix3d& m) const { return (! (*this == m)); } inline Matrix3d& Matrix3d::operator=(const Matrix3d& m) { v[0] = m.v[0]; v[1] = m.v[1]; v[2] = m.v[2]; return(*this); } inline Matrix3d& Matrix3d::operator+=(const Matrix3d& m) { v[0] += m.v[0]; v[1] += m.v[1]; v[2] += m.v[2]; return(*this); } inline Matrix3d& Matrix3d::operator-=(const Matrix3d& m) { v[0] -= m.v[0]; v[1] -= m.v[1]; v[2] -= m.v[2]; return(*this); } inline Matrix3d& Matrix3d::operator*=(const Matrix3d& m) { Matrix3d c(*this); // necessary copy v[0] = Vector3d(Vector3d(c.v[0].x,c.v[1].x,c.v[2].x) * m.v[0], Vector3d(c.v[0].y,c.v[1].y,c.v[2].y) * m.v[0], Vector3d(c.v[0].z,c.v[1].z,c.v[2].z) * m.v[0]); v[1] = Vector3d(Vector3d(c.v[0].x,c.v[1].x,c.v[2].x) * m.v[1], Vector3d(c.v[0].y,c.v[1].y,c.v[2].y) * m.v[1], Vector3d(c.v[0].z,c.v[1].z,c.v[2].z) * m.v[1]); v[2] = Vector3d(Vector3d(c.v[0].x,c.v[1].x,c.v[2].x) * m.v[2], Vector3d(c.v[0].y,c.v[1].y,c.v[2].y) * m.v[2], Vector3d(c.v[0].z,c.v[1].z,c.v[2].z) * m.v[2]); return(*this); } inline Matrix3d& Matrix3d::operator*=(Real c) { v[0] *= c; v[1] *= c; v[2] *= c; return(*this); } inline Matrix3d& Matrix3d::operator/=(Real c) { Real c1 = 1.0 / c; v[0] *= c1; v[1] *= c1; v[2] *= c1; return(*this); } inline Matrix3d Matrix3d::operator+() const { return Matrix3d(v[0],v[1],v[2]); } inline Matrix3d Matrix3d::operator+(const Matrix3d& m) const { return Matrix3d(v[0] + m.v[0], v[1] + m.v[1], v[2] + m.v[2]); } inline Matrix3d Matrix3d::operator-() const { return Matrix3d(-v[0],-v[1],-v[2]); } inline Matrix3d Matrix3d::operator-(const Matrix3d& m) const { return Matrix3d(v[0] - m.v[0], v[1] - m.v[1], v[2] - m.v[2]); } inline Matrix3d Matrix3d::operator*(const Matrix3d& m) const { return(Matrix3d(Vector3d(Vector3d(this->v[0].x,v[1].x,v[2].x) * m.v[0], Vector3d(v[0].y,v[1].y,v[2].y) * m.v[0], Vector3d(v[0].z,v[1].z,v[2].z) * m.v[0]), Vector3d(Vector3d(v[0].x,v[1].x,v[2].x) * m.v[1], Vector3d(v[0].y,v[1].y,v[2].y) * m.v[1], Vector3d(v[0].z,v[1].z,v[2].z) * m.v[1]), Vector3d(Vector3d(v[0].x,v[1].x,v[2].x) * m.v[2], Vector3d(v[0].y,v[1].y,v[2].y) * m.v[2], Vector3d(v[0].z,v[1].z,v[2].z) * m.v[2]))); } inline Matrix3d operator*(Real c, const Matrix3d& m) { return(Matrix3d(m.v[0] * c,m.v[1] * c,m.v[2] * c)); } inline Matrix3d operator*(const Matrix3d& m, Real c) { return(c * m); } inline Matrix3d operator/(const Matrix3d& m, Real c) { Real c1 = 1.0 / c; return(Matrix3d(m.v[0] * c1,m.v[1] * c1,m.v[2] * c1)); } inline istream& operator>>(istream& is, Matrix3d& m) { is >> m.v[0] >> m.v[1] >> m.v[2]; return is; } inline ostream& operator<<(ostream& os, const Matrix3d& m) { os << '(' << m.v[0] << ", " << m.v[1] << ", " << m.v[2] << ')'; return os; } // Plane0: inline Plane0::Plane0(const Vector3d& nv) // Computes the plane throught the origin and the 2 points { n = nv; } inline Plane0::Plane0(const Point3d& p, const Point3d& q) // Computes the plane throught the origin and the 2 points { n = p ^ q; n.normalize(); } inline Real Plane0::eval(const Point3d& p) const // Plugs point p into the plane equation. { return (n * p); } inline int Plane0::classify(const Point3d& p) const // Returns -1, 0, or 1, if p is to the left of, on, // or right of the plane, respectively. { Real d = eval(p); return (d < -EPS) ? -1 : (d > EPS ? 1 : 0); } // Plane: inline Plane::Plane(const Vector3d& nv, const Point3d& pt) { n = nv; ndotp = -(n * pt); } inline Plane::Plane(const Point3d& p, const Point3d& q, const Point3d& r) // Computes the normalized plane equation through the p,q & r { Vector3d n1 = q - p; Vector3d n2 = r - p; n = n1 ^ n2; n.normalize(); ndotp = - (n * p); } inline Real Plane::eval(const Point3d& p) const // Plugs point p into the plane equation. { return ((n * p) - ndotp); } inline int Plane::classify(const Point3d& p) const // Returns -1, 0, or 1, if p is to the left of, on, // or right of the plane, respectively. { Real d = eval(p); return (d < -EPS) ? -1 : (d > EPS ? 1 : 0); } #endif t3d& r) // Computes the normalized plane equation through the p,q & r { Vector3d n1 = q - p; Vector3d n2 = r - p; n = n1 ^ n2; n.normalize(); ndotp = - (n * p); } inline Real Plane::eval(const Point3d& hs.cc000064400105260001753000000400530642537744000132470ustar00stuerzlcompsci00000000000000/****************************************************************************** * hs.cc * Projection of Patches onto a Hemi-Sphere * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #include #include #include "hs_int.h" #include "hsphere.h" static Projection view; /* current view */ static BHSP *root; /* the current BHSP */ static Pol new_pol; /* the current Polygon */ static double *ffactors; /* resulting ff area indexed by pol_id */ static double ff_background; /* ffsum for BACKGROUND_ID polygons */ static double ff_surface; /* ffsum for SURFACE_ID polygons */ static float zval[BIGMAX]; /* zvalues for ff comparisons */ Arena* my_arena; /******************************************************************************/ static void compute_depth_pol(Pol *pol) { int i; float zmin,zmax; double scale; TVector3f mid; zmin = FLT_MAX; zmax = -FLT_MAX; InitPoint(mid,0.0,0.0,0.0); for (i = 0; i < pol->nPts; i++) { if (pol->z[i] < zmin) zmin = pol->z[i]; if (pol->z[i] > zmax) zmax = pol->z[i]; AddVector(mid,mid,pol->vert[i]); } ScaleVector(mid,1.0 / pol->nPts); scale = LenVector(mid); if (-pol->np_dist < scale * zmin) zmin = scale * zmin; else zmin = -pol->np_dist; pol->zmin = zmin * (1.0 - DEPTH_EPS); pol->zmax = (zmax < FLT_MAX) ? zmax * (1.0 + DEPTH_EPS) : zmax; } static void estimate_depth(Edge *start,TVector3f *normal1,double np_dist1, float *zmin1, float *zmax1,float *zvalues) { int i; float zmin,zmax; double ndotp,scale,z; Edge *e; TVector3f mid; if (np_dist1 <= -FLT_MAX) { *zmin1 = FLT_MAX; *zmax1 = FLT_MAX; if (zvalues != 0) { e = start; do { *zvalues++ = FLT_MAX; e = e->Next(); } while (e != start); } return; } zmin = FLT_MAX; zmax = -FLT_MAX; InitPoint(mid,0.0,0.0,0.0); i = 0; e = start; do { ndotp = DotVector(*normal1,e->Org()->p); if (ndotp >= 0.0) { if (ndotp > 0.0) wordy("polygon hit from wrong side\n"); z = FLT_MAX; } else z = np_dist1 / ndotp; if (zvalues != 0) *zvalues++ = z; if (z < zmin) zmin = z; if (z > zmax) zmax = z; AddVector(mid,mid,e->Org()->p); i++; e = e->Next(); } while (e != start); ScaleVector(mid,1.0 / i); scale = LenVector(mid); if (-np_dist1 < scale * zmin) zmin = scale * zmin; else zmin = -np_dist1; *zmin1 = zmin * (1.0 - DEPTH_EPS); *zmax1 = (zmax < FLT_MAX) ? zmax * (1.0 + DEPTH_EPS) : zmax; } static SIDE compare_depths(Edge *start,TVector3f *normal1,double np_dist1, double np_dist2,float *zvalues) { int front,back; float t1,t2; double ndotp,diff; Edge *e; if (np_dist1 <= -FLT_MAX || np_dist2 <= -FLT_MAX) { if (np_dist1 <= -FLT_MAX) { if (np_dist2 <= -FLT_MAX) return(INSIDE); else return(BEHIND); } else return(BEFORE); } front = back = 0; e = start; do { ndotp = DotVector(*normal1,e->Org()->p); t1 = (ndotp >= 0.0) ? FLT_MAX : np_dist1 / ndotp; t2 = *zvalues++; if (t1 - t2 == t1) // t1 >> t2 front++; else if (t2 - t1 == t2) // t1 << t2 back++; else { diff = (t1 - t2) / ((t1 + t2) * 0.5); if (diff > DEPTH_EPS) // t1 > t2 front++; else if (diff < -DEPTH_EPS) // t1 < t2 back++; } e = e->Next(); } while (e != start); if (front > 0 && back > 0) return(BOTH); else if (front > 0) return(BEHIND); else if (back > 0) return(BEFORE); return(INSIDE); } /******************************************************************************/ static SIDE classify_normal(Pol& pol,TVector3f* norm) { int i; int front,back; double ndotp; TPoint3f pnear,pfar; if (norm->x >= 0.0) { pnear.x = pol.min3.x; pfar.x = pol.max3.x; } else { pnear.x = pol.max3.x; pfar.x = pol.min3.x; } if (norm->y >= 0.0) { pnear.y = pol.min3.y; pfar.y = pol.max3.y; } else { pnear.y = pol.max3.y; pfar.y = pol.min3.y; } if (norm->z >= 0.0) { pnear.z = pol.min3.z; pfar.z = pol.max3.z; } else { pnear.z = pol.max3.z; pfar.z = pol.min3.z; } if (DotVector(pnear,*norm) > PNT_EPS) return(BEFORE); if (DotVector(pfar,*norm) < -PNT_EPS) return(BEHIND); front = back = 0; for (i = 0; i < pol.nPts; i++) { ndotp = DotVector(pol.vert[i],*norm); if (ndotp < -PNT_EPS) back++; else if (ndotp > PNT_EPS) front++; } if (front > 0 && back > 0) return(BOTH); else if (front > 0) return(BEFORE); else if (back > 0) return(BEHIND); return(INSIDE); } /******************************************************************************/ /* assumes convex polygon, i.e. not 3 points in a row ! */ /* returns the ff of the polygon */ static double prepare_polygon(TPolygon *poly,TPlane *plan,int id,int surf_id, Pol *pol) { int i,x; double temp,depth,ff; TPoint3f p,newp; TVector3f v; TPolygon clip_poly; SubVector(v,poly->vert[0],view.center); if (DotVector(v,plan->normal) >= 0.0) /* backfacing -> don't project */ return(0); x = poly_clip_to_plane(poly,&clip_poly,plan,&view.plane); if (x == POLY_CLIP_BEHIND) /* nothing before viewer */ return(0); pol->id = id; /* to save some params */ pol->surf_id = surf_id; pol->nPts = clip_poly.n; pol->plane = *plan; SubVector(p,clip_poly.vert[clip_poly.n - 1],view.center); /* last point */ NormalizeVector(temp,p); /* project onto sphere */ InitPoint(pol->min3,FLT_MAX,FLT_MAX,FLT_MAX); InitPoint(pol->max3,-FLT_MAX,-FLT_MAX,-FLT_MAX); for (i = 0; i < clip_poly.n; i++) { SubVector(newp,clip_poly.vert[i],view.center); NormalizeVector(depth,newp); /* project onto sphere */ if (depth == 0.0) /* point exactly at view.center */ error("BUG: this case currently not handled correctly !\n"); MakeBbox(pol->min3,pol->max3,newp); pol->vert[i] = newp; pol->z[i] = depth; } pol->np_dist = pol->plane.np - DotVector(pol->plane.normal,view.center); if (pol->np_dist >= 0.0) return(0); /* viewpoint in plane/behind polygon -> ignored */ if (areaPoly(pol->vert,pol->nPts) < AREA_EPS) return(0); /* too small anyway */ for (i = 0; i < pol->nPts; i++) { CrossVector(pol->norm[i],pol->vert[i],pol->vert[(i + 1) % pol->nPts]); NormalizeVector(temp,pol->norm[i]); /* compute normal */ } compute_depth_pol(pol); ff = calc_ff_pol(pol,view.normal); if (ff < FF_EPS) /* no significant influence */ return(0.0); return(ff); } /******************************************************************************/ static void intersect_node(BHSP **tree,Pol *pol) { int i; SIDE side; double ndotv,told,tnew,ff; float newzmin,newzmax; BHSP *node; Edge *before,*behind; TPoint3f p; estimate_depth((*tree)->pol,&pol->plane.normal,pol->np_dist, &newzmin,&newzmax,zval); if (newzmin > (*tree)->zmax) /* new one is behind old box */ return; side = compare_depths((*tree)->pol,&(*tree)->normal,(*tree)->np_dist, pol->np_dist,zval); if (side == BEFORE) /* old one is before new plane */ return; for (i = 0; i < pol->nPts; i++) { split_poly(pol->norm[i],&(*tree)->pol,&(*tree)->normal, (*tree)->np_dist,&before,&behind); if (behind == 0) { if (before != 0) (*tree)->pol = before; /* reset old polygon */ /* else (*tree)->pol is unchanged ! */ return; /* new pol clipped to nothing */ } if (before == 0) { (*tree)->pol = behind; continue; /* tree pol is totally behind -> clip further */ } node = new(my_arena) BHSP(NODE,&pol->norm[i],0.0,0.0); node->before = new(my_arena) BHSP(IN,&(*tree)->normal,0.0,0.0); node->before->pol = before; node->before->np_dist = (*tree)->np_dist; node->before->id = (*tree)->id; estimate_depth(before,&(*tree)->normal,(*tree)->np_dist, &node->before->zmin,&node->before->zmax,0); SetNode(node->before->pol,node->before); node->behind = *tree; node->behind->pol = behind; estimate_depth(behind,&(*tree)->normal,(*tree)->np_dist, &node->behind->zmin,&node->behind->zmax,0); SetNode(node->behind->pol,node->behind); node->zmin = MIN(node->before->zmin,node->behind->zmin); node->zmax = MAX(node->before->zmax,node->behind->zmax); *tree = node; tree = &(*tree)->behind; } estimate_depth((*tree)->pol,&pol->plane.normal,pol->np_dist, &newzmin,&newzmax,zval); /* either background or */ /* new polygon is a element of a (previously entered) surface */ if ((*tree)->id == BACKGROUND_ID || ((*tree)->id >= SURFACE_ID && pol->surf_id == (*tree)->id)) goto INSERT_NEW_POL; if (newzmin > (*tree)->zmax) /* behind old */ return; if (newzmax < (*tree)->zmin) /* totally before new */ goto INSERT_NEW_POL; side = compare_depths((*tree)->pol,&(*tree)->normal,(*tree)->np_dist, pol->np_dist,zval); if (side == BEFORE) /* old one is before */ return; else if (side == BOTH) { wordy("intersecting polys\n"); /* problematical case */ /* test the old & the new polygon in the tree: which one is in front */ /* using the midpoint of the first triangle of the old polygon */ AddVector(p,(*tree)->pol->Org()->p,(*tree)->pol->Dest()->p); AddVector(p,p,(*tree)->pol->Next()->Dest()->p); ScaleVector(p,1.0 / 3.0); NormalizeVector(ndotv,p); told = (*tree)->np_dist / DotVector((*tree)->normal,p); if (told <= 0.0) error("polygon hit from wrong side2"); tnew = pol->np_dist / DotVector(pol->plane.normal,p); if (tnew <= 0.0) error("bad intersect2"); if (tnew >= told) /* old is before -> ignore new */ return; } /* else old one is behind/inside */ INSERT_NEW_POL: ff = calc_ff((*tree)->pol,view.normal); /* calc ff from polygon */ if ((*tree)->id == BACKGROUND_ID) ff_background -= ff; else if ((*tree)->id >= SURFACE_ID) ff_surface -= ff; else if ((*tree)->pol != 0 && ffactors != NULL) ffactors[(*tree)->id] -= ff; /* subtract from old */ if (pol->id >= SURFACE_ID) ff_surface += ff; else if (ffactors != NULL) ffactors[pol->id] += ff; /* add to new */ (*tree)->normal = pol->plane.normal; /* update info */ (*tree)->np_dist = pol->np_dist; (*tree)->id = pol->id; (*tree)->zmin = newzmin; (*tree)->zmax = newzmax; // SetNode((*tree)->pol,(*tree)); // not neccessary, already done } /******************************************************************************/ static void insert_poly(BHSP **tree) { SIDE side; if (new_pol.zmin > (*tree)->zmax) /* too far away anyway */ return; switch ((*tree)->kind) { case NODE: side = classify_normal(new_pol,&(*tree)->normal); if (side == BEFORE || side == BOTH) insert_poly(&(*tree)->before); if (side == BEHIND || side == BOTH) insert_poly(&(*tree)->behind); (*tree)->zmin = MIN((*tree)->before->zmin,(*tree)->behind->zmin); (*tree)->zmax = MAX((*tree)->before->zmax,(*tree)->behind->zmax); break; case IN: intersect_node(tree,&new_pol); break; case KILL: /* ignore all polys coming here */ break; } } /******************************************************************************/ int ProjectPolygonHS(TPolygon *poly,TPlane *plan,int id,int surf_id) { double ff; ff = prepare_polygon(poly,plan,id,surf_id,&new_pol); if (ff <= 0.0) return(0); insert_poly(&root); return(1); } /******************************************************************************/ static SIDE poly_clip(BigPol* p1,BigPol* p2,TVector3f& plane_norm) { int behind,i; double t, tu, tv; TPoint3f temp; TPoint3f *v, *u; static double ndotp[BIGMAX + 1]; /* adr: from p1.nPts downto 1 */ if (PointEqual(p1->plane.normal,plane_norm)) { p2->nPts = 0; return(BEHIND); } behind = 0; /* count vertices "behind" with respect to the plane */ for (v = p1->vert, i = p1->nPts; i > 0; i--, v++) { ndotp[i] = DotVector(*v,plane_norm); if (ndotp[i] < 0.0) behind++; } if (behind == 0) { /* check if all vertices are front */ //p2 = p1; // memcpy(p2, p1, sizeof(Pol)); return (BEFORE); } if (behind == p1->nPts) { /* check if all vertices are behind */ p2->nPts = 0; return (BEHIND); } p2->nPts = 0; u = &p1->vert[p1->nPts - 1]; /* start with u=vert[n-1], v=vert[0] */ tu = - ndotp[1]; tv = 0.0; // to avoid warnings for (v = p1->vert, i = p1->nPts; i > 0; i--, u = v, tu = tv, v++) { tv = - ndotp[i]; if (tu <= 0.0 ^ tv <= 0.0) { /* edge crosses plane */ t = tu / (tu - tv); /* add intersection point to p2 */ SubVector(temp,*v,*u); /* vert[p2->nPts] = u+t*(v-u) */ ScaleVector(temp,t); AddVector(p2->vert[p2->nPts],*u,temp); NormalizeVector(t,p2->vert[p2->nPts]); // project onto sphere p2->nPts++; } if (tv <= 0.0) /* vertex v is in, copy it to p2 */ p2->vert[p2->nPts++] = *v; } if (p2->nPts == 0) return (BEHIND); return (BOTH); } static double covered_pol(BHSP *tree,Pol& pol) { SIDE side; float newzmin,newzmax; double ff,temp; TVector3f norm; Edge* e; BigPol* po1; BigPol* po2; BigPol* pswap; BigPol p1,p2; if (pol.surf_id != tree->id && tree->id >= SURFACE_ID) return(0.0); if (pol.surf_id != tree->id) { // different pol -> test if infront estimate_depth(tree->pol,&pol.plane.normal,pol.np_dist, &newzmin,&newzmax,zval); if (newzmin > tree->zmax) /* new one is behind old box */ return(0.0); if (newzmax > tree->zmin) { side = compare_depths(tree->pol,&tree->normal,tree->np_dist, pol.np_dist,zval); if (side == BEFORE) /* old one is before new plane */ return(0.0); else if (side == BOTH) error("intersecting polygons not handled yet"); } } p1.nPts = pol.nPts; p1.plane = pol.plane; memcpy(p1.vert,pol.vert,sizeof(TPoint3f) * pol.nPts); p2.plane = p1.plane; po1 = &p1; po2 = &p2; e = tree->pol; do { CrossVector(norm,e->Dest()->p,e->Org()->p); // wrong way to point inside NormalizeVector(temp,norm); side = poly_clip(po1,po2,norm); if (side == BEHIND) /* clipped to nothing */ return(0.0); if (side != BEFORE) { // was split pswap = po1; // swap polygons po1 = po2; po2 = pswap; } if (po1->nPts > 20) message("<%d>",po1->nPts); e = e->Next(); } while (e != tree->pol); ff = calc_ff_bigpol(po1,view.normal); return(ff); } /******************************************************************************/ static double covered_ff(BHSP *tree) { double f1,f2; SIDE side; if (tree == 0) return(0.0); if (new_pol.zmin > tree->zmax) /* too far away anyway */ return(0.0); switch (tree->kind) { case NODE: side = classify_normal(new_pol,&tree->normal); if (side == BEFORE || side == BOTH) f1 = covered_ff(tree->before); else f1 = 0.0; if (side == BEHIND || side == BOTH) f2 = covered_ff(tree->behind); else f2 = 0.0; return(f1 + f2); case IN: /* something is already here */ return(covered_pol(tree,new_pol)); case KILL: return(0.0); } return(0.0); /* bad tree */ } double TestPolygonHS(TPolygon *poly,TPlane *plan,int id,int surf_id, double *covered) { double ff; ff = prepare_polygon(poly,plan,id,surf_id,&new_pol); if (ff == 0.0) { *covered = 0.0; return(0.0); } *covered = covered_ff(root); if (*covered > ff) { if (*covered > ff + 1E-5) wordy(("problem: covered %15.13g > ff %15.13g\n",*covered,ff)); *covered = ff; } return(ff); } /******************************************************************************/ void InitHS(TPoint3f *centr,TPlane *plan,TVector3f *tangU, TVector3f *tangV,double *formfactors) { my_arena = new Arena; view.center = *centr; view.normal = plan->normal; view.tangentU = *tangU; view.tangentV = *tangV; view.plane = *plan; ffactors = formfactors; ff_background = 1.0; /* begins with full HS */ ff_surface = 0.0; init_BHSP(&root,view); } void EndHS(int check) { if (ff_surface != 0.0) message("Surface ff sum: %15.12f\n",ff_surface); if (fabs(ff_background) > 1E-3) message("Not covered by HS: %15.12f\n",ff_background); if (! check) { my_arena->~Arena(); /* release resources */ root = NULL; // to make sure ;-) } } view.tangentU = *tangU; view.tangentV = *tangV; view.plane = *plan; ffactors = formfactors; ff_background = 1.0; /* begins with full HS */ ff_surface = 0.0; init_BHSP(&root,view); } void EndHS(int check) { if (ff_surface != 0.0) message("Surface ff sum: %15.12f\n",ff_surface); if (fabs(ff_background) > 1E-3) message("Not covered by HS: %15.12f\n",ff_background); if (! check) { my_arena->~Arena(); /* release resources */ hs1.cc000064400105260001753000000240650642537724600133410ustar00stuerzlcompsci00000000000000/****************************************************************************** * hs1.cc * Support modules for HS-Projection * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #include #include "hsphere.h" #include "hs_int.h" BHSP::BHSP(BHSPtyp kind1,TVector3f *normal1,float zmin1,float zmax1) { kind = kind1; if (normal1 != 0) normal = *normal1; zmin = zmin1; zmax = zmax1; } /******************************************************************************/ #define gen3plist(p1,p2,p3,center,norm,np_dist) { \ double _t,_ndotp; TVector3f _n1,_n2; \ SubVector(_n1,p2,p1); SubVector(_n2,p3,p1); \ CrossVector(norm,_n1,_n2); NormalizeVector(_t,norm); \ _ndotp = (DotVector(norm,p1) > 0.0) ? REAL_MAX : -REAL_MAX; \ np_dist = _ndotp - DotVector(norm,center); } Subdivision* init_BHSP(BHSP **tree,Projection &view) { double np_dis; double mindist; BHSP *root,*node; TVector3f tangU,tangV,negU,negV,norm; mindist = REAL_MAX * (1.0 / sqrt(3.0)); /* height of pyramid */ tangU = view.tangentU; tangV = view.tangentV; negU = tangU; NegVector(negU); negV = tangV; NegVector(negV); Vertex v[4] = { Vertex(Point3d(tangU.x,tangU.y,tangU.z)), Vertex(Point3d(negV.x,negV.y,negV.z)), Vertex(Point3d(negU.x,negU.y,negU.z)), Vertex(Point3d(tangV.x,tangV.y,tangV.z)) }; Subdivision *mesh = new(my_arena) Subdivision(&v[0],4); SetNode(mesh->AnEdge()->Sym(),0); Vertex *top = new(my_arena) Vertex( Point3d(view.normal.x,view.normal.y,view.normal.z)); Edge *e = mesh->AnEdge()->Lnext(); Edge *ne = SplitFace(e,0,e->Lnext()->Lnext(),0); SplitEdge(ne,top); Edge *ne1 = SplitFace(ne->Lnext(),0,ne->Lprev(),0); Edge *ne2 = SplitFace(ne->Sym(),0,ne->Sym()->Lnext()->Lnext(),0); root = new(my_arena) BHSP(NODE,&view.normal,mindist,REAL_MAX); root->before = new(my_arena) BHSP(NODE,&tangU,mindist,REAL_MAX); root->behind = new(my_arena) BHSP(KILL,0,REAL_MAX,REAL_MAX); /* clipping plane */ root->before->before = new(my_arena) BHSP(NODE,&tangV,mindist,REAL_MAX); root->before->behind = new(my_arena) BHSP(NODE,&tangV,mindist,REAL_MAX); gen3plist(tangV,tangU,view.normal,view.center,norm,np_dis); node = new(my_arena) BHSP(IN,&norm,mindist,REAL_MAX); node->pol = ne1->Sym(); node->np_dist = np_dis; node->id = BACKGROUND_ID; SetNode(node->pol,node); root->before->before->before = node; gen3plist(tangU,negV,view.normal,view.center,norm,np_dis); node = new(my_arena) BHSP(IN,&norm,mindist,REAL_MAX); node->pol = ne1; node->np_dist = np_dis; node->id = BACKGROUND_ID; SetNode(node->pol,node); root->before->before->behind = node; gen3plist(negU,tangV,view.normal,view.center,norm,np_dis); node = new(my_arena) BHSP(IN,&norm,mindist,REAL_MAX); node->pol = ne2; node->np_dist = np_dis; node->id = BACKGROUND_ID; SetNode(node->pol,node); root->before->behind->before = node; gen3plist(negV,negU,view.normal,view.center,norm,np_dis); node = new(my_arena) BHSP(IN,&norm,mindist,REAL_MAX); node->pol = ne2->Sym(); node->np_dist = np_dis; node->id = BACKGROUND_ID; SetNode(node->pol,node); root->before->behind->behind = node; *tree = root; return(mesh); } /******************************************************************************/ double calc_ff(Edge *start,TVector3f &plane_normal) { double ff,angle,dotprod,temp; TVector3f s,t,sxt; Edge *e; ff = 0.0; e = start; AssignPoint3dToTVector3f(e->Prev()->Org()->p,s); /* get last vertex */ do { AssignPoint3dToTVector3f(e->Org()->p,t); angle = DotVector(s,t); if (angle > 1.0) angle = 0.0; else if (angle < -1.0) angle = M_PI; else angle = acos(angle); CrossVector(sxt,s,t); /* ComputeNormal(s,t,sxt); */ NormalizeVector(temp,sxt); dotprod = DotVector(sxt,plane_normal); ff += angle * dotprod; s = t; e = e->Next(); } while (e != start); ff /= -2.0 * M_PI; if (ff < 0.0) return(0.0); else if (ff > 1.0) return(1.0); return(ff); } double calc_ff_pol(Pol *poly,TVector3f &plane_normal) { int i; double ff,angle,dotprod,temp; TVector3f s,t,sxt; ff = 0.0; s = poly->vert[poly->nPts - 1]; /* get last vertex */ for (i = 0; i < poly->nPts; i++) { t = poly->vert[i]; angle = DotVector(s,t); if (angle > 1.0) angle = 0.0; else if (angle < -1.0) angle = M_PI; else angle = acos(angle); CrossVector(sxt,s,t); /* ComputeNormal(s,t,sxt); */ NormalizeVector(temp,sxt); dotprod = DotVector(sxt,plane_normal); ff += angle * dotprod; s = t; } ff /= -2.0 * M_PI; if (ff < 0.0) return(0.0); else if (ff > 1.0) return(1.0); return(ff); } double calc_ff_bigpol(BigPol *poly,TVector3f &plane_normal) { int i; double ff,angle,dotprod,temp; TVector3f s,t,sxt; ff = 0.0; s = poly->vert[poly->nPts - 1]; /* get last vertex */ for (i = 0; i < poly->nPts; i++) { t = poly->vert[i]; angle = DotVector(s,t); if (angle > 1.0) angle = 0.0; else if (angle < -1.0) angle = M_PI; else angle = acos(angle); CrossVector(sxt,s,t); /* ComputeNormal(s,t,sxt); */ NormalizeVector(temp,sxt); dotprod = DotVector(sxt,plane_normal); ff += angle * dotprod; s = t; } ff /= -2.0 * M_PI; if (ff < 0.0) return(0.0); else if (ff > 1.0) return(1.0); return(ff); } /******************************************************************************/ static TVector3f *face_normal; static double face_np_dist; static void intersect_line_plane(Vertex *newv,Edge *p1,Edge *p2, TVector3f& plane) { double ndotv,len,t,ndotp; TVector3f v,newp; SubVector(v,p2->Org()->p,p1->Org()->p); NormalizeVector(len,v); ndotv = DotVector(plane,v); if (fabs(ndotv) <= PNT_EPS) /* ray parallel plane */ error("no intersect"); t = -DotVector(plane,p1->Org()->p) / ndotv; /* t is now ints param */ ScaleVector(v,t); AddVector(newp,v,p1->Org()->p); NormalizeVector(len,newp); /* project onto sphere */ ndotp = DotVector(*face_normal,newp); if (ndotp > 0.0) { wordy("polygon hit from backside"); ndotp = -PNT_EPS; } newv->p = Point3d(newp.x,newp.y,newp.z); // newv->depth = (face_np_dist <= -REAL_MAX) ? REAL_MAX : face_np_dist / ndotp; } /******************************************************************************/ typedef enum { ZERO, NEGATIVE, POSITIVE } SIGN; static Edge *findnext_intersect(Edge *begin,TVector3f &norm,Vertex **inter, SIGN &sign) { int sign1,sign2,firstrun; double temp1,temp2; Edge *e; firstrun = 1; e = begin; do { if (firstrun) { temp1 = DotVector(e->Org()->p,norm); if (temp1 < -PNT_EPS) sign1 = -1; else if (temp1 > PNT_EPS) sign1 = 1; else { /* edges beginning with a 0 sign are not */ e = e->Next(); continue; /* considered valid intersections */ } } else { temp1 = temp2; /* reuse old value */ sign1 = sign2; } firstrun = 0; temp2 = DotVector(norm,e->Dest()->p); if (temp2 < -PNT_EPS) sign2 = -1; else if (temp2 > PNT_EPS) sign2 = 1; else { /* intersection considered valid */ *inter = e->Dest(); sign = (sign1 == -1) ? NEGATIVE : POSITIVE; return(e); } if (sign1 ^ sign2) { /* different sides */ intersect_line_plane(*inter,e,e->Next(),norm); sign = (sign1 == -1) ? NEGATIVE : POSITIVE; return(e); } e = e->Next(); } while (e != begin); sign = ZERO; return(0); } static Edge *create_other(Edge *e1,Vertex *i1,Edge *e2,Vertex *i2) { Vertex *pi1 = (i1 != 0) ? i1 : e1->Dest(); Vertex *pi2 = (i2 != 0) ? i2 : e2->Dest(); // if (! OnEdge(pi1->p,e1) || OnPoint(pi1->p,e1->Org())) // error("illegal split point 1"); // if (! OnEdge(pi2->p,e2) || OnPoint(pi2->p,e2->Org())) // error("illegal split point 2"); if (OnEdge2(e2->Dest()->p,pi1->p,pi2->p)) { e2 = e2->Next(); if (OnEdge2(e2->Dest()->p,pi1->p,pi2->p)) return(0); /* this is flat */ i2 = 0; } if (OnEdge2(e1->Dest()->p,pi1->p,pi2->p)) { e1 = e1->Next(); if (OnEdge2(e1->Dest()->p,pi1->p,pi2->p)) return(0); /* this is flat */ i1 = 0; } Edge *e = SplitFace(e1,i1,e2,i2); return(e); } static SIGN side_poly(Edge *start,TVector3f &norm) { int isNeg,isPos; double value; Edge *e; isNeg = isPos = 0; e = start; do { value = DotVector(e->Org()->p,norm); if (value < -PNT_EPS) isNeg++; else if (value > PNT_EPS) isPos++; /* else 0 */ e = e->Next(); } while (e != start); /* in the very rare case that some vertices slip thru to other side of */ /* plane due to round-off errors, pick the maximum vertex count. */ /* otherwise one of the 2 numbers is 0, and the comparison works also! */ if (isNeg > isPos) return(NEGATIVE); else if (isPos > isNeg) return (POSITIVE); return(ZERO); } void split_poly(TVector3f &split,Edge **faceIn,TVector3f *faceNorm, double face_np,Edge **facePos,Edge **faceNeg) { Edge *v1,*v2; Edge *newFace; Vertex i1,i2; Vertex* pi1 = &i1; Vertex* pi2 = &i2; SIGN sign_v1,sign_v2; *facePos = 0; *faceNeg = 0; face_normal = faceNorm; face_np_dist = face_np; v1 = findnext_intersect(*faceIn,split,&pi1,sign_v1); if (v1 != 0) { v2 = findnext_intersect(v1->Next(),split,&pi2,sign_v2); /* Due to numerical instabilities, both intersection points may * have the same sign such as in the case when splitting very close * to a vertex. This should not count as a split. */ if (v2 != 0 && sign_v1 == sign_v2) v2 = 0; } if (v1 == 0 || v2 == 0) { SIGN side = side_poly(*faceIn,split); if (side == NEGATIVE) { *faceNeg = *faceIn; *faceIn = 0; } else if (side == POSITIVE) { *facePos = *faceIn; *faceIn = 0; } else wordy("projecting polygon ignored\n"); return; } /* v1 & v2 are considered valid now */ if (pi1 == &i1) // new coords! pi1 = new(my_arena) Vertex(pi1->p); else pi1 = 0; // point = v1->Dest(); if (pi2 == &i2) // new coords! pi2 = new(my_arena) Vertex(pi2->p); else pi2 = 0; // point = v2->Dest(); newFace = create_other(v1,pi1,v2,pi2); if (newFace == 0) return; /* both new degnerate old poly remains */ if (sign_v1 == NEGATIVE) { *faceNeg = newFace; *facePos = newFace->Sym(); } else if (sign_v1 == POSITIVE) { *faceNeg = newFace->Sym(); *facePos = newFace; } *faceIn = 0; } ew(my_arena) Vertex(pi1->p); else pi1 = 0; // point = v1->Dest(); if (pi2 == &i2) // new coords! pi2 = new(my_arena) Vertex(pi2->p); else pi2 = 0; // point = v2->Dest(); newFace = create_other(v1,pi1,v2,pi2); if (newFace == 0) return; /* both new degnerate old poly remains */ if (sign_v1 == NEGATIVE) { *faceNeg = newFace; *facePos = newFace->Sym(); } else if (sign_v1 == POSITIVE) { *faceNeg = newFachs_int.h000064400105260001753000000054130642537772200137670ustar00stuerzlcompsci00000000000000/****************************************************************************** * hs_int.h * HS Projection Internal header file * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #ifndef __HS_INT__ #define __HS_INT__ #include #include #include "arena.h" #include "geom.h" #include "mesh.h" #define ILLEGAL_ID 0xFFFFFFFFL #ifndef M_PI #define M_PI 3.14159265359879 #endif #define DEPTH_EPS 1E-5 /* used for depth comparisons */ #define PNT_EPS 1E-6 /* used for point comparisons */ #define FF_EPS 1E-6 /* minimal ff */ #define AREA_EPS 1E-10 /* minimal area of polyon */ #define AssignPoint3dToTVector3f(p,v) (v).x = (p).x,(v).y = (p).y,(v).z = (p).z #define AssignTVector3fToPoint3d(p,v) (v).x = (p).x,(v).y = (p).y,(v).z = (p).z #ifdef DEBUG #define wordy(s) { printf(s); } #else #define wordy(s) { } #endif typedef enum { BOTH, BEFORE, BEHIND, INSIDE } SIDE; typedef enum { NODE, IN, KILL } BHSPtyp; class BHSP { public: BHSPtyp kind; /* ALL: typ */ float zmin,zmax; /* ALL: HS depth BBOX */ TVector3f normal; /* NODE: partition plane normal */ /* IN: surface normal */ struct BHSP *before; /* NODE: recurse */ struct BHSP *behind; /* NODE: recurse */ Edge *pol; /* IN: polygon vertices */ double np_dist; /* IN: ndotp - ndot(projection center) */ int id; /* IN: extern polygon id # */ BHSP(BHSPtyp kind,TVector3f *normal,float zmin,float zmax); }; typedef struct Pol { TPoint3f min3,max3; /* bbox of pol in coord system - center */ float zmin,zmax; /* HS min/max vertex depth */ int nPts; /* # of Points */ TPoint3f vert[kMaxPolyPoints]; /* vertex list */ TVector3f norm[kMaxPolyPoints]; /* normal vectors of side planes */ float z[kMaxPolyPoints]; /* depth values */ TPlane plane; /* plane of polygon */ double np_dist; /* ndotp - ndot(projection center) */ int id; /* numeric id of polygon */ int surf_id; /* numeric surface id of polygon */ } Pol; #define BIGMAX 512 typedef struct BigPol { int nPts; /* # of Points */ TPoint3f vert[BIGMAX]; /* vertex list */ TPlane plane; /* plane of polygon */ } BigPol; typedef struct projection { TPoint3f center; TVector3f normal; TVector3f tangentU; TVector3f tangentV; TPlane plane; } Projection; /* hs1.cc */ Subdivision *init_BHSP(BHSP **tree,Projection &view); double calc_ff(Edge *edge,TVector3f &plane_normal); double calc_ff_pol(Pol *pol,TVector3f &plane_normal); double calc_ff_bigpol(BigPol *pol,TVector3f &plane_normal); void split_poly(TVector3f &split,Edge **faceIn,TVector3f *faceNorm, double face_np,Edge **facePos,Edge **faceNeg); void init_graph(void); void show_obj(BHSP *root,int loop,int line); void end_graph(void); #endif U; TVector3f tangentV; TPlane plane; } Projection; /* hs1.cc */ Subdivision *init_BHSP(BHSP **tree,Projection &view); double calc_ff(Edge *edge,TVector3f &plane_normal); double calc_ff_pol(Pol *pol,TVector3f &plane_normal); double calc_ff_hsphere.h000064400105260001753000000015730601011456700141260ustar00stuerzlcompsci00000000000000/****************************************************************************** * hs.h * Header for Projection of Patches onto a Hemi-Sphere * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #ifndef __HSPHERE__ #define __HSPHERE__ #include "geom.h" #define BACKGROUND_ID 0x7FFFFFFFL #define SURFACE_ID 0x70000000L /* make it C++ friendly */ #ifdef __cplusplus extern "C" { #endif /* hs.c external interface */ void InitHS(TPoint3f *center, TPlane *plane, TVector3f *tangentU, TVector3f *tangentV, double *formfactors); int ProjectPolygonHS(TPolygon *pol,TPlane *plane,int id,int surf_id); double TestPolygonHS(TPolygon *pol,TPlane *plane,int id,int surf_id, double *covered); int CalcGradient(TVector3f* gradient); void EndHS(int check); #ifdef __cplusplus }; #endif #endif L /* make it C++ friendly */ #ifdef __cplusplus extern "C" { #endif /* hs.c external interface */ void InitHS(TPoint3f *center, TPmesh.cc000064400105260001753000000071720601011465400135600ustar00stuerzlcompsci00000000000000/****************************************************************************** * mesh.cc * quadedge mesh * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #include "arena.h" #include "mesh.h" Subdivision::Subdivision(const Vertex& a, const Vertex& b, const Vertex& c) // Initialize a subdivision to the triangle defined by the points a, b, c. { Vertex *da = new(my_arena) Vertex(a); Vertex *db = new(my_arena) Vertex(b); Vertex *dc = new(my_arena) Vertex(c); Edge* ea = MakeEdge(); ea->EndPoints(da, db); Edge* eb = MakeEdge(); Splice(ea->Sym(), eb); eb->EndPoints(db, dc); Edge* ec = MakeEdge(); Splice(eb->Sym(), ec); ec->EndPoints(dc, da); Splice(ec->Sym(), ea); startingEdge = ea; } Subdivision::Subdivision(const Vertex* verts,int numVertex) // Initialize a subdivision to the convex polygon defined by the points v. { int i; Vertex* v0 = new(my_arena) Vertex(verts[0]); /* store first */ Vertex* vp = v0; Vertex* v = new(my_arena) Vertex(verts[1]); Edge* e0 = MakeEdge(); Edge* e = e0; Edge *ep; e->EndPoints(vp, v); for (i = 1; i < numVertex - 1; i++) { vp = v; v = new(my_arena) Vertex(verts[i + 1]); ep = e; e = MakeEdge(); Splice(ep->Sym(), e); e->EndPoints(vp, v); } vp = v; ep = e; e = MakeEdge(); Splice(ep->Sym(), e); e->EndPoints(vp, v0); Splice(e->Sym(), e0); startingEdge = e0; } Edge* Subdivision::AnEdge() { return(startingEdge); } /************************* Geometric Predicates ****************************/ int OnPoint(const Point3d& x, Vertex* v) // A predicate that determines if the point x is on the begin of the edge e. // The point is considered on if it is in the EPS-neighborhood // of the origin of the edge. { return ((x - v->p).norm() < EPS); } int OnEdge(const Point3d& x, Edge* e) // A predicate that determines if the point x is on the edge e. // The point is considered on if it is in the EPS-neighborhood // of the edge. { Real t1, t2, t3; t1 = (x - e->Origin().p).norm(); t2 = (x - e->Destination().p).norm(); if (t1 < EPS || t2 < EPS) return TRUE; t3 = (e->Origin().p - e->Destination().p).norm(); if (t1 > t3 || t2 > t3) return FALSE; Plane0 plane(e->Origin().p, e->Destination().p); return (fabs(plane.eval(x)) < EPS); } int OnEdge2(const Point3d& x, const Point3d& p1, const Point3d& p2) // A predicate that determines if the point x is on the edge. // The point is considered on if it is in the EPS-neighborhood // of the edge betwee p1 & p2. { Real t1, t2, t3; t1 = (x - p1).norm(); t2 = (x - p2).norm(); if (t1 < EPS || t2 < EPS) return TRUE; t3 = (p1 - p2).norm(); if (t1 > t3 || t2 > t3) return FALSE; Plane0 plane(p1, p2); return (fabs(plane.eval(x)) < EPS); } Edge* SplitEdge(Edge* e,Vertex* v) // Inserts a Point into an edge; v is then e->Dest()!!!!! { Edge* t = e->Lnext(); Splice(e->Sym(), t); e->EndPoints(e->Org(),v); Edge *ne = Connect(e,t); return ne; } Edge *SplitFace(Edge *a,Vertex *va,Edge *b,Vertex *vb) // Splits a Face // if va is set the edge a is split with the vertex; same for vb,b // else the origins of the edges are taken! { if (va) SplitEdge(a,va); /* Dest(a) = va afterwards */ else a = a->Lprev(); /* for split at origin of a! */ if (vb) b = SplitEdge(b,vb); Edge* e = Connect(a,b); /* connects Dest(a) with Orig(b)! */ return(e); } void SetNode(Edge *e, BHSP* face) // Sets the face data inside the !LEFT! ring { Edge* start = e; do { e->SetLeftFace(face); e = e->Lnext(); } while (e != start); } void DumpEdge(Edge* start) { Edge* e = start; do { cerr << e->Org()->p << "\n"; e = e->Next(); } while (e != start); } /* Dest(a) = va afterwards */ else a = a->Lprev(); /* for split at origin of a! */ if (vb) b = SplitEdge(b,vb); Edge* e = Connect(a,b); /* connects Dest(a) with Orig(b)! */ return(e); } void SetNode(Edge *e, BHSP* face) // Sets the face data inside the !LEFT! ring { Edge* start = e; do { e->SetLeftFace(face); e = e->Lnext(); } while (e != start); } void Dummesh.h000064400105260001753000000016230601011470200134070ustar00stuerzlcompsci00000000000000/****************************************************************************** * mesh.h * quadedge mesh * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #ifndef MESH_H #define MESH_H #include "geom3d.h" #include "quadedge.h" class Vertex { public: Point3d p; Vertex() { } Vertex(const Point3d& pnt) { p = pnt; } }; class Subdivision { private: Edge *startingEdge; Edge *Locate(const Vertex&); public: Subdivision(const Vertex&, const Vertex&, const Vertex&); Subdivision(const Vertex*, int); Edge *AnEdge(); }; int OnPoint(const Point3d& x, Vertex* v); int OnEdge(const Point3d& x, Edge* e); int OnEdge2(const Point3d& x, const Point3d& p1, const Point3d& p2); Edge* SplitEdge(Edge* e,Vertex* v); Edge *SplitFace(Edge *a,Vertex *va,Edge *b,Vertex *vb); class BHSP; // fwd declaration void SetNode(Edge *e, BHSP* face); #endif sion { private: Edge *startingEdge; Edge *Locate(const Vertex&); public: Subdivision(const Vertex&, coquadedge.cc000064400105260001753000000041300601011500000143540ustar00stuerzlcompsci00000000000000/****************************************************************************** * quadedge.cc * quadedge datastructure see GGems code by Lischinski * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #include "quadedge.h" #include "arena.h" /*********************** Basic Topological Operators ************************/ Edge* MakeEdge() { QuadEdge *ql = new(my_arena) QuadEdge; return ql->e; } void Splice(Edge* a, Edge* b) // This operator affects the two edge rings around the origins of a and b, // and, independently, the two edge rings around the left faces of a and b. // In each case, (i) if the two rings are distinct, Splice will combine // them into one; (ii) if the two are the same ring, Splice will break it // into two separate pieces. // Thus, Splice can be used both to attach the two edges together, and // to break them apart. See Guibas and Stolfi (1985) p.96 for more details // and illustrations. { Edge* alpha = a->Onext()->Rot(); Edge* beta = b->Onext()->Rot(); Edge* t1 = b->Onext(); Edge* t2 = a->Onext(); Edge* t3 = beta->Onext(); Edge* t4 = alpha->Onext(); a->next = t1; b->next = t2; alpha->next = t3; beta->next = t4; } void DeleteEdge(Edge* e) { Splice(e, e->Oprev()); Splice(e->Sym(), e->Sym()->Oprev()); delete e->Qedge(); } /***************** Topological Operations for Meshes **************************/ Edge* Connect(Edge* a, Edge* b) // Add a new edge e connecting the destination of a to the // origin of b, in such a way that all three have the same // left face after the connection is complete. // Additionally, the data pointers of the new edge are set. { Edge* e = MakeEdge(); Splice(e, a->Lnext()); Splice(e->Sym(), b); e->EndPoints(a->Dest(), b->Org()); return e; } void Swap(Edge* e) // Essentially turns edge e counterclockwise inside its enclosing // quadrilateral. The data pointers are modified accordingly. { Edge* a = e->Oprev(); Edge* b = e->Sym()->Oprev(); Splice(e, a); Splice(e->Sym(), b); Splice(e, a->Lnext()); Splice(e->Sym(), b->Lnext()); e->EndPoints(a->Dest(), b->Dest()); } Additionally, the data pointers of the new edge are set. { Edge* e = MakeEdge(); Splice(e, a->Lnext()); Splice(e->Sym(), b); e->EndPoints(a->Dest(), b->Org()); return e; } void Swap(Edge* e) // Essentially turns edge e counterclockwise inside its enclosing // quadrilateral. The data pointers are modified accordingly. { Edge* a = e->Oprev(); Edge* b = e->Sym()->Oprev(); Splice(e, a); Splice(e->Sym(), b); Splicequadedge.h000064400105260001753000000105400601011475500142400ustar00stuerzlcompsci00000000000000/****************************************************************************** * quadedge.h * quadedge datastructure see GGems code by Lischinski * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #ifndef QUADEDGE_H #define QUADEDGE_H class Vertex; // externally declared class BHSP; // externally declared class QuadEdge; // fwd declaration class Edge { friend QuadEdge; friend void Splice(Edge*, Edge*); friend void DeleteEdge(Edge *); private: int num; Edge *next; union { Vertex *vtx_data; BHSP *node_data; } u; public: Edge() { u.vtx_data = 0; } Edge* Rot(); Edge* invRot(); Edge* Sym(); Edge* Onext(); Edge* Oprev(); Edge* Dnext(); Edge* Dprev(); Edge* Lnext(); Edge* Lprev(); Edge* Rnext(); Edge* Rprev(); Edge* Next(); Edge* Prev(); Vertex* Org(); Vertex* Dest(); const Vertex& Origin() const; const Vertex& Destination() const; void EndPoints(Vertex*, Vertex*); BHSP* Edge::LeftFace(); BHSP* Edge::RightFace(); void Edge::SetLeftFace(BHSP* left); void Edge::SetFaces(BHSP* left, BHSP* right); QuadEdge* Qedge() { return (QuadEdge *)(this - num); } void Draw(unsigned int); }; class QuadEdge { friend Edge *MakeEdge(); private: Edge e[4]; QuadEdge *next; unsigned int ts; public: QuadEdge(); int TimeStamp(unsigned int); }; Edge* Connect(Edge* a, Edge* b); void Swap(Edge* e); inline QuadEdge::QuadEdge() { e[0].num = 0, e[1].num = 1, e[2].num = 2, e[3].num = 3; e[0].next = &(e[0]); e[1].next = &(e[3]); e[2].next = &(e[2]); e[3].next = &(e[1]); next = 0; ts = 0; } inline int QuadEdge::TimeStamp(unsigned int stamp) { if (ts != stamp) { ts = stamp; return 1; } else return 0; } /************************* Edge Algebra *************************************/ inline Edge* Edge::Rot() // Return the dual of the current edge, directed from its right to its left. { return (num < 3) ? this + 1 : this - 3; } inline Edge* Edge::invRot() // Return the dual of the current edge, directed from its left to its right. { return (num > 0) ? this - 1 : this + 3; } inline Edge* Edge::Sym() // Return the edge from the destination to the origin of the current edge. { return (num < 2) ? this + 2 : this - 2; } inline Edge* Edge::Onext() // Return the next ccw edge around (from) the origin of the current edge. { return next; } inline Edge* Edge::Oprev() // Return the next cw edge around (from) the origin of the current edge. { return Rot()->Onext()->Rot(); } inline Edge* Edge::Dnext() // Return the next ccw edge around (into) the destination of the current edge. { return Sym()->Onext()->Sym(); } inline Edge* Edge::Dprev() // Return the next cw edge around (into) the destination of the current edge. { return invRot()->Onext()->invRot(); } inline Edge* Edge::Lnext() // Return the ccw edge around the left face following the current edge. { return invRot()->Onext()->Rot(); } inline Edge* Edge::Lprev() // Return the ccw edge around the left face before the current edge. { return Onext()->Sym(); } inline Edge* Edge::Rnext() // Return the edge around the right face ccw following the current edge. { return Rot()->Onext()->invRot(); } inline Edge* Edge::Rprev() // Return the edge around the right face ccw before the current edge. { return Sym()->Onext(); } inline Edge* Edge::Next() // Return the ccw edge around the left face following the current edge. { return invRot()->Onext()->Rot(); } inline Edge* Edge::Prev() // Return the ccw edge around the left face before the current edge. { return Onext()->Sym(); } /************** Access to data pointers *************************************/ inline Vertex* Edge::Org() { return u.vtx_data; } inline Vertex* Edge::Dest() { return Sym()->u.vtx_data; } inline const Vertex& Edge::Origin() const { return *u.vtx_data; } inline const Vertex& Edge::Destination() const { return (num < 2) ? *((this + 2)->u.vtx_data) : *((this - 2)->u.vtx_data); } inline void Edge::EndPoints(Vertex* or, Vertex* de) { u.vtx_data = or; Sym()->u.vtx_data = de; } inline BHSP* Edge::LeftFace() { return invRot()->u.node_data; } inline BHSP* Edge::RightFace() { return Rot()->u.node_data; } inline void Edge::SetLeftFace(BHSP* left) { invRot()->u.node_data = left; } inline void Edge::SetFaces(BHSP* left, BHSP* right) { invRot()->u.node_data = left; Rot()->u.node_data = right; } #endif /* QUADEDGE_H */ is + 2)->u.vtx_data) : *((this - 2)->u.vtx_data); } inline void Edge::EndPoints(Vertex* or, Vertex* de) { u.vtx_data = or; Sym()->u.vtx_data = de; } inline /****************************************************************************** * mesh.h * quadedge mesh * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #ifndef MESH_H #define MESH_H #include "geom3d.h" #include "quadedge.h" class Vertex { public: Point3d p; Vertex() { } Vertex(const Point3d& pnt) { p = pnt; } }; class Subdivision { private: Edge *startingEdge; Edge *Locate(const Vertex&); public: Subdivision(const Vertex&, const Vertex&, const Vertex&); Subdivision(const Vertex*, int); Edge *AnEdge(); }; int OnPoint(const Point3d& x, Vertex* v); int OnEdge(const Point3d& x, Edge* e); int OnEdge2(const Point3d& x, const Point3d& p1, const Point3d& p2); Edge* SplitEdge(Edge* e,Vertex* v); Edge *SplitFace(Edge *a,Vertex *va,Edge *b,Vertex *vb); class BHSP; // fwd declaration void SetNode(Edge *e, BHSP* face); #endif sion { private: Edge *startingEdge; Edge *Locate(const Vertex&); public: Subdivision(const Vertex&, coquadedge.cc000064400105260001753000000041300601011500000143540ustar00stuerzlcompsci00000000000000/****************************************************************************** * quadedge.cc * quadedge datastructure see GGems code by Lischinski * (c)95 by Wolfgang Stuerzlinger ******************************************************************************/ #include "quadedge.h" #include "arena.h" /*********************** Basic Topological Operators ************************/ Edge* MakeEdge() { QuadEdge *ql = new(my_arena) QuadEdge; return ql->e; } void Splice(Edge* a, Edge* b) // This operator affects the two edge rings around the origins of a and b, // and, independently, the two edge rings around the left faces of a and b. // In each case, (i) if the two rings are distinct, Splice will combine // them into one; (ii) if the two are the same ring, Splice will break it // into two separate pieces. // Thus, Splice can be used both to attach the two edges together, and // to break them apart. See Guibas and Stolfi (1985) p.96 for more details // and illustrations. { Edge* alpha = a->Onext()->Rot(); Edge* beta = b->Onext()->Rot(); Edge* t1 = b->Onext(); Edge* t2 = a->Onext(); Edge* t3 = beta->Onext(); Edge* t4 = alpha->Onext(); a->next = t1; b->next = t2; alpha->next = t3; beta->next = t4; } void DeleteEdge(Edge* e) { Splice(e, e->Oprev()); Splice(e->Sym(), e->Sym()->Oprev()); delete e->Qedge(); } /***************** Topological Operations for Meshes **************************/ Edge* Connect(Edge* a, Edge* b) // Add a new edge e connecting the destination of a to the // origin of b, in su