Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added support for multiple volumes #37

Merged
merged 2 commits into from
Oct 25, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 4 additions & 3 deletions brayns/Brayns.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ struct Brayns::Impl

// Build geometry
loadData();
scene->commitVolumeData();
scene->buildEnvironment( );
scene->buildGeometry( );

Expand Down Expand Up @@ -140,13 +141,13 @@ struct Brayns::Impl

if(!volumeParameters.getFilename().empty() || !volumeParameters.getFolder().empty())
{
scene->getVolumeHandler()->setTimestamp( 0.f );
const Vector3ui& volumeDimensions = scene->getVolumeHandler()->getDimensions();
const Vector3f& volumeScale = volumeParameters.getScale();
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
36 changes: 19 additions & 17 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 @@ -160,6 +159,8 @@ void Scene::buildDefault( )
{
BRAYNS_INFO << "Building default Cornell Box scene" << std::endl;

const Vector3f WHITE = { 1.f, 1.f, 1.f };

const Vector3f positions[8] =
{
{ 0.f, 0.f, 0.f },
Expand Down Expand Up @@ -192,26 +193,24 @@ void Scene::buildDefault( )
{ 0.8f, 0.8f, 0.8f }
};

const Vector3f WHITE = { 1.f, 1.f, 1.f };

// Cornell box
for( size_t material = 1; material < 6; ++material )
{
_materials[material]->setColor( colors[material] );
_materials[material]->setColor( colors[ material ] );
_materials[material]->setSpecularColor( WHITE );
_materials[material]->setSpecularExponent( 10.f );
_materials[material]->setReflectionIndex( material == 4 ? 0.8f : 0.f );
_materials[material]->setOpacity( 1.f );
for( size_t i = 0; i < 6; ++i )
{
const Vector3f& position = positions[ indices[material][i] ];
const Vector3f& position = positions[ indices[ material ][ i ] ];
_trianglesMeshes[material].getVertices().push_back( position );
_bounds.merge( position );
_trianglesMeshes[material].getIndices().push_back(
Vector3i( 0, 1, 2 ));
_trianglesMeshes[material].getIndices().push_back(
Vector3i( 3, 4, 5 ));
}
_trianglesMeshes[material].getIndices().push_back(
Vector3ui( 0, 1, 2 ));
_trianglesMeshes[material].getIndices().push_back(
Vector3ui( 3, 4, 5 ));
}

size_t material = 7;
Expand Down Expand Up @@ -514,21 +513,23 @@ AbstractSimulationHandlerPtr Scene::getSimulationHandler() const

VolumeHandlerPtr Scene::getVolumeHandler()
{
const std::string& volumeFile =
_parametersManager.getVolumeParameters().getFilename();
const std::string& volumeFolder =
_parametersManager.getVolumeParameters().getFolder();
if( volumeFile.empty() && volumeFolder.empty() )
return 0;

try
{
const std::string& volumeFile =
_parametersManager.getVolumeParameters().getFilename();
const std::string& volumeFolder =
_parametersManager.getVolumeParameters().getFolder();

if( !_volumeHandler && ( !volumeFile.empty() || !volumeFolder.empty() ))
if( !_volumeHandler )
{
_volumeHandler.reset( new VolumeHandler( _parametersManager.getVolumeParameters() ));
_volumeHandler.reset( new VolumeHandler(
_parametersManager.getVolumeParameters(), TimestampMode::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 +551,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 class TimestampMode
{
unchanged,
modulo,
bounded
};

}

#endif // TYPES_H
174 changes: 139 additions & 35 deletions brayns/common/volume/VolumeHandler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,66 +28,170 @@
#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 )
, _timestamp( 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 ));
// Add volume descriptor for specified timestamp
_volumeDescriptors[ timestamp ].reset( new VolumeDescriptor(
volumeFile,
_volumeParameters->getDimensions(),
_volumeParameters->getElementSpacing(),
_volumeParameters->getOffset()));

struct stat sb;
if( ::fstat( _cacheFileDescriptors[ timestamp ], &sb ) == -1 )
BRAYNS_THROW( std::runtime_error( "Failed to attach " + volumeFile ));
// Update timestamp range
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;
}

_memoryMapPtrs[ timestamp ] = ::mmap(
0, sb.st_size, PROT_READ, MAP_PRIVATE, _cacheFileDescriptors[ timestamp ], 0 );
if( _memoryMapPtrs[ timestamp ] == MAP_FAILED )
void VolumeHandler::setTimestamp( const float timestamp )
{
const float ts = _getBoundedTimestamp( timestamp );
if( ts != _timestamp &&
_volumeDescriptors.find( ts ) != _volumeDescriptors.end( ))
{
_memoryMapPtrs[ timestamp ] = 0;
::close( _cacheFileDescriptors[ timestamp ] );
BRAYNS_THROW( std::runtime_error( "Failed to attach " + volumeFile ));
if( _volumeDescriptors.find( _timestamp ) != _volumeDescriptors.end( ))
_volumeDescriptors[ _timestamp ]->unmap();
_timestamp = ts;
_volumeDescriptors[ _timestamp ]->map();
}
}

_size = sb.st_size;
void* VolumeHandler::getData() const
{
return _volumeDescriptors.at( _timestamp )->getMemoryMapPtr();
}

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;
float VolumeHandler::getEpsilon(
const Vector3f& elementSpacing,
const uint16_t samplesPerRay )
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

const

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

{
const Vector3f diag = _volumeDescriptors.at( _timestamp )->getDimensions( ) * elementSpacing;
return diag.find_max() / float( samplesPerRay );
}

const Vector3ui VolumeHandler::getDimensions() const
{
return _volumeDescriptors.at( _timestamp )->getDimensions();
}

const Vector3f VolumeHandler::getElementSpacing() const
{
return _volumeDescriptors.at( _timestamp )->getElementSpacing();
}

void* VolumeHandler::getData( const float timestamp )
const Vector3f VolumeHandler::getOffset() const
{
size_t ts = timestamp;
ts = ts % _memoryMapPtrs.size();
BRAYNS_INFO << "Assigning volume for timestamp " << ts << std::endl;
return _memoryMapPtrs[ ts ];
return _volumeDescriptors.at( _timestamp )->getOffset();
}

float VolumeHandler::getEpsilon( const Vector3f& scale, const uint16_t samplesPerRay )
uint64_t VolumeHandler::getSize() const
{
Vector3f diag = Vector3f(_dimensions) * scale;
return std::max(diag.x(), std::max( diag.y(), diag.z())) / float( samplesPerRay );
return _volumeDescriptors.at( _timestamp )->getSize();
}

float VolumeHandler::_getBoundedTimestamp( const float timestamp ) const
{
float result;
switch( _timestampMode )
{
case TimestampMode::modulo:
result = size_t( timestamp + _timestampRange.x( )) % _volumeDescriptors.size();
break;
case TimestampMode::bounded:
result = std::max( std::min( timestamp, _timestampRange.y( )), _timestampRange.x( ));
case TimestampMode::unchanged:
default:
result = timestamp;
}
return result;
}

VolumeHandler::VolumeDescriptor::VolumeDescriptor(
const std::string& filename,
const Vector3ui& dimensions,
const Vector3f& elementSpacing,
const Vector3f& offset )
: _filename( filename )
, _memoryMapPtr( 0 )
, _cacheFileDescriptor( NO_DESCRIPTOR )
, _dimensions( dimensions )
, _elementSpacing( elementSpacing )
, _offset( offset )
{
}

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