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 Fiber { class EvolutionSurface : public VSkeletonRenderObject { public: struct MyState : State, Fiber::TriangularSurface { vector<Fiber::TriangularSurface> gridEvolution; }; override RefPtr<State> newState() const { return new MyState(); } struct EvolutionSurfaceIterator: EvolutionIterator<Grid> { double startTime; double pastTime; double skip; //MR should better be a uint vector<Fiber::TriangularSurface> *grid; int counter; EvolutionSurfaceIterator(vector<Fiber::TriangularSurface> *surfaces, double time, double past_time,double skipSteps) : startTime(time) , grid(surfaces) , skip(skipSteps) , counter(0) , pastTime(past_time) {} override bool apply(double time, GridID&id, Grid&G) { if( startTime < 0 || startTime-time>pastTime ) { return false; } // MR should be something like ( counter % skip == 0), such that only everth nth surface is drawn if( counter==skip ) { RefPtr<Grid> *newGrid = new RefPtr<Grid>(&G); grid->push_back(*newGrid); } counter ++; if(counter > skip) { counter = 0; } return true; } }; TypedSlot<rgba_float_t> SurfaceColor, SurfaceBackColor; TypedSlot<double> Transparency; TypedSlot<double> PastTime; TypedSlot<double> SkipSteps; EvolutionSurface(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) , PastTime(this, "pastTime", 1) , SkipSteps(this, "skipSteps", 1) { PastTime.setProperty("max", 100.0); SkipSteps.setProperty("max", 100.0); } override void render(VGLRenderContext&Context) const; override bool update(VRequest&R, double precision); static string createChildname(const string&parent_name) { return "EvolutionSurface(" + parent_name + ")"; } }; bool EvolutionSurface::update(VRequest&Context, double precision) { RefPtr<MyState> S = myState(Context); GridSelector GS = getGridSelector(Context); RefPtr<Grid> G = findMostRecentGrid( Context ); string SelectedGridName = GS.getGridname(); if (!G) { removeState(Context); return setStatusError(Context, "No Grid found."); } S->TriangularSurface::operator=(G); if (!*S) return setStatusError(Context, "No surface available."); setBoundingBall(Context, getBoundingBox( S->CoordField ) ); if (BundlePtr B = GS.getBundle() ) { S->gridEvolution.clear(); double pastTime = 0.0; PastTime << Context >> pastTime; double skipSteps = 0.0; SkipSteps << Context >> skipSteps; double t = getTime(Context, B); EvolutionSurfaceIterator iterator(&(S->gridEvolution), t, pastTime, skipSteps); B->iterateBackward(t, SelectedGridName, iterator, false); S->gridEvolution.push_back(G); } 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 EvolutionSurface::render(VGLRenderContext&Context) const { RefPtr<MyState> myState = getState(Context); if (!myState) return; Fiber::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(">>>>> EvolutionSurface: RENDER cells for t=%ld, %lu Triangles\n", // myState->CellField->time_value(), Cells->nElements() ); RefPtr<Field> Tmp = Surface.getTriangleBaryCenters(); RefPtr<CreativeArrayBase> BaryCenters = Tmp->getCreator(); std::ostringstream stream; for(int i=0; i<myState->gridEvolution.size(); i++) { stream<<i; // // 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(), stream.str()); // Call the VBO if it's there and all ready to go. if (myVBO && !myVBO->isOlderThan( *Surface.CellField) && !myVBO->isOlderThan( *Surface.CoordField) ) { for(int j=i; j<myState->gridEvolution.size()&&myVBO; j++) { if ( RefPtr<TriangleRenderer> TR = myVBO->getRenderer() ) { assert( TR->MyElementSorter ); TR->CurrentIBO = TR->sortByDepth(Context, BaryCenters, ViewCacheSize ); myVBO->call(); } stream<<j+1; myVBO = Context( *Surface )( typeid(*this) )( V )(VERTEXBUFFER(), stream.str()); } return; } } catch(const GLCacheError&Err) {} if (!myVBO) myVBO = Context[*Surface][ typeid(*this) ][ V ]( VERTEXBUFFER(), stream.str()); 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->gridEvolution[i].getCoords()->myChunk() ) ); if (RefPtr<TriangularSurface::NormalVectorArray_t> VertexNormals = Surface.getNormals() ) { myVBO->append( new TypedNormalArray<bivector3>( VertexNormals->myChunk() )); } RefPtr<TriangleRenderer> TR = new TriangleRenderer(myState->gridEvolution[i].getCoords(), myState->gridEvolution[i].CellField->getData() ); TR->MyElementSorter = new GL::TypedElementSorter<TriangleCell>(myState->gridEvolution[i].CellField->getCreator() ); TR->CurrentIBO = TR->sortByDepth(Context, BaryCenters, ViewCacheSize ); myVBO->setRenderer( TR ); myVBO->call(); } } // // Object Creation // struct GridInspector { static SkeletonExistence InspectionProperty() { return SkeletonExistence( Fiber::TriangularSurface::ID() ); } }; static Ref<GridActor<GridInspector, EvolutionSurface> > MyEvolutionSurfaceCreator("Display/EvolutionSurface", ObjectQuality::EXPERIMENTAL); } // anon namespace