Start e.g.:
../../../bin/vish SimpleStreamline.vis
Further tutorials: - TexturedStreamLines.cpp
00001 #include <ocean/GLvish/VRenderObject.hpp> 00002 #include <fish/lakeview/bone/FishSlice.hpp> 00003 #include <fish/lakeview/bone/FishField.hpp> 00004 00005 #include <ocean/GLvish/Colormap.hpp> // use of color_t 00006 00007 #include <eagle/FixedArray.hpp> 00008 #include <field/DirectProductArray.hpp> 00009 #include <ocean/GLvish/BoundingBox.hpp> 00010 00011 #include <fish/fiber/vector/Interpolate.hpp> 00012 #include <fish/fiber/vector/LinearIpol.hpp> 00013 #include <fish/fiber/vector/CubicIpol.hpp> 00014 00015 #include <ocean/plankton/VOperatorCache.hpp> 00016 00017 00018 00019 using namespace Wizt; 00020 using namespace Fiber; 00021 00039 class SimpleStreamline : public virtual VRenderObject, public virtual Fish<Slice>, public virtual Fish<Field> 00040 { 00041 public: 00042 typedef MemArray<3, tvector> VectorArray_t; 00043 typedef MemArray<3, point> CoordsArray_t; 00044 typedef DirectProductMemArray<point> ProceduralArray_t; 00045 00046 typedef FixedArray<float,3> rgb; 00047 00048 // define data type for storing one line 00049 typedef std::vector<point> Line_t; 00050 00051 // prepare storing and caching of computed lines in an std::vector of lines 00052 typedef VOperatorCache<std::vector<Line_t> > OpCache_t; 00053 00054 TypedSlot<int> LineLength; 00055 TypedSlot<int> LineWidth; 00056 TypedSlot<int> PointSize; 00057 TypedSlot<int> LineNumber; 00058 TypedSlot<double> StepSize; 00059 TypedSlot<double> FanDelta; 00060 00061 TypedSlot<double> X, 00062 Y, 00063 Z; 00064 00065 struct MyState : State 00066 {}; 00067 00068 override RefPtr<State> newState() const 00069 { 00070 return new MyState(); 00071 } 00072 00073 SimpleStreamline(const string&name, int p, const RefPtr<VCreationPreferences>&VP) 00074 : VRenderObject(name, p, VP) 00075 , Fish<VObject>(this) 00076 , Fish<Field>("datafield") 00077 , LineLength(this, "LineLength", 40) 00078 , LineWidth(this, "LineWidth", 2) 00079 , PointSize(this, "PointSize", 2) 00080 , LineNumber(this, "LineNumber", 10) 00081 , StepSize(this, "StepSize", 0.1) 00082 , FanDelta(this, "FanDelta", 0.05) 00083 , X(this, "X", 0.271) 00084 , Y(this, "Y", 0.294) 00085 , Z(this, "Z", 0.531) 00086 { 00087 LineLength.setProperty("max", 100); 00088 LineLength.setProperty("min", 1); 00089 LineWidth.setProperty("max", 20); 00090 PointSize.setProperty("max", 20); 00091 LineNumber.setProperty("min", 1); 00092 X.setProperty("max", 1.0); 00093 Y.setProperty("max", 1.0); 00094 Z.setProperty("max", 1.0); 00095 00096 acceptType<Eagle::tvector3>(); 00097 } 00098 00099 00100 override bool update( VRequest&R, double precision ); 00101 override void render( VRenderContext&R ) const; 00102 00103 void getCoordinates(const point& float_index, point& position_cordinates); 00104 }; 00105 00106 00110 bool SimpleStreamline::update( VRequest&R, double precision ) 00111 { 00112 printf("SimpleStreamline::update(): updating\n"); 00113 00114 FieldSelector FS = getFieldSelector(R); 00115 00116 // get the grid of the fiber bundle 00117 RefPtr<Grid> G = FS.GridSource(); 00118 if (!G) 00119 return true; 00120 00121 // get the coordinates of the grid 00122 RefPtr<Field> Coords = G->CartesianPositions(); 00123 if (!Coords) { puts("SimpleStreamline::update(): No coord field!"); return true; } 00124 00125 00126 // get the vector data of the grid 00127 RefPtr<Field> Vectors = FS.getField(); 00128 if (!Vectors) { puts("SimpleStreamline::update(): No vector field!"); return true; } 00129 00130 00131 // associate the caching object to the field. As long as the field is valid the 00132 // cached lines can by used. If a new field is load (e.g. from another time step) 00133 // OC is a reference pointer to a std::vector of lines, where they are going to be stored. 00134 RefPtr<OpCache_t>&OC = OpCache_t::retrieve( *Vectors ) [ self() ]; 00135 if (!OC) OC = new OpCache_t(); 00136 00137 00138 RefPtr<VectorArray_t> Vctrs = Vectors->getData(); 00139 if( !Vctrs) 00140 { 00141 printf("SimpleStreamline::update(): Could get vector field data yet!\n"); 00142 if (OC) 00143 { 00144 OC->resize( 0 ); 00145 GLCache::clear( *OC ); 00146 } 00147 return true; 00148 } 00149 else 00150 printf("SimpleStreamline::update(): Gotvector field data!\n"); 00151 00152 RefPtr<ProceduralArray_t> PCrds = Coords->getData(); 00153 RefPtr<CoordsArray_t> Crds = Coords->getData(); 00154 if (!(Crds || PCrds)) 00155 { 00156 printf("SimpleStreamline::update(): Did not find any coordinates : %s\n", 00157 Typename( Coords->getType() ).c_str() ); 00158 return true; 00159 } 00160 00161 00162 00163 RefPtr<ValueSet> Changeables = new ValueSet(); 00164 // Register parameters that shall invoke an update call, if changed. 00165 Changeables & R += X, Y, Z, LineLength, PointSize, StepSize, FanDelta, LineNumber; 00166 00167 // if parameters didn't change, don't do a new calculation 00168 if (OC->unchanged( Changeables ) ) 00169 { 00170 printf("SimpleStreamline::update(): Line Calc Skipped, Lines in Cache...\n"); 00171 return true; 00172 } 00173 00174 00175 int line_number = 1; 00176 LineNumber << R >> line_number; 00177 00178 // resize std::vector to number of lines 00179 OC->resize( line_number ); 00180 GLCache::clear( *OC ); 00181 00182 // Now do the Interpolation of the Coordinates 00183 // Get index Range of Data (and Coordinates) 00184 MultiIndex<3> FieldSize = Vctrs->Size(); 00185 00186 00187 double x, y, z; 00188 point float_index; 00189 point max_float_index; 00190 point vertex; 00191 int line_length; 00192 double hh; 00193 double fan_delta; 00194 00195 LineLength << R >> line_length; 00196 StepSize << R >> hh; 00197 FanDelta<< R >> fan_delta; 00198 00199 // Get user specified position ranging from 0 to 1.0 in each coordinate covering the whole dataset 00200 X << R >> x; 00201 Y << R >> y; 00202 Z << R >> z; 00203 00204 max_float_index = FieldSize[0] - 1, FieldSize[1] - 1, FieldSize[2] - 1; 00205 float_index = x * FieldSize[0] - 1, y * FieldSize[1] -1 , z * FieldSize[2] - 1; 00206 00207 // Clamp wrong inputs 00208 for (int i = 0; i < 3; i++) 00209 { 00210 if( float_index[i] < 0 ) 00211 float_index[i] = 0.0; 00212 00213 if( float_index[i] >= FieldSize[i] ) 00214 float_index[i] = FieldSize[i] - 1; 00215 } 00216 00217 // assume uniform PCrds here (should be extended to other types of coordinates (curvlinear, ...) as well ) 00218 // get maximum and minimum coordinates 00219 point DomainStart = PCrds->first(); 00220 point DomaintEnd = PCrds->last(); 00221 00222 tvector DomainDiagonal = DomaintEnd - DomainStart; 00223 00224 00225 // Calc Positions of the StartPoints of the fan of streamlines 00226 std::vector<point> StartVertex; 00227 StartVertex.resize(line_number); 00228 00229 // First calculate the start position of the first of the start points 00230 // This is done using DomainDiagonal as a basis and componentwise array operations, so 00231 // it can be optimized using the vector SMID unit of the CPU. 00232 StartVertex[0] = ( DomainStart + tvector(component_wise( component_wise(DomainDiagonal, max_float_index, Eagle::Operator<'/'>() ), float_index, Eagle::Operator<'*'>() ) ) ); 00233 00234 00235 tvector CurrentDir; 00236 point CurrentVertex; 00237 point CurrentFloatIndex; 00238 tvector FanOffset; 00239 FanOffset = 1, 0, 0; 00240 00241 resetBBox( R ); 00242 embrace( R, StartVertex[0]); 00243 00244 // Calculate stream lines 00245 for(int l = 0; l < line_number; l++) 00246 { 00247 // Calucalte startpoints of the fan by adding the offest to the x-coordinate 00248 StartVertex[l] = StartVertex[0] + FanOffset * l * fan_delta; 00249 00250 Line_t&myLine = (*OC)[l]; 00251 myLine.clear(); 00252 00253 for(int i = 0; i < line_length; i++) 00254 { 00255 if (i == 0) 00256 { 00257 CurrentVertex = StartVertex[l]; 00258 00259 // We have to use the float_index space for the interpolator. We already know 00260 // it for the startpoint. 00261 Interpolate<3, tvector, CubicIpol <tvector> > VecField(*Vctrs, float_index); 00262 // Get direction at current point 00263 CurrentDir = VecField.eval(); 00264 } 00265 else 00266 { 00267 // Calculate the floatindex of the current position from data coordinates 00268 CurrentFloatIndex = point( tvector( component_wise(component_wise(CurrentVertex - DomainStart, DomainDiagonal, Eagle::Operator<'/'>() ), max_float_index, Eagle::Operator<'*'>()) )); 00269 00270 // Stop line calculation, when going out of the data range 00271 if(CurrentFloatIndex [0] < 0.0 ||CurrentFloatIndex [0] > max_float_index[0]) 00272 break; 00273 if(CurrentFloatIndex [1] < 0.0 ||CurrentFloatIndex [1] > max_float_index[1]) 00274 break; 00275 if(CurrentFloatIndex [2] < 0.0 ||CurrentFloatIndex [2] > max_float_index[2]) 00276 break; 00277 00278 // Get direction at current point. 00279 Interpolate<3, tvector, CubicIpol <tvector> > VecField(*Vctrs, CurrentFloatIndex); 00280 CurrentDir = VecField.eval(); 00281 } 00282 00283 // calc new point 00284 CurrentVertex += CurrentDir * hh; 00285 myLine.push_back(CurrentVertex); 00286 embrace( R, CurrentVertex); 00287 } 00288 } 00289 00290 printf("SimpleStreamline::update(): Integrated into Cache\n"); 00291 closeBBox( R ); 00292 00293 return true; 00294 } 00295 00296 00297 void SimpleStreamline::render( VRenderContext& Context ) const 00298 { 00299 00300 // Get handle to vectorfield 00301 RefPtr<Field> Vectors = getField( Context ); 00302 if (!Vectors) 00303 { 00304 puts("void SimpleStreamline::render(VRenderContext&RenderContext): NO VECTORS"); 00305 return; 00306 } 00307 00308 // Get cached lines 00309 const RefPtr<OpCache_t>&OC = OpCache_t::retrieve( *Vectors ) ( self() ); 00310 if (!OC) 00311 { 00312 puts("void SimpleStreamline::render(VRenderContext&RenderContext): NO LINE CACHE"); 00313 return; 00314 } 00315 if (OC->size()<1) 00316 { 00317 puts("void SimpleStreamline::render(VRenderContext&RenderContext): NO LINES in CACHE"); 00318 return; 00319 } 00320 00321 int line_width, point_size; 00322 int line_length = 1; 00323 00324 LineWidth << Context >> line_width; 00325 PointSize << Context >> point_size; 00326 LineLength << Context >> line_length; 00327 00328 if(line_width < 1) 00329 line_width = 1; 00330 00331 glEnable(GL_DEPTH_TEST); 00332 glDisable(GL_LIGHTING); 00333 00334 glLineWidth( line_width ); 00335 00336 if(point_size > 0) 00337 glPointSize( point_size ); 00338 else 00339 glPointSize( 1 ); 00340 00341 RefPtr<MyState> state = myState(Context); 00342 00343 RefPtr<ValueSet> RenderParameterSpace = new ValueSet(); 00344 RefPtr<DisplayList> DL; 00345 try{ 00346 DL = Context(*OC)(this)( RenderParameterSpace ); 00347 } 00348 catch(...){} 00349 RefPtr<ValueSet> Changeables = new ValueSet(); 00350 Changeables & Context += LineLength, LineNumber, StepSize; 00351 00352 if ( DL && OC->unchanged( Changeables )) //call display list if availlable, check if changables have changed 00353 { 00354 printf("SimpleStreamline::render(): Calling List\n"); 00355 DL->call(); 00356 } 00357 else //prepare display list 00358 { 00359 printf("SimpleStreamline::render(): Rendering List\n"); 00360 00361 DL = Context[*OC][this][ RenderParameterSpace ]; 00362 if (!DL) throw "SimpleStreamline::render() No Display List!?"; 00363 00364 glCompile( *DL ) 00365 { 00366 int l = 0; 00367 int p = 0; 00368 00369 // iterate over all lines in cache and draw a line_strip 00370 for( OpCache_t::const_iterator lbit = OC->begin(); lbit != OC->end(); lbit++ ) 00371 { 00372 p = 0; 00373 //printf("SimpleStreamline::render()> :Line %d\n", l); 00374 Line_t::const_iterator lit = lbit->begin(); 00375 00376 if (lit == lbit->end() ) 00377 break; 00378 00379 glBegin( GL_LINE_STRIP ); // GLCHECK must not be used in between a glBegin and glEnd statement 00380 bivector dir; 00381 00382 for(; lit != lbit->end();) 00383 { 00384 // printf("SimpleStreamline::render()> :point %d\n", p); 00385 point P = *lit; 00386 lit++; 00387 if (lit != lbit->end()) 00388 dir = (*lit - P).unit(); 00389 00390 // use length of the line as color information 00391 glColor3f((double)p/lbit->size() , 1-(double)p/lbit->size(), 0.0); 00392 glVertex( P ); 00393 00394 p++; 00395 } 00396 00397 l++; 00398 glEnd(); 00399 } 00400 00401 00402 // draw points 00403 if(point_size > 0 ) 00404 { 00405 for( OpCache_t::const_iterator lbit = OC->begin(); lbit != OC->end(); lbit++ ) 00406 { 00407 p = 0; 00408 //printf("SimpleStreamline::render()> :Line %d\n", l); 00409 Line_t::const_iterator lit = lbit->begin(); 00410 00411 if (lit == lbit->end() ) 00412 break; 00413 00414 tvector dir; 00415 glBegin(GL_POINTS); 00416 00417 for(; lit != lbit->end();) 00418 { 00419 //printf("SimpleStreamline::render()> :point %d\n", p); 00420 point P = *lit; 00421 lit++; 00422 if (lit != lbit->end()) 00423 dir = (*lit - P).unit(); 00424 00425 glColor3f((double)p/lbit->size(), 1-(double)p/lbit->size(), 0.7); 00426 glVertex( P ); 00427 00428 p++; 00429 } 00430 glEnd(); 00431 } 00432 } 00433 } 00434 } 00435 00436 state->touch(); // synchinozes state, prevents unneccessary calls of the update function. 00437 } 00438 00439 00440 static Ref<VCreator<SimpleStreamline, AcceptList<Fiber::Field> > > myCreator("Tutorial/SimpleStreamline"); 00441 00442 VISH_DEFAULT_INIT