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

📄 bloomenthal.cpp

📁 快速fft变换的c实现
💻 CPP
📖 第 1 页 / 共 2 页
字号:
// Bloomenthal.cpp: implementation of the Bloomenthal class. 
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
//#include "RBF3D.h"
#include "Bloomenthal.h"

/*
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
*/

using namespace BLOOMENTHAL;

//static INTLISTS *cubetable[256];
static struct Bloomenthal::intlists *cubetable[256];

/*			edge: LB, LT, LN, LF, RB, RT, RN, RF, BN, BF, TN, TF */
static int corner1[12]	   = {LBN,LTN,LBN,LBF,RBN,RTN,RBN,RBF,LBN,LBF,LTN,LTF};
static int corner2[12]	   = {LBF,LTF,LTN,LTF,RBF,RTF,RTN,RTF,RBN,RBF,RTN,RTF};
static int leftface[12]	   = {B,  L,  L,  F,  R,  T,  N,  R,  N,  B,  T,  F};
			     /* face on left when going corner1 to corner2 */
static int rightface[12]   = {L,  T,  N,  L,  B,  R,  R,  F,  B,  F,  N,  T};
			     /* face on right when going corner1 to corner2 */

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

Bloomenthal::Bloomenthal()
{

}

Bloomenthal::~Bloomenthal()
{

}


double Bloomenthal::torus(double x, double y, double z)
{
	double x2 = x*x, y2 = y*y, z2 = z*z;
    double a = x2+y2+z2+(0.5*0.5)-(0.1*0.1);
    return a*a-4.0*(0.5*0.5)*(y2+z2);
}

double Bloomenthal::sphere(double x, double y, double z)
{
	double rsq = x*x+y*y+z*z;
    return 1.0/(rsq < 0.00001? 0.00001 : rsq);
}


double Bloomenthal::blob(double x, double y, double z)
{
	return 4.0-sphere(x+1.0,y,z)-sphere(x,y+1.0,z)-sphere(x,y,z+1.0);
}


int Bloomenthal::triproc(int i1, int i2, int i3, VERTICES vertices)
{
	gvertices = vertices;
	gntris++;

	if(FILEOUT){
		fprintf(tri_file, "%d %d %d\n", i1, i2, i3);
	}
	else{
		TRILIST* n_tris = new TRILIST;
		n_tris->next = tris;
		n_tris->i1 = i1;
		n_tris->i2 = i2;
		n_tris->i3 = i3;
		tris = n_tris;
	}
    return 1;
}	

/**** An Implicit Surface Polygonizer ****/


/* polygonize: polygonize the implicit surface function
 *   arguments are:
 *	 double function (x, y, z)
 *		 double x, y, z (an arbitrary 3D point)
 *	     the implicit surface function
 *	     return negative for inside, positive for outside
 *	 double size
 *	     width of the partitioning cube
 *	 int bounds
 *	     max. range of cubes (+/- on the three axes) from first cube
 *	 double x, y, z
 *	     coordinates of a starting point on or near the surface
 *	     may be defaulted to 0., 0., 0.
 *	 int triproc (i1, i2, i3, vertices)
 *		 int i1, i2, i3 (indices into the vertex array)
 *		 VERTICES vertices (the vertex array, indexed from 0)
 *	     called for each triangle
 *	     the triangle coordinates are (for i = i1, i2, i3):
 *		 vertices.ptr[i].position.x, .y, and .z
 *	     vertices are ccw when viewed from the out (positive) side
 *		 in a left-handed coordinate system
 *	     vertex normals point outwards
 *	     return 1 to continue, 0 to abort
 *	 int mode
 *	     TET: decompose cube and polygonize six tetrahedra
 *	     NOTET: polygonize cube directly
 *   returns error or NULL
 */

