App_Vivid.cpp 31.8 KB
Newer Older
Michele Bosi's avatar
Michele Bosi committed
1 2 3 4 5
/**************************************************************************************/
/*                                                                                    */
/*  Visualization Library                                                             */
/*  http://visualizationlibrary.org                                                   */
/*                                                                                    */
Michele Bosi's avatar
Michele Bosi committed
6
/*  Copyright (c) 2005-2016, Michele Bosi                                             */
Michele Bosi's avatar
Michele Bosi committed
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48
/*  All rights reserved.                                                              */
/*                                                                                    */
/*  Redistribution and use in source and binary forms, with or without modification,  */
/*  are permitted provided that the following conditions are met:                     */
/*                                                                                    */
/*  - Redistributions of source code must retain the above copyright notice, this     */
/*  list of conditions and the following disclaimer.                                  */
/*                                                                                    */
/*  - Redistributions in binary form must reproduce the above copyright notice, this  */
/*  list of conditions and the following disclaimer in the documentation and/or       */
/*  other materials provided with the distribution.                                   */
/*                                                                                    */
/*  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND   */
/*  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED     */
/*  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE            */
/*  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR  */
/*  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES    */
/*  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;      */
/*  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON    */
/*  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT           */
/*  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS     */
/*  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.                      */
/*                                                                                    */
/**************************************************************************************/

#include "BaseDemo.hpp"
#include <vlCore/glsl_math.hpp>
#include <vlGraphics/GLSL.hpp>
#include <vlGraphics/Light.hpp>
#include <vlGraphics/Text.hpp>
#include <vlGraphics/FontManager.hpp>
#include <vlCore/VisualizationLibrary.hpp>
#include <vlCore/FileSystem.hpp>
#include <vlCore/DiskDirectory.hpp>
#include <vlCore/ResourceDatabase.hpp>
#include <vlCore/LoadWriterManager.hpp>
#include <vlGraphics/TriangleStripGenerator.hpp>
#include <vlGraphics/DoubleVertexRemover.hpp>
#include <vlGraphics/FontManager.hpp>
#include <vlGraphics/plugins/ioVLX.hpp>
#include <vlGraphics/DepthSortCallback.hpp>
#include <vlGraphics/GeometryPrimitives.hpp>
Michele Bosi's avatar
Michele Bosi committed
49
#include <vlVivid/VividRendering.hpp>
50
#include <vlGraphics/CalibratedCamera.hpp>
51
#include <vlGraphics/AdjacencyExtractor.hpp>
Michele Bosi's avatar
Michele Bosi committed
52

53
// #define MODEL_FILENAME "/tmp/dragon.ply"
54
// #define MODEL_FILENAME "/tmp/bunny.ply"
55 56
// #define MODEL_FILENAME "/tmp/niftk.vlb"
#define MODEL_FILENAME "/tmp/rsg-liver.vlb"
Michele Bosi's avatar
Michele Bosi committed
57 58
// #define MODEL_FILENAME "/tmp/MRV.stl"

Michele Bosi's avatar
Michele Bosi committed
59

60 61
using namespace vl;

