VISH  0.2
AnemoneBoundingVolume.cpp

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 BoundingVolume.cpp example, which demonstrates drawing a Bounding Volume using raw OpenGL, without the Anemone object.

See also:
SeagrassBoundingVolume.cpp for an advanced version involving MemCore Cache Management of Limited Resources management through the Seagrass class.
#include <ocean/plankton/VPipeline.hpp>
#include <ocean/GLvish/VGLRenderObject.hpp>
#include <ocean/eagle/PhysicalSpace.hpp>
#include <ocean/eagle/GL/EagleGL.hpp>
#include <ocean/GLvish/BoundingBox.hpp>
#include <ocean/GLvish/GLFonts.hpp>

using namespace Wizt;
using namespace Eagle;

namespace
{


class   BoundingBoxRenderer : public VGLRenderObject
{
public:
        TypedSlot<VBoundingBox>         myData;
        TypedSlot<double>               Thickness,
                                        FontSize;

        TypedSlot<GLFontManager>        MyFonts;

        
        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)
        , MyFonts(this, "fonts", Empty(), 10 )
        {
                FontSize.setProperty("max",10.0);
                Thickness.setProperty("max",10.0);
        }

        override bool update(VRequest&Context, double precision);

        override void render(VGLRenderContext&Context) const;

static string createChildname(const string&parent_name)
        {
                return "BoundingVolumeOf" + parent_name;
        }
};


bool    BoundingBoxRenderer::update(VRequest&Context, double precision)
{
VBoundingBox    BBox;
        myData << Context >> BBox;
        if (!BBox)
        {
                resetBBox( Context );
                return true;
        }

        setBoundingBall(Context, BBox);
        return true;
}



class   FontTentacle : public Anemone::SpecializedTentacle<Anemone::DisplayLists>
{
public:
        string                          text;
        Eagle::PhysicalSpace::point     Position;
        double                          FontScale;
        RefPtr<GLFontManager::Font>     myFont;

        FontTentacle(const string&txt,
                     const Eagle::PhysicalSpace::point&thePosition,
                     double theFontScale,
                     const RefPtr<GLFontManager::Font>&theFont)
        : text(txt)
        , Position( thePosition )
        , FontScale ( theFontScale )
        , myFont( theFont )
        {
                myFont->setSize(2);
        }

        override bool activate(const Anemone&)
        {
        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;
        }

        override bool deactivate(const Anemone&)
        {
                return true;
        }
};


void    BoundingBoxRenderer::render(VGLRenderContext&Context) const
{
VBoundingBox    IB;
        myData << Context >> IB;
        if (!IB)
                return; 

using namespace Eagle::PhysicalSpace; 

point   P0 = IB->center(),
        P1 = IB->center(); 

RefPtr<BoundingBox> BB = IB; 
        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();
                }
        }

double  FontScale = 1.0;
        FontSize << Context >> FontScale;
        if (FontScale>0.0)
        {
        RefPtr<Anemone>  FontAnemone = new Anemone();

                if (GLFontManager*V = GLFontManagerCreator::getFontManager() )
                {
                RefPtr<GLFontManager::Font> MyFont = V->newFont("arial.ttf;Vera.ttf",';'); 
                        if (MyFont)
                        {
                                MyFont->setSize(2);
                                {
                                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 );

                                {
                                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 );
                                }


                                FontAnemone->wave();
                        } 
                        else
                                puts("font not found");
                } 
                else
                        puts("no font manager");

        }


//              printf("BBOX: %lg,%lg,%lg <-> %lg,%lg,%lg\n",
//                     P0[0], P0[1], P0[2],
//                     P1[0], P1[1], P1[2] ); 

double  width = 20;
        Thickness << Context >> width; 

        if (width<0.01) width=0.01;


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
*/ 
         glLineWidth(width);
         glEnable(GL_LINE_SMOOTH);

         glDisable(GL_LIGHTING);
         glEnable(GL_DEPTH_TEST); 

         glColor3f( 0.5, 0.7, 0.6); 

RefPtr<Anemone>  BBoxAnemone = new Anemone();
        {
        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 = new Anemone(); 
        {
        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();

}

static  VSink< AcceptList<VBoundingBox>, BoundingBoxRenderer> 
        ThisIsMyGreatCreator("Display/AnemoneBoundingVolume", ObjectQuality::DEMO);

}