FiberVISH 0.2
Fish - The Fiber Bundle API for the Vish Visualization Shell
TransparentColoredSurface.cpp
Spherical surface displayed via TransparentColoredSurface module.

Display a triangular surface as transparent object with a pretty shader using conventional depth-sorting (NOT depth-peeling).

The most simple version of a surface rendered is demonstrated by MonochromeSurface .

#include <ocean/plankton/VPipeline.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 <eagle/PhysicalSpace.hpp>
#include <field/Cell.hpp>
#include <GL/fiberGL.hpp>
#include <GL/FieldBuffer.hpp>
#include <baseop/ExpandBBox.hpp>
#include <eye/retina/VSkeletonRenderObject.hpp>
#include <grid/types/TriangularSurface.hpp>
#include <bundle/BundleProperty.hpp>
#include <bone/GridActor.hpp>
#include <GL/PartialElementRenderer.hpp>
#include <GLvish/Programmable.hpp>
#include <bone/FishField.hpp>
#include <ocean/GLvish/VGLColormap.hpp>
#include <baseop/GridField.hpp>
using namespace Wizt;
using namespace Fiber;
using namespace Eagle;
namespace
{
#define FSHADER_COLORMAP_NAME "ColormapTexture"
class TransparentColoredSurface : public VSkeletonRenderObject, public Programmable
{
public:
using glsl = RenderNamespace::glsl;
// temporary, should use triangular surface inspection here
// typedef Fiber::GridInspector<BundleProperty::Anything> GridInspector;
glsl vertex_shader(VRenderContext&Context) const override
{
return embed_glsl( {
#embed "TransparentColoredSurface.vert"
} );
}
glsl fragment_shader(VRenderContext&Context) const override
{
return embed_glsl( {
#embed "TransparentColoredSurface.frag"
} );
}
struct MyState : State, TriangularSurface
{
RefPtr<Field> ColorField;
string ColorFieldName,
ErrorMessage;
using TriangularSurface::operator=;
};
RefPtr<State> newState() const override
{
return new MyState();
}
TypedSlot<double> Transparency,
Shininess,
Alpha,
Speculartransparency;
TypedSlot<Range> InputRange;
TypedSlot<Field> SurfaceColorField;
enum { NumberOfInputFields = 1 };
// typedef LIST<double, LIST<float> > InputTypes;
typedef META::LIST<double> InputTypes;
TransparentColoredSurface(const string&name, int, const RefPtr<VCreationPreferences>&VP)
, Transparency(this, "transparency", 0.0, 0)
, Shininess(this, "shininess", 0.5, 0)
, Alpha(this, "alpha", 1.0, 2)
, Speculartransparency(this, "speculartransparency", 0.0,3)
, InputRange(this, "range", Range(0,1), 0 )
, Colormap(this, "colormap", NullPtr() )
, SurfaceColorField(this, "field" )
{}
bool renderGL(VGLRenderContext&Context) const override;
bool update(VRequest&R, double precision) override;
static string createChildname(const string&parent_name)
{
return "TransparentColoredSurface(" + parent_name + ")";
}
};
bool TransparentColoredSurface::update(VRequest&Context, double precision)
{
GridField GF(GS, FS, getTime(Context) );
/*
Fiber::Bundle::GridInfo_t GI = findMostRecentGrid( Context );
RefPtr<Grid> G = GI;
if (!G)
{
G = FS.getGrid();
if (!G)
{
removeState(Context);
return setStatusError(Context, "No Grid found.");
}
}
*/
RefPtr<MyState> S = myState(Context);
*S = GF;
if (!*S)
return setStatusError(Context, "No surface available.");
if (!S->CartesianVertices)
return setStatusError(Context, "No vertices on the surface available.");
S->ColorFieldName = FS();
S->ColorField = GF;
if (S->ColorField)
{
puts("YAYYYYYYYY HAVE COLORFIELD");
printf("And it should have a name: %s\n", S->ColorFieldName.c_str() );
}
else
puts("NOPE. NO COLORFIELD");
setBoundingBall(Context, getBoundingBox( S->CoordField ) );
if (S->ErrorMessage.length()>0)
return setStatusError(Context, S->ErrorMessage );
return setStatusInfo(Context, "Surface ready to render.");
}
{
, Cells(TriangleCells)
{
assert( Cells->getTypedStorage() );
const std::vector<TriangleCell>&Cls = Cells->getTypedStorage()->get_vector();
this->CurrentIBO = new IndexBuffer<TriangleCell>( Cls );
draw_mode = GL_TRIANGLES;
}
// TODO: Add modus with alpha clamping and depth buffer writing
void prefix() override
{
glEnable(GL_DEPTH_TEST); // see depth buffer
// glDepthMask(GL_FALSE); // but don't write to it
glDepthMask(GL_TRUE); // and write to it
}
void postfix() override
{
}
};
bool TransparentColoredSurface::renderGL(VGLRenderContext&Context) const
{
RefPtr<MyState> myState = getState(Context);
if (!myState)
return false;
myState->ErrorMessage = "";
if (!Surface)
{
myState->ErrorMessage = "Grid is not a surface";
return false;
}
if (!Surface.CoordField)
{
printf("Did not find coordinates :( \n");
myState->ErrorMessage = "Did not find surface coordinates.";
return false;
}
if (!Surface.CellField)
{
printf("Did not find triangles :( \n");
myState->ErrorMessage = "Did not find triangles.";
return false;
}
if (!myState->CellField->getData() )
{
printf("Did not find triangles indices :( \n");
myState->ErrorMessage = "Did not find triangle indices (no data in triangle field)";
return false;
}
//
// Check for a named color field.
//
RefPtr<Field> Colors = myState->ColorField;
if (!Colors)
{
myState->ErrorMessage = "No such field: \"" + myState->ColorFieldName + "\"";
return false;
}
//
// Generic OpenGL section, these settings affect all VBO's rendered later
//
double Shine = 0.5;
glMaterial( GL::FRONT_AND_BACK, GL::AMBIENT , Color( 0,0,.01,0) );
glMaterial( GL::FRONT_AND_BACK, GL::SPECULAR, Color( 0.5,0.5,.53, 0) );
glMaterial( GL::FRONT_AND_BACK, GL::EMISSION, Color( 0., 0.,0., 0) );
glColor4f(1,0,0, 0.5);
// glColorMaterial( GL_FRONT_AND_BACK, GL_DIFFUSE);
// glEnable( GL_COLOR_MATERIAL );
// printf(">>>>> TransparentColoredSurface: RENDER cells for t=%ld, %lu Triangles\n",
// myState->CellField->time_value(), Cells->nElements() );
RefPtr<Field> Tmp = Surface.getTriangleBaryCenters();
RefPtr<CreativeArrayBase> BaryCenters = Tmp->getCreator();
RefPtr<GLProgram> MyProgram = CompileShader( Context, "TransparentColoredSurface" );
assert( MyProgram );
MyProgram->use();
Alpha << Context > MyProgram;
//
// 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:
//
// http://sciviz.cct.lsu.edu/papers/2009/VizCascade.pdf
//
string VBOKey = myState->ColorFieldName ;
RefPtr<ValueSet> V;// = ScaleFactor(Context);
//
// Colormap handling
//
TextureCreator&TC = Context[ *myState ][ this ][ CmapValues ]( TEXTURE() );
GLColormap::Enable(Cmap, TC, 1, true); // true: clamp values, not repeating
{
MyProgram->setUniformTexture( FSHADER_COLORMAP_NAME , *CmapTexture);
}
// Set the data mapping as the INVERSE of the color map
unsigned ViewCacheSize = 1;
try
{
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)
&& !myVBO->isOlderThan( InputRange->age(Context) )
&& (Colors && !myVBO->isOlderThan( *Colors) ) )
{
if (RefPtr<TriangleRenderer> TR = myVBO->getRenderer() )
{
assert( TR->MyElementSorter );
TR->CurrentIBO = TR->sortByDepth(Context, BaryCenters, ViewCacheSize );
if (myVBO->call() )
{
myState->ErrorMessage = "";
return true;
}
}
}
}
catch(const GLCacheError&Err)
{}
if (!myVBO)
myVBO = Context[*Surface][ typeid(*this) ][ V ]( VERTEXBUFFER(), VBOKey);
myVBO->clear();
//
// Loading fields as vertex arrays and append them to the VBO.
//
using namespace Eagle::PhysicalSpace;
myVBO->append( new TypedVertexArray<point3>( myState->getCoords()->myChunk() ) );
if (RefPtr<TriangularSurface::NormalVectorArray_t> VertexNormals = Surface.getNormals() )
{
myVBO->append( new TypedNormalArray<bivector3>( VertexNormals->myChunk() ));
}
#if 0
// no color field found, set something artifical here
if (!Colors)
{
index_t nVertices = Surface.CartesianVertices->getPositions()->getData()->nElements();
for(index_t i=0; i<nVertices; i++)
{
// a floating point index, which ranges from 0.0 to 1.0
double fi = i/(nVertices-1.0);
// some simple and stupid, but colorful formula
// to map an index to colors.
(*SurfaceColors)[ MIndex(i) ] = fi;
}
Colors = new Field(SurfaceColors);
}
#endif
assert(Colors);
if (RefPtr<TypedArray<rgba_float_t> > colordata = Colors->getData() )
{
myVBO->append( newColorArray( colordata->myChunk() ));
}
else if (RefPtr<TypedArray<double> > colordata = Colors->getData() )
{
RefPtr<MemBase> FieldData = Colors->getData();
if (!DataRange.isIdentity() )
{
FieldData = colordata->applyOperator(DataRange, NullPtr() );
}
else
myVBO->append( TCA );
}
else if( RefPtr<TypedArray<float> > colordata = Colors->getData() )
{
puts("TransparentColoredSurface::render() Apparently this is not called!?!?");
RefPtr<MemBase> FieldData = Colors->getData();
if (!DataRange.isIdentity() )
{
FieldData = colordata->applyOperator(DataRange, NullPtr() );
}
else
myVBO->append( TCA );
}
else
{
puts("TransparentColoredSurface::render() Apparently this IS called!?!?");
myState->ErrorMessage = "Color field has unsupported type "
+ Typename(Colors->getElementType())
+ ", only RGB or double supported";
return false;
}
RefPtr<TriangleRenderer> TR = new TriangleRenderer(myState->getCoords(), myState->CellField->getData() );
TR->MyElementSorter = new GL::TypedElementSorter<TriangleCell>(myState->CellField->getCreator() );
TR->CurrentIBO = TR->sortByDepth(Context, BaryCenters, ViewCacheSize );
myVBO->setRenderer( TR );
myVBO->call();
return true;
}
//
// Object Creation
//
{
static SkeletonExistence InspectionProperty()
{
return SkeletonExistence( TriangularSurface::ID() );
}
};
/*
Outdated because not using the Anemonia API.
*/
using namespace Panthalassa;
MyTransparentColoredSurfaceCreator(Category("Display")/ VIdentifier("TransparentColoredSurface"), ObjectQuality::OUTDATED);
//static VSink<Field, TransparentColoredSurface>
MmmmyTransparentColoredSurfaceCreator( Category("Display")/ VIdentifier("ColoredSurface"), ObjectQuality::OUTDATED);
} // anon namespace
An iterator with an optional DataCreator, which is just a class to intercept creation of data along a...
Definition CreativeIterator.hpp:34
An internal class that stores a couple of textual names.
Definition FieldSelector.hpp:18
A Field is a collection of CreativeArrayBase reference pointers which are accessed via FragmentID obj...
Definition Field.hpp:245
Context information to select a grid from within a bundle.
Definition GridSelector.hpp:26
A concrete Grid Property which looks for the existence of a Skeleton of the specified dimension and i...
Definition BundleProperty.hpp:76
Base class for objects that render information given on the triangle of a Grid.
Definition TriangleRenderer.hpp:22
virtual void postfix()
virtual void prefix()
Base class for objects rendering skeletons of a fiber bundle.
Definition VSkeletonRenderObject.hpp:21
Given a fragmented field of curvilinear coordinates, (3D array of coordinates), build a uniform Grid ...
Definition FAQ.dox:2
std::nullptr_t NullPtr
note: cannot derive from FloatingSkeletonRenderer as long as independent base class TriangleRenderer ...
RenderNamespace::glsl embed_glsl(const char(&file_content)[N])
DEFAULT_OBJECT
Definition Lytica.hpp:7
Class for ranges of types, such as minimum/maximum.
Definition Range.hpp:379
Definition fs/init.hpp:20
A helper class to retrieve fields given on a Grid.
Definition GridField.hpp:19
Definition GridInspector.hpp:13
A triangular surface stored on a Grid.
Definition TriangularSurface.hpp:43
Base class to draw a selection of elements as OpenGL points.
Definition PartialElementRenderer.hpp:85