volume conversion tools and really basic data converter app

This commit is contained in:
Emil Axelsson
2016-05-18 11:56:06 +02:00
parent 74c7413115
commit 2911168e5b
22 changed files with 1069 additions and 7 deletions

View File

@@ -0,0 +1,45 @@
#########################################################################################
# #
# OpenSpace #
# #
# Copyright (c) 2014-2016 #
# #
# Permission is hereby granted, free of charge, to any person obtaining a copy of this #
# software and associated documentation files (the "Software"), to deal in the Software #
# without restriction, including without limitation the rights to use, copy, modify, #
# merge, publish, distribute, sublicense, and/or sell copies of the Software, and to #
# permit persons to whom the Software is furnished to do so, subject to the following #
# conditions: #
# #
# The above copyright notice and this permission notice shall be included in all copies #
# or substantial portions of the Software. #
# #
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, #
# INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A #
# PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT #
# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF #
# CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE #
# OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #
#########################################################################################
set(APPLICATION_NAME DataConverter)
set(APPLICATION_LINK_TO_OPENSPACE ON)
include (${GHOUL_BASE_DIR}/support/cmake/handle_external_library.cmake)
set(application_path ${OPENSPACE_APPS_DIR}/DataConverter)
set(SOURCE_FILES
${application_path}/main.cpp
${application_path}/milkywayconversiontask.cpp
)
set(HEADER_FILES
${application_path}/conversiontask.h
${application_path}/milkywayconversiontask.h
)
add_executable(${APPLICATION_NAME} MACOSX_BUNDLE
${SOURCE_FILES}
${HEADER_FILES}
)

View File

@@ -0,0 +1,17 @@
#ifndef __CONVERSIONTASK_H__
#define __CONVERSIONTASK_H__
#include <functional>
namespace openspace {
namespace dataconverter {
class ConversionTask {
public:
virtual void perform(const std::function<void(float)>& onProgress) = 0;
};
}
}
#endif

View File

@@ -0,0 +1,77 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014-2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <iostream>
#include <string>
#include <glm/glm.hpp>
#include <ghoul/opengl/ghoul_gl.h>
#include <ghoul/io/texture/texturereader.h>
#include <ghoul/io/texture/texturereaderdevil.h>
#include <ghoul/io/texture/texturereaderfreeimage.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/ghoul.h>
#include <openspace/util/progressbar.h>
#include <apps/DataConverter/milkywayconversiontask.h>
int main(int argc, char** argv) {
using namespace openspace;
using namespace dataconverter;
ghoul::initialize();
#ifdef GHOUL_USE_DEVIL
ghoul::io::TextureReader::ref().addReader(std::make_shared<ghoul::io::TextureReaderDevIL>());
#endif // GHOUL_USE_DEVIL
#ifdef GHOUL_USE_FREEIMAGE
ghoul::io::TextureReader::ref().addReader(std::make_shared<ghoul::io::TextureReaderFreeImage>());
#endif // GHOUL_USE_FREEIMAGE
openspace::ProgressBar pb(100);
std::function<void(float)> onProgress = [&](float progress) {
pb.print(progress * 100);
};
// TODO: Make the converter configurable using either
// config files (json, lua dictionaries),
// lua scripts,
// or at the very least: a command line interface.
MilkyWayConversionTask mwConversionTask(
"F:/milky-way/cam2_main.",
".exr",
1385,
512,
"F:/milky-way/mw_512_512_64.rawvolume",
glm::vec3(512, 512, 64));
mwConversionTask.perform(onProgress);
std::cout << "Done." << std::endl;
std::cin.get();
return 0;
};

View File

