⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 voronoi.cxx

📁 [Game.Programming].Academic - Graphics Gems (6 books source code)
💻 CXX
字号:
#include <iostream.h>#include <math.h>#include "global.h"#include "voronoi.h"                            // D-DIM. VORONOI TEMPLATEstruct cell : public VECTOR<3> {                // 3-DIMENSIONAL VORONOI-CELL        vector p;                               // POSITION OF PARTICLE        list<cell*> ln;                         // CONTIGUOUS CELLS        list<object*> lh;                       // HOST OBJECT(S)        list<object*> lo;                       // LIST OF INTERSECTING OBJECTS        long t;                                 // LOCAL TRAVERSE CODE (WORK)        cell *b;                                // BACK (voronoi::disperse)        cell() {t=0L;}        cell(vector& v, object *o=(object*)0) {                double x[3]; x[0]=v[0]; x[1]=v[1]; x[2]=v[2];                *((VECTOR<3>*)this)=VECTOR<3>(x); p=v; {if(o)lh+=o;} t=0L;        }        int operator&(vector& p) {              // CELL CONTAINS POINT p                for(cell*n=ln.first();n;n=ln.next())                        if(!(halfspace(this->p,n->p)&p)) return 0;                return 1;        }        int operator&(object& o) {              // CELL INTERSECTS OBJECT o                for(cell*n=ln.first();n;n=ln.next())                        if(!(o&halfspace(this->p,n->p))) return 0;                return 1;        }};//      GLOBAL METHODS (NOT REALLY AN OBJECT ORIENTED APPROACH!)static void initcells(VERTEX<3>*v) {        // VORONOI-CELLS FROM VORONOI<3>        for(register int i=0; i<3; i++) {                cell *ci=(cell*)(v->p[i]);                for(register int j=i+1; j<4; j++) {                        cell *cj=(cell*)(v->p[j]);                        if(!ci->ln[cj]) ci->ln+=cj;                        if(!cj->ln[ci]) cj->ln+=ci;                }        }}static int lexcmp(const void *v1, const void *v2) {        cell *c1=*(cell**)v1; cell *c2=*(cell**)v2;        const double EPS=1e-6;        for(register int i=0; i<3; i++) {                double d=(*c1)[i]-(*c2)[i];                if(d<-EPS) return -1;                if(d>EPS) return 1;        }        return 0;}//      METHODS OF class voronoivoid voronoi::disperse(object *o, cell *C) {        traverse++;        if(traverse==-1L) {                             // OVERFLOW                traverse=-3L; disperse((object*)0,C);   // REINITIALIZE                traverse=0L;        }         cell *c=C; c->b=(cell*)0;                       // PARTICULAR CASE        cell *n=c->ln.first();                          // ACTUAL NEIGHBOR        register int back=0;                            // DON'T STEP BACK YET        for(;;) {                                       // ITERATIVE TRAVERSE                c->t=traverse;                          // MARK AS TRAVERSED                register int go=0;                      // DON'T GO YET                do {                                    // ACTION ON ACTUAL c                        if(back) {                      // STEP BACKWARDS                                cell *b=c->b;           // FROM WHERE WE CAME                                if(o) c->lo+=o;         // PERFORM ACTION                                c=b; back=0; continue;  // TAKE BACK CELL                        }                        if(n==c->b) continue;           // DON'T STEP BACK YET                        if(n->t==traverse) continue;    // ALREADY TRAVERSED                        if(o && !(*n&(*o))) continue;   // PARTIAL TRAVERSE                        go=1; break;                    // GO ON                } while(n=c->ln.next());                // UNTIL NOT ALL DONE                if(go) {                                // STEP FORWARDS                        n->b=c;                         // ESTABLISH BACK LINK                        c=n; n=c->ln.first(); continue; // LET'S GO AHEAD                }                if(c==C) break;                         // RETURNED                back=1;                                 // GO BACK IF NO BETTER        }        if(o) C->lo+=o; C->t=traverse;                  // C IS THE LAST ONE}void voronoi::preprocess(list<object*> *lo) {           // PREPROCESSING        list<cell*> *lc=new list<cell*>;        register int n=0;        for(object* o=lo->first(); o; o=lo->next()) {           // OBJECTS                list<vector*> *lp=o->particles();                for(vector* p=lp->first(); p; p=lp->next())                         {(*lc)+=new cell(*p,o); n++; delete p;}                delete lp;        }        for(o=lightsources.first(); o; o=lightsources.next()) { // LIGHTSRC.S                list<vector*> *lp=o->particles();                for(vector* p=lp->first(); p; p=lp->next())                         {(*lc)+=new cell(*p); n++; delete p;}                delete lp;        }        (*lc)+=new cell(actcamera.getray(0.,0.).o); n++;        // EYE        cell **C=new cell*[n];        n=0;        for(cell* c=lc->first(); c; c=lc->next()) C[n++]=c;        delete lc;        qsort((void*)C, (size_t)n, sizeof(cell*), lexcmp);  // LEXICOGRAPHIC        list<VECTOR<3>*> *lv=new list<VECTOR<3>*>;        (*lv)+=C[0]; cell* p=C[0];        vector cm=C[0]->p;                              // CENTER OF MASS        for(register int i=1; i<n; i++) {                cm=cm+C[i]->p;                if(lexcmp((const void**)&C[i],          // MULTIPLE PARTICLE                          (const void**)&p)==0) {                        for(o=C[i]->lh.first(); o; o=C[i]->lh.next())                                p->lh+=o;                        delete C[i];                } else {(*lv)+=C[i]; p=C[i];}           // SINGLE (YET)        }        cm=cm/(double)n;                                // CENTER OF MASS        delete C;        VECTOR<3>*b[4]; for(i=0;i<4;i++) b[i]=new cell; // BOUNDARY CELLS        VORONOI<3> V(lv,b);                             // VERTEX STRUCTURE        for(i=0;i<4;i++) {                              // BOUNDARY CELLS                cell* c=(cell*)b[i];                c->p=vector((*c)[0],(*c)[1],(*c)[2]);   // UPDATE        }        V(initcells);                                   // 3D VORONOI-CELLS        traverse=0L;                                    // INITIALIZE disperse        double ddmin; register int first=1;             // INITIALIZE SEARCH        for(c=(cell*)lv->first();c;c=(cell*)lv->next()) {                for(o=c->lh.first();o;o=c->lh.next())   // BUILD OBJECT LISTS                        disperse(o,c);                  // PARTIAL TRAVERSE                vector u=c->p-cm; double dd=u%u;        // DISTANCE^2 FROM cm                if(first || dd<ddmin)                   // FIND CLOSEST TO cm                        {ddmin=dd;this->C=c;}                first=0;        }        n=1<<(lmax+1);        s=new cell*[n]; for(i=0;i<n;i++) s[i]=this->C;  // START FOR firstlist        delete lv; // ???}void voronoi::step() {                                  // ONE STEP ALONG RAY r        double tmin=0.; cell* nmin=(cell*)0;            // INITIALIZE SEARCH        for(cell*n=a->ln.first(); n; n=a->ln.next()) {  // NEIGHBORING CELLS                vector u=n->p-a->p;                     // NORMAL OF BISECTOR                double d=r->d%u;                        // DENOMINATOR                if(fabs(d)<EPS) continue;               // PARALLEL FACE                vector v=(n->p+a->p)*.5-r->o;                double t=(v%u)/d;                       // t AT INTERSECTION                if(t<=this->t) continue;                // WOULD BE A BACK STEP                if(t<EPS)                               // r->o ON BISECTOR PL.                        if(u%r->d>0.) {tmin=EPS; nmin=n; continue;}                        else continue;                if(!tmin || t<tmin) {tmin=t; nmin=n;}   // CLOSER INTERSECTION        }        this->t=tmin; a=nmin;}list<object*>* voronoi::firstlist(ray& r) {        register int i=r.c>=0?r.c:(1<<(lmax+1))-1;      // INDEX INTO s        a=s[i];                                         // INITIALIZE step()        if(!((*a)&r.o)) {                               // COHERENCE FAILED                ray R(a->p,norm(r.o-a->p),0,0);         // PATH OF WALK                this->r=&R; t=0.;                       // INITIALIZE step()                for(step(); a; step())                  // WALK                        if((*a)&r.o) {s[i]=a; break;}   // SUCCESS        }        this->r=&r; t=0.;                               // INITIALIZE step()        return a?&a->lo:(list<object*>*)0;}list<object*>* voronoi::nextlist() {        step();                                         // ONE STEP        return a?&a->lo:(list<object*>*)0;              // SUCCESS OR FAIL}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -