Skip to content

Commit

Permalink
Added support for multiple volumes
Browse files Browse the repository at this point in the history
  • Loading branch information
favreau committed Oct 24, 2016
1 parent 6c96b58 commit 2620852
Show file tree
Hide file tree
Showing 23 changed files with 428 additions and 205 deletions.
7 changes: 3 additions & 4 deletions brayns/Brayns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -140,13 +140,12 @@ struct Brayns::Impl

if(!volumeParameters.getFilename().empty() || !volumeParameters.getFolder().empty())
{
const Vector3ui& volumeDimensions = scene->getVolumeHandler()->getDimensions();
const Vector3f& volumeScale = volumeParameters.getScale();
const Vector3ui& volumeDimensions = scene->getVolumeHandler()->getDimensions( 0.f );
const Vector3f& volumeElementSpacing = volumeParameters.getElementSpacing();
Boxf& worldBounds = scene->getWorldBounds();
worldBounds.merge( Vector3f( 0.f, 0.f, 0.f ));
worldBounds.merge( Vector3f( volumeDimensions ) * volumeScale );
worldBounds.merge( Vector3f( volumeDimensions ) * volumeElementSpacing );
}
scene->commitVolumeData();

if( scene->isEmpty() && !scene->getVolumeHandler() )
scene->buildDefault();
Expand Down
6 changes: 3 additions & 3 deletions brayns/common/scene/Scene.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@
#include <servus/uri.h>

#include <boost/filesystem.hpp>
#include <algorithm>

namespace brayns
{
Expand Down Expand Up @@ -523,12 +522,12 @@ VolumeHandlerPtr Scene::getVolumeHandler()

if( !_volumeHandler && ( !volumeFile.empty() || !volumeFolder.empty() ))
{
_volumeHandler.reset( new VolumeHandler( _parametersManager.getVolumeParameters() ));
_volumeHandler.reset(
new VolumeHandler( _parametersManager.getVolumeParameters(), TM_MODULO ));
if( !volumeFile.empty() )
_volumeHandler->attachVolumeToFile( 0.f, volumeFile );
else
{
float timestamp = 0.f;
strings filenames;

boost::filesystem::directory_iterator endIter;
Expand All @@ -550,6 +549,7 @@ VolumeHandlerPtr Scene::getVolumeHandler()
}
}
std::sort(filenames.begin(), filenames.end());
float timestamp = 0.f;
for( const auto& filename: filenames )
{
_volumeHandler->attachVolumeToFile( timestamp, filename );
Expand Down
7 changes: 7 additions & 0 deletions brayns/common/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -299,6 +299,13 @@ enum CameraType
CT_PANORAMIC
};

enum TimestampMode
{
TM_DEFAULT,
TM_MODULO,
TM_BOUNDED
};

}

#endif // TYPES_H
177 changes: 142 additions & 35 deletions brayns/common/volume/VolumeHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,66 +28,173 @@
#include <sys/stat.h>
#include <fcntl.h>

namespace
{
const int NO_DESCRIPTOR = -1;
}

namespace brayns
{

VolumeHandler::VolumeHandler(
const VolumeParameters& volumeParameters )
: _dimensions( volumeParameters.getDimensions() )
VolumeParameters& volumeParameters,
const TimestampMode timestampMode )
: _volumeParameters( &volumeParameters )
, _currentTimestamp( std::numeric_limits<float>::max( ))
, _timestampRange( std::numeric_limits<float>::max(), std::numeric_limits<float>::min( ))
, _timestampMode( timestampMode )
{
}

VolumeHandler::~VolumeHandler()
{
for( auto memoryMapPtr: _memoryMapPtrs )
if( memoryMapPtr.second )
::munmap( (void *)memoryMapPtr.second, _size );

for( auto cacheFileDescriptor: _cacheFileDescriptors )
if( cacheFileDescriptor.second != -1 )
::close( cacheFileDescriptor.second );
_volumeDescriptors.clear();
}

void VolumeHandler::attachVolumeToFile( const float timestamp, const std::string& volumeFile )
{
BRAYNS_INFO << "Attaching " << volumeFile << " to timestamp " << timestamp << std::endl;
_cacheFileDescriptors[ timestamp ] = open( volumeFile.c_str(), O_RDONLY );
if( _cacheFileDescriptors[ timestamp ] == -1 )
BRAYNS_THROW( std::runtime_error( "Failed to attach " + volumeFile ));
_volumeDescriptors[ timestamp ].reset(
new VolumeDescriptor( volumeFile, _volumeParameters->getDimensions( )));
for( const auto& volumeDescriptor: _volumeDescriptors )
{
_timestampRange.x() = std::min( _timestampRange.x(), volumeDescriptor.first );
_timestampRange.y() = std::max( _timestampRange.y(), volumeDescriptor.first );
}
BRAYNS_INFO << "Attached " << volumeFile << " to timestamp "
<< timestamp << " " << _timestampRange << std::endl;
}

struct stat sb;
if( ::fstat( _cacheFileDescriptors[ timestamp ], &sb ) == -1 )
BRAYNS_THROW( std::runtime_error( "Failed to attach " + volumeFile ));
void* VolumeHandler::getData( const float timestamp )
{
const float ts = _getBoundedTimestamp( timestamp );
if( ts != _currentTimestamp &&
_volumeDescriptors.find( ts ) != _volumeDescriptors.end( ))
{
if( _volumeDescriptors.find( _currentTimestamp ) != _volumeDescriptors.end( ))
_volumeDescriptors[ _currentTimestamp ]->unmap();
_currentTimestamp = ts;
_volumeDescriptors[ _currentTimestamp ]->map();
}
return _volumeDescriptors[ _currentTimestamp ]->getMemoryMapPtr();
}

