FragmentBoxes.cpp

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