@@ -0,0 +1,50 @@
#include <apps/DataConverter/milkywayconversiontask.h>
#include <modules/volume/textureslicevolumereader.h>
#include <modules/volume/rawvolumewriter.h>
#include <modules/volume/volumesampler.h>
namespace openspace {
namespace dataconverter {
MilkyWayConversionTask::MilkyWayConversionTask(
const std::string& inFilenamePrefix,
const std::string& inFilenameSuffix,
size_t inFirstIndex,
size_t inNSlices,
const std::string& outFilename,
const glm::ivec3& outDimensions)
: _inFilenamePrefix(inFilenamePrefix)
, _inFilenameSuffix(inFilenameSuffix)
, _inFirstIndex(inFirstIndex)
, _inNSlices(inNSlices)
, _outFilename(outFilename)
, _outDimensions(outDimensions) {}
void MilkyWayConversionTask::perform(const std::function<void(float)>& onProgress) {
std::vector<std::string> filenames;
for (int i = 0; i < _inNSlices; i++) {
filenames.push_back(_inFilenamePrefix + std::to_string(i + _inFirstIndex) + _inFilenameSuffix);
}
TextureSliceVolumeReader<glm::tvec4<GLfloat>> sliceReader(filenames, _inNSlices, 10);
sliceReader.initialize();
RawVolumeWriter<glm::tvec4<GLfloat>> rawWriter(_outFilename);
rawWriter.setDimensions(_outDimensions);
glm::vec3 resolutionRatio =
static_cast<glm::vec3>(sliceReader.dimensions()) / static_cast<glm::vec3>(rawWriter.dimensions());
VolumeSampler<TextureSliceVolumeReader<glm::tvec4<GLfloat>>> sampler(sliceReader, resolutionRatio);
std::function<glm::tvec4<GLfloat>(glm::ivec3)> sampleFunction = [&](glm::ivec3 outCoord) {
glm::vec3 inCoord = ((glm::vec3(outCoord) + glm::vec3(0.5)) * resolutionRatio) - glm::vec3(0.5);
glm::tvec4<GLfloat> value = sampler.sample(inCoord);
return value;
};
rawWriter.write(sampleFunction, onProgress);
}
}
}

View File

@@ -0,0 +1,41 @@
#ifndef __MILKYWAYCONVERSIONTASK_H__
#define __MILKYWAYCONVERSIONTASK_H__
#include <apps/DataConverter/conversiontask.h>
#include <string>
#include <glm/glm.hpp>
#include <functional>
#include <modules/volume/textureslicevolumereader.h>
#include <modules/volume/rawvolumewriter.h>
namespace openspace {
namespace dataconverter {
/**
* Converts a set of exr image slices to a raw volume
* with floating point RGBA data (32 bit per channel).
*/
class MilkyWayConversionTask : public ConversionTask {
public:
MilkyWayConversionTask(const std::string& inFilenamePrefix,
const std::string& inFilenameSuffix,
size_t inFirstIndex,
size_t inNSlices,
const std::string& outFilename,
const glm::ivec3& outDimensions);
void perform(const std::function<void(float)>& onProgress) override;
private:
std::string _inFilenamePrefix;
std::string _inFilenameSuffix;
size_t _inFirstIndex;
size_t _inNSlices;
std::string _outFilename;
glm::ivec3 _outDimensions;
};
}
}
#endif

View File