int counter = 0;
char* Bloomenthal::polygonize(Mesh* mesh, double size, float bounds[6], double x, double y, double z, int mode)
{
	gntris = 0;
	if(FILEOUT){
		ver_file = fopen(VERFILE, "w");
		tri_file = fopen(TRIFILE, "w");
	}
	else{
		tris = new TRILIST;
		tris->i1 = -1;
		tris->i2 = -1;
		tris->i3 = -1;
		tris->next = NULL;
	}

	PROCESS p;
    int n, noabort;
    //CORNER *setcorner();
    TEST in, out;// find();

    //p.function = this->function;//function;
    //p.triproc = triproc;
    p.size = size;
    //p.bounds = bounds;
	p.boundsX1 = bounds[0];
	p.boundsX2 = bounds[1];
	p.boundsY1 = bounds[2];
	p.boundsY2 = bounds[3];
	p.boundsZ1 = bounds[4];
	p.boundsZ2 = bounds[5];
    p.delta = size/(double)(RES*RES);

    /* allocate hash tables and build cube polygon table: */
    p.centers = (CENTERLIST **) mycalloc(HASHSIZE,sizeof(CENTERLIST *));
    p.corners = (CORNERLIST **) mycalloc(HASHSIZE,sizeof(CORNERLIST *));
    p.edges =	(EDGELIST   **) mycalloc(2*HASHSIZE,sizeof(EDGELIST *));
    makecubetable();

    /* find point on surface, beginning search at (x, y, z): */
    srand(1);
    in = find1(1, &p, x, y, z);
    out = find1(0, &p, x, y, z);
    if (!in.ok || !out.ok) return "can't find starting point";
    converge(&in.p, &out.p, in.value, &p.start);

    /* push initial cube on stack: */
    p.cubes = (CUBES *) mycalloc(1, sizeof(CUBES)); /* list of 1 */
    p.cubes->cube.i = p.cubes->cube.j = p.cubes->cube.k = 0;
    p.cubes->next = NULL;

    /* set corners of initial cube: */
    for (n = 0; n < 8; n++)
	p.cubes->cube.corners[n] = setcorner1(&p, BIT(n,2), BIT(n,1), BIT(n,0));

    p.vertices.count = p.vertices.max = 0; /* no vertices yet */
    p.vertices.ptr = NULL;

    setcenter(p.centers, 0, 0, 0);

    while (p.cubes != NULL) { /* process active cubes till none left */
	CUBE c;
	CUBES *temp = p.cubes;
	c = p.cubes->cube;

	noabort = mode == TET?
	       /* either decompose into tetrahedra and polygonize: */
	       dotet(&c, LBN, LTN, RBN, LBF, &p) &&
	       dotet(&c, RTN, LTN, LBF, RBN, &p) &&
	       dotet(&c, RTN, LTN, LTF, LBF, &p) &&
	       dotet(&c, RTN, RBN, LBF, RBF, &p) &&
	       dotet(&c, RTN, LBF, LTF, RBF, &p) &&
	       dotet(&c, RTN, LTF, RTF, RBF, &p)
	       :
	       /* or polygonize the cube directly: */
	       docube(&c, &p);
	if (! noabort) return "aborted";

	/* pop current cube from stack */
	p.cubes = p.cubes->next;
	free((char *) temp);

	/* test six face directions, maybe add to stack: */
	testface(c.i-1, c.j, c.k, &c, L, LBN, LBF, LTN, LTF, &p);
	testface(c.i+1, c.j, c.k, &c, R, RBN, RBF, RTN, RTF, &p);
	testface(c.i, c.j-1, c.k, &c, B, LBN, LBF, RBN, RBF, &p);
	testface(c.i, c.j+1, c.k, &c, T, LTN, LTF, RTN, RTF, &p);
	testface(c.i, c.j, c.k-1, &c, N, LBN, LTN, RBN, RTN, &p);
	testface(c.i, c.j, c.k+1, &c, F, LBF, LTF, RBF, RTF, &p);

	for(n=0; n<8; n++)
		free((char *)c.corners[n]);
    }

	//free
	for(int i=0; i<HASHSIZE; i++){
		while(p.centers[i] != NULL){
			CENTERLIST* current = p.centers[i];
			p.centers[i] = current->next;
			free((char*)current);
		}
	}
	free((char*)p.centers);

	for(i=0; i<HASHSIZE; i++){
		while(p.corners[i] != NULL){
			CORNERLIST* current = p.corners[i];
			p.corners[i] = current->next;
			free((char*)current);
		}
	}
	free((char*)p.corners);

	for(i=0; i<2*HASHSIZE; i++){
		while(p.edges[i] != NULL){
			EDGELIST* current = p.edges[i];
			p.edges[i] = current->next;
			free((char*)current);
		}
	}
    free((char*)p.edges);

	//out
	int vertex_N = gvertices.count;
	int face_N = gntris;
	if(FILEOUT)
	{
		fclose(ver_file);
		fclose(tri_file);
		ver_file = fopen(VERFILE, "r");
		tri_file = fopen(TRIFILE, "r");
		
		FILE* mesh_file = fopen(MESHFILE, "w");
		fprintf(mesh_file, "%d\n%d\n", vertex_N, face_N);
		for(i=0; i<vertex_N; i++)
		{
			//float *v = mesh->vertex[i];
			//fscanf(ver_file, "%f %f %f", &v[0], &v[1], &v[2]);

			float vx, vy, vz;
			fscanf(ver_file, "%f %f %f", &vx, &vy, &vz);
			fprintf(mesh_file, "%f %f %f\n", vx, vy, vz);
		}
		for(i=0; i<face_N; i++)
		{
			//mesh->setPolygonCount(i, 3);
			//int* f = mesh->face[i];
			//fscanf(tri_file, "%d %d %d", &f[0], &f[1], &f[2]);

			int i0, i1, i2;
			fscanf(tri_file, "%d %d %d", &i0, &i1, &i2);
			fprintf(mesh_file, "3 %d %d %d\n", i0, i1, i2);
		}
		fclose(ver_file);
		fclose(tri_file);

		fclose(mesh_file);
	}
	else
	{
		mesh->SetFaceCount(face_N);
		mesh->SetVertexCount(vertex_N);
		for(i=0; i<vertex_N; i++)
		{
//			VERTEX v;
//			v = gvertices.ptr[i];
			float x = (float)gvertices.ptr[i].position.x;
			float y = (float)gvertices.ptr[i].position.y;
			float z = (float)gvertices.ptr[i].position.z;
			mesh->SetVertex(i, x, y, z);
//			mesh->vertex[i][0] = (float)v.position.x;
//			mesh->vertex[i][1] = (float)v.position.y;
//			mesh->vertex[i][2] = (float)v.position.z;
		}
		if (gvertices.ptr != NULL) free((char *)gvertices.ptr);

		TRILIST* current = tris;
		for(i=0; i<face_N; i++)
		{
			mesh->SetFace(i, current->i1, current->i2, current->i3);
//			mesh->setPolygonCount(i, 3);
//			mesh->face[i][0] = current->i1;
//			mesh->face[i][1] = current->i2;
//			mesh->face[i][2] = current->i3;
			TRILIST* previous = current;
			current = current->next;
			delete previous;
		}
	}

    return NULL;
}

