Display a triangular surface as transparent object using depth-sorting.
#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/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> #include <GL/PartialElementRenderer.hpp> using namespace Wizt; using namespace Fiber; using namespace Eagle; namespace { class TransparentSurface : public VSkeletonRenderObject { public: struct MyState : State, TriangularSurface { using TriangularSurface::operator=; }; override RefPtr<State> newState() const { return new MyState(); } TypedSlot<rgba_float_t> SurfaceColor, SurfaceBackColor; TypedSlot<double> Transparency; TransparentSurface(const string&name, int, const RefPtr<VCreationPreferences>&VP) : VGLRenderObject(name, TRANSPARENT_OBJECT, VP) , Fish<VObject>(this) , VSkeletonRenderObject(name, TRANSPARENT_OBJECT, VP) , SurfaceColor(this, "color", makeColor(1.,.1,1., 1.0),0) , SurfaceBackColor(this, "backcolor", makeColor(.0, 1.,1.0, 1.0),0) , Transparency(this, "opacity", 0.5, 0) {} override void render(VGLRenderContext&Context) const; override bool update(VRequest&R, double precision); static string createChildname(const string&parent_name) { return "TransparentSurface(" + parent_name + ")"; } }; bool TransparentSurface::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."); } *S = G; if (!*S) return setStatusError(Context, "No surface available."); setBoundingBall(Context, getBoundingBox( S->CoordField ) ); return setStatusInfo(Context, "Surface ready to render."); } struct TriangleRenderer : GL::PartialElementRenderer { RefPtr<TriangularSurface::CellArray_t> Cells; TriangleRenderer(const MemCore::RefPtr<Fiber::MemBase>&FieldCoordinates, const RefPtr<TriangularSurface::CellArray_t>&TriangleCells) : GL::PartialElementRenderer( FieldCoordinates, NullPtr() ) , Cells(TriangleCells) { assert( TriangleCells ); assert( Cells->getTypedStorage() ); const std::vector<TriangleCell>&Cls = Cells->getTypedStorage()->get_vector(); this->CurrentIBO = new IndexBuffer<TriangleCell>( Cls ); draw_mode = GL_TRIANGLES; } override void prefix() { glEnable(GL_DEPTH_TEST); // see depth buffer glDepthMask(GL_FALSE); // but don't write to it glEnable(GL_NORMALIZE); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glEnable( GL_BLEND ); } void postfix() { glDepthMask(GL_TRUE); } }; void TransparentSurface::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 triangles :( \n"); 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; rgba_float_t SurfBackColor( makeColor(1,0,0,0.5 ) ); SurfaceBackColor << Context >> SurfBackColor; double Alpha = 0.5; Transparency << Context >> Alpha; SurfColor[3] = Alpha; SurfBackColor[3] = Alpha; // glEnable( GL_DEPTH_TEST ); // glEnable( GL_MULTISAMPLE_ARB ); // glEnable( GL_SAMPLE_ALPHA_TO_COVERAGE_ARB ); glMaterial( GL::FRONT, GL::DIFFUSE, SurfColor ); glMaterial( GL::BACK , GL::DIFFUSE, SurfBackColor ); // glColor4f( 1,0,0,.8); // glMaterial( GL::FRONT, GL::DIFFUSE, makeColor( 1., 0.,0., 0.3) ); // glMaterial( GL::BACK , GL::DIFFUSE, makeColor( .3, 1.,0., 0.3) ); // printf(">>>>> TransparentSurface: RENDER cells for t=%ld, %lu Triangles\n", // myState->CellField->time_value(), Cells->nElements() ); RefPtr<Field> Tmp = Surface.getTriangleBaryCenters(); RefPtr<CreativeArrayBase> BaryCenters = Tmp->getCreator(); // // VBO Access via GLCache, retrieve and re-use or generate new VBO // const string VBOKey = ""; RefPtr<ValueSet> V;// = ScaleFactor(Context); RefPtr<VBO> myVBO; RefPtr<TriangleRenderer> MyTriangleRenderer; 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) ) { if (RefPtr<TriangleRenderer> TR = myVBO->getRenderer() ) { assert( TR->MyElementSorter ); TR->CurrentIBO = TR->sortByDepth(Context, BaryCenters, ViewCacheSize ); if (myVBO->call() ) { return; } } } } catch(const GLCacheError&Err) {} 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. // 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() )); } 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(); } // // Object Creation // struct GridInspector { static SkeletonExistence InspectionProperty() { return SkeletonExistence( TriangularSurface::ID() ); } }; static Ref<GridActor<GridInspector, TransparentSurface> > MyTransparentSurfaceCreator("Display/TransparentSurface", ObjectQuality::MATURE); } // anon namespace