Skip to content

Commit

Permalink
Rework SPSR code to accept pre-generated points
Browse files Browse the repository at this point in the history
  • Loading branch information
starseeker committed Nov 17, 2023
1 parent bb34091 commit 6f063a3
Show file tree
Hide file tree
Showing 6 changed files with 47 additions and 94 deletions.
3 changes: 0 additions & 3 deletions src/libged/facetize/tessellate/continuation.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -104,9 +104,6 @@ continuation_mesh(struct rt_bot_internal **obot, struct db_i *dbip, const char *
int num_verts = bot->num_vertices;
bot->vertices = NULL;
bot->faces = NULL;
// TODO - analyze_polygonize should take an rt_db_internal, if possible - the matrix
// positioning of a tree walk isn't baked into a name or dp, so if we're going to
// sample in a tree walk with matrices we really need to work with the positioned data...
polygonize_failure = analyze_polygonize(&(bot->faces), (int *)&(bot->num_faces),
(point_t **)&(bot->vertices),
(int *)&(bot->num_vertices),
Expand Down
27 changes: 18 additions & 9 deletions src/libged/facetize/tessellate/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ _nmg_tessellate(struct rt_bot_internal **nbot, struct rt_db_internal *intern, c
return BRLCAD_ERROR;

if (!bot_is_manifold(*nbot)) {
// Urk - we got an NMG mesh, but it's no good for a Manifold(??)
bu_log("We got an NMG mesh, but it's no good for a Manifold(!?)\n");
if ((*nbot)->vertices)
bu_free((*nbot)->vertices, "verts");
if ((*nbot)->faces)
Expand Down Expand Up @@ -300,23 +300,32 @@ main(int argc, const char **argv)
if (!pnts) {
pnts = _tess_pnts_sample(dp->d_namep, gedp->dbip, &s);
}
// CM is a marching method using an inside/outside test
//ret = _cm_tessellate(&obot, &intern, &ttol, &tol);
// CM is a marching method using an inside/outside test. We need a
// seed point on the surface, so we get one that we know was a raytrace
// hit from the pnts sample.
struct pnt_normal *pl = (struct pnt_normal *)pnts->point;
struct pnt_normal *pn = BU_LIST_PNEXT(pnt_normal, pl);
ret = continuation_mesh(&obot, gedp->dbip, dp->d_namep, &s, pn->v);
if (ret == BRLCAD_OK)
goto write_obot;
}

pnt_sampling_methods:

// TODO - all of the following methods require first sampling points from the solid
// with the raytracer. Do this once - if one method fails, we can use the same point
// input for other methods.

if (s.Co3Ne) {
if (!pnts) {
pnts = _tess_pnts_sample(dp->d_namep, gedp->dbip, &s);
}
//ret = _co3ne_tessellate(&obot, &intern, &ttol, &tol);
//ret = co3ne_mesh(&obot, &intern, &ttol, &tol);
if (ret == BRLCAD_OK)
goto write_obot;
}

if (s.ball_pivot) {
if (!pnts) {
pnts = _tess_pnts_sample(dp->d_namep, gedp->dbip, &s);
}
//ret = ball_pivot_mesh(&obot, &intern, &ttol, &tol);
if (ret == BRLCAD_OK)
goto write_obot;
}
Expand All @@ -325,7 +334,7 @@ main(int argc, const char **argv)
if (!pnts) {
pnts = _tess_pnts_sample(dp->d_namep, gedp->dbip, &s);
}
//ret = _spsr_tessellate(&obot, &intern, &ttol, &tol);
//ret = spsr_mesh(&obot, &intern, &ttol, &tol);
if (ret == BRLCAD_OK)
goto write_obot;
}
Expand Down
2 changes: 1 addition & 1 deletion src/libged/facetize/tessellate/sample.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ _tess_pnts_sample(const char *oname, struct db_i *dbip, struct tess_opts *s)
/* Pick our mode(s) */
int flags = 0;
flags |= ANALYZE_OBJ_TO_PNTS_RAND;
flags |= ANALYZE_OBJ_TO_PNTS_SOBOL;
//flags |= ANALYZE_OBJ_TO_PNTS_SOBOL;

struct rt_pnts_internal *pnts = NULL;
BU_GET(pnts, struct rt_pnts_internal);
Expand Down
103 changes: 26 additions & 77 deletions src/libged/facetize/tessellate/spsr.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
/* F A C E T I Z E . C P P
/* S P S R . C P P
* BRL-CAD
*
* Copyright (c) 2008-2023 United States Government as represented by
Expand All @@ -17,9 +17,10 @@
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file libged/facetize.cpp
/** @file libged/facetize/tessellate/spsr.cpp
*
* The facetize command.
* Tessellation interface to the Screened Poisson surface reconstruction
* algorithm.
*
*/

Expand All @@ -32,89 +33,43 @@
static int
_db_uniq_test(struct bu_vls *n, void *data)
{
struct ged *gedp = (struct ged *)data;
if (db_lookup(gedp->dbip, bu_vls_addr(n), LOOKUP_QUIET) == RT_DIR_NULL) return 1;
struct db_i *dbip = (struct db_i *)data;
if (db_lookup(dbip, bu_vls_addr(n), LOOKUP_QUIET) == RT_DIR_NULL) return 1;
return 0;
}

int
_ged_spsr_obj(struct ged *gedp, const char *objname, const char *newname)
spsr_mesh(struct rt_bot_internal **obot, struct db_i *dbip, struct rt_pnts_internal *pnts, struct tess_opts *s)
{
int ret = BRLCAD_OK;
struct directory *dp;
int decimation_succeeded = 0;
int max_time = 0; // TODO - pass in
struct db_i *dbip = gedp->dbip;
struct rt_db_internal in_intern;
struct bn_tol btol = BN_TOL_INIT_TOL;
struct rt_pnts_internal *pnts;
struct rt_bot_internal *bot = NULL;
struct pnt_normal *pn, *pl;
double avg_thickness = 0.0;
int flags = 0;
int i = 0;
int free_pnts = 0;
struct bg_3d_spsr_opts s_opts = BG_3D_SPSR_OPTS_DEFAULT;
point_t *input_points_3d = NULL;
vect_t *input_normals_3d = NULL;
point_t rpp_min, rpp_max;
point_t obj_min, obj_max;
VSETALL(rpp_min, INFINITY);
VSETALL(rpp_max, -INFINITY);

dp = db_lookup(dbip, objname, LOOKUP_QUIET);
if (!dp) {
bu_log("Error: could not determine type of object %s, skipping\n", objname);
return BRLCAD_ERROR;
}

if (rt_db_get_internal(&in_intern, dp, dbip, (fastf_t *)NULL, &rt_uniresource) < 0) {
bu_log("Error: could not determine type of object %s, skipping\n", objname);
return BRLCAD_ERROR;
}

/* If we have a half, this won't work */
if (in_intern.idb_minor_type == DB5_MINORTYPE_BRLCAD_HALF) {
return BRLCAD_ERROR;
}

/* Key some settings off the bbox size */
rt_obj_bounds(gedp->ged_result_str, gedp->dbip, 1, (const char **)&objname, 0, obj_min, obj_max);
VMINMAX(rpp_min, rpp_max, (double *)obj_min);
VMINMAX(rpp_min, rpp_max, (double *)obj_max);


if (in_intern.idb_minor_type == DB5_MINORTYPE_BRLCAD_PNTS) {
/* If we have a point cloud, there's no need to raytrace it */
pnts = (struct rt_pnts_internal *)in_intern.idb_ptr;

} else {
int max_pnts = 200000; // TODO - pass in
BU_ALLOC(pnts, struct rt_pnts_internal);
pnts->magic = RT_PNTS_INTERNAL_MAGIC;
pnts->scale = 0.0;
pnts->type = RT_PNT_TYPE_NRM;
flags = ANALYZE_OBJ_TO_PNTS_RAND;
free_pnts = 1;

bu_log("SPSR: generating %d points from %s\n", max_pnts, objname);

if (analyze_obj_to_pnts(pnts, &avg_thickness, gedp->dbip, objname, &btol, flags, max_pnts, max_time, 1)) {
ret = BRLCAD_ERROR;
goto ged_facetize_spsr_memfree;
}
}

input_points_3d = (point_t *)bu_calloc(pnts->count, sizeof(point_t), "points");
input_normals_3d = (vect_t *)bu_calloc(pnts->count, sizeof(vect_t), "normals");

struct pnt_normal *pn;
struct pnt_normal *pl = (struct pnt_normal *)pnts->point;
i = 0;
pl = (struct pnt_normal *)pnts->point;
for (BU_LIST_FOR(pn, pnt_normal, &(pl->l))) {
VMOVE(input_points_3d[i], pn->v);
VMOVE(input_normals_3d[i], pn->n);
i++;
}

struct rt_bot_internal *bot;
BU_ALLOC(bot, struct rt_bot_internal);
bot->magic = RT_BOT_INTERNAL_MAGIC;
bot->mode = RT_BOT_SOLID;
Expand All @@ -134,7 +89,7 @@ _ged_spsr_obj(struct ged *gedp, const char *objname, const char *newname)

/* do decimation */
{
struct rt_bot_internal *obot = bot;
*obot = bot;
fastf_t feature_size = 0.0; // TODO - pass in
fastf_t xlen = fabs(rpp_max[X] - rpp_min[X]);
fastf_t ylen = fabs(rpp_max[Y] - rpp_min[Y]);
Expand All @@ -147,13 +102,13 @@ _ged_spsr_obj(struct ged *gedp, const char *objname, const char *newname)

bot = _tess_facetize_decimate(bot, feature_size);

if (bot == obot) {
if (bot == *obot) {
if (bot->vertices) bu_free(bot->vertices, "verts");
if (bot->faces) bu_free(bot->faces, "verts");
ret = BRLCAD_ERROR;
goto ged_facetize_spsr_memfree;
}
if (bot != obot) {
if (bot != *obot) {
decimation_succeeded = 1;
}
}
Expand All @@ -174,8 +129,7 @@ _ged_spsr_obj(struct ged *gedp, const char *objname, const char *newname)
* from the original shape, if we know the avg. thickness of the original object raytrace
* the candidate BoT and compare the avg. thicknesses */
if (avg_thickness > 0) {
const char *av[3];
int max_pnts = 200000; // TODO - pass in
int max_pnts = s->max_pnts; // old value 200000;
double navg_thickness = 0.0;
struct bu_vls tmpname = BU_VLS_INIT_ZERO;
struct rt_bot_internal *tbot = NULL;
Expand All @@ -194,35 +148,31 @@ _ged_spsr_obj(struct ged *gedp, const char *objname, const char *newname)
memcpy(tbot->faces, bot->faces, sizeof(int) * tbot->num_faces *3);

flags = ANALYZE_OBJ_TO_PNTS_RAND;
bu_vls_sprintf(&tmpname, "%s.tmp", newname);
if (db_lookup(gedp->dbip, bu_vls_addr(&tmpname), LOOKUP_QUIET) != RT_DIR_NULL) {
bu_vls_sprintf(&tmpname, "spsr_bot.tmp");
if (db_lookup(dbip, bu_vls_addr(&tmpname), LOOKUP_QUIET) != RT_DIR_NULL) {
bu_vls_printf(&tmpname, "-0");
bu_vls_incr(&tmpname, NULL, NULL, &_db_uniq_test, (void *)gedp);
bu_vls_incr(&tmpname, NULL, NULL, &_db_uniq_test, (void *)dbip);
}
if (_tess_facetize_write_bot(gedp, tbot, bu_vls_addr(&tmpname)) & BRLCAD_ERROR) {
if (_tess_facetize_write_bot(dbip, tbot, bu_vls_addr(&tmpname)) & BRLCAD_ERROR) {
bu_log("SPSR: could not write BoT to temporary name %s\n", bu_vls_addr(&tmpname));
bu_vls_free(&tmpname);
ret = BRLCAD_ERROR;
goto ged_facetize_spsr_memfree;
}

if (analyze_obj_to_pnts(NULL, &navg_thickness, gedp->dbip, bu_vls_addr(&tmpname), &btol, flags, max_pnts, max_time, 1)) {
bu_log("SPSR: could not raytrace temporary BoT %s\n", bu_vls_addr(&tmpname));
if (analyze_obj_to_pnts(NULL, &navg_thickness, dbip, bu_vls_cstr(&tmpname), &btol, flags, max_pnts, max_time, 1)) {
bu_log("SPSR: could not raytrace temporary BoT %s\n", bu_vls_cstr(&tmpname));
ret = BRLCAD_ERROR;
}

/* Remove the temporary BoT object, succeed or fail. */
av[0] = "kill";
av[1] = bu_vls_addr(&tmpname);
av[2] = NULL;
(void)ged_exec(gedp, 2, (const char **)av);

if (ret == BRLCAD_ERROR) {
dp = db_lookup(dbip, bu_vls_cstr(&tmpname), LOOKUP_QUIET);
if (!dp || db_delete(dbip, dp) != 0 || db_dirdelete(dbip, dp) != 0) {
bu_vls_free(&tmpname);
ret = BRLCAD_ERROR;
goto ged_facetize_spsr_memfree;
}


if (fabs(avg_thickness - navg_thickness) > avg_thickness * 0.5) {
bu_log("SPSR: BoT average sampled thickness %f is widely different from original sampled thickness %f\n", navg_thickness, avg_thickness);
ret = BRLCAD_ERROR;
Expand All @@ -238,14 +188,13 @@ _ged_spsr_obj(struct ged *gedp, const char *objname, const char *newname)
bu_log("SPSR: decimation succeeded, final BoT has %d faces\n", (int)bot->num_faces);
}

ret = _tess_facetize_write_bot(gedp, bot, newname);

ged_facetize_spsr_memfree:
if (free_pnts) bu_free(pnts, "free pnts");
if (input_points_3d) bu_free(input_points_3d, "3d pnts");
if (input_normals_3d) bu_free(input_normals_3d, "3d pnts");
rt_db_free_internal(&in_intern);

*obot = bot;

return ret;
}

Expand Down
2 changes: 1 addition & 1 deletion src/libged/facetize/tessellate/tessellate.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ extern struct rt_bot_internal *
_tess_facetize_decimate(struct rt_bot_internal *bot, fastf_t feature_size);

extern int
_tess_facetize_write_bot(struct ged *gedp, struct rt_bot_internal *bot, const char *name);
_tess_facetize_write_bot(struct db_i *dbip, struct rt_bot_internal *bot, const char *name);

extern struct rt_pnts_internal *
_tess_pnts_sample(const char *oname, struct db_i *dbip, struct tess_opts *s);
Expand Down
4 changes: 1 addition & 3 deletions src/libged/facetize/tessellate/util.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,10 +83,8 @@ _tess_facetize_decimate(struct rt_bot_internal *bot, fastf_t feature_size)
}

int
_tess_facetize_write_bot(struct ged *gedp, struct rt_bot_internal *bot, const char *name)
_tess_facetize_write_bot(struct db_i *dbip, struct rt_bot_internal *bot, const char *name)
{
struct db_i *dbip = gedp->dbip;

/* Export BOT as a new solid */
struct rt_db_internal intern;
RT_DB_INTERNAL_INIT(&intern);
Expand Down

0 comments on commit 6f063a3

Please sign in to comment.