@@ -25,14 +25,24 @@
include(${OPENSPACE_CMAKE_EXT_DIR}/module_definition.cmake)
set(HEADER_FILES
# ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablevolume.h
# ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablevolumegl.h
${CMAKE_CURRENT_SOURCE_DIR}/rawvolume.h
${CMAKE_CURRENT_SOURCE_DIR}/rawvolumereader.h
${CMAKE_CURRENT_SOURCE_DIR}/rawvolumewriter.h
${CMAKE_CURRENT_SOURCE_DIR}/textureslicevolumereader.h
${CMAKE_CURRENT_SOURCE_DIR}/lrucache.h
${CMAKE_CURRENT_SOURCE_DIR}/linearlrucache.h
${CMAKE_CURRENT_SOURCE_DIR}/volumesampler.h
${CMAKE_CURRENT_SOURCE_DIR}/volumeutils.h
)
source_group("Header Files" FILES ${HEADER_FILES})
set(SOURCE_FILES
# ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablevolume.cpp
# ${CMAKE_CURRENT_SOURCE_DIR}/rendering/renderablevolumegl.cpp
${CMAKE_CURRENT_SOURCE_DIR}/rawvolume.inl
${CMAKE_CURRENT_SOURCE_DIR}/rawvolumereader.inl
${CMAKE_CURRENT_SOURCE_DIR}/rawvolumewriter.inl
${CMAKE_CURRENT_SOURCE_DIR}/textureslicevolumereader.inl
${CMAKE_CURRENT_SOURCE_DIR}/volumesampler.inl
${CMAKE_CURRENT_SOURCE_DIR}/volumeutils.cpp
)
source_group("Source Files" FILES ${SOURCE_FILES})

View File

@@ -0,0 +1,91 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __LRUCACHE_H__
#define __LRUCACHE_H__
#include <glm/glm.hpp>
#include <list>
#include <iterator>
namespace openspace {
template <typename ValueType>
class LinearLruCache {
public:
LinearLruCache(size_t capacity, size_t nIndices)
: _tracker()
, _cache(nIndices, std::make_pair(nullptr, _tracker.end()))
, _capacity(capacity) {};
bool has(size_t key) {
return _cache[key].first != nullptr;
};
void set(size_t key, ValueType value) {
auto prev = _cache[key];
if (prev.first != nullptr) {
prev.first = value;
std::list<size_t>::iterator trackerIter = prev.second;
_tracker.splice(_tracker.end(),
_tracker,
trackerIter);
}
else {
insert(key, value);
}
};
ValueType& use(size_t key) {
auto pair = _cache[key];
std::list<size_t>::iterator trackerIter = pair.second;
_tracker.splice(_tracker.end(),
_tracker,
trackerIter);
return pair.first;
};
ValueType& get(size_t key) {
return _cache[key].first;
};
void evict() {
_cache[_tracker.front()] = make_pair(nullptr, _tracker.end());
_tracker.pop_front();
};
size_t capacity() {
return _capacity;
};
private:
void insert(size_t key, const ValueType& value) {
if (_tracker.size() == _capacity) {
evict();
}
auto iter = _tracker.insert(_tracker.end(), key);
_cache[key] = std::make_pair(value, iter);
};
std::list<size_t> _tracker;
std::vector<std::pair<ValueType, typename std::list<size_t>::iterator>> _cache;
size_t _capacity;
};
}
#endif

91
modules/volume/lrucache.h Normal file
View File

@@ -0,0 +1,91 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __LRUCACHE_H__
#define __LRUCACHE_H__
#include <glm/glm.hpp>
#include <list>
#include <iterator>
namespace openspace {
template <typename KeyType, typename ValueType, template<typename...> class ContainerType>
class LruCache {
typedef KeyType K;
public:
LruCache(size_t capacity) {
_capacity = capacity;
};
bool has(const KeyType& key) {
return (_cache.find(key) != _cache.end());
};
void set(const KeyType& key, ValueType value) {
auto prev = _cache.find(key);
if (prev != _cache.end()) {
prev->second.first = value;
std::list<KeyType>::iterator trackerIter = prev->second.second;
_tracker.splice(_tracker.end(),
_tracker,
trackerIter);
}
else {
insert(key, value);
}
};
ValueType& use(const KeyType& key) {
auto iter = _cache.find(key);
std::list<KeyType>::iterator trackerIter = iter->second.second;
_tracker.splice(_tracker.end(),
_tracker,
trackerIter);
return iter->second.first;
};
ValueType& get(const KeyType& key) {
auto iter = _cache.find(key);
return iter->second.first;
};
void evict() {
_cache.erase(_cache.find(_tracker.front()));
_tracker.pop_front();
};
size_t capacity() {
return _capacity;
};
private:
void insert(const KeyType& key, const ValueType& value) {
if (_cache.size() == _capacity) {
evict();
}
auto iter = _tracker.insert(_tracker.end(), key);
_cache[key] = std::make_pair(value, iter);
};
ContainerType<KeyType, std::pair<ValueType, typename std::list<KeyType>::iterator>> _cache;
std::list<KeyType> _tracker;
size_t _capacity;
};
}
#endif

