The Vish Visualization Shell 0.3
Vish
SeagrassBoundingVolume.cpp

Draw the bounding box of some VObject, if that one provides the respective information as an interface.

Draw the bounding box of some VObject, if that one provides the respective information as an interface.This example demonstrates uses Render Anemone objects to perform the actual rendering. A Render Anemone is an Vish object to encapsulate rendering operations, see Wizt::Anemone for detailed documentation and the AnemoneBoundingVolume.cpp example, which demonstrates use of Render Anemones on a more basic level.

Associated with the Anemone is the Seagrass class, which provides cache management for Anemone objects. This example demonstrates how to make use of this Seagrass management, whereby the associated AnemoneCreator objects are stored in the object's local state object.

Storing AnemoneCreator with an object's local state object is the safest way to store them, as those AnemoneCreator will vanish automatically if the object dies. However, this is not the only possible scenario. AnemoneCreator may also be stored at some data objects to allow them to be shared across visualization modules: Two visualization modules will then use exactly the same rendering Anemones if they are based on the same data. This is however advanced usage and needs to be done very cautiously. The example given here is thus a very simple, but frequently applicable version which already provides all of the require efficient and safe cache management.

#include <ocean/plankton/VPipeline.hpp>
#include <ocean/GLvish/VGLRenderObject.hpp>
#include <eagle/PhysicalSpace.hpp>
#include <eagle/GL/EagleGL.hpp>
#include <ocean/GLvish/BoundingBox.hpp>
#include <ocean/GLvish/GLFonts.hpp>
#include <ocean/Anemonia/Seagrass.hpp>
using namespace Wizt;
using namespace Eagle;
namespace
{
class BoundingBoxRenderer : public VGLRenderObject
{
public:
TypedSlot<double> Thickness,
FontSize;
struct MyState : State
{
FontAnemoneCreator,
BoxAnemoneCreator,
CornerAnemoneCreator;
};
RefPtr<State> newState() const override
{
return new MyState();
}
BoundingBoxRenderer(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
: VGLRenderObject(name, p, VP)
, myData( this, "source", VBoundingBox() )
, Thickness(this, "thickness", 1.5, NullPtr(), 5)
, FontSize(this, "fontsize", 1.0, NullPtr(), 0)
{
FontSize.setProperty("max",10.0);
Thickness.setProperty("max",10.0);
}
bool update(VRequest&Context, double precision) override;
bool renderGL(VGLRenderContext&Context) const override;
static string createChildname(const string&parent_name)
{
return "BoundingVolumeOf" + parent_name;
}
};
bool BoundingBoxRenderer::update(VRequest&Context, double precision)
{
myData << Context >> BBox;
if (!BBox)
{
resetBBox( Context );
return true;
}
setBoundingBall(Context, BBox);
return true;
}
class FontTentacle : public Anemone::SpecializedTentacle<Anemone::DisplayLists>
{
public:
string text;
double FontScale;
FontTentacle(const string&txt,
const Eagle::PhysicalSpace::point&thePosition,
double theFontScale,
: text(txt)
, Position( thePosition )
, FontScale ( theFontScale )
, myFont( theFont )
{
myFont->setSize(2);
}
bool activate(const Anemone&) override
{
float llx, lly, llz, urx, ury, urz;
glPushMatrix();
glTranslate( Position );
myFont->getBBox( text.c_str(), llx, lly, llz, urx, ury, urz);
glTranslatef( -FontScale*(urx-llx)/2, -(ury-lly), 0);
glScalef(FontScale, FontScale, FontScale );
myFont->render(text.c_str() );
glPopMatrix();
return true;
}
bool deactivate(const Anemone&) override
{
return true;
}
};
bool BoundingBoxRenderer::renderGL(VGLRenderContext&Context) const
{
myData << Context >> IB;
if (!IB)
return false;
using namespace Eagle::PhysicalSpace;
point P0 = IB->center(),
P1 = IB->center();
if (BB)
{
P0 = BB->mincoord();
P1 = BB->maxcoord();
}
else
{
for(int i=0; i<P0.SIZE; i++)
{
P0[i] -= IB->radius();
P1[i] += IB->radius();
}
}
/*
Get the local state object
*/
RefPtr<MyState> S = myState(Context);
/*
If there are no Anemone Creators yet, create them.
Note that we cannot do that in the constructor of the
state object because AnemoneCreators require a Seagrass
object, which is only provided in the render() function.
Optionally we could create and set MyState object explicitly
here and add it to the object state.
*/
if (!S->FontAnemoneCreator)
S->FontAnemoneCreator = new AnemoneCreator<>( Context.getSeagrass() );
assert(S->FontAnemoneCreator);
if (!S->BoxAnemoneCreator)
S->BoxAnemoneCreator = new AnemoneCreator<>( Context.getSeagrass() );
assert(S->BoxAnemoneCreator);
if (!S->CornerAnemoneCreator)
S->CornerAnemoneCreator = new AnemoneCreator<>( Context.getSeagrass() );
assert(S->CornerAnemoneCreator);
/*
Taking care of the text display.
*/
double FontScale = 1.0;
FontSize << Context >> FontScale;
if (FontScale>0.0)
{
RefPtr<Anemone> FontAnemone = S->FontAnemoneCreator->create();
{
float front_emission[4] = { 0.3, 0.2, 0.1, 0.0 };
float front_ambient[4] = { 0.2, 0.2, 0.2, 0.0 };
float front_diffuse[4] = { 0.95, 0.95, 0.8, 0.0 };
float front_specular[4] = { 0.6, 0.6, 0.6, 0.0 };
glMaterialfv(GL_FRONT, GL_EMISSION, front_emission);
glMaterialfv(GL_FRONT, GL_AMBIENT, front_ambient);
glMaterialfv(GL_FRONT, GL_DIFFUSE, front_diffuse);
glMaterialfv(GL_FRONT, GL_SPECULAR, front_specular);
glMaterialf(GL_FRONT, GL_SHININESS, 16.0);
glColor4fv(front_diffuse);
glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_FALSE);
glColorMaterial(GL_FRONT, GL_DIFFUSE);
glEnable(GL_COLOR_MATERIAL);
glDisable( GL_TEXTURE_2D);
glEnable( GL_DEPTH_TEST);
glDisable( GL_BLEND);
}
glEnable( GL_NORMALIZE );
if (FontAnemone->empty() )
{
FontAnemone->CacheInfoString = "FontAnemone";
{
if (MyFont)
{
MyFont->setSize(2);
{
char coords0[2048];
sprintf(coords0,"(%lg,%lg,%lg)", P0[0], P0[1], P0[2] );
Ref<FontTentacle> TextAtP0( coords0, P0, FontScale, MyFont);
FontAnemone->insert( TextAtP0 );
}
{
char coords1[2048];
sprintf(coords1,"(%lg,%lg,%lg)", P1[0], P1[1], P1[2] );
Ref<FontTentacle> TextAtP1( coords1, P1, FontScale, MyFont);
FontAnemone->insert( TextAtP1 );
}
}
else
puts("font not found");
}
}
FontAnemone->wave();
}
/*
Drawing the bounding box with round corners.
*/
// printf("BBOX: %lg,%lg,%lg <-> %lg,%lg,%lg\n",
// P0[0], P0[1], P0[2],
// P1[0], P1[1], P1[2] );
point P000 ( P0.x(), P0.y(), P0.z() ),
P001 ( P0.x(), P0.y(), P1.z() ),
P010 ( P0.x(), P1.y(), P0.z() ),
P011 ( P0.x(), P1.y(), P1.z() ),
P100 ( P1.x(), P0.y(), P0.z() ),
P101 ( P1.x(), P0.y(), P1.z() ),
P110 ( P1.x(), P1.y(), P0.z() ),
P111 ( P1.x(), P1.y(), P1.z() );
/*
This code is inspired by
http://www.bluevoid.com/opengl/sig00/advanced00/notes/node290.html
*/
/*
Same as mentioned above, this OpenGL code should go into
an existing Tentacle as provided by the RenderContext instead.
*/
double width = 20;
Thickness << Context >> width;
if (width<0.01) width=0.01;
glLineWidth(width);
glEnable(GL_LINE_SMOOTH);
glDisable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glColor3f( 0.5, 0.7, 0.6);
RefPtr<Anemone> BBoxAnemone = S->BoxAnemoneCreator->create();
if (BBoxAnemone->empty() )
{
BBoxAnemone->CacheInfoString = "BBoxAnemone";
{
MemVector<point> BoxVertices(24);
BoxVertices[ 0] = P000; BoxVertices[ 1] = P010;
BoxVertices[ 2] = P010; BoxVertices[ 3] = P011;
BoxVertices[ 4] = P011; BoxVertices[ 5] = P001;
BoxVertices[ 6] = P001; BoxVertices[ 7] = P000;
BoxVertices[ 8] = P100; BoxVertices[ 9] = P110;
BoxVertices[10] = P110; BoxVertices[11] = P111;
BoxVertices[12] = P111; BoxVertices[13] = P101;
BoxVertices[14] = P101; BoxVertices[15] = P100;
BoxVertices[16] = P000; BoxVertices[17] = P100;
BoxVertices[18] = P010; BoxVertices[19] = P110;
BoxVertices[20] = P011; BoxVertices[21] = P111;
BoxVertices[22] = P001; BoxVertices[23] = P101;
BBoxAnemone->insert( Context.createCoordinates( BoxVertices ) );
}
BBoxAnemone->insert( Context.drawPrimitives( RenderBasin::LINES ) );
}
// actual rendering
BBoxAnemone->wave();
glEnable(GL_POINT_SMOOTH);
glPointSize(width);
RefPtr<Anemone> BBoxCornerAnemone = S->CornerAnemoneCreator->create();
if (BBoxCornerAnemone->empty() )
{
BBoxCornerAnemone->CacheInfoString = "BBoxCornerAnemone";
{
MemVector<point> BoxVertices(8, true); // reserve space for 8 points
BoxVertices.push_back( P000 );
BoxVertices.push_back( P010 );
BoxVertices.push_back( P011 );
BoxVertices.push_back( P001 );
BoxVertices.push_back( P100 );
BoxVertices.push_back( P110 );
BoxVertices.push_back( P111 );
BoxVertices.push_back( P101 );
BBoxCornerAnemone->insert( Context.createCoordinates( BoxVertices ) );
}
BBoxCornerAnemone->insert( Context.drawPrimitives( RenderBasin::POINTS ) );
}
// actual rendering
BBoxCornerAnemone->wave();
return true;
}
static VSink< AcceptList<VBoundingBox>, BoundingBoxRenderer>
ThisIsMyGreatCreator("Display/SeagrassBoundingVolume", ObjectQuality::EXPERIMENTAL);
}
A set of variable names, with indices associated to each type.
Definition Context.hpp:18
A point in physical 3D space.
Definition elementary/eagle/PhysicalSpace.hpp:106
A reference counting pointer class which keeps objects alive as long as strong pointers to these obje...
Definition RefPtr.hpp:405
Base class for Tentacles that are specialized for a specific purpose.
Definition Anemone.hpp:420
Abstract object for elementary render objects.
Definition Anemone.hpp:39
An input slot for VObjects, bound to a specific type.
Definition TypedSlot.hpp:57
bool setProperty(const string &theName, const Type &theValue) const
Set a property of the parameter that is associated with this slot.
Definition TypedSlot.hpp:718
Base class for objects that implement a drawing routine using OpenGL.
Definition VGLRenderObject.hpp:20
Request structure.
Definition VRequest.hpp:24
MemCore::RefPtr< Eagle::BoundingBox > VBoundingBox
The Vish type to communicate bounding boxes.
Definition ocean/shrimp/BoundingBox.hpp:27
Geometric algebra of the physical 3D-space, by which we mean the Clifford algebara over Euclidean,...
Definition AnalyticFunction.hpp:31
Gather general basic mathematic functions which are not available in cmath here.
Definition Context.cpp:7
std::nullptr_t NullPtr
A type indicating an invalid pointer, similar to the NULL pointer in C, but type-safe.
Definition DynPtr.hpp:368
The Vish namespace.
Definition Anemone.cpp:17
A convenience class that looks like a std::vector<>, but is actually referring to a reference-counted...
Definition elementary/memcore/Chunk.hpp:515
Pointer to a refcountable object which automatically initializes the pointer with constructing an obj...
Definition RefPtr.hpp:1138
The Anemone Cache, called the Seagrass, is based on Anemone objects.
Definition Seagrass.hpp:282
A special vish context that is passed to VGLRenderObjects when rendering.
Definition VGLRenderContext.hpp:35
Implements a data sink.
Definition VPipeline.hpp:73