MonochromeSurface.cpp

MonochromeSurface.jpg

Spherical surface displayed via MonochromeSurface module.

Display a triangular surface in monochrome colors. Very minimalistic simple code.

More advanced surface renderers are PolychromeSurface, TransparentSurface and CrystalSurface_8cpp-example.html ( CrystalSurface.cpp ).

#include <ocean/plankton/VCreator.hpp>

#include <ocean/GLvish/VGLRenderObject.hpp>
#include <ocean/GLvish/BoundingBox.hpp>
#include <ocean/GLvish/ArrayTypes.hpp>
#include <ocean/GLvish/colors.hpp>

//#include <ocean/shrimp/VObjectStatus.hpp> 
#include <ocean/shrimp/VEnum.hpp>

#include <ocean/eagle/PhysicalSpace.hpp>

#include <field/Cell.hpp>
#include <GL/fiberGL.hpp>

#include <baseop/ExpandBBox.hpp>
#include <eye/retina/VSkeletonRenderObject.hpp>
#include <grid/types/TriangularSurface.hpp>
#include <bundle/BundleProperty.hpp>
#include <bone/GridActor.hpp>

using namespace Wizt;
using namespace Fiber;
using namespace Eagle;

namespace
{


class   MonochromeSurface : public VSkeletonRenderObject
{
public:

        struct MyState : State, TriangularSurface
        {
                using TriangularSurface::operator=;
        };
        
        override RefPtr<State> newState() const
        {
                return new MyState();
        }

        TypedSlot<rgba_float_t> SurfaceColor;

        TypedSlot<VEnum>        SurfaceMode;

        MonochromeSurface(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
        : VGLRenderObject(name,DEFAULT_OBJECT, VP)
        , Fish<VObject>(this)
        , VSkeletonRenderObject(name, DEFAULT_OBJECT, VP)
        , SurfaceColor(this, "color", makeColor(.8,.5,.1, 1.0),0)
        , SurfaceMode(this, "mode", VEnum(0, "solid", "line", "points") )
        {}

        override void render(VGLRenderContext&Context) const;
        override bool update(VRequest&R, double precision);

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

};


bool MonochromeSurface::update(VRequest&Context, double precision)
{
RefPtr<MyState> S = myState(Context);

RefPtr<Grid>  G = findMostRecentGrid( Context );
        if (!G)
        {
                removeState(Context);
                return setStatusError(Context, "No Grid found.");
        } 

        /*
          Assign grid pointer to TriangularSurface, which investigates
          the Grid for properties conforming to a TriangularSurface.
          If the Grid is not a TriangularSurface, then the following
          status check witll return false.
         */
        *S = G;

        if (!*S)
                return setStatusError(Context, "No surface available.");

        setBoundingBall(Context, getBoundingBox( S->CoordField ) );

        return setStatusInfo(Context, "Surface ready to render.");
}


/*
  VBO render call back, allows to set the
  glPolygonMode .
  http://www.opengl.org/sdk/docs/man/xhtml/glPolygonMode.xml
 */
struct  TriangleRenderer : VBO::Renderer
{
        RefPtr<TriangularSurface::CellArray_t>  Cells;

        /*
           GL_FRONT for front-facing polygons,
           GL_BACK for back-facing polygons,
           or GL_FRONT_AND_BACK
        */
        GLenum          face;

        /*
          Specifies how polygons will be rasterized.
          Accepted values are
          GL_POINT,
          GL_LINE, and
          GL_FILL.
        */
        GLenum  mode;

        void setMode(int i)
        {
                switch(i)
                {
                case 0: mode = GL_FILL; break;
                case 1: mode = GL_LINE; break;
                case 2: mode = GL_POINT; break;
                }
        }
                
        TriangleRenderer(const RefPtr<TriangularSurface::CellArray_t>&TriangleCells)
        : Cells(TriangleCells)
        , face(GL_FRONT_AND_BACK)
        , mode(GL_FILL)
        {
                mode = GL_LINE;
        }

        override void prefix()
        {
                glPolygonMode( face, mode);

                glEnable(GL_NORMALIZE); 
                glDisable( GL_BLEND );
        }