_memoryMapPtrs[ timestamp ] = ::mmap(
0, sb.st_size, PROT_READ, MAP_PRIVATE, _cacheFileDescriptors[ timestamp ], 0 );
if( _memoryMapPtrs[ timestamp ] == MAP_FAILED )
float VolumeHandler::getEpsilon(
const float timestamp ,
const Vector3f& elementSpacing,
const uint16_t samplesPerRay )
{
const float ts = _getBoundedTimestamp( timestamp );
if( _volumeDescriptors.find( ts ) != _volumeDescriptors.end( ))
{
Vector3f diag = Vector3f( _volumeDescriptors[ ts ]->getDimensions( )) * elementSpacing;
return std::max(diag.x(), std::max( diag.y(), diag.z())) / float( samplesPerRay );
}
else
{
_memoryMapPtrs[ timestamp ] = 0;
::close( _cacheFileDescriptors[ timestamp ] );
BRAYNS_THROW( std::runtime_error( "Failed to attach " + volumeFile ));
BRAYNS_ERROR << "No volume is attached to the specified timestamp: "
<< timestamp << std::endl;
return 0;
}
}

_size = sb.st_size;
const Vector3ui VolumeHandler::getDimensions( const float timestamp )
{
float ts = _getBoundedTimestamp( timestamp );
if( _volumeDescriptors.find( ts ) != _volumeDescriptors.end( ))
return _volumeDescriptors[ ts ]->getDimensions();
else
{
BRAYNS_ERROR << "No volume is attached to the specified timestamp: "
<< timestamp << std::endl;
return Vector3ui( 0.f );
}
}

BRAYNS_INFO << "Volume size : " << _size << " bytes ["
<< _size / 1048576 << " MB]" << std::endl;
BRAYNS_INFO << "Volume dimensions: " << _dimensions << std::endl;
BRAYNS_INFO << "Successfully attached to " << volumeFile << std::endl;
uint64_t VolumeHandler::getSize( const float timestamp )
{
const float ts = _getBoundedTimestamp( timestamp );
if( _volumeDescriptors.find( ts ) != _volumeDescriptors.end( ))
return _volumeDescriptors[ ts ]->getSize();
else
{
BRAYNS_ERROR << "No volume is attached to the specified timestamp: "
<< timestamp << std::endl;
return 0;
}
}

void* VolumeHandler::getData( const float timestamp )
float VolumeHandler::_getBoundedTimestamp( const float timestamp )
{
size_t ts = timestamp;
ts = ts % _memoryMapPtrs.size();
BRAYNS_INFO << "Assigning volume for timestamp " << ts << std::endl;
return _memoryMapPtrs[ ts ];
float result;
switch( _timestampMode )
{
case TM_MODULO:
result = size_t( timestamp + _timestampRange.x( )) % _volumeDescriptors.size();
break;
case TM_BOUNDED:
result = std::max( std::min( timestamp, _timestampRange.y( )), _timestampRange.x( ));
case TM_DEFAULT:
default:
result = timestamp;
}
return result;
}

float VolumeHandler::getEpsilon( const Vector3f& scale, const uint16_t samplesPerRay )
VolumeHandler::VolumeDescriptor::VolumeDescriptor(
const std::string& filename,
const Vector3f& dimensions )
: _filename( filename )
, _memoryMapPtr( 0 )
, _cacheFileDescriptor( NO_DESCRIPTOR )
, _dimensions( dimensions )
{
Vector3f diag = Vector3f(_dimensions) * scale;
return std::max(diag.x(), std::max( diag.y(), diag.z())) / float( samplesPerRay );
}

VolumeHandler::VolumeDescriptor::~VolumeDescriptor()
{
unmap();
}

void VolumeHandler::VolumeDescriptor::map()
{
_cacheFileDescriptor = open( _filename.c_str(), O_RDONLY );
if( _cacheFileDescriptor == NO_DESCRIPTOR )
{
BRAYNS_ERROR << "Failed to attach " << _filename << std::endl;
return;
}

struct stat sb;
if( ::fstat( _cacheFileDescriptor, &sb ) == NO_DESCRIPTOR )
{
BRAYNS_ERROR << "Failed to attach " << _filename << std::endl;
return;
}

_size = sb.st_size;
_memoryMapPtr = ::mmap( 0, _size, PROT_READ, MAP_PRIVATE, _cacheFileDescriptor, 0 );
if( _memoryMapPtr == MAP_FAILED )
{
_memoryMapPtr = 0;
::close( _cacheFileDescriptor );
_cacheFileDescriptor = NO_DESCRIPTOR;
BRAYNS_ERROR << "Failed to attach " << _filename << std::endl;
return;
}
}

void VolumeHandler::VolumeDescriptor::unmap()
{
if( _memoryMapPtr )
{
::munmap( (void*)_memoryMapPtr, _size );
_memoryMapPtr = 0;
}
if( _cacheFileDescriptor != NO_DESCRIPTOR )
{
::close( _cacheFileDescriptor );
_cacheFileDescriptor = NO_DESCRIPTOR;
}
}

}
Loading

0 comments on commit 2620852

Please sign in to comment.