Draw a bounding box for a Grid object residing in the fiber bundle. Refinement representations and field fragments are supported (which constitutes AMR).
For each coordinate field, the bounding box is stored with the field and thus re-used if possible. Also, there might be an field in the same data represention be specified. The bounding box information of this field is then shown in addition. This field may consist of various fragments, such that multiple bounding boxes are shown. The bounding box information is cached at each field fragment.
If values in field coordinates are changed, this is not recognized. Code doing so would have to clear the field's FragmentBoxes interface.
#include <bone/BundleInput.hpp> #include <bone/GridObject.hpp> #include <bone/FishField.hpp> #include <bone/FieldObject.hpp> #include <ocean/shrimp/VEnum.hpp> #include <ocean/GLvish/BoundingBox.hpp> #include <ocean/eagle/PhysicalSpace.hpp> #include <fish/lakeview/eye/retina/VFieldRenderObject.hpp> #include <baseop/ExpandBBox.hpp> using namespace Wizt; using namespace Fiber; using namespace Eagle; namespace { class VFragmentBoxes : virtual public VFieldRenderObject, virtual public Fish<Fiber::Skeleton> { public: struct FieldState : State, FieldFragmentIterator { RefPtr<Field> CurrentCoords; RefPtr<BoundingBox> FieldBBox; std::vector<RefPtr<BoundingBox> > BBoxes; override bool apply(const RefPtr<FragmentID>&f, const RefPtr<CreativeArrayBase>&CAB); }; override RefPtr<State> newState() const { return new FieldState(); } TypedSlot<int> Thickness; VFragmentBoxes(const string&name, int p, const RefPtr<VCreationPreferences>&VP) : VGLRenderObject(name, p, VP) , Fish<VObject>(this) , Fish<Field>("field") , VFieldRenderObject(name, p, VP) , Thickness(this, "thickness", 20, 5) {} override bool update(VRequest&R, double precision); override void render(VGLRenderContext&Context) const; static string createChildname(const string&obj) { return "FragmentBBox(" + obj + ")"; } }; /* Bounding box field state iterator callback function: Called for each fragment of an (optional) field. Determines the bounding box for the respective field fragments using the global coordinate information. */ bool VFragmentBoxes::FieldState::apply(const RefPtr<FragmentID>&fid, const RefPtr<CreativeArrayBase>&FragmentDataCreator) { using namespace Eagle::PhysicalSpace; // printf("bool VFragmentBoxes::FieldState::apply(const RefPtr<FragmentID>&f, CreativeArrayBase&CAB): %d boxes\n", BBoxes.size() ); if (!CurrentCoords) { printf("bool VFragmentBoxes::FieldState::apply(const RefPtr<FragmentID>&, CreativeArrayBase&): NO COORDINATES!\n" ); return false; } if (RefPtr<BoundingBox> BBox = getFragmentBBox(fid, FragmentDataCreator, *CurrentCoords) ) { BBoxes.push_back( BBox ); FieldBBox->insert( *BBox ); } return true; } /* Update function: evaluates the current parameter settings and determines the bounding box information for the entire representation, plus the field fragments if a field is specified. */ bool VFragmentBoxes::update(VRequest&Context, double precision) { struct DataExtractor : LevelIterator { RefPtr<FieldState> S; string Fieldname; override bool apply(const RefPtr<Fiber::Representation>&CartesianLevelRep, double time, int Level, const RefPtr<Fiber::Grid>&GridWithCoarsetRefinementLevel, const RefPtr<ValuePool>&Context) { RefPtr<Field> Coords = CartesianLevelRep->Positions(); RefPtr<Field> DataField = (*CartesianLevelRep)(Fieldname); // printf("LEVEL %d\n", Level); // CartesianLevelRep.speak("CartesianLevelRep"); S->CurrentCoords = Coords; DataField->iterate( *S ); return true; } } DE; DE.S = myState(Context); DE.S->FieldBBox = new BoundingBox(); DE.S->BBoxes.clear(); DE.Fieldname = getFieldname(Context); IterateLevels(DE, Context); if (DE.S->FieldBBox) DE.S->FieldBBox->updateBall(); setBoundingBall(Context, DE.S->FieldBBox); return true; } void VFragmentBoxes::render(VGLRenderContext&Context) const { RefPtr<FieldState> myState = getState(Context); if (!myState) return; RefPtr<BoundingBox> MyBBox = myState->FieldBBox; using namespace Eagle::PhysicalSpace; int width = 20; Thickness << Context >> width; glLineWidth(width/10.0); glEnable(GL_LINE_SMOOTH); glEnable(GL_POINT_SMOOTH); glPointSize(width/10.0); glColor3f( 0.6, 0.7, 0.9); glDisable(GL_LIGHTING); glEnable( GL_DEPTH_TEST ); if (MyBBox && !MyBBox->empty() ) glDraw( *MyBBox ); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable( GL_BLEND ); glColor4f( 0.6, 0.2, 0.1, 0.5); for(unsigned i=0; i<myState->BBoxes.size(); i++) { if (!myState->BBoxes[ i ] ) continue; #if 0 if (RefPtr<BoundingBox> BBox = myState->BBoxes[i]) printf("RENDER: (%lg,%lg,%lg)-(%lg,%lg,%lg)\n", BBox->mincoord().x(), BBox->mincoord().y(), BBox->mincoord().z(), BBox->maxcoord().x(), BBox->maxcoord().y(), BBox->maxcoord().z() ); #endif glDraw( *myState->BBoxes[ i ] ); } } static Ref<VCreator<VFragmentBoxes, AcceptList<Fiber::Field> > > myCreator("Display/FragmentBoxes", ObjectQuality::MATURE); } // namespace