        override bool draw() 
        {
        MultiArray<1, TriangleCell> Triangles = *Cells;
                glPolygonMode( face, mode);
                GL::DrawElements( Triangles ); 
                return true;
        }

};

void MonochromeSurface::render(VGLRenderContext&Context) const
{
RefPtr<MyState> myState = getState(Context); 
        if (!myState)
                return;

TriangularSurface&Surface = *myState; 
        if (!Surface)
                return;

        if (!Surface.CoordField)
        {
                printf("Did not find coordinates :( \n");
                return;
        } 

        if (!Surface.CellField)
        {
                printf("Did not find cells :(  \n"); 
//                     Typename( Surface.CellField->getFieldStorageType() ).c_str() ); 
                return;
        }
        if (!Surface.CellField->getData())
        {
//              printf("Did not find cells :(  %s\n",
//                     Typename( Surface.CellField->getFieldStorageType() ).c_str() ); 

//              Surface.CellField.Speak("               Surface.CellField");
//              Surface.CellField->getCreator().Speak("         Surface.CellField->getCreator()");
//              Surface.CellField->getData().Speak("            Surface.CellField->getData()");

                puts("MonochromeSurface: No triangles.");
                return;
        }


// 
// Generic OpenGL section, these settings affect all VBO's rendered later 
//
        glEnable(GL_LIGHTING);

        glMaterialf( GL_FRONT, GL_SHININESS,  3 );
        glMaterialf( GL_BACK , GL_SHININESS, 50 ); 

        glMaterial( GL::FRONT_AND_BACK, GL::AMBIENT , makeColor( 0,0,.01,0) );
        glMaterial( GL::FRONT_AND_BACK, GL::SPECULAR, makeColor( 0.5,0.5,.53, 0) );
        glMaterial( GL::FRONT_AND_BACK, GL::EMISSION, makeColor( 0., 0.,0., 0) );
        glColor4f(1,0,0, 0.5); 

        glLightModeli(GL_LIGHT_MODEL_TWO_SIDE, GL_TRUE); 
        glColorMaterial( GL_FRONT_AND_BACK, GL_DIFFUSE);
        glEnable( GL_COLOR_MATERIAL );

rgba_float_t    SurfColor( makeColor(1,0,0,0.5 ) );
        SurfaceColor << Context >> SurfColor; 

VEnum   Mode; 
        SurfaceMode << Context >> Mode;


//      glEnable( GL_DEPTH_TEST ); 
        //       glEnable( GL_MULTISAMPLE_ARB ); 
        // glEnable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB );

        glColor( SurfColor ); 


//      printf(">>>>>   MonochromeSurface: RENDER cells for t=%ld, %lu Triangles\n", 
//             myState->CellField->time_value(), Cells->nElements() );


/*
 Vertex Buffer Object (VBO) Access via GLCache,
 retrieve and re-use or generate new VBO 
 
 The caching mechanism is part of the "Visualization Cascade" and 
 described in the article: 

 @link http://sciviz.cct.lsu.edu/papers/2009/VizCascade.pdf Beyond the Visualization Pipeline: The Visualization Cascade @endlink
*/ 

const string VBOKey = ""; // This is an additional parameter for the OpenGL Cache. 
                          // It can be an arbitrary string, and this would be the 
                          // right place to use the name of a field fragment when 
                          // support for fragmented surfaces is added. For now, 
                          // such is not supported, and we can keep this key empty. 

RefPtr<ValueSet> V;     // This is a set of values for each of which there should 
                        // be one OpenGL cache entry generated. This means that if 
                        // a parameter is changed to a value that it already had 
                        // in the past, then the VBO that is associated with this 
                        // value will be re-used instead of newly generated. 
                        // Be *very* cautious about what values to use here, 
                        // since every cache entry eats up valueable memory at 
                        // the GPU. See documentation for class ValueSet on 
                        // how to assign values here.

RefPtr<VBO> myVBO;
        try
        {
                // n-dimensional readonly cache indexing (see VizCascade paper)
                myVBO = Context( *Surface )( typeid(*this) )( V )(VERTEXBUFFER(), VBOKey);

                //
                // Call the VBO if it's there and all ready to go. 
                //
                if (myVBO
                    && !myVBO->isOlderThan( *Surface.CellField)
                    && !myVBO->isOlderThan( *Surface.CoordField) )
                {
                        if (RefPtr<TriangleRenderer> TR = myVBO->getRenderer() )
                        {
                                TR->setMode( Mode.Case("solid", "line", "points") );
                                if (myVBO->call() )
                                {
                                        return;
                                }
                        }
                } 
                //  Cellfield is newer than surface view VBO, need to re-load VBO
        }
        catch(const GLCacheError&Err)
        {} 

        //
        // Create new VBO if it doesn't exist yet.
        //
        if (!myVBO)
                myVBO = Context[*Surface][ typeid(*this) ][ V ]( VERTEXBUFFER(), VBOKey); 

        assert( myVBO );
        myVBO->clear();

// 
// Loading fields as vertex arrays and append them to the VBO. 
// 
// Vertex arrays are loaded by appending objects that have been 
// derived from class BufferArray.
//
using namespace Eagle::PhysicalSpace; 

        // Note: this approach does not support fragmented surfaces.

        myVBO->append( new TypedVertexArray<point3>( myState->getCoords()->myChunk() ) ); 

        if (RefPtr<TriangularSurface::NormalVectorArray_t> VertexNormals = Surface.getNormals() )
        {
                myVBO->append( new TypedNormalArray<bivector3>( VertexNormals->myChunk() ));
        }

RefPtr<TriangleRenderer> TR = new TriangleRenderer(myState->CellField->getData() ); 
        TR->setMode( Mode.Case("solid", "line", "points") ); 
        myVBO->setRenderer( TR );

        myVBO->call();
}


//
// Object Creation
//

struct  GridInspector
{
static  SkeletonExistence InspectionProperty()
        {
                return SkeletonExistence( TriangularSurface::ID() );
        }
};

static  Ref<GridActor<GridInspector, MonochromeSurface> > 
        MyMonochromeSurfaceCreator("Display/MonochromeSurface",  ObjectQuality::MATURE);

} // anon namespace