View File

@@ -0,0 +1,54 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __RAWVOLUME_H__
#define __RAWVOLUME_H__
namespace openspace {
template <typename Voxel>
class RawVolume {
public:
typedef Voxel VoxelType;
RawVolume(const glm::ivec3& dimensions);
glm::ivec3 dimensions() const;
void setDimensions(const glm::ivec3& dimensions);
VoxelType get(const glm::ivec3& coordinates) const;
VoxelType get(const size_t index) const;
void set(const glm::ivec3& coordinates, const VoxelType& value);
void set(size_t index, const VoxelType& value);
void forEachVoxel(const std::function<void(const glm::ivec3&, const VoxelType&)>& fn);
VoxelType* data();
private:
size_t coordsToIndex(const glm::ivec3& cartesian) const;
glm::ivec3 indexToCoords(size_t linear) const;
glm::ivec3 _dimensions;
std::vector<VoxelType> _data;
};
}
#include "rawvolume.inl"
#endif // __RAWVOLUME_H__

View File

@@ -0,0 +1,100 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#include <modules/volume/volumeutils.h>
namespace openspace {
template <typename VoxelType>
RawVolume<VoxelType>::RawVolume(const glm::ivec3& dimensions)
: _dimensions(dimensions)
, _data(static_cast<size_t>(dimensions.x) *
static_cast<size_t>(dimensions.y) *
static_cast<size_t>(dimensions.z)) {}
template <typename VoxelType>
glm::ivec3 RawVolume<VoxelType>::dimensions() const {
return _dimensions;
}
template <typename VoxelType>
void RawVolume<VoxelType>::setDimensions(const glm::ivec3& dimensions) {
_dimensions = dimensions;
_data.resize(static_cast<size_t>(dimensions.x) *
static_cast<size_t>(dimensions.y) *
static_cast<size_t>(dimensions.z));
}
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::get(const glm::ivec3& coordinates) const {
return get(coordsToIndex(coordinates, dimensions()));
}
template <typename VoxelType>
VoxelType RawVolume<VoxelType>::get(size_t index) const {
return _data[index];
}
template <typename VoxelType>
void RawVolume<VoxelType>::set(const glm::ivec3& coordinates, const VoxelType& value) {
return set(coordsToIndex(coordinates, dimensions()), value);
}
template <typename VoxelType>
void RawVolume<VoxelType>::set(size_t index, const VoxelType& value) {
_data[index] = value;
}
template <typename VoxelType>
void RawVolume<VoxelType>::forEachVoxel(
const std::function<void(const glm::ivec3&, const VoxelType&)>& fn)
{
glm::ivec3 dims = dimensions();
size_t nVals = static_cast<size_t>(dims.x) *
static_cast<size_t>(dims.y) *
static_cast<size_t>(dims.z);
for (size_t i = 0; i < nVals; i++) {
glm::ivec3 coords = indexToCoords(i);
fn(coords, _data[i]);
}
}
template <typename VoxelType>
size_t RawVolume<VoxelType>::coordsToIndex(const glm::ivec3& cartesian) const {
return volumeutils::coordsToIndex(cartesian, dimensions());
}
template <typename VoxelType>
glm::ivec3 RawVolume<VoxelType>::indexToCoords(size_t linear) const {
return volumeutils::indexToCoords(linear, dimensions());
}
template <typename VoxelType>
VoxelType* RawVolume<VoxelType>::data() {
return _data.data();
}
}

View File