Michele Bosi's avatar
Michele Bosi committed
62 63 64 65 66
class App_Vivid: public BaseDemo
{
public:
  void initEvent()
  {
Michele Bosi's avatar
Michele Bosi committed
67 68
    Log::notify( appletInfo() );

69 70
    Log::print( Say("GL_VERSION: %s\n") << glGetString(GL_VERSION));
    Log::print( Say("GL_RENDERER: %s\n\n") << glGetString(GL_RENDERER));
Michele Bosi's avatar
Michele Bosi committed
71

Michele Bosi's avatar
Michele Bosi committed
72
    openglContext()->setContinuousUpdate( false );
73 74 75

    // Vivid Rendering

76
    mVividRendering = new VividRendering;
77 78 79
    mVivid = mVividRendering->vividRenderer();
    trackball()->setCamera( mVividRendering->calibratedCamera() );

80 81
    // Other

82
    mLiverOutlineMode = new Uniform( "vl_Vivid.renderMode" );
83
    mLiverOutlineMode->setUniformI( 4 );
84
    mOutlineMode = new Uniform( "vl_Vivid.renderMode" );
85
    mOutlineMode->setUniformI( 0 );
86 87
    mOutlineSlicePlane = new Uniform( "vl_Vivid.outline.slicePlane" );
    mOutlineSlicePlane->setUniform( vec4( 1, 0, 0, 0 ) );
Michele Bosi's avatar
Michele Bosi committed
88

89
#if 0
Michele Bosi's avatar
Michele Bosi committed
90 91
    initScene();
#else
92
    std::vector<String> files;
Michele Bosi's avatar
Michele Bosi committed
93 94
    files.push_back(MODEL_FILENAME);
    loadModel(files);
Michele Bosi's avatar
Michele Bosi committed
95
#endif
96

Michele Bosi's avatar
Michele Bosi committed
97 98
    // mBackgroundImages[0] = loadImage( "/tmp/rsg-liver.png" );
    mBackgroundImages[0] = loadImage( "/tmp/liver.jpg" );
99 100 101
    mBackgroundImages[1] = loadImage( "/images/sun1.png" );
    mBackgroundImages[2] = loadImage( "/images/sun2.png" );
    mBackgroundImages[3] = loadImage( "/images/sun3.png" );
102
    // deep copy
103
    mBackgroundImage = new Image;
104
    *mBackgroundImage = *mBackgroundImages[0];
Michele Bosi's avatar
Michele Bosi committed
105 106
  }

107

Michele Bosi's avatar
Michele Bosi committed
108
  void initScene() {
109 110 111 112 113
    ref<Effect> fx1 = VividRendering::makeVividEffect();
    fx1->shader()->disable(EN_BLEND);
    fx1->shader()->enable(EN_DEPTH_TEST);
    fx1->shader()->enable(EN_LIGHTING);
    fx1->shader()->setRenderState( new Light, 0 );
Michele Bosi's avatar
Michele Bosi committed
114
    fx1->shader()->gocLightModel()->setTwoSide(true);
115
    fx1->shader()->gocLightModel()->setLocalViewer(true);
116 117 118
    fx1->shader()->gocMaterial()->setAmbient( fvec4(1.0f, 1.0f, 1.0f, 1.0f) );
    fx1->shader()->gocMaterial()->setDiffuse( fvec4(1.0f, 0.0f, 0.0f, 1.0f) );
    fx1->shader()->gocMaterial()->setSpecular( fvec4(1.0f, 1.0f, 1.0f, 1.0f) );
119
    fx1->shader()->gocMaterial()->setShininess(128.0f);
120
    fx1->shader()->gocMaterial()->setColorMaterialEnabled(false);
121
    fx1->shader()->gocMaterial()->setColorMaterial(PF_FRONT_AND_BACK, CM_DIFFUSE);
122
    fx1->shader()->gocUniform("vl_Vivid.colorMaterialEnabled")->setUniform( 0 );
Michele Bosi's avatar
Michele Bosi committed
123

124 125 126 127 128
    ref<Effect> fx2 = VividRendering::makeVividEffect();
    fx2->shader()->enable(EN_BLEND);
    fx2->shader()->enable(EN_DEPTH_TEST);
    fx2->shader()->enable(EN_LIGHTING);
    fx2->shader()->setRenderState( new Light, 0 );
Michele Bosi's avatar
Michele Bosi committed
129
    fx2->shader()->gocLightModel()->setTwoSide(true);
130
    fx2->shader()->gocLightModel()->setLocalViewer(true);
131 132
    fx2->shader()->gocMaterial()->setDiffuse( fvec4(1.0f, 1.0f, 0.0f, 0.25f) );
    fx2->shader()->gocMaterial()->setSpecular( fvec4(1.0f, 1.0f, 1.0f, 1.0f) );
133
    fx2->shader()->gocMaterial()->setShininess(128.0f);
134
    fx2->shader()->gocMaterial()->setColorMaterialEnabled(true);
135
    fx2->shader()->gocMaterial()->setColorMaterial(PF_FRONT_AND_BACK, CM_DIFFUSE);
136
    fx2->shader()->gocUniform("vl_Vivid.colorMaterialEnabled")->setUniform( 1 );
137

138 139
    ref< Transform > tr1 = new Transform();
    tr1->setLocalAndWorldMatrix(mat4::getTranslation(+0.025f, 0, 0));
Michele Bosi's avatar
Michele Bosi committed
140

141 142
    ref< Transform > tr2 = new Transform();
    tr2->setLocalAndWorldMatrix(mat4::getTranslation(-0.025f, 0, 0) * mat4::getRotationXYZ(90, 0, 0));
Michele Bosi's avatar
Michele Bosi committed
143

144 145
    ref< Geometry > torus = makeTorus( vec3( 0, 0, 0 ), 0.1f, 0.02f, 20, 40 );
    torus->setColorArray(fvec4(1.0f, 0.5f, 0.0f, 0.25f));
Michele Bosi's avatar
Michele Bosi committed
146

147 148
    mVividRendering->sceneManager()->tree()->addActor( torus.get(), fx1.get(), tr1.get() );
    mVividRendering->sceneManager()->tree()->addActor( torus.get(), fx2.get(), tr2.get() );
Michele Bosi's avatar
Michele Bosi committed
149 150 151 152 153 154

    adjustScene();
  }

