/**
 * Computes normal from density field at given point.
 *
 * \note Doesn't do normalization!
 */
static void vnormal(PROCESS *process, const float point[3], float r_no[3])
{
	const float delta = process->delta;
	const float f = metaball(process, point[0], point[1], point[2]);

	r_no[0] = metaball(process, point[0] + delta, point[1], point[2]) - f;
	r_no[1] = metaball(process, point[0], point[1] + delta, point[2]) - f;
	r_no[2] = metaball(process, point[0], point[1], point[2] + delta) - f;

#if 0
	f = normalize_v3(r_no);

	if (0) {
		float tvec[3];

		delta *= 2.0f;

		f = process->function(process, point[0], point[1], point[2]);

		tvec[0] = process->function(process, point[0] + delta, point[1], point[2]) - f;
		tvec[1] = process->function(process, point[0], point[1] + delta, point[2]) - f;
		tvec[2] = process->function(process, point[0], point[1], point[2] + delta) - f;

		if (normalize_v3(tvec) != 0.0f) {
			add_v3_v3(r_no, tvec);
			normalize_v3(r_no);
		}
	}
#endif
}
/**
 * return corner with the given lattice location
 * set (and cache) its function value
 */
static CORNER *setcorner(PROCESS *process, int i, int j, int k)
{
	/* for speed, do corner value caching here */
	CORNER *c;
	int index;

	/* does corner exist? */
	index = HASH(i, j, k);
	c = process->corners[index];

	for (; c != NULL; c = c->next) {
		if (c->i == i && c->j == j && c->k == k) {
			return c;
		}
	}

	c = BLI_memarena_alloc(process->pgn_elements, sizeof(CORNER));

	c->i = i;
	c->co[0] = ((float)i - 0.5f) * process->size;
	c->j = j;
	c->co[1] = ((float)j - 0.5f) * process->size;
	c->k = k;
	c->co[2] = ((float)k - 0.5f) * process->size;

	c->value = metaball(process, c->co[0], c->co[1], c->co[2]);

	c->next = process->corners[index];
	process->corners[index] = c;

	return c;
}
Exemple #3
0
int main(int argc, char **argv) {
    VoxelMesh vm(dim3(20, 20, 20), point(0, 0, 0), point(1, 1, 1));

    std::vector<metaball> mbs;

    for (int i = 0; i < 20; i++) {
        mbs.push_back(metaball(point(randv(), randv(), randv()), 3 * randv() - 1));
    }

    std::cout << "Setting voxel data" << std::endl;

    vm.for_each_voxel([&mbs] (VoxelMesh &vm, const dim3 &vox) {
            const point &p = vm.center(vox);
/*            vm[vox] = 0;
            for (const auto &m : mbs)
                vm[vox] += m(p); */
            vm[vox] = 1. / (p - point(.5, .5, .5)).norm();
        });

    bool tri = true;
    if (argc > 1)
        tri = std::string(argv[1])[0] == 't';

    std::cout << "Generating mesh" << std::endl;
    double th = 2.1;
    if (tri) {
        SurfaceMesh<triangle> sm(vm, th);
        std::cout << "Saving TRI mesh" << std::endl;
        sm.save_vtk("res_tri.vtk");
        sm.save_txt("res.tri");
    } else {
        SurfaceMesh<quad> sm(vm, th);
        std::cout << "Saving QUAD mesh" << std::endl;
        sm.save_vtk("res_quad.vtk");
        sm.save_txt("res.quad");
    }
    return 0;
}
/**
 * Given two corners, computes approximation of surface intersection point between them.
 * In case of small threshold, do bisection.
 */
static void converge(PROCESS *process, const CORNER *c1, const CORNER *c2, float r_p[3])
{
	float tmp, dens;
	unsigned int i;
	float c1_value, c1_co[3];
	float c2_value, c2_co[3];

	if (c1->value < c2->value) {
		c1_value = c2->value;
		copy_v3_v3(c1_co, c2->co);
		c2_value = c1->value;
		copy_v3_v3(c2_co, c1->co);
	}
	else {
		c1_value = c1->value;
		copy_v3_v3(c1_co, c1->co);
		c2_value = c2->value;
		copy_v3_v3(c2_co, c2->co);
	}


	for (i = 0; i < process->converge_res; i++) {
		interp_v3_v3v3(r_p, c1_co, c2_co, 0.5f);
		dens = metaball(process, r_p[0], r_p[1], r_p[2]);

		if (dens > 0.0f) {
			c1_value = dens;
			copy_v3_v3(c1_co, r_p);
		}
		else {
			c2_value = dens;
			copy_v3_v3(c2_co, r_p);
		}
	}

	tmp = -c1_value / (c2_value - c1_value);
	interp_v3_v3v3(r_p, c1_co, c2_co, tmp);
}