/* testface: given cube at lattice (i, j, k), and four corners of face,
 * if surface crosses face, compute other four corners of adjacent cube
 * and add new cube to cube stack */

void Bloomenthal::testface(int i, int j, int k, CUBE *old, 
						   int face, int c1, int c2, int c3, int c4, PROCESS *p)
{
	CUBE new1;
    CUBES *oldcubes = p->cubes;
    //CORNER *setcorner();
    static int facebit[6] = {2, 2, 1, 1, 0, 0};
    int n, pos = old->corners[c1]->value > 0.0 ? 1 : 0, bit = facebit[face];

    /* test if no surface crossing, cube out of bounds, or already visited: */
    if ((old->corners[c2]->value > 0) == pos &&
	(old->corners[c3]->value > 0) == pos &&
	(old->corners[c4]->value > 0) == pos) return;
    //if (abs(i) > p->bounds || abs(j) > p->bounds || abs(k) > p->bounds) return;
	float size = (float)p->size;
	if(i*size + p->start.x > p->boundsX1 
		|| i*size + p->start.x < p->boundsX2 
		|| j*size + p->start.y > p->boundsY1 
		|| j*size + p->start.y < p->boundsY2 
		|| k*size + p->start.z > p->boundsZ1 
		|| k*size + p->start.z < p->boundsZ2)
		return;
    if (setcenter(p->centers, i, j, k)) return;

    /* create new cube: */
    new1.i = i;
    new1.j = j;
    new1.k = k;
	/*
    for (n = 0; n < 8; n++) new1.corners[n] = NULL;
    new1.corners[FLIP(c1, bit)] = old->corners[c1];
    new1.corners[FLIP(c2, bit)] = old->corners[c2];
    new1.corners[FLIP(c3, bit)] = old->corners[c3];
    new1.corners[FLIP(c4, bit)] = old->corners[c4];*/
    for (n = 0; n < 8; n++)
	//if (new1.corners[n] == NULL)
	    new1.corners[n] = setcorner1(p, i+BIT(n,2), j+BIT(n,1), k+BIT(n,0));

    /*add cube to top of stack: */
    p->cubes = (CUBES *) mycalloc(1, sizeof(CUBES));
    p->cubes->cube = new1;
    p->cubes->next = oldcubes;
}

/* setcorner: return corner with the given lattice location
   set (and cache) its function value */
Bloomenthal::CORNER * Bloomenthal::setcorner1(PROCESS *p, int i, int j, int k)
{
	/* for speed, do corner value caching here */
    CORNER *c = (CORNER *) mycalloc(1, sizeof(CORNER));
    int index = HASH(i, j, k);
    CORNERLIST *l = p->corners[index];
    c->i = i; c->x = p->start.x+((double)i-.5)*p->size;
    c->j = j; c->y = p->start.y+((double)j-.5)*p->size;
    c->k = k; c->z = p->start.z+((double)k-.5)*p->size;
    for (; l != NULL; l = l->next)

⌨️ 快捷键说明

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