  void adjustScene() {
    // position the camera to nicely see the objects in the scene
155
    trackball()->adjustView( mVividRendering.get(), vec3(0,0,1), vec3(0,1,0), 1.0f );
Michele Bosi's avatar
Michele Bosi committed
156 157

    // throttle ghost camera manipulator speed based on the scene size, using a simple euristic formula
158 159 160
    mVividRendering->sceneManager()->computeBounds();
    const AABB& scene_aabb = mVividRendering->sceneManager()->boundingBox();
    real speed = (scene_aabb.width() + scene_aabb.height() + scene_aabb.depth()) / 20.0f;
Michele Bosi's avatar
Michele Bosi committed
161 162 163
    ghostCameraManipulator()->setMovementSpeed(speed);
  }

164 165
  String filename( const String& path ) {
      std::vector< String > splits;
166 167 168 169
      path.split('/', splits, true);
      return splits.back();
  }

170
  void loadModel(const std::vector<String>& files)
Michele Bosi's avatar
Michele Bosi committed
171 172 173
  {
    // default effects

174
    mVividRendering->sceneManager()->tree()->actors()->clear();
Michele Bosi's avatar
Michele Bosi committed
175 176 177

    for(unsigned int i=0; i<files.size(); ++i)
    {
178
      ref<ResourceDatabase> resource_db = loadResource(files[i], false);
Michele Bosi's avatar
Michele Bosi committed
179

180
      if (!resource_db || resource_db->count<Actor>() == 0)
Michele Bosi's avatar
Michele Bosi committed
181 182 183 184 185 186 187 188 189 190 191 192 193
      {
        VL_LOG_ERROR << "No data found.\n";
        continue;
      }

#if 0
      // VLX save
      String save_path = files[i].extractPath() + files[i].extractFileName() + ".vlb";
      saveVLB(save_path, resource_db.get());
#endif

      showStatistics(resource_db);

Michele Bosi's avatar
Michele Bosi committed
194
      for(size_t j=0; j<resource_db->resources().size(); ++j)
Michele Bosi's avatar
Michele Bosi committed
195
      {
196
        Actor* act = resource_db->resources()[j]->as<Actor>();
Michele Bosi's avatar
Michele Bosi committed
197

198
        if ( ! act )
Michele Bosi's avatar
Michele Bosi committed
199 200
          continue;

201
        printf( "Actor: %s\n", act->objectName().c_str() );
202

203 204 205 206
        mLastModelName = filename( files[i] );

        // saveActor( act );

207
        // act->actorEventCallbacks()->push_back( new DepthSortCallback );
Michele Bosi's avatar
Michele Bosi committed
208

209
        Geometry* geom = act->lod(0)->as<Geometry>();
210
        geom->computeNormals();
211 212
        if ( geom->drawCalls()[0]->primitiveType() != PT_TRIANGLES_ADJACENCY ) {
          ref< Geometry > geom_adj = AdjacencyExtractor::extract( geom );
213 214
          geom->shallowCopyFrom( *geom_adj );
        }
215

216
        // const AABB& aabb = act->boundingBox();
217 218 219
        geom->setBoundsDirty( true );
        act->computeBounds();

220 221
        #if 0
          // Center
222
          geom->vertexArray()->transform( mat4::getTranslation( -1.0f * aabb.center() ) );
223 224 225 226 227 228 229 230
          geom->setBoundsDirty( true );
          act->computeBounds();
          if ( act->transform() ) {
            act->transform()->computeWorldMatrix();
          }

          // Scale to 1 meter
          float s = 1000.0f / aabb.width();
231
          geom->vertexArray()->transform( mat4::getScaling( s, s, s ) );
232 233 234 235 236 237 238 239
          geom->setBoundsDirty( true );
          act->computeBounds();

          printf("aabb: %f %f %f\n", aabb.width(), aabb.height(), aabb.depth() );
          printf("aabb-min: %f %f %f\n", aabb.minCorner().x(), aabb.minCorner().y(), aabb.minCorner().z() );
          printf("aabb-max: %f %f %f\n", aabb.maxCorner().x(), aabb.maxCorner().y(), aabb.maxCorner().z() );
        #endif

240
        // Get, init or create the effect using incoming material settings if any
241
        ref<Effect> fx1 = VividRendering::makeVividEffect( act->effect() );
242
        act->setEffect( fx1.get() );
243 244 245 246 247 248 249 250
        if ( fx1->shader()->getMaterial() ) {
          Shader* sh = fx1->shader();
          sh->gocUniform( "vl_Vivid.material.diffuse" )->setUniform( sh->getMaterial()->frontDiffuse() );
          sh->gocUniform( "vl_Vivid.material.specular" )->setUniform( sh->getMaterial()->frontSpecular() );
          sh->gocUniform( "vl_Vivid.material.ambient" )->setUniform( sh->getMaterial()->frontAmbient() );
          sh->gocUniform( "vl_Vivid.material.emission" )->setUniform( sh->getMaterial()->frontEmission() );
          sh->gocUniform( "vl_Vivid.material.shininess" )->setUniformF( sh->getMaterial()->frontShininess() );
        }
Michele Bosi's avatar
Michele Bosi committed
251

252
        //if ( ! fx1.get() ) {
253
        //  fx1 = new Effect;
254 255
        //  act->setEffect(fx1.get());
        //}
256

257 258 259 260 261 262 263
        // Skip skin
        if ( act->objectName() == "surface:skin" ) {
          continue;
        }

        // bones
        if ( act->objectName() == "surface:bones" ) {
264
          //  fx1->shader()->gocMaterial()->setDiffuse( fvec4(0.8f, 0.0f, 0.0f, 1) );
265 266 267 268 269
          continue;
        }

        // Stencil Test: liver geometry
        if ( act->objectName() == "surface:liver" ) {
Michele Bosi's avatar
Michele Bosi committed
270
          // mVividRendering->stencilActors().push_back( act );
271
          // mVividRendering->setStencilEnabled( true );
272 273 274 275 276
          // continue;
          mLiverActor = act;
          // mLiverActor->setEnableMask( 0 );
        }

277 278
        if ( ! fx1->shader()->getMaterial() )
        {
279 280
          fx1->shader()->gocMaterial()->setDiffuse( fvec4(1.0f, 0.6f, 0.5f, 1.0) );
          fx1->shader()->gocMaterial()->setSpecular( fvec4(1.0f, 1.0f, 1.0f, 1.0f) );
281 282
          fx1->shader()->gocMaterial()->setShininess(128.0f);
        }
283

Michele Bosi's avatar
Michele Bosi committed
284 285
#if 0
        if ( j == 11 ) {
286
          fx1->shader()->gocMaterial()->setDiffuse( fvec4( 1, 1, 1, 1 ) );
Michele Bosi's avatar
Michele Bosi committed
287 288
          // continue;
        } else if ( j == 3 ) {
289
          fx1->shader()->gocMaterial()->setDiffuse( fvec4( 0.8f, 0.8f, 0.0f, 0.20 ) );
Michele Bosi's avatar
Michele Bosi committed
290 291 292 293 294
        } else {
          continue;
        }
#endif

295 296 297 298
        fx1->shader()->enable( EN_BLEND );
        fx1->shader()->enable( EN_DEPTH_TEST );
        fx1->shader()->enable( EN_LIGHTING );
        fx1->shader()->setRenderState( new Light, 0 );
299 300
        fx1->shader()->gocLightModel()->setTwoSide( true );
        fx1->shader()->gocLightModel()->setLocalViewer( true );
301
        // fx1->shader()->gocDepthMask()->set( false );
302

303
#if 0
304
        // Fog
305 306 307
        fx1->shader()->disable( EN_FOG );
        fx1->shader()->gocFog()->setMode( FM_LINEAR );
        fx1->shader()->gocFog()->setColor( black );
308 309 310
        fx1->shader()->gocFog()->setStart( act->boundingBox().width() * 1 ); // Only used with Linear mode
        fx1->shader()->gocFog()->setEnd( act->boundingBox().width() * 2 );   // Only used with Linear mode
        fx1->shader()->gocFog()->setDensity( 1.0f );                         // Only used with Exp & Exp2 mode
311 312
        fx1->shader()->gocUniform("vl_Vivid.fog.mode")->setUniformI( 1 );   // 0=OFF, 1=Linear, 2=Exp, 3=Exp2
        fx1->shader()->gocUniform("vl_Vivid.fog.target")->setUniformI( 0 ); // 0=Color, 1=Alpha, 2=Saturation
313 314
#endif

315
        fx1->shader()->gocUniform("vl_Vivid.outline.color")->setUniform( white );
316

317
        // Outline
318
        if ( act->objectName() == "surface:liver" ) {
319 320
          fx1->shader()->setUniform( mLiverOutlineMode.get() );
          fx1->shader()->setUniform( mOutlineSlicePlane.get() );
321
          fx1->shader()->gocUniform("vl_Vivid.outline.color")->setUniform( royalblue );
322
          fx1->shader()->gocUniform("vl_Vivid.renderMode")->setUniformI( 4 );
323 324 325
          fx1->setRenderRank( 1 );
        } else
        if ( act->objectName() == "surface:liver tumor" ) {
326
          fx1->shader()->gocUniform("vl_Vivid.outline.color")->setUniform( green );
327
          fx1->shader()->gocUniform("vl_Vivid.renderMode")->setUniformI( 4 );
328 329 330
          fx1->setRenderRank( 2 );
        } else
        if ( act->objectName() == "surface:liver hypervascular lump" ) {
331
          fx1->shader()->gocUniform("vl_Vivid.outline.color")->setUniform( green );
332
          fx1->shader()->gocUniform("vl_Vivid.renderMode")->setUniformI( 4 );
333 334
          fx1->setRenderRank( 2 );
        } else {
335 336 337 338 339
          // fx1->shader()->gocUniform("vl_Vivid.renderMode")->setUniformI( j == 0 || j == 11 ); // 0=Polys, 1=Outline3D, 2=Polys + Outline
          // fx1->shader()->gocUniform("vl_Vivid.renderMode")->setUniformI( 0 ); // 0=Polys, 1=Outline3D, 2=Polys + Outline
          fx1->shader()->setUniform( mOutlineMode.get() );
          fx1->shader()->setUniform( mOutlineSlicePlane.get() );
          // Outline color must be provided
340
          // fx1->shader()->gocUniform("vl_Vivid.outline.color")->setUniform( j == 11 ? violet : pink );
341 342 343
        }

        // draw all outlines
344
        // fx1->shader()->gocUniform("vl_Vivid.renderMode")->setUniformI( 1 );
345

346
#if 0
347
        // Clipping
348

349
        // Clip volume #0
350 351 352
        fx1->shader()->gocUniform("vl_Vivid.smartClip[0].mode")->setUniformI( 2 ); // 0=OFF, 1=Sphere, 2=Box, 3=Plane
        fx1->shader()->gocUniform("vl_Vivid.smartClip[0].fadeRange")->setUniformF( 0.0 ); // 0=Sharp, 0...=Fuzzy
        fx1->shader()->gocUniform("vl_Vivid.smartClip[0].target")->setUniformI( 0 ); // 0=Color, 1=Alpha, 2=Saturation
353 354 355 356
        fx1->shader()->gocUniform("vl_Vivid.smartClip[0].color")->setUniform( royalblue );
        fx1->shader()->gocUniform("vl_Vivid.smartClip[0].sphere")->setUniform( vec4( 0, 0, 0, 350.0 ) );  // Sphere X,Y,Z,Radius (World Coords)
        fx1->shader()->gocUniform("vl_Vivid.smartClip[0].boxMin")->setUniform( vec3( -250, -250, -250 ) ); // AABB min edge       (World Coords)
        fx1->shader()->gocUniform("vl_Vivid.smartClip[0].boxMax")->setUniform( vec3( +250, +250, +250 ) ); // AABB max edge       (World Coords)
357
        fx1->shader()->gocUniform("vl_Vivid.smartClip[0].reverse")->setUniformI( 0 ); // 0=FALSE, 1=TRUE
358 359

        // Clip volume #1
360 361 362
        fx1->shader()->gocUniform("vl_Vivid.smartClip[1].mode")->setUniformI( 1 ); // 0=OFF, 1=Sphere, 2=Box, 3=Plane
        fx1->shader()->gocUniform("vl_Vivid.smartClip[1].fadeRange")->setUniformF( 50.0 ); // 0=Sharp, 0...=Fuzzy
        fx1->shader()->gocUniform("vl_Vivid.smartClip[1].target")->setUniformI( 1 ); // 0=Color, 1=Alpha, 2=Saturation
363 364 365 366
        fx1->shader()->gocUniform("vl_Vivid.smartClip[1].color")->setUniform( royalblue );
        fx1->shader()->gocUniform("vl_Vivid.smartClip[1].sphere")->setUniform( vec4( 0, -350, 0, 350.0 ) );  // Sphere X,Y,Z,Radius (World Coords)
        fx1->shader()->gocUniform("vl_Vivid.smartClip[1].boxMin")->setUniform( vec3( -250, -250, -250 ) ); // AABB min edge       (World Coords)
        fx1->shader()->gocUniform("vl_Vivid.smartClip[1].boxMax")->setUniform( vec3( +250, +250, +250 ) ); // AABB max edge       (World Coords)
367
        fx1->shader()->gocUniform("vl_Vivid.smartClip[1].reverse")->setUniformI( 1 ); // 0=FALSE, 1=TRUE
368

369
        // Clip volume #2
370 371 372
        fx1->shader()->gocUniform("vl_Vivid.smartClip[2].mode")->setUniformI( 3 ); // 0=OFF, 1=Sphere, 2=Box, 3=Plane
        fx1->shader()->gocUniform("vl_Vivid.smartClip[2].fadeRange")->setUniformF( 00.0 ); // 0=Sharp, 0...=Fuzzy
        fx1->shader()->gocUniform("vl_Vivid.smartClip[2].target")->setUniformI( 2 ); // 0=Color, 1=Alpha, 2=Saturation
373 374
        fx1->shader()->gocUniform("vl_Vivid.smartClip[2].color")->setUniform( royalblue );
        fx1->shader()->gocUniform("vl_Vivid.smartClip[2].plane")->setUniform( vec4( 0, 1, 0, -250 ) );    // Plane Nx,Ny,Nz,Pd (World Coords)
375 376 377
        fx1->shader()->gocUniform("vl_Vivid.smartClip[2].reverse")->setUniformI( 1 ); // 0=FALSE, 1=TRUE

        fx1->shader()->gocUniform("vl_Vivid.smartClip[3].mode")->setUniformI( 0 );
378
#else
379 380 381 382
        fx1->shader()->gocUniform("vl_Vivid.smartClip[0].mode")->setUniformI( 0 );
        fx1->shader()->gocUniform("vl_Vivid.smartClip[1].mode")->setUniformI( 0 );
        fx1->shader()->gocUniform("vl_Vivid.smartClip[2].mode")->setUniformI( 0 );
        fx1->shader()->gocUniform("vl_Vivid.smartClip[3].mode")->setUniformI( 0 );
383
#endif
Michele Bosi's avatar
Michele Bosi committed
384

385
        mVividRendering->sceneManager()->tree()->addActor( act );
Michele Bosi's avatar
Michele Bosi committed
386
        act->setEnableMask( vl::Vivid::VividEnableMask );
Michele Bosi's avatar
Michele Bosi committed
387 388 389 390
      }
    }

    adjustScene();
391 392 393 394
    // mic fixme:
    // - adjustScene() should take care of this?
    // - why don't we call it before?
    mVividRendering->sceneManager()->computeBounds();
395
    mVividRendering->sceneManager()->tree()->computeAABB();
396

Michele Bosi's avatar
Michele Bosi committed
397
#if 1
398
    // make spherical stencil
399 400 401
    ref< Geometry > icosphere = makeIcosphere( mVividRendering->sceneManager()->tree()->aabb().center() + vec3( -50, 0, 25 ), 100, 3 );
    // ref< Geometry > stencil = makeIcosphere( vec3( 0, 0, 0 ), 100, 3 );
    icosphere->computeNormals();
402 403
    // stencil = AdjacencyExtractor::extract( stencil.get() );
    ref< Effect > fx = VividRendering::makeVividEffect();
404 405 406 407 408 409 410 411 412 413
    ref< Transform > tr1 = new Transform;
    ref< Transform > tr2 = new Transform;
    Actor* stencil_act1 = mVividRendering->sceneManager()->tree()->addActor( icosphere.get(), fx.get(), tr1.get() );
    stencil_act1->setEnableMask( 0 );
    Actor* stencil_act2 = mVividRendering->sceneManager()->tree()->addActor( icosphere.get(), fx.get(), tr2.get() );
    stencil_act2->setEnableMask( 0 );
    mVividRendering->stencilActors().push_back( stencil_act1 );
    mVividRendering->stencilActors().push_back( stencil_act2 );
    tr1->setLocalAndWorldMatrix( vl::mat4::getTranslation(-50,0,0) );
    tr2->setLocalAndWorldMatrix( vl::mat4::getTranslation(+50,0,0) );
Michele Bosi's avatar
Michele Bosi committed
414
#endif
415

Michele Bosi's avatar
Michele Bosi committed
416
#if 1
Michele Bosi's avatar
Michele Bosi committed
417 418 419 420 421 422 423 424 425 426
    // make points
    {
      ref< Geometry > points = makeIcosphere( mVividRendering->sceneManager()->tree()->aabb().center() + vec3( -50, 0, 25 ), 100, 3 );
      points->drawCalls().clear();
      points->drawCalls().push_back( new vl::DrawArrays( vl::PT_POINTS, 0, points->vertexArray()->size() ) );
      points->setColorArray( vl::yellow );
      fx = VividRendering::makeVividEffect();
      fx->shader()->getPointSize()->set( 20 );
      Actor* points_act = mVividRendering->sceneManager()->tree()->addActor( points.get(), fx.get(), NULL );
  #if 1
Michele Bosi's avatar
Michele Bosi committed
427
      points_act->setEnableMask( vl::Vivid::VividEnableMask );
Michele Bosi's avatar
Michele Bosi committed
428 429 430 431
      fx->shader()->getUniform( "vl_Vivid.enableLighting" )->setUniformI( 0 );
      fx->shader()->getUniform( "vl_Vivid.enablePointSprite" )->setUniformI( 1 );
      fx->shader()->gocUniform( "vl_Vivid.enableTextureMapping" )->setUniformI( 1 );
      ref<vl::Image> img = new Image("/images/sphere.png");
Michele Bosi's avatar
Michele Bosi committed
432
      ref<vl::Texture> texture = fx->shader()->getTextureSampler( vl::Vivid::UserTexture )->texture();
Michele Bosi's avatar
Michele Bosi committed
433 434
      texture->createTexture2D( img.get(), vl::TF_UNKNOWN, false, false );
  #else
435
      points_act->setEnableMask( vl::VividRenderer::StandardEnableMask );
Michele Bosi's avatar
Michele Bosi committed
436 437 438 439 440 441
      fx->shader()->enable( vl::EN_POINT_SMOOTH );
      fx->shader()->enable( vl::EN_BLEND );
      fx->shader()->disable( vl::EN_LIGHTING );
      fx->shader()->gocHint()->setPointSmoothHint( vl::HM_FASTEST );
  #endif
    }
Michele Bosi's avatar
Michele Bosi committed
442 443
#endif

444
#if 0
445
    // fog
446 447 448 449 450
    ref< Fog > fog = new Fog();
    fog->setMode( FM_LINEAR );
    fog->setColor( black );
    fog->setStart( 100 /*mVividRendering->sceneManager()->boundingBox().width() * 1*/ ); // Only used with Linear mode
    fog->setEnd( 150 /*mVividRendering->sceneManager()->boundingBox().width() * 2*/ );   // Only used with Linear mode
451
    fog->setDensity( 1.0f );                                    // Only used with Exp & Exp2 mode
452

453
    // uniforms
454
    mFogMode = new Uniform( "vl_Vivid.fog.mode" );
455
    mFogMode->setUniformI( 0 );   // 0=OFF, 1=Linear, 2=Exp, 3=Exp2
456
    mFogTarget = new Uniform( "vl_Vivid.fog.target" );
457 458
    mFogTarget->setUniformI( 0 ); // 0=Color, 1=Alpha, 2=Saturation

459
    ActorCollection* actors = mVividRendering->sceneManager()->tree()->actors();
460
    for( int i=0; i<actors->size(); ++i ) {
461 462
      Shader* sh = actors->at( i )->effect()->shader();
        sh->disable( EN_FOG );
463 464 465 466
        sh->setRenderState( fog.get() );
        sh->setUniform( mFogMode.get() );
        sh->setUniform( mFogTarget.get() );
    }
467 468 469
#endif

    // Volume
470 471 472 473 474
    vec3 volume_box_center = mVividRendering->sceneManager()->tree()->aabb().center();
    AABB volume_box;
    volume_box.setMinCorner( volume_box_center - vec3(100,50,50) );
    volume_box.setMaxCorner( volume_box_center + vec3(100,50,50) );
    printf("%f %f %f\n", volume_box.width(), volume_box.height(), volume_box.depth() );
Michele Bosi's avatar
Michele Bosi committed
475
#if 1
476
    ref< Image > volume = vl::loadImage("/volume/BostonTeapot.dat");
477
    mVividRendering->setupVolume( volume.get(), volume_box, NULL );
478 479 480

    // volume bounding box outline
    ref<Effect> fx_box = VividRendering::makeVividEffect();
Michele Bosi's avatar
Michele Bosi committed
481
    fx_box->shader()->gocLineWidth()->set( 3 );
482
    fx_box->shader()->gocPolygonMode()->set( PM_LINE, PM_LINE );
483
    fx_box->shader()->gocUniform( "vl_Vivid.enableLighting" )->setUniformI( 0 );
484 485
    ref<Geometry> box_outline = vl::makeBox( volume_box );
    box_outline->computeNormals();
486
    box_outline->setColorArray( vl::red );
487
    Actor* vol_box = mVividRendering->sceneManager()->tree()->addActor( box_outline.get(), fx_box.get(), mVividRendering->vividVolume()->volumeTransform() );
Michele Bosi's avatar
Michele Bosi committed
488
    vol_box->setEnableMask( vl::Vivid::VividEnableMask );
489
    vol_box->setObjectName( "Volume Box" );
Michele Bosi's avatar
Michele Bosi committed
490
#endif
491

Michele Bosi's avatar
Michele Bosi committed
492
#if 1
Michele Bosi's avatar
Michele Bosi committed
493 494 495 496 497 498
    // texture mapped quad
    ref<Image> vl_img = loadImage( "/tmp/liver/VL-Stencil.png" );
    ref<Geometry> quad = vl::makeGrid( volume_box.center(), volume_box.width(), volume_box.depth(), 10, 10, true );
    fx = vl::VividRendering::makeVividEffect();
    Actor* quad_act = mVividRendering->sceneManager()->tree()->addActor( quad.get(), fx.get(), NULL );
    quad->setObjectName( "QUAD" );
Michele Bosi's avatar
Michele Bosi committed
499
    quad_act->setEnableMask( vl::Vivid::VividEnableMask );
Michele Bosi's avatar
Michele Bosi committed
500 501 502 503 504
    fx->shader()->getUniform("vl_Vivid.enableTextureMapping")->setUniformI( 1 );
    fx->shader()->getUniform("vl_Vivid.enableLighting")->setUniformI( 0 );
    // When texture mapping is enabled texture is modulated by vertex color
    quad->setColorArray( vl::white );
    // These must be present as part of the default Vivid material
Michele Bosi's avatar
Michele Bosi committed
505 506
    VL_CHECK( fx->shader()->getTextureSampler( vl::Vivid::UserTexture ) )
    VL_CHECK( fx->shader()->getTextureSampler( vl::Vivid::UserTexture )->texture() )
507 508
    VL_CHECK( fx->shader()->getUniform("vl_UserTexture2D") );
    VL_CHECK( fx->shader()->getUniform("vl_UserTexture2D")->getUniformI() == vl::Vivid::UserTexture );
Michele Bosi's avatar
Michele Bosi committed
509
    ref<vl::Texture> texture = fx->shader()->getTextureSampler( vl::Vivid::UserTexture )->texture();
Michele Bosi's avatar
Michele Bosi committed
510 511
    // Recreate new texture (TexParameter is not reset so we can keep the current defaults)
    texture->createTexture2D( vl_img.get(), vl::TF_UNKNOWN, false, false );
Michele Bosi's avatar
Michele Bosi committed
512
#endif
513
    adjustScene();
Michele Bosi's avatar
Michele Bosi committed
514 515
  }

516 517
  void saveActor( Actor* act ) {
      ref< ResourceDatabase > db = new ResourceDatabase;
518
      // db->resources().push_back( act );
519
      // String fname = filename( files[i] );
520
      db->resources().push_back( act );
521 522
      Geometry* geom = act->lod(0)->as< Geometry >();
      ref< ArrayAbstract > na = geom->normalArray();
523
      geom->setNormalArray( NULL );
524 525 526
      String fname = mLastModelName;
      saveVLT( "C:/git-ucl/VisualizationLibrary/data/tmp/_" + fname + ".vlt", db.get() );
      saveVLB( "C:/git-ucl/VisualizationLibrary/data/tmp/_" + fname + ".vlb", db.get() );
527 528
      geom->setNormalArray( na.get() );
  }
Michele Bosi's avatar
Michele Bosi committed
529
  //--------------------------------------------------------------------------
530
  void keyPressEvent(unsigned short unicode_ch, EKey /*key*/)
Michele Bosi's avatar
Michele Bosi committed
531 532 533 534 535
  {
    // BaseDemo::keyReleaseEvent(unicode_ch, key);

    switch((unsigned char)tolower(unicode_ch))
    {
Michele Bosi's avatar
Michele Bosi committed
536
    case 'b':
537 538
      mVividRendering->setBackgroundImageEnabled( ! mVividRendering->backgroundImageEnabled() );
      if ( mVividRendering->backgroundImageEnabled() ) {
539 540
        // mVividRendering->setBackgroundImage( mBackgroundImage.get() );
        mVividRendering->backgroundTexSampler()->texture()->createTexture2D( mBackgroundImage.get(), TF_RGBA, false, false );
541 542
      }
      break;
Michele Bosi's avatar
Michele Bosi committed
543
    case 'v':
544
      mVividRendering->setStencilEnabled( ! mVividRendering->stencilEnabled() );
545
      break;
546
    case 'n':
547
      mOutlineMode->setUniformI( (mOutlineMode->getUniformI() + 1) % 6 );
Michele Bosi's avatar
Michele Bosi committed
548 549
      break;
    case 'r':
550
      mVivid->initShaders();
551
      mVividRendering->vividVolume()->volumeGLSLProgram()->reload();
552
      break;
Michele Bosi's avatar
Michele Bosi committed
553
    case 'q':
554 555
      mVivid->setUseQueryObject(!mVivid->useQueryObject());
      break;
Michele Bosi's avatar
Michele Bosi committed
556
    case '+':
557 558
      mVivid->setNumPasses(mVivid->numPasses() + 1);
      break;
Michele Bosi's avatar
Michele Bosi committed
559
    case '-':
560 561 562 563
      if (mVivid->numPasses() > 1) {
        mVivid->setNumPasses(mVivid->numPasses() - 1);
      }
      break;
Michele Bosi's avatar
Michele Bosi committed
564
    case '1':
Michele Bosi's avatar
Michele Bosi committed
565
      mVividRendering->setRenderingMode(Vivid::DepthPeeling);
566
      break;
Michele Bosi's avatar
Michele Bosi committed
567
    case '2':
Michele Bosi's avatar
Michele Bosi committed
568
      mVividRendering->setRenderingMode(Vivid::FastRender);
569
      break;
Michele Bosi's avatar
Michele Bosi committed
570
    case '3':
Michele Bosi's avatar
Michele Bosi committed
571
      mVividRendering->setRenderingMode(Vivid::StencilRender);
572 573
      break;
    case 's':
574
      saveActor( this->mVividRendering->sceneManager()->tree()->actors()->at(0) );
575
      break;
Michele Bosi's avatar
Michele Bosi committed
576
    case 'a': {
577
        float opacity = mVividRendering->opacity() - 0.025f;
578
        opacity = max(opacity, 0.0f);
579
        mVividRendering->setOpacity( opacity );
580 581
        printf("opacity: %f\n", opacity);
      }
Michele Bosi's avatar
Michele Bosi committed
582 583
      break;
    case 'd': {
584
        float opacity = mVividRendering->opacity() + 0.025f;
585
        opacity = min(opacity, 1.0f);
586
        mVividRendering->setOpacity( opacity );
587 588 589
        printf("opacity: %f\n", opacity);
      }
      break;
590 591 592 593 594 595 596
    case 'o':
      mFogMode->setUniformI( ( mFogMode->getUniformI() + 1 ) % 4 );
      break;
    case 'p':
      mFogTarget->setUniformI( ( mFogTarget->getUniformI() + 1 ) % 3 );
      break;
    case 'i':
597 598
      mLiverOutlineMode->setUniformI( ( mLiverOutlineMode->getUniformI() + 1 ) % 6 );
      // mLiverActor->setEnableMask( mLiverOutlineMode->getUniformI() == 1 );
599 600
      break;
    }
Michele Bosi's avatar
Michele Bosi committed
601

602
    const char* method[] = { "DepthPeeling", "FastRender", "StencilRender" };
603
    printf("method:           %s\n", method[mVividRendering->renderingMode()]);
Michele Bosi's avatar
Michele Bosi committed
604 605 606
    printf("pass counter:     %d\n", mVivid->passCounter());
    printf("num passes:       %d\n", mVivid->numPasses());
    printf("use query object: %d\n", mVivid->useQueryObject());
Michele Bosi's avatar
Michele Bosi committed
607 608 609 610
    printf("---\n");
    openglContext()->update();
  }

611 612 613 614 615 616
  void resizeEvent(int w, int h)
  {
    mVividRendering->camera()->viewport()->set( 0, 0, w, h );
    mVividRendering->camera()->setProjectionPerspective();
  }

617
  void updateEvent() {
618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637
    openglContext()->makeCurrent();

    // FPS counter
    if (Time::currentTime() - mStartTime > 0.500f)
    {
      double secs = (Time::currentTime() - mStartTime);
      mFPS = mFrameCount / secs;
      mFrameCount = 0;
      mStartTime = Time::currentTime();
    }
    mFrameCount++;

    // update the scene content
    updateScene();

    // set frame time for all the rendering
    real now_time = Time::currentTime();
    mVividRendering->setFrameClock( now_time );

    // execute rendering
638
    mVividRendering->render( openglContext()->framebuffer() );
639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655

    // show rendering
    if ( openglContext()->hasDoubleBuffer() ) {
      openglContext()->swapBuffers();
    }

    VL_CHECK_OGL();

    // useful for debugging
    // wglMakeCurrent(NULL,NULL);

    if ( mFPSTimer.elapsed() > 1 )
    {
      mFPSTimer.start();
      openglContext()->setWindowTitle( vl::Say("[%.1n] %s") << fps() << appletName()  + " - " + vl::String("VL ") + vl::VisualizationLibrary::versionString() );
      vl::Log::print( vl::Say("FPS=%.1n\n") << fps() );
    }
656

657
    // update textured quad
658
    //if ( mVivid->backgroundImage() == mBackgroundImage.get() && mVivid->backgroundImageEnabled() ) {
659
    //  if ( fract( Time::currentTime() ) < 0.25f ) {
660 661
    //    memcpy( mBackgroundImage->pixels(), mBackgroundImages[0]->pixels(), mBackgroundImage->requiredMemory() );
    //    mVivid->updateBackgroundImage();
662
    //  } else
663
    //  if ( fract( Time::currentTime() ) < 0.50f ) {
664 665
    //    memcpy( mBackgroundImage->pixels(), mBackgroundImages[1]->pixels(), mBackgroundImage->requiredMemory() );
    //    mVivid->updateBackgroundImage();
666
    //  } else
667
    //  if ( fract( Time::currentTime() ) < 0.75f ) {
668 669 670 671 672 673 674
    //    memcpy( mBackgroundImage->pixels(), mBackgroundImages[2]->pixels(), mBackgroundImage->requiredMemory() );
    //    mVivid->updateBackgroundImage();
    //  } else {
    //    memcpy( mBackgroundImage->pixels(), mBackgroundImages[3]->pixels(), mBackgroundImage->requiredMemory() );
    //    mVivid->updateBackgroundImage();
    //  }
    //}
675 676
  }

677
  void showStatistics(ref<ResourceDatabase> res_db)
Michele Bosi's avatar
Michele Bosi committed
678
  {
679 680 681
    std::set<Geometry*> geometries;
    std::vector< ref<Geometry> > geom_db;
    std::vector< ref<Actor> > actor_db;
Michele Bosi's avatar
Michele Bosi committed
682

683 684
    res_db->get<Actor>(actor_db);
    res_db->get<Geometry>(geom_db);
Michele Bosi's avatar
Michele Bosi committed
685 686 687 688 689 690 691 692

    // find number of unique geometries

    for(size_t i=0; i<geom_db.size(); ++i)
      geometries.insert( geom_db[i].get() );

    for(size_t i=0; i<actor_db.size(); ++i)
    {
693
      Geometry* geom = actor_db[i]->lod(0)->as<Geometry>();
Michele Bosi's avatar
Michele Bosi committed
694 695 696 697 698 699
      if (geom)
        geometries.insert( geom );
    }

    int total_triangles = 0;
    int total_draw_calls = 0;
700
    for( std::set<Geometry*>::iterator it = geometries.begin(); it != geometries.end(); ++it )
Michele Bosi's avatar
Michele Bosi committed
701 702 703 704 705 706 707 708 709 710 711 712 713
    {
      total_draw_calls += (*it)->drawCalls().size();
      for(int i=0; i < (*it)->drawCalls().size(); ++i )
        total_triangles += (*it)->drawCalls().at(i)->countTriangles();
    }

    VL_LOG_PRINT << "Statistics:\n";
    VL_LOG_PRINT << "+ Total triangles  = " << total_triangles << "\n";
    VL_LOG_PRINT << "+ Total draw calls = " << total_draw_calls << "\n";
    VL_LOG_PRINT << "+ Actors           = " << actor_db.size() << "\n";
    VL_LOG_PRINT << "+ Geometries       = " << geometries.size() << "\n";
  }

714
  void fileDroppedEvent(const std::vector<String>& files)
Michele Bosi's avatar
Michele Bosi committed
715 716 717 718 719 720 721
  {
    loadModel(files);
    // update the rendering
    openglContext()->update();
  }

protected:
Michele Bosi's avatar
Michele Bosi committed
722
  ref<VividRendering> mVividRendering;
723 724
  ref<VividRenderer> mVivid;

Michele Bosi's avatar
Michele Bosi committed
725
  std::set<ref<Effect>> mEffects;
726 727
  std::vector<String> mLastShaders;
  String mLastModelName;
Michele Bosi's avatar
Michele Bosi committed
728 729 730 731 732 733 734 735
  ref<Image> mBackgroundImages[4];
  ref<Image> mBackgroundImage;
  ref<Uniform> mOutlineMode;
  ref<Uniform> mOutlineSlicePlane;
  ref<Uniform> mFogMode;
  ref<Uniform> mFogTarget;
  ref<Uniform> mLiverOutlineMode;
  ref<Actor> mLiverActor;
Michele Bosi's avatar
Michele Bosi committed
736 737 738 739 740
};

// Have fun!

BaseDemo* Create_App_Vivid() { return new App_Vivid; }