@@ -0,0 +1,57 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __RAWVOLUMEREADER_H__
#define __RAWVOLUMEREADER_H__
#include <functional>
#include <apps/DataConverter/volume.h>
#include <modules/volume/rawvolume.h>
namespace openspace {
template <typename Voxel>
class RawVolumeReader {
public:
typedef Voxel VoxelType;
RawVolumeReader(const std::string& path, const glm::ivec3& dimensions);
glm::ivec3 dimensions() const;
std::string path() const;
void setPath(const std::string& path);
void setDimensions(const glm::ivec3& dimensions);
//VoxelType get(const glm::ivec3& coordinates) const; // TODO: Implement this
//VoxelType get(const size_t index) const; // TODO: Implement this
std::unique_ptr<RawVolume<VoxelType>> read();
private:
size_t coordsToIndex(const glm::ivec3& cartesian) const;
glm::ivec3 indexToCoords(size_t linear) const;
glm::ivec3 _dimensions;
std::string _path;
};
}
#include "rawvolumereader.inl"
#endif // __RAWVOLUMEREADER_H__

View File

@@ -0,0 +1,73 @@
#include <fstream>
namespace openspace {
template <typename VoxelType>
RawVolumeReader<VoxelType>::RawVolumeReader(const std::string& path,
const glm::ivec3& dimensions)
: _path(path)
, _dimensions(dimensions) {}
template <typename VoxelType>
glm::ivec3 RawVolumeReader<VoxelType>::dimensions() const {
return _dimensions;
}
template <typename VoxelType>
void RawVolumeReader<VoxelType>::setDimensions(const glm::ivec3& dimensions) {
_dimensions = dimensions;
}
template <typename VoxelType>
std::string RawVolumeReader<VoxelType>::path() const {
return _path;
}
template <typename VoxelType>
void RawVolumeReader<VoxelType>::setPath(const std::string& path) {
_path = path;
}
/*
TODO: Implement these methods for random access in raw volume file
template <typename VoxelType>
VoxelType RawVolumeReader<VoxelType>::get(const glm::ivec3& coordinates) const {
return get(coordsToIndex(coordinates, dimensions()));
}
template <typename VoxelType>
VoxelType RawVolumeReader<VoxelType>::get(size_t index) const {
// TODO: read from specific position.
return VoxelType();
}*/
template <typename VoxelType>
size_t RawVolumeReader<VoxelType>::coordsToIndex(const glm::ivec3& cartesian) const {
return volumeutils::coordsToIndex(cartesian, dimensions());
}
template <typename VoxelType>
glm::ivec3 RawVolumeReader<VoxelType>::indexToCoords(size_t linear) const {
return volumeutils::indexToCoords(linear, dimensions());
}
template <typename VoxelType>
std::unique_ptr<RawVolume<VoxelType>> RawVolumeReader<VoxelType>::read() {
glm::ivec3 dims = dimensions();
std::unique_ptr<RawVolume<VoxelType>> volume =
std::make_unique<RawVolume<VoxelType>>(dims);
std::ifstream file(_path, std::ios::binary);
char *buffer = reinterpret_cast<char*>(volume->data());
size_t length = static_cast<size_t>(dims.x) *
static_cast<size_t>(dims.y) *
static_cast<size_t>(dims.z) *
sizeof(VoxelType);
file.read(buffer, length);
return volume;
}
}

View File

@@ -0,0 +1,33 @@
#ifndef __RAWVOLUMEWRITER_H__
#define __RAWVOLUMEWRITER_H__
#include <functional>
#include <string>
#include <modules/volume/rawvolume.h>
namespace openspace {
template <typename VoxelType>
class RawVolumeWriter {
public:
RawVolumeWriter(std::string path, size_t bufferSize = 1024);
void setPath(const std::string& path);
glm::ivec3 dimensions() const;
void setDimensions(const glm::ivec3& dimensions);
void write(const std::function<VoxelType(const glm::ivec3&)>& fn,
const std::function<void(float t)>& onProgress = [&](float t) {});
void write(const RawVolume<VoxelType>& volume);
size_t coordsToIndex(const glm::ivec3& coords) const;
glm::ivec3 indexToCoords(size_t linear) const;
private:
glm::ivec3 _dimensions;
std::string _path;
size_t _bufferSize;
};
}
#include "rawvolumewriter.inl";
#endif

