Compare commits

...
1 Commits
Author SHA1 Message Date
Clifford Yapp 66972fee0b Work to improve visualization 2026-03-04 22:58:50 -05:00
138 changed files with 14149 additions and 9016 deletions
+54
View File
@@ -8,3 +8,57 @@ useful bit of gdb knowledge about the details of how to watch a specific array
memory location using "watch -l":
https://stackoverflow.com/a/42251209/2037687
When wanting to step through a multithreaded program after hitting a breakpoint,
I found it useful to use the scheduler-locking option (apparently it must
be set after calling run?):
https://stackoverflow.com/q/6721940
build (dbi2)$ gdb --args ./src/librt/tests/rt_cache_drawing Generic_Twin.g
GNU gdb (GDB) Red Hat Enterprise Linux 11.2-3.el8
(gdb) break main
Breakpoint 1 at 0x4016f3: file brlcad/src/librt/tests/cache_drawing.cpp, line 149.
(gdb) break cache_mesh_update
Function "cache_mesh_update" not defined.
Make breakpoint pending on future shared library load? (y or [n]) y
Breakpoint 2 (cache_mesh_update) pending.
(gdb) run
Starting program: brlcad/build/src/librt/tests/rt_cache_drawing Generic_Twin.g
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib64/libthread_db.so.1".
Breakpoint 1, main (argc=2, argv=0x7fffffffd938) at brlcad/src/librt/tests/cache_drawing.cpp:149
149 {
(gdb) set scheduler-locking on
(gdb) c
Continuing.
[New Thread 0x7ffef03ec700 (LWP 2566467)]
[New Thread 0x7ffeefbeb700 (LWP 2566468)]
[New Thread 0x7ffeef3ea700 (LWP 2566469)]
[Switching to Thread 0x7ffeef3ea700 (LWP 2566469)]
Thread 4 "rt_cache_drawin" hit Breakpoint 2, cache_mesh_update (c=0x4edfb0, ip=0x57ffa0, name=0x506160 "7602.1.t0") at brlcad/src/librt/cache_drawing.cpp:176
176 {
(gdb) bt
#0 cache_mesh_update (c=0x4edfb0, ip=0x57ffa0, name=0x506160 "7602.1.t0")
at brlcad/src/librt/cache_drawing.cpp:176
#1 0x00007ffff76924ec in lod_calc (
p=std::shared_ptr<ProcessDrawData> (use count 4, weak count 0) = {...})
at brlcad/src/librt/cache_drawing.cpp:351
#2 0x00007ffff769fa83 in std::__invoke_impl<void, void (*)(std::shared_ptr<ProcessDrawData>), std::shared_ptr<ProcessDrawData> > (
__f=@0x4f8498: 0x7ffff769222f <lod_calc(std::shared_ptr<ProcessDrawData>)>)
at /usr/include/c++/12/bits/invoke.h:61
#3 0x00007ffff769f92e in std::__invoke<void (*)(std::shared_ptr<ProcessDrawData>), std::shared_ptr<ProcessDrawData> > (
__fn=@0x4f8498: 0x7ffff769222f <lod_calc(std::shared_ptr<ProcessDrawData>)>) at /usr/include/c++/12/bits/invoke.h:96
#4 0x00007ffff769f80e in std::thread::_Invoker<std::tuple<void (*)(std::shared_ptr<ProcessDrawData>), std::shared_ptr<ProcessDrawData> > >::_M_invoke<0ul, 1ul> (this=0x4f8488)
at /usr/include/c++/12/bits/std_thread.h:258
#5 0x00007ffff769f6cd in std::thread::_Invoker<std::tuple<void (*)(std::shared_ptr<ProcessDrawData>), std::shared_ptr<ProcessDrawData> > >::operator() (
this=0x4f8488)
at /usr/include/c++/12/bits/std_thread.h:265
#6 0x00007ffff769f60f in std::thread::_State_impl<std::thread::_Invoker<std::tuple<void (*)(std::shared_ptr<ProcessDrawData>), std::shared_ptr<ProcessDrawData>----Type--Type <RET> f--Type <RET> for--Type <RE--Type <RET> for more, q to quit, c --Type <RET> for mor--Type <RET> for more, q to quit, c to continue without paging--
> > >::_M_run (this=0x4f8480) at /usr/include/c++/12/bits/std_thread.h:210
#7 0x00007ffff2a29b23 in execute_native_thread_routine () from /lib64/libstdc++.so.6
#8 0x00007ffff21b51ca in start_thread () from /lib64/libpthread.so.0
#9 0x00007ffff1e0f8d3 in clone () from /lib64/libc.so.6
(gdb)
+1
View File
@@ -56,6 +56,7 @@
#include "bg/lseg.h"
#include "bg/obr.h"
#include "bg/plane.h"
#include "bg/pnts.h"
#include "bg/polygon.h"
#include "bg/sat.h"
#include "bg/spsr.h"
+1 -1
View File
@@ -11,6 +11,7 @@ set(
plane.h
polygon.h
polygon_types.h
pnts.h
sat.h
spsr.h
tri_pt.h
@@ -21,7 +22,6 @@ set(
)
brlcad_manage_files(bg_headers ${INCLUDE_DIR}/brlcad/bg REQUIRED libbg)
cmakefiles(pointgen.h)
cmakefiles(CMakeLists.txt)
# Local Variables:
+111
View File
@@ -0,0 +1,111 @@
/* P N T S . H
* BRL-CAD
*
* Copyright (c) 2004-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/*----------------------------------------------------------------------*/
/* @file pnts.h */
/** @addtogroup bg_pnts */
/** @{ */
/**
* @brief Routines for working with points.
*/
#ifndef BG_PNTS_H
#define BG_PNTS_H
#include "common.h"
#include "vmath.h"
#include "bn/numgen.h"
#include "bg/defines.h"
__BEGIN_DECLS
/**
* @brief
* Calculate the axis-aligned bounding box for a point set.
*
* Returns BRLCAD_OK if successful, else BRLCAD_ERROR.
*
* @param[out] min XYZ coordinate defining the minimum bbox point
* @param[out] max XYZ coordinate defining the maximum bbox point
* @param[in] p array that holds the points defining the trimesh
* @param[in] num_pnts size of pnts array
*/
BG_EXPORT extern int
bg_pnts_aabb(point_t *min, point_t *max, const point_t *p, size_t num_pnts);
/**
* @brief
* Calculate an oriented bounding box for a point set.
*
* Returns BRLCAD_OK if successful, else BRLCAD_ERROR.
*
* @param[out] c XYZ coordinate defining the bbox center
* @param[out] v1 first extent vector of the bbox
* @param[out] v2 second extent vector of the bbox
* @param[out] v3 third extent vector of the bbox
* @param[in] p array that holds the points defining the trimesh
* @param[in] num_pnts size of pnts array
*/
BG_EXPORT extern int
bg_pnts_obb(point_t *c, vect_t *v1, vect_t *v2, vect_t *v3, const point_t *p, size_t num_pnts);
/**
* @brief
* Calculate explicit vertices for an oriented box.
*
* Note verts (supplied by caller) must have sufficient storage to hold 8 vertex points
*
* Returns BRLCAD_OK if successful, else BRLCAD_ERROR.
*
* @param[out] verts array of 8 XYZ coordinates defining the bbox
* @param[in] c XYZ coordinate defining the bbox center
* @param[out] v1 first extent vector of the bbox
* @param[out] v2 second extent vector of the bbox
* @param[out] v3 third extent vector of the bbox
*
* Output vertices are organized according to the librt arb8 convention:
* verts[0]: 0,0,0
* verts[1]: 0,1,0
* verts[2]: 0,1,1
* verts[3]: 0,0,1
* verts[4]: 1,0,0
* verts[5]: 1,1,0
* verts[6]: 1,1,1
* verts[7]: 1,0,1
*/
BG_EXPORT extern int
bg_obb_pnts(point_t *verts, const point_t *c, const vect_t *v1, const vect_t *v2, const vect_t *v3);
__END_DECLS
#endif /* BG_PNTS_H */
/** @} */
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
-65
View File
@@ -1,65 +0,0 @@
/* P O I N T G E N . H
* BRL-CAD
*
* Copyright (c) 2004-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/*----------------------------------------------------------------------*/
/* @file pointgen.h */
/** @addtogroup bg_pointgen */
/** @{ */
/**
* @brief Routines for the generation of pseudo-random and quasi-random
* points.
*/
#ifndef BG_POINTGEN_H
#define BG_POINTGEN_H
#include "common.h"
#include "vmath.h"
#include "bn/numgen.h"
#include "bg/defines.h"
__BEGIN_DECLS
/**
* @brief
* Generate points on a sphere per Marsaglia (1972).
*
* The return code is the number of points generated.
*
* The user is responsible for selecting the numerical generator used to
* supply pseudo or quasi-random numbers to bg_sph_sample - different
* types of inputs may be needed depending on the application.
*/
BG_EXPORT extern size_t bg_sph_sample(point_t *pnts, size_t cnt, const point_t center, const fastf_t radius, bn_numgen n);
__END_DECLS
#endif /* BG_POINTGEN_H */
/** @} */
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
+2 -2
View File
@@ -92,8 +92,8 @@ bg_sat_tri_obb(
*/
BG_EXPORT extern int
bg_sat_aabb_obb(
point_t aabb_min, point_t aabb_max,
point_t obb_center, vect_t obb_extent1, vect_t obb_extent2, vect_t obb_extent3
const point_t aabb_min, const point_t aabb_max,
const point_t obb_center, const vect_t obb_extent1, const vect_t obb_extent2, const vect_t obb_extent3
);
/**
+19
View File
@@ -141,6 +141,25 @@ BG_EXPORT extern struct bg_trimesh_halfedge * bg_trimesh_generate_edge_list(int
BG_EXPORT extern int
bg_trimesh_aabb(point_t *min, point_t *max, const int *faces, size_t num_faces, const point_t *p, size_t num_pnts);
/**
* @brief
* Calculate an oriented bounding box for a triangle mesh.
*
* NOTE: This routine bounds only those points that are active in the triangle
* mesh, not all points present in the supplied points array.
*
* @param[out] c XYZ coordinate defining the bbox center
* @param[out] v1 first extent vector of the bbox
* @param[out] v2 second extent vector of the bbox
* @param[out] v3 third extent vector of the bbox
* @param[in] faces array of trimesh faces
* @param[in] num_faces size of faces array
* @param[in] p array that holds the points defining the trimesh
* @param[in] num_pnts size of pnts array
*/
BG_EXPORT extern int
bg_trimesh_obb(point_t *c, vect_t *v1, vect_t *v2, vect_t *v3, const int *faces, size_t num_faces, const point_t *p, size_t num_pnts);
/**
* @brief
* Calculate the surface area of a triangle mesh.
+1 -1
View File
@@ -122,7 +122,7 @@ BN_EXPORT int bn_numgen_next_doubles(double *l, size_t cnt, bn_numgen ngen);
* https://projecteuclid.org/euclid.aoms/1177692644
*
* The user is responsible for selecting the numerical generator used to
* supply pseudo or quasi-random numbers to bg_sph_sample - different
* supply pseudo or quasi-random numbers to bn_sph_sample - different
* types of inputs may be needed depending on the application.
*/
BN_EXPORT extern void bn_sph_pnts(point_t *pnts, size_t cnt, bn_numgen n);
+38 -51
View File
@@ -62,6 +62,10 @@ __BEGIN_DECLS
// would get gnarly if we allowed something like that to be a valid key.)
#define BU_CACHE_KEY_MAXLEN 511
// If we need to be certain cache operations are complete before proceeding,
// or nobody else will start a cache operation until we're done, use this
// semaphore.
BU_EXPORT extern int BU_SEM_CACHE;
struct bu_cache_impl;
struct bu_cache_txn;
@@ -96,13 +100,9 @@ struct bu_cache_item {
BU_EXPORT extern struct bu_cache *bu_cache_open(const char *cache_db, int create, size_t max_cache_size);
/**
* Closes the bu_cache and frees all associated memory. Will NOT close
* if bu_cache_write still has an active txn - in that case, calling
* code needs to call bu_cache_write_commit or bu_cache_write_abort before
* bu_cache_close will succeed. returns BRLCAD_ERROR if close was not
* successful, else BRLCAD_OK.
* Closes the bu_cache and frees all associated memory.
*/
BU_EXPORT extern int bu_cache_close(struct bu_cache *c);
BU_EXPORT extern void bu_cache_close(struct bu_cache *c);
/**
* Erase the specified cache from disk. Any open instances of the
@@ -131,55 +131,14 @@ BU_EXPORT size_t bu_cache_get(void **data, const char *key, struct bu_cache *c,
BU_EXPORT void bu_cache_get_done(struct bu_cache_txn **t);
/**
* Assign data to the cache using the specified key.
*
* If t is NULL, the write is handled immediately as a complete operation, and
* bu_cache_write immediately validates that the written data can be
* successfully read.
*
* If t is non-NULL, the txn is not finalized and the calling code can queue up
* more write operations for eventual commit. This mode is MUCH more
* performant when lots of rapid writes are needed, but no per-write read-back
* validation is performed (since the write is not yet finalized.) This mode
* requires explicit management of when to finalize the operation for the
* database, and if the user wants to validate that reads successfully return
* the expected data they will need to do it themselves, but the speedup
* will almost always be worth it for any non-trivial data input. If an individual
* write DOES report failure (return size 0) in this mode, parent code should
* not try to continue writing - they should call bu_cache_write_abort
* immediately and handle the failure case, since the commit operation will
* also ultimately fail.
*
* A cache may only have one active write txn at a time - this is enforced
* internally in the implementation, and a bu_cache_write will fail if it
* attempts to create a new write when one is already active.
* Assign data to the cache using the specified key
*/
BU_EXPORT size_t bu_cache_write(void *data, size_t dsize, const char *key, struct bu_cache *c, struct bu_cache_txn **t);
BU_EXPORT size_t bu_cache_write(void *data, size_t dsize, const char *key, struct bu_cache *c);
/**
* Like bu_cache_get_done for data retrieval, a series of write operations may
* be either committed or (if the parent code has changed its mind) aborted.
* t is the bu_cache_txn returned by bu_cache write's t parameter.
*
* returns BRLCAD_OK on success and BRLCAD_ERROR on error.
* Clear data associated with the specified key from the cache
*/
BU_EXPORT int bu_cache_write_commit(struct bu_cache *c, struct bu_cache_txn **t);
/**
* If the calling code decides not to commit a series of bu_cache_write calls staged
* with a non-NULL t param to a bu_cache_write, call bu_cache_write_abort to clear
* the decks. */
BU_EXPORT void bu_cache_write_abort(struct bu_cache_txn **t);
/**
* Clear data associated with the specified key from the cache. Because this is a
* write operation as far as the database is concerned, it is treated the same way
* bu_cache_write operations are as far as txn behavior is concerned. If you have
* a batch bu_cache_write in progress and want to do a clear, the write txn should
* be provided to bu_cache_clear as well, and like other writes it will not be
* finalized until commit is called.
*/
BU_EXPORT void bu_cache_clear(const char *key, struct bu_cache *c, struct bu_cache_txn **t);
BU_EXPORT void bu_cache_clear(const char *key, struct bu_cache *c);
/**
* Get an array of keys present in the cache. Caller is responsible
@@ -188,6 +147,34 @@ BU_EXPORT void bu_cache_clear(const char *key, struct bu_cache *c, struct bu_cac
BU_EXPORT int bu_cache_keys(char ***keysv, struct bu_cache *c);
// It is common convention within the BRL-CAD code to use a ":#[#...]" suffix
// after a hash string to denote a particular type of data when creating a hash
// key. Most of these are internal, but in a few cases the type of hashed data
// is common to many different libraries. Therefore, for convenience, we define
// a few of them here and document the expected storage to enable data reuse.
/* Axis Aligned Bounding Box - stored as an array of two points:
* bbmin[0]bbmin[1][bbmin[2][bbmax[0]bbmax[1]bbmax[2] */
#define CACHE_AABB "aabb"
/* An inversion matrix is intended to take data defined at the origin after a
* Principle Component Analysis and restore it to its original position.
* Stored as an array of 16 fastf_t values per the vmath.h mat_t convention. */
#define CACHE_INV_MAT "im"
/* Oriented Bounding Box - stored as an array of a center point
* c and three extent vectors v1, v2, v3:
* c[0]c[1]c[2]v1[0]v1[1]v1[2]v2[0]v2[1]v2[2]v3[0]v3[1]v3[2] */
#define CACHE_OBB "obb"
/* Timestamp (microseconds since UNIX epoch) stored as a single int64_t */
#define CACHE_TIMESTAMP "timestmp"
__END_DECLS
#endif /* BU_CACHE_H */
+8 -1
View File
@@ -66,7 +66,14 @@ BU_EXPORT extern int bu_file_exists(const char *path, int *fd);
* @return >=0 The given filename exists.
* @return -1 The given filename does not exist or there was an error.
*/
BU_EXPORT extern int bu_file_size(const char *path);
BU_EXPORT extern long long bu_file_size(const char *path);
/**
* Returns the timestamp in microseconds since the UNIX
* epoch. Time should be compatible with bu_gettime for
* comparison purposes.
*/
BU_EXPORT extern int64_t bu_file_timestamp(const char *path);
/**
* Returns truthfully as to whether the two provided filenames are the
+1 -1
View File
@@ -260,7 +260,7 @@ union bu_lex_token {
};
struct bu_lex_key {
int tok_val;
char *string;
const char *string;
};
#define BU_LEX_NEED_MORE 0
+1
View File
@@ -83,6 +83,7 @@ __BEGIN_DECLS
#define BN_TOL_MAGIC 0x98c734bb /**< ??4? */
#define BN_UNIF_MAGIC 0x00be7460 /**< ??t` => 12481632 */
#define BN_VERT_TREE_MAGIC 0x56455254 /**< VERT */
#define BV_SOBJ_MAGIC 0x534F424A /**< SOBJ */
#define BV_VLBLOCK_MAGIC 0x981bd112 /**< ???? */
#define BV_VLIST_MAGIC 0x98237474 /**< ?\#tt */
+1 -1
View File
@@ -43,11 +43,11 @@
#include "./bv/defines.h"
#include "./bv/adc.h"
#include "./bv/lod.h"
#include "./bv/objs.h"
#include "./bv/polygon.h"
#include "./bv/snap.h"
#include "./bv/util.h"
#include "./bv/vlist.h"
#include "./bv/view_sets.h"
#endif /* BV_H */
+1 -1
View File
@@ -5,6 +5,7 @@ set(
events.h
faceplate.h
lod.h
objs.h
plot3.h
polygon.h
snap.h
@@ -13,7 +14,6 @@ set(
util.h
vectfont.h
vlist.h
view_sets.h
)
brlcad_manage_files(bv_headers ${INCLUDE_DIR}/brlcad/bv REQUIRED libbv)
+38 -77
View File
@@ -132,12 +132,13 @@ struct bv_axes {
// for value setting
struct bv_obj_settings {
int s_dmode; /**< @brief draw modes (TODO - are these accurate?):
int s_dmode; /**< @brief draw modes:
* 0 - wireframe
* 1 - shaded bots and polysolids only (booleans NOT evaluated)
* 2 - shaded (booleans NOT evaluated)
* 3 - shaded (booleans evaluated)
* 3 - wireframe (evaluated)
* 4 - hidden line
* 5 - point sampled triangles (evaluated)
*/
int mixed_modes; /**< @brief when drawing, don't remove an objects view objects for other modes */
fastf_t transparency; /**< @brief holds a transparency value in the range [0.0, 1.0] - 1 is opaque */
@@ -191,14 +192,9 @@ struct bview;
#define BV_LOCAL_OBJS 0x04
#define BV_CHILD_OBJS 0x08
struct bv_scene_obj_internal;
struct bv_scene_obj {
struct bu_list l;
/* Internal implementation storage */
struct bv_scene_obj_internal *i;
/* View object name and type id */
unsigned long long s_type_flags;
struct bu_vls s_name; /**< @brief object name (should be unique if view objects are to be addressed by name) */
@@ -206,6 +202,10 @@ struct bv_scene_obj {
void *dp; /**< @brief app obj data */
mat_t s_mat; /**< @brief mat to use for internal lookup and mesh LoD drawing */
/* Timestamp of when the bv_scene_obj was last altered. Should be
* set by user codes if they are the ones doing the altering. */
int64_t timestamp;
/* Associated bv. Note that scene objects are not assigned uniquely to
* one view. This value may be changed by the application in a multi-view
* scenario as an object is edited from multiple different views, to supply
@@ -217,9 +217,15 @@ struct bv_scene_obj {
/* Knowledge of how to create/update s_vlist and the other 3D geometry data, as well as
* manage any custom data specific to this object */
void *s_i_data; /**< @brief custom view data (bv_line_seg, bv_label, bv_polyon, etc) */
int (*s_update_callback)(struct bv_scene_obj *, struct bview *, int); /**< @brief custom update/generator for s_vlist */
void (*s_free_callback)(struct bv_scene_obj *); /**< @brief free any info stored in s_i_data, s_path and draw_data */
// TODO - maybe this can be replaced with a "reset" flag which will be used by ft_scene_obj
// to determine whether to force a rebuild of the vlist info... If the responsibility for
// ensuring current data shifts to the app rather than libdm, the scene obj shouldn't have
// to encode knowledge of how to update itself...
int reset;
int (*s_update_callback)(struct bv_scene_obj *, struct bview *, int); /**< @brief custom update/generator for s_vlist */
/* 3D vector list geometry data */
struct bu_list s_vlist; /**< @brief Pointer to unclipped vector list */
size_t s_vlen; /**< @brief Number of actual cmd[] entries in vlist */
@@ -277,12 +283,24 @@ struct bv_scene_obj {
* may be overridden locally */
struct bv_obj_settings *s_os;
struct bv_obj_settings s_local_os;
int s_inherit_settings; /**< @brief Use current obj settings when drawing children instead of their settings */
int s_override_obj_ref_settings; /**< @brief Use current obj settings when drawing obj_refs instead of their settings */
/* Settings that may be less necessary... */
struct bv_scene_obj_old_settings s_old;
/* Child objects of this object */
/* Objects to draw when drawing this object. Like
* children in that they are drawn using this
* object's settings, but unlike them in that their
* memory management is not handled by this object.
* Used for things like "instance objects" to reference
* another object's geometry for drawing purposes. */
struct bu_ptbl obj_refs;
/* Child objects of this object. Used for things like
* textual labels on geometric primitives, these will
* be deleted when this object is deleted (unlike object
* references above.) */
struct bu_ptbl children;
/* Parent object of this object */
@@ -296,7 +314,7 @@ struct bv_scene_obj {
struct bu_list *vlfree;
/* Container for reusing bv_scene_obj allocations */
struct bv_scene_obj *free_scene_obj;
struct bv_obj_pool *obj_pool;
/* View container containing this object */
struct bu_ptbl *otbl;
@@ -374,45 +392,6 @@ struct bv_scene_obj {
*/
#define bv_scene_group bv_scene_obj
/* The primary "working" data for mesh Level-of-Detail (LoD) drawing is stored
* in a bv_mesh_lod container.
*
* Most LoD information is deliberately hidden in the internal, but the key
* data needed for drawing routines and view setup are exposed. Although this
* data structure is primarily managed in libbg, the public data in this struct
* is needed at many levels of the software stack, including libbv. */
struct bv_mesh_lod {
// The set of triangle faces to be used when drawing
int fcnt;
const int *faces;
// The vertices used by the faces array
int pcnt;
const point_t *points; // If using snapped points, that's this array. Else, points == points_orig.
int porig_cnt;
const point_t *points_orig;
// Optional: per-face-vertex normals (one normal per triangle vertex - NOT
// one normal per vertex. I.e., a given point from points_orig may have
// multiple normals associated with it in different faces.)
const vect_t *normals;
// Bounding box of the original full-detail data
point_t bmin;
point_t bmax;
// The scene object using this LoD structure
struct bv_scene_obj *s;
// Pointer to the higher level LoD context associated with this LoD data
void *c;
// Pointer to internal LoD implementation information specific to this object
void *i;
};
/* Flags to identify categories of objects to snap */
#define BV_SNAP_SHARED 0x1
#define BV_SNAP_LOCAL 0x2
@@ -555,7 +534,9 @@ struct bview_knobs {
};
struct bview_set;
typedef int (*dm_obj_clbk_t)(void *, struct bv_scene_obj *);
typedef int (*dm_view_clbk_t)(void *, struct bview *);
typedef unsigned long long (*dm_hash_clbk_t)(void *);
struct bview {
uint32_t magic; /**< @brief magic number */
@@ -613,22 +594,6 @@ struct bview {
struct bview_settings *gv_s; /**< @brief shared settings supplied by user */
struct bview_settings gv_ls; /**< @brief locally maintained settings specific to view (used if gv_s is null) */
/* If a view is marked as independent, its local containers are used even
* if pointers to shared tables are set. This allows for fully independent
* views with the same GED instance, at the cost of increased memory usage
* if multiple views draw the same objects. */
int independent;
/* Set containing this view. Also holds pointers to resources shared
* across multiple views */
struct bview_set *vset;
/* Scene objects active in a view. Managing these is a relatively complex
* topic and depends on whether a view is shared, independent or adaptive.
* Shared objects are common across views to make more efficient use of
* system memory. */
struct bview_objs gv_objs;
/* We sometimes need to define the volume in space that is "active" for the
* view. For an orthogonal camera this is the oriented bounding box
* extruded to contain active scene objects visible in the view The app
@@ -659,17 +624,13 @@ struct bview {
void (*gv_callback)(struct bview *, void *); /**< @brief called in ged_view_update with gvp and gv_clientData */
void *gv_clientData; /**< @brief passed to gv_callback */
struct bu_ptbl *callbacks;
void *dmp; /* Display manager pointer, if one is associated with this view */
void *u_data; /* Caller data associated with this view */
};
// Because bview instances frequently share objects in applications, they are
// not always fully independent - we define a container and some basic
// operations to manage this.
struct bview_set_internal;
struct bview_set {
struct bview_set_internal *i;
struct bview_settings settings;
void *dmp; /* Display manager pointer, if one is associated with this view */
dm_obj_clbk_t *dm_draw_sobj; /* Function pointer to a method to draw a scene object in the dmp display manager. */
dm_view_clbk_t *dm_draw_view; /* Function pointer to a method to draw view only graphics such as faceplate. */
dm_hash_clbk_t *dm_hash; /* Function pointer to a method to calculate a state hash of dmp. */
void *u_data; /* Caller data associated with this view */
};
__END_DECLS
+112 -125
View File
@@ -22,8 +22,8 @@
/** @addtogroup bv_lod
*
* @brief
* Functions for generating view dependent level-of-detail data,
* particularly for meshes.
* Functions for generating, storing and retrieving view dependent
* level-of-detail data.
*/
/** @{ */
/* @file lod.h */
@@ -38,159 +38,147 @@
__BEGIN_DECLS
/* Given a view, construct either an oriented bounding box or a view frustum
* extruded to contain scene objects visible in the view. Conceptually, think
* of it as a framebuffer pane pushed through the scene in the direction the
* camera is looking. If the view width and height are not set or there is
* some other problem, no volume is computed. This function is intended
* primarily to be set as an updating callback for the bview structure. */
BV_EXPORT extern void
bv_view_bounds(struct bview *v);
#define LOD_MESH_MAGIC 0x4C4F44D /**< LODM */
/* Given a screen x,y coordinate, construct the set of all scene objects whose
* AABB intersect with the OBB created by the projection of that pixel through
* the scene. sset holds the struct bv_scene_obj pointers of the selected
* objects. */
BV_EXPORT int
bv_view_objs_select(struct bu_ptbl *sset, struct bview *v, int x, int y);
/* Other libraries may care if libbv's format changes */
#define BV_CACHE_CURRENT_FORMAT 3
/* Given a screen x1,y1,x2,y2 rectangle, construct and return the set of all scene
* objects whose AABB intersect with the OBB created by the projection of that
* rectangle through the scene. */
BV_EXPORT int
bv_view_objs_rect_select(struct bu_ptbl *sset, struct bview *v, int x1, int y1, int x2, int y2);
/* Storing and reading from a lot of small, individual files doesn't work very
* well on some platforms. We provide a "context" to manage bookkeeping of data
* across objects. The details are implementation internal - the application
* will simply create a context with a file name and provide it to the various
* LoD calls. */
struct bv_mesh_lod_context_internal;
struct bv_mesh_lod_context {
struct bv_mesh_lod_context_internal *i;
};
/* Create an LoD context using "name". If data is already present associated
* with that name it will be loaded, otherwise a new storage structure will be
* initialized. If creation or loading fails for any reason the return value
* NULL.
/* The primary "working" data for mesh Level-of-Detail (LoD) drawing is stored
* in a bv_mesh_lod container.
*
* Note that "name" should be a full, unique path associated with the source
* database. libbu will manage where the context data is cached.
*/
BV_EXPORT struct bv_mesh_lod_context *
bv_mesh_lod_context_create(const char *name);
/* Free all memory associated with context c. Note that this call does NOT
* remove the on-disk data. */
BV_EXPORT void
bv_mesh_lod_context_destroy(struct bv_mesh_lod_context *c);
/* Remove cache data associated with key. If key == 0, remove ALL cache data
* associated with all LoD objects in c. (i.e. a full LoD cache reset for that
* .g database). If key == 0 AND c == NULL, clear all LoD cache data for all
* .g databases associated with the current user's cache.
* Most LoD information is deliberately hidden in the internal, but the key
* data needed for drawing routines and view setup are exposed.
*
* TODO - this container can probably be more generic than just triangle
* data - for example, we might want to cache wireframes for CSG objects.
*
* Should the dlist arrays for OpenGL live here too? This might be a logical
* place to put them...
*/
BV_EXPORT void
bv_mesh_lod_clear_cache(struct bv_mesh_lod_context *c, unsigned long long key);
struct bv_lod_mesh {
uint32_t magic;
// The set of triangle faces to be used when drawing
int fcnt;
const int *faces;
// The vertices used by the faces array
int pcnt;
const point_t *points; // If using snapped points, that's this array. Else, points == points_orig.
int porig_cnt;
const point_t *points_orig;
// Optional: per-face-vertex normals (one normal per triangle vertex - NOT
// one normal per vertex. I.e., a given point from points_orig may have
// multiple normals associated with it in different faces.)
const vect_t *normals;
// Bounding box of the original full-detail data
point_t bmin;
point_t bmax;
// libbu cache data is being retrieved from
struct bu_cache *c;
// The scene object using this LoD structure
struct bv_scene_obj *s;
// Pointer to internal LoD implementation information specific to this object
void *i;
};
/**
* Given a set of points and faces, calculate a lookup key and determine if the
* cache has the LoD data for this particular mesh. If it does not, do the
* initial calculations to generate the cached LoD data needed for subsequent
* lookups, otherwise just return the calculated key.
* initial calculations to generate the LoD data needed for subsequent
* lookups and return a set of struct bu_cache_item containers. Caller should
* write these to the cache of their choice.
*
* Name is passed in to allow the internal logic to generate the cache keys
* needed. While these are technically visible in the bu_cache_item containers
* and used in bu_cache_write calls, they are NOT intended to be user modifiable
* and constitute internal implementation details of the LoD data system.
*
* This is potentially an expensive operation, particularly if the LoD data set
* must be generated for the mesh.
*
* If user_key != 0, it will be used instead of the mesh data hash as the db
* key to be used for subsequent lookups. Typically calculated with
* bu_data_hash from user supplied data, if the mesh data is not
* the desired source of the key.
* Note: to clear pre-existing cached data first, use bv_lod_clear_gen(tbl, name, c) to generate bu_cache_items and then call bu_cache_clear on the active cache using the item keys;
*
* Note: to clear pre-existing cached data, run bv_mesh_lod_clear_cache();
*
* @return the lookup key calculated from the data */
BV_EXPORT unsigned long long
bv_mesh_lod_cache(struct bv_mesh_lod_context *c, const point_t *v, size_t vcnt, const vect_t *vn, int *f, size_t fcnt, unsigned long long user_key, fastf_t fratio);
/**
* Given a name, see if the context has a key associated with that name.
* If so return it, else return zero.
*
* Users of this feature need to be aware that it is the responsibility
* of the application to maintain the LoD cache data and keep it current -
* it is quite possible, in a data sense, for the LoD data to be out of
* date if something has changed the named geometry object and not updated
* the cache.
*
* The advantage of this feature, if the application does maintain the
* data correctly, is to make it possible to load a high level view of
* a large model without having to hash the full mesh data of the model
* to retrieve the data.
*/
BV_EXPORT unsigned long long
bv_mesh_lod_key_get(struct bv_mesh_lod_context *c, const char *name);
/**
* Given a name and a key, instruct the context to associate that name with
* the key.
*
* Returns 0 if successful, else error
*/
* @return 0 if no data create, 1 if data items were created. */
BV_EXPORT int
bv_mesh_lod_key_put(struct bv_mesh_lod_context *c, const char *name, unsigned long long key);
bv_lod_mesh_gen(struct bu_ptbl *cache_items, const char *name, const point_t *v, size_t vcnt, const vect_t *vn, int *f, size_t fcnt, fastf_t fratio);
/**
* Set up the bv_mesh_lod container using cached LoD information associated
* with key. If no cached data has been prepared, a NULL container is
* returned - to prepare cached data, call bv_mesh_lod_cache with the original
* mesh input data. This call is intended to be usable in situations where
* we don't want to pull the full mesh data set into memory, so we can't assume
* the original data is present.
* Generate a set of LoD cache data items associated with name
* to be cleared. (The cache is needed because keys are sometimes
* used to look up other associated keys.)
*/
BV_EXPORT void
bv_lod_clear_gen(struct bu_ptbl *cache_items, const char *name, struct bu_cache *c);
/**
* Set up the bv_lod_mesh container using cached mesh LoD information associated
* with name. If no cached mesh data is associated with name, a NULL container is
* returned.
*
* Note: bv_mesh_lod assumes a non-changing mesh - if the mesh is changed after
* it is created, the internal container does *NOT* automatically update. In
* that case the old struct should be destroyed and a new one created.
* To prepare cached data, call bv_lod_mesh_cache with the original
* mesh input data.
*
* A bv_mesh_lod return from this function will be initialized only to the
* This call is intended to be usable in situations where we don't want to pull
* the full mesh data set into memory, so we can't assume the original data is
* present.
*
* A bv_lod_mesh return from this function will be initialized only to the
* lowest level of data (i.e. the coarsest possible representation of the
* object.) To tailor the data, use the bv_mesh_lod_view function. For lower
* level control, the bv_mesh_lod_level function may be used to explicitly
* object.) To tailor the data, use the bv_lod_mesh_view function. For lower
* level control, the bv_lod_mesh_level function may be used to explicitly
* manipulate the loaded LoD (usually used for debugging, but also useful if an
* application wishes to visualize levels explicitly.)
*/
BV_EXPORT struct bv_mesh_lod *
bv_mesh_lod_create(struct bv_mesh_lod_context *c, unsigned long long key);
BV_EXPORT struct bv_lod_mesh *
bv_lod_mesh_get(struct bu_cache *c, const char *name);
/* Clean up the lod container. */
BV_EXPORT void
bv_mesh_lod_destroy(struct bv_mesh_lod *l);
bv_lod_mesh_put(struct bv_lod_mesh *l);
/**
* Given a scene object with mesh LoD data stored in s->draw_data, reduce
* memory footprint (for use after client codes have completed use of a
* particular level's info, but aren't done with the object. Main use case
* currently is OpenGL display lists - once generated, we can clear the
* internally stored LoD data until the level changes. Note that there is a
* re-loading performance penalty as a trade-off to the memory savings. */
* Given a scene object with LoD data stored in s->draw_data, reduce memory
* footprint if possible. Intended for use after client codes have completed
* use of a particular level's info, but aren't done with the object.
*
* Main use case currently is OpenGL display lists - once generated, we can
* clear the internally stored LoD data until the level changes. Note that
* there is a re-loading performance penalty as a trade-off to the memory
* savings. */
BV_EXPORT void
bv_mesh_lod_memshrink(struct bv_scene_obj *s);
bv_lod_memshrink(struct bv_scene_obj *s);
/**
* Given a scene object with mesh LoD data stored in s->draw_data and a bview,
* load the appropriate level of detail for displaying the mesh in that view.
* Set reset == 1 if the caller wants to undo a memshrink operation even if the
* level isn't changed by the current view settings.
* Given a scene object with LoD data stored in s->draw_data and a bview,
* calculate the appropriate level of detail for that view.
*
* This function simply returns the level without changing any data, which
* allows applications to decide if any further action is warranted.
*
* Returns the level appropriate for the view. If v == NULL, return current
* level of l. If there is an error or l == NULL, return -1; */
BV_EXPORT int
bv_lod_calc_level(struct bv_scene_obj *s, const struct bview *v);
/**
* Given a scene object with LoD data stored in s->draw_data and a bview, load
* the appropriate level of detail for displaying in that view. Set reset == 1
* if the caller wants to undo a memshrink operation even if the level isn't
* changed by the current view settings.
*
* Returns the level selected. If v == NULL, return current level of l. If
* there is an error or l == NULL, return -1; */
BV_EXPORT int
bv_mesh_lod_view(struct bv_scene_obj *s, struct bview *v, int reset);
bv_lod_view(struct bv_scene_obj *s, const struct bview *v, int reset);
/**
* Given a scene object with mesh LoD data stored in s->draw_data and a detail
* Given a scene object with LoD data stored in s->draw_data and a detail
* level, load the appropriate data. This is not normally used by client codes
* directly, but may be needed if an app needs manipulate the level of detail
* without a view. Set reset == 1 if the caller wants to undo a memshrink
@@ -199,14 +187,13 @@ bv_mesh_lod_view(struct bv_scene_obj *s, struct bview *v, int reset);
* Returns the level selected. If level == -1, return current level of l. If
* there is an error, return -1; */
BV_EXPORT int
bv_mesh_lod_level(struct bv_scene_obj *s, int level, int reset);
bv_lod_level(struct bv_scene_obj *s, int level, int reset);
/* Free a scene object's LoD data. Suitable as a s_free_callback function
* for a bv_scene_obj. This function will also trigger any additional
* "free" callback functions which might be defined for the LoD container. */
BV_EXPORT void
bv_mesh_lod_free(struct bv_scene_obj *s);
bv_lod_free(struct bv_scene_obj *s);
/* In order to preserve library barriers, a number of operations needed to
@@ -215,11 +202,11 @@ bv_mesh_lod_free(struct bv_scene_obj *s);
/* Set function callbacks for retrieving and freeing high levels of mesh detail */
BV_EXPORT void
bv_mesh_lod_detail_setup_clbk(struct bv_mesh_lod *lod, int (*clbk)(struct bv_mesh_lod *, void *), void *cb_data);
bv_lod_mesh_detail_setup_clbk(struct bv_lod_mesh *lod, int (*clbk)(struct bv_lod_mesh *, void *), void *cb_data);
BV_EXPORT void
bv_mesh_lod_detail_clear_clbk(struct bv_mesh_lod *lod, int (*clbk)(struct bv_mesh_lod *, void *));
bv_lod_mesh_detail_clear_clbk(struct bv_lod_mesh *lod, int (*clbk)(struct bv_lod_mesh *, void *));
BV_EXPORT void
bv_mesh_lod_detail_free_clbk(struct bv_mesh_lod *lod, int (*clbk)(struct bv_mesh_lod *, void *));
bv_lod_mesh_detail_free_clbk(struct bv_lod_mesh *lod, int (*clbk)(struct bv_lod_mesh *, void *));
__END_DECLS
+143
View File
@@ -0,0 +1,143 @@
/* O B J S . H
* BRL-CAD
*
* Copyright (c) 1993-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @addtogroup bv_objs
*
* Routines for managing and operating on libbv scene objects.
*
*/
/** @{ */
/** @file bv/objs.h */
#ifndef BV_OBJS_H
#define BV_OBJS_H
#include "common.h"
#include "bu/ptbl.h"
#include "bn/tol.h"
#include "bv/defines.h"
#include "dm/defines.h"
__BEGIN_DECLS
/* Copy settings. Return 0 if no changes were made to dest. If dest did have
* one or more settings updated from src, return 1. */
BV_EXPORT extern int bv_obj_settings_sync(struct bv_obj_settings *dest, struct bv_obj_settings *src);
/* Scene objects are one of the things we sometimes want to reuse. The
* following routines support the creation an opaque memory pool libbv routines
* can optionally pull from. */
struct bv_obj_pool_internal;
struct bv_obj_pool {
struct bv_obj_pool_internal *i;
};
/* Create an empty object pool */
BV_EXPORT struct bv_obj_pool *
bv_obj_pool_create();
/* Destroy an object pool and all internal contents */
BV_EXPORT void
bv_obj_pool_destroy(struct bv_obj_pool *p);
/* Create a bv_scene_obj. If p is not NULL, first try to pull from the pool
* before mallocing a new object. */
BV_EXPORT struct bv_scene_obj *
bv_obj_get(struct bv_obj_pool *p);
/* Given an object, create an object that is a child of that object. Will use
* s->obj_pool (if set) for memory allocation. */
BV_EXPORT struct bv_scene_obj *
bv_obj_get_child(struct bv_scene_obj *s);
/* Given a scene object and a name vname, glob match child names and uuids to
* attempt to locate a child of s that matches vname */
BV_EXPORT struct bv_scene_obj *
bv_obj_find_child(struct bv_scene_obj *s, const char *vname);
/* Copy object attributes (but not geometry) from src to dest */
BV_EXPORT extern void
bv_obj_sync(struct bv_scene_obj *dest, struct bv_scene_obj *src);
/* Clear the contents of an object (including releasing its children).
* Generally used when redrawing an object */
BV_EXPORT void
bv_obj_reset(struct bv_scene_obj *s);
/* Release an object. If o->obj_pool is not NULL, clear it and add to the pool
* of available objects. If o->obj_pool is NULL, free o. */
BV_EXPORT void
bv_obj_put(struct bv_scene_obj *o);
/* Compute the min, max, and center points of the scene object.
* Return 1 if a bound was computed, else 0 */
BV_EXPORT extern int
bv_obj_bound(struct bv_scene_obj *s);
/* Set the illumination state on the object and its children to ill_state.
* Returns 0 if no states were changed, and 1 if one or more states were
* updated. */
BV_EXPORT int
bv_obj_illum(struct bv_scene_obj *s, char ill_state);
/* Given a view, and a set of scene objects, construct either an oriented
* bounding box or a view frustum extruded to contain scene objects visible in
* the view. Conceptually, think of it as a framebuffer pane pushed through
* the scene in the direction the camera is looking. If the view width and
* height are not set or there is some other problem, no volume is computed.
* This function is intended primarily to be set as an updating callback for
* the bview structure. */
BV_EXPORT extern void
bv_view_bounds(struct bview *v, const struct bu_ptbl *so);
/* Given a view and an object, return whether or or not that object is
* visible in the view - 1 is visible, 0 is not visible. */
BV_EXPORT extern int
bv_view_obj_vis(const struct bview *v, const struct bv_scene_obj *s);
/* Given a screen x,y coordinate, construct the set of all scene objects whose
* AABB intersect with the OBB created by the projection of that pixel through
* the scene. sset holds the struct bv_scene_obj pointers of the selected
* objects. */
BV_EXPORT int
bv_view_objs_select(struct bu_ptbl *sset, const struct bview *v, const struct bu_ptbl *so, int x, int y);
/* Given a screen x1,y1,x2,y2 rectangle, construct and return the set of all scene
* objects whose AABB intersect with the OBB created by the projection of that
* rectangle through the scene. */
BV_EXPORT int
bv_view_objs_rect_select(struct bu_ptbl *sset, const struct bview *v, const struct bu_ptbl *so, int x1, int y1, int x2, int y2);
__END_DECLS
/** @} */
#endif /* BV_OBJS_H */
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
+2 -2
View File
@@ -72,10 +72,10 @@ struct bv_polygon {
};
// Given a polygon, create a scene object
BV_EXPORT extern struct bv_scene_obj *bv_create_polygon_obj(struct bview *v, int flags, struct bv_polygon *p);
BV_EXPORT extern struct bv_scene_obj *bv_create_polygon_obj(struct bview *v, struct bv_polygon *p);
// Creates a scene object with a default polygon
BV_EXPORT extern struct bv_scene_obj *bv_create_polygon(struct bview *v, int flags, int type, point_t *fp);
BV_EXPORT extern struct bv_scene_obj *bv_create_polygon(struct bview *v, int type, point_t *fp);
// Various update modes have similar logic - we pass in the flags to the update
// routine to enable/disable specific portions of the overall flow.
+3 -3
View File
@@ -42,11 +42,11 @@ __BEGIN_DECLS
* v->gv_s->gv_snap_flags also tells the routine which categories of objects to
* consider - objs objects will also be evaluated against the flags before
* being used. */
BV_EXPORT extern int bv_snap_lines_2d(struct bview *v, fastf_t *fx, fastf_t *fy);
BV_EXPORT extern int bv_snap_lines_2d(struct bview *v, const struct bu_ptbl *sobjs, fastf_t *fx, fastf_t *fy);
BV_EXPORT extern void bv_view_center_linesnap(struct bview *v);
BV_EXPORT extern void bv_view_center_linesnap(struct bview *v, const struct bu_ptbl *sobjs);
BV_EXPORT extern int bv_snap_lines_3d(point_t *out_pt, struct bview *v, point_t *p);
BV_EXPORT extern int bv_snap_lines_3d(point_t *out_pt, struct bview *v, const struct bu_ptbl *sobjs, point_t *p);
BV_EXPORT extern int bv_snap_grid_2d(struct bview *v, fastf_t *fx, fastf_t *fy);
__END_DECLS
+15 -176
View File
@@ -27,15 +27,15 @@
#define BV_UTIL_H
#include "common.h"
#include "bu/hash.h"
#include "bu/ptbl.h"
#include "bn/tol.h"
#include "dm/defines.h"
#include "bv/defines.h"
#include "dm/defines.h"
__BEGIN_DECLS
/* Set default values for a bv. */
BV_EXPORT extern void bv_init(struct bview *v, struct bview_set *s);
BV_EXPORT extern void bv_init(struct bview *v);
BV_EXPORT extern void bv_free(struct bview *v);
/**
@@ -52,16 +52,11 @@ BV_EXPORT extern void bv_settings_init(struct bview_settings *s);
/**
* Automatically set up the view to make the scene objects visible
*/
BV_EXPORT extern void bv_autoview(struct bview *v, fastf_t scale, int all_view_objs);
BV_EXPORT extern void bv_autoview(struct bview *v, const struct bu_ptbl *so, fastf_t scale);
/* Copy the size and camera info (deliberately not a full copy of all view state) */
BV_EXPORT extern void bv_sync(struct bview *dest, struct bview *src);
/* Copy settings (potentially) common to the view and scene objects.
* Return 0 if no changes were made to dest. If dest did have one
* or more settings updated from src, return 1. */
BV_EXPORT extern int bv_obj_settings_sync(struct bv_obj_settings *dest, struct bv_obj_settings *src);
/* Sync values within the bv, perform callbacks if any are defined */
BV_EXPORT extern void bv_update(struct bview *gvp);
@@ -80,22 +75,6 @@ BV_EXPORT extern int bv_update_selected(struct bview *gvp);
#define BV_KNOBS_ABS 2
BV_EXPORT extern void bv_knobs_reset(struct bview_knobs *k, int category);
/* Hash the semantic (non-pointer) contents of a bview_knobs struct. This
* intentionally excludes any *_udata pointers to avoid pointer address noise
* and skips any padding that would be present if hashing the raw struct.
*
* If 'state' is non-NULL the supplied hash state is updated in-place and the
* function returns 0 (the caller is expected to finalize the hash later.)
* If 'state' is NULL an internal hash state is created, populated and
* finalized and the resulting hash value is returned.
*
* Returns:
* 0 if k is NULL or state supplied (non-owning mode)
* hash if state is NULL (owning mode)
*/
BV_EXPORT extern unsigned long long
bv_knobs_hash(struct bview_knobs *k, struct bu_data_hash_state *state);
/**
* @brief
* Process an individual libbv knob command.
@@ -126,54 +105,20 @@ BV_EXPORT extern int bv_knobs_cmd_process(
char origin, int model_flag, int incr_flag
);
/**
* @brief
* Rotate the view based on an Euler angle triplet (degrees) specified
* in one of several coordinate frames, about one of several origins.
/* @brief
* Process a knob rotation vector.
*
* coords: Rotation input frame
* 'v' - rvec in view coordinates
* 'm' - rvec in model coordinates (converted via Rv * Rm * Rv^{-1})
* 'o' - rvec in object coordinates (use obj_rot to map object->model->view,
* fallback to 'v' semantics if obj_rot is NULL)
*
* origin: Rotation pivot specifier
* 'v' : view center (0,0,0 in view space)
* 'm' : model origin
* 'e' : eye point (0,0,1 in view space)
* 'k' : model-space custom pivot supplied via pvt_pt
* Any unrecognized value falls back to 'v'.
*
* obj_rot:
* Accumulated object->model rotation matrix when coords=='o'. NULL otherwise.
*
* pvt_pt:
* Model-space pivot point when origin=='k'. Ignored otherwise.
* NULL == model origin.
*
* BEHAVIOR
* 1. rvec is converted into a pure view-space rotation matrix according
* to 'coords' (and obj_rot for 'o').
* 2. If origin != 'v', the view center (gv_center) is relocated so the
* specified pivot is invariant under the applied rotation.
* 3. gv_rotation is post-multiplied by the view rotation matrix.
* 4. bv_update(v) refreshes derived matrices. Absolute translation bookkeeping
* (tra_v_abs / tra_m_abs) is always recomputed
*
* @param[in,out] v target bview structure
* @param[in] rvec rotation vector (Euler angles, degrees) expressed in the coordinate frame indicated by coords.
* @param[in] origin char indicating origin - may be 'e' (eye_pt), 'm' (model origin), 'v' (view origin - default) or 'k' (keypoint)
* @param[in] coords coordinate frame - may be 'm' (model), 'o' (obj coords via obj_rot), or 'v' (view)
* @param[in] obj_rot pointer to accumulated object rotation matrix (may be NULL)
* @param[in] pvt_pt model space pivot point
* @param[in] v bview structure
* @param[in] rvec Pointer to rotation vector
* @param[in] origin char indicating origin - may be 'e' (eye_pt), 'm' (model origin) or 'v' (view origin - default)
* @param[in] model_flag Manipulate view using model coordinates rather than view coordinates
*/
BV_EXPORT extern void
bv_knobs_rot(struct bview *v,
const vect_t rvec,
vect_t *rvec,
char origin,
char coords,
const matp_t obj_rot,
const pointp_t pvt_pt);
int model_flag);
/* @brief
* Process a knob translation vector.
@@ -184,7 +129,7 @@ bv_knobs_rot(struct bview *v,
*/
BV_EXPORT extern void
bv_knobs_tran(struct bview *v,
const vect_t tvec,
vect_t *tvec,
int model_flag);
@@ -206,10 +151,6 @@ BV_EXPORT extern unsigned long long bv_hash(struct bview *v);
/* Return a hash of the contents of a display list. Returns 0 on failure. */
BV_EXPORT extern unsigned long long bv_dl_hash(struct display_list *dl);
/* Returns number of objects defined in any object container
* known to this view (0 if completely cleared). */
BV_EXPORT extern size_t bv_clear(struct bview *v, int flags);
/* Note that some of these are mutually exclusive as far as producing any
* changes - a simultaneous constraint in X and Y, for example, results in a
* no-op. */
@@ -235,7 +176,7 @@ BV_EXPORT extern int bv_adjust(struct bview *v, int dx, int dy, point_t keypoint
/* Return -1 if width and/or height are unset (and hence a meaningful
* calculation is impossible), else 0. */
BV_EXPORT extern int bv_screen_to_view(struct bview *v, fastf_t *fx, fastf_t *fy, fastf_t x, fastf_t y);
BV_EXPORT extern int bv_screen_to_view(const struct bview *v, fastf_t *fx, fastf_t *fy, fastf_t x, fastf_t y);
/* Return -1 if width and/or height are unset (and hence a meaningful
* calculation is impossible), else 0.
@@ -245,112 +186,10 @@ BV_EXPORT extern int bv_screen_to_view(struct bview *v, fastf_t *fx, fastf_t *fy
*/
BV_EXPORT extern int bv_screen_pt(point_t *p, fastf_t x, fastf_t y, struct bview *v);
/* Compute the min, max, and center points of the scene object.
* Return 1 if a bound was computed, else 0 */
BV_EXPORT extern int bv_scene_obj_bound(struct bv_scene_obj *s, struct bview *v);
/* Find the nearest (mode == 0) or farthest (mode == 1) data_vZ value from
* the vlist points in s in the context of view v */
BV_EXPORT extern fastf_t bv_vZ_calc(struct bv_scene_obj *s, struct bview *v, int mode);
/* Copy object attributes (but not geometry) from src to dest */
BV_EXPORT extern void bv_obj_sync(struct bv_scene_obj *dest, struct bv_scene_obj *src);
/* Mark object and any child objects as stale for the drawing routines */
/* There are a few options for this situation - this one, which requires the client code
* to explicitly notify the drawing routines they need to do work, an internal options
* hash stored in the bv_scene_obj itself which is checked at render time, and setter
* wrapper functions that do the bookkeeping for the caller (in lieu of directly setting
* values in the bv_scene_obj struct.) The first one isn't ideal because the visual will
* be wrong if the caller doesn't supply the notification, the second has unknown
* performance implications, and the third would be a major rework of how the bv_scene_obj
* data is accessed (effectively, making the internal storage of bv_scene_obj fully hidden
* a.l.a the libdm rework.) Not sure what the best option is yet... leaning towards #2
* if it is "fast enough"... */
BV_EXPORT void bv_obj_stale(struct bv_scene_obj *s);
/* Given a view, create an object of the specified type. Like bv_obj_get, except it
* leaves the addition of objects to the client. Lower level. */
BV_EXPORT struct bv_scene_obj *
bv_obj_create(struct bview *v, int type);
/* Given a view, create an object of the specified type and add it to the
* appropriate container. Issues such as memory management as a function of
* view settings are handled internally, so client codes don't need to manage
* it. */
BV_EXPORT struct bv_scene_obj *
bv_obj_get(struct bview *v, int type);
/* Given an object, create an object that is a child of that object. Issues
* such as memory management as a function of view settings are handled
* internally, so client codes don't need to manage it. */
BV_EXPORT struct bv_scene_obj *
bv_obj_get_child(struct bv_scene_obj *s);
/* Clear the contents of an object (including releasing its children), but keep
* it active in the view. Generally used when redrawing an object */
BV_EXPORT void
bv_obj_reset(struct bv_scene_obj *s);
/* Release an object to the internal pools. */
BV_EXPORT void
bv_obj_put(struct bv_scene_obj *o);
/* Given a scene object and a name vname, glob match child names and uuids to
* attempt to locate a child of s that matches vname */
BV_EXPORT struct bv_scene_obj *
bv_find_child(struct bv_scene_obj *s, const char *vname);
/* Given a view and a name vname, glob match names and uuids to attempt to
* locate a scene object in v that matches vname.
*
* NOTE - currently this is searching the top level objects, but does not walk
* down into their children. May want to support that in the future... */
BV_EXPORT struct bv_scene_obj *
bv_find_obj(struct bview *v, const char *vname);
/* Given a seed name, generate a name that does not collide with any existing
* object names in the top level. If the seed name does not collide, it is
* returned as the result - otherwise, a name based on the seed name will be
* generated.
*/
BV_EXPORT void
bv_uniq_obj_name(struct bu_vls *oname, const char *seed, struct bview *v);
/* For the specified object/view pairing, return the appropriate scene object
* to use with that view. Usually this will return s, but if a Level of Detail
* scheme or some other view-aware rendering of the object is active, that object
* will be returned instead. */
BV_EXPORT struct bv_scene_obj *
bv_obj_for_view(struct bv_scene_obj *s, struct bview *v);
/* Get a view-specific object vobj for view v on object s. */
BV_EXPORT struct bv_scene_obj *
bv_obj_get_vo(struct bv_scene_obj *s, struct bview *v);
/* Check for the presence of view-specific objects */
BV_EXPORT int
bv_obj_have_vo(struct bv_scene_obj *s, struct bview *v);
/* Clear view-specific objects */
BV_EXPORT int
bv_clear_view_obj(struct bv_scene_obj *s, struct bview *v);
/* Set the illumination state on the object and its children to ill_state.
* Returns 0 if no states were changed, and 1 if one or more states were
* updated. */
BV_EXPORT int
bv_illum_obj(struct bv_scene_obj *s, char ill_state);
/* For the given view, return a pointer to the bu_ptbl holding active scene
* objects with the specified type. Note that view-specific db objects are not
* part of these sets - they should be retrieved from the scene objects in this
* set with bv_obj_for_view. */
BV_EXPORT struct bu_ptbl *
bv_view_objs(struct bview *v, int type);
/* Given a view, construct the view plane */
BV_EXPORT int
bv_view_plane(plane_t *p, struct bview *v);
-94
View File
@@ -1,94 +0,0 @@
/* V I E W _ S E T S . H
* BRL-CAD
*
* Copyright (c) 1993-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @addtogroup bv_util
*
* In applications with multiple views, those views typically share common
* scene objects and memory. To manage this sharing, we define view sets.
*/
/** @{ */
/** @file bv/view_sets.h */
#ifndef BV_VIEW_SETS_H
#define BV_VIEW_SETS_H
#include "common.h"
#include "bv/defines.h"
__BEGIN_DECLS
/**
* Initialize an empty view set
*/
BV_EXPORT void
bv_set_init(struct bview_set *s);
/**
* Free view set
*/
BV_EXPORT void
bv_set_free(struct bview_set *s);
/**
* Add view v to set s, handling shared memory assignments.
*/
BV_EXPORT void
bv_set_add_view(struct bview_set *s, struct bview *v);
/**
* Remove view v from set s. If v == NULL, all views
* are removed from the set.
*/
BV_EXPORT void
bv_set_rm_view(struct bview_set *s, struct bview *v);
/**
* Return a bu_ptbl holding pointers to all views in set s
*/
BV_EXPORT struct bu_ptbl *
bv_set_views(struct bview_set *s);
/**
* Return a pointer to the view with name vname, if it is present in s. If not
* found, returns NULL
*/
BV_EXPORT struct bview *
bv_set_find_view(struct bview_set *s, const char *vname);
// Expose free_scene_obj for older codes - do not use in new coding
BV_EXPORT struct bv_scene_obj *
bv_set_fsos(struct bview_set *s);
__END_DECLS
/** @} */
#endif /* BV_VIEW_SETS_H */
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
+2 -10
View File
@@ -310,16 +310,8 @@ BV_EXPORT void bv_vlist_rpp(struct bu_list *vlists, struct bu_list *hd, const po
BV_EXPORT extern void bv_plot_vlblock(FILE *fp,
const struct bv_vlblock *vbp);
BV_EXPORT extern void bv_vlblock_to_objs(struct bu_ptbl *out,
const char *name_root,
struct bv_vlblock *vbp,
struct bview *v,
struct bv_scene_obj *f,
struct bu_list *vlfree);
BV_EXPORT extern struct bv_scene_obj *
bv_vlblock_obj(struct bv_vlblock *vbp, struct bview *v, const char *name);
BV_EXPORT extern int
bv_vlblock_obj(struct bv_scene_obj *s, struct bv_vlblock *vbp);
/**
* Output a vlist as an extended 3-D floating point UNIX-Plot file.
+2
View File
@@ -270,6 +270,8 @@ DM_EXPORT extern void dm_set_bound_flag(struct dm *dmp, int bound);
DM_EXPORT extern int dm_draw_obj(struct dm *dmp, struct bv_scene_obj *s);
DM_EXPORT extern int dm_draw_sobj(void *vdmp, struct bv_scene_obj *s);
DM_EXPORT extern int dm_draw_view(void *vdmp, struct bview *v);
/* Rather low level exposure of display list concepts. Needed for MGED
+2 -2
View File
@@ -69,10 +69,10 @@ DM_EXPORT extern void dm_draw_faceplate(struct bview *v);
* sort on a bv scene object... */
#include "rt/wdb.h"
DM_EXPORT extern void dm_draw_viewobjs(struct rt_wdb *wdbp, struct bview *v, struct dm_view_data *d);
//DM_EXPORT extern void dm_draw_viewobjs(struct rt_wdb *wdbp, struct bview *v, struct dm_view_data *d);
/* Stripped down form of dm_draw_viewobjs that does just what's needed for the new setup */
DM_EXPORT extern void dm_draw_objs(struct bview *v, void (*dm_draw_custom)(struct bview *, void *), void *u_data);
//DM_EXPORT extern void dm_draw_objs(struct bview *v, void (*dm_draw_custom)(struct bview *, void *), void *u_data);
#endif /* DM_NO_RT */
__END_DECLS
+4 -5
View File
@@ -166,8 +166,8 @@ struct ged {
/*************************************************************/
/* The current view */
struct bview *ged_gvp;
/* The full set of views associated with this ged object */
struct bview_set ged_views;
/* All available views */
struct bu_ptbl ged_views;
/* Sometimes applications will supply GED views, and sometimes GED commands
* may create views. In the latter case, ged_close will also need to free
* the views. We define a container to hold those views that libged is
@@ -175,9 +175,8 @@ struct ged {
* than GED. */
struct bu_ptbl ged_free_views;
/* Drawing data associated with this .g file */
struct bv_mesh_lod_context *ged_lod;
/* Set of free scene objects */
struct bv_obj_pool *free_scene_objs;
void *u_data; /**< @brief User data associated with this ged instance */
+1
View File
@@ -85,6 +85,7 @@ class QTCAD_EXPORT QgMeasureFilter : public QObject
void view_updated(int);
public:
struct ged *gedp = NULL;
struct bview *v = NULL;
struct bv_scene_obj *s = NULL;
std::string oname = std::string("tool:measurement");
+2
View File
@@ -58,6 +58,7 @@ struct rt_db_internal {
const struct rt_functab *idb_meth; /**< @brief for ft_ifree(), etc. */
void * idb_ptr;
struct bu_attribute_value_set idb_avs;
void * idb_uptr; /**< @brief pointer to associate user data with the internal */
};
#define idb_type idb_minor_type
#define RT_DB_INTERNAL_INIT(_p) { \
@@ -66,6 +67,7 @@ struct rt_db_internal {
(_p)->idb_minor_type = -1; \
(_p)->idb_meth = (const struct rt_functab *) ((void *)0); \
(_p)->idb_ptr = ((void *)0); \
(_p)->idb_uptr = ((void *)0); \
bu_avs_init_empty(&(_p)->idb_avs); \
}
#define RT_DB_INTERNAL_INIT_ZERO {RT_DB_INTERNAL_MAGIC, -1, -1, NULL, NULL, BU_AVS_INIT_ZERO}
+1 -1
View File
@@ -52,7 +52,7 @@ RT_EXPORT extern void rt_copy_curve(struct rt_curve *crv_out,
RT_EXPORT extern struct rt_sketch_internal *rt_copy_sketch(const struct rt_sketch_internal *sketch_ip);
RT_EXPORT extern struct bv_scene_obj *
db_sketch_to_scene_obj(const char *sname, struct db_i *dbip, struct directory *dp, struct bview *sv, int flags);
db_sketch_to_scene_obj(const char *sname, struct db_i *dbip, struct directory *dp, struct bview *sv);
RT_EXPORT extern struct directory *
db_scene_obj_to_sketch(struct db_i *dbip, const char *sname, struct bv_scene_obj *s);
+57 -5
View File
@@ -31,16 +31,68 @@
#include "bu/ptbl.h"
#include "bn/tol.h"
#include "bv/defines.h"
#include "bv/lod.h" // for libbv CACHE_* defines
#include "rt/defines.h"
__BEGIN_DECLS
// Changes to any of these requires incrementing DB_CACHE_CURRENT_FORMAT.
// Key strings to use in combination with a name hash to look up data.
#define CACHE_REGION_ID "rid"
#define CACHE_REGION_FLAG "rf"
#define CACHE_INHERIT_FLAG "if"
#define CACHE_COLOR "c"
// Internal functional key strings
#define CACHE_GEOM_KEY "gk"
// If BV_CACHE_CURRENT_FORMAT is incremented, this
// should be as well.
#define DB_CACHE_CURRENT_FORMAT 3
/**
* Set up cache processing. Will kick off initialization of db_i
* data if it is not already found. Launches and detaches working
* threads to handle processing in the background, since cache setup
* may be a lengthy process. */
RT_EXPORT extern int db_cache_start(struct db_i *dbip, int verbose);
/**
* Report if the cache backend is actively processing inputs.
* Allows applications to wait for the dust to settle before
* attempting certain operations. */
RT_EXPORT extern int db_cache_processing(struct db_i *dbip);
/**
* Queue up the named object to regenerate its cache info to reflect the
* current state of the object in dbip. If there is no object present in dbip
* with that name, removes any cached data associated with that name from
* the cache.
*
* If no cache is present, or the attempt encounters a problem, return
* BRLCAD_ERROR - else returns BRLCAD_OK;
*
* Note that this queues up the object, but its processing may be delayed
* if there is a lot of ongoing caching work - if db_cache_processing
* is active the cache contents returned for the named object may be
* out of date.
*/
RT_EXPORT extern int db_cache_update(struct db_i *dbip, const char *name);
/* Routines for managing the Drawing cache. As many of the details as
* possible of the cache should be private, but we do at least need ways to set
* up, clear, update and load information. */
/**
* Retrieve the bv_lod_mesh data from the dbip's cache associated with
* the named object. If no such data is present, returns NULL.
*
* Use bv_lod_mesh_put to free.
*/
RT_EXPORT extern struct bv_lod_mesh *db_cache_lod_mesh_get(struct db_i *dbip, const char *name);
/* Routines for managing the mesh LoD cache */
RT_EXPORT extern void db_mesh_lod_init(struct db_i *dbip, int verbose);
RT_EXPORT extern void db_mesh_lod_clear(struct db_i *dbip);
RT_EXPORT extern int db_mesh_lod_update(struct db_i *dbip, const char *name);
RT_EXPORT extern struct bv_mesh_lod *db_mesh_lod_get(struct db_i *dbip, const char *name);
/**
* NOTE: Normally, librt doesn't have a concept of a "display" of the geometry.
+51 -123
View File
@@ -149,77 +149,6 @@ ProcessIOHandler::read()
return lcpy;
}
class DisplayHash {
public:
bool hash(struct ged *, bool, bool);
void dirty(struct ged *, const DisplayHash &);
unsigned long long d = 0;
unsigned long long v = 0;
unsigned long long l = 0;
unsigned long long g = 0;
};
bool
DisplayHash::hash(struct ged *gedp, bool dbi_state_check, bool new_cmd_forms)
{
d = 0; v = 0; l = 0; g = 0;
struct bview *bv = gedp->ged_gvp;
if (!bv)
return false;
struct dm *dmp = (struct dm *)bv->dmp;
if (!dmp)
return false;
d = dm_hash(dmp);
v = bv_hash(bv);
if (new_cmd_forms && gedp->dbi_state) {
if (dbi_state_check) {
DbiState *dbis = (DbiState *)gedp->dbi_state;
unsigned long long updated = dbis->update();
l = (updated) ? l + 1 : 0;
if (bv->gv_s->gv_cleared) {
l = 1;
bv->gv_s->gv_cleared = 0;
}
} else {
l = 0;
}
} else {
l = dl_name_hash(gedp);
}
g = ged_dl_hash(ged_dl(gedp));
return true;
}
void
DisplayHash::dirty(struct ged *gedp, const DisplayHash &o)
{
struct bview *bv = gedp->ged_gvp;
if (!bv)
return;
struct dm *dmp = (struct dm *)bv->dmp;
if (!dmp)
return;
if (d != o.d) {
dm_set_dirty(dmp, 1);
}
if (v != o.v) {
dm_set_dirty(dmp, 1);
}
if (l != o.l) {
dm_set_dirty(dmp, 1);
}
if (g != o.g) {
dm_set_dirty(dmp, 1);
}
}
/* The overall state of the gsh application is encapsulated by a state class
* called GshState. It defines the method for executing libged commands and
* manages the linenoise interactive thread, as well as the necessary state
@@ -246,9 +175,7 @@ class GshState {
size_t listeners_cnt();
// Display management
void view_checkpoint();
void view_update();
DisplayHash prev_hash;
void view_update(struct bview *v = NULL);
struct ged *gedp;
std::string gfile; // Mostly used to test the post_opendb callback
@@ -380,8 +307,6 @@ GshState::GshState()
BU_GET(gedp, struct ged);
ged_init(gedp);
view_checkpoint();
// Assign gsh specific open/close db handlers to the gedp
ged_clbk_set(gedp, "opendb", BU_CLBK_PRE, &gsh_pre_opendb_clbk, (void *)this);
ged_clbk_set(gedp, "opendb", BU_CLBK_POST, &gsh_post_opendb_clbk, (void *)this);
@@ -406,7 +331,7 @@ GshState::GshState()
GshState::~GshState()
{
#ifdef USE_DM
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
struct bu_ptbl *views = &gedp->ged_views;
for (size_t i = 0; i < BU_PTBL_LEN(views); i++) {
struct bview *v = (struct bview *)BU_PTBL_GET(views, i);
if (v->dmp) {
@@ -431,14 +356,16 @@ GshState::eval(int argc, const char **argv)
return BRLCAD_ERROR;
}
// We've got a valid GED command. Before any BRL-CAD logic is executed,
// stash the state of the view info so we can recognize changes.
view_checkpoint();
int gret = ged_exec(gedp, argc, argv);
if (!(gret & BRLCAD_ERROR))
view_update();
if (!(gret & BRLCAD_ERROR)) {
// See if any of the views need updating
struct bu_ptbl *views = &gedp->ged_views;
for (size_t i = 0; i < BU_PTBL_LEN(views); i++) {
struct bview *v = (struct bview *)BU_PTBL_GET(views, i);
view_update(v);
}
}
return gret;
}
@@ -501,14 +428,6 @@ GshState::disconnect(struct ged_subprocess *p, bu_process_io_t t)
p->end_clbk(0, NULL, NULL, p->end_clbk_data);
}
void
GshState::view_checkpoint()
{
#ifdef USE_DM
prev_hash.hash(gedp, false, new_cmd_forms);
#endif
}
void
GshState::subprocess_output()
{
@@ -569,46 +488,55 @@ GshState::listeners_cnt()
}
void
GshState::view_update()
GshState::view_update(struct bview *v)
{
#ifdef USE_DM
DisplayHash hashes;
if (!hashes.hash(gedp, true, new_cmd_forms))
if (!gedp || !gedp->dbi_state)
return;
hashes.dirty(gedp, prev_hash);
BViewState *vs = gedp->dbi_state->GetBViewState(v);
if (!vs)
return;
struct bview *v = gedp->ged_gvp;
// Calculate current hashes
vs->Hash();
// If nothing changed, we're good
if (!vs->Dirty())
return;
// Something changed - go to it.
struct dm *dmp = (struct dm *)v->dmp;
if (dm_get_dirty(dmp)) {
if (new_cmd_forms) {
unsigned char *dm_bg1;
unsigned char *dm_bg2;
dm_get_bg(&dm_bg1, &dm_bg2, dmp);
dm_set_bg(dmp, dm_bg1[0], dm_bg1[1], dm_bg1[2], dm_bg2[0], dm_bg2[1], dm_bg2[2]);
dm_set_dirty(dmp, 0);
dm_draw_objs(v, NULL, NULL);
dm_draw_end(dmp);
} else {
matp_t mat = gedp->ged_gvp->gv_model2view;
dm_loadmatrix(dmp, mat, 0);
unsigned char geometry_default_color[] = { 255, 0, 0 };
dm_draw_begin(dmp);
dm_draw_head_dl(dmp, (struct bu_list *)ged_dl(gedp),
1.0, gedp->ged_gvp->gv_isize, -1, -1, -1, 1,
0, 0, geometry_default_color, 1, 0);
dm_set_dirty(dmp, 1);
// Faceplate drawing
if (gedp->dbip) {
struct rt_wdb *wdbp = wdb_dbopen(gedp->dbip, RT_WDB_TYPE_DB_DEFAULT);
v->gv_base2local = gedp->dbip->dbi_base2local;
v->gv_local2base = gedp->dbip->dbi_local2base;
dm_draw_viewobjs(wdbp, v, NULL);
} else {
dm_draw_viewobjs(NULL, v, NULL);
}
dm_draw_end(dmp);
if (new_cmd_forms) {
unsigned char *dm_bg1;
unsigned char *dm_bg2;
dm_get_bg(&dm_bg1, &dm_bg2, dmp);
dm_set_bg(dmp, dm_bg1[0], dm_bg1[1], dm_bg1[2], dm_bg2[0], dm_bg2[1], dm_bg2[2]);
dm_draw_begin(dmp);
vs->Render();
dm_set_dirty(dmp, 0);
dm_draw_end(dmp);
} else {
matp_t mat = gedp->ged_gvp->gv_model2view;
dm_loadmatrix(dmp, mat, 0);
unsigned char geometry_default_color[] = { 255, 0, 0 };
dm_draw_begin(dmp);
dm_draw_head_dl(dmp, (struct bu_list *)ged_dl(gedp),
1.0, gedp->ged_gvp->gv_isize, -1, -1, -1, 1,
0, 0, geometry_default_color, 1, 0);
// Faceplate drawing
if (gedp->dbip) {
//struct rt_wdb *wdbp = wdb_dbopen(gedp->dbip, RT_WDB_TYPE_DB_DEFAULT);
v->gv_base2local = gedp->dbip->dbi_base2local;
v->gv_local2base = gedp->dbip->dbi_local2base;
//dm_draw_viewobjs(wdbp, v, NULL);
} else {
//dm_draw_viewobjs(NULL, v, NULL);
}
dm_draw_end(dmp);
}
#endif
}
+2
View File
@@ -22,6 +22,7 @@ set(
polygon_op.cpp
polygon_triangulate.cpp
polygon_point_in.c
pnts.cpp
sat.cpp
spsr.cpp
tri_pt.cpp
@@ -30,6 +31,7 @@ set(
trimesh.cpp
trimesh_diff.cpp
trimesh_isect.cpp
trimesh_bb.cpp
trimesh_plot3.cpp
trimesh_sync.cpp
trimesh_split.cpp
+214
View File
@@ -0,0 +1,214 @@
/* P N T S . C P P
* BRL-CAD
*
* Copyright (c) 2016-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file pnts.cpp
*
* Routines for working with pnts
*/
#include "common.h"
#include <stdlib.h>
#include "Mathematics/ContOrientedBox3.h"
#include "vmath.h"
#include "bu/log.h"
#include "bu/malloc.h"
#include "bn/numgen.h"
#include "bn/rand.h"
#include "bg/pnts.h"
int
bg_pnts_aabb(point_t *min, point_t *max, const point_t *p, size_t num_pnts)
{
/* If we can't produce any output, there's no point in continuing */
if (!min || !max)
return BRLCAD_ERROR;
/* If something goes wrong with any bbox logic, we want to know it as soon
* as possible. Make sure as soon as we can that the bbox output is set to
* invalid defaults, so we don't end up with something that accidentally
* looks reasonable if things fail. */
VSETALL((*min), INFINITY);
VSETALL((*max), -INFINITY);
/* If we don't have inputs, we can't do anything */
if (!p || num_pnts == 0)
return BRLCAD_ERROR;
/* Check max and min of points */
for(size_t i = 0; i < num_pnts; i++)
VMINMAX((*min), (*max), p[i]);
/* Make sure the RPP created is not of zero volume */
if (NEAR_EQUAL((*min)[X], (*max)[X], SMALL_FASTF)) {
(*min)[X] -= SMALL_FASTF;
(*max)[X] += SMALL_FASTF;
}
if (NEAR_EQUAL((*min)[Y], (*max)[Y], SMALL_FASTF)) {
(*min)[Y] -= SMALL_FASTF;
(*max)[Y] += SMALL_FASTF;
}
if (NEAR_EQUAL((*min)[Z], (*max)[Z], SMALL_FASTF)) {
(*min)[Z] -= SMALL_FASTF;
(*max)[Z] += SMALL_FASTF;
}
/* Success */
return 0;
}
int
bg_pnts_obb(point_t *c, vect_t *v1, vect_t *v2, vect_t *v3,
const point_t *p, size_t num_pnts)
{
/* If we can't produce any output, there's no point in continuing */
if (!c || !v1 || !v2 || !v3)
return BRLCAD_ERROR;
/* If something goes wrong with any bbox logic, we want to know it as soon
* as possible. Make sure as soon as we can that the bbox output is set to
* invalid defaults, so we don't end up with something that accidentally
* looks reasonable if things fail. */
VSETALL((*c), 0);
VSET((*v1), INFINITY, 0, 0);
VSET((*v2), 0, INFINITY, 0);
VSET((*v3), 0, 0, INFINITY);
/* If we don't have any points we can't do anything */
if (!p || num_pnts == 0)
return BRLCAD_ERROR;
// Calculate the gte::OrientedBox3
gte::OrientedBox3<fastf_t> gte_bb;
if (!gte::GetContainer(num_pnts, (gte::Vector3<fastf_t> *)p, gte_bb))
return BRLCAD_ERROR;
// Success - convert GTE values to vmath types
VSET(*c, gte_bb.center[0], gte_bb.center[1], gte_bb.center[2]);
VSET(*v1, gte_bb.axis[0][0], gte_bb.axis[0][1], gte_bb.axis[0][2]);
if (!NEAR_ZERO(gte_bb.extent[0], VUNITIZE_TOL))
VSCALE(*v1, *v1, gte_bb.extent[0]);
VSET(*v2, gte_bb.axis[1][0], gte_bb.axis[1][1], gte_bb.axis[1][2]);
if (!NEAR_ZERO(gte_bb.extent[1], VUNITIZE_TOL))
VSCALE(*v2, *v2, gte_bb.extent[1]);
VSET(*v3, gte_bb.axis[2][0], gte_bb.axis[2][1], gte_bb.axis[2][2]);
if (!NEAR_ZERO(gte_bb.extent[2], VUNITIZE_TOL))
VSCALE(*v3, *v3, gte_bb.extent[2]);
#if 0
// while we have the info, validate that bg_obb_pnts is doing the right
// reassembly of the GTE class for the explicit points calculation
point_t pt[8];
std::array<gte::Vector3<fastf_t>, 8> calculated_bb;
gte_bb.GetVertices(calculated_bb);
// V0: 0,0,0
VSET(pt[0], calculated_bb[0][0], calculated_bb[0][1], calculated_bb[0][2]);
// V1: 0,1,0
VSET(pt[1], calculated_bb[1][0], calculated_bb[1][1], calculated_bb[1][2]);
// V2: 0,1,1
VSET(pt[2], calculated_bb[3][0], calculated_bb[3][1], calculated_bb[3][2]);
// V3: 0,0,1
VSET(pt[3], calculated_bb[2][0], calculated_bb[2][1], calculated_bb[2][2]);
// V4: 1,0,0
VSET(pt[4], calculated_bb[4][0], calculated_bb[4][1], calculated_bb[4][2]);
// V5: 1,1,0
VSET(pt[5], calculated_bb[5][0], calculated_bb[5][1], calculated_bb[5][2]);
// V6: 1,1,1
VSET(pt[6], calculated_bb[7][0], calculated_bb[7][1], calculated_bb[7][2]);
// V7: 1,0,1
VSET(pt[7], calculated_bb[6][0], calculated_bb[6][1], calculated_bb[6][2]);
point_t *pverts = (point_t *)bu_calloc(8, sizeof(point_t), "p");
bg_obb_pnts(pverts, (const point_t *)c, (const vect_t *)v1, (const vect_t *)v2, (const vect_t *)v3);
// Make sure bg_obb_pnts matches what GTE gives us
for (size_t i = 0; i < 8; i++) {
if (!VNEAR_EQUAL(pt[i], pverts[i], VUNITIZE_TOL)) {
bu_log("%g %g %g -> %g %g %g\n", V3ARGS(pt[i]), V3ARGS(pverts[i]));
bu_exit(-1, "WRONG!\n");
}
}
#endif
return BRLCAD_OK;
}
int
bg_obb_pnts(point_t *verts, const point_t *c, const vect_t *v1, const vect_t *v2, const vect_t *v3)
{
if (!c || !v1 || !v2 || !v3 || !verts)
return BRLCAD_ERROR;
vect_t evects[3];
VMOVE(evects[0], *v1);
VMOVE(evects[1], *v2);
VMOVE(evects[2], *v3);
fastf_t emags[3];
for (size_t i = 0; i < 3; i++)
emags[i] = MAGNITUDE(evects[i]);
for (size_t i = 0; i < 3; i++)
VUNITIZE(evects[i]);
gte::OrientedBox3<fastf_t> gte_bb;
gte_bb.center[0] = (*c)[X];
gte_bb.center[1] = (*c)[Y];
gte_bb.center[2] = (*c)[Z];
for (size_t i = 0; i < 3; i++) {
gte_bb.extent[i] = emags[i];
for (size_t j = 0; j < 3; j++)
gte_bb.axis[i][j] = evects[i][j];
}
// success: convert gte calculated -> verts
std::array<gte::Vector3<fastf_t>, 8> calculated_bb;
gte_bb.GetVertices(calculated_bb);
// V0: 0,0,0
VSET(verts[0], calculated_bb[0][0], calculated_bb[0][1], calculated_bb[0][2]);
// V1: 0,1,0
VSET(verts[1], calculated_bb[1][0], calculated_bb[1][1], calculated_bb[1][2]);
// V2: 0,1,1
VSET(verts[2], calculated_bb[3][0], calculated_bb[3][1], calculated_bb[3][2]);
// V3: 0,0,1
VSET(verts[3], calculated_bb[2][0], calculated_bb[2][1], calculated_bb[2][2]);
// V4: 1,0,0
VSET(verts[4], calculated_bb[4][0], calculated_bb[4][1], calculated_bb[4][2]);
// V5: 1,1,0
VSET(verts[5], calculated_bb[5][0], calculated_bb[5][1], calculated_bb[5][2]);
// V6: 1,1,1
VSET(verts[6], calculated_bb[7][0], calculated_bb[7][1], calculated_bb[7][2]);
// V7: 1,0,1
VSET(verts[7], calculated_bb[6][0], calculated_bb[6][1], calculated_bb[6][2]);
return BRLCAD_OK;
}
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8 cino=N-s
-71
View File
@@ -1,71 +0,0 @@
/* P O I N T G E N . C
* BRL-CAD
*
* Copyright (c) 2016-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file pointgen.c
*
* Interface for generating patterns of points. Currently only
* spherical sampling.
*
*/
#include "common.h"
#include <stdlib.h>
#include "bu/malloc.h"
#include "bn/numgen.h"
#include "bg/pointgen.h"
size_t
bg_sph_sample(point_t *pnts, size_t cnt, const point_t center, const fastf_t radius, bn_numgen n)
{
size_t i = 0;
size_t ret = 0;
ret = bn_sph_sample(pnts, cnt, n);
if (ret != cnt) {
bu_log("Unable to generate %d points (%d generated), aborting\n", cnt, ret);
return 0;
}
for (i = 0; i < cnt; i++) {
/* If we've got a non-unit sph radius, scale the point */
if (!NEAR_EQUAL(radius, 1.0, SMALL_FASTF)) {
VSCALE(sample, sample, radius);
}
/* If we've got a non-zero sph center, translate the point */
if (!VNEAR_ZERO(sample, SMALL_FASTF)) {
VADD2(sample, sample, center);
}
}
return cnt;
}
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
+4
View File
@@ -35,6 +35,10 @@ brlcad_addexec(bg_obr obr.c "libbg;libbn;libbu" TEST)
#BRLCAD_ADD_TEST(NAME bg_obr_simple COMMAND bg_obr) # Default points
# ************ bouding box tests *************
brlcad_addexec(bg_bb bb.c "libbg;libbn;libbu" TEST)
#
# ************ plane.c tests *************
+192
View File
@@ -0,0 +1,192 @@
/* B B . C
* BRL-CAD
*
* Copyright (c) 2011-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
#include "common.h"
#include <stdio.h>
#include "bu.h"
#include "bg.h"
int
obb_diff(
point_t ac, vect_t av1, vect_t av2, vect_t av3,
point_t bc, vect_t bv1, vect_t bv2, vect_t bv3
)
{
point_t diff;
VSUB2(diff, ac, bc);
vect_t bv[3];
VMOVE(bv[0], bv1);
VMOVE(bv[1], bv2);
VMOVE(bv[2], bv3);
VSCALE(bv[0], bv[0], -1);
VSCALE(bv[1], bv[1], -1);
VSCALE(bv[2], bv[2], -1);
if (!VNEAR_EQUAL(ac, bc, VUNITIZE_TOL)) {
bu_log("Note: obb (%g %g %g) and obb verts obb (%g %g %g) center point differs: %0.15f %0.15f %0.15f\n", V3ARGS(ac), V3ARGS(bc), V3ARGS(diff));
return 1;
}
VSUB2(diff, av1, bv1);
if (!VNEAR_EQUAL(av1, bv1, VUNITIZE_TOL) && !VNEAR_EQUAL(av1, bv[0], VUNITIZE_TOL)) {
bu_log("Note: obb (%g %g %g) and obb verts obb (%g %g %g) v1 differs: %0.15f %0.15f %0.15f\n", V3ARGS(av1), V3ARGS(bv1), V3ARGS(diff));
return 1;
}
VSUB2(diff, av2, bv2);
if (!VNEAR_EQUAL(av2, bv2, VUNITIZE_TOL) && !VNEAR_EQUAL(av2, bv[1], VUNITIZE_TOL)) {
bu_log("Note: obb (%g %g %g) and obb verts obb (%g %g %g) v2 differs: %0.15f %0.15f %0.15f\n", V3ARGS(av2), V3ARGS(bv2), V3ARGS(diff));
return 1;
}
VSUB2(diff, av3, bv3);
if (!VNEAR_EQUAL(av3, bv3, VUNITIZE_TOL) && !VNEAR_EQUAL(av3, bv[2], VUNITIZE_TOL)) {
bu_log("Note: obb (%g %g %g) and obb verts obb (%g %g %g) v3 differs: %0.15f %0.15f %0.15f\n", V3ARGS(av3), V3ARGS(bv3), V3ARGS(diff));
return 1;
}
return 0;
}
int
arb_diff(point_t *p1, point_t *p2)
{
for (int i = 0; i < 8; i++) {
int have_match = 0;
for (int j = 0; j < 8; j++) {
if (VNEAR_EQUAL(p1[i], p2[j], VUNITIZE_TOL))
have_match = 1;
}
if (!have_match) {
bu_log("Note: p1[%d] (%g %g %g) has no matching point in p2, arbs differ\n", i, V3ARGS(p1[i]));
return 1;
}
}
return 0;
}
int
main(int UNUSED(argc), const char *argv[])
{
bu_setprogname(argv[0]);
int faces[12] = {
1, 3, 2,
1, 2, 4,
1, 4, 3,
3, 4, 2};
point_t verts[5];
VSET(verts[0], -1, -1, -1);
VSET(verts[1], 5000, 4000, 3000);
VSET(verts[2], 5000, 6000, 3000);
VSET(verts[3], 5000, 6000, 5000);
VSET(verts[4], 3000, 6000, 3000);
for (int i = 0; i < 10; i++) {
verts[1][X] += i;
verts[1][Y] -= i;
verts[2][Y] += i;
verts[3][Z] -= i;
bu_log("\nTest %d\n", i+1);
{
point_t paabmin, paabmax;
if (bg_pnts_aabb(&paabmin, &paabmax, (const point_t *)verts, 5) != BRLCAD_OK)
bu_exit(-1, "Error calculating pnts aabb\n");
bu_log("pnts_aabb: %g %g %g -> %g %g %g\n", V3ARGS(paabmin), V3ARGS(paabmax));
}
{
point_t pobbc;
vect_t pv1, pv2, pv3;
if (bg_pnts_obb(&pobbc, &pv1, &pv2, &pv3, (const point_t *)verts, 5) != BRLCAD_OK)
bu_exit(-1, "Error calculating pnts obb\n");
bu_log("pnts_obb: %g %g %g: %g %g %g, %g %g %g, %g %g %g\n", V3ARGS(pobbc), V3ARGS(pv1), V3ARGS(pv2), V3ARGS(pv3));
point_t *pbverts = (point_t *)bu_calloc(8, sizeof(point_t), "p out");
if (bg_obb_pnts(pbverts, (const point_t *)&pobbc, (const vect_t *)&pv1, (const vect_t *)&pv2, (const vect_t *)&pv3) != BRLCAD_OK)
bu_exit(-1, "Error calculating obb pnts\n");
bu_log("pnts_obb_verts: %g %g %g: %g %g %g, %g %g %g, %g %g %g\n", V3ARGS(pbverts[0]), V3ARGS(pbverts[1]), V3ARGS(pbverts[2]), V3ARGS(pbverts[3]));
bu_log(" %g %g %g: %g %g %g, %g %g %g, %g %g %g\n", V3ARGS(pbverts[4]), V3ARGS(pbverts[5]), V3ARGS(pbverts[6]), V3ARGS(pbverts[7]));
}
{
point_t taabmin, taabmax;
if (bg_trimesh_aabb(&taabmin, &taabmax, faces, 4, (const point_t *)verts, 5) != BRLCAD_OK)
bu_exit(-1, "Error calculating trimesh aabb\n");
bu_log("trimesh_aabb: %g %g %g -> %g %g %g\n", V3ARGS(taabmin), V3ARGS(taabmax));
}
{
point_t tobbc;
vect_t tv1, tv2, tv3;
if (bg_trimesh_obb(&tobbc, &tv1, &tv2, &tv3, faces, 4, (const point_t *)verts, 5) != BRLCAD_OK)
bu_exit(-1, "Error calculating trimesh obb\n");
bu_log("trimesh_obb: %g %g %g: %g %g %g, %g %g %g, %g %g %g\n", V3ARGS(tobbc), V3ARGS(tv1), V3ARGS(tv2), V3ARGS(tv3));
point_t *tbverts = (point_t *)bu_calloc(8, sizeof(point_t), "p out");
if (bg_obb_pnts(tbverts, (const point_t *)&tobbc, (const vect_t *)&tv1, (const vect_t *)&tv2, (const vect_t *)&tv3) != BRLCAD_OK)
bu_exit(-1, "Error calculating obb pnts\n");
bu_log("trimesh_obb_verts: %g %g %g: %g %g %g, %g %g %g, %g %g %g\n", V3ARGS(tbverts[0]), V3ARGS(tbverts[1]), V3ARGS(tbverts[2]), V3ARGS(tbverts[3]));
bu_log(" %g %g %g: %g %g %g, %g %g %g, %g %g %g\n", V3ARGS(tbverts[4]), V3ARGS(tbverts[5]), V3ARGS(tbverts[6]), V3ARGS(tbverts[7]));
point_t btobbc;
vect_t btv1, btv2, btv3;
if (bg_pnts_obb(&btobbc, &btv1, &btv2, &btv3, (const point_t *)tbverts, 8) != BRLCAD_OK)
bu_exit(-1, "Error calculating trimesh obb verts obb\n");
bu_log("trimesh_obb_pnts_obb: %g %g %g: %g %g %g, %g %g %g, %g %g %g\n", V3ARGS(tobbc), V3ARGS(tv1), V3ARGS(tv2), V3ARGS(tv3));
if (obb_diff(tobbc, tv1, tv2, tv3, btobbc, btv1, btv2, btv3)) {
bu_log("NOTE: obb info differs between obb calculated from the original mesh and that calculated from the bounding box verts.\nNeed to generate verts from the obb calculated from the bounding box verts and verify that all points in the first obb vert set are present in the second (ordering may differ).\n");
point_t *tbpntverts = (point_t *)bu_calloc(8, sizeof(point_t), "p out");
if (bg_obb_pnts(tbpntverts, (const point_t *)&btobbc, (const vect_t *)&btv1, (const vect_t *)&btv2, (const vect_t *)&btv3) != BRLCAD_OK)
bu_exit(-1, "Error calculating obb pnts\n");
bu_log("trimesh_obb_verts: %g %g %g: %g %g %g, %g %g %g, %g %g %g\n", V3ARGS(tbpntverts[0]), V3ARGS(tbpntverts[1]), V3ARGS(tbpntverts[2]), V3ARGS(tbpntverts[3]));
bu_log(" %g %g %g: %g %g %g, %g %g %g, %g %g %g\n", V3ARGS(tbpntverts[4]), V3ARGS(tbpntverts[5]), V3ARGS(tbpntverts[6]), V3ARGS(tbpntverts[7]));
if (arb_diff(tbverts, tbpntverts)) {
bu_log("Arb points differ. The implication of this is the original mesh obb can't be faithfully recreated from the center point and extents, which is a problem!\n");
} else {
bu_log("All original arb points found. Should verify whether either arb is twisted, but at least all points are present.\n");
}
}
}
}
return 0;
}
/** @} */
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
+1 -57
View File
@@ -1,4 +1,4 @@
/* T R I M E S H . C
/* T R I M E S H . C P P
* BRL-CAD
*
* Copyright (c) 2004-2025 United States Government as represented by
@@ -817,62 +817,6 @@ bg_trimesh_area(const int *faces, size_t num_faces, const point_t *p, size_t num
return area;
}
int
bg_trimesh_aabb(point_t *min, point_t *max, const int *faces, size_t num_faces, const point_t *p, size_t num_pnts)
{
/* If we can't produce any output, there's no point in continuing */
if (!min || !max)
return -1;
/* If something goes wrong with any bbox logic, we want to know it as soon
* as possible. Make sure as soon as we can that the bbox output is set to
* invalid defaults, so we don't end up with something that accidentally
* looks reasonable if things fail. */
VSETALL((*min), INFINITY);
VSETALL((*max), -INFINITY);
/* If inputs are insufficient, we can't produce a bbox */
if (!faces || num_faces == 0 || !p || num_pnts == 0)
return -1;
/* First Pass: coherently iterate through all faces of the BoT and
* mark vertices in a bit-vector that are referenced by a face. */
struct bu_bitv *visit_vert = bu_bitv_new(num_pnts);
for (size_t tri_index = 0; tri_index < num_faces; tri_index++) {
BU_BITSET(visit_vert, faces[tri_index*3 + X]);
BU_BITSET(visit_vert, faces[tri_index*3 + Y]);
BU_BITSET(visit_vert, faces[tri_index*3 + Z]);
}
/* Second Pass: check max and min of vertices marked */
for(size_t vert_index = 0; vert_index < num_pnts; vert_index++){
if(BU_BITTEST(visit_vert,vert_index)){
VMINMAX((*min), (*max), p[vert_index]);
}
}
/* Done with bitv */
bu_bitv_free(visit_vert);
/* Make sure the RPP created is not of zero volume */
if (NEAR_EQUAL((*min)[X], (*max)[X], SMALL_FASTF)) {
(*min)[X] -= SMALL_FASTF;
(*max)[X] += SMALL_FASTF;
}
if (NEAR_EQUAL((*min)[Y], (*max)[Y], SMALL_FASTF)) {
(*min)[Y] -= SMALL_FASTF;
(*max)[Y] += SMALL_FASTF;
}
if (NEAR_EQUAL((*min)[Z], (*max)[Z], SMALL_FASTF)) {
(*min)[Z] -= SMALL_FASTF;
(*max)[Z] += SMALL_FASTF;
}
/* Success */
return 0;
}
int
bg_trimesh_2d_gc(int **ofaces, point2d_t **opnts, int *n_opnts,
const int *faces, int num_faces, const point2d_t *in_pts)
+158
View File
@@ -0,0 +1,158 @@
/* T R I M E S H _ O B B . C P P
* BRL-CAD
*
* Copyright (c) 2004-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
#include "common.h"
#include <vector>
#include <string.h>
#include "Mathematics/ContOrientedBox3.h"
#include "vmath.h"
#include "bu/bitv.h"
#include "bg/pnts.h"
#include "bg/trimesh.h"
int
bg_trimesh_aabb(point_t *min, point_t *max, const int *faces, size_t num_faces, const point_t *p, size_t num_pnts)
{
/* If we can't produce any output, there's no point in continuing */
if (!min || !max)
return -1;
/* If something goes wrong with any bbox logic, we want to know it as soon
* as possible. Make sure as soon as we can that the bbox output is set to
* invalid defaults, so we don't end up with something that accidentally
* looks reasonable if things fail. */
VSETALL((*min), INFINITY);
VSETALL((*max), -INFINITY);
/* If we don't have faces, see if we can calculate with just points */
if (!faces || num_faces == 0 || !p || num_pnts == 0)
return bg_pnts_aabb(min, max, p, num_pnts);
/* First Pass: coherently iterate through all faces of the BoT and
* mark vertices in a bit-vector that are referenced by a face. */
struct bu_bitv *visit_vert = bu_bitv_new(num_pnts);
for (size_t tri_index = 0; tri_index < num_faces; tri_index++) {
BU_BITSET(visit_vert, faces[tri_index*3 + X]);
BU_BITSET(visit_vert, faces[tri_index*3 + Y]);
BU_BITSET(visit_vert, faces[tri_index*3 + Z]);
}
/* Second Pass: check max and min of vertices marked */
for(size_t vert_index = 0; vert_index < num_pnts; vert_index++){
if(BU_BITTEST(visit_vert,vert_index)){
VMINMAX((*min), (*max), p[vert_index]);
}
}
/* Done with bitv */
bu_bitv_free(visit_vert);
/* Make sure the RPP created is not of zero volume */
if (NEAR_EQUAL((*min)[X], (*max)[X], SMALL_FASTF)) {
(*min)[X] -= SMALL_FASTF;
(*max)[X] += SMALL_FASTF;
}
if (NEAR_EQUAL((*min)[Y], (*max)[Y], SMALL_FASTF)) {
(*min)[Y] -= SMALL_FASTF;
(*max)[Y] += SMALL_FASTF;
}
if (NEAR_EQUAL((*min)[Z], (*max)[Z], SMALL_FASTF)) {
(*min)[Z] -= SMALL_FASTF;
(*max)[Z] += SMALL_FASTF;
}
/* Success */
return 0;
}
int
bg_trimesh_obb(point_t *c, vect_t *v1, vect_t *v2, vect_t *v3,
const int *faces, size_t num_faces, const point_t *p, size_t num_pnts)
{
/* If we can't produce any output, there's no point in continuing */
if (!c || !v1 || !v2 || !v3)
return BRLCAD_ERROR;
/* If something goes wrong with any bbox logic, we want to know it as soon
* as possible. Make sure as soon as we can that the bbox output is set to
* invalid defaults, so we don't end up with something that accidentally
* looks reasonable if things fail. */
VSETALL((*c), 0);
VSET((*v1), INFINITY, 0, 0);
VSET((*v2), 0, INFINITY, 0);
VSET((*v3), 0, 0, INFINITY);
/* If we don't have any faces, but we DO have points, we can still
* produce a bbox */
if (!faces || num_faces == 0)
return bg_pnts_obb(c, v1, v2, v3, p, num_pnts);
/* First Pass: coherently iterate through all faces of the BoT and
* mark vertices in a bit-vector that are referenced by a face. */
struct bu_bitv *visit_vert = bu_bitv_new(num_pnts);
for (size_t tri_index = 0; tri_index < num_faces; tri_index++) {
BU_BITSET(visit_vert, faces[tri_index*3 + X]);
BU_BITSET(visit_vert, faces[tri_index*3 + Y]);
BU_BITSET(visit_vert, faces[tri_index*3 + Z]);
}
/* Second Pass: Build up a vector of active pnts per the faces */
std::vector<fastf_t> apnts;
size_t apnt_cnt = 0;
for(size_t vert_index = 0; vert_index < num_pnts; vert_index++){
if(BU_BITTEST(visit_vert,vert_index)){
apnts.push_back(p[vert_index][0]);
apnts.push_back(p[vert_index][1]);
apnts.push_back(p[vert_index][2]);
apnt_cnt++;
}
}
// Calculate the gte::OrientedBox3
gte::OrientedBox3<fastf_t> gte_bb;
if (!gte::GetContainer(apnt_cnt, (gte::Vector3<fastf_t> *)apnts.data(), gte_bb))
return BRLCAD_ERROR;
// Success - convert GTE values to vmath types
VSET(*c, gte_bb.center[0], gte_bb.center[1], gte_bb.center[2]);
VSET(*v1, gte_bb.axis[0][0], gte_bb.axis[0][1], gte_bb.axis[0][2]);
VSCALE(*v1, *v1, gte_bb.extent[0]);
VSET(*v2, gte_bb.axis[1][0], gte_bb.axis[1][1], gte_bb.axis[1][2]);
VSCALE(*v2, *v2, gte_bb.extent[1]);
VSET(*v3, gte_bb.axis[2][0], gte_bb.axis[2][1], gte_bb.axis[2][2]);
VSCALE(*v3, *v3, gte_bb.extent[2]);
return BRLCAD_OK;
}
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8
+9
View File
@@ -208,6 +208,15 @@ bg_trimesh_diff(
for (size_t i = 0; i < pv2.size(); i++)
ind_map_2[i] = pv2[i].orig_ind;
// TODO - to make this properly insensitive to face ordering, need to make
// arrys of faces the same way we did with the points - do the reordering to
// always lead with the lowest numerical index in the face (using the maps
// to target the sorted vert arrays) and then sort the faces - that should
// put all matching faces in the same array positions regardless of where
// they started. Didn't do it yet since for most BRL-CAD applications it
// isn't likely an otherwise identical mesh will have its faces scrambled,
// but from a completeness standpoint should do it - from a solid raytracing
// perspective it doesn't matter which BoT face is where in the faces array.
for (size_t i = 0; i < num_f1; i++) {
size_t tri_1[3];
tri_1[0] = ind_map_1[f1[3*i+0]];
+3
View File
@@ -36,6 +36,7 @@
#include "bu/defines.h"
#include "bu/app.h"
#include "bu/cache.h"
#include "bu/parallel.h"
#include "bu/dylib.h"
@@ -45,6 +46,7 @@ int BU_SEM_GENERAL;
int BU_SEM_SYSCALL;
int BU_SEM_BN_NOISE;
int BU_SEM_MAPPEDFILE;
int BU_SEM_CACHE;
/* These ARE NOT exported outside LIBBU */
extern "C" int BU_SEM_DATETIME;
@@ -62,6 +64,7 @@ libbu_init(void)
BU_SEMAPHORE_DEFINE(BU_SEM_SYSCALL);
BU_SEMAPHORE_DEFINE(BU_SEM_BN_NOISE);
BU_SEMAPHORE_DEFINE(BU_SEM_MAPPEDFILE);
BU_SEMAPHORE_DEFINE(BU_SEM_CACHE);
BU_SEMAPHORE_DEFINE(BU_SEM_THREAD);
BU_SEMAPHORE_DEFINE(BU_SEM_MALLOC);
BU_SEMAPHORE_DEFINE(BU_SEM_DATETIME);
+58 -4
View File
@@ -20,6 +20,7 @@
#include "common.h"
#include <chrono>
#include <filesystem>
#include <system_error>
@@ -108,13 +109,12 @@ bu_file_exists(const char *path, int *fd)
return 0;
}
int
long long
bu_file_size(const char *path)
{
int fbytes = 0;
if (!bu_file_exists(path, NULL)) {
long long fbytes = 0;
if (!bu_file_exists(path, NULL))
return -1;
}
#ifdef HAVE_SYS_STAT_H
{
@@ -157,6 +157,60 @@ bu_file_size(const char *path)
return fbytes;
}
// TODO - once C++20 is implemented and well supported, use that
// instead: https://stackoverflow.com/q/61030383
int64_t
bu_file_timestamp(const char *path)
{
if (!path)
return -1;
#ifdef HAVE_WINDOWS_H
HANDLE h = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
FILETIME ft_lastwrite;
int fret = GetFileTime(h, NULL, NULL, &ft_lastwrite);
CloseHandle(h);
if (!fret)
return -1;
// FILETIME is number of 100-nanosecond intervals since Jan 1, 1601. For compatibility
// with bu_gettime(), we need the number of microseconds since the UNIX epoch.
// First convert FILETIME to a 64 bit integer
ULARGE_INTEGER li;
li.LowPart = ft_lastwrite.dwLowDateTime;
li.HighPart = ft_lastwrite.dwHighDateTime;
uint64_t fileTime100ns = li.QuadPart;
// Number of 100-nanosecond intervals between 1601-01-01 and 1970-01-01
const uint64_t EPOCH_DIFFERENCE_100NS = 116444736000000000ULL;
// Correct for epoch difference
uint64_t unixTime100ns = fileTime100ns - EPOCH_DIFFERENCE_100NS;
// Convert to microseconds
int64_t timestamp = static_cast<int64_t>(unixTime100ns / 10);
return timestamp;
#elif HAVE_SYS_STAT_H
struct stat sb;
if (stat(path, &sb) != 0)
return 0;
long long sec_micro = sb.st_mtim.tv_sec * 1000000;
long long nano_micro = sb.st_mtim.tv_nsec / 1000;
int64_t timestamp = (int64_t)sec_micro + (int64_t)nano_micro;
return timestamp;
#else
// Currently unsupported
return 0;
#endif
}
#ifdef HAVE_GETFULLPATHNAME
static int
+8
View File
@@ -683,6 +683,14 @@ brlcad_add_test(NAME bu_opt_3_vect_02 COMMAND bu_test opt 3 V 2)
brlcad_add_test(NAME bu_opt_3_vect_03 COMMAND bu_test opt 3 V 3)
brlcad_add_test(NAME bu_opt_3_vect_04 COMMAND bu_test opt 3 V 4)
#
# *********** hash.c tests ************
#
brlcad_addexec(bu_cache cache.cpp libbu TEST)
if(TARGET bu_test)
add_dependencies(bu_test bu_cache)
endif(TARGET bu_test)
#
# *********** datetime.c tests ************
#
+43 -1
View File
@@ -20,6 +20,7 @@
#include "common.h"
#include <inttypes.h>
#include <string.h>
#ifdef HAVE_SYS_STAT_H
# include <sys/stat.h>
@@ -205,7 +206,48 @@ main(int ac, char *av[])
bu_free(rpath, "free realpath");
}
/* Clean up, delete all our files and dir */
/* Check file timestamp behavior. */
// File ops are not instantaneous, so there will be some delta between a
// file timestamp and a bu_gettime call, but it should be very small if the
// time units are working correctly. "Very small" depends on system load,
// OS type, and many other factors - this value is intended to represent a
// reasonable maximum.
int64_t max_expected_timestamp_delta = 10000;
// Create a new file to timestamp - we want the file's timestamp as close
// to "now" as we can get it for a minimal time delta.
bu_vls_sprintf(&fname, "%s/bu_file_timestamp", tdir);
fp = fopen(bu_vls_cstr(&fname), "wb");
if (!fp) {
bu_exit(1, "%s [FAIL] Unable to create test file %s\n", av[0], bu_vls_cstr(&fname));
} else {
fclose(fp);
}
// Call bu_gettime IMMEDIATELY after file creation is complete. On Windows,
// we can't get a timestamp until after fclose, so this is the earliest we
// can make the call successfully.
int64_t sys_time = bu_gettime();
// Read our new file's timestamp.
int64_t timestamp = bu_file_timestamp(bu_vls_cstr(&fname));
// Print and check deltas
int64_t tdelta = sys_time - timestamp;
bu_log("sys_time: %" PRId64 "\n", sys_time);
bu_log("timestamp: %" PRId64 " (Δ from sys_time:%" PRId64 ") \n", timestamp, tdelta);
if (tdelta < 0 || tdelta > max_expected_timestamp_delta )
bu_exit(1, "%s [FAIL] Unexpected delta between bu_gettime() value and timestamp value on %s\n", av[0], bu_vls_cstr(&fname));
// Clean up timestamp file
(void)bu_file_delete(bu_vls_cstr(&fname));
/* Clean up all other files, delete dir */
cleanup(tdir, file_cnt);
bu_vls_free(&fname);
+1 -1
View File
@@ -8,6 +8,7 @@ set(
hash.c
knobs.cpp
lod.cpp
objs.cpp
polygon.c
polygon_op.cpp
polygon_fill.cpp
@@ -22,7 +23,6 @@ set(
tig/vector.c
util.cpp
vlist.c
view_sets.cpp
)
set(BV_LOCAL_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR} ${LMDB_INCLUDE_DIR})
+9 -10
View File
@@ -28,22 +28,21 @@
#include "common.h"
#include "bu/list.h"
#include "bu/malloc.h"
#include "bu/ptbl.h"
#include "bv/defines.h"
#include <unordered_map>
#include "bv/objs.h"
struct bview_set_internal {
struct bu_ptbl views;
struct bu_ptbl shared_db_objs;
struct bu_ptbl shared_view_objs;
struct bv_scene_obj *free_scene_obj;
struct bv_obj_pool_internal {
struct bv_scene_obj head;
struct bu_list vlfree;
};
struct bv_scene_obj_internal {
std::unordered_map<struct bview *, struct bv_scene_obj *> vobjs;
};
BV_EXPORT extern struct bv_scene_obj *
bv_obj_pool_get(struct bv_obj_pool *p);
BV_EXPORT extern void
bv_obj_pool_put(struct bv_obj_pool *p, struct bv_scene_obj *s);
#endif /* LIBBV_BV_PRIVATE_H */
-21
View File
@@ -32,7 +32,6 @@
#include "bv/vlist.h"
#include "bv/defines.h"
#include "bv/util.h"
#include "bv/view_sets.h"
static void
_bv_adc_state_hash(struct bu_data_hash_state *state, struct bv_adc_state *v)
@@ -312,26 +311,6 @@ bv_hash(struct bview *v)
_bv_data_polygon_state_hash(state, &v->gv_tcl.gv_sdata_polygons);
_bv_other_state_hash(state, &v->gv_tcl.gv_prim_labels);
struct bu_ptbl *tbls[4];
tbls[0] = bv_view_objs(v, BV_DB_OBJS);
tbls[1] = bv_view_objs(v, BV_DB_OBJS | BV_LOCAL_OBJS);
tbls[2] = bv_view_objs(v, BV_VIEW_OBJS);
tbls[3] = bv_view_objs(v, BV_VIEW_OBJS | BV_LOCAL_OBJS);
for (int t = 0; t < 4; t++) {
if (!tbls[t])
continue;
for (size_t i = 0; i < BU_PTBL_LEN(tbls[t]); i++) {
struct bv_scene_group *g = (struct bv_scene_group *)BU_PTBL_GET(tbls[t], i);
if (BU_PTBL_IS_INITIALIZED(&g->children)) {
for (size_t j = 0; j < BU_PTBL_LEN(&g->children); j++) {
struct bv_scene_obj *s_c = (struct bv_scene_obj *)BU_PTBL_GET(&g->children, j);
bv_scene_obj_hash(state, s_c);
}
}
bv_scene_obj_hash(state, g);
}
}
unsigned long long hash_val = bu_data_hash_val(state);
bu_data_hash_destroy(state);
+321 -1114
View File
File diff suppressed because it is too large Load Diff
+864
View File
@@ -0,0 +1,864 @@
/* O B J S . C P P
* BRL-CAD
*
* Copyright (c) 2020-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file util.cpp
*
* Utility functions for operating on BRL-CAD views
*
*/
#include "common.h"
#include <set>
#include <string.h>
#include "vmath.h"
#include "bu/log.h"
#include "bu/malloc.h"
#include "bu/path.h"
#include "bu/ptbl.h"
#include "bu/str.h"
#include "bu/time.h"
#include "bu/vls.h"
#include "bn/mat.h"
#include "bg/plane.h"
#include "bg/sat.h"
#include "bv/defines.h"
#include "bv/lod.h"
#include "bv/objs.h"
#include "bv/snap.h"
#include "bv/util.h"
#include "bv/vlist.h"
#include "./bv_private.h"
int
bv_obj_settings_sync(struct bv_obj_settings *dest, struct bv_obj_settings *src)
{
int ret = 0;
if (!dest || !src)
return ret;
if (dest->s_line_width != src->s_line_width) {
dest->s_line_width = src->s_line_width;
ret = 1;
}
if (!NEAR_EQUAL(dest->s_arrow_tip_length, src->s_arrow_tip_length, SMALL_FASTF)) {
dest->s_arrow_tip_length = src->s_arrow_tip_length;
ret = 1;
}
if (!NEAR_EQUAL(dest->s_arrow_tip_width, src->s_arrow_tip_width, SMALL_FASTF)) {
dest->s_arrow_tip_width = src->s_arrow_tip_width;
ret = 1;
}
if (!NEAR_EQUAL(dest->transparency, src->transparency, SMALL_FASTF)) {
dest->transparency = src->transparency;
ret = 1;
}
if (dest->s_dmode != src->s_dmode) {
dest->s_dmode = src->s_dmode;
ret = 1;
}
if (dest->color_override != src->color_override) {
dest->color_override = src->color_override;
ret = 1;
}
if (!VNEAR_EQUAL(dest->color, src->color, SMALL_FASTF)) {
VMOVE(dest->color, src->color);
ret = 1;
}
if (dest->draw_solid_lines_only != src->draw_solid_lines_only) {
dest->draw_solid_lines_only = src->draw_solid_lines_only;
ret = 1;
}
if (dest->draw_non_subtract_only != src->draw_non_subtract_only) {
dest->draw_non_subtract_only = src->draw_non_subtract_only;
ret = 1;
}
return ret;
}
struct bv_obj_pool *
bv_obj_pool_create()
{
struct bv_obj_pool *p;
BU_GET(p, struct bv_obj_pool);
BU_GET(p->i, struct bv_obj_pool_internal);
BU_LIST_INIT(&p->i->head.l);
BU_LIST_INIT(&p->i->vlfree);
return p;
}
void
bv_obj_pool_destroy(struct bv_obj_pool *p)
{
if (!p)
return;
/* Free scene objects */
struct bv_scene_obj *sp = BU_LIST_NEXT(bv_scene_obj, &p->i->head.l);
while (BU_LIST_NOT_HEAD(sp, &p->i->head.l)) {
struct bv_scene_obj *nsp = BU_LIST_PNEXT(bv_scene_obj, sp);
BU_LIST_DEQUEUE(&((sp)->l));
sp->obj_pool = NULL;
bv_obj_put(sp);
sp = nsp;
}
/* Free vlists */
struct bu_list *vp;
while (BU_LIST_WHILE(vp, bu_list, &p->i->vlfree)) {
BU_LIST_DEQUEUE(vp);
struct bv_vlist *pv = (struct bv_vlist *)vp;
BU_FREE(pv, struct bv_vlist);
}
/* Final cleanup */
BU_PUT(p->i, struct bv_obj_pool_internal);
BU_PUT(p, struct bv_obj_pool);
}
struct bv_scene_obj *
bv_obj_pool_get(struct bv_obj_pool *p)
{
if (UNLIKELY(!p))
return NULL;
struct bv_scene_obj *s = BU_LIST_FIRST(bv_scene_obj, &p->i->head.l);
if (BU_LIST_IS_HEAD(&s->l, &p->i->head.l)) {
s = bv_obj_get(NULL);
} else {
BU_LIST_DEQUEUE(&(s->l));
}
s->obj_pool = p;
s->vlfree = &p->i->vlfree;
return s;
}
void
bv_obj_pool_put(struct bv_obj_pool *p, struct bv_scene_obj *s)
{
if (UNLIKELY(!p || !s))
return;
s->obj_pool = NULL;
bv_obj_reset(s);
BU_LIST_APPEND(&s->l, &(p->i->head.l));
}
struct bv_scene_obj *
bv_obj_get(struct bv_obj_pool *p)
{
struct bv_scene_obj *s = NULL;
if (!p) {
BU_ALLOC(s, struct bv_scene_obj);
s->l.magic = BV_SOBJ_MAGIC;
// Zero out callback pointers
s->s_type_flags = 0;
s->s_free_callback = NULL;
s->s_dlist_free_callback = NULL;
// Use reset to do most of the initialization
bv_obj_reset(s);
} else {
s = bv_obj_pool_get(p);
}
return s;
}
struct bv_scene_obj *
bv_obj_get_child(struct bv_scene_obj *sp)
{
if (!sp)
return NULL;
bv_log(1, "bv_obj_create_child %s(%s)", bu_vls_cstr(&sp->s_name), bu_vls_cstr(&sp->s_v->gv_name));
// Children use their parent's info
struct bv_scene_obj *s = bv_obj_pool_get(sp->obj_pool);
s->s_v = sp->s_v;
s->dp = sp->dp;
// Assign child name
bu_vls_sprintf(&s->s_name, "child:%s:%zd", bu_vls_cstr(&sp->s_name), BU_PTBL_LEN(&sp->children));
// Tell sp about the child
bu_ptbl_ins(&sp->children, (long *)s);
return s;
}
struct bv_scene_obj *
bv_obj_find_child(struct bv_scene_obj *s, const char *vname)
{
if (!s || !vname || !BU_PTBL_IS_INITIALIZED(&s->children))
return NULL;
for (size_t i = 0; i < BU_PTBL_LEN(&s->children); i++) {
struct bv_scene_obj *s_c = (struct bv_scene_obj *)BU_PTBL_GET(&s->children, i);
if (!bu_path_match(vname, bu_vls_cstr(&s_c->s_name), 0))
return s_c;
}
return NULL;
}
void
bv_obj_sync(struct bv_scene_obj *dest, struct bv_scene_obj *src)
{
bv_obj_settings_sync(dest->s_os, src->s_os);
VMOVE(dest->s_center, src->s_center);
VMOVE(dest->s_color, src->s_color);
VMOVE(dest->bmin, src->bmin);
VMOVE(dest->bmax, src->bmax);
MAT_COPY(dest->s_mat, src->s_mat);
dest->s_size = src->s_size;
dest->s_soldash = src->s_soldash;
dest->s_arrow = src->s_arrow;
dest->adaptive_wireframe = src->adaptive_wireframe;
dest->view_scale = src->view_scale;
dest->bot_threshold = src->bot_threshold;
dest->curve_scale = src->curve_scale;
dest->point_scale = src->point_scale;
}
void
bv_obj_reset(struct bv_scene_obj *s)
{
// handle children
if (BU_PTBL_IS_INITIALIZED(&s->children)) {
for (size_t i = 0; i < BU_PTBL_LEN(&s->children); i++) {
struct bv_scene_obj *s_c = (struct bv_scene_obj *)BU_PTBL_GET(&s->children, i);
bv_obj_put(s_c);
}
} else {
BU_PTBL_INIT(&s->children);
}
bu_ptbl_reset(&s->children);
// References are not cleaned up themselves, but we do clear
// the table
if (!BU_PTBL_IS_INITIALIZED(&s->obj_refs)) {
BU_PTBL_INIT(&s->obj_refs);
}
bu_ptbl_reset(&s->obj_refs);
// If we have a callback for the internal data, use it
if (s->s_free_callback)
(*s->s_free_callback)(s);
s->s_free_callback = NULL;
// If we have a callback for the display list data, use it
if (s->s_dlist_free_callback)
(*s->s_dlist_free_callback)(s);
s->s_dlist_free_callback = NULL;
// Free vlist data. If we have an associated vlfree list for
// reuse use that, otherwise free it for real.
if (BU_LIST_IS_INITIALIZED(&s->s_vlist)) {
if (s->vlfree) {
BV_FREE_VLIST(s->vlfree, &s->s_vlist);
} else {
struct bu_list *p;
while (BU_LIST_WHILE(p, bu_list, &s->s_vlist)) {
BU_LIST_DEQUEUE(p);
struct bv_vlist *pv = (struct bv_vlist *)p;
BU_FREE(pv, struct bv_vlist);
}
}
}
BU_LIST_INIT(&(s->s_vlist));
if (!BU_VLS_IS_INITIALIZED(&s->s_name))
BU_VLS_INIT(&s->s_name);
bu_vls_trunc(&s->s_name, 0);
struct bv_obj_settings defaults = BV_OBJ_SETTINGS_INIT;
bv_obj_settings_sync(&s->s_local_os, &defaults);
s->s_os = &s->s_local_os;
s->s_override_obj_ref_settings = 0;
MAT_IDN(s->s_mat);
VSET(s->s_color, 255, 0, 0);
VSETALL(s->bmax, -INFINITY);
VSETALL(s->bmin, INFINITY);
VSETALL(s->s_center, 0);
s->adaptive_wireframe = 0;
s->bot_threshold = 0;
s->csg_obj = 0;
s->current = 0;
s->curve_scale = 0;
s->dp = NULL;
s->draw_data = NULL;
s->have_bbox = 0;
s->mesh_obj = 0;
s->point_scale = 0;
s->s_arrow = 0;
s->s_csize = 0;
s->s_flag = UP;
s->s_force_draw = 0;
s->s_i_data = NULL;
s->s_iflag = DOWN;
s->s_path = NULL;
s->s_size = 0;
s->s_soldash = 0;
s->s_update_callback = NULL;
s->s_v = NULL;
s->view_scale = 0;
// Set timestamp
s->timestamp = bu_gettime();
}
void
bv_obj_put(struct bv_scene_obj *s)
{
bv_log(1, "bv_obj_put %s[%s]", bu_vls_cstr(&s->s_name), (s->s_v) ? bu_vls_cstr(&s->s_v->gv_name) : "NULL");
for (size_t i = 0; i < BU_PTBL_LEN(&s->children); i++) {
struct bv_scene_group *cg = (struct bv_scene_group *)BU_PTBL_GET(&s->children, i);
bv_obj_put(cg);
}
// If this object was selected for snapping, it is no longer a valid candidate
// TODO - manage this at a higher level
if (s->s_v)
bu_ptbl_rm(&s->s_v->gv_s->gv_snap_objs, (long *)s);
if (s->obj_pool) {
bv_obj_pool_put(s->obj_pool, s);
} else {
bv_obj_reset(s);
bu_vls_free(&s->s_name);
BU_FREE(s, struct bv_scene_obj);
}
}
int
bv_obj_bound(struct bv_scene_obj *s)
{
int cmd;
VSET(s->bmin, INFINITY, INFINITY, INFINITY);
VSET(s->bmax, -INFINITY, -INFINITY, -INFINITY);
int calc = 0;
if (s->s_type_flags & BV_MESH_LOD) {
struct bv_lod_mesh *i = (struct bv_lod_mesh *)s->draw_data;
if (i) {
point_t obmin, obmax;
VMOVE(obmin, i->bmin);
VMOVE(obmax, i->bmax);
// Apply the scene matrix to the bounding box values to bound this
// instance, since the BV_MESH_LOD data is based on the
// non-instanced mesh.
MAT4X3PNT(s->bmin, s->s_mat, obmin);
MAT4X3PNT(s->bmax, s->s_mat, obmax);
calc = 1;
}
} else if (bu_list_len(&s->s_vlist)) {
int dismode;
cmd = bv_vlist_bbox(&s->s_vlist, &s->bmin, &s->bmax, NULL, &dismode);
if (cmd) {
bu_log("unknown vlist op %d\n", cmd);
}
s->s_displayobj = dismode;
calc = 1;
}
if (calc) {
s->s_center[X] = (s->bmin[X] + s->bmax[X]) * 0.5;
s->s_center[Y] = (s->bmin[Y] + s->bmax[Y]) * 0.5;
s->s_center[Z] = (s->bmin[Z] + s->bmax[Z]) * 0.5;
s->s_size = s->bmax[X] - s->bmin[X];
V_MAX(s->s_size, s->bmax[Y] - s->bmin[Y]);
V_MAX(s->s_size, s->bmax[Z] - s->bmin[Z]);
return 1;
}
return 0;
}
int
bv_illum_obj(struct bv_scene_obj *s, char ill_state)
{
bool changed = 0;
for (size_t i = 0; i < BU_PTBL_LEN(&s->children); i++) {
struct bv_scene_obj *s_c = (struct bv_scene_obj *)BU_PTBL_GET(&s->children, i);
int cchanged = bv_illum_obj(s_c, ill_state);
if (cchanged)
changed = 1;
}
if (ill_state != s->s_iflag) {
changed = 1;
s->s_iflag = ill_state;
}
return changed;
}
// Debugging function to see constructed arb
#define ARB_MAX_STRLEN 400
const char *
obb_arb(vect_t obb_center, vect_t obb_extent1, vect_t obb_extent2, vect_t obb_extent3)
{
static char str[ARB_MAX_STRLEN+1];
// For debugging purposes, construct an arb
point_t arb[8];
// 1 - c - e1 - e2 - e3
VSUB2(arb[0], obb_center, obb_extent1);
VSUB2(arb[0], arb[0], obb_extent2);
VSUB2(arb[0], arb[0], obb_extent3);
// 2 - c - e1 - e2 + e3
VSUB2(arb[1], obb_center, obb_extent1);
VSUB2(arb[1], arb[1], obb_extent2);
VADD2(arb[1], arb[1], obb_extent3);
// 3 - c - e1 + e2 + e3
VSUB2(arb[2], obb_center, obb_extent1);
VADD2(arb[2], arb[2], obb_extent2);
VADD2(arb[2], arb[2], obb_extent3);
// 4 - c - e1 + e2 - e3
VSUB2(arb[3], obb_center, obb_extent1);
VADD2(arb[3], arb[3], obb_extent2);
VSUB2(arb[3], arb[3], obb_extent3);
// 1 - c + e1 - e2 - e3
VADD2(arb[4], obb_center, obb_extent1);
VSUB2(arb[4], arb[4], obb_extent2);
VSUB2(arb[4], arb[4], obb_extent3);
// 2 - c + e1 - e2 + e3
VADD2(arb[5], obb_center, obb_extent1);
VSUB2(arb[5], arb[5], obb_extent2);
VADD2(arb[5], arb[5], obb_extent3);
// 3 - c + e1 + e2 + e3
VADD2(arb[6], obb_center, obb_extent1);
VADD2(arb[6], arb[6], obb_extent2);
VADD2(arb[6], arb[6], obb_extent3);
// 4 - c + e1 + e2 - e3
VADD2(arb[7], obb_center, obb_extent1);
VADD2(arb[7], arb[7], obb_extent2);
VSUB2(arb[7], arb[7], obb_extent3);
#if 0
bu_log("center: %f %f %f\n", V3ARGS(obb_center));
bu_log("e1: %f %f %f\n", V3ARGS(obb_extent1));
bu_log("e2: %f %f %f\n", V3ARGS(obb_extent2));
bu_log("e3: %f %f %f\n", V3ARGS(obb_extent3));
#endif
snprintf(str, ARB_MAX_STRLEN, "in obb.s arb8 %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f %f\n",
V3ARGS(arb[0]), V3ARGS(arb[1]), V3ARGS(arb[2]), V3ARGS(arb[3]), V3ARGS(arb[4]), V3ARGS(arb[5]), V3ARGS(arb [6]), V3ARGS(arb[7]));
return str;
}
static void
obj_bb(int *have_objs, vect_t *min, vect_t *max, struct bv_scene_obj *s)
{
vect_t minus, plus;
if (bv_obj_bound(s)) {
*have_objs = 1;
minus[X] = s->s_center[X] - s->s_size;
minus[Y] = s->s_center[Y] - s->s_size;
minus[Z] = s->s_center[Z] - s->s_size;
VMIN(*min, minus);
plus[X] = s->s_center[X] + s->s_size;
plus[Y] = s->s_center[Y] + s->s_size;
plus[Z] = s->s_center[Z] + s->s_size;
VMAX(*max, plus);
}
for (size_t i = 0; i < BU_PTBL_LEN(&s->children); i++) {
struct bv_scene_obj *sc = (struct bv_scene_obj *)BU_PTBL_GET(&s->children, i);
obj_bb(have_objs, min, max, sc);
}
}
static void
view_obb(struct bview *v,
point_t sbbc, fastf_t radius,
vect_t dir,
point_t ec, point_t ep1, point_t ep2)
{
// Box center is the closest point to the view center on the plane defined
// by the scene's center and the view dir
plane_t p;
bg_plane_pt_nrml(&p, sbbc, dir);
fastf_t pu, pv;
point_t lec;
VMOVE(lec, ec);
bg_plane_closest_pt(&pu, &pv, &p, &lec);
bg_plane_pt_at(&v->obb_center, &p, pu, pv);
// The first extent is just the scene radius in the lookat direction
VSCALE(dir, dir, radius);
VMOVE(v->obb_extent1, dir);
// The other two extents we find by subtracting the view center from the edge points
VSUB2(v->obb_extent2, ep1, ec);
VSUB2(v->obb_extent3, ep2, ec);
bv_log(3, "view_obb inputs[%s]: sbbc(%f %f %f) radius(%f) dir(%f %f %f)", bu_vls_cstr(&v->gv_name), V3ARGS(sbbc), radius, V3ARGS(dir));
bv_log(3, "view_obb[%s]: %f %f %f -> [%f %f %f] [%f %f %f] [%f %f %f]", bu_vls_cstr(&v->gv_name), V3ARGS(v->obb_center), V3ARGS(v->obb_extent1), V3ARGS(v->obb_extent2), V3ARGS(v->obb_extent3));
bv_log(3, "%s", obb_arb(v->obb_center, v->obb_extent1, v->obb_extent2, v->obb_extent3));
}
static void
_scene_radius(point_t *sbbc, fastf_t *radius, const struct bu_ptbl *so)
{
if (!sbbc || !radius || !so)
return;
VSET(*sbbc, 0, 0, 0);
*radius = 1.0;
vect_t min, max, work;
VSETALL(min, INFINITY);
VSETALL(max, -INFINITY);
int have_objs = 0;
for (size_t i = 0; i < BU_PTBL_LEN(so); i++) {
struct bv_scene_obj *g = (struct bv_scene_obj *)BU_PTBL_GET(so, i);
obj_bb(&have_objs, &min, &max, g);
}
if (have_objs) {
VADD2SCALE(*sbbc, max, min, 0.5);
VSUB2SCALE(work, max, min, 0.5);
(*radius) = MAGNITUDE(work);
}
}
void
bv_view_bounds(struct bview *v, const struct bu_ptbl *so)
{
if (!v || !v->gv_width || !v->gv_height || !so)
return;
// Get the radius of the scene.
point_t sbbc = VINIT_ZERO;
fastf_t radius = 1.0;
_scene_radius(&sbbc, &radius, so);
// Using the pixel width and height of the current "window", construct some
// view space dimensions related to that window
int w = v->gv_width;
int h = v->gv_height;
int x = (int)(w * 0.5);
int y = (int)(h * 0.5);
//bu_log("w,h,x,y: %d %d %d %d\n", w,h, x, y);
fastf_t x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0, xc = 0.0, yc = 0.0;
bv_screen_to_view(v, &x1, &y1, x, h);
bv_screen_to_view(v, &x2, &y2, w, y);
bv_screen_to_view(v, &xc, &yc, x, y);
// Also stash the window's view space bbox
fastf_t w0, w1, w2, w3;
bv_screen_to_view(v, &w0, &w1, 0, 0);
bv_screen_to_view(v, &w2, &w3, w, h);
v->gv_wmin[0] = (w0 < w2) ? w0 : w2;
v->gv_wmin[1] = (w1 < w3) ? w1 : w3;
v->gv_wmax[0] = (w0 > w2) ? w0 : w2;
v->gv_wmax[1] = (w1 > w3) ? w1 : w3;
//bu_log("vbbmin: %f %f\n", v->gv_wmin[0], v->gv_wmin[1]);
//bu_log("vbbmax: %f %f\n", v->gv_wmax[0], v->gv_wmax[1]);
// Get the model space points for the mid points of the top and right edges
// of the view. If we don't have a width or height, we will use the
// existing min and max since we don't have a "screen" to base the box on
//bu_log("x1,y1: %f %f\n", x1, y1);
//bu_log("x2,y2: %f %f\n", x2, y2);
//bu_log("xc,yc: %f %f\n", xc, yc);
point_t vp1, vp2, vc, ep1, ep2, ec;
VSET(vp1, x1, y1, 0);
VSET(vp2, x2, y2, 0);
VSET(vc, xc, yc, 0);
MAT4X3PNT(ep1, v->gv_view2model, vp1);
MAT4X3PNT(ep2, v->gv_view2model, vp2);
MAT4X3PNT(ec, v->gv_view2model, vc);
//bu_log("view center: %f %f %f\n", V3ARGS(ec));
//bu_log("edge point 1: %f %f %f\n", V3ARGS(ep1));
//bu_log("edge point 2: %f %f %f\n", V3ARGS(ep2));
// Need the direction vector - i.e., where the camera is looking. Got this
// trick from the libged nirt code...
vect_t dir;
VMOVEN(dir, v->gv_rotation + 8, 3);
VUNITIZE(dir);
VSCALE(dir, dir, -1.0);
// If perspective mode is not enabled, update the oriented bounding box.
if (!(SMALL_FASTF < v->gv_perspective)) {
view_obb(v, sbbc, radius, dir, ec, ep1, ep2);
}
// While we have the info, construct the "backed out" point that will let
// us construct the "backed out" view plane, and save that point and the
// lookat direction to the view
VMOVE(v->gv_lookat, dir);
VSCALE(dir, dir, -radius);
VADD2(v->gv_vc_backout, sbbc, dir);
v->radius = radius;
}
static void
_find_active_objs(std::set<struct bv_scene_obj *> &active, struct bv_scene_obj *s, struct bview *v, point_t obb_c, point_t obb_e1, point_t obb_e2, point_t obb_e3)
{
if (BU_PTBL_LEN(&s->children)) {
for (size_t i = 0; i < BU_PTBL_LEN(&s->children); i++) {
struct bv_scene_obj *sc = (struct bv_scene_obj *)BU_PTBL_GET(&s->children, i);
_find_active_objs(active, sc, v, obb_c, obb_e1, obb_e2, obb_e3);
}
} else {
bv_obj_bound(s);
if (bg_sat_aabb_obb(s->bmin, s->bmax, obb_c, obb_e1, obb_e2, obb_e3))
active.insert(s);
}
}
int
bv_view_objs_select(struct bu_ptbl *sset, struct bview *v, struct bu_ptbl *so, int x, int y)
{
if (!v || !sset || !v->gv_width || !v->gv_height || !so)
return 0;
bu_ptbl_reset(sset);
if (x < 0 || y < 0 || x > v->gv_width || y > v->gv_height)
return 0;
// Get the radius of the scene.
point_t sbbc = VINIT_ZERO;
fastf_t radius = 1.0;
_scene_radius(&sbbc, &radius, so);
// Using the pixel width and height of the current "window", construct some
// view space dimensions related to that window
fastf_t x1 = 0.0, y1 = 0.0, x2 = 0.0, y2 = 0.0, xc = 0.0, yc = 0.0;
bv_screen_to_view(v, &x1, &y1, x, y+1);
bv_screen_to_view(v, &x2, &y2, x+1, y);
bv_screen_to_view(v, &xc, &yc, x, y);
// Get the model space points for the mid points of the top and right edges
// of the "pixel + 1" box.
//bu_log("x1,y1: %f %f\n", x1, y1);
//bu_log("x2,y2: %f %f\n", x2, y2);
//bu_log("xc,yc: %f %f\n", xc, yc);
point_t vp1, vp2, vc, ep1, ep2, ec;
VSET(vp1, x1, y1, 0);
VSET(vp2, x2, y2, 0);
VSET(vc, xc, yc, 0);
MAT4X3PNT(ep1, v->gv_view2model, vp1);
MAT4X3PNT(ep2, v->gv_view2model, vp2);
MAT4X3PNT(ec, v->gv_view2model, vc);
// Need the direction vector - i.e., where the camera is looking. Got this
// trick from the libged nirt code...
vect_t dir;
VMOVEN(dir, v->gv_rotation + 8, 3);
VUNITIZE(dir);
VSCALE(dir, dir, -1.0);
// Construct the box values needed for the SAT test
point_t obb_c, obb_e1, obb_e2, obb_e3;
// Box center is the closest point to the view center on the plane defined
// by the scene's center and the view dir
plane_t p;
bg_plane_pt_nrml(&p, sbbc, dir);
fastf_t pu, pv;
bg_plane_closest_pt(&pu, &pv, &p, &ec);
bg_plane_pt_at(&obb_c, &p, pu, pv);
// The first extent is just the scene radius in the lookat direction
VSCALE(dir, dir, radius);
VMOVE(obb_e1, dir);
// The other two extents we find by subtracting the view center from the edge points
VSUB2(obb_e2, ep1, ec);
VSUB2(obb_e3, ep2, ec);
// Having constructed the box, test the scene objects against it. Any that intersect,
// add them to the set
std::set<struct bv_scene_obj *> active;
for (size_t i = 0; i < BU_PTBL_LEN(so); i++) {
struct bv_scene_obj *s = (struct bv_scene_obj *)BU_PTBL_GET(so, i);
_find_active_objs(active, s, v, obb_c, obb_e1, obb_e2, obb_e3);
}
if (active.size()) {
std::set<struct bv_scene_obj *>::iterator a_it;
for (a_it = active.begin(); a_it != active.end(); a_it++) {
bu_ptbl_ins(sset, (long *)*a_it);
}
}
return active.size();
}
int
bv_view_objs_rect_select(struct bu_ptbl *sset, struct bview *v, struct bu_ptbl *so, int x1, int y1, int x2, int y2)
{
if (!v || !sset || !v->gv_width || !v->gv_height || !so)
return 0;
bu_ptbl_reset(sset);
if (x1 < 0 || y1 < 0 || x1 > v->gv_width || y1 > v->gv_height)
return 0;
if (x2 < 0 || y2 < 0 || x2 > v->gv_width || y2 > v->gv_height)
return 0;
// Get the radius of the scene.
point_t sbbc = VINIT_ZERO;
fastf_t radius = 1.0;
_scene_radius(&sbbc, &radius, so);
// Using the pixel width and height of the current "window", construct some
// view space dimensions related to that window
fastf_t fx1 = 0.0, fy1 = 0.0, fx2 = 0.0, fy2 = 0.0, fxc = 0.0, fyc = 0.0;
bv_screen_to_view(v, &fx1, &fy1, (int)(0.5*(x1+x2)), y2);
bv_screen_to_view(v, &fx2, &fy2, x2, (int)(0.5*(y1+y2)));
bv_screen_to_view(v, &fxc, &fyc, (int)(0.5*(x1+x2)), (int)(0.5*(y1+y2)));
// Get the model space points for the mid points of the top and right edges
// of the box.
point_t vp1, vp2, vc, ep1, ep2, ec;
VSET(vp1, fx1, fy1, 0);
VSET(vp2, fx2, fy2, 0);
VSET(vc, fxc, fyc, 0);
MAT4X3PNT(ep1, v->gv_view2model, vp1);
MAT4X3PNT(ep2, v->gv_view2model, vp2);
MAT4X3PNT(ec, v->gv_view2model, vc);
//bu_log("in sph1.s sph %f %f %f 1\n", V3ARGS(ep1));
//bu_log("in sph2.s sph %f %f %f 2\n", V3ARGS(ep2));
//bu_log("in sphc.s sph %f %f %f 3\n", V3ARGS(ec));
// Need the direction vector - i.e., where the camera is looking. Got this
// trick from the libged nirt code...
vect_t dir;
VMOVEN(dir, v->gv_rotation + 8, 3);
VUNITIZE(dir);
VSCALE(dir, dir, -1.0);
// Construct the box values needed for the SAT test
point_t obb_c, obb_e1, obb_e2, obb_e3;
// Box center is the closest point to the view center on the plane defined
// by the scene's center and the view dir
plane_t p;
bg_plane_pt_nrml(&p, sbbc, dir);
fastf_t pu, pv;
bg_plane_closest_pt(&pu, &pv, &p, &ec);
bg_plane_pt_at(&obb_c, &p, pu, pv);
// The first extent is just the scene radius in the lookat direction
VSCALE(dir, dir, radius);
VMOVE(obb_e1, dir);
// The other two extents we find by subtracting the view center from the edge points
VSUB2(obb_e2, ep1, ec);
VSUB2(obb_e3, ep2, ec);
#if 0
bu_log("%s", obb_arb(obb_c, obb_e1, obb_e2, obb_e3));
#endif
// Having constructed the box, test the scene objects against it. Any that intersect,
// add them to the set
std::set<struct bv_scene_obj *> active;
for (size_t i = 0; i < BU_PTBL_LEN(so); i++) {
struct bv_scene_obj *s = (struct bv_scene_obj *)BU_PTBL_GET(so, i);
_find_active_objs(active, s, v, obb_c, obb_e1, obb_e2, obb_e3);
}
if (active.size()) {
std::set<struct bv_scene_obj *>::iterator a_it;
for (a_it = active.begin(); a_it != active.end(); a_it++) {
bu_ptbl_ins(sset, (long *)*a_it);
}
}
return active.size();
}
int
bv_view_obj_vis(const struct bview *v, const struct bv_scene_obj *s)
{
if (bg_sat_aabb_obb(s->bmin, s->bmax, v->obb_center, v->obb_extent1, v->obb_extent2, v->obb_extent3)) {
bv_log(3, "obj_visible[%s] - passed bg_sat_abb_obb: %f %f %f -> %f %f %f", bu_vls_cstr(&v->gv_name), V3ARGS(s->bmin), V3ARGS(s->bmax));
bv_log(3, " view abb : %f %f %f -> [%f %f %f] [%f %f %f] [%f %f %f]", V3ARGS(v->obb_center), V3ARGS(v->obb_extent1), V3ARGS(v->obb_extent2), V3ARGS(v->obb_extent3));
//bv_log(3, "%s", obb_arb(v->obb_center, v->obb_extent1, v->obb_extent2, v->obb_extent3));
return 1;
} else {
bv_log(3, "obj_visible[%s] - FAILED bg_sat_abb_obb: %f %f %f -> %f %f %f", bu_vls_cstr(&v->gv_name),V3ARGS(s->bmin), V3ARGS(s->bmax));
bv_log(3, " view abb : %f %f %f -> [%f %f %f] [%f %f %f] [%f %f %f]", V3ARGS(v->obb_center), V3ARGS(v->obb_extent1), V3ARGS(v->obb_extent2), V3ARGS(v->obb_extent3));
//bv_log(3, "%s", obb_arb(v->obb_center, v->obb_extent1, v->obb_extent2, v->obb_extent3));
}
if (SMALL_FASTF < v->gv_perspective) {
// For perspective mode, project the vertices of the distorted bounding
// box into the view plane, bound them, and see if the box overlaps with
// the view screen's box.
point_t arb[8];
VSET(arb[0], s->bmin[0], s->bmin[1], s->bmin[2]);
VSET(arb[1], s->bmin[0], s->bmin[1], s->bmax[2]);
VSET(arb[2], s->bmin[0], s->bmax[1], s->bmin[2]);
VSET(arb[3], s->bmin[0], s->bmax[1], s->bmax[2]);
VSET(arb[4], s->bmax[0], s->bmin[1], s->bmin[2]);
VSET(arb[5], s->bmax[0], s->bmin[1], s->bmax[2]);
VSET(arb[6], s->bmax[0], s->bmax[1], s->bmin[2]);
VSET(arb[7], s->bmax[0], s->bmax[1], s->bmax[2]);
point2d_t omin = {INFINITY, INFINITY};
point2d_t omax = {-INFINITY, -INFINITY};
for (int i = 0; i < 8; i++) {
point_t pp, ppnt;
point2d_t pxy;
MAT4X3PNT(pp, v->gv_pmat, arb[i]);
MAT4X3PNT(ppnt, v->gv_model2view, pp);
V2SET(pxy, ppnt[0], ppnt[1]);
V2MINMAX(omin, omax, pxy);
}
// IFF the omin/omax box and the corresponding view box overlap, this
// object may be visible in the current view and needs to be updated
for (int i = 0; i < 2; i++) {
if (omax[i] < v->gv_wmin[i] || omin[i] > v->gv_wmax[i])
return 0;
}
return 1;
}
return 0;
}
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8
+10 -9
View File
@@ -39,6 +39,7 @@
#include "bg/polygon.h"
#include "bv/defines.h"
#include "bv/polygon.h"
#include "bv/objs.h"
#include "bv/snap.h"
void
@@ -75,7 +76,7 @@ bv_fill_polygon(struct bv_scene_obj *s)
return;
// free old fill, if present
struct bv_scene_obj *fobj = bv_find_child(s, "*fill*");
struct bv_scene_obj *fobj = bv_obj_find_child(s, "*fill*");
if (fobj)
bv_obj_put(fobj);
@@ -166,7 +167,7 @@ bv_polygon_vlist(struct bv_scene_obj *s)
if (p->fill_flag) {
bv_fill_polygon(s);
} else {
struct bv_scene_obj *fobj = bv_find_child(s, "*fill*");
struct bv_scene_obj *fobj = bv_obj_find_child(s, "*fill*");
if (fobj)
bv_obj_put(fobj);
@@ -174,11 +175,11 @@ bv_polygon_vlist(struct bv_scene_obj *s)
}
struct bv_scene_obj *
bv_create_polygon_obj(struct bview *v, int flags, struct bv_polygon *p)
bv_create_polygon_obj(struct bview *v, struct bv_polygon *p)
{
struct bv_scene_obj *s = bv_obj_get(v, flags);
struct bv_scene_obj *s = bv_obj_get(NULL);
s->s_v = v;
s->s_type_flags |= BV_POLYGONS;
s->s_type_flags |= BV_VIEWONLY;
// Construct the plane
bv_view_plane(&p->vp, v);
@@ -200,7 +201,7 @@ bv_create_polygon_obj(struct bview *v, int flags, struct bv_polygon *p)
}
struct bv_scene_obj *
bv_create_polygon(struct bview *v, int flags, int type, point_t *fp)
bv_create_polygon(struct bview *v, int type, point_t *fp)
{
struct bv_polygon *p;
BU_GET(p, struct bv_polygon);
@@ -250,7 +251,7 @@ bv_create_polygon(struct bview *v, int flags, int type, point_t *fp)
p->polygon.contour[0].open = 1;
// Have polygon, now make scene object
struct bv_scene_obj *s = bv_create_polygon_obj(v, flags, p);
struct bv_scene_obj *s = bv_create_polygon_obj(v, p);
if (!s)
BU_PUT(p, struct bv_polygon);
return s;
@@ -764,7 +765,7 @@ bv_update_polygon(struct bv_scene_obj *s, struct bview *v, int utype)
struct bv_polygon *p = (struct bv_polygon *)s->s_i_data;
// Regardless of type, sync fill color
struct bv_scene_obj *fobj = bv_find_child(s, "*fill*");
struct bv_scene_obj *fobj = bv_obj_find_child(s, "*fill*");
if (fobj) {
bu_color_to_rgb_chars(&p->fill_color, fobj->s_color);
}
@@ -831,7 +832,7 @@ bv_dup_view_polygon(const char *nname, struct bv_scene_obj *s)
BU_GET(p, struct bv_polygon);
bv_polygon_cpy(p, ip);
struct bv_scene_obj *np = bv_create_polygon_obj(s->s_v, s->s_type_flags, p);
struct bv_scene_obj *np = bv_create_polygon_obj(s->s_v, p);
// Have geometry, now copy visual settings
VMOVE(np->s_color, s->s_color);
+17 -54
View File
@@ -255,7 +255,7 @@ line_tol_sq(struct bview *v, int lwidth)
}
int
bv_snap_lines_3d(point_t *out_pt, struct bview *v, point_t *p)
bv_snap_lines_3d(point_t *out_pt, struct bview *v, const struct bu_ptbl *sobjs, point_t *p)
{
int ret = 0;
struct bview_settings *gv_s = (v->gv_s) ? v->gv_s : &v->gv_ls;
@@ -263,58 +263,21 @@ bv_snap_lines_3d(point_t *out_pt, struct bview *v, point_t *p)
if (!p || !v) return 0;
// If we're not in Tcl mode only, we are looking at objects - either
// all of them, or a specified subset
// If we're not in Tcl mode only, we are looking at the list of supplied objects
if (gv_s->gv_snap_flags != BV_SNAP_TCL) {
if (!sobjs)
return 0;
struct bv_cp_info *s = &cpinfo.c;
s->ctol_sq = line_tol_sq(v, 1);
if (BU_PTBL_LEN(&gv_s->gv_snap_objs) > 0) {
for (size_t i = 0; i < BU_PTBL_LEN(&gv_s->gv_snap_objs); i++) {
struct bv_scene_obj *so = (struct bv_scene_obj *)BU_PTBL_GET(&gv_s->gv_snap_objs, i);
if (gv_s->gv_snap_flags) {
if (gv_s->gv_snap_flags == BV_SNAP_DB && (!(so->s_type_flags & BV_DB_OBJS)))
continue;
if (gv_s->gv_snap_flags == BV_SNAP_VIEW && (!(so->s_type_flags & BV_VIEW_OBJS)))
continue;
}
struct bv_obj_settings *s_os = (so->s_os) ? so->s_os : &so->s_local_os;
s->ctol_sq = line_tol_sq(v, (s_os->s_line_width) ? s_os->s_line_width : 1);
ret += _find_closest_obj_point(s, p, so);
}
} else {
if (!gv_s->gv_snap_flags || (gv_s->gv_snap_flags & BV_SNAP_DB)) {
if (!gv_s->gv_snap_flags || (gv_s->gv_snap_flags & BV_SNAP_SHARED)) {
struct bu_ptbl *sobjs = bv_view_objs(v, BV_DB_OBJS);
for (size_t i = 0; i < BU_PTBL_LEN(sobjs); i++) {
struct bv_scene_obj *so = (struct bv_scene_obj *)BU_PTBL_GET(sobjs, i);
ret += _find_closest_obj_point(s, p, so);
}
}
if (!gv_s->gv_snap_flags || (gv_s->gv_snap_flags & BV_SNAP_LOCAL)) {
struct bu_ptbl *sobjs = bv_view_objs(v, BV_DB_OBJS | BV_LOCAL_OBJS);
for (size_t i = 0; i < BU_PTBL_LEN(sobjs); i++) {
struct bv_scene_obj *so = (struct bv_scene_obj *)BU_PTBL_GET(sobjs, i);
ret += _find_closest_obj_point(s, p, so);
}
}
}
if (!gv_s->gv_snap_flags || (gv_s->gv_snap_flags & BV_SNAP_VIEW)) {
if (!gv_s->gv_snap_flags || (gv_s->gv_snap_flags & BV_SNAP_SHARED)) {
struct bu_ptbl *sobjs = bv_view_objs(v, BV_VIEW_OBJS);
for (size_t i = 0; i < BU_PTBL_LEN(sobjs); i++) {
struct bv_scene_obj *so = (struct bv_scene_obj *)BU_PTBL_GET(sobjs, i);
ret += _find_closest_obj_point(s, p, so);
}
}
if (!gv_s->gv_snap_flags || (gv_s->gv_snap_flags & BV_SNAP_LOCAL)) {
struct bu_ptbl *sobjs = bv_view_objs(v, BV_VIEW_OBJS | BV_LOCAL_OBJS);
for (size_t i = 0; i < BU_PTBL_LEN(sobjs); i++) {
struct bv_scene_obj *so = (struct bv_scene_obj *)BU_PTBL_GET(sobjs, i);
ret += _find_closest_obj_point(s, p, so);
}
}
}
for (size_t i = 0; i < BU_PTBL_LEN(sobjs); i++) {
struct bv_scene_obj *so = (struct bv_scene_obj *)BU_PTBL_GET(sobjs, i);
struct bv_obj_settings *s_os = (so->s_os) ? so->s_os : &so->s_local_os;
s->ctol_sq = line_tol_sq(v, (s_os->s_line_width) ? s_os->s_line_width : 1);
ret += _find_closest_obj_point(s, p, so);
}
// TODO - need to figure out how to do intersection snapping with lines
// in scene objects...
}
// There are some issues with line snapping that don't come up with grid
@@ -322,7 +285,7 @@ bv_snap_lines_3d(point_t *out_pt, struct bview *v, point_t *p)
// and how do we handle snapping when close enough to multiple lines? We
// probably want to prefer intersections between lines to closest line
// point if we are close to multiple lines...
if (!gv_s->gv_snap_flags || gv_s->gv_snap_flags & BV_SNAP_TCL) {
if (gv_s->gv_snap_flags & BV_SNAP_TCL) {
int tret = 0;
int lwidth;
lwidth = (v->gv_tcl.gv_data_lines.gdls_line_width) ? v->gv_tcl.gv_data_lines.gdls_line_width : 1;
@@ -354,7 +317,7 @@ bv_snap_lines_3d(point_t *out_pt, struct bview *v, point_t *p)
}
int
bv_snap_lines_2d(struct bview *v, fastf_t *vx, fastf_t *vy)
bv_snap_lines_2d(struct bview *v, const struct bu_ptbl *sobjs, fastf_t *vx, fastf_t *vy)
{
if (!v || !vx || !vy) return 0;
@@ -365,7 +328,7 @@ bv_snap_lines_2d(struct bview *v, fastf_t *vx, fastf_t *vy)
point_t p = VINIT_ZERO;
MAT4X3PNT(p, v->gv_view2model, vp);
point_t out_pt = VINIT_ZERO;
if (bv_snap_lines_3d(&out_pt, v, &p) == 1) {
if (bv_snap_lines_3d(&out_pt, v, sobjs, &p) == 1) {
MAT4X3PNT(vp, v->gv_model2view, out_pt);
(*vx) = vp[0];
(*vy) = vp[1];
@@ -376,14 +339,14 @@ bv_snap_lines_2d(struct bview *v, fastf_t *vx, fastf_t *vy)
}
void
bv_view_center_linesnap(struct bview *v)
bv_view_center_linesnap(struct bview *v, const struct bu_ptbl *sobjs)
{
point_t view_pt;
point_t model_pt;
MAT_DELTAS_GET_NEG(model_pt, v->gv_center);
MAT4X3PNT(view_pt, v->gv_model2view, model_pt);
bv_snap_lines_2d(v, &view_pt[X], &view_pt[Y]);
bv_snap_lines_2d(v, sobjs, &view_pt[X], &view_pt[Y]);
MAT4X3PNT(model_pt, v->gv_view2model, view_pt);
MAT_DELTAS_VEC_NEG(v->gv_center, model_pt);
bv_update(v);
+14 -874
View File
File diff suppressed because it is too large Load Diff
-151
View File
@@ -1,151 +0,0 @@
/* V I E W _ S E T S . C P P
* BRL-CAD
*
* Copyright (c) 2020-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file view_sets.cpp
*
* Utility functions for operating on BRL-CAD view sets
*
*/
#include "common.h"
#include <string.h>
#include "vmath.h"
#include "bu/log.h"
#include "bu/malloc.h"
#include "bu/str.h"
#include "bn/mat.h"
#include "bv/defines.h"
#include "bv/util.h"
#include "bv/view_sets.h"
#include "./bv_private.h"
void
bv_set_init(struct bview_set *s)
{
BU_GET(s->i, struct bview_set_internal);
BU_PTBL_INIT(&s->i->views);
bu_ptbl_init(&s->i->shared_db_objs, 8, "db_objs init");
bu_ptbl_init(&s->i->shared_view_objs, 8, "view_objs init");
BU_LIST_INIT(&s->i->vlfree);
/* init the solid list */
BU_GET(s->i->free_scene_obj, struct bv_scene_obj);
BU_LIST_INIT(&s->i->free_scene_obj->l);
}
void
bv_set_free(struct bview_set *s)
{
if (s->i) {
bu_ptbl_free(&s->i->views);
bu_ptbl_free(&s->i->shared_db_objs);
bu_ptbl_free(&s->i->shared_view_objs);
// TODO - replace free_scene_obj with bu_ptbl
struct bv_scene_obj *sp, *nsp;
sp = BU_LIST_NEXT(bv_scene_obj, &s->i->free_scene_obj->l);
while (BU_LIST_NOT_HEAD(sp, &s->i->free_scene_obj->l)) {
nsp = BU_LIST_PNEXT(bv_scene_obj, sp);
BU_LIST_DEQUEUE(&((sp)->l));
if (sp->s_free_callback)
(*sp->s_free_callback)(sp);
if (sp->s_dlist_free_callback)
(*sp->s_dlist_free_callback)(sp);
bu_ptbl_free(&sp->children);
BU_PUT(sp, struct bv_scene_obj);
sp = nsp;
}
BU_PUT(s->i->free_scene_obj, struct bv_scene_obj);
BU_PUT(s->i, struct bview_set_internal);
}
// TODO - clean up vlfree
}
void
bv_set_add_view(struct bview_set *s, struct bview *v){
if (!s || !v)
return;
bu_ptbl_ins_unique(&s->i->views, (long *)v);
v->vset = s;
// By default, when we add a view to a set it is no longer considered
// independent
v->independent = 0;
}
void
bv_set_rm_view(struct bview_set *s, struct bview *v){
if (!s)
return;
if (!v) {
bu_ptbl_reset(&s->i->views);
return;
}
bu_ptbl_rm(&s->i->views, (long int *)v);
v->vset = NULL;
// By default, when we remove a view from a set it is considered
// independent
v->independent = 1;
}
struct bu_ptbl *
bv_set_views(struct bview_set *s){
if (!s)
return NULL;
return &s->i->views;
}
struct bview *
bv_set_find_view(struct bview_set *s, const char *vname)
{
struct bview *v = NULL;
for (size_t i = 0; i < BU_PTBL_LEN(&s->i->views); i++) {
struct bview *tv = (struct bview *)BU_PTBL_GET(&s->i->views, i);
if (BU_STR_EQUAL(bu_vls_cstr(&tv->gv_name), vname)) {
v = tv;
break;
}
}
return v;
}
struct bv_scene_obj *
bv_set_fsos(struct bview_set *s)
{
return s->i->free_scene_obj;
}
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8
+18 -85
View File
@@ -31,6 +31,7 @@
#include "bu/list.h"
#include "bu/log.h"
#include "bu/str.h"
#include "bv/objs.h"
#define PLOT3_IMPLEMENTATION
#include "bv/plot3.h"
#include "bv/vlist.h"
@@ -521,96 +522,28 @@ bv_plot_vlblock(FILE *fp, const struct bv_vlblock *vbp)
}
}
#define GET_BV_SCENE_OBJ(p, fp) { \
if (BU_LIST_IS_EMPTY(fp)) { \
BU_ALLOC((p), struct bv_scene_obj); \
} else { \
p = BU_LIST_NEXT(bv_scene_obj, fp); \
BU_LIST_DEQUEUE(&((p)->l)); \
} \
bu_vls_init(&(p)->s_name); \
(p)->s_path = NULL; \
BU_LIST_INIT( &((p)->s_vlist) ); }
#define FREE_BV_SCENE_OBJ(p, fp, vlf) { \
BU_LIST_APPEND(fp, &((p)->l)); \
BV_FREE_VLIST(vlf, &((p)->s_vlist)); }
void
bv_vlblock_to_objs(struct bu_ptbl *out, const char *name_root, struct bv_vlblock *vbp, struct bview *v, struct bv_scene_obj *f, struct bu_list *vlfree)
int
bv_vlblock_obj(struct bv_scene_obj *s, struct bv_vlblock *vbp)
{
if (!out || !vbp || !f)
return;
// Before we create new objects, check that the proposed names are
// not already used. If they are, we first remove the old versions
struct bu_ptbl oobjs = BU_PTBL_INIT_ZERO;
for (size_t i = 0; i < vbp->nused; i++) {
if (!BU_LIST_IS_EMPTY(&(vbp->head[i]))) {
struct bu_vls cname = BU_VLS_INIT_ZERO;
bu_vls_sprintf(&cname, "%sobj%zd", name_root, i);
for (size_t j = 0; j < BU_PTBL_LEN(out); j++) {
struct bv_scene_obj *s = (struct bv_scene_obj *)BU_PTBL_GET(out, j);
if (BU_STR_EQUAL(bu_vls_cstr(&cname), bu_vls_cstr(&s->s_name))) {
bu_ptbl_ins_unique(&oobjs, (long *)s);
}
}
}
}
for (size_t i = 0; i < BU_PTBL_LEN(&oobjs); i++) {
struct bv_scene_obj *s = (struct bv_scene_obj *)BU_PTBL_GET(&oobjs, i);
bu_ptbl_rm(out, (long *)s);
FREE_BV_SCENE_OBJ(s, &f->l, vlfree);
}
for (size_t i = 0; i < vbp->nused; i++) {
if (!BU_LIST_IS_EMPTY(&(vbp->head[i]))) {
struct bv_scene_obj *s;
GET_BV_SCENE_OBJ(s, &f->l);
s->s_type_flags = BV_VIEWONLY;
s->s_v = v;
bu_vls_sprintf(&s->s_name, "%sobj%zd", name_root, i);
struct bv_vlist *bvl = (struct bv_vlist *)&vbp->head[i];
long int rgb = vbp->rgb[i];
s->s_vlen = bv_vlist_cmd_cnt(bvl);
BU_LIST_APPEND_LIST(&(s->s_vlist), &(bvl->l));
BU_LIST_INIT(&(bvl->l));
s->s_color[0] = (rgb>>16);
s->s_color[1] = (rgb>>8);
s->s_color[2] = (rgb) & 0xFF;
bu_ptbl_ins(out, (long *)s);
}
}
}
struct bv_scene_obj *
bv_vlblock_obj(struct bv_vlblock *vbp, struct bview *v, const char *name)
{
if (!vbp || !v)
return NULL;
struct bv_scene_obj *s = bv_find_obj(v, name);
if (s) {
bv_obj_reset(s);
} else {
s = bv_obj_get(v, BV_VIEW_OBJS);
}
if (!s|| !vbp)
return BRLCAD_ERROR;
for (size_t i = 0; i < vbp->nused; i++) {
if (!BU_LIST_IS_EMPTY(&(vbp->head[i]))) {
struct bv_scene_obj *sc = bv_obj_get_child(s);
struct bv_vlist *bvl = (struct bv_vlist *)&vbp->head[i];
long int rgb = vbp->rgb[i];
sc->s_vlen = bv_vlist_cmd_cnt(bvl);
BU_LIST_APPEND_LIST(&(sc->s_vlist), &(bvl->l));
BU_LIST_INIT(&(bvl->l));
sc->s_color[0] = (rgb>>16);
sc->s_color[1] = (rgb>>8);
sc->s_color[2] = (rgb) & 0xFF;
bu_vls_sprintf(&sc->s_name, "%s_%d_%d_%d", name, V3ARGS(sc->s_color));
}
if (BU_LIST_IS_EMPTY(&(vbp->head[i])))
continue;
struct bv_scene_obj *sc = bv_obj_get_child(s);
struct bv_vlist *bvl = (struct bv_vlist *)&vbp->head[i];
long int rgb = vbp->rgb[i];
sc->s_vlen = bv_vlist_cmd_cnt(bvl);
BU_LIST_APPEND_LIST(&(sc->s_vlist), &(bvl->l));
BU_LIST_INIT(&(bvl->l));
sc->s_color[0] = (rgb>>16);
sc->s_color[1] = (rgb>>8);
sc->s_color[2] = (rgb) & 0xFF;
bu_vls_sprintf(&sc->s_name, "%s_%d_%d_%d", bu_vls_cstr(&s->s_name), V3ARGS(sc->s_color));
}
return s;
return BRLCAD_OK;
}
void
+83 -3
View File
@@ -37,6 +37,9 @@
#include "./include/private.h"
#include "./null/dm-Null.h"
extern void dm_add_arrows(struct dm *dmp, struct bv_scene_obj *s);
extern void dm_draw_label(struct dm *dmp, struct bv_scene_obj *s);
void *
dm_interp(struct dm *dmp)
{
@@ -627,12 +630,89 @@ dm_draw_vlist_hidden_line(struct dm *dmp, struct bv_vlist *vp)
return dmp->i->dm_drawVListHiddenLine(dmp, vp);
}
int
dm_draw_obj(struct dm *dmp, struct bv_scene_obj *s){
if (UNLIKELY(!dmp)) return -1;
return dmp->i->dm_draw_obj(dmp, s);
dm_draw_obj(struct dm *dmp, struct bv_scene_obj *s)
{
if (UNLIKELY(!dmp || !s)) return -1;
// If an object is turned off, we're not drawing it
if (s->s_flag == DOWN && !s->s_force_draw)
return 0;
// First, handle any object references
for (size_t i = 0; i < BU_PTBL_LEN(&s->obj_refs); i++) {
struct bv_scene_obj *o = (struct bv_scene_obj *)BU_PTBL_GET(&s->obj_refs, i);
struct bv_obj_settings *tmp_s_os = o->s_os;
o->s_os = (s->s_override_obj_ref_settings) ? s->s_os : o->s_os;
dm_draw_obj(dmp, o);
o->s_os = tmp_s_os;
}
// Coloring
if (s->s_iflag == UP) {
dm_set_fg(dmp, 255, 255, 255, 0, s->s_os->transparency);
} else {
if (s->s_os->color_override) {
dm_set_fg(dmp, s->s_os->color[0], s->s_os->color[1], s->s_os->color[2], 0, s->s_os->transparency);
} else {
dm_set_fg(dmp, s->s_color[0], s->s_color[1], s->s_color[2], 0, s->s_os->transparency);
}
}
// Line attributes
dm_set_line_attr(dmp, s->s_os->s_line_width, s->s_soldash);
// Primary object drawing.
int ret = dmp->i->dm_draw_obj(dmp, s);
// There are a few cases that have additional special drawing work we need
// to carry out.
if (!(s->s_type_flags & BV_MESH_LOD))
dm_add_arrows(dmp, s);
if (s->s_type_flags & BV_AXES)
dm_draw_scene_axes(dmp, s);
if (s->s_type_flags & BV_LABELS)
dm_draw_label(dmp, s);
// Handle any children (TODO - see if we need pre-and-post primary
// drawing options for children...)
for (size_t i = 0; i < BU_PTBL_LEN(&s->children); i++) {
struct bv_scene_obj *o = (struct bv_scene_obj *)BU_PTBL_GET(&s->children, i);
dm_draw_obj(dmp, o);
}
return ret;
}
int
dm_draw_sobj(void *vdmp, struct bv_scene_obj *s)
{
struct dm *dmp = (struct dm *)vdmp;
return dm_draw_obj(dmp, s);
}
int
dm_draw_view(void *vdmp, struct bview *v)
{
if (UNLIKELY(!vdmp || !v)) return -1;
struct dm *dmp = (struct dm *)vdmp;
/* Set up matrices for HUD drawing, rather than 3D scene drawing. */
(void)dm_hud_begin(dmp);
dm_draw_faceplate(v);
/* Restore non-HUD settings. */
(void)dm_hud_end(dmp);
return 0;
}
int
dm_draw_begin(struct dm *dmp)
{
+6 -6
View File
@@ -64,7 +64,7 @@ dlist_free_callback(struct bv_scene_obj *s)
// down the big mesh into smaller pieces as in the earlier LoD experiments in
// order to keep using display lists...
static int
gl_draw_tri(struct dm *dmp, struct bv_mesh_lod *lod)
gl_draw_tri(struct dm *dmp, struct bv_lod_mesh *lod)
{
int fcnt = lod->fcnt;
int pcnt = lod->pcnt;
@@ -97,10 +97,10 @@ gl_draw_tri(struct dm *dmp, struct bv_mesh_lod *lod)
// If we've had a memshrink, the loaded data isn't
// going to be correct to generate new draw info.
// First, find out the current level:
int curr_level = bv_mesh_lod_level(s, -1, 0);
int curr_level = bv_lod_level(s, -1, 0);
// Trigger a load operation to restore it
bv_mesh_lod_level(s, curr_level, 1);
bv_lod_level(s, curr_level, 1);
fcnt = lod->fcnt;
pcnt = lod->pcnt;
@@ -237,7 +237,7 @@ gl_draw_tri(struct dm *dmp, struct bv_mesh_lod *lod)
// If the original data is sizable, clear it to save system memory.
// The dlist has what it needs, and the LoD code will re-load info
// as needed for updates.
bv_mesh_lod_memshrink(s);
bv_lod_memshrink(s);
}
MAT_COPY(save_mat, s->s_v->gv_model2view);
@@ -344,7 +344,7 @@ gl_draw_tri(struct dm *dmp, struct bv_mesh_lod *lod)
// If the original data is sizable, clear it to save system memory.
// The dlist has what it needs, and the LoD code will re-load info
// as needed for updates.
bv_mesh_lod_memshrink(s);
bv_lod_memshrink(s);
}
MAT_COPY(save_mat, s->s_v->gv_model2view);
@@ -543,7 +543,7 @@ extern "C"
int gl_draw_obj(struct dm *dmp, struct bv_scene_obj *s)
{
if (s->s_type_flags & BV_MESH_LOD) {
struct bv_mesh_lod *lod = (struct bv_mesh_lod *)s->draw_data;
struct bv_lod_mesh *lod = (struct bv_lod_mesh *)s->draw_data;
return gl_draw_tri(dmp, lod);
}
+12 -8
View File
@@ -572,6 +572,7 @@ dm_draw_labels(struct dm *dmp, struct bv_data_label_state *gdlsp, matp_t m2vmat)
}
}
#if 0
static void
draw_scene_obj(struct dm *dmp, struct bv_scene_obj *s, struct bview *v, int force_draw, struct bv_obj_settings *obj_settings)
{
@@ -683,14 +684,14 @@ dm_draw_viewobjs(struct rt_wdb *wdbp, struct bview *v, struct dm_view_data *vd)
if (db_objs) {
for (size_t i = 0; i < BU_PTBL_LEN(db_objs); i++) {
struct bv_scene_group *g = (struct bv_scene_group *)BU_PTBL_GET(db_objs, i);
draw_scene_obj(dmp, g, v, g->s_force_draw, (g->s_inherit_settings) ? g->s_os : NULL);
draw_scene_obj(dmp, g, v, g->s_force_draw, (g->s_override_child_settings) ? g->s_os : NULL);
}
}
struct bu_ptbl *local_db_objs = bv_view_objs(v, BV_DB_OBJS | BV_LOCAL_OBJS);
if (local_db_objs) {
for (size_t i = 0; i < BU_PTBL_LEN(local_db_objs); i++) {
struct bv_scene_group *g = (struct bv_scene_group *)BU_PTBL_GET(local_db_objs, i);
draw_scene_obj(dmp, g, v, g->s_force_draw, (g->s_inherit_settings) ? g->s_os : NULL);
draw_scene_obj(dmp, g, v, g->s_force_draw, (g->s_override_child_settings) ? g->s_os : NULL);
}
}
@@ -699,14 +700,14 @@ dm_draw_viewobjs(struct rt_wdb *wdbp, struct bview *v, struct dm_view_data *vd)
if (view_objs) {
for (size_t i = 0; i < BU_PTBL_LEN(view_objs); i++) {
struct bv_scene_obj *s = (struct bv_scene_obj *)BU_PTBL_GET(view_objs, i);
draw_scene_obj(dmp, s, v, s->s_force_draw, (s->s_inherit_settings) ? s->s_os : NULL);
draw_scene_obj(dmp, s, v, s->s_force_draw, (s->s_override_child_settings) ? s->s_os : NULL);
}
}
struct bu_ptbl *local_view_objs = bv_view_objs(v, BV_VIEW_OBJS | BV_LOCAL_OBJS);
if (view_objs) {
for (size_t i = 0; i < BU_PTBL_LEN(local_view_objs); i++) {
struct bv_scene_obj *s = (struct bv_scene_obj *)BU_PTBL_GET(local_view_objs, i);
draw_scene_obj(dmp, s, v, s->s_force_draw, (s->s_inherit_settings) ? s->s_os : NULL);
draw_scene_obj(dmp, s, v, s->s_force_draw, (s->s_override_child_settings) ? s->s_os : NULL);
}
}
@@ -737,7 +738,9 @@ dm_draw_viewobjs(struct rt_wdb *wdbp, struct bview *v, struct dm_view_data *vd)
(void)dm_hud_end(dmp);
}
#endif
#if 0
// To allow completely custom modes like the sketch editor to be defined by
// applications in terms of libdm, we allow an optional callback that can be
// passed in to this function. If non-NULL, that function will be called in
@@ -805,7 +808,7 @@ dm_draw_objs(struct bview *v, void (*dm_draw_custom)(struct bview *, void *), vo
for (size_t i = 0; i < BU_PTBL_LEN(sobjs); i++) {
struct bv_scene_group *g = (struct bv_scene_group *)BU_PTBL_GET(sobjs, i);
//bu_log("dm_draw_objs %s\n", bu_vls_cstr(&g->s_name));
draw_scene_obj(dmp, g, v, g->s_force_draw, (g->s_inherit_settings) ? g->s_os : NULL);
draw_scene_obj(dmp, g, v, g->s_force_draw, (g->s_override_child_settings) ? g->s_os : NULL);
}
}
struct bu_ptbl *iobjs = bv_view_objs(v, BV_DB_OBJS | BV_LOCAL_OBJS);
@@ -813,7 +816,7 @@ dm_draw_objs(struct bview *v, void (*dm_draw_custom)(struct bview *, void *), vo
for (size_t i = 0; i < BU_PTBL_LEN(iobjs); i++) {
struct bv_scene_group *g = (struct bv_scene_group *)BU_PTBL_GET(iobjs, i);
//bu_log("dm_draw_objs(i) %s\n", bu_vls_cstr(&g->s_name));
draw_scene_obj(dmp, g, v, g->s_force_draw, (g->s_inherit_settings) ? g->s_os : NULL);
draw_scene_obj(dmp, g, v, g->s_force_draw, (g->s_override_child_settings) ? g->s_os : NULL);
}
}
@@ -822,14 +825,14 @@ dm_draw_objs(struct bview *v, void (*dm_draw_custom)(struct bview *, void *), vo
if (view_objs && !v->independent) {
for (size_t i = 0; i < BU_PTBL_LEN(view_objs); i++) {
struct bv_scene_obj *s = (struct bv_scene_obj *)BU_PTBL_GET(view_objs, i);
draw_scene_obj(dmp, s, v, s->s_force_draw, (s->s_inherit_settings) ? s->s_os : NULL);
draw_scene_obj(dmp, s, v, s->s_force_draw, (s->s_override_child_settings) ? s->s_os : NULL);
}
}
struct bu_ptbl *vo = bv_view_objs(v, BV_VIEW_OBJS | BV_LOCAL_OBJS);
if (vo && (vo != view_objs || v->independent)) {
for (size_t i = 0; i < BU_PTBL_LEN(vo); i++) {
struct bv_scene_obj *s = (struct bv_scene_obj *)BU_PTBL_GET(vo, i);
draw_scene_obj(dmp, s, v, s->s_force_draw, (s->s_inherit_settings) ? s->s_os : NULL);
draw_scene_obj(dmp, s, v, s->s_force_draw, (s->s_override_child_settings) ? s->s_os : NULL);
}
}
@@ -846,6 +849,7 @@ dm_draw_objs(struct bview *v, void (*dm_draw_custom)(struct bview *, void *), vo
/* Restore non-HUD settings. */
(void)dm_hud_end(dmp);
}
#endif
/*
* Local Variables:
+4
View File
@@ -302,6 +302,10 @@ set(
ged_init.cpp
columns.c
dbi_state.cpp
dbi2_state.cpp
dbi2_bview.cpp
dbi2_select.cpp
dcache.cpp
display_list.c
draw.cpp
ged.cpp
+1 -1
View File
@@ -38,7 +38,7 @@ set(
bot_face_fuse.c
bot_face_sort.c
bot_flip.c
bot_fuse.c
bot_fuse.cpp
bot_merge.c
bot_smooth.c
bot_split.c
+2 -3
View File
@@ -662,11 +662,10 @@ _bot_cmd_sync(void *bs, int argc, const char **argv)
static void
_bot_vlblock_plot(struct ged *gedp, struct bv_vlblock *vbp, const char *sname)
{
struct bview *view = gedp->ged_gvp;
if (gedp->new_cmd_forms) {
struct bu_vls nroot = BU_VLS_INIT_ZERO;
bu_vls_sprintf(&nroot, "bot::%s", sname);
bv_vlblock_obj(vbp, view, bu_vls_cstr(&nroot));
bu_vls_sprintf(&nroot, "ged::bot::%s", sname);
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, bu_vls_cstr(&nroot), vbp);
bu_vls_free(&nroot);
} else {
_ged_cvt_vlblock_to_solids(gedp, vbp, sname, 0);
@@ -1,4 +1,4 @@
/* B O T _ F U S E . C
/* B O T _ F U S E . C P P
* BRL-CAD
*
* Copyright (c) 2008-2025 United States Government as represented by
@@ -17,7 +17,7 @@
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file libged/bot_fuse.c
/** @file libged/bot_fuse.cpp
*
* The bot_fuse command.
*
@@ -129,9 +129,8 @@ show_dangling_edges(struct ged *gedp, const uint32_t *magic_p, const char *name,
/* Add overlay */
if (gedp->new_cmd_forms) {
struct bu_vls nroot = BU_VLS_INIT_ZERO;
bu_vls_sprintf(&nroot, "bot_fuse::%s", name);
struct bview *view = gedp->ged_gvp;
bv_vlblock_obj(vbp, view, bu_vls_cstr(&nroot));
bu_vls_sprintf(&nroot, "ged::bot_fuse::%s", name);
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, bu_vls_cstr(&nroot), vbp);
bu_vls_free(&nroot);
} else {
_ged_cvt_vlblock_to_solids(gedp, vbp, name, 0);
@@ -151,7 +150,7 @@ show_dangling_edges(struct ged *gedp, const uint32_t *magic_p, const char *name,
}
int
extern "C" int
ged_bot_fuse_core(struct ged *gedp, int argc, const char **argv)
{
struct directory *old_dp, *new_dp;
@@ -323,12 +322,11 @@ ged_bot_fuse_core(struct ged *gedp, int argc, const char **argv)
}
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8 cino=N-s
+2 -3
View File
@@ -289,9 +289,8 @@ draw_edges(struct ged *gedp, struct rt_bot_internal *bot, int num_edges, int edg
if (gedp->new_cmd_forms) {
struct bu_vls nroot = BU_VLS_INIT_ZERO;
bu_vls_sprintf(&nroot, "bot_check::%s", draw_name);
struct bview *view = gedp->ged_gvp;
bv_vlblock_obj(vbp, view, bu_vls_cstr(&nroot));
bu_vls_sprintf(&nroot, "ged::bot_check::%s", draw_name);
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, bu_vls_cstr(&nroot), vbp);
bu_vls_free(&nroot);
} else {
_ged_cvt_vlblock_to_solids(gedp, vbp, draw_name, 0);
+1 -2
View File
@@ -779,8 +779,7 @@ _brep_cmd_intersect(void *bs, int argc, const char **argv)
}
if (gedp->new_cmd_forms) {
struct bview *view = gedp->ged_gvp;
bv_vlblock_obj(gb->vbp, view, "brep_intersect");
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, "ged::brep_intersect", gb->vbp);
} else {
char namebuf[65];
_ged_cvt_vlblock_to_solids(gedp, gb->vbp, namebuf, 0);
+2 -3
View File
@@ -993,11 +993,10 @@ plot_nurbs_cv(struct bu_list *vlfree, struct bv_vlblock *vbp, int ucount, int vc
static void
_brep_vlblock_plot(struct ged *gedp, struct bv_vlblock *vbp, const char *sname)
{
struct bview *view = gedp->ged_gvp;
if (gedp->new_cmd_forms) {
struct bu_vls nroot = BU_VLS_INIT_ZERO;
bu_vls_sprintf(&nroot, "brep::%s", sname);
bv_vlblock_obj(vbp, view, bu_vls_cstr(&nroot));
bu_vls_sprintf(&nroot, "ged::brep::%s", sname);
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, bu_vls_cstr(&nroot), vbp);
bu_vls_free(&nroot);
} else {
_ged_cvt_vlblock_to_solids(gedp, vbp, sname, 0);
+1 -1
View File
@@ -9,7 +9,7 @@ set(
check_gap.c
check_mass.c
check_moments.c
check_overlaps.c
check_overlaps.cpp
check_surf_area.c
check_unconf_air.c
check_volume.c
@@ -1,4 +1,4 @@
/* C H E C K _ O V E R L A P S . C
/* C H E C K _ O V E R L A P S . C P P
* BRL-CAD
*
* Copyright (c) 2018-2025 United States Government as represented by
@@ -35,12 +35,32 @@ struct ged_check_plot {
struct overlap_list {
struct bu_list l;
char *reg1; /* overlapping region 1 */
char *reg2; /* overlapping region 2 */
struct bu_vls reg1; /* overlapping region 1 */
struct bu_vls reg2; /* overlapping region 2 */
size_t count; /* number of time reported */
double maxdepth; /* maximum overlap depth */
};
void
overlap_list_init(struct overlap_list *ol)
{
if (!ol)
return;
BU_LIST_INIT(&(ol->l));
bu_vls_init(&ol->reg1);
bu_vls_init(&ol->reg2);
ol->count = 0;
ol->maxdepth = 0;
}
void
overlap_list_free(struct overlap_list *ol)
{
bu_vls_free(&ol->reg1);
bu_vls_free(&ol->reg2);
if (BU_LIST_NON_EMPTY(&(ol->l)))
BU_LIST_DEQUEUE(&(ol->l));
}
struct overlaps_context {
struct overlap_list *overlapList;
@@ -84,9 +104,10 @@ check_log_overlaps(struct ged *gedp, const char *reg1, const char *reg2, double
*/
} else {
BU_GET(new_op, struct overlap_list);
overlap_list_init(new_op);
bu_semaphore_acquire(callbackdata->sem_stats);
for (BU_LIST_FOR(op, overlap_list, &(olist->l))) {
if ((BU_STR_EQUAL(reg1, op->reg1)) && (BU_STR_EQUAL(reg2, op->reg2))) {
if ((BU_STR_EQUAL(reg1, bu_vls_cstr(&op->reg1))) && (BU_STR_EQUAL(reg2, bu_vls_cstr(&op->reg2)))) {
op->count++;
if (depth > op->maxdepth)
op->maxdepth = depth;
@@ -98,7 +119,7 @@ check_log_overlaps(struct ged *gedp, const char *reg1, const char *reg2, double
for (BU_LIST_FOR(op, overlap_list, &(olist->l))) {
/* if this pair was seen in reverse, decrease the unique counter */
if ((BU_STR_EQUAL(reg1, op->reg2)) && (BU_STR_EQUAL(reg2, op->reg1))) {
if ((BU_STR_EQUAL(reg1, bu_vls_cstr(&op->reg2))) && (BU_STR_EQUAL(reg2, bu_vls_cstr(&op->reg1)))) {
callbackdata->unique_overlap_count--;
break;
}
@@ -107,10 +128,8 @@ check_log_overlaps(struct ged *gedp, const char *reg1, const char *reg2, double
/* we have a new overlapping region pair */
callbackdata->overlap_count++;
callbackdata->unique_overlap_count++;
new_op->reg1 = (char *)bu_malloc(strlen(reg1)+1, "reg1");
new_op->reg2 = (char *)bu_malloc(strlen(reg2)+1, "reg2");
bu_strlcpy(new_op->reg1, reg1, strlen(reg1)+1);
bu_strlcpy(new_op->reg2, reg2, strlen(reg2)+1);
bu_vls_sprintf(&new_op->reg1, "%s", reg1);
bu_vls_sprintf(&new_op->reg2, "%s", reg2);
new_op->maxdepth = depth;
new_op->count = 1;
BU_LIST_INSERT(&(olist->l), &(new_op->l));
@@ -144,12 +163,12 @@ printOverlaps(struct ged *gedp, void *context, struct check_parameters *options)
for (BU_LIST_FOR(op, overlap_list, &(olist->l))) {
for (BU_LIST_FOR_BACKWARDS(backop, overlap_list, &(op->l))) {
if ((BU_STR_EQUAL(op->reg2, backop->reg1)) && (BU_STR_EQUAL(op->reg1, backop->reg2))) break;
if ((BU_STR_EQUAL(bu_vls_cstr(&op->reg2), bu_vls_cstr(&backop->reg1))) && (BU_STR_EQUAL(bu_vls_cstr(&op->reg1), bu_vls_cstr(&backop->reg2)))) break;
if (BU_LIST_IS_HEAD(&(backop->l), &(olist->l))) break;
}
if (backop && BU_LIST_NOT_HEAD(&(backop->l), &(olist->l))) continue;
bu_vls_printf(&str, "%s and %s overlap\n", op->reg1, op->reg2);
bu_vls_printf(&str, "%s and %s overlap\n", bu_vls_cstr(&op->reg1), bu_vls_cstr(&op->reg2));
nextop = (struct overlap_list *)NULL;
/* if there are still matching pairs to search for */
@@ -158,7 +177,7 @@ printOverlaps(struct ged *gedp, void *context, struct check_parameters *options)
* reverse matching pair (done inside loop
* explicitly)*/
BU_LIST_TAIL(&(olist->l), op, nextop, struct overlap_list) {
if ((BU_STR_EQUAL(op->reg1, nextop->reg2)) && (BU_STR_EQUAL(op->reg2, nextop->reg1)))
if ((BU_STR_EQUAL(bu_vls_cstr(&op->reg1), bu_vls_cstr(&nextop->reg2))) && (BU_STR_EQUAL(bu_vls_cstr(&op->reg2), bu_vls_cstr(&nextop->reg1))))
break;
}
/* when we leave the loop, nextop is either
@@ -167,11 +186,11 @@ printOverlaps(struct ged *gedp, void *context, struct check_parameters *options)
}
bu_vls_printf(&str, "\t<%s, %s>: %zu overlap%c detected, maximum depth is %g %s\n",
op->reg1, op->reg2, op->count, op->count>1 ? 's' : (char) 0, op->maxdepth/options->units[LINE]->val, options->units[LINE]->name);
bu_vls_cstr(&op->reg1), bu_vls_cstr(&op->reg2), op->count, op->count>1 ? 's' : (char) 0, op->maxdepth/options->units[LINE]->val, options->units[LINE]->name);
if (nextop && BU_LIST_NOT_HEAD(nextop, &(olist->l))) {
bu_vls_printf(&str,
"\t<%s, %s>: %zu overlap%c detected, maximum depth is %g %s\n",
nextop->reg1, nextop->reg2, nextop->count,
bu_vls_cstr(&nextop->reg1), bu_vls_cstr(&nextop->reg2), nextop->count,
nextop->count > 1 ? 's' : (char)0, nextop->maxdepth/options->units[LINE]->val, options->units[LINE]->name);
/* counter the decrement below to account for
* the matched reverse pair
@@ -201,26 +220,26 @@ printOverlaps(struct ged *gedp, void *context, struct check_parameters *options)
for (BU_LIST_FOR(op, overlap_list, &(olist->l))) {
/* iterate over the list and see if we already printed this one */
for (BU_LIST_FOR_BACKWARDS(backop, overlap_list, &(op->l))) {
if ((BU_STR_EQUAL(op->reg1, backop->reg1)) || (BU_STR_EQUAL(op->reg1, backop->reg2)))
if ((BU_STR_EQUAL(bu_vls_cstr(&op->reg1), bu_vls_cstr(&backop->reg1))) || (BU_STR_EQUAL(bu_vls_cstr(&op->reg1), bu_vls_cstr(&backop->reg2))))
break;
if (BU_LIST_IS_HEAD(&(backop->l), &(olist->l))) break;
}
/* if we got to the head of the list (backop points to the match) */
if (BU_LIST_IS_HEAD(&(backop->l), &(olist->l))) {
bu_vls_printf(&str, "%s ", op->reg1);
bu_vls_printf(&str, "%s ", bu_vls_cstr(&op->reg1));
object_counter++;
}
/* iterate over the list again up to where we are to see if the second
* region was already printed */
for (BU_LIST_FOR_BACKWARDS(backop, overlap_list, &(op->l))) {
if ((BU_STR_EQUAL(op->reg2, backop->reg1)) || (BU_STR_EQUAL(op->reg2, backop->reg2)))
if ((BU_STR_EQUAL(bu_vls_cstr(&op->reg2), bu_vls_cstr(&backop->reg1))) || (BU_STR_EQUAL(bu_vls_cstr(&op->reg2), bu_vls_cstr(&backop->reg2))))
break;
if (BU_LIST_IS_HEAD(&(backop->l), &(olist->l))) break;
}
/* if we got to the head of the list (backop points to the match) */
if (BU_LIST_IS_HEAD(&(backop->l), &(olist->l))) {
bu_vls_printf(&str, "%s ", op->reg2);
bu_vls_printf(&str, "%s ", bu_vls_cstr(&op->reg2));
object_counter++;
}
}
@@ -287,20 +306,17 @@ int check_overlaps(struct ged *gedp, struct current_state *state,
struct bu_list *vlfree = &rt_vlfree;
FILE *plot_overlaps = NULL;
char *name = "overlaps.plot3";
const char *name = "overlaps.plot3";
int overlap_color[3] = { 255, 255, 0 }; /* yellow */
/* init overlaps list */
BU_LIST_INIT(&(overlapList.l));
overlapList.count = 0;
overlapList.reg1 = "";
overlapList.reg2 = "";
overlapList.maxdepth = 0;
overlap_list_init(&overlapList);
if (options->plot_files) {
plot_overlaps = fopen(name, "wb");
if (plot_overlaps == (FILE *)NULL) {
bu_vls_printf(gedp->ged_result_str, "cannot open plot file %s\n", name);
overlap_list_free(&overlapList);
return BRLCAD_ERROR;
}
}
@@ -327,12 +343,10 @@ int check_overlaps(struct ged *gedp, struct current_state *state,
if (perform_raytracing(state, dbip, tobjtab, tnobjs, ANALYSIS_OVERLAPS)) {
while (BU_LIST_WHILE(op, overlap_list, &(overlapList.l))){
bu_free(op->reg1, "reg1 name");
bu_free(op->reg2, "reg1 name");
BU_LIST_DEQUEUE(&(op->l));
overlap_list_free(op);
BU_PUT(op, struct overlap_list);
}
overlap_list_free(&overlapList);
return BRLCAD_ERROR;
}
@@ -342,8 +356,7 @@ int check_overlaps(struct ged *gedp, struct current_state *state,
if (options->overlaps_overlay_flag) {
if (gedp->new_cmd_forms) {
struct bview *view = gedp->ged_gvp;
bv_vlblock_obj(check_plot.vbp, view, "check::overlaps");
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, "ged::check::overlaps", check_plot.vbp);
} else {
_ged_cvt_vlblock_to_solids(gedp, check_plot.vbp, "OVERLAPS", 0);
}
@@ -356,22 +369,20 @@ int check_overlaps(struct ged *gedp, struct current_state *state,
}
while (BU_LIST_WHILE(op, overlap_list, &(overlapList.l))) {
bu_free(op->reg1, "reg1 name");
bu_free(op->reg2, "reg1 name");
BU_LIST_DEQUEUE(&(op->l));
overlap_list_free(op);
BU_PUT(op, struct overlap_list);
}
overlap_list_free(&overlapList);
return BRLCAD_OK;
}
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8 cino=N-s
-3
View File
@@ -61,9 +61,6 @@ ged_close_core(struct ged *gedp, int UNUSED(argc), const char **UNUSED(argv))
if (gedp->dbi_state)
delete (DbiState *)gedp->dbi_state;
gedp->dbi_state = NULL;
if (gedp->ged_lod)
bv_mesh_lod_context_destroy(gedp->ged_lod);
gedp->ged_lod = NULL;
/* Terminate any ged subprocesses */
for (size_t i = 0; i < BU_PTBL_LEN(&gedp->ged_subp); i++) {
+981 -273
View File
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+305
View File
@@ -0,0 +1,305 @@
/* D B I _ S E L E C T . C P P
* BRL-CAD
*
* Copyright (c) 1990-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @addtogroup ged_db*/
/** @{ */
/** @file libged/dbi_state.cpp
*
* Maintain and manage an in-memory representation of the database hierarchy.
* Main utility of this is to make commonly needed hierarchy/attribute
* information available to applications without having to crack combs from
* disk during a standard tree walk.
*/
#include "common.h"
#include <algorithm>
#include <map>
#include <thread>
#include <fstream>
#include <sstream>
extern "C" {
#include "lmdb.h"
}
#include "./alphanum.h"
#include "vmath.h"
#include "bu/app.h"
#include "bu/color.h"
#include "bu/hash.h"
#include "bu/path.h"
#include "bu/opt.h"
#include "bu/sort.h"
#include "bu/time.h"
#include "bv/lod.h"
#include "raytrace.h"
#include "ged/defines.h"
#include "ged/view.h"
#include "./ged_private.h"
// alphanum sort
static bool alphanum_cmp(const std::string &a, const std::string &b)
{
return alphanum_impl(a.c_str(), b.c_str(), NULL) < 0;
}
/* Handle selection status for various instances in the database */
BSelectState::BSelectState(DbiState *s)
{
dbis = s;
}
bool
BSelectState::Select(const char *path, bool update)
{
if (!path)
return false;
DbiPath *p = dbis->GetDbiPath(path);
if (!p)
return false;
return Select(p->hash(), update);
}
bool
BSelectState::Select(unsigned long long hash, bool update)
{
if (!hash)
return false;
// To select a path by hash, we need the Dbi state to
// be able to decode it for us.
DbiPath *p = dbis->GetDbiPath(hash);
if (!p)
return false;
// If we're going to select this path, we need to clear out conflicting
// paths. We deliberately don't allow selection of multiple levels of a
// single path, to avoid unexpected and unintuitive behaviors. This means
// we have to clear any selection that is either a superset of this path or
// a child of it.
dbis->RemovePathsBelow(&selected, hash);
std::unordered_set<unsigned long long>::iterator p_it;
for (p_it = p->parent_path_hashes.begin(); p_it != p->parent_path_hashes.end(); ++p_it) {
selected.erase(*p_it);
}
// Add to selected set
selected.insert(hash);
// If we're not updating the other sets, we're done
if (!update)
return true;
// We are updating - process the sets
characterize();
return true;
}
bool
BSelectState::DeSelect(const char *path, bool update)
{
if (!path)
return false;
DbiPath *p = dbis->GetDbiPath(path);
if (!p)
return false;
return DeSelect(p->hash(), update);
}
bool
BSelectState::DeSelect(unsigned long long hash, bool update)
{
// Don't bother with any checking - valid or not, hash is out of the set
selected.erase(hash);
// If we're not updating, that's all
if (!update)
return true;
// We are updating - process the sets
characterize();
return true;
}
bool
BSelectState::IsSelected(unsigned long long hash)
{
if (!hash)
return false;
if (selected.find(hash) != selected.end())
return true;
return false;
}
bool
BSelectState::IsActivated(unsigned long long hash)
{
if (!hash)
return false;
if (children.find(hash) != children.end())
return true;
return false;
}
bool
BSelectState::IsActiveParent(unsigned long long hash)
{
if (!hash)
return false;
if (immediate_parents.find(hash) != immediate_parents.end())
return true;
return false;
}
bool
BSelectState::IsActiveAncestor(unsigned long long hash)
{
if (!hash)
return false;
if (ancestors.find(hash) != ancestors.end())
return true;
return false;
}
void
BSelectState::Clear()
{
selected.clear();
children.clear();
immediate_parents.clear();
ancestors.clear();
}
std::vector<std::string>
BSelectState::FindSelectedPaths(const char *pattern)
{
std::vector<std::string> ret;
std::unordered_set<unsigned long long>::iterator s_it;
for (s_it = selected.begin(); s_it != selected.end(); s_it++) {
DbiPath *p = dbis->GetDbiPath(*s_it);
if (!p)
continue;
std::string pstr = p->str();
if (!pattern || !strlen(pattern) || !bu_path_match(pattern, pstr.c_str(), 0))
ret.push_back(p->str());
}
std::sort(ret.begin(), ret.end(), &alphanum_cmp);
return ret;
}
void
BSelectState::characterize()
{
children.clear();
immediate_parents.clear();
ancestors.clear();
std::unordered_set<unsigned long long>::iterator s_it;
for (s_it = selected.begin(); s_it != selected.end(); ++s_it) {
DbiPath *p = dbis->GetDbiPath(*s_it);
if (!p)
continue;
dbis->AddPathsBelow(&children, *s_it);
immediate_parents.insert(p->parent_hash);
std::unordered_set<unsigned long long>::iterator pp_it;
for (pp_it = p->parent_path_hashes.begin(); pp_it != p->parent_path_hashes.end(); ++pp_it) {
if (*pp_it == p->parent_hash)
continue;
ancestors.insert(*pp_it);
}
}
}
void
BSelectState::Sync()
{
#if 0
std::unordered_set<BViewState *> vstates;
struct bu_ptbl *views = bv_set_views(&dbis->gedp->ged_views);
for (size_t i = 0; i < BU_PTBL_LEN(views); i++) {
struct bview *v = (struct bview *)BU_PTBL_GET(views, i);
BViewState *vs = dbis->get_view_state(v);
vstates.insert(vs);
}
std::unordered_map<unsigned long long, std::unordered_map<int, struct bv_scene_obj *>>::iterator so_it;
std::unordered_map<int, struct bv_scene_obj *>::iterator m_it;
std::unordered_set<BViewState *>::iterator vs_it;
for (vs_it = vstates.begin(); vs_it != vstates.end(); vs_it++) {
for (so_it = (*vs_it)->s_map.begin(); so_it != (*vs_it)->s_map.end(); so_it++) {
char ill_state = is_active(so_it->first) ? UP : DOWN;
//bu_log("select ill_state: %s\n", (ill_state == UP) ? "up" : "down");
for (m_it = so_it->second.begin(); m_it != so_it->second.end(); m_it++) {
struct bv_scene_obj *so = m_it->second;
int ill_changed = bv_illum_obj(so, ill_state);
if (ill_changed)
changed = true;
}
}
}
#endif
}
unsigned long long
BSelectState::state_hash()
{
std::unordered_set<unsigned long long>::iterator s_it;
struct bu_data_hash_state *s = bu_data_hash_create();
if (!s)
return 0;
for (s_it = selected.begin(); s_it != selected.end(); s_it++) {
unsigned long long phash = *s_it;
bu_data_hash_update(s, &phash, sizeof(unsigned long long));
}
unsigned long long hval = bu_data_hash_val(s);
bu_data_hash_destroy(s);
return hval;
}
/** @} */
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8
File diff suppressed because it is too large Load Diff
+769 -3246
View File
File diff suppressed because it is too large Load Diff
+166
View File
@@ -0,0 +1,166 @@
/* D C A C H E . C P P
* BRL-CAD
*
* Copyright (c) 1990-2025 United States Government as represented by
* the U.S. Army Research Laboratory.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License
* version 2.1 as published by the Free Software Foundation.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this file; see the file named COPYING for more
* information.
*/
/** @addtogroup ged_db*/
/** @{ */
/** @file libged/dcache.cpp
*
* Manage cached drawing data.
*/
#include "common.h"
#include <algorithm>
#include <map>
#include <thread>
#include <fstream>
#include <sstream>
extern "C" {
#include "lmdb.h"
}
#include "./alphanum.h"
#include "vmath.h"
#include "bu/app.h"
#include "bu/color.h"
#include "bu/hash.h"
#include "bu/path.h"
#include "bu/opt.h"
#include "bu/sort.h"
#include "bu/time.h"
#include "bv/lod.h"
#include "raytrace.h"
#include "ged/defines.h"
#include "ged/view.h"
#include "./ged_private.h"
// Subdirectory in BRL-CAD cache to Dbi state data
#define DBI_CACHEDIR ".Dbi"
// Maximum database size.
#define CACHE_MAX_DB_SIZE 4294967296
// Define what format of the cache is current - if it doesn't match, we need
// to wipe and redo.
#define CACHE_CURRENT_FORMAT 3
struct bu_cache *
dbi_cache_open(const char *name)
{
struct bu_cache *c = NULL;
// Hash the input filename to generate a key for uniqueness - the base name
// of the specified .g file may not be unique on the filesystem, but by
// definition the full path to the file is.
struct bu_vls fname = BU_VLS_INIT_ZERO;
bu_vls_sprintf(&fname, "%s", bu_path_normalize(name));
unsigned long long hash = bu_data_hash(bu_vls_cstr(&fname), bu_vls_strlen(&fname)*sizeof(char));
// Get the basename and add the hash
struct bu_vls bname = BU_VLS_INIT_ZERO;
bu_path_component(&bname, bu_path_normalize(name), BU_PATH_BASENAME_EXTLESS);
bu_vls_sprintf(&fname, "%s_%llu", bu_vls_cstr(&bname), hash);
bu_vls_free(&bname);
char crelpath[MAXPATHLEN];
bu_dir(crelpath, MAXPATHLEN, DBI_CACHEDIR, bu_vls_cstr(&fname), NULL);
bu_vls_free(&fname);
// See if we have a pre-existing format in place - if we do, and it is too old,
// clear the old cache
char dir[MAXPATHLEN];
bu_dir(dir, MAXPATHLEN, BU_DIR_CACHE, DBI_CACHEDIR, "format", NULL);
if (bu_file_exists(dir, NULL)) {
std::ifstream format_file(dir);
size_t disk_format_version = 0;
format_file >> disk_format_version;
format_file.close();
if (disk_format_version != CACHE_CURRENT_FORMAT) {
bu_log("Old GED drawing info cache (%zd) found - clearing\n", disk_format_version);
bu_cache_erase(bu_vls_cstr(&fname));
}
}
// Open the cache, creating it if it doesn't already exist
c = bu_cache_open(crelpath, 1, 0);
if (!c)
return NULL;
// Make sure our identification of the cache on-disk format is current.
if (c) {
FILE *fp = fopen(dir, "w");
if (fp) {
fprintf(fp, "%d\n", CACHE_CURRENT_FORMAT);
fclose(fp);
}
}
// Success - return the context
return c;
}
size_t
cache_get(struct bu_cache *c, void **data, unsigned long long hash, const char *component)
{
if (!c || !data || hash == 0 || !component)
return 0;
// Construct lookup key
std::string keystr = std::to_string(hash) + std::string(":") + std::string(component);
return bu_cache_get(data, keystr.c_str(), c);
}
void
cache_write(struct bu_cache *c, unsigned long long hash, const char *component, std::stringstream &s)
{
if (!c || hash == 0 || !component)
return;
// Prepare inputs for writing
std::string keystr = std::to_string(hash) + std::string(":") + std::string(component);
std::string buffer = s.str();
bu_cache_write(buffer.data(), buffer.length()*sizeof(char), keystr.c_str(), c);
}
void
cache_del(struct bu_cache *c, unsigned long long hash, const char *component)
{
if (!c || hash == 0 || !component)
return;
// Construct lookup key
std::string keystr = std::to_string(hash) + std::string(":") + std::string(component);
bu_cache_clear(keystr.c_str(), c);
}
/** @} */
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8
+9 -22
View File
@@ -232,8 +232,6 @@ dl_erasePathFromDisplay(struct ged *gedp, const char *path, int allow_split)
struct directory *dp;
struct db_full_path subpath;
int found_subpath;
struct bv_scene_obj *free_scene_obj = bv_set_fsos(&gedp->ged_views);
struct bu_list *vlfree = &rt_vlfree;
if (db_string_to_path(&subpath, dbip, path) == 0)
found_subpath = 1;
@@ -266,8 +264,7 @@ dl_erasePathFromDisplay(struct ged *gedp, const char *path, int allow_split)
(void)db_dirdelete(dbip, dp);
}
BU_LIST_DEQUEUE(&sp->l);
FREE_BV_SCENE_OBJ(sp, &free_scene_obj->l, vlfree);
bv_obj_put(sp);
}
}
@@ -291,8 +288,7 @@ dl_erasePathFromDisplay(struct ged *gedp, const char *path, int allow_split)
if (db_full_path_match_top(&subpath, &bdata->s_fullpath)) {
ged_destroy_vlist_cb(gedp, sp->s_dlist, 1);
BU_LIST_DEQUEUE(&sp->l);
FREE_BV_SCENE_OBJ(sp, &free_scene_obj->l, vlfree);
bv_obj_put(sp);
need_split = 1;
}
@@ -330,11 +326,10 @@ dl_erasePathFromDisplay(struct ged *gedp, const char *path, int allow_split)
static void
eraseAllSubpathsFromSolidList(struct ged *gedp, struct display_list *gdlp,
struct db_full_path *subpath,
const int skip_first, struct bu_list *vlfree)
const int skip_first)
{
struct bv_scene_obj *sp;
struct bv_scene_obj *nsp;
struct bv_scene_obj *free_scene_obj = bv_set_fsos(&gedp->ged_views);
sp = BU_LIST_NEXT(bv_scene_obj, &gdlp->dl_head_scene_obj);
while (BU_LIST_NOT_HEAD(sp, &gdlp->dl_head_scene_obj)) {
@@ -344,8 +339,7 @@ eraseAllSubpathsFromSolidList(struct ged *gedp, struct display_list *gdlp,
nsp = BU_LIST_PNEXT(bv_scene_obj, sp);
if (db_full_path_subset(&bdata->s_fullpath, subpath, skip_first)) {
ged_destroy_vlist_cb(gedp, sp->s_dlist, 1);
BU_LIST_DEQUEUE(&sp->l);
FREE_BV_SCENE_OBJ(sp, &free_scene_obj->l, vlfree);
bv_obj_put(sp);
}
sp = nsp;
}
@@ -366,7 +360,6 @@ _dl_eraseAllNamesFromDisplay(struct ged *gedp, const char *name, const int skip
struct db_i *dbip = gedp->dbip;
struct display_list *gdlp;
struct display_list *next_gdlp;
struct bu_list *vlfree = &rt_vlfree;
gdlp = BU_LIST_NEXT(display_list, hdlp);
while (BU_LIST_NOT_HEAD(gdlp, hdlp)) {
@@ -404,7 +397,7 @@ _dl_eraseAllNamesFromDisplay(struct ged *gedp, const char *name, const int skip
struct db_full_path subpath;
if (db_string_to_path(&subpath, dbip, name) == 0) {
eraseAllSubpathsFromSolidList(gedp, gdlp, &subpath, skip_first, vlfree);
eraseAllSubpathsFromSolidList(gedp, gdlp, &subpath, skip_first);
db_free_full_path(&subpath);
}
}
@@ -423,11 +416,9 @@ _dl_eraseFirstSubpath(struct ged *gedp,
{
struct bu_list *hdlp = gedp->i->ged_gdp->gd_headDisplay;
struct db_i *dbip = gedp->dbip;
struct bv_scene_obj *free_scene_obj = bv_set_fsos(&gedp->ged_views);
struct bv_scene_obj *sp;
struct bv_scene_obj *nsp;
struct db_full_path dup_path;
struct bu_list *vlfree = &rt_vlfree;
db_full_path_init(&dup_path);
@@ -447,8 +438,7 @@ _dl_eraseFirstSubpath(struct ged *gedp,
bdata->s_fullpath.fp_len = full_len - 1;
db_dup_full_path(&dup_path, &bdata->s_fullpath);
bdata->s_fullpath.fp_len = full_len;
BU_LIST_DEQUEUE(&sp->l);
FREE_BV_SCENE_OBJ(sp, &free_scene_obj->l, vlfree);
bv_obj_put(sp);
BU_LIST_DEQUEUE(&gdlp->l);
@@ -528,10 +518,8 @@ void
_dl_freeDisplayListItem (struct ged *gedp, struct display_list *gdlp)
{
struct db_i *dbip = gedp->dbip;
struct bv_scene_obj *free_scene_obj = bv_set_fsos(&gedp->ged_views);
struct bv_scene_obj *sp;
struct directory *dp;
struct bu_list *vlfree = &rt_vlfree;
if (gedp->ged_destroy_vlist_callback != GED_DESTROY_VLIST_FUNC_NULL) {
@@ -553,8 +541,7 @@ _dl_freeDisplayListItem (struct ged *gedp, struct display_list *gdlp)
(void)db_dirdelete(dbip, dp);
}
BU_LIST_DEQUEUE(&sp->l);
FREE_BV_SCENE_OBJ(sp, &free_scene_obj->l, vlfree);
bv_obj_put(sp);
}
}
@@ -688,7 +675,7 @@ int invent_solid(struct ged *gedp, char *name, struct bu_list *vhead, long int r
}
/* Obtain a fresh solid structure, and fill it in */
sp = bv_obj_get(gedp->ged_gvp, BV_DB_OBJS);
sp = bv_obj_get(gedp->free_scene_objs);
struct ged_bv_data *bdata = (sp->s_u_data) ? (struct ged_bv_data *)sp->s_u_data : NULL;
if (!bdata) {
BU_GET(bdata, struct ged_bv_data);
@@ -709,7 +696,7 @@ int invent_solid(struct ged *gedp, char *name, struct bu_list *vhead, long int r
solid_append_vlist(sp, (struct bv_vlist *)vhead);
BU_LIST_INIT(vhead);
}
bv_scene_obj_bound(sp, gedp->ged_gvp);
bv_obj_bound(sp);
/* set path information -- this is a top level node */
db_add_node_to_full_path(&bdata->s_fullpath, dp);
+7 -7
View File
@@ -82,7 +82,7 @@ _dm_name_lookup(struct _ged_dm_info *gd, const char *dm_name)
}
struct ged *gedp = gd->gedp;
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
struct bu_ptbl *views = &gedp->ged_views;
if (!BU_PTBL_LEN(views)) {
bu_vls_printf(gedp->ged_result_str, ": no views defined in GED\n");
return NULL;
@@ -311,7 +311,7 @@ _dm_cmd_list(void *ds, int argc, const char **argv)
}
}
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
struct bu_ptbl *views = &gedp->ged_views;
if (!BU_PTBL_LEN(views) && !cdmp) {
bu_vls_printf(gedp->ged_result_str, ": no views defined in GED\n");
return BRLCAD_ERROR;
@@ -499,7 +499,7 @@ _dm_cmd_attach(void *ds, int argc, const char **argv)
// No name - generate one
bu_vls_sprintf(&dm_name, "%s-0", argv[0]);
int exists = 0;
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
struct bu_ptbl *views = &gedp->ged_views;
for (size_t i = 0; i < BU_PTBL_LEN(views); i++) {
struct bview *gdvp = (struct bview *)BU_PTBL_GET(views, i);
struct dm *ndmp = (struct dm *)gdvp->dmp;
@@ -544,7 +544,7 @@ _dm_cmd_attach(void *ds, int argc, const char **argv)
}
// Have name - see if it already exists
int exists = 0;
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
struct bu_ptbl *views = &gedp->ged_views;
for (size_t i = 0; i < BU_PTBL_LEN(views); i++) {
struct bview *gdvp = (struct bview *)BU_PTBL_GET(views, i);
struct dm *ndmp = (struct dm *)gdvp->dmp;
@@ -565,7 +565,7 @@ _dm_cmd_attach(void *ds, int argc, const char **argv)
struct bview *target_view = NULL;
if (bu_vls_strlen(&view_name)) {
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
struct bu_ptbl *views = &gedp->ged_views;
for (size_t i = 0; i < BU_PTBL_LEN(views); i++) {
struct bview *tview = (struct bview *)BU_PTBL_GET(views, i);
if (!bu_vls_strcmp(&view_name, &tview->gv_name)) {
@@ -579,8 +579,8 @@ _dm_cmd_attach(void *ds, int argc, const char **argv)
if (!target_view) {
BU_GET(target_view, struct bview);
bv_init(target_view, &gedp->ged_views);
bv_set_add_view(&gedp->ged_views, target_view);
bv_init(target_view);
bu_ptbl_ins(&gedp->ged_views, (long *)target_view);
// This view is being created by GED, so it needs to be cleaned
// up by GED as well
bu_ptbl_ins(&gedp->ged_free_views, (long *)target_view);
+1 -1
View File
@@ -102,7 +102,7 @@ ged_screen_grab_core(struct ged *gedp, int argc, const char *argv[])
if (bu_vls_strlen(&dm_name) && gedp->ged_gvp) {
// We have a name - see if we can match it.
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
struct bu_ptbl *views = &gedp->ged_views;
for (size_t j = 0; j < BU_PTBL_LEN(views); j++) {
if (dmp)
break;
+8 -672
View File
@@ -48,6 +48,7 @@
#include "ged/view.h"
#include "./ged_private.h"
#if 0
static int
prim_tess(struct bv_scene_obj *s, struct rt_db_internal *ip)
{
@@ -80,29 +81,9 @@ prim_tess(struct bv_scene_obj *s, struct rt_db_internal *ip)
return 0;
}
#endif
static void
draw_free_data(struct bv_scene_obj *s)
{
/* Validate */
if (!s)
return;
if (s->s_path) {
struct db_full_path *sfp = (struct db_full_path *)s->s_path;
db_free_full_path(sfp);
BU_PUT(sfp, struct db_full_path);
}
/* free drawing info */
struct draw_update_data_t *d = (struct draw_update_data_t *)s->s_i_data;
if (!d)
return;
BU_PUT(d, struct draw_update_data_t);
s->s_i_data = NULL;
}
#if 0
static int
csg_wireframe_update(struct bv_scene_obj *vo, struct bview *v, int flag)
{
@@ -175,214 +156,9 @@ csg_wireframe_update(struct bv_scene_obj *vo, struct bview *v, int flag)
return 1;
}
#endif
struct ged_full_detail_clbk_data {
struct db_i *dbip;
struct directory *dp;
struct resource *res;
struct rt_db_internal *intern;
};
/* Set up the data for drawing */
static int
bot_mesh_info_clbk(struct bv_mesh_lod *lod, void *cb_data)
{
if (!lod || !cb_data)
return -1;
struct ged_full_detail_clbk_data *cd = (struct ged_full_detail_clbk_data *)cb_data;
struct db_i *dbip = cd->dbip;
struct directory *dp = cd->dp;
BU_GET(cd->intern, struct rt_db_internal);
RT_DB_INTERNAL_INIT(cd->intern);
struct rt_db_internal *ip = cd->intern;
int ret = rt_db_get_internal(ip, dp, dbip, NULL, cd->res);
if (ret < 0) {
BU_PUT(cd->intern, struct rt_db_internal);
return -1;
}
struct rt_bot_internal *bot = (struct rt_bot_internal *)ip->idb_ptr;
RT_BOT_CK_MAGIC(bot);
lod->faces = bot->faces;
lod->fcnt = bot->num_faces;
lod->pcnt = bot->num_vertices;
lod->points = (const point_t *)bot->vertices;
lod->points_orig = (const point_t *)bot->vertices;
return 0;
}
/* Free up the drawing data, but not (yet) done with ged_full_detail_clbk_data */
static int
bot_mesh_info_clear_clbk(struct bv_mesh_lod *lod, void *cb_data)
{
struct ged_full_detail_clbk_data *cd = (struct ged_full_detail_clbk_data *)cb_data;
if (cd->intern) {
rt_db_free_internal(cd->intern);
BU_PUT(cd->intern, struct rt_db_internal);
}
cd->intern = NULL;
lod->faces = NULL;
lod->fcnt = 0;
lod->pcnt = 0;
lod->points = NULL;
lod->points_orig = NULL;
return 0;
}
/* Done - free up everything */
static int
bot_mesh_info_free_clbk(struct bv_mesh_lod *lod, void *cb_data)
{
bot_mesh_info_clear_clbk(lod, cb_data);
struct ged_full_detail_clbk_data *cd = (struct ged_full_detail_clbk_data *)cb_data;
BU_PUT(cd, struct ged_full_detail_clbk_data);
return 0;
}
static void
bot_adaptive_plot(struct bv_scene_obj *s, struct bview *v)
{
if (!s || !v)
return;
s->csg_obj = 0;
s->mesh_obj = 1;
bv_log(1, "bot_adaptive_plot %s[%s]", bu_vls_cstr(&s->s_name), (v) ? bu_vls_cstr(&v->gv_name) : "NULL");
struct bv_scene_obj *vo = bv_obj_for_view(s, v);
if (!vo) {
vo = bv_obj_get_vo(s, v);
vo->csg_obj = 0;
vo->mesh_obj = 1;
struct draw_update_data_t *d = (struct draw_update_data_t *)s->s_i_data;
if (!d || !d->mesh_c)
return;
struct db_i *dbip = d->dbip;
struct db_full_path *fp = (struct db_full_path *)s->s_path;
struct directory *dp = (fp) ? DB_FULL_PATH_CUR_DIR(fp) : (struct directory *)s->dp;
if (!dp)
return;
// We need the key to look up the LoD data from the cache, and if we don't
// already have cache data for this bot we need to generate it.
unsigned long long key = bv_mesh_lod_key_get(d->mesh_c, dp->d_namep);
if (!key) {
// We don't have a key associated with the name. Get and check the BoT
// data itself, creating the LoD data if we don't already have it
struct rt_db_internal dbintern;
RT_DB_INTERNAL_INIT(&dbintern);
struct rt_db_internal *ip = &dbintern;
int ret = rt_db_get_internal(ip, dp, dbip, NULL, d->res);
if (ret < 0)
return;
struct rt_bot_internal *bot = (struct rt_bot_internal *)ip->idb_ptr;
RT_BOT_CK_MAGIC(bot);
key = bv_mesh_lod_cache(d->mesh_c, (const point_t *)bot->vertices, bot->num_vertices, NULL, bot->faces, bot->num_faces, 0, 0.66);
bv_mesh_lod_key_put(d->mesh_c, dp->d_namep, key);
rt_db_free_internal(&dbintern);
}
if (!key)
return;
// Once we have a valid key, proceed to create the necessary
// data structures and objects.
struct bv_mesh_lod *lod = bv_mesh_lod_create(d->mesh_c, key);
if (!lod) {
// Stale key? Clear it and try a regeneration
unsigned long long old_key = key;
bv_mesh_lod_clear_cache(d->mesh_c, key);
// Load mesh and process
struct rt_db_internal dbintern;
RT_DB_INTERNAL_INIT(&dbintern);
struct rt_db_internal *ip = &dbintern;
int ret = rt_db_get_internal(ip, dp, dbip, NULL, d->res);
if (ret < 0)
return;
struct rt_bot_internal *bot = (struct rt_bot_internal *)ip->idb_ptr;
RT_BOT_CK_MAGIC(bot);
key = bv_mesh_lod_cache(d->mesh_c, (const point_t *)bot->vertices, bot->num_vertices, NULL, bot->faces, bot->num_faces, 0, 0.66);
bv_mesh_lod_key_put(d->mesh_c, dp->d_namep, key);
rt_db_free_internal(&dbintern);
// Sanity
if (old_key == key) {
bu_log("%s: LoD lookup by key failed, but regeneration generated the same key (?)\n", dp->d_namep);
return;
}
unsigned long long new_key = bv_mesh_lod_key_get(d->mesh_c, dp->d_namep);
if (new_key == old_key) {
bu_log("%s: LoD regenerated with new key, but key lookup still returns old key (?)\n", dp->d_namep);
return;
}
// If after all that we STILL don't get an LoD struct, give up
lod = bv_mesh_lod_create(d->mesh_c, key);
if (!lod)
return;
}
// Assign the LoD information to the object's draw_data, and let
// the LoD know which object it is associated with.
vo->draw_data = (void *)lod;
lod->s = vo;
// The object bounds are based on the LoD's calculations. Because the LoD
// cache stores only one cached data set per object, but full path
// instances in the scene can be placed with matrices, we must apply the
// s_mat transformation to the "baseline" LoD bbox info to get the correct
// box for the instance.
MAT4X3PNT(vo->bmin, s->s_mat, lod->bmin);
MAT4X3PNT(vo->bmax, s->s_mat, lod->bmax);
VMOVE(s->bmin, vo->bmin);
VMOVE(s->bmax, vo->bmax);
// Record the necessary information for full detail information recovery. We
// don't duplicate the full mesh detail in the on-disk LoD storage, since we
// already have that info in the .g itself, but we need to know how to get at
// it when needed. The free callback will clean up, but we need to initialize
// the callback data here.
struct ged_full_detail_clbk_data *cbd;
BU_GET(cbd, ged_full_detail_clbk_data);
cbd->dbip = dbip;
cbd->dp = dp;
cbd->res = &rt_uniresource;
cbd->intern = NULL;
bv_mesh_lod_detail_setup_clbk(lod, &bot_mesh_info_clbk, (void *)cbd);
bv_mesh_lod_detail_clear_clbk(lod, &bot_mesh_info_clear_clbk);
bv_mesh_lod_detail_free_clbk(lod, &bot_mesh_info_free_clbk);
// LoD will need to re-check its level settings whenever the view changes
vo->s_update_callback = &bv_mesh_lod_view;
vo->s_free_callback = &bv_mesh_lod_free;
// Initialize the LoD data to the current view
int level = bv_mesh_lod_view(vo, vo->s_v, 0);
if (level < 0) {
bu_log("Error loading info for initial LoD view\n");
}
// Mark the object as a Mesh LoD so the drawing routine knows to handle it differently
vo->s_type_flags |= BV_MESH_LOD;
}
bv_mesh_lod_view(vo, v, 0);
bv_obj_stale(vo);
return;
}
#if 0
static void
brep_adaptive_plot(struct bv_scene_obj *s, struct bview *v)
{
@@ -530,263 +306,11 @@ brep_adaptive_plot(struct bv_scene_obj *s, struct bview *v)
bv_mesh_lod_view(vo, vo->s_v, 0);
bv_obj_stale(vo);
return;
}
#endif
/* Wrapper to handle adaptive vs non-adaptive wireframes */
static void
wireframe_plot(struct bv_scene_obj *s, struct bview *v, struct rt_db_internal *ip)
{
bv_log(1, "wireframe_plot %s[%s]", bu_vls_cstr(&s->s_name), (v) ? bu_vls_cstr(&v->gv_name) : "NULL");
struct draw_update_data_t *d = (struct draw_update_data_t *)s->s_i_data;
const struct bn_tol *tol = d->tol;
const struct bg_tess_tol *ttol = d->ttol;
s->csg_obj = 1;
s->mesh_obj = 0;
// Standard (view independent) wireframe
if (!v || !v->gv_s->adaptive_plot_csg) {
if (ip->idb_meth->ft_plot) {
ip->idb_meth->ft_plot(&s->s_vlist, ip, ttol, tol, s->s_v);
// Because this data is view independent, it only needs to be
// generated once rather than per-view.
s->current = 1;
}
return;
}
// If we're adaptive, call the primitive's adaptive plotting, if any.
if (ip->idb_meth->ft_adaptive_plot) {
struct bv_scene_obj *vo = bv_obj_for_view(s, v);
if (!vo) {
vo = bv_obj_get_vo(s, v);
// Make a copy of the draw info for vo.
struct draw_update_data_t *ld;
BU_GET(ld, struct draw_update_data_t);
ld->fp = (struct db_full_path *)s->s_path;
ld->dbip = d->dbip;
ld->tol = d->tol;
ld->ttol = d->ttol;
ld->mesh_c = d->mesh_c;
ld->res = d->res;
vo->s_i_data= (void *)ld;
// We're adaptive - have to plot when the view changes. Set the
// callbacks
vo->s_update_callback = &csg_wireframe_update;
vo->s_free_callback = &draw_free_data;
// Mark type as CSG LoD
vo->s_type_flags |= BV_CSG_LOD;
}
csg_wireframe_update(vo, v, 1);
return;
}
// If we've got this far, we have no adaptive plotting capability for this
// object. Do the normal plot rather than show nothing.
if (ip->idb_meth->ft_plot) {
ip->idb_meth->ft_plot(&s->s_vlist, ip, ttol, tol, s->s_v);
// Because this data is view independent, it only needs to be
// generated once rather than per-view.
s->current = 1;
}
}
extern "C" int draw_m3(struct bv_scene_obj *s);
extern "C" int draw_points(struct bv_scene_obj *s);
/* This function is the master controller that decides, based on available settings
* and data, which specific drawing routines need to be triggered. */
extern "C" void
draw_scene(struct bv_scene_obj *s, struct bview *v)
{
// If the scene object indicates we're good, don't repeat.
if (s->current && !v)
return;
bv_log(1, "draw_scene %s[%s]", bu_vls_cstr(&s->s_name), (v) ? bu_vls_cstr(&v->gv_name) : "NULL");
// If we're not adaptive, trigger the view insensitive drawing routines
if (v && !v->gv_s->adaptive_plot_csg && !v->gv_s->adaptive_plot_mesh) {
return draw_scene(s, NULL);
}
// If we have a scene object without drawing data, it is most likely
// a container holding other objects we do need to draw. Iterate over
// any children and trigger their drawing operations.
struct draw_update_data_t *d = (struct draw_update_data_t *)s->s_i_data;
if (!d) {
for (size_t i = 0; i < BU_PTBL_LEN(&s->children); i++) {
struct bv_scene_obj *c = (struct bv_scene_obj *)BU_PTBL_GET(&s->children, i);
draw_scene(c, v);
}
return;
}
/**************************************************************************
* A couple of the drawing modes have their own completely independent and
* substantial logic defined elsewhere. Spot those cases first and steer
* them where they need to go
**************************************************************************/
/* Mode 3 generates an evaluated wireframe rather than drawing
* the individual solid wireframes */
if (s->s_os->s_dmode == 3) {
draw_m3(s);
bv_scene_obj_bound(s, v);
s->current = 1;
return;
}
/* Mode 5 draws a point cloud in lieu of wireframes */
if (s->s_os->s_dmode == 5) {
draw_points(s);
bv_scene_obj_bound(s, v);
s->current = 1;
return;
}
/**************************************************************************
* A couple of the object types will also have unique logic, typically for
* special handling of difficult drawing cases. Look for those as well.
**************************************************************************/
struct db_i *dbip = d->dbip;
struct db_full_path *fp = (struct db_full_path *)s->s_path;
if (fp && fp->fp_len <= 0)
return;
struct directory *dp = (fp) ? DB_FULL_PATH_CUR_DIR(fp) : (struct directory *)s->dp;
if (!dp)
return;
// Adaptive BoTs have specialized LoD routines to help cope with very large
// data sets, both for wireframe and shaded mode.
if (dp->d_minor_type == DB5_MINORTYPE_BRLCAD_BOT && v && v->gv_s->adaptive_plot_mesh &&
(s->s_os->s_dmode == 0 || s->s_os->s_dmode == 1)) {
bot_adaptive_plot(s, v);
return;
}
// Adaptive BReps have specialized LoD routines to manage shaded displays, which
// can involve slow and large mesh generations. BRep wireframes are based on the
// NURBS data, so this is used only for shaded mode
if (dp->d_minor_type == DB5_MINORTYPE_BRLCAD_BREP && v && v->gv_s->adaptive_plot_mesh && s->s_os->s_dmode == 1) {
brep_adaptive_plot(s, v);
return;
}
/**************************************************************************
* For the remainder of the options we're into more standard wireframe
* callback modes - crack the internal and stage the tolerances
**************************************************************************/
const struct bn_tol *tol = d->tol;
const struct bg_tess_tol *ttol = d->ttol;
struct rt_db_internal dbintern;
RT_DB_INTERNAL_INIT(&dbintern);
struct rt_db_internal *ip = &dbintern;
int ret = rt_db_get_internal(ip, dp, dbip, s->s_mat, d->res);
if (ret < 0)
return;
// If we don't have a BRL-CAD type, see if we've got a plot routine
if (ip->idb_major_type != DB5_MAJORTYPE_BRLCAD) {
wireframe_plot(s, v, ip);
goto geom_done;
}
// At least for the moment, we don't try anything fancy with pipes - they
// get a wireframe, regardless of mode settings
if (ip->idb_minor_type == DB5_MINORTYPE_BRLCAD_PIPE) {
wireframe_plot(s, v, ip);
goto geom_done;
}
// For anything other than mode 0, we call specific routines for
// some of the primitives.
if (s->s_os->s_dmode > 0) {
switch (ip->idb_minor_type) {
case DB5_MINORTYPE_BRLCAD_BOT:
(void)rt_bot_plot_poly(&s->s_vlist, ip, ttol, tol);
goto geom_done;
break;
case DB5_MINORTYPE_BRLCAD_POLY:
(void)rt_pg_plot_poly(&s->s_vlist, ip, ttol, tol);
goto geom_done;
break;
case DB5_MINORTYPE_BRLCAD_BREP:
(void)rt_brep_plot_poly(&s->s_vlist, dp, ip, ttol, tol, NULL);
goto geom_done;
break;
default:
break;
}
}
// Now the more general cases
switch (s->s_os->s_dmode) {
case 0:
case 1:
// Get wireframe (for mode 1, all the non-wireframes are handled
// by the above BOT/POLY/BREP cases
wireframe_plot(s, v, ip);
s->s_os->s_dmode = 0;
break;
case 2:
// Shade everything except pipe, don't evaluate, fall
// back to wireframe in case of failure
if (prim_tess(s, ip) < 0) {
wireframe_plot(s, v, ip);
s->s_os->s_dmode = 0;
} else {
s->current = 1;
}
break;
case 3:
// Evaluated wireframes
bu_log("Error - got too deep into _scene_obj_draw routine with drawing mode 3 - wireframe drawing with evaluated booleans\n");
return;
break;
case 4:
// Hidden line - generate polygonal forms, fall back to
// un-hidden wireframe in case of failure
if (prim_tess(s, ip) < 0) {
wireframe_plot(s, v, ip);
s->s_os->s_dmode = 0;
} else {
s->current = 1;
}
break;
case 5:
// Triangles at sampled points
bu_log("Error - got too deep into _scene_obj_draw routine with drawing mode 5 - triangles at ray-sampled points\n");
return;
break;
default:
// Default to wireframe
wireframe_plot(s, v, ip);
break;
}
geom_done:
// Update s_size and s_center
bv_scene_obj_bound(s, v);
// Store current view info, in case of adaptive plotting
s->adaptive_wireframe = s->s_v->gv_s->adaptive_plot_csg;
s->view_scale = s->s_v->gv_scale;
s->bot_threshold= s->s_v->gv_s->bot_threshold;
s->curve_scale = s->s_v->gv_s->curve_scale;
s->point_scale = s->s_v->gv_s->point_scale;
rt_db_free_internal(&dbintern);
}
#if 0
static void
tree_color(struct directory *dp, struct draw_data_t *dd)
{
@@ -854,195 +378,7 @@ tree_color(struct directory *dp, struct draw_data_t *dd)
// Done with attributes
bu_avs_free(&c_avs);
}
/*****************************************************************************
The primary drawing subtree walk.
To get an initial idea of scene size and center for adaptive plotting (i.e.
before we have wireframes drawn) we also have a need to check ft_bbox ahead
of the vlist generation. It can be thought of as a "preliminary autoview"
step. That mode is also supported by this subtree walk.
******************************************************************************/
static void
draw_walk_tree(struct db_full_path *path, union tree *tp, mat_t *curr_mat,
void (*traverse_func) (struct db_full_path *path, mat_t *, void *),
void *client_data, void *comb_inst_map)
{
mat_t om, nm;
struct directory *dp;
struct draw_data_t *dd= (struct draw_data_t *)client_data;
std::unordered_map<std::string, int> *cinst_map = (std::unordered_map<std::string, int> *)comb_inst_map;
if (!tp)
return;
RT_CK_FULL_PATH(path);
RT_CHECK_DBI(dd->dbip);
RT_CK_TREE(tp);
switch (tp->tr_op) {
case OP_NOT:
case OP_GUARD:
case OP_XNOP:
draw_walk_tree(path, tp->tr_b.tb_left, curr_mat, traverse_func, client_data, comb_inst_map);
break;
case OP_UNION:
case OP_INTERSECT:
case OP_SUBTRACT:
case OP_XOR:
draw_walk_tree(path, tp->tr_b.tb_left, curr_mat, traverse_func, client_data, comb_inst_map);
dd->bool_op = tp->tr_op;
draw_walk_tree(path, tp->tr_b.tb_right, curr_mat, traverse_func, client_data, comb_inst_map);
break;
case OP_DB_LEAF:
if (UNLIKELY(dd->dbip->dbi_use_comb_instance_ids && cinst_map))
(*cinst_map)[std::string(tp->tr_l.tl_name)]++;
if ((dp=db_lookup(dd->dbip, tp->tr_l.tl_name, LOOKUP_QUIET)) == RT_DIR_NULL) {
return;
} else {
/* Update current matrix state to reflect the new branch of
* the tree. Either we have a local matrix, or we have an
* implicit IDN matrix. */
MAT_COPY(om, *curr_mat);
if (tp->tr_l.tl_mat) {
MAT_COPY(nm, tp->tr_l.tl_mat);
} else {
MAT_IDN(nm);
}
bn_mat_mul(*curr_mat, om, nm);
// Stash current color settings and see if we're getting new ones
struct bu_color oc;
int inherit_old = dd->color_inherit;
HSET(oc.buc_rgb, dd->c.buc_rgb[0], dd->c.buc_rgb[1], dd->c.buc_rgb[2], dd->c.buc_rgb[3]);
if (!dd->bound_only) {
tree_color(dp, dd);
}
// Two things may prevent further processing - a hidden dp, or
// a cyclic path. Can check either here or in traverse_func -
// just do it here since otherwise the logic would have to be
// duplicated in all traverse functions.
if (!(dp->d_flags & RT_DIR_HIDDEN)) {
db_add_node_to_full_path(path, dp);
DB_FULL_PATH_SET_CUR_BOOL(path, tp->tr_op);
if (UNLIKELY(dd->dbip->dbi_use_comb_instance_ids && cinst_map))
DB_FULL_PATH_SET_CUR_COMB_INST(path, (*cinst_map)[std::string(tp->tr_l.tl_name)]-1);
if (!db_full_path_cyclic(path, NULL, 0)) {
/* Keep going */
traverse_func(path, curr_mat, client_data);
}
}
/* Done with branch - restore path, put back the old matrix state,
* and restore previous color settings */
DB_FULL_PATH_POP(path);
MAT_COPY(*curr_mat, om);
if (!dd->bound_only) {
dd->color_inherit = inherit_old;
HSET(dd->c.buc_rgb, oc.buc_rgb[0], oc.buc_rgb[1], oc.buc_rgb[2], oc.buc_rgb[3]);
}
return;
}
default:
bu_log("db_functree_subtree: unrecognized operator %d\n", tp->tr_op);
bu_bomb("db_functree_subtree: unrecognized operator\n");
}
}
/**
* This walker builds a list of db_full_path entries corresponding to
* the contents of the tree under *path. It does so while assigning
* the boolean operation associated with each path entry to the
* db_full_path structure. This list is then used for further
* processing and filtering by the search routines.
*/
extern "C" void
draw_gather_paths(struct db_full_path *path, mat_t *curr_mat, void *client_data)
{
struct directory *dp;
struct draw_data_t *dd= (struct draw_data_t *)client_data;
RT_CK_FULL_PATH(path);
RT_CK_DBI(dd->dbip);
dp = DB_FULL_PATH_CUR_DIR(path);
if (!dp)
return;
// If we're skipping subtractions and we have a subtraction op there's no
// point in going further.
if (dd->g->s_os->draw_non_subtract_only && dd->bool_op == 4) {
return;
}
if (dp->d_flags & RT_DIR_COMB) {
struct rt_db_internal in;
struct rt_comb_internal *comb;
if (rt_db_get_internal(&in, dp, dd->dbip, NULL, &rt_uniresource) < 0)
return;
comb = (struct rt_comb_internal *)in.idb_ptr;
if (UNLIKELY(dd->dbip->dbi_use_comb_instance_ids)) {
std::unordered_map<std::string, int> cinst_map;
draw_walk_tree(path, comb->tree, curr_mat, draw_gather_paths, client_data, (void *)&cinst_map);
} else {
draw_walk_tree(path, comb->tree, curr_mat, draw_gather_paths, client_data, NULL);
}
rt_db_free_internal(&in);
} else {
// If we've got a solid, things get interesting. There are a lot of
// potentially relevant options to sort through. It may be that most
// will end up getting handled by the object update callbacks, and the
// job here will just be to set up the key data for later use...
struct bv_scene_obj *s = bv_obj_get_child(dd->g);
db_path_to_vls(&s->s_name, path);
BU_GET(s->s_path, struct db_full_path);
db_full_path_init((struct db_full_path *)s->s_path);
db_dup_full_path((struct db_full_path *)s->s_path, path);
MAT_COPY(s->s_mat, *curr_mat);
bv_obj_settings_sync(s->s_os, dd->g->s_os);
s->s_type_flags = BV_DBOBJ_BASED;
s->current = 0;
s->s_changed++;
if (!s->s_os->draw_solid_lines_only) {
s->s_soldash = (dd->bool_op == 4) ? 1 : 0;
}
bu_color_to_rgb_chars(&dd->c, s->s_color);
// TODO - check path against the GED default selected set - if we're
// drawing something the app has already flagged as selected, need to
// illuminate
// Stash the information needed for a draw update callback
struct draw_update_data_t *ud;
BU_GET(ud, struct draw_update_data_t);
ud->fp = (struct db_full_path *)s->s_path;
ud->dbip = dd->dbip;
ud->tol = dd->tol;
ud->ttol = dd->ttol;
ud->mesh_c = dd->mesh_c;
ud->res = &rt_uniresource; // TODO - at some point this may be from the app or view. dd->res is temporary, so we don't use it here
s->s_i_data = (void *)ud;
s->s_free_callback = &draw_free_data;
// Let the object know about its size
if (dd->s_size && dd->s_size->find(DB_FULL_PATH_CUR_DIR(path)) != dd->s_size->end()) {
s->s_size = (*dd->s_size)[DB_FULL_PATH_CUR_DIR(path)];
}
}
}
#endif
// Local Variables:
// tab-width: 8
+38 -15
View File
@@ -78,13 +78,14 @@ solid_set_color_info(
}
void
dl_add_path(int dashflag, struct bu_list *vhead, const struct db_full_path *pathp, struct db_tree_state *tsp, unsigned char *wireframe_color_override, struct _ged_client_data *dgcdp)
{
if (!dgcdp || !dgcdp->v)
return;
struct bv_scene_obj *sp = bv_obj_get(dgcdp->v, BV_DB_OBJS);
struct bv_scene_obj *sp = bv_obj_get(dgcdp->gedp->free_scene_objs);
if (!sp)
return;
@@ -107,7 +108,7 @@ dl_add_path(int dashflag, struct bu_list *vhead, const struct db_full_path *path
sp->s_vlen += bv_vlist_cmd_cnt(bvv);
BU_LIST_APPEND_LIST(&(sp->s_vlist), &(bvv->l));
bv_scene_obj_bound(sp, dgcdp->v);
bv_obj_bound(sp);
db_dup_full_path(&bdata->s_fullpath, pathp);
@@ -268,7 +269,7 @@ append_solid_to_display_list(
}
/* create solid */
struct bv_scene_obj *sp = bv_obj_get(bv_data->v, BV_DB_OBJS);
struct bv_scene_obj *sp = bv_obj_get(bv_data->gedp->free_scene_objs);
struct ged_bv_data *bdata = (sp->s_u_data) ? (struct ged_bv_data *)sp->s_u_data : NULL;
if (!bdata) {
BU_GET(bdata, struct ged_bv_data);
@@ -332,7 +333,7 @@ append_solid_to_display_list(
sp->s_vlen += bv_vlist_cmd_cnt(bvv);
BU_LIST_APPEND_LIST(&(sp->s_vlist), &(bvv->l));
bv_scene_obj_bound(sp, bv_data->v);
bv_obj_bound(sp);
while (BU_LIST_WHILE(vp, bv_vlist, &(sp->s_vlist))) {
BU_LIST_DEQUEUE(&vp->l);
@@ -1264,6 +1265,7 @@ _ged_drawtrees(struct ged *gedp, int argc, const char *argv[], int kind, struct
bv_data.wireframe_color[2]= dgcdp.vs.color[2];
bv_data.transparency= dgcdp.vs.transparency;
bv_data.dmode = dgcdp.vs.s_dmode;
bv_data.gedp = gedp;
bv_data.v = gedp->ged_gvp;
dgcdp.gdlp = dl_addToDisplay(gedp->i->ged_gdp->gd_headDisplay, gedp->dbip, argv[i]);
@@ -1721,19 +1723,41 @@ ged_redraw_core(struct ged *gedp, int argc, const char *argv[])
return BRLCAD_OK;
}
#ifdef GED_PLUGIN
#include "../include/plugin.h"
#define GED_DRAW_COMMANDS(X, XID) \
X(draw, ged_draw_core, GED_CMD_DEFAULT) \
X(E, ged_E_core, GED_CMD_DEFAULT) \
X(e, ged_draw_core, GED_CMD_DEFAULT) \
X(ev, ged_ev_core, GED_CMD_DEFAULT) \
X(redraw, ged_redraw_core, GED_CMD_DEFAULT) \
X(loadview, ged_loadview_core, GED_CMD_DEFAULT) \
X(preview, ged_preview_core, GED_CMD_DEFAULT)
struct ged_cmd_impl draw_cmd_impl = {"draw", ged_draw_core, GED_CMD_DEFAULT};
const struct ged_cmd draw_cmd = { &draw_cmd_impl };
GED_DECLARE_COMMAND_SET(GED_DRAW_COMMANDS)
GED_DECLARE_PLUGIN_MANIFEST("libged_draw", 1, GED_DRAW_COMMANDS)
struct ged_cmd_impl bigE_cmd_impl = {"E", ged_E_core, GED_CMD_DEFAULT};
const struct ged_cmd bigE_cmd = { &bigE_cmd_impl };
struct ged_cmd_impl e_cmd_impl = {"e", ged_draw_core, GED_CMD_DEFAULT};
const struct ged_cmd e_cmd = { &e_cmd_impl };
struct ged_cmd_impl ev_cmd_impl = {"ev", ged_ev_core, GED_CMD_DEFAULT};
const struct ged_cmd ev_cmd = { &ev_cmd_impl };
struct ged_cmd_impl redraw_cmd_impl = {"redraw", ged_redraw_core, GED_CMD_DEFAULT};
const struct ged_cmd redraw_cmd = { &redraw_cmd_impl };
extern int ged_loadview_core(struct ged *gedp, int argc, const char *argv[]);
struct ged_cmd_impl loadview_cmd_impl = {"loadview", ged_loadview_core, GED_CMD_DEFAULT};
const struct ged_cmd loadview_cmd = { &loadview_cmd_impl };
extern int ged_preview_core(struct ged *gedp, int argc, const char *argv[]);
struct ged_cmd_impl preview_cmd_impl = {"preview", ged_preview_core, GED_CMD_DEFAULT};
const struct ged_cmd preview_cmd = { &preview_cmd_impl };
const struct ged_cmd *draw_cmds[] = { &draw_cmd, &bigE_cmd, &e_cmd, &ev_cmd, &redraw_cmd, &loadview_cmd, &preview_cmd, NULL };
static const struct ged_plugin pinfo = { GED_API, draw_cmds, 7 };
COMPILER_DLLEXPORT const struct ged_plugin *ged_plugin_info(void)
{
return &pinfo;
}
#endif /* GED_PLUGIN */
/*
* Local Variables:
@@ -1744,4 +1768,3 @@ GED_DECLARE_PLUGIN_MANIFEST("libged_draw", 1, GED_DRAW_COMMANDS)
* End:
* ex: shiftwidth=4 tabstop=8
*/
+49 -139
View File
@@ -41,7 +41,6 @@
#include "ged/view.h"
#include "../ged_private.h"
#include "../dbi.h"
static int
draw_opt_color(struct bu_vls *msg, size_t argc, const char **argv, void *data)
@@ -76,63 +75,11 @@ ged_draw2_core(struct ged *gedp, int argc, const char *argv[])
/* initialize result */
bu_vls_trunc(gedp->ged_result_str, 0);
/* Draw may operate on a specific user specified view. If it does so,
* we want the default settings to reflect those set in that particular
* view. In order to set up the correct default views, we need to know
* if a specific view has in fact been specified. We do a preliminary
* option check to figure this out */
struct bview *cv = gedp->ged_gvp;
struct bu_vls cvls = BU_VLS_INIT_ZERO;
struct bu_opt_desc vd[2];
BU_OPT(vd[0], "V", "view", "name", &bu_opt_vls, &cvls, "specify view to draw on");
BU_OPT_NULL(vd[1]);
int opt_ret = bu_opt_parse(NULL, argc, argv, vd);
argc = opt_ret;
if (argc < 0) {
bu_vls_free(&cvls);
return BRLCAD_ERROR;
}
if (bu_vls_strlen(&cvls)) {
cv = bv_set_find_view(&gedp->ged_views, bu_vls_cstr(&cvls));
if (!cv) {
bu_vls_printf(gedp->ged_result_str, "Specified view %s not found\n", bu_vls_cstr(&cvls));
bu_vls_free(&cvls);
return BRLCAD_ERROR;
}
if (!cv->independent) {
bu_vls_printf(gedp->ged_result_str, "Specified view %s is not an independent view, and as such does not support specifying db objects for display in only this view. To change the view's status, he command 'view independent %s 1' may be applied.\n", bu_vls_cstr(&cvls), bu_vls_cstr(&cvls));
bu_vls_free(&cvls);
return BRLCAD_ERROR;
}
}
// If we don't have a specified view, and the default view isn't a shared view, see if
// we can find a shared view in the view set.
if (!bu_vls_strlen(&cvls) && (!cv || cv->independent)) {
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
for (size_t i = 0; i < BU_PTBL_LEN(views); i++) {
struct bview *bv = (struct bview *)BU_PTBL_GET(views, i);
if (!bv->independent) {
cv = bv;
break;
}
}
}
bu_vls_free(&cvls);
// We need a current view, either from gedp or from the options
if (!cv) {
bu_vls_printf(gedp->ged_result_str, "No view specified and no shared views found");
return BRLCAD_ERROR;
}
/* User settings may override various options - set up to collect them.
* Option defaults may be overridden for the purposes of the current draw
* command by command line options. */
struct bv_obj_settings vs = BV_OBJ_SETTINGS_INIT;
struct bu_vls cvls = BU_VLS_INIT_ZERO;
int drawing_modes[6] = {-1, 0, 0, 0, 0, 0};
struct bu_opt_desc d[18];
@@ -153,6 +100,7 @@ ged_draw2_core(struct ged *gedp, int argc, const char *argv[])
BU_OPT(d[14], "C", "color", "r/g/b", &draw_opt_color, &vs, "Override object colors");
BU_OPT(d[15], "", "line-width", "#", &bu_opt_int, &vs.s_line_width, "Override default line width");
BU_OPT(d[16], "R", "no-autoview", "", NULL, &no_autoview, "Do not calculate automatic view, even if initial scene is empty.");
BU_OPT(d[17], "V", "view", "name", &bu_opt_vls, &cvls, "Specify specific view to add paths to (instantiates objects only in that view)");
BU_OPT_NULL(d[17]);
/* If no args, must be wanting help */
@@ -163,7 +111,7 @@ ged_draw2_core(struct ged *gedp, int argc, const char *argv[])
/* Process command line args into vs with bu_opt */
struct bu_vls omsg = BU_VLS_INIT_ZERO;
opt_ret = bu_opt_parse(&omsg, argc, argv, d);
int opt_ret = bu_opt_parse(&omsg, argc, argv, d);
if (opt_ret < 0) {
bu_vls_printf(gedp->ged_result_str, "option parsing error: %s\n", bu_vls_cstr(&omsg));
bu_vls_free(&omsg);
@@ -176,6 +124,24 @@ ged_draw2_core(struct ged *gedp, int argc, const char *argv[])
return BRLCAD_OK;
}
// If we have a specified view, make sure it matches one we know about
BViewState *svs = NULL;
if (bu_vls_strlen(&cvls)) {
std::string vname(bu_vls_cstr(&cvls));
std::vector<BViewState *> svsv = gedp->dbi_state->FindBViewState(vname.c_str());
if (!svsv.size()) {
bu_vls_printf(gedp->ged_result_str, "Specified view %s not found\n", bu_vls_cstr(&cvls));
bu_vls_free(&cvls);
return BRLCAD_ERROR;
}
if (svsv.size() > 1) {
bu_vls_printf(gedp->ged_result_str, "TODO - More than one view matches %s, need to support that...\n", bu_vls_cstr(&cvls));
bu_vls_free(&cvls);
return BRLCAD_ERROR;
}
svs = svsv[0];
}
// Whatever is left after argument processing are the potential draw paths
argc = opt_ret;
@@ -203,72 +169,24 @@ ged_draw2_core(struct ged *gedp, int argc, const char *argv[])
vs.s_dmode = drawing_modes[0];
}
// Before we start doing anything with the object set, record if things are
// Before we start doing anything with the object set, record if any views are
// starting out empty.
int blank_slate = 0;
struct bu_ptbl *dobjs = bv_view_objs(cv, BV_DB_OBJS);
struct bu_ptbl *local_dobjs = bv_view_objs(cv, BV_DB_OBJS);
struct bu_ptbl *vobjs = bv_view_objs(cv, BV_VIEW_OBJS);
struct bu_ptbl *vlobjs = bv_view_objs(cv, BV_VIEW_OBJS | BV_LOCAL_OBJS);
if ((!dobjs || !BU_PTBL_LEN(dobjs)) && (!local_dobjs || !BU_PTBL_LEN(local_dobjs)) &&
(!vobjs || !BU_PTBL_LEN(vobjs)) && (!vlobjs || !BU_PTBL_LEN(vlobjs))) {
blank_slate = 1;
}
gedp->dbi_state->FlagEmpty();
// Drawing can get complicated when we have multiple active views with
// different settings. The simplest case is when the current or specified
// view is an independent view - we just update it and return.
if (cv->independent) {
DbiState *dbis = (DbiState *)gedp->dbi_state;
BViewState *bvs = dbis->get_view_state(cv);
for (size_t i = 0; i < (size_t)argc; ++i)
bvs->add_path(argv[i]);
std::unordered_set<struct bview *> vset;
vset.insert(cv);
bvs->redraw(&vs, vset, !(blank_slate && !no_autoview));
return BRLCAD_OK;
}
// If we have a specified view, add JUST to that view. Otherwise, we're after
// the default view.
BViewState *wv = (svs) ? svs : gedp->dbi_state->GetBViewState(NULL);
for (int i = 0; i < argc; i++)
wv->AddPath(argv[i], vs.s_dmode, &vs);
// If we have multiple views, we have to handle each view. Most of the
// time the work will be done in the first pass (when objects do not have
// view specific geometry to generate) but this is not true when adaptive
// plotting is enabled.
std::unordered_map<BViewState *, std::unordered_set<struct bview *>> vmap;
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
for (size_t i = 0; i < BU_PTBL_LEN(views); i++) {
struct bview *v = (struct bview *)BU_PTBL_GET(views, i);
if (v->independent)
continue;
DbiState *dbis = (DbiState *)gedp->dbi_state;
BViewState *bvs = dbis->get_view_state(cv);
if (!bvs)
continue;
vmap[bvs].insert(v);
}
std::unordered_map<BViewState *, std::unordered_set<struct bview *>>::iterator bv_it;
for (bv_it = vmap.begin(); bv_it != vmap.end(); bv_it++) {
for (size_t i = 0; i < (size_t)argc; ++i)
bv_it->first->add_path(argv[i]);
bv_it->first->redraw(&vs, bv_it->second, !(blank_slate && !no_autoview));
}
// Path added - one or more views now need to be updated. Unless we've been
// told not to, trigger autoview on any previously empty views.
gedp->dbi_state->Redraw(wv, !no_autoview);
gedp->dbi_state->Render(wv);
return BRLCAD_OK;
}
static int
_ged_redraw_view(struct ged *gedp, struct bview *v, int argc, const char **argv)
{
if (!gedp || !gedp->dbi_state || !v)
return BRLCAD_ERROR;
std::unordered_set<struct bview *> vset;
DbiState *dbis = (DbiState *)gedp->dbi_state;
BViewState *bvs = dbis->get_view_state(v);
if (!bvs)
return BRLCAD_ERROR;
bvs->refresh(v, argc, argv);
return BRLCAD_OK;
}
extern "C" int
ged_redraw2_core(struct ged *gedp, int argc, const char *argv[])
{
@@ -281,46 +199,38 @@ ged_redraw2_core(struct ged *gedp, int argc, const char *argv[])
bu_vls_trunc(gedp->ged_result_str, 0);
/* redraw may operate on a specific user specified view, or on
/* Redraw may operate on a specific user specified view, or on
* all views (default) */
struct bview *cv = NULL;
struct bu_vls cvls = BU_VLS_INIT_ZERO;
struct bu_opt_desc vd[2];
BU_OPT(vd[0], "V", "view", "name", &bu_opt_vls, &cvls, "specify view to draw on");
BU_OPT_NULL(vd[1]);
int opt_ret = bu_opt_parse(NULL, argc, argv, vd);
argc = opt_ret;
BViewState *svs = NULL;
if (bu_vls_strlen(&cvls)) {
cv = bv_set_find_view(&gedp->ged_views, bu_vls_cstr(&cvls));
if (!cv) {
std::string vname(bu_vls_cstr(&cvls));
std::vector<BViewState *> svsv = gedp->dbi_state->FindBViewState(vname.c_str());
if (!svsv.size()) {
bu_vls_printf(gedp->ged_result_str, "Specified view %s not found\n", bu_vls_cstr(&cvls));
bu_vls_free(&cvls);
return BRLCAD_ERROR;
}
if (svsv.size() > 1) {
bu_vls_printf(gedp->ged_result_str, "TODO - More than one view matches %s, need to support that...\n", bu_vls_cstr(&cvls));
bu_vls_free(&cvls);
return BRLCAD_ERROR;
}
svs = svsv[0];
}
bu_vls_free(&cvls);
int ret = BRLCAD_OK;
if (cv) {
return _ged_redraw_view(gedp, cv, argc, argv);
} else {
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
if (!BU_PTBL_LEN(views)) {
bu_vls_printf(gedp->ged_result_str, "No views defined\n");
return BRLCAD_OK;
}
for (size_t i = 0; i < BU_PTBL_LEN(views); i++) {
struct bview *v = (struct bview *)BU_PTBL_GET(views, i);
if (!v) {
bu_log("WARNING, draw2.cpp:%d - null view stored in ged_views index %zu, skipping\n", __LINE__, i);
continue;
}
int nret = _ged_redraw_view(gedp, v, argc, argv);
if (nret != BRLCAD_OK)
ret = nret;
}
}
return ret;
BViewState *wv = (svs) ? svs : gedp->dbi_state->GetBViewState(NULL);
gedp->dbi_state->Redraw(wv);
gedp->dbi_state->Render(wv);
return BRLCAD_OK;
}
// Local Variables:
+1
View File
@@ -40,6 +40,7 @@ struct ged_solid_data {
int wireframe_color[3];
fastf_t transparency;
int dmode;
struct ged *gedp;
struct bview *v;
};
+1 -2
View File
@@ -440,8 +440,7 @@ ged_preview_core(struct ged *gedp, int argc, const char *argv[])
if (draw_eye_path) {
if (gedp->new_cmd_forms) {
struct bview *view = gedp->ged_gvp;
bv_vlblock_obj(preview_vbp, view, "preview::eye_path");
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, "ged::preview::eye_path", preview_vbp);
} else {
_ged_cvt_vlblock_to_solids(gedp, preview_vbp, "EYE_PATH", 0);
}
+9 -11
View File
@@ -65,7 +65,6 @@
#include "bu/opt.h"
#include "../ged_private.h"
#include "../dbi.h"
#include "./ged_edit2.h"
// Container to hold information about top level options and
@@ -297,13 +296,13 @@ cmd_perturb::exec(struct ged *gedp, void *u_data, int argc, const char **argv)
for (size_t i = 0; i < BU_PTBL_LEN(&objs); i++) {
struct directory *odp = (struct directory *)BU_PTBL_GET(&objs, i);
int oret = dp_perturb(odp);
einfo->gedp->dbi_state->changed.insert(odp);
if (oret != BRLCAD_OK)
ret = BRLCAD_ERROR;
}
bu_ptbl_free(&objs);
DbiState *dbis = (DbiState *)einfo->gedp->dbi_state;
dbis->update();
einfo->gedp->dbi_state->Sync();
return ret;
}
@@ -367,8 +366,7 @@ ged_edit2_core(struct ged *gedp, int argc, const char *argv[])
// High level options are only defined prior to the geometry specifier
// and/or subcommand.
int geom_pos = INT_MAX;
std::vector<unsigned long long> gs;
DbiState *dbis = (DbiState *)gedp->dbi_state;
DbiPath gs;
for (int i = 0; i < argc; i++) {
// TODO - de-quote so we can support obj names matching options...
// TODO - Allow URI specifications to call out primitive params
@@ -389,15 +387,15 @@ ged_edit2_core(struct ged *gedp, int argc, const char *argv[])
if (obj_uri.get_query().length() > 0)
bu_log("have query: %s\n", obj_uri.get_query().c_str());
}
gs = dbis->digest_path(obj_path.c_str());
gs.Init(obj_path.c_str());
}
catch (std::invalid_argument &uri_e)
{
std::string uri_error = uri_e.what();
bu_log("invalid uri: %s\n", uri_error.c_str());
gs = dbis->digest_path(argv[i]);
gs.Init(argv[i]);
}
if (gs.size() > 1 || dbis->get_hdp(gs[0]) != RT_DIR_NULL) {
if (gs.valid()) {
geom_pos = i;
break;
@@ -496,13 +494,13 @@ ged_edit2_core(struct ged *gedp, int argc, const char *argv[])
// to all geometry, but the majority of editing operations are specific to
// each individual geometric primitive type. We first decode the specifier,
// to determine what operations we're able to support.
einfo.dp = dbis->get_hdp(gs[0]);
if (gs.size() == 1 && !einfo.dp) {
einfo.dp = gs.GetDp();
if (gs.Depth() == 0 && !einfo.dp) {
bu_vls_printf(gedp->ged_result_str, ": geometry specifier lookup failed for %s\n", argv[0]);
return BRLCAD_ERROR;
}
if (gs.size() > 1) {
if (gs.Depth() > 1) {
bu_log("Comb instance specifier - only generic edit operations.\n");
} else {
// TODO - once we have the object type, ask librt what subcommands and parameters are
+20 -37
View File
@@ -33,12 +33,9 @@
#include "bu/opt.h"
#include "bu/sort.h"
#include "bv/view_sets.h"
#include "ged/database.h"
#include "ged/view.h"
#include "../dbi.h"
/*
* Erase objects from the scene. In many ways this is the most complex
* operation we need to perform on a displayed set of objects. When subsets of
@@ -51,7 +48,6 @@ ged_erase2_core(struct ged *gedp, int argc, const char *argv[])
{
static const char *usage = "[object(s)]";
const char *cmdName = argv[0];
struct bview *v = gedp->ged_gvp;
GED_CHECK_DATABASE_OPEN(gedp, BRLCAD_ERROR);
GED_CHECK_DRAWABLE(gedp, BRLCAD_ERROR);
@@ -60,57 +56,44 @@ ged_erase2_core(struct ged *gedp, int argc, const char *argv[])
/* initialize result */
bu_vls_trunc(gedp->ged_result_str, 0);
/* Erase may operate on a specific user specified view. If it does so,
* we want the default settings to reflect those set in that particular
* view. In order to set up the correct default views, we need to know
* if a specific view has in fact been specified. We do a preliminary
* option check to figure this out */
/* skip past cmd */
argc--; argv++;
/* Erase may operate on a specific user specified view. */
struct bu_vls cvls = BU_VLS_INIT_ZERO;
struct bu_opt_desc vd[3];
struct bu_opt_desc vd[5];
int mode = -1;
BU_OPT(vd[0], "V", "view", "name", &bu_opt_vls, &cvls, "specify view to draw on");
BU_OPT(vd[1], "m", "mode", "#", &bu_opt_int, &mode, "erase objects drawn in the specified drawing mode");
int scene_objs = 0;
BU_OPT(vd[0], "V", "view", "name", &bu_opt_vls, &cvls, "Specify view to draw on. Note that if a view is linked, objects originating from the linked view will not be cleared.");
BU_OPT(vd[1], "m", "mode", "#", &bu_opt_int, &mode, "Erase only one specific drawing mode for specified objects.");
BU_OPT(vd[2], "S", "scene-objs", "", NULL, &scene_objs, "Specifiers are for view scene objects rather than database paths.");
BU_OPT_NULL(vd[2]);
int opt_ret = bu_opt_parse(NULL, argc, argv, vd);
argc = opt_ret;
if (bu_vls_strlen(&cvls)) {
v = bv_set_find_view(&gedp->ged_views, bu_vls_cstr(&cvls));
if (!v) {
bu_vls_printf(gedp->ged_result_str, "Specified view %s not found\n", bu_vls_cstr(&cvls));
bu_vls_free(&cvls);
return BRLCAD_ERROR;
}
if (!v->independent) {
bu_vls_printf(gedp->ged_result_str, "Specified view %s is not an independent view, and as such does not support specifying db objects for display in only this view. To change the view's status, the command 'view independent %s 1' may be applied.\n", bu_vls_cstr(&cvls), bu_vls_cstr(&cvls));
std::vector<BViewState *> vsv;
if (bu_vls_strlen(&cvls)) {
std::string vname(bu_vls_cstr(&cvls));
vsv = gedp->dbi_state->FindBViewState(vname.c_str());
if (!vsv.size()) {
bu_vls_printf(gedp->ged_result_str, "Specified view(s) %s not found\n", bu_vls_cstr(&cvls));
bu_vls_free(&cvls);
return BRLCAD_ERROR;
}
} else {
BViewState *dv = gedp->dbi_state->GetBViewState(NULL);
vsv.push_back(dv);
}
bu_vls_free(&cvls);
/* Check that we have a view */
if (!v) {
bu_vls_printf(gedp->ged_result_str, "No view specified and no current view defined in GED, nothing to erase from");
return BRLCAD_ERROR;
}
/* must be wanting help */
if (argc == 1) {
bu_vls_printf(gedp->ged_result_str, "Usage: %s %s", cmdName, usage);
return GED_HELP;
}
/* skip past cmd */
argc--; argv++;
if (!gedp->dbi_state)
return BRLCAD_OK;
DbiState *dbis = (DbiState *)gedp->dbi_state;
BViewState *bvs = dbis->get_view_state(v);
bvs->erase_path(mode, argc, argv);
for (size_t i = 0; i < vsv.size(); i++)
vsv[i]->Erase(mode, scene_objs, argc, argv);
return BRLCAD_OK;
}
+2 -19
View File
@@ -38,8 +38,6 @@
#include "raytrace.h"
#include "ged.h"
#include "../dbi.h"
void print_help_msg(struct bu_vls *str)
{
bu_vls_printf(str, "Usage: garbage_collect [-c|--confirm] [-h|--help]\n");
@@ -63,6 +61,7 @@ ged_garbage_collect_core(struct ged *gedp, int argc, const char *argv[])
const char *av[10] = {NULL};
fastf_t fs_percent = 0.0;
int confirmed = 0;
int dbret = 0;
int new_file_size = 0;
int old_file_size = 0;
int path_cnt = 0;
@@ -86,6 +85,7 @@ ged_garbage_collect_core(struct ged *gedp, int argc, const char *argv[])
struct directory *dp = NULL;
struct directory *new_global_dp = NULL;
struct directory *old_global_dp = NULL;
struct ged_subprocess *rrp = NULL;
struct rt_wdb *gc_wdbp = NULL;
std::ifstream cfile;
std::ofstream ofile;
@@ -151,23 +151,6 @@ ged_garbage_collect_core(struct ged *gedp, int argc, const char *argv[])
bu_free(paths, "free db_ls output");
paths = NULL;
/* In addition to the database data itself, we also want to restore any
* views to their original state when we open the garbage collected
* database. Save the who list. (TODO - do we need to save views? Or
* will drawing without resize work?) */
if (gedp->new_cmd_forms) {
DbiState *dbis = (DbiState *)gedp->dbi_state;
BViewState *bvs = dbis->get_view_state(gedp->ged_gvp);
std::vector<std::string> wpaths = bvs->list_drawn_paths(-1, false);
for (size_t i = 0; i < wpaths.size(); i++) {
who_objs.push_back(wpaths[i]);
}
} else {
struct display_list *gdlp;
for (BU_LIST_FOR(gdlp, display_list, (struct bu_list *)ged_dl(gedp)))
who_objs.push_back(std::string(bu_vls_cstr(&gdlp->dl_path)));
}
/* Create "working" database. */
bu_vls_sprintf(&working_file, "%s/%d_gc_%s", bu_vls_cstr(&fdir),
bu_pid(), bu_vls_cstr(&fname));
@@ -1,4 +1,4 @@
/* G D I F F . C
/* G D I F F . C P P
* BRL-CAD
*
* Copyright (c) 2014-2025 United States Government as represented by
@@ -17,7 +17,7 @@
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file libged/gdiff.c
/** @file libged/gdiff.cpp
*
* The gdiff command.
*
@@ -415,8 +415,7 @@ ged_gdiff_core(struct ged *gedp, int argc, const char *argv[])
}
if (gedp->new_cmd_forms) {
struct bview *view = gedp->ged_gvp;
bv_vlblock_obj(vbp, view, "gdiff");
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, "ged::gdiff", vbp);
} else {
_ged_cvt_vlblock_to_solids(gedp, vbp, "diff_visual", 0);
}
@@ -437,12 +436,11 @@ ged_gdiff_core(struct ged *gedp, int argc, const char *argv[])
GED_DECLARE_COMMAND_SET(GED_GDIFF_COMMANDS)
GED_DECLARE_PLUGIN_MANIFEST("libged_gdiff", 1, GED_GDIFF_COMMANDS)
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8 cino=N-s
+23 -8
View File
@@ -70,9 +70,6 @@ ged_close(struct ged *gedp)
gedp->dbip = NULL;
}
if (gedp->ged_lod)
bv_mesh_lod_context_destroy(gedp->ged_lod);
/* Terminate any ged subprocesses */
if (gedp != GED_NULL) {
for (size_t i = 0; i < BU_PTBL_LEN(&gedp->ged_subp); i++) {
@@ -109,7 +106,7 @@ ged_init(struct ged *gedp)
bu_vls_init(&gedp->go_name);
// View related containers
bv_set_init(&gedp->ged_views);
BU_PTBL_INIT(&gedp->ged_views);
BU_PTBL_INIT(&gedp->ged_free_views);
/* TODO: If we're init-ing the list here, does that mean the gedp has
@@ -120,11 +117,14 @@ ged_init(struct ged *gedp)
// Establish an initial view
BU_ALLOC(gedp->ged_gvp, struct bview);
bv_init(gedp->ged_gvp, &gedp->ged_views);
bv_init(gedp->ged_gvp);
bu_vls_sprintf(&gedp->ged_gvp->gv_name, "default");
bv_set_add_view(&gedp->ged_views, gedp->ged_gvp);
bu_ptbl_ins(&gedp->ged_views, (long *)gedp->ged_gvp);
bu_ptbl_ins(&gedp->ged_free_views, (long *)gedp->ged_gvp);
// Scene objects pool
gedp->free_scene_objs = bv_obj_pool_create();
/* Create a non-opened fbserv */
BU_GET(gedp->ged_fbs, struct fbserv_obj);
gedp->ged_fbs->fbs_listener.fbsl_fd = -1;
@@ -201,15 +201,24 @@ ged_free(struct ged *gedp)
bu_vls_free(&gedp->go_name);
// Sanity
gedp->ged_gvp = NULL;
// Free views container - any bview structs that aren't the application's
// responsibility will be handled by ged_free_views
bu_ptbl_free(&gedp->ged_views);
/* Free scene objects */
bv_obj_pool_destroy(gedp->free_scene_objs);
gedp->free_scene_objs = NULL;
/* Free libged owned views */
for (size_t i = 0; i < BU_PTBL_LEN(&gedp->ged_free_views); i++) {
struct bview *gdvp = (struct bview *)BU_PTBL_GET(&gedp->ged_free_views, i);
bv_free(gdvp);
bu_free((void *)gdvp, "bv");
}
bu_ptbl_free(&gedp->ged_free_views);
bv_set_free(&gedp->ged_views);
if (gedp->i->ged_gdp != GED_DRAWABLE_NULL) {
@@ -378,7 +387,13 @@ ged_open(const char *dbtype, const char *filename, int existing_only)
db_update_nref(gedp->dbip, &rt_uniresource);
gedp->ged_lod = NULL;
// LoD cache updating may take a while, so we don't want
// to block on it.
const char *do_lod_init = getenv("LIBGED_LOD_INIT");
if (BU_STR_EQUAL(do_lod_init, "1")) {
std::thread lod_thread(db_cache_mesh_init, gedp->dbip, 0);
lod_thread.detach();
}
return gedp;
}
+19 -1
View File
@@ -31,6 +31,7 @@
#include <time.h>
#include "bu/avs.h"
#include "bu/cache.h"
#include "bu/cmd.h"
#include "bu/opt.h"
#include "bg/spsr.h"
@@ -212,7 +213,6 @@ struct draw_data_t {
int color_inherit;
int bool_op;
struct resource *res;
struct bv_mesh_lod_context *mesh_c;
/* To avoid the need for multiple subtree walking
* functions, we also set up to support a bounding
@@ -484,6 +484,24 @@ _ged_subcmd2_help(struct ged *gedp, struct bu_opt_desc *gopts, std::map<std::str
__END_DECLS
#ifdef __cplusplus
#include <sstream>
struct bu_cache *
dbi_cache_open(const char *name);
size_t
cache_get(struct bu_cache *c, void **data, unsigned long long hash, const char *component);
void
cache_write(struct bu_cache *c, unsigned long long hash, const char *component, std::stringstream &s);
void
cache_del(struct bu_cache *c, unsigned long long hash, const char *component);
#endif
#endif /* LIBGED_GED_PRIVATE_H */
/** @} */
+9 -16
View File
@@ -251,7 +251,7 @@ _ged_subcmd2_help(struct ged *gedp, struct bu_opt_desc *gopts, std::map<std::str
* respectively (we don't do it here so callers may run this routine
* repeatedly over different tables to accumulate bounds. */
static int
scene_bounding_sph(struct bu_ptbl *so, vect_t *vmin, vect_t *vmax, int pflag)
scene_bounding_sph(const struct bu_ptbl *so, vect_t *vmin, vect_t *vmax, int pflag)
{
struct bv_scene_obj *sp;
vect_t minus, plus;
@@ -1068,10 +1068,9 @@ ged_who_argc(struct ged *gedp)
if (gedp->new_cmd_forms) {
if (!gedp || !gedp->ged_gvp || !gedp->dbi_state)
return 0;
DbiState *dbis = (DbiState *)gedp->dbi_state;
BViewState *bvs = dbis->get_view_state(gedp->ged_gvp);
BViewState *bvs = gedp->dbi_state->GetBViewState(gedp->ged_gvp);
if (bvs)
return bvs->count_drawn_paths(-1, true);
return bvs->DrawnPathCount();
return 0;
}
@@ -1106,10 +1105,9 @@ ged_who_argv(struct ged *gedp, char **start, const char **end)
if (gedp->new_cmd_forms) {
if (!gedp->ged_gvp || !gedp->dbi_state)
return 0;
DbiState *dbis = (DbiState *)gedp->dbi_state;
BViewState *bvs = dbis->get_view_state(gedp->ged_gvp);
BViewState *bvs = gedp->dbi_state->GetBViewState(gedp->ged_gvp);
if (bvs) {
std::vector<std::string> drawn_paths = bvs->list_drawn_paths(-1, true);
std::vector<std::string> drawn_paths = bvs->DrawnPaths();
for (size_t i = 0; i < drawn_paths.size(); i++) {
if ((vp != NULL) && ((const char **)vp < end)) {
*vp++ = bu_strdup(drawn_paths[i].c_str());
@@ -1706,12 +1704,8 @@ _ged_rt_set_eye_model(struct ged *gedp,
if (gedp->new_cmd_forms) {
VSETALL(extremum[0], INFINITY);
VSETALL(extremum[1], -INFINITY);
struct bu_ptbl *db_objs = bv_view_objs(gedp->ged_gvp, BV_DB_OBJS);
if (db_objs)
(void)scene_bounding_sph(db_objs, &(extremum[0]), &(extremum[1]), 1);
struct bu_ptbl *local_db_objs = bv_view_objs(gedp->ged_gvp, BV_DB_OBJS | BV_LOCAL_OBJS);
if (local_db_objs)
(void)scene_bounding_sph(local_db_objs, &(extremum[0]), &(extremum[1]), 1);
const struct bu_ptbl *db_objs = ged_find_scene_objs(gedp, NULL, NULL, 1, 1);
(void)scene_bounding_sph(db_objs, &(extremum[0]), &(extremum[1]), 1);
} else {
(void)dl_bounding_sph(gedp->i->ged_gdp->gd_headDisplay, &(extremum[0]), &(extremum[1]), 1);
}
@@ -1996,10 +1990,9 @@ _ged_rt_write(struct ged *gedp,
if (argc >= 0) {
if (!argc) {
if (gedp->new_cmd_forms) {
DbiState *dbis = (DbiState *)gedp->dbi_state;
BViewState *bvs = dbis->get_view_state(gedp->ged_gvp);
BViewState *bvs = gedp->dbi_state->GetBViewState(gedp->ged_gvp);
if (bvs) {
std::vector<std::string> drawn_paths = bvs->list_drawn_paths(-1, true);
std::vector<std::string> drawn_paths = bvs->DrawnPaths();
for (size_t i = 0; i < drawn_paths.size(); i++) {
fprintf(fp, "draw %s;\n", drawn_paths[i].c_str());
}
+1 -2
View File
@@ -2723,8 +2723,7 @@ aborted:
if (analysis_flags & ANALYSIS_PLOT_OVERLAPS) {
if (gedp->new_cmd_forms) {
struct bview *view = gedp->ged_gvp;
bv_vlblock_obj(ged_gqa_plot.vbp, view, "gqa::overlaps");
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, "ged::gqa::overlaps", ged_gqa_plot.vbp);
} else {
_ged_cvt_vlblock_to_solids(gedp, ged_gqa_plot.vbp, "OVERLAPS", 0);
}
+2 -2
View File
@@ -1,13 +1,13 @@
set(PLUGIN_LIBS libged libbu)
ged_plugin_library(ged-joint
joint.c
joint.cpp
LIBS ${PLUGIN_LIBS}
)
cmakefiles(
CMakeLists.txt
joint.c
joint.cpp
)
# Local Variables:
@@ -1,4 +1,4 @@
/* J O I N T . C
/* J O I N T . C P P
* BRL-CAD
*
* Copyright (c) 2004-2025 United States Government as represented by
@@ -17,7 +17,7 @@
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file libged/joint.c
/** @file libged/joint.cpp
*
* Process all animation edit commands.
*
@@ -238,7 +238,7 @@ static struct db_tree_state mesh_initial_tree_state = {
static int
joint_mesh(struct ged *gedp, int argc, const char *argv[])
joint_mesh(struct ged *gedp, int argc, const char **argv)
{
const char *name;
struct bv_vlblock*vbp;
@@ -296,8 +296,7 @@ joint_mesh(struct ged *gedp, int argc, const char *argv[])
}
if (gedp->new_cmd_forms) {
struct bview *view = gedp->ged_gvp;
bv_vlblock_obj(vbp, view, "joint");
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, "ged::joint", vbp);
} else {
_ged_cvt_vlblock_to_solids(gedp, vbp, name, 0);
}
@@ -318,7 +317,7 @@ joint_mesh(struct ged *gedp, int argc, const char *argv[])
static int
joint_debug(struct ged *gedp,
int argc,
const char *argv[])
const char **argv)
{
if (argc >= 2) {
sscanf(argv[1], "%x", &J_DEBUG);
@@ -337,7 +336,7 @@ joint_debug(struct ged *gedp,
* Common code for help commands
*/
static int
helpcomm(struct ged *gedp, int argc, const char *argv[], struct funtab *functions)
helpcomm(struct ged *gedp, int argc, const char **argv, struct funtab *functions)
{
struct funtab *ftp;
int i, bad;
@@ -368,7 +367,7 @@ helpcomm(struct ged *gedp, int argc, const char *argv[], struct funtab *function
* the indicated commands.
*/
static int
joint_usage(struct ged *gedp, int argc, const char *argv[], struct funtab *functions)
joint_usage(struct ged *gedp, int argc, const char **argv, struct funtab *functions)
{
struct funtab *ftp;
@@ -384,7 +383,7 @@ joint_usage(struct ged *gedp, int argc, const char *argv[], struct funtab *funct
static int
joint_command_tab(struct ged *gedp, int argc, const char *argv[], struct funtab *functions)
joint_command_tab(struct ged *gedp, int argc, const char **argv, struct funtab *functions)
{
struct funtab *ftp;
@@ -402,7 +401,7 @@ joint_command_tab(struct ged *gedp, int argc, const char *argv[], struct funtab
static int
joint_help_commands(struct ged *gedp, int argc, const char *argv[])
joint_help_commands(struct ged *gedp, int argc, const char **argv)
{
int status;
@@ -416,7 +415,7 @@ joint_help_commands(struct ged *gedp, int argc, const char *argv[])
static int
joint_help(struct ged *gedp, int argc, const char *argv[])
joint_help(struct ged *gedp, int argc, const char **argv)
{
int status;
@@ -653,7 +652,7 @@ hold_clear_flags(struct hold *hp)
static int
joint_unload(struct ged *gedp, int argc, const char *argv[])
joint_unload(struct ged *gedp, int argc, const char **argv)
{
struct joint *jp;
struct hold *hp;
@@ -805,7 +804,7 @@ static const char *lex_name;
static double mm2base, base2mm;
static void
parse_error(struct ged *gedp, struct bu_vls *vlsp, char *error)
parse_error(struct ged *gedp, struct bu_vls *vlsp, const char *error)
{
char *text;
size_t i;
@@ -884,7 +883,7 @@ get_token(struct ged *gedp, union bu_lex_token *token, FILE *fip, struct bu_vls
static int
gobble_token(struct ged *gedp, int type_wanted, int value_wanted, FILE *fip, struct bu_vls *str)
{
static char *types[] = {
static const char *types[] = {
"any",
"integer",
"double",
@@ -1138,7 +1137,7 @@ parse_ARC(struct ged *gedp, struct arc *ap, FILE *fip, struct bu_vls *str)
{
union bu_lex_token token;
int max;
char *error;
const char *error;
if (J_DEBUG & DEBUG_J_PARSE) {
bu_vls_printf(gedp->ged_result_str, "parse_ARC: open.\n");
@@ -2293,7 +2292,7 @@ joint_adjust(struct ged *gedp, struct joint *jp)
static int
joint_load(struct ged *gedp, int argc, const char *argv[])
joint_load(struct ged *gedp, int argc, const char **argv)
{
static struct bu_list path_head;
@@ -2430,7 +2429,7 @@ joint_load(struct ged *gedp, int argc, const char *argv[])
static int
joint_save(struct ged *gedp, int argc, const char *argv[])
joint_save(struct ged *gedp, int argc, const char **argv)
{
struct joint *jp;
int i;
@@ -2515,7 +2514,7 @@ joint_save(struct ged *gedp, int argc, const char *argv[])
static int
joint_accept(struct ged *gedp, int argc, const char *argv[])
joint_accept(struct ged *gedp, int argc, const char **argv)
{
struct joint *jp;
int i;
@@ -2554,7 +2553,7 @@ joint_accept(struct ged *gedp, int argc, const char *argv[])
static int
joint_reject(struct ged *gedp, int argc, const char *argv[])
joint_reject(struct ged *gedp, int argc, const char **argv)
{
struct joint *jp;
int i;
@@ -3175,7 +3174,7 @@ Middle:
static int
joint_solve(struct ged *gedp, int argc, const char *argv[])
joint_solve(struct ged *gedp, int argc, const char **argv)
{
struct hold *hp;
int loops, count;
@@ -3354,7 +3353,7 @@ joint_solve(struct ged *gedp, int argc, const char *argv[])
static int
joint_hold(struct ged *gedp, int argc, const char *argv[])
joint_hold(struct ged *gedp, int argc, const char **argv)
{
struct hold *hp;
++argv;
@@ -3377,7 +3376,7 @@ joint_hold(struct ged *gedp, int argc, const char *argv[])
static int
joint_list(struct ged *gedp, int UNUSED(argc), const char *UNUSED(argv[]))
joint_list(struct ged *gedp, int UNUSED(argc), const char **UNUSED(argv))
{
struct joint *jp;
@@ -3481,7 +3480,7 @@ joint_move(struct ged *gedp, int argc, const char *argv[])
static int
joint_cmd(struct ged *gedp,
int argc,
const char *argv[],
const char **argv,
struct funtab functions[])
{
struct funtab *ftp;
@@ -3522,7 +3521,7 @@ joint_cmd(struct ged *gedp,
int
ged_joint_core(struct ged *gedp, int argc, const char *argv[])
ged_joint_core(struct ged *gedp, int argc, const char **argv)
{
int status;
@@ -3546,36 +3545,21 @@ ged_joint_core(struct ged *gedp, int argc, const char *argv[])
struct funtab joint_tab[] = {
{"joint ", "", "Joint command table",
0, 0, 0, FALSE},
{"?", "[commands]", "summary of available joint commands",
joint_help_commands, 0, FUNTAB_UNLIMITED, FALSE},
{"accept", "[joints]", "accept a series of moves",
joint_accept, 1, FUNTAB_UNLIMITED, FALSE},
{"debug", "[hex code]", "Show/set debugging bit vector for joints",
joint_debug, 1, 2, FALSE},
{"help", "[commands]", "give usage message for given joint commands",
joint_help, 0, FUNTAB_UNLIMITED, FALSE},
{"holds", "[names]", "list constraints",
joint_hold, 1, FUNTAB_UNLIMITED, FALSE},
{"list", "[names]", "list joints.",
joint_list, 1, FUNTAB_UNLIMITED, FALSE},
{"load", "file_name", "load a joint/constraint file",
joint_load, 2, FUNTAB_UNLIMITED, FALSE},
{"mesh", "", "Build the grip mesh",
joint_mesh, 0, 1, FALSE},
{"move", "joint_name p1 [p2...p6]", "Manual adjust a joint",
joint_move, 3, 8, FALSE},
{"reject", "[joint_names]", "reject joint motions",
joint_reject, 1, FUNTAB_UNLIMITED, FALSE},
{"save", "file_name", "Save joints and constraints to disk",
joint_save, 2, 2, FALSE},
{"solve", "constraint", "Solve a or all constraints",
joint_solve, 1, FUNTAB_UNLIMITED, FALSE},
{"unload", "", "Unload any joint/constraints that have been loaded",
joint_unload, 1, 1, FALSE},
{NULL, NULL, NULL,
NULL, 0, 0, FALSE}
{"joint ", "", "Joint command table", 0, 0, 0, FALSE},
{"?", "[commands]", "summary of available joint commands", joint_help_commands, 0, FUNTAB_UNLIMITED, FALSE},
{"accept", "[joints]", "accept a series of moves", joint_accept, 1, FUNTAB_UNLIMITED, FALSE},
{"debug", "[hex code]", "Show/set debugging bit vector for joints", joint_debug, 1, 2, FALSE},
{"help", "[commands]", "give usage message for given joint commands", joint_help, 0, FUNTAB_UNLIMITED, FALSE},
{"holds", "[names]", "list constraints", joint_hold, 1, FUNTAB_UNLIMITED, FALSE},
{"list", "[names]", "list joints.", joint_list, 1, FUNTAB_UNLIMITED, FALSE},
{"load", "file_name", "load a joint/constraint file", joint_load, 2, FUNTAB_UNLIMITED, FALSE},
{"mesh", "", "Build the grip mesh", joint_mesh, 0, 1, FALSE},
{"move", "joint_name p1 [p2...p6]", "Manual adjust a joint", joint_move, 3, 8, FALSE},
{"reject", "[joint_names]", "reject joint motions", joint_reject, 1, FUNTAB_UNLIMITED, FALSE},
{"save", "file_name", "Save joints and constraints to disk", joint_save, 2, 2, FALSE},
{"solve", "constraint", "Solve a or all constraints", joint_solve, 1, FUNTAB_UNLIMITED, FALSE},
{"unload", "", "Unload any joint/constraints that have been loaded", joint_unload, 1, 1, FALSE},
{NULL, NULL, NULL, NULL, 0, 0, FALSE}
};
#include "../include/plugin.h"
@@ -3586,12 +3570,11 @@ struct funtab joint_tab[] = {
GED_DECLARE_COMMAND_SET(GED_JOINT_COMMANDS)
GED_DECLARE_PLUGIN_MANIFEST("libged_joint", 1, GED_JOINT_COMMANDS)
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8 cino=N-s
+3 -3
View File
@@ -173,9 +173,9 @@ struct hold {
#define FUNTAB_UNLIMITED -1
struct funtab {
char *ft_name;
char *ft_parms;
char *ft_comment;
const char *ft_name;
const char *ft_parms;
const char *ft_comment;
int (*ft_func)(struct ged *, int, const char **);
int ft_min;
int ft_max;
+1 -2
View File
@@ -347,9 +347,8 @@ ged_lint_core(struct ged *gedp, int argc, const char *argv[])
}
if (visualize) {
struct bview *view = gedp->ged_gvp;
if (gedp->new_cmd_forms) {
bv_vlblock_obj(ldata.vbp, view, "lint_visual");
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, "ged::lint_visual", ldata.vbp);
} else {
_ged_cvt_vlblock_to_solids(gedp, ldata.vbp, "lint_visual", 0);
}
+8 -7
View File
@@ -590,10 +590,10 @@ ged_nirt_core(struct ged *gedp, int argc, const char *argv[])
/* Whether or not we're doing graphics, if we took a shot we should clear any
* old objects from prior shots. */
if (gedp->new_cmd_forms) {
struct bview *view = gedp->ged_gvp;
struct bv_scene_obj *nobj = bv_find_obj(view, bu_vls_cstr(&gedp->i->ged_gdp->gd_qray_basename));
if (nobj)
bv_obj_put(nobj);
BViewState *vs = gedp->dbi_state->GetBViewState(gedp->ged_gvp);
std::vector<struct bv_scene_obj *> nobjs = vs->FindSceneObjs(bu_vls_cstr(&gedp->i->ged_gdp->gd_qray_basename));
for (size_t i = 0; i < nobjs.size(); i++)
bv_obj_put(nobjs[i]);
} else {
struct directory **dpv;
struct bu_vls dp_pattern = BU_VLS_INIT_ZERO;
@@ -617,9 +617,10 @@ ged_nirt_core(struct ged *gedp, int argc, const char *argv[])
bu_log("Error loading plot data from %s\n", bu_vls_cstr(&nv.plotfile));
} else {
if (gedp->new_cmd_forms) {
struct bview *view = gedp->ged_gvp;
struct bv_scene_obj *nobj = bv_vlblock_obj(vbp, view, bu_vls_cstr(&gedp->i->ged_gdp->gd_qray_basename));
bu_vls_sprintf(&nobj->s_name, "%s", bu_vls_cstr(&gedp->i->ged_gdp->gd_qray_basename));
struct bu_vls nroot = BU_VLS_INIT_ZERO;
bu_vls_sprintf(&nroot, "%s", bu_vls_cstr(&gedp->i->ged_gdp->gd_qray_basename));
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, bu_vls_cstr(&nroot), vbp);
bu_vls_free(&nroot);
} else {
_ged_cvt_vlblock_to_solids(gedp, vbp, bu_vls_cstr(&gedp->i->ged_gdp->gd_qray_basename), 0);
}
+11 -5
View File
@@ -143,14 +143,20 @@ ged_opendb_core(struct ged *gedp, int argc, const char *argv[])
/* New database open, need to initialize reference counts */
db_update_nref(gedp->dbip, &rt_uniresource);
// LoD context creation (DbiState initialization can use info
// stored here, so do this first)
if (gedp->new_cmd_forms)
gedp->ged_lod = bv_mesh_lod_context_create(argv[0]);
// LoD cache updating may take a while, so we don't want
// to block on it.
const char *do_lod_init = getenv("LIBGED_LOD_INIT");
if (BU_STR_EQUAL(do_lod_init, "1")) {
std::thread lod_thread(db_cache_mesh_init, gedp->dbip, 0);
lod_thread.detach();
}
// If enabled, set up the DbiState container for fast structure access
if (gedp->new_cmd_forms)
if (gedp->new_cmd_forms) {
if (gedp->dbi_state)
delete gedp->dbi_state;
gedp->dbi_state = new DbiState(gedp);
}
// Set the view units, if we have a view
if (gedp->ged_gvp) {
+2 -2
View File
@@ -1,13 +1,13 @@
set(PLUGIN_LIBS libged libbu)
ged_plugin_library(ged-overlay
overlay.c
overlay.cpp
LIBS ${PLUGIN_LIBS}
)
cmakefiles(
CMakeLists.txt
overlay.c
overlay.cpp
)
# Local Variables:
@@ -1,4 +1,4 @@
/* O V E R L A Y . C
/* O V E R L A Y . C P P
* BRL-CAD
*
* Copyright (c) 2008-2025 United States Government as represented by
@@ -17,7 +17,7 @@
* License along with this file; see the file named COPYING for more
* information.
*/
/** @file libged/overlay.c
/** @file libged/overlay.cpp
*
* The overlay command.
*
@@ -35,7 +35,7 @@
#include "../ged_private.h"
static int
overlay_image_mime(struct bu_vls *msg, size_t argc, const char **argv, void *set_mime)
image_mime(struct bu_vls *msg, size_t argc, const char **argv, void *set_mime)
{
int type_int;
bu_mime_image_t type = BU_MIME_IMAGE_UNKNOWN;
@@ -95,7 +95,7 @@ ged_overlay_core(struct ged *gedp, int argc, const char *argv[])
BU_OPT(d[10], "w", "width", "#", &bu_opt_int, &width, "[Fb] image width");
BU_OPT(d[11], "n", "height", "#", &bu_opt_int, &height, "[Fb] image height");
BU_OPT(d[12], "S", "square", "#", &bu_opt_int, &square, "[Fb] image width/height (for square image)");
BU_OPT(d[13], "", "format", "fmt", &overlay_image_mime, &type, "[Fb] image file format");
BU_OPT(d[13], "", "format", "fmt", &image_mime, &type, "[Fb] image file format");
BU_OPT_NULL(d[14]);
GED_CHECK_DATABASE_OPEN(gedp, BRLCAD_ERROR);
@@ -333,12 +333,11 @@ ged_overlay_core(struct ged *gedp, int argc, const char *argv[])
GED_DECLARE_COMMAND_SET(GED_OVERLAY_COMMANDS)
GED_DECLARE_PLUGIN_MANIFEST("libged_overlay", 1, GED_OVERLAY_COMMANDS)
/*
* Local Variables:
* mode: C
* tab-width: 8
* indent-tabs-mode: t
* c-file-style: "stroustrup"
* End:
* ex: shiftwidth=4 tabstop=8
*/
// Local Variables:
// tab-width: 8
// mode: C++
// c-basic-offset: 4
// indent-tabs-mode: t
// c-file-style: "stroustrup"
// End:
// ex: shiftwidth=4 tabstop=8 cino=N-s
+7 -31
View File
@@ -106,44 +106,20 @@ rtcheck_vector_handler(void *clientData, int type)
/* Get vector output from rtcheck */
if (!rtcp->draw_read_failed && (feof(rtcp->fp) || (value = getc(rtcp->fp)) == EOF)) {
size_t i;
rtcp->draw_read_failed = 1;
// Clear any prior rtcheck outputs - whether or not we have new
// overlaps to draw, we're eliminating all the old objects
const char *sname = "rtcheck::";
struct bview *v = gedp->ged_gvp;
struct bu_ptbl *vobjs = bv_view_objs(v, BV_VIEW_OBJS);
std::set<struct bv_scene_obj *> robjs;
if (vobjs) {
for (i = 0; i < BU_PTBL_LEN(vobjs); i++) {
struct bv_scene_obj *s = (struct bv_scene_obj *)BU_PTBL_GET(vobjs, i);
if (!bu_strncmp(sname, bu_vls_cstr(&s->s_name), strlen(sname))) {
robjs.insert(s);
}
}
}
std::set<struct bv_scene_obj *>::iterator r_it;
for (r_it = robjs.begin(); r_it != robjs.end(); r_it++) {
struct bv_scene_obj *s = *r_it;
bv_obj_put(s);
}
struct bu_vls nroot = BU_VLS_INIT_ZERO;
bu_vls_sprintf(&nroot, "ged::rtcheck_ovlps");
BViewState *bvs = gedp->dbi_state->GetBViewState();
bvs->RemoveObjs(bu_vls_cstr(&nroot));
/* Add any visual output generated by rtcheck */
if (rtcp->vbp) {
int have_visual = 0;
for (i = 0; i < rtcp->vbp->nused; i++) {
if (!BU_LIST_IS_EMPTY(&(rtcp->vbp->head[i]))) {
have_visual = 1;
break;
}
}
if (have_visual) {
bu_log("final nused: %zu\n", rtcp->vbp->nused);
bv_vlblock_obj(rtcp->vbp, gedp->ged_gvp, sname);
}
ged_vlblock_scene_obj(gedp, gedp->ged_gvp, bu_vls_cstr(&nroot), rtcp->vbp);
}
bu_vls_free(&nroot);
}
if (rtcp->read_failed && rtcp->draw_read_failed) {
+23 -21
View File
@@ -151,7 +151,7 @@ _select_cmd_list(void *bs, int argc, const char **argv)
DbiState *dbis = (DbiState *)gedp->dbi_state;
if (!argc) {
std::vector<std::string> ssets = dbis->list_selection_sets();
std::vector<std::string> ssets = dbis->FindSelectionSets();
for (size_t i = 0; i < ssets.size(); i++) {
bu_vls_printf(gedp->ged_result_str, "%s\n", ssets[i].c_str());
}
@@ -159,15 +159,15 @@ _select_cmd_list(void *bs, int argc, const char **argv)
}
const char *sname = argv[0];
std::vector<BSelectState *> ss = dbis->get_selected_states(sname);
std::vector<std::string> ss = dbis->FindSelectionSets(sname);
if (!ss.size()) {
bu_vls_printf(gedp->ged_result_str, ": %s does not match any selection sets\n", sname);
return BRLCAD_ERROR;
}
for (size_t i = 0; i < ss.size(); i++) {
std::vector<std::string> paths = ss[i]->list_selected_paths();
BSelectState *s = dbis->GetSelectionSet(ss[i].c_str());
std::vector<std::string> paths = s->FindSelectedPaths(NULL);
for (size_t j = 0; j < paths.size(); j++) {
bu_vls_printf(gedp->ged_result_str, "%s\n", paths[j].c_str());
}
@@ -201,15 +201,18 @@ _select_cmd_clear(void *bs, int argc, const char **argv)
sname = bu_vls_cstr(&gd->curr_set);
}
std::vector<BSelectState *> ss = dbis->get_selected_states(sname);
if (!ss.size()) {
std::vector<std::string> ssets = dbis->FindSelectionSets(sname);
if (!ssets.size()) {
if (sname)
bu_vls_printf(gedp->ged_result_str, ": %s does not match any selection sets\n", sname);
return BRLCAD_ERROR;
}
for (size_t i = 0; i < ss.size(); i++) {
ss[i]->clear();
for (size_t i = 0; i < ssets.size(); i++) {
BSelectState *s = dbis->GetSelectionSet(ssets[i].c_str());
if (!s)
continue;
s->Clear();
}
return BRLCAD_OK;
@@ -244,8 +247,9 @@ _select_cmd_add(void *bs, int argc, const char **argv)
if (bu_vls_strlen(&gd->curr_set))
sname = bu_vls_cstr(&gd->curr_set);
std::vector<BSelectState *> ss = dbis->get_selected_states(sname);
if (ss.size() != 1) {
std::vector<std::string> ss = dbis->FindSelectionSets(sname);
BSelectState *s = (ss.size() == 1) ? dbis->GetSelectionSet(ss[0].c_str()) : NULL;
if (!s) {
if (sname)
bu_vls_printf(gedp->ged_result_str, ": %s does not match one selection set\n", sname);
return BRLCAD_ERROR;
@@ -256,15 +260,12 @@ _select_cmd_add(void *bs, int argc, const char **argv)
bu_vls_sprintf(&dpath, "%s", argv[i]);
if (bu_vls_cstr(&dpath)[0] != '/')
bu_vls_prepend(&dpath, "/");
if (!ss[0]->select_path(bu_vls_cstr(&dpath), false)) {
if (!s->Select(bu_vls_cstr(&dpath), true)) {
bu_vls_printf(gedp->ged_result_str, "Selection set %s: unable to add path: %s", (sname) ? sname : "default", argv[i]);
bu_vls_free(&dpath);
return BRLCAD_ERROR;
}
}
ss[0]->characterize();
bu_vls_free(&dpath);
return BRLCAD_OK;
@@ -298,8 +299,9 @@ _select_cmd_rm(void *bs, int argc, const char **argv)
if (bu_vls_strlen(&gd->curr_set))
sname = bu_vls_cstr(&gd->curr_set);
std::vector<BSelectState *> ss = dbis->get_selected_states(sname);
if (ss.size() != 1) {
std::vector<std::string> ss = dbis->FindSelectionSets(sname);
BSelectState *s = (ss.size() == 1) ? dbis->GetSelectionSet(ss[0].c_str()) : NULL;
if (!s) {
if (sname)
bu_vls_printf(gedp->ged_result_str, ": %s does not match one selection set\n", sname);
return BRLCAD_ERROR;
@@ -310,7 +312,7 @@ _select_cmd_rm(void *bs, int argc, const char **argv)
bu_vls_sprintf(&dpath, "%s", argv[i]);
if (bu_vls_cstr(&dpath)[0] != '/')
bu_vls_prepend(&dpath, "/");
if (!ss[0]->deselect_path(bu_vls_cstr(&dpath), false)) {
if (!s->DeSelect(bu_vls_cstr(&dpath), true)) {
bu_vls_printf(gedp->ged_result_str, "Selection set %s: unable to remove path: %s", (sname) ? sname : "default", argv[i]);
bu_vls_free(&dpath);
return BRLCAD_ERROR;
@@ -318,11 +320,10 @@ _select_cmd_rm(void *bs, int argc, const char **argv)
}
bu_vls_free(&dpath);
ss[0]->characterize();
return BRLCAD_OK;
}
#if 0
int
_select_cmd_collapse(void *bs, int argc, const char **argv)
{
@@ -419,12 +420,13 @@ _select_cmd_expand(void *bs, int argc, const char **argv)
return BRLCAD_OK;
}
#endif
const struct bu_cmdtab _select_cmds[] = {
{ "add", _select_cmd_add},
{ "clear", _select_cmd_clear},
{ "collapse", _select_cmd_collapse},
{ "expand", _select_cmd_expand},
//{ "collapse", _select_cmd_collapse},
//{ "expand", _select_cmd_expand},
{ "list", _select_cmd_list},
{ "rm", _select_cmd_rm},
{ (char *)NULL, NULL}
+12 -19
View File
@@ -39,25 +39,20 @@
void
dm_refresh(struct ged *gedp, int vnum)
{
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
struct bview *v = (struct bview *)BU_PTBL_GET(views, vnum);
struct bview *v = (struct bview *)BU_PTBL_GET(&gedp->ged_views, vnum);
if (!v)
return;
DbiState *dbis = (DbiState *)gedp->dbi_state;
BViewState *bvs = dbis->get_view_state(v);
dbis->update();
std::unordered_set<struct bview *> uset;
uset.insert(v);
bvs->redraw(NULL, uset, 1);
BViewState *bvs = gedp->dbi_state->GetBViewState(v);
gedp->dbi_state->Sync();
struct dm *dmp = (struct dm *)v->dmp;
unsigned char *dm_bg1;
unsigned char *dm_bg2;
dm_get_bg(&dm_bg1, &dm_bg2, dmp);
dm_set_bg(dmp, dm_bg1[0], dm_bg1[1], dm_bg1[2], dm_bg2[0], dm_bg2[1], dm_bg2[2]);
dm_set_dirty(dmp, 0);
dm_draw_objs(v, NULL, NULL);
dm_draw_end(dmp);
bvs->Redraw(false);
bvs->Render();
}
int
@@ -76,8 +71,7 @@ img_cmp(int vnum, int id, struct ged *gedp, const char *cdir, int soft_fail)
dm_refresh(gedp, vnum);
struct bu_ptbl *views = bv_set_views(&gedp->ged_views);
struct bview *v = (struct bview *)BU_PTBL_GET(views, vnum);
struct bview *v = (struct bview *)BU_PTBL_GET(&gedp->ged_views, vnum);
if (!v)
bu_exit(EXIT_FAILURE, "Invalid view specifier: %d\n", vnum);
struct dm *dmp = (struct dm *)v->dmp;
@@ -187,23 +181,22 @@ main(int ac, char *av[]) {
gedp->new_cmd_forms = 1;
bu_setenv("DM_SWRAST", "1", 1);
// We don't want the default GED views for this test
bv_set_rm_view(&gedp->ged_views, NULL);
// Set up the views. Unlike the other drawing tests, we are explicitly
// out to test the behavior of multiple views and dms, so we need to
// set up multiples. We'll start out with four non-independent views,
// to mimic the most common multi-dm/view display - a Quad view widget.
// Each view will get its own attached swrast DM.
//
// TODO - properly add BViewStates to DbiState
struct bview *views[4];
for (size_t i = 0; i < 4; i++) {
for (size_t i = 1; i < 4; i++) {
BU_GET(views[i], struct bview);
if (!i)
gedp->ged_gvp = views[i];
struct bview *v = views[i];
bv_init(v, &gedp->ged_views);
bv_init(v);
bu_vls_sprintf(&v->gv_name, "V%zd", i);
bv_set_add_view(&gedp->ged_views, v);
bu_ptbl_ins(&gedp->ged_views, (long *)v);
bu_ptbl_ins(&gedp->ged_free_views, (long *)v);
/* To generate images that will allow us to check if the drawing
+1 -4
View File
@@ -30,8 +30,6 @@
#include <dm.h>
#include <ged.h>
#include "../../dbi.h"
extern "C" void ged_changed_callback(struct db_i *UNUSED(dbip), struct directory *dp, int mode, void *u_data);
extern "C" int img_cmp(int id, struct ged *gedp, const char *cdir, bool clear_scene, bool clear_image, int soft_fail, int approximate_check, const char *clear_root, const char *img_root);
@@ -249,7 +247,6 @@ main(int ac, char *av[]) {
// Set up new cmd data (not yet done by default in ged_open
gedp->dbi_state = new DbiState(gedp);
DbiState *dbis = (DbiState *)gedp->dbi_state;
gedp->new_cmd_forms = 1;
bu_setenv("DM_SWRAST", "1", 1);
@@ -607,7 +604,7 @@ main(int ac, char *av[]) {
s_av[3] = "all.bot";
s_av[4] = NULL;
ged_exec_facetize(gedp, 4, s_av);
dbis->update();
dbis->Sync();
s_av[0] = "draw";
+2 -4
View File
@@ -100,9 +100,7 @@ main(int ac, char *av[]) {
// Set up new cmd data (not yet done by default in ged_open
gedp->dbi_state = new DbiState(gedp);
DbiState *dbis = (DbiState *)gedp->dbi_state;
gedp->new_cmd_forms = 1;
gedp->ged_lod = bv_mesh_lod_context_create(gedp->dbip->dbi_filename);
bu_setenv("DM_SWRAST", "1", 1);
// Set callback so database changes will update dbi_state
@@ -157,7 +155,7 @@ main(int ac, char *av[]) {
s_av[3] = "all.bot";
s_av[4] = NULL;
ged_exec_facetize(gedp, 4, s_av);
dbis->update();
dbis->Sync();
s_av[0] = "ae";
s_av[1] = "35";
@@ -241,7 +239,7 @@ main(int ac, char *av[]) {
s_av[3] = "all.brep";
s_av[4] = NULL;
ged_exec_brep(gedp, 4, s_av);
dbis->update();
dbis->Sync();
bu_log("Sanity - testing shaded mode 1 (triangle only) drawing, Level-of-Detail disabled...\n");
s_av[0] = "view";

Some files were not shown because too many files have changed in this diff Show More