FiberVISH 0.2
Fish - The Fiber Bundle API for the Vish Visualization Shell
ColoredLines.cpp

Display a set of lines as specified by the Edge skeleton of a grid.

Display a set of lines as specified by the Edge skeleton of a grid.Refinement levels and fragmented fields not implemented.

#include <ocean/plankton/VPipeline.hpp>
#include <ocean/GLvish/VGLRenderObject.hpp>
#include <ocean/GLvish/BoundingBox.hpp>
#include <ocean/GLvish/VGLColormap.hpp>
#include <ocean/GLvish/GlossyTexture.hpp>
#include <ocean/GLvish/ArrayTypes.hpp>
#include <eagle/PhysicalSpace.hpp>
#include <ocean/shrimp/VEnum.hpp>
#include <ocean/shrimp/TimeDependent.hpp>
#include <ocean/shrimp/VObjectStatus.hpp>
#include <ocean/shrimp/EaglePhysicalSpaceTVector.hpp>
#include <ocean/Anemonia/FloatOrigin.hpp>
#include <GL/FieldBuffer.hpp>
#include <GL/LineSetRenderer.hpp>
#include <bone/GridActor.hpp>
#include <bone/GridObject.hpp>
#include <bone/FishField.hpp>
#include <bundle/BundleProperty.hpp>
#include <grid/types/LineSet.hpp>
#include <baseop/ExpandBBox.hpp>
#include <baseop/GridField.hpp>
#include <fiberop/Range.hpp>
#include <field/ArrayRef.hpp>
#include <memcore/Chunk.hpp>
//#define VERBOSE
using namespace Wizt;
using namespace Fiber;
using namespace Eagle;
namespace
{
class RampTexture : public GLTexture1D
{
rgba_float_t color1;
rgba_float_t color2;
public:
RampTexture(const int tex_unit, const rgba_float_t&c1, const rgba_float_t&c2)
, color1(c1)
, color2(c2)
{}
void enlighten()
{
rgb texture[512];
double p;
for(int i = 0; i < 512 ; i++)
{
p = double(i)/512.0;
col[0] = (1-p)*color1[0] + p*color2[0];
col[1] = (1-p)*color1[1] + p*color2[1];
col[2] = (1-p)*color1[2] + p*color2[2];
texture[i] = col;
}
create_and_bind();
GL::TexImage1D( texture, 512, GL_RGB);
}
void prerender()
{
enable();
//glTexEnvf(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE); //not really nesseccasy ?
bind(); // should do corresponding glActiveTexture(GL_TEXTURE1); ?? automatically ??
}
};
class GlossColorMapLines : public virtual VGLRenderObject
, public TimeDependent
, public FloatOrigin
{
struct FieldState : State
{
WeakPtr<Grid> theGridOfInterest;
};
RefPtr<State> newState() const override
{
return new FieldState();
}
{
: S( SP )
{
S->fragments.clear();
}
bool apply(const RefPtr<FragmentID>&f,
{
if(!f)
return false;
S->fragments.push_back( f );
return true;
}
} ;
public:
GlossyTexture::Parameters GlossyParameters;
TypedSlot<Grid> MyLinesGrid;
TypedSlot<Field> InputField;
TypedSlot<double> LineWidth;
TypedSlot<rgba_float_t> ColStart, ColEnd;
TypedSlot<Enum> GhostyLines;
TypedSlot<Range> InputRange;
enum { NumberOfInputFields = 1 };
typedef META::LIST<double> InputTypes;
// wrong, should check for line sets
// typedef Fiber::GridInspector<BundleProperty::Anything> GridInspector;
{
static SkeletonExistence InspectionProperty()
{
return SkeletonExistence( LineSet::ID() );
}
};
GlossColorMapLines(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
, GlossyParameters(this)
, MyLinesGrid(this, "grid", GridSelector(), 2)
, InputField(this, "field" )
, LineWidth(this, "linewidth", 2.0, 1)
, ColStart(this, "col_start", {0.0, 1.0, 0.0, 1.0},2)
, ColEnd (this, "col_end" , {1.0, 0.0, 0.0, 1.0},2)
// , AutoLenScale(this, "autoscale", Enum(1,"on", "off"), 0)
, GhostyLines(this, "ghostylines", Enum("off", "on"),3 )
, InputRange(this, "range", Range(0,1), 0)
, Colormap(this, "colormap", NullPtr() )
// , LengthRange( self(), "fieldrange", Range(0.0, 1.0) )
{
LineWidth.setProperty( "max", 20.0);
}
void setup(const CreationSlots_t&CreationSlots) override
{
setupTime(CreationSlots);
}
bool update(VRequest&R, double precision) override;
bool renderGL(VGLRenderContext&Context) const override;
static string createChildname(const string&parent_name)
{
return "ColoredLinesOf" + parent_name;
}
};
//
// Update function, is called whenever some input is changed
// It extracts the fields required for rendering and deposits them
// in the context-relative state object. This state object is
// available then during rendering.
//
bool GlossColorMapLines::update(VRequest&Context, double precision)
{
// exit(0);
/*
{
VEnum als;
AutoLenScale << Context >> als;
if (als()==0) setExpertLevel(InputRange, 10);
else setExpertLevel(InputRange, 0);
}
*/
GridField GF(GS, FS, getTime(Context) );
if (!GF.getGrid() )
{
return setStatusError(Context, "No grid object found at T=" + String( getTime(Context) ) );
}
/*
Info<Skeleton> SI;
{
SI = GS.getRefinementLevel( getTime(Context), 0, 0 );
}
double time = SI.getTime();
if (!SI.getGrid() )
{
SI = FS.getRefinementLevel( getTime(Context), 0, 0 );
time = SI.getTime();
if (!SI.getGrid() )
return setStatusError(Context,"No grid object found at T=" + String(time) );
}
*/
setBoundingBall( Context, getBoundingBox( *GF.getGrid() ) );
LineSet LS = GF.getGrid();
if (!LS)
{
return setStatusError(Context,"No line grid found at T=" + String( GF.getTime() ) );
}
if (!LS.CartesianVertices)
{
return setStatusError(Context,"No grid without cartesian vertices at T=" + String( GF.getTime() ) );
}
S->theGridOfInterest = GF.getGrid();
LS.setupStandardFields( GF.getGrid() );
// collect fragment IDs in state
if( LS.LineIndices )
LS.LineIndices->iterate(myIt);
else
setStatusError(Context,"No LineIndices Field fount at T=" + String( GF.getTime() ) );
#ifdef VERBOSE
for(size_t i = 0; i < S->fragments.size(); i++ )
cout << "Found LineSet-Fragment: " << S->fragments[i]->Name() << endl;
#endif
// if no fragments push one NullPtr on the vector, so the for loop in the rendering
// can be used for unfragmented linesets as well
if( S->fragments.empty() )
S->fragments.push_back( NullPtr() );
//RefPtr<Field> F = (*LS.CartesianVertices)( FS.getFieldName() );
// if (!F) F = (*LS.CartesianVertices)( LineSet::ArcLengthFieldName );
// if (F)
{
/*
if (RefPtr<DataRange<double> > DR = getRange(*F) )
{
Range FieldRange(DR->Min(), DR->Max() );
LengthRange << Context << FieldRange;
}
*/
// S->TextureField = F;
// S->Fieldname = FS.getFieldName();
return setStatusInfo(Context, "Lines ready, inspecting " + FS.getFieldName() );
}
// else
{
// S->TextureField = NullPtr();
// return setStatusInfo(Context, "Lines ready, no field available.");
}
}
static
{
const MultiArray<1, double>&Input = *Data;
ArrayRef<double> Output(Input.Size() );
for(index_t i=0; i<Output.size(); i++)
{
Output[i] = R(Input[ i ]);
}
return Output;
}
/*
The renderer object for the VBO. It uses the information
about line segments to issue glDrawElements() commands.
It is implemented as a callback iterator object for
LineSet's.
@todo Investigate this construction whether it not creates a
circular reference keeping the involved Grid object
alive by itself. Probably it does not, but that has
to be verified by investing some more brain power.
Update: yes it did. Must not derive from LineSet here.
This is an absolute NO.
Previous code die
@code
struct MyRenderer : DrawArrays, LineSet
{
};
@endcode
which was a very bad idea...
*/
/*
The render routine. Takes care of vertex buffer objects
and calls its render routines.
*/
bool GlossColorMapLines::renderGL(VGLRenderContext&Context) const
{
Eagle::tvector3 TranslationVector;
auto V = getCoordinateTranslation(Context, TranslationVector);
// cout << "Transvec: " << TranslationVector << endl;
// puts("GlossColorMapLines::render()");fflush(stdout);
if (!S)
return false;
if (!S->theGridOfInterest)
return false;
LineSet LS(S->theGridOfInterest);
if (!LS.LineIndices)
return false;
string Fieldname = FS.getFieldName();
//
// Setup glossy texture on unit 0
//
{
try
{
LineTexture = Context( *S )( this ) ( GlossyValues ) ( TEXTURE() );
}
catch( const GLError&)
{}
if (!LineTexture)
{
LineTexture = new GlossyTexture(0);
LineTexture->enlighten();
LineTexture->enlighten(GlossyParameters, Context);
GLCHECK( LineTexture->enlighten );
Context[ *S ][ this ][ GlossyValues ] ( TEXTURE() ) = LineTexture;
}
}
//
// Setup coloration texture on unit 1
//
{
TextureCreator&TC = Context[ *LS.LineIndices ][ this ][ CmapValues ]( TEXTURE() );
if (!GLColormap::Enable(Cmap, TC, 1, true) )
{
LineTexture2 = new RampTexture(1, c1, c2);
LineTexture2->enlighten();
LineTexture2->prerender();
}
}
//
//
// OpenGL prefix
//
//
double width = 1.0;
if( width < 1e-4)
width = 0.01;
glLineWidth(width);
// blending, experiment here
if (GhostL("on") )
else
//Enum Auto;
// AutoLenScale << Context >> Auto;
{
assert(LineTexture);
GlossyTexture::Render LINERENDER( *LineTexture, Context.getCameraSettings() );
Range ValueRange(0.0, 1.0);
/*
switch( Auto() )
{
case 1:
*/
/*
break;
default:
case 0:
LengthRange << Context >> ValueRange;
}
*/
const int ColormapTextureUnit = 1;
#if 0
//
// Do scaling of colormap values via texture matrix on unit 1
// which is much faster than rescaling the input values of the
// provided scalar field.
//
glTexCoord4d(0.0, 0.0, 0.0, 1.0);
/*
m * (t,0,0,0) = t( m[0] + m[1] + m[2] + m[3] )
*/
/*
double m[16] = { ValueRange.inv_scale(), 0,0, ValueRange.inv_bias(),
0,1,0,0,
0,0,1,0,
0,0,0,1 };
*/
// double m[16] = { ValueRange.inv_scale(), 0,0, ValueRange.bias(),
// double m[16] = { 1.0, 0,0, ValueRange.bias(),
double m[16] = { 1.0, 0,0, 0,
0,1,0,0,
0,0,1,0,
0,0,0,1 };
/* printf("TEXTURE MAPPING: inv[scale=%lg, bias=%lg] [scale=%lg, bias=%lg], f(0)=%lg f(1)=%lg\n",
ValueRange.inv_scale(), ValueRange.inv_bias(),
ValueRange.scale(), ValueRange.bias(),
m[3], m[0] + m[3]
);
*/
#endif
// for each field make a new VBO
*myCacheableValues <<= InputField(Context);
// printf("CACHE VALUE: [%s]\n", myCacheableValues->ValueState().c_str() );
// WeakPtr<VValueBase> VB = InputField(Context);
// printf("INPUT FIELD: [%s]\n", VB->Text().c_str() );
// TODO sort by kdtree
for( size_t frag_i = 0; frag_i < S->fragments.size(); frag_i++ )
{
string VBOKey ="";
if( S->fragments[frag_i] )
VBOKey = S->fragments[frag_i]->Name();
#ifdef VERBOSE
cout << "VBKey: " << VBOKey << endl;
#endif
Intercube&CacheObject = *S->theGridOfInterest;
try
{
}
catch(...){} // could investigate reasons here why cache is not available.
RefPtr<Field> TextureField = (*LS.CartesianVertices)( Fieldname );
#if 1
if (!myVBO || !myVBO->getRenderer() ||
myVBO->isOlderThan( ConnectionAge() ) ||
(LS.Coords && myVBO->isOlderThan( *LS.Coords) ) ||
(LS.LineIndices && myVBO->isOlderThan( *LS.LineIndices) ) ||
(TextureField && myVBO->isOlderThan( *TextureField) ) ||
// InputRange.age( Context ).isNewerThan( *S ) ||
InputRange.age( Context ).isNewerThan( *myVBO ) )
#else
if (true)
#endif
{
#ifdef VERBOSE
if (!myVBO) puts("No VBO found");
else
{
if (!myVBO->getRenderer() ) puts("No rendered in VBO");
if (LS.Coords && myVBO->isOlderThan( *LS.Coords) ) puts("Coordinates are newer");
if (LS.LineIndices && myVBO->isOlderThan( *LS.LineIndices) ) puts("Line indices are newer");
if (myVBO->isOlderThan( ConnectionAge() ) ) puts("network connections have changed");
if (TextureField && myVBO->isOlderThan( *TextureField) ) puts("color field has changed");
if (InputRange.age( Context ).isNewerThan( *S ) ) puts("input range is newer than status");
if (InputRange.age( Context ).isNewerThan( *myVBO ) ) puts("input range is newer than vbo");
}
#endif
RefPtr<MemBase> Pts = LS.Coords->getData( S->fragments[frag_i] );
//std::vector<point> vertices = Pts;
if(!TA)
{
puts("No coords array retrieved");
return false;
}
std::vector<point> VertexVector = TA->myChunk()->get_vector();
// here float origin?
for(index_t v = 0; v < VertexVector.size(); v++ )
VertexVector[v] -= TranslationVector;
myVBO = Context[ CacheObject ][ typeid(*this) ][ myCacheableValues ] ( VERTEXBUFFER(), VBOKey );
myVBO->clear();
if (RefPtr<LineSet::TangentialVector_t> Tangents = LS.getTangentialVectors( S->fragments[frag_i] ) )
{
#ifdef VERBOSE
for(mi[0] = 0; mi[0] < 3; mi[0]++)
std::cout << (*Tangents)[mi] << std::endl;
#endif
const int TextureUnit = 0;
myVBO->append( TCA );
#ifdef VERBOSE
cout << "ColoredLines::render() appended tangents: # " << TCA->BufferArray::NumberOfElements() << endl;
#endif
}
else
{
LS.getLineset().Speak("********************LineSet EDGE Sets - WRONG EDGE SET DATA TYPE?");
return false;
}
#ifdef VERBOSE
puts("Load a texture coordinate field, maybe?");
#endif
if (TextureField)
{
if (RefPtr<MemArray<1, double> > TextureData = TextureField->getData( S->fragments[frag_i] ) )
{
#ifdef VERBOSE
puts("Load a texture coordinate field");
#endif
GL::FieldBuffer<TypedTexCoordArray<double> >::createParam( ColormapTextureUnit,
LoadData, false, NullPtr() );
myVBO->append( TCA );
#ifdef VERBOSE
cout << "ColoredLines::render() appended texture: # " << TCA->BufferArray::NumberOfElements() << endl;
#endif
}
else
{
puts("NOTE: CANNOT get texture field data?!");
}
}
else
{
puts("NOTE: NO texture field!");
}
VA->load(VertexVector);
myVBO->append( VA );
#ifdef VERBOSE
cout << "ColoredLines::render() appended vertices: # " << VA->BufferArray::NumberOfElements() << endl;
#endif
myVBO->setRenderer( new GL::LineSetRenderer( S->theGridOfInterest, GL::LineSetRenderer::AsLineStrip, S->fragments[frag_i] ) );
myVBO->update( ConnectionAge() );
//#define VERBOSE
#ifdef VERBOSE
puts("CREATING NEW LINE RENDER VBO");
if (TextureField && myVBO->isOlderThan( *TextureField) )
{
puts(" BECAUSE this VBO is older than the associated texture field");
TextureField.speak("ASSOC TEXTURE FIELD");
{
printf(" FIELDNAME: %s\n", FS.getFieldName().c_str() );
}
}
else
{
puts(" BUT texture field has not changed");
}
#endif
}
#ifdef VERBOSE
else
puts("USING CACHED LINE RENDER VBO");
#endif
#ifdef VERBOSE
puts("call1");fflush(stdout);
#endif
myVBO->call();
}
}
return true;
}
//
// Object Creation
//
{
static SkeletonExistence InspectionProperty()
{
return SkeletonExistence( LineSet::ID() );
}
};
MyGlossyLinesCreator( "Display/ColoredLines", ObjectQuality::OUTDATED);
MyTransparentColoredSurfaceCreator("Display/OnColoredLines", ObjectQuality::OUTDATED);
} // anon namespace
_Expr< _ValFunClos< _ValArray, _Tp >, _Tp > apply(_Tp __func(_Tp)) const
constexpr _Bind_helper< __is_socketlike< _Func >::value, _Func, _BoundArgs... >::type bind(_Func &&__f, _BoundArgs &&... __args)
basic_ostream< _CharT, _Traits > & endl(basic_ostream< _CharT, _Traits > &__os)
ostream cout
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
Base class for iterators over the fragments of a field.
Definition FragmentID.hpp:249
Context information to select a grid from within a bundle.
Definition GridSelector.hpp:26
A set of lines stored on a Grid.
Definition LineSet.hpp:55
A concrete Grid Property which looks for the existence of a Skeleton of the specified dimension and i...
Definition BundleProperty.hpp:76
void speak(const char *s, const char *prefix="") const noexcept
bool setProperty(const string &theName, const Type &theValue) const
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 ...
DEFAULT_OBJECT
Definition Lytica.hpp:7
Definition fs/init.hpp:20
A helper class to retrieve fields given on a Grid.
Definition GridField.hpp:19
Definition GridInspector.hpp:13
Definition examples/200-SpatialSorting/main.cpp:36
Common base class for objects that render information given on line sets, merely for grouping purpose...
Definition eye/retina/LineSetRenderer.hpp:39