View File

@@ -0,0 +1,80 @@
#include <fstream>
#include <modules/volume/volumeutils.h>
namespace openspace {
template <typename VoxelType>
RawVolumeWriter<VoxelType>::RawVolumeWriter(std::string path, size_t bufferSize)
: _path(path)
, _bufferSize(bufferSize) {}
template <typename VoxelType>
size_t RawVolumeWriter<VoxelType>::coordsToIndex(const glm::ivec3& cartesian) const {
return volumeutils::coordsToIndex(cartesian, dimensions());
}
template <typename VoxelType>
glm::ivec3 RawVolumeWriter<VoxelType>::indexToCoords(size_t linear) const {
return volumeutils::indexToCoords(linear, dimensions());
}
template <typename VoxelType>
void RawVolumeWriter<VoxelType>::setDimensions(const glm::ivec3& dimensions) {
_dimensions = dimensions;
}
template <typename VoxelType>
glm::ivec3 RawVolumeWriter<VoxelType>::dimensions() const {
return _dimensions;
}
template <typename VoxelType>
void RawVolumeWriter<VoxelType>::write(const std::function<VoxelType(const glm::ivec3&)>& fn,
const std::function<void(float t)>& onProgress)
{
glm::ivec3 dims = dimensions();
size_t size = static_cast<size_t>(dims.x) *
static_cast<size_t>(dims.y) *
static_cast<size_t>(dims.z);
std::vector<VoxelType> buffer(_bufferSize);
std::ofstream file(_path, std::ios::binary);
int nChunks = size / _bufferSize;
if (size % _bufferSize > 0) {
nChunks++;
}
size_t i = 0;
for (int c = 0; c < nChunks; c++) {
size_t bufferPos = 0;
size_t bufferSize = std::min(_bufferSize, size - i);
for (bufferPos = 0; bufferPos < bufferSize; bufferPos++, i++) {
buffer[bufferPos] = fn(indexToCoords(i));
}
file.write(reinterpret_cast<char*>(buffer.data()), bufferSize * sizeof(VoxelType));
onProgress(static_cast<float>(c + 1) / nChunks);
}
file.close();
}
template <typename VoxelType>
void RawVolumeWriter<VoxelType>::write(const RawVolume<VoxelType>& volume) {
glm::ivec3 dims = dimensions();
ghoul_assert(dims == volume.dims());
const char* buffer = reinterpret_cast<char*>(volume.data());
size_t length = static_cast<size_t>(dims.x) *
static_cast<size_t>(dims.y) *
static_cast<size_t>(dims.z) *
sizeof(VoxelType);
std::ofstream file(_path, std::ios::binary);
file.write(buffer, length);
file.close();
}
}

View File

@@ -0,0 +1,35 @@
#ifndef __TEXTURESLICEVOLUMEREADER_H__
#define __TEXTURESLICEVOLUMEREADER_H__
#include <vector>
#include <ghoul/opengl/texture.h>
#include <memory>
#include <modules/volume/linearlrucache.h>
#include <map>
#include <unordered_map>
namespace openspace {
template <typename Voxel>
class TextureSliceVolumeReader {
public:
typedef Voxel VoxelType;
TextureSliceVolumeReader(std::vector<std::string> paths, size_t sliceCacheMaxItems, size_t sliceCacheSize);
VoxelType get(const glm::ivec3& coordinates) const;
virtual glm::ivec3 dimensions() const;
void setPaths(const std::vector<std::string> paths);
void setCacheSize(size_t size);
void initialize();
private:
ghoul::opengl::Texture& getSlice(int sliceIndex) const;
std::vector<std::string> _paths;
mutable LinearLruCache<std::shared_ptr<ghoul::opengl::Texture>> _cache;
glm::ivec2 _sliceDimensions;
bool _initialized;
};
}
#include "textureslicevolumereader.inl"
#endif // __TEXTURESLICEVOLUME_H__

View File

@@ -0,0 +1,63 @@
#include <ghoul/io/texture/texturereader.h>
namespace openspace {
template <typename VoxelType>
VoxelType TextureSliceVolumeReader<VoxelType>::get(const glm::ivec3& coordinates) const {
ghoul::opengl::Texture& slice = getSlice(coordinates.z);
return slice.texel<VoxelType>(coordinates.xy());
}
template <typename VoxelType>
glm::ivec3 TextureSliceVolumeReader<VoxelType>::dimensions() const {
return glm::ivec3(_sliceDimensions, _paths.size());
}
template <typename VoxelType>
TextureSliceVolumeReader<VoxelType>::TextureSliceVolumeReader(std::vector<std::string> paths,
size_t sliceCacheNIndices,
size_t sliceCacheCapacity)
: _initialized(false)
, _paths(paths)
, _cache(sliceCacheCapacity, sliceCacheNIndices) {}
template <typename VoxelType>
void TextureSliceVolumeReader<VoxelType>::initialize() {
ghoul_assert(_paths.size() > 0, "No paths to read slices from.");
std::shared_ptr<ghoul::opengl::Texture> firstSlice =
ghoul::io::TextureReader::ref().loadTexture(_paths[0]);
_sliceDimensions = firstSlice->dimensions().xy();
_initialized = true;
_cache.set(0, firstSlice);
}
template <typename VoxelType>
void TextureSliceVolumeReader<VoxelType>::setPaths(const std::vector<std::string> paths) {
_paths = paths;
}
template <typename VoxelType>
void TextureSliceVolumeReader<VoxelType>::setCacheSize(size_t sliceCacheSize) {
_cache.resize(sliceCacheSize);
}
template <typename VoxelType>
ghoul::opengl::Texture& TextureSliceVolumeReader<VoxelType>::getSlice(int sliceIndex) const {
ghoul_assert(_initialized, "Volume is not initialized");
ghoul_assert(sliceIndex >= 0 && sliceIndex < _paths.size(),
"Slice index " + std::to_string(sliceIndex) + "is outside the range.");
if (!_cache.has(sliceIndex)) {
std::shared_ptr<ghoul::opengl::Texture> texture =
ghoul::io::TextureReader::ref().loadTexture(_paths[sliceIndex]);
glm::ivec2 dims = texture->dimensions().xy();
ghoul_assert(dims == _sliceDimensions, "Slice dimensions do not agree.");
_cache.set(sliceIndex, std::move(texture));
}
return *_cache.get(sliceIndex).get();
}
}

View File

@@ -40,8 +40,6 @@ VolumeModule::VolumeModule()
void VolumeModule::internalInitialize() {
auto fRenderable = FactoryManager::ref().factory<Renderable>();
ghoul_assert(fRenderable, "No renderable factory existed");
//fRenderable->registerClass<RenderableVolumeGL>("RenderableVolumeGL");
}
} // namespace openspace

View File

@@ -0,0 +1,20 @@
#ifndef __VOLUMESAMPLER_H__
#define __VOLUMESAMPLER_H__
namespace openspace {
template <typename VolumeType>
class VolumeSampler {
public:
VolumeSampler(const VolumeType& volume, const glm::vec3& filterSize);
typename VolumeType::VoxelType sample(const glm::vec3& position) const;
private:
glm::ivec3 _filterSize;
const VolumeType* _volume;
};
}
#include "volumesampler.inl"
#endif

View File

@@ -0,0 +1,57 @@
namespace openspace {
template <typename VolumeType>
VolumeSampler<VolumeType>::VolumeSampler(const VolumeType& volume, const glm::vec3& filterSize) {
// Only accept filter sizes of size 1, 3, 5, 7...
// Round down to closest odd number.
_filterSize = static_cast<glm::ivec3>((filterSize - glm::vec3(1.0)) * glm::vec3(0.5)) *
glm::ivec3(2) + glm::ivec3(1);
_volume = &volume;
}
template <typename VolumeType>
typename VolumeType::VoxelType VolumeSampler<VolumeType>::sample(const glm::vec3& position) const {
glm::ivec3 flooredPos = static_cast<glm::ivec3>(glm::floor(position));
glm::vec3 t = glm::fract(position);
// t is now in interval [0, 1[ (never 1)
glm::ivec3 minCoords = flooredPos - _filterSize / 2; // min coord to sample from
glm::ivec3 maxCoords = minCoords + _filterSize; // max coords to sample from, including interpolation.
glm::ivec3 clampCeiling = _volume->dimensions() - glm::ivec3(1);
VolumeType::VoxelType value;
for (int z = minCoords.z; z <= maxCoords.z; z++) {
for (int y = minCoords.y; y <= maxCoords.y; y++) {
for (int x = minCoords.x; x <= maxCoords.x; x++) {
glm::ivec3 sampleCoords = glm::ivec3(x, y, z);
float filterCoefficient = 1.0;
if (x == minCoords.x) {
filterCoefficient *= (1.0 - t.x);
} else if (x == maxCoords.x) {
filterCoefficient *= t.x;
}
if (y == minCoords.y) {
filterCoefficient *= (1.0 - t.y);
} else if (y == maxCoords.y) {
filterCoefficient *= t.y;
}
if (z == minCoords.z) {
filterCoefficient *= (1.0 - t.z);
} else if (z == maxCoords.z) {
filterCoefficient *= t.z;
}
glm::ivec3 clampedCoords = glm::clamp(sampleCoords, glm::ivec3(0), clampCeiling);
value += filterCoefficient * _volume->get(clampedCoords);
}
}
}
value /= static_cast<float>(_filterSize.x * _filterSize.y * _filterSize.z);
return value;
}
}

View File

@@ -0,0 +1,31 @@
#include "volumeutils.h"
namespace openspace {
namespace volumeutils {
size_t coordsToIndex(const glm::vec3& coords, const glm::ivec3& dims) {
size_t w = dims.x;
size_t h = dims.y;
size_t d = dims.z;
size_t x = coords.x;
size_t y = coords.y;
size_t z = coords.z;
return coords.z * (h * w) + coords.y * w + coords.x;
}
glm::vec3 indexToCoords(size_t index, const glm::ivec3& dims) {
size_t w = dims.x;
size_t h = dims.y;
size_t d = dims.z;
size_t x = index % w;
size_t y = (index / w) % h;
size_t z = index / w / h;
return glm::ivec3(x, y, z);
}
}
}

View File

@@ -0,0 +1,39 @@
/*****************************************************************************************
* *
* OpenSpace *
* *
* Copyright (c) 2014 - 2016 *
* *
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
* software and associated documentation files (the "Software"), to deal in the Software *
* without restriction, including without limitation the rights to use, copy, modify, *
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
* permit persons to whom the Software is furnished to do so, subject to the following *
* conditions: *
* *
* The above copyright notice and this permission notice shall be included in all copies *
* or substantial portions of the Software. *
* *
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
****************************************************************************************/
#ifndef __VOLUMEUTILS_H__
#define __VOLUMEUTILS_H__
#include <glm/glm.hpp>
namespace openspace {
namespace volumeutils {
size_t coordsToIndex(const glm::vec3& coords, const glm::ivec3& dimensions);
glm::vec3 indexToCoords(size_t index, const glm::ivec3& dimensions);
}
}
#endif // __VOLUMEUTILS__