diff --git a/.gitignore b/.gitignore index dc6c035a1a..eb0db62a4f 100644 --- a/.gitignore +++ b/.gitignore @@ -4,6 +4,10 @@ ext/SGCT .DS_Store *.swp +# generated glsl files +*.gglsl +*.OpenSpaceGenerated.glsl + # CMake stuff CMakeCache.txt CMakeFiles diff --git a/config/sgct/ccmc_lab_all.xml b/config/sgct/ccmc_lab_all.xml new file mode 100644 index 0000000000..9c2fcd4958 --- /dev/null +++ b/config/sgct/ccmc_lab_all.xml @@ -0,0 +1,65 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/sgct/ccmc_lab_work.xml b/config/sgct/ccmc_lab_work.xml new file mode 100644 index 0000000000..0c9f4069b6 --- /dev/null +++ b/config/sgct/ccmc_lab_work.xml @@ -0,0 +1,47 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/config/sgct/single.xml b/config/sgct/single.xml index 63abb4989c..eec3b163c1 100644 --- a/config/sgct/single.xml +++ b/config/sgct/single.xml @@ -1,13 +1,19 @@ - + - + + + + - - + + + + + diff --git a/include/openspace/abuffer/abuffer.h b/include/openspace/abuffer/abuffer.h new file mode 100644 index 0000000000..f7c2f9e032 --- /dev/null +++ b/include/openspace/abuffer/abuffer.h @@ -0,0 +1,93 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 __ABUFFER_H__ +#define __ABUFFER_H__ + +#include + +#include +#include + +#include +#include + +namespace ghoul { + namespace opengl { + class Texture; + } +} + +namespace openspace { + +class ABuffer: public ABuffer_I { +public: + + ABuffer(); + virtual ~ABuffer(); + virtual void resolve(); + + void addVolume(const std::string& tag,ghoul::opengl::Texture* volume); + void addTransferFunction(const std::string& tag,ghoul::opengl::Texture* transferFunction); + int addSamplerfile(const std::string& filename); + +protected: + virtual std::string settings() = 0; + + bool initializeABuffer(); + + void generateShaderSource(); + bool updateShader(); + + std::string openspaceHeaders(); + std::string openspaceSamplerCalls(); + std::string openspaceSamplers(); + std::string openspaceTransferFunction(); + + unsigned int _width, _height, _totalPixels; + +private: + GLuint _screenQuad; + + bool _validShader; + std::string _fragmentShaderPath; + ghoul::filesystem::File* _fragmentShaderFile; + ghoul::opengl::ProgramObject* _resolveShader; + + std::vector > _volumes; + std::vector > _transferFunctions; + std::vector _samplerFiles; + std::vector _samplers; + + // Development functionality to update shader for changes in several files + std::vector _shaderFiles; + + float _volumeStepFactor; + + + +}; // ABuffer +} // openspace + +#endif // __ABUFFER_H__ \ No newline at end of file diff --git a/include/openspace/abuffer/abufferSingleLinked.h b/include/openspace/abuffer/abufferSingleLinked.h new file mode 100644 index 0000000000..c348abee52 --- /dev/null +++ b/include/openspace/abuffer/abufferSingleLinked.h @@ -0,0 +1,60 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 __ABUFFERSINGLELINKED_H__ +#define __ABUFFERSINGLELINKED_H__ + +#include + +namespace openspace { + +class ABufferSingleLinked: public ABuffer { +public: + + ABufferSingleLinked(); + virtual ~ABufferSingleLinked(); + virtual bool initialize(); + + virtual void clear(); + virtual void preRender(); + virtual void postRender(); + + virtual std::string settings(); + +private: + + GLuint *_data; + GLuint _anchorPointerTexture; + GLuint _anchorPointerTextureInitializer; + GLuint _atomicCounterBuffer; + GLuint _fragmentBuffer; + GLuint _fragmentTexture; + + + + +}; // ABufferSingleLinked +} // openspace + +#endif // __ABUFFERSINGLELINKED_H__ \ No newline at end of file diff --git a/include/openspace/abuffer/abuffer_i.h b/include/openspace/abuffer/abuffer_i.h new file mode 100644 index 0000000000..04a8e4277c --- /dev/null +++ b/include/openspace/abuffer/abuffer_i.h @@ -0,0 +1,43 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 __ABUFFER_I_H__ +#define __ABUFFER_I_H__ + +namespace openspace { + +class ABuffer_I { +public: + virtual ~ABuffer_I() {}; + virtual bool initialize() = 0; + + virtual void clear() = 0; + virtual void preRender() = 0; + virtual void postRender() = 0; + virtual void resolve() = 0; + +}; // ABuffer_I +} // openspace + +#endif // __ABUFFER_I_H__ \ No newline at end of file diff --git a/include/openspace/abuffer/abufferdynamic.h b/include/openspace/abuffer/abufferdynamic.h new file mode 100644 index 0000000000..23959f08f1 --- /dev/null +++ b/include/openspace/abuffer/abufferdynamic.h @@ -0,0 +1,60 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 __ABUFFERDYNAMIC_H__ +#define __ABUFFERDYNAMIC_H__ + +#include + +namespace openspace { + +class ABufferDynamic: public ABuffer { +public: + + ABufferDynamic(); + virtual ~ABufferDynamic(); + virtual bool initialize(); + + virtual void clear(); + virtual void preRender(); + virtual void postRender(); + + virtual std::string settings(); + +private: + + GLuint *_data; + GLuint _anchorPointerTexture; + GLuint _anchorPointerTextureInitializer; + GLuint _atomicCounterBuffer; + GLuint _fragmentBuffer; + GLuint _fragmentTexture; + + + + +}; // ABufferDynamic +} // openspace + +#endif // __ABUFFERDYNAMIC_H__ \ No newline at end of file diff --git a/include/openspace/abuffer/abufferfixed.h b/include/openspace/abuffer/abufferfixed.h new file mode 100644 index 0000000000..cc211e0b57 --- /dev/null +++ b/include/openspace/abuffer/abufferfixed.h @@ -0,0 +1,61 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 __ABUFFERFIXED_H__ +#define __ABUFFERFIXED_H__ + +#include + +namespace openspace { + +class ABufferFixed: public ABuffer { +public: + + ABufferFixed(); + virtual ~ABufferFixed(); + virtual bool initialize(); + + virtual void clear(); + virtual void preRender(); + virtual void postRender(); + + virtual std::string settings(); + +private: + + GLuint *_data; + GLuint _anchorPointerTexture; + GLuint _anchorPointerTextureInitializer; + GLuint _atomicCounterBuffer; + GLuint _atomicCounterTexture; + GLuint _fragmentBuffer; + GLuint _fragmentTexture; + + + + +}; // ABufferFixed +} // openspace + +#endif // __ABUFFERFIXED_H__ \ No newline at end of file diff --git a/include/openspace/engine/openspaceengine.h b/include/openspace/engine/openspaceengine.h index ef98decc83..dae55381ab 100644 --- a/include/openspace/engine/openspaceengine.h +++ b/include/openspace/engine/openspaceengine.h @@ -27,7 +27,6 @@ #include #include -#include #include #include @@ -35,22 +34,25 @@ #include #include -//#define FLARE_ONLY +// #define FLARE_ONLY #include +#include -namespace ghoul { - namespace cmdparser { - class CommandlineCommand; - class CommandlineParser; - } -} +#define ABUFFER_SINGLE_LINKED 1 +#define ABUFFER_FIXED 2 +#define ABUFFER_DYNAMIC 3 +#define ABUFFER_IMPLEMENTATION ABUFFER_SINGLE_LINKED + +// #define OPENSPACE_VIDEO_EXPORT namespace openspace { +class ScriptEngine; + class OpenSpaceEngine { public: - static bool create(int argc, char** argv, std::vector& sgctArguments); + static void create(int argc, char** argv, std::vector& sgctArguments); static void destroy(); static OpenSpaceEngine& ref(); @@ -65,7 +67,7 @@ public: ghoul::opencl::CLContext& clContext(); InteractionHandler& interactionHandler(); RenderEngine& renderEngine(); - scripting::ScriptEngine& scriptEngine(); + ShaderCreator& shaderBuilder(); // SGCT callbacks bool initializeGL(); @@ -82,24 +84,25 @@ public: void decode(); private: - OpenSpaceEngine(std::string programName); + OpenSpaceEngine(); ~OpenSpaceEngine(); - - bool gatherCommandlineArguments(); - + static OpenSpaceEngine* _engine; ghoul::Dictionary* _configurationManager; InteractionHandler* _interactionHandler; RenderEngine* _renderEngine; - scripting::ScriptEngine* _scriptEngine; - ghoul::cmdparser::CommandlineParser* _commandlineParser; +#ifdef OPENSPACE_VIDEO_EXPORT + bool _doVideoExport; +#endif #ifdef FLARE_ONLY Flare* _flare; #endif + // ScriptEngine* _scriptEngine; ghoul::opencl::CLContext _context; sgct::SharedVector _synchronizationBuffer; + ShaderCreator _shaderBuilder; }; #define OsEng (openspace::OpenSpaceEngine::ref()) diff --git a/include/openspace/interaction/interactionhandler.h b/include/openspace/interaction/interactionhandler.h index b8505beda2..80b867dd91 100644 --- a/include/openspace/interaction/interactionhandler.h +++ b/include/openspace/interaction/interactionhandler.h @@ -11,6 +11,8 @@ #include #include #include +#include +#include namespace openspace { @@ -56,6 +58,8 @@ public: void mouseButtonCallback(int key, int action); void mousePositionCallback(int x, int y); void mouseScrollWheelCallback(int pos); + + void addKeyCallback(int key, std::function f); private: glm::vec3 mapToTrackball(glm::vec2 mousePos); @@ -77,6 +81,8 @@ private: // for locking and unlocking std::mutex cameraGuard_; + + std::multimap > _keyCallbacks; }; diff --git a/include/openspace/rendering/renderable.h b/include/openspace/rendering/renderable.h index 2ff4bda48a..a1959f72aa 100644 --- a/include/openspace/rendering/renderable.h +++ b/include/openspace/rendering/renderable.h @@ -52,9 +52,10 @@ public: virtual void update(); protected: - // Renderable(); + std::string findPath(const std::string& path); private: PowerScaledScalar boundingSphere_; + std::string _relativePath; }; } // namespace openspace diff --git a/include/openspace/rendering/renderablefieldlines.h b/include/openspace/rendering/renderablefieldlines.h new file mode 100644 index 0000000000..e250a7e4d5 --- /dev/null +++ b/include/openspace/rendering/renderablefieldlines.h @@ -0,0 +1,71 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 RENDERABLEFIELDLINES_H_ +#define RENDERABLEFIELDLINES_H_ + +// open space includes +#include + +// ghoul includes +#include +#include + +namespace openspace { + struct LinePoint; + +class RenderableFieldlines : public Renderable { +public: + RenderableFieldlines(const ghoul::Dictionary& dictionary); + ~RenderableFieldlines(); + + bool initialize(); + bool deinitialize(); + + virtual void render(const Camera *camera, const psc& thisPosition); + virtual void update(); + +private: + std::vector > getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary); + + std::vector _hintsDictionaries; + std::vector _filenames; + std::vector _seedPoints; + + ghoul::opengl::ProgramObject *_fieldlinesProgram; + GLuint _VAO, _seedpointVAO; + + ghoul::filesystem::File* _vertexSourceFile; + ghoul::filesystem::File* _fragmentSourceFile; + + std::vector _lineStart; + std::vector _lineCount; + + bool _programUpdateOnSave; + bool _update; + void safeShaderCompilation(); +}; + +} // namespace openspace +#endif // RENDERABLEFIELDLINES_H_ diff --git a/include/openspace/rendering/renderablevolume.h b/include/openspace/rendering/renderablevolume.h index 00bc8c680b..9c9c1c4b9c 100644 --- a/include/openspace/rendering/renderablevolume.h +++ b/include/openspace/rendering/renderablevolume.h @@ -29,7 +29,6 @@ #include // ghoul includes -#include #include #include @@ -37,23 +36,19 @@ namespace openspace { class RenderableVolume: public Renderable { public: - // constructors & destructor RenderableVolume(const ghoul::Dictionary& dictionary); ~RenderableVolume(); protected: - std::string findPath(const std::string& path); ghoul::opengl::Texture* loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary); + glm::vec3 getVolumeOffset(const std::string& filepath, const ghoul::Dictionary& hintsDictionary); ghoul::RawVolumeReader::ReadHints readHints(const ghoul::Dictionary& dictionary); ghoul::opengl::Texture* loadTransferFunction(const std::string& filepath); private: - - // relative path - std::string _relativePath; }; } // namespace openspace -#endif \ No newline at end of file +#endif diff --git a/include/openspace/rendering/renderablevolumegl.h b/include/openspace/rendering/renderablevolumegl.h index 6cca3f458f..dce4c1942b 100644 --- a/include/openspace/rendering/renderablevolumegl.h +++ b/include/openspace/rendering/renderablevolumegl.h @@ -35,24 +35,10 @@ #include #include -#define SGCT_WINDOWS_INCLUDE -#include - -#ifdef __APPLE__ - #include -#else - #include -#endif - -namespace sgct_utils { - class SGCTBox; -} - namespace openspace { class RenderableVolumeGL: public RenderableVolume { public: - // constructors & destructor RenderableVolumeGL(const ghoul::Dictionary& dictionary); ~RenderableVolumeGL(); @@ -64,29 +50,31 @@ public: virtual void update(); private: - - + ghoul::Dictionary _hintsDictionary; + std::string _filename; - ghoul::RawVolumeReader::ReadHints _hints; - float _stepSize; - ghoul::opengl::FramebufferObject* _fbo; - ghoul::opengl::Texture* _backTexture; - ghoul::opengl::Texture* _frontTexture; + + std::string _transferFunctionName; + std::string _volumeName; + + std::string _transferFunctionPath; + std::string _samplerFilename; + + ghoul::filesystem::File* _transferFunctionFile; + ghoul::opengl::Texture* _volume; - ghoul::opengl::ProgramObject *_fboProgram, *_twopassProgram; - sgct_utils::SGCTBox* _boundingBox; - GLuint _screenQuad; - - std::mutex* _shaderMutex; - - ghoul::filesystem::File* _vertexSourceFile; - ghoul::filesystem::File* _fragmentSourceFile; - bool _programUpdateOnSave; - - void safeShaderCompilation(); + ghoul::opengl::Texture* _transferFunction; + + GLuint _boxArray; + ghoul::opengl::ProgramObject *_boxProgram; + glm::vec3 _boxScaling, _boxOffset; + float _w; + GLint _MVPLocation, _modelTransformLocation, _typeLocation; + bool _updateTransferfunction; + int _id; }; } // namespace openspace -#endif \ No newline at end of file +#endif diff --git a/include/openspace/rendering/renderengine.h b/include/openspace/rendering/renderengine.h index da2c74d712..2c64e84e5b 100644 --- a/include/openspace/rendering/renderengine.h +++ b/include/openspace/rendering/renderengine.h @@ -30,6 +30,8 @@ #include #include +#include + namespace openspace { class Camera; @@ -45,6 +47,7 @@ public: SceneGraph* sceneGraph(); Camera* camera() const; + ABuffer* abuffer() const; // sgct wrapped functions bool initializeGL(); @@ -58,6 +61,8 @@ public: private: Camera* _mainCamera; SceneGraph* _sceneGraph; + + ABuffer* _abuffer; }; } // namespace openspace diff --git a/include/openspace/rendering/volumeraycasterbox.h b/include/openspace/rendering/volumeraycasterbox.h index 5792b0e0c3..4e0a3018d5 100644 --- a/include/openspace/rendering/volumeraycasterbox.h +++ b/include/openspace/rendering/volumeraycasterbox.h @@ -45,7 +45,7 @@ public: VolumeRaycasterBox(); ~VolumeRaycasterBox(); bool initialize(); - void render(const glm::mat4& MVP); + void render(const glm::mat4& MVP, const glm::mat4& transform = glm::mat4(1.0), int type = 0); ghoul::opengl::Texture* backFace(); ghoul::opengl::Texture* frontFace(); @@ -56,7 +56,7 @@ private: ghoul::opengl::Texture *_backTexture, *_frontTexture; ghoul::opengl::ProgramObject *_boxProgram; sgct_utils::SGCTBox* _boundingBox; - GLint _MVPLocation; + GLint _MVPLocation, _modelTransformLocation, _typeLocation; glm::size2_t _dimensions; }; diff --git a/include/openspace/scenegraph/scenegraphnode.h b/include/openspace/scenegraph/scenegraphnode.h index b809f84ce4..0123e45dad 100644 --- a/include/openspace/scenegraph/scenegraphnode.h +++ b/include/openspace/scenegraph/scenegraphnode.h @@ -71,6 +71,7 @@ public: // bounding sphere PowerScaledScalar calculateBoundingSphere(); + PowerScaledScalar boundingSphere() const; SceneGraphNode* childNode(const std::string& name); @@ -90,6 +91,7 @@ private: // renderable Renderable* _renderable; bool _renderableVisible; + bool _renderableToggle; // bounding sphere bool _boundingSphereVisible; diff --git a/include/openspace/util/kameleonwrapper.h b/include/openspace/util/kameleonwrapper.h index 3ba0afbbb0..1bd768e72a 100644 --- a/include/openspace/util/kameleonwrapper.h +++ b/include/openspace/util/kameleonwrapper.h @@ -25,7 +25,6 @@ #ifndef KAMELEONWRAPPER_H_ #define KAMELEONWRAPPER_H_ -#include #include namespace ccmc { @@ -35,6 +34,16 @@ namespace ccmc { namespace openspace { +struct LinePoint { + glm::vec3 position; + glm::vec4 color; + + LinePoint(glm::vec3 pos, glm::vec4 col) { + position = pos; + color = col; + } +}; + class KameleonWrapper { public: @@ -43,14 +52,58 @@ public: BATSRUS // Magnetosphere }; + enum class TraceDirection { + FORWARD = 1, + BACK = -1 + }; + + enum class FieldlineEnd { + NORTH, + SOUTH, + OUT + }; + KameleonWrapper(const std::string& filename, Model model); ~KameleonWrapper(); float* getUniformSampledValues(const std::string& var, glm::size3_t outDimensions); + float* getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, + const std::string& zVar, glm::size3_t outDimensions); + + std::vector > getClassifiedFieldLines(const std::string& xVar, + const std::string& yVar, const std::string& zVar, + std::vector seedPoints, float stepSize); + + std::vector > getFieldLines(const std::string& xVar, + const std::string& yVar, const std::string& zVar, + std::vector seedPoints, float stepSize, glm::vec4 color); + + std::vector > getLorentzTrajectories(std::vector seedPoints, + glm::vec4 color, float stepsize); + + glm::vec3 getModelBarycenterOffset(); private: + std::vector traceCartesianFieldline(const std::string& xVar, + const std::string& yVar, const std::string& zVar, glm::vec3 seedPoint, + float stepSize, TraceDirection direction, FieldlineEnd& end); + + std::vector traceLorentzTrajectory(glm::vec3 seedPoint, + float stepsize, float eCharge); + + void getGridVariables(std::string& x, std::string& y, std::string& z); + void progressBar(int current, int end); + glm::vec4 classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd); + ccmc::Model* _model; Model _type; ccmc::Interpolator* _interpolator; + + // Model parameters + float _xMin, _xMax, _yMin, _yMax, _zMin, _zMax; + std::string _xCoordVar, _yCoordVar, _zCoordVar; + + // For progressbar + int _lastiProgress; }; } // namespace openspace diff --git a/include/openspace/util/shadercreator.h b/include/openspace/util/shadercreator.h new file mode 100644 index 0000000000..9274d60715 --- /dev/null +++ b/include/openspace/util/shadercreator.h @@ -0,0 +1,60 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 __SHADERCREATOR_H__ +#define __SHADERCREATOR_H__ + + +#include + +#include + +namespace openspace { +class ShaderCreator { + +public: + ShaderCreator(); + ~ShaderCreator(); + + void createSourceFile(bool b); + void sourceFileExtension(const std::string& extension); + void sourceFileHeader(const std::string& header); + + ghoul::opengl::ProgramObject* buildShader(const std::string& name, const std::string& vpath, const std::string& fpath); + +private: + + void _generateSource(const std::string& filename); + std::string _loadSource(const std::string& filename, unsigned int depth = 0); + std::string _generateFilename(const std::string& filename); + + bool _createSourceFile; + std::string _sourceFileExtension; + std::string _sourceFileHeader; + unsigned int _maxDepth; + +}; +} + +#endif \ No newline at end of file diff --git a/openspace.cfg b/openspace.cfg index 9b45f4704d..65ebf301ab 100644 --- a/openspace.cfg +++ b/openspace.cfg @@ -6,7 +6,8 @@ return { SHADERS = "${BASE_PATH}/shaders", OPENSPACE_DATA = "${BASE_PATH}/openspace-data", TESTDIR = "${BASE_PATH}/src/tests", - SCENEPATH = "${OPENSPACE_DATA}/scene", + -- SCENEPATH = "${OPENSPACE_DATA}/scene", + SCENEPATH = "${OPENSPACE_DATA}/ABufferVolumes", CONFIG = "${BASE_PATH}/config" }, SGCTConfig = "${SGCT}/single.xml", diff --git a/shaders/ABuffer/abufferAddToBuffer.hglsl b/shaders/ABuffer/abufferAddToBuffer.hglsl new file mode 100644 index 0000000000..92248796c0 --- /dev/null +++ b/shaders/ABuffer/abufferAddToBuffer.hglsl @@ -0,0 +1,102 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED +layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; +layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; +layout (binding = 0, offset = 0) uniform atomic_uint atomicCounterBuffer; +#endif + +#if ABUFFER_IMPLEMENTATION == ABUFFER_FIXED +layout (binding = 0, r32ui) uniform uimage2D anchorPointerTexture; +layout (binding = 1, rgba32ui) uniform uimageBuffer fragmentTexture; + + #define _MAX_LAYERS_ 16 + #define _SCREEN_WIDTH_ 1280 + #define _SCREEN_HEIGHT_ 720 +#endif + +ABufferStruct_t createGeometryFragment(vec4 fragColor, vec4 position, float z = gl_FragCoord.z) { + ABufferStruct_t frag; + _col_(frag, fragColor); + _z_(frag, z); + _type_(frag, 0); + _pos_(frag, position); + return frag; +} + +void addToBuffer(ABufferStruct_t frag) { + +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED + uint index = atomicCounterIncrement(atomicCounterBuffer); + index *= 2; + uint old_head = imageAtomicExchange(anchorPointerTexture, ivec2(gl_FragCoord.xy), index); + _next_(frag,old_head); + + uvec4 p1 = uvec4(frag.z, frag.id, frag.rg, frag.ba); + uvec4 p2 = uvec4(floatBitsToUint(frag.position.x),floatBitsToUint(frag.position.y),floatBitsToUint(frag.position.z),floatBitsToUint(frag.position.w)); + + imageStore(fragmentTexture, int(index), p1); + imageStore(fragmentTexture, int(index+1), p2); +#endif + +#if ABUFFER_IMPLEMENTATION == ABUFFER_FIXED + uint index = imageAtomicAdd(anchorPointerTexture, ivec2(gl_FragCoord.xy), 1); + if(index < _MAX_LAYERS_) { + int offset = (int(gl_FragCoord.y) * _SCREEN_WIDTH_ + int(gl_FragCoord.x))*_MAX_LAYERS_ + int(index)*2; + + uvec4 p1 = uvec4(frag.z, frag.id, frag.rg, frag.ba); + uvec4 p2 = uvec4(floatBitsToUint(frag.position.x),floatBitsToUint(frag.position.y),floatBitsToUint(frag.position.z),floatBitsToUint(frag.position.w)); + + imageStore(fragmentTexture, int(offset ), p1); + imageStore(fragmentTexture, int(offset+1), p2); + } else { + imageAtomicAdd(anchorPointerTexture, ivec2(gl_FragCoord.xy), -1); + } + +#endif + +} + +ABufferStruct_t loadFromBuffer(uint id) { + +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED + uvec4 u1 = imageLoad(fragmentTexture, int(id)); + uvec4 u2 = imageLoad(fragmentTexture, int(id+1)); +#endif + +#if ABUFFER_IMPLEMENTATION == ABUFFER_FIXED + int offset = (int(gl_FragCoord.y) * _SCREEN_WIDTH_ + int(gl_FragCoord.x))*_MAX_LAYERS_ + int(id)*2; + uvec4 u1 = imageLoad(fragmentTexture, int(offset)); + uvec4 u2 = imageLoad(fragmentTexture, int(offset+1)); +#endif + + vec4 position = vec4( uintBitsToFloat(u2.x), + uintBitsToFloat(u2.y), + uintBitsToFloat(u2.z), + uintBitsToFloat(u2.w)); + + return ABufferStruct_t(u1.x, u1.y, u1.z, u1.w, position); + +} \ No newline at end of file diff --git a/shaders/ABuffer/abufferResolveFragment.glsl b/shaders/ABuffer/abufferResolveFragment.glsl new file mode 100644 index 0000000000..6c3245cdff --- /dev/null +++ b/shaders/ABuffer/abufferResolveFragment.glsl @@ -0,0 +1,291 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + +#version 430 + +// ================================================================================ +// Settings +// ================================================================================ +#pragma openspace insert SETTINGS + +// Select type of depth calculations +#define PSCDEPTH 1 +#define ZDEPTH 2 +#define ZTYPE ZDEPTH + +// Maximum number of fragments +#define MAX_FRAGMENTS 16 // The size of the local fragment list +// #define VISUALIZE_TRANSFERFUNCTIONS // +#define USE_JITTERING // +// #define USE_COLORNORMALIZATION // + +// If you need to render a volume box but not sample the volume (debug purpose) +// #define SKIP_VOLUME_0 +// #define SKIP_VOLUME_1 +// #define SKIP_VOLUME_2 +// #define SKIP_VOLUME_3 + +// constants +const float stepSize = 0.01; +const float samplingRate = 1.0; +uniform float ALPHA_LIMIT = 0.99; + + +// Math defintions +#define M_E 2.7182818284590452354 +#define M_LOG2E 1.4426950408889634074 /* log_2 e */ +#define M_LOG10E 0.43429448190325182765 /* log_10 e */ +#define M_LN2 0.69314718055994530942 /* log_e 2 */ +#define M_LN10 2.30258509299404568402 /* log_e 10 */ +#define M_PI 3.14159265358979323846 /* pi */ +#define M_PI_2 1.57079632679489661923 /* pi/2 */ +#define M_PI_4 0.78539816339744830962 /* pi/4 */ +#define M_1_PI 0.31830988618379067154 /* 1/pi */ +#define M_2_PI 0.63661977236758134308 /* 2/pi */ +#define M_2_SQRTPI 1.12837916709551257390 /* 2/sqrt(pi) */ +#define M_SQRT2 1.41421356237309504880 /* sqrt(2) */ +#define M_SQRT1_2 0.70710678118654752440 /* 1/sqrt(2) */ +#define M_SQRT1_3 0.57735026919 /* 1/sqrt(3) */ + +in vec2 texCoord; +out vec4 out_color; + +// ================================================================================ +// Headers, +// volume and transferfunctions uniforms +// ================================================================================ +#pragma openspace insert HEADERS + +// ================================================================================ +// The ABuffer specific includes and definitions +// ================================================================================ +#include "abufferStruct.hglsl" +ABufferStruct_t fragments[MAX_FRAGMENTS]; + +#if MAX_VOLUMES > 0 + vec3 volume_direction[MAX_VOLUMES]; + float volume_length[MAX_VOLUMES]; + vec3 volume_position[MAX_VOLUMES]; + int volumes_in_fragment[MAX_VOLUMES]; + int volume_count = 0; + + #if ZTYPE == ZDEPTH + vec2 volume_zlength[MAX_VOLUMES]; + #elif ZTYPE == PSCDEPTH + float volume_zlength[MAX_VOLUMES]; + #endif +#endif +#include "abufferSort.hglsl" + +// ================================================================================ +// Helper functions functions +// ================================================================================ +vec3 CartesianToSpherical(vec3 _cartesian) { + // Put cartesian in [-1..1] range first + vec3 cartesian = vec3(-1.0,-1.0,-1.0) + _cartesian * 2.0f; + + float r = length(cartesian); + float theta, phi; + + if (r == 0.0) { + theta = phi = 0.0; + } else { + theta = acos(cartesian.z/r) / M_PI; + phi = (M_PI + atan(cartesian.y, cartesian.x)) / (2.0*M_PI ); + } + r *= M_SQRT1_3; + // r = r / sqrt(3.0f); + + // Sampler ignores w component + return vec3(r, theta, phi); +} + +vec4 blend(vec4 src, vec4 dst) { + vec4 o; + o.a = src.a + dst.a * (1.0f - src.a); + o.rgb = (src.rgb*src.a + dst.rgb*dst.a* (1.0f - src.a)); + return o; + //return mix(src, dst, dst.a*(1.0f - src.a)); +} + +void blendStep(inout vec4 dst, in vec4 src, in float stepSize) { + src.a = 1.0 - pow(1.0 - src.a, stepSize ); + // src.a = 1.0 -(1.0 - src.a*stepSize); + dst.rgb = dst.rgb + (1.0 - dst.a) * src.a * src.rgb; + dst.a = dst.a + (1.0 -dst.a) * src.a; +} + +float volumeRaycastingDistance(in int id, in ABufferStruct_t startFrag, in ABufferStruct_t endFrag) { +#if ZTYPE == ZDEPTH + const float S1 = volume_zlength[id].x; + const float S2 = volume_zlength[id].y; + const float L = S1 - S2; + // const float z1 = globz(_z_(startFrag)); + // const float z2 = globz(_z_(endFrag)); + const float z1 = _z_(startFrag); + const float z2 = _z_(endFrag); + return ((z1 - S1) / L - (z2 - S1) / L) * volume_length[id]; +#elif ZTYPE == PSCDEPTH + const float L = volume_zlength[id]; + const vec4 p1 = _pos_(startFrag); + const vec4 p2 = _pos_(endFrag); + const float dist = pscLength(p1, p2); + // const float z1 = _z_(startFrag); + // const float z2 = _z_(endFrag); + return (dist / L) * volume_length[id]; +#endif +} + +vec4 calculate_final_color(uint frag_count) { + // volumeStepSize[volID] = 0.01; + int currentVolumeBitmask = 0; + vec4 final_color = vec4(0); + + if(frag_count == 1 && _type_(fragments[0]) == 0) { + final_color = blend(final_color, _col_(fragments[0])); + return final_color; + } + + int frag_count_1 = int(frag_count)-1; + for(int i = 0; i < frag_count_1 && final_color.a < ALPHA_LIMIT; i++) { + + ABufferStruct_t startFrag = fragments[i]; + ABufferStruct_t endFrag = fragments[i+1]; + int type = int(_type_(startFrag)); + + if(type == 0) { + //blendStep(final_color, _col_(startFrag), stepSize); + final_color = blend(final_color, _col_(startFrag)); + } else { + currentVolumeBitmask = currentVolumeBitmask ^ (1 << (type-1)); + } + + +#if MAX_VOLUMES > 0 + if(currentVolumeBitmask > 0) { + + + int volID; + float myMaxSteps = 0.0000001; + if(volume_count > 1) { + for(int v = 0; v < volume_count; ++v) { + int vol = volumes_in_fragment[v]; + float l = volumeRaycastingDistance(vol, startFrag, endFrag); + myMaxSteps = max(myMaxSteps, l/volumeStepSizeOriginal[vol]); + } + + for(int v = 0; v < volume_count; ++v) { + int vol = volumes_in_fragment[v]; + float l = volumeRaycastingDistance(vol, startFrag, endFrag); + float aaa = l/myMaxSteps; + volumeStepSize[vol] = aaa; + volID = vol; + } + } else { + volID = type -1; + } + + float l = volumeRaycastingDistance(volID, startFrag, endFrag); + int max_iterations = int(l / volumeStepSize[volID]); + + // TransferFunction + vec4 color = vec4(0); + for(int k = 0; k < max_iterations && final_color.a < ALPHA_LIMIT && k < LOOP_LIMIT; ++k) { + +#pragma openspace insert SAMPLERCALLS + + + } + + } +#endif + + + + + //blendGeometry(final_color, startFrag); + //if(i == maxFrags -1 && _type_(endFrag) == 0) + // blendGeometry(final_color, endFrag); + + // final_color = blend(final_color, frag_color); + if(i == frag_count_1 -1 && _type_(endFrag) == 0) + // if(i == frag_count_1 -1) + final_color = blend(final_color, _col_(endFrag)); + + } + // final_color = vec4(0); + // int id =3; + // if(id < frag_count)final_color = blend(final_color, _col_(fragments[id])); + + // if(frag_count > 0) + // final_color = _col_(fragments[0]); + +// ================================================================================ +// Transferfunction visualizer +// ================================================================================ +#ifdef VISUALIZE_TRANSFERFUNCTIONS +#pragma openspace insert TRANSFERFUNC +#endif + + // if(frag_count == 1) { + // final_color = vec4(1.0,0.0,0.0,1.0); + // } else if(frag_count == 2) { + // final_color = vec4(0.0,1.0,0.0,1.0); + // // final_color = vec4(volume_direction[0],1.0); + // } else if(frag_count == 3) { + // final_color = vec4(0.0,0.0,1.0,1.0); + // // final_color = vec4(volume_direction[0],1.0); + // } else if(frag_count == 4) { + // final_color = vec4(1.0,1.0,0.0,1.0); + // // final_color = vec4(volume_direction[0],1.0); + // } else { + // final_color = vec4(1.0,1.0,1.0,1.0); + // } + +#ifdef USE_COLORNORMALIZATION + final_color.rgb = final_color.rgb * final_color.a; + final_color.a = 1.0; +#endif + + return final_color; + +} + +// ================================================================================ +// Main function +// ================================================================================ +void main() { + out_color = vec4(texCoord,0.0,1.0); + int frag_count = build_local_fragments_list(); + sort_fragments_list(frag_count); + out_color = calculate_final_color(frag_count); +} + +// ================================================================================ +// The samplers implementations +// ================================================================================ +#pragma openspace insert SAMPLERS + + + diff --git a/shaders/ABuffer/abufferResolveVertex.glsl b/shaders/ABuffer/abufferResolveVertex.glsl new file mode 100644 index 0000000000..301a151753 --- /dev/null +++ b/shaders/ABuffer/abufferResolveVertex.glsl @@ -0,0 +1,33 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + +#version 430 + +in vec4 position; +out vec2 texCoord; + +void main() { + gl_Position = position; + texCoord = 0.5 + position.xy / 2.0; +} diff --git a/shaders/ABuffer/abufferSort.hglsl b/shaders/ABuffer/abufferSort.hglsl new file mode 100644 index 0000000000..71acc355b7 --- /dev/null +++ b/shaders/ABuffer/abufferSort.hglsl @@ -0,0 +1,141 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 "abufferAddToBuffer.hglsl" + +uniform float volumeStepFactor = 1.0f; + +int build_local_fragments_list() { + +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED + uint current; + int frag_count = 0; + + current = imageLoad(anchorPointerTexture, ivec2(gl_FragCoord.xy)).x; + + while(current != 0 && frag_count < MAX_FRAGMENTS) { + ABufferStruct_t item = loadFromBuffer(current); + current = _next_(item); + + fragments[frag_count] = item; + + frag_count++; + } + + return frag_count; +#endif + +#if ABUFFER_IMPLEMENTATION == ABUFFER_FIXED + uint frag_count = imageLoad(anchorPointerTexture, ivec2(gl_FragCoord.xy)).x; + + int i; + for(i = 0; i < frag_count && i < MAX_FRAGMENTS; ++i) { + fragments[i] = loadFromBuffer(i); + } + + return int(frag_count); +#endif + +} + +float pscLength(vec4 v1, vec4 v2) { + const float k = 10.0; + float ds = v2.w - v1.w; + vec4 vector; + if(ds >= 0) { + float p = pow(k,-ds); + vector = vec4(v1.x*p - v2.x, v1.y*p - v2.y, v1.z*p - v2.z, v2.w); + } else { + float p = pow(k,ds); + vector = vec4(v1.x - v2.x*p, v1.y - v2.y*p, v1.z - v2.z*p, v1.w); + } + return length(vector.xyz)*pow(k,vector.w); +} + +float permute(float i) { + return mod((62.0*i*i + i), 961.0); // permutation polynomial; 62=2*31; 961=31*31 +} + +void sort_fragments_list(uint frag_count) { + uint i,j; + ABufferStruct_t tmp; + + // INSERTION SORT + for(i = 1; i < frag_count; ++i) { + tmp = fragments[i]; + for(j = i; j > 0 && _z_(tmp) < _z_(fragments[j-1]); --j) { + fragments[j] = fragments[j-1]; + } + fragments[j] = tmp; + } + +#if MAX_VOLUMES > 0 + int ii, jj; + for(ii = 0; ii < MAX_VOLUMES; ++ii) { + bool start = true; + vec3 startColor; + vec4 startPosition; + for(jj = 0; jj < frag_count; ++jj) { + int type = int(_type_(fragments[jj])) - 1; + if(type== ii) { + if(start) { + startColor = _col_(fragments[jj]).rgb; + startPosition = _pos_(fragments[jj]); +#if ZTYPE == ZDEPTH + volume_zlength[ii].x = _z_(fragments[jj]); +#endif + start = false; + } else { + volumes_in_fragment[volume_count++] = ii; + vec3 dir = _col_(fragments[jj]).rgb - startColor; + volume_position[ii] = startColor; + volume_length[ii] = length(dir); + volume_direction[ii] = normalize(dir); + volumeStepSize[ii] = 1.0/(volumeStepFactor * length(volume_direction[ii]*volume_dim[ii])); + volumeStepSizeOriginal[ii] = volumeStepSize[ii]; +#if ZTYPE == ZDEPTH + volume_zlength[ii].y = _z_(fragments[jj]); +#elif ZTYPE == PSCDEPTH + volume_zlength[ii] = pscLength(_pos_(fragments[jj]), startPosition); +#endif +#ifdef USE_JITTERING + if(volumeStepSize[ii] < volume_length[ii]) { + // jittering + float x = gl_FragCoord.x; + float y = gl_FragCoord.y; + float jitterValue = float(permute(x + permute(y))) / 961.0; + vec3 frontPosNew = startColor + (jitterValue*volumeStepSize[ii])*volume_direction[ii]; + volume_position[ii] = frontPosNew; + } +#endif + + break; + } + } + } + } +#endif + //volume_direction[0] = vec3(1.0,0.0,0.0); + //volume_direction[0] = _col_(fragments[0]).rgb; +} diff --git a/shaders/ABuffer/abufferStruct.hglsl b/shaders/ABuffer/abufferStruct.hglsl new file mode 100644 index 0000000000..5c510c4bd0 --- /dev/null +++ b/shaders/ABuffer/abufferStruct.hglsl @@ -0,0 +1,162 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 ABUFFERSTRUCT_H_HGLSL +#define ABUFFERSTRUCT_H_HGLSL + +// The different kinds of implementation, set from OpenSpace +// #define ABUFFER_SINGLE_LINKED 1 +// #define ABUFFER_FIXED 2 +// #define ABUFFER_DYNAMIC 3 +// #define ABUFFER_IMPLEMENTATION ABUFFER_SINGLE_LINKED + + +//======================================================================================== +// ABufferStruct_t declaration +//======================================================================================== +// struct ABufferStruct_t { +// uint z; // the depth value +// uint id; // bits 0-28 next, bits 29-32 type +// vec4 color; // packed rgba +// //vec4 position; // packed position +// // uint padding1; +// // uint padding2; +// }; +struct ABufferStruct_t { + uint z; // the depth value + uint id; // bits 0-28 next, bits 29-32 type + uint rg; // packed red green color + uint ba; // packed blue alpha color + vec4 position; // position +}; + + +//======================================================================================== +// Bitwise operations +//======================================================================================== +const uint mask_1 = 1; +const uint mask_8 = 255; +const uint mask_16 = 65535; +const uint mask_24 = 16777215; +const uint mask_29 = 536870911; +const uint mask_30 = 1073741823; +const uint mask_31 = 2147483647; +const uint mask_32 = 4294967295; +const uint mask_id = mask_16; +const uint shift_id = 0; +const uint mask_type = mask_24 - mask_16; +const uint shift_type = 16; +/* +const uint mask_zid_z = mask_24; +const uint shift_zid_z = 0; +const uint mask_zid_id = mask_29 - mask_24; +const uint shift_zid_id = 24; +const uint mask_zid_type = mask_31 - mask_29; +const uint shift_zid_type = 29; +const uint mask_zid_xxx = mask_32 - mask_31; +const uint shift_zid_xxx = 31; +*/ + +const uint mask_id_next = mask_29; +const uint shift_id_next = 0; +const uint mask_id_type = mask_32 - mask_29; +const uint shift_id_type = 29; + +void bitinsert_u(inout uint pack, uint val, uint mask, uint shift) { + pack &= ~mask; + pack |= (val << shift) & mask; +} +uint bitextract_u(in uint pack, uint mask, uint shift) { + return (pack >> shift) & (mask >> shift); +} +void bitinsert_i(inout int pack, int val, uint mask, uint shift) { + pack &= int( ~mask ); + pack |= int( (uint(val) << shift) & mask ); +} +int bitextract_i(in int pack, uint mask, uint shift) { + return int( (uint(pack) >> shift) & (mask >> shift) ); +} + +//======================================================================================== +// Access functions +//======================================================================================== +float _z_(ABufferStruct_t frag) { + return uintBitsToFloat(frag.z); +} +void _z_(inout ABufferStruct_t frag, float z) { + frag.z = floatBitsToUint(z); +} + +vec4 _pos_(ABufferStruct_t frag) { + // return vec4(0.0,0.0,0.0,0.0); + return frag.position; + //return unpackUnorm4x8(frag.position); +} +void _pos_(inout ABufferStruct_t frag, vec4 position) { + frag.position = position; + // frag.position = packUnorm4x8(position); +} + +vec4 _col_(ABufferStruct_t frag) { + return vec4(unpackUnorm2x16(frag.rg),unpackUnorm2x16(frag.ba)); + //return unpackUnorm4x8(frag.color); +} +void _col_(inout ABufferStruct_t frag, vec4 color) { + frag.rg = packUnorm2x16(color.rg); + frag.ba = packUnorm2x16(color.ba); + //frag.color = packUnorm4x8(color); +} + +uint _type_(ABufferStruct_t frag) { +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED + return bitextract_u(frag.id, mask_id_type, shift_id_type); +#else + return frag.id; +#endif +} +void _type_(inout ABufferStruct_t frag, uint type) { +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED + bitinsert_u(frag.id, type, mask_id_type, shift_id_type); +#else + frag.id = type; +#endif +} + +//======================================================================================== +// Implementation specific functions +//======================================================================================== + +// _next_ is only needed for the single linked implementation +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED +uint _next_(ABufferStruct_t frag) { + return bitextract_u(frag.id, mask_id_next, shift_id_next); + //return frag.id; +} +void _next_(inout ABufferStruct_t frag, uint id) { + bitinsert_u(frag.id, id, mask_id_next, shift_id_next); + //frag.id = id; +} +#endif + +#endif \ No newline at end of file diff --git a/shaders/PowerScaling/powerScaling_fs.hglsl b/shaders/PowerScaling/powerScaling_fs.hglsl new file mode 100644 index 0000000000..c227016f1d --- /dev/null +++ b/shaders/PowerScaling/powerScaling_fs.hglsl @@ -0,0 +1,90 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 POWERSCALING_FS_H_HGLSL +#define POWERSCALING_FS_H_HGLSL + +// Observable universe is 10^27m, setting the far value to extremely high, aka 30!! ERMAHGERD! + +const float k = 10.0; +const float s_far = 27.0f; //= gl_DepthRange.far; // 40 +const float s_farcutoff = 12.0f; +const float s_nearcutoff = 7.00f; +const float s_near = 0.00f;// gl_DepthRange.near; // 0.1 + +vec4 psc_normlization(vec4 invec) { + + float xymax = max(invec.x,invec.y); + + if(invec.z > 0.0f || invec.z < 0.0f) { + return invec / abs(invec.z); + } else if (xymax != 0.0f) { + return invec / xymax; + } else { + return invec / -.0; + } +} + +float pscDepth(vec4 position) { + float depth = 0.0f; + if(position.w <= 0.5) { + //depth = abs(position.z * pow(10, position.w)) / pow(k,s_far); + depth = (position.w+log(abs(position.z)))/pow(k, position.w); + } else if(position.w < 3.0) { + depth = position.w+log(abs(position.z))/pow(k, position.w); + } else { + depth = position.w+log(abs(position.z)); + } + + + // DEBUG + float depth_orig = depth; + float x = 0.0f; + float cutoffs = 0.0; + float orig_z = position.z; + + // calculate a normalized depth [0.0 1.0] + if((depth > s_near && depth <= s_nearcutoff) || (depth > s_farcutoff && depth < s_far)) { + + // completely linear interpolation [s_near .. depth .. s_far] + depth = (depth - s_near) / (s_far - s_near); + + } else if(depth > s_nearcutoff && depth < s_farcutoff) { + + // DEBUG + cutoffs = 1.0; + + // interpolate [10^s_nearcutoff .. 10^depth .. 10^s_farcutoff] + // calculate between 0..1 where the depth is + x = (pow(10,depth) - pow(10, s_nearcutoff)) / (pow(10,s_farcutoff) - pow(10, s_nearcutoff)); + + // remap the depth to the 0..1 depth buffer + depth = s_nearcutoff + x * (s_farcutoff - s_nearcutoff); + depth = (depth - s_near) / (s_far - s_near); + + } + return depth; +} + +#endif \ No newline at end of file diff --git a/shaders/PowerScaling/powerScaling_vs.hglsl b/shaders/PowerScaling/powerScaling_vs.hglsl new file mode 100644 index 0000000000..0ec24564b7 --- /dev/null +++ b/shaders/PowerScaling/powerScaling_vs.hglsl @@ -0,0 +1,80 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 POWERSCALING_VS_H_HGLSL +#define POWERSCALING_VS_H_HGLSL + +const float k = 10.0; + +vec4 psc_addition(vec4 v1, vec4 v2) { + float ds = v2.w - v1.w; + if(ds >= 0) { + float p = pow(k,-ds); + return vec4(v1.x*p + v2.x, v1.y*p + v2.y, v1.z*p + v2.z, v2.w); + } else { + float p = pow(k,ds); + return vec4(v1.x + v2.x*p, v1.y + v2.y*p, v1.z + v2.z*p, v1.w); + } +} + +vec4 psc_to_meter(vec4 v1, vec2 v2) { + float factor = v2.x * pow(k,v2.y + v1.w); + return vec4(v1.xyz * factor, 1.0); +} + +vec4 psc_scaling(vec4 v1, vec2 v2) { + float ds = v2.y - v1.w; + if(ds >= 0) { + return vec4(v1.xyz * v2.x * pow(k,v1.w), v2.y); + } else { + return vec4(v1.xyz * v2.x * pow(k,v2.y), v1.w); + } +} + +vec4 pscTransform(vec4 vertexPosition, vec4 cameraPosition, vec2 scaling, mat4 modelTransform) { + vec3 local_vertex_pos = mat3(modelTransform) * vertexPosition.xyz; + //vec4 lvp = ModelTransform * vertexPosition; + + // PSC addition; local vertex position and the object power scaled world position + vec4 position = psc_addition(vec4(local_vertex_pos,vertexPosition.w),objpos); + //position = psc_addition(lvp,objpos); + + // PSC addition; rotated and viewscaled vertex and the cmaeras negative position + position = psc_addition(position,vec4(-cameraPosition.xyz,cameraPosition.w)); + + // rotate the camera + local_vertex_pos = mat3(camrot) * position.xyz; + position = vec4(local_vertex_pos, position.w); + //position = camrot* position; + + // rescales the scene to fit inside the view frustum + // is set from the main program, but these are decent values + // scaling = vec2(1.0, -8.0); + + // project using the rescaled coordinates, + //vec4 vs_position_rescaled = psc_scaling(position, scaling); + return psc_to_meter(position, scaling); +} + +#endif \ No newline at end of file diff --git a/shaders/cubeFrag.glsl b/shaders/cubeFrag.glsl index 0b6be3de9a..292f1396c8 100644 --- a/shaders/cubeFrag.glsl +++ b/shaders/cubeFrag.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 330 in vec4 color; diff --git a/shaders/cubeVert.glsl b/shaders/cubeVert.glsl index 68a1d89d43..38393b3e3f 100644 --- a/shaders/cubeVert.glsl +++ b/shaders/cubeVert.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 330 uniform mat4 projectionMatrix; diff --git a/shaders/exitpoints.frag b/shaders/exitpoints.frag index 1ea86ecb38..71dac97245 100644 --- a/shaders/exitpoints.frag +++ b/shaders/exitpoints.frag @@ -1,8 +1,52 @@ -#version 400 core +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + +#version 430 core + +uniform int volumeType; in vec3 vPosition; -out vec4 fragColor; +in vec3 worldPosition; +in float s; + +#include "ABuffer/abufferStruct.hglsl" +#include "ABuffer/abufferAddToBuffer.hglsl" +#include "PowerScaling/powerScaling_fs.hglsl" void main() { - fragColor = vec4(vPosition+0.5, 1.0); + vec4 fragColor = vec4(vPosition+0.5, 1.0); + vec4 position = vec4(worldPosition,s); + float depth = pscDepth(position); + + gl_FragDepth = depth; + + ABufferStruct_t frag; + _col_(frag, fragColor); + _z_(frag, depth); + _type_(frag, volumeType); + _pos_(frag, position); + addToBuffer(frag); + + discard; } \ No newline at end of file diff --git a/shaders/exitpoints.vert b/shaders/exitpoints.vert index 0668ef5618..a3295d3a6f 100644 --- a/shaders/exitpoints.vert +++ b/shaders/exitpoints.vert @@ -1,11 +1,62 @@ -#version 400 core +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + +#version 430 core + +layout(location = 0) in vec4 vertPosition; -layout(location = 2) in vec3 vertPosition; uniform mat4 modelViewProjection; +uniform mat4 modelTransform; +uniform vec4 campos; +uniform mat4 camrot; +uniform vec2 scaling; +uniform vec4 objpos; out vec3 vPosition; +out vec3 worldPosition; +out float s; + +#include "PowerScaling/powerScaling_vs.hglsl" void main() { - gl_Position = modelViewProjection * vec4(vertPosition, 1.0); - vPosition = vertPosition; + + //vs_st = in_st; + //vs_stp = in_position.xyz; + + vPosition = vertPosition.xyz; + + // this is wrong for the normal. The normal transform is the transposed inverse of the model transform + //vs_normal = normalize(modelTransform * vec4(in_normal,0)); + + vec4 position = pscTransform(vertPosition, campos, scaling, modelTransform); + worldPosition = position.xyz; + s = position.w; + + // project the position to view space + gl_Position = modelViewProjection * position; + + // vPosition = vertPosition.xyz; + // worldPosition = (modelTransform *vec4(vPosition, 1.0)).xyz; + // gl_Position = modelViewProjection *vec4(worldPosition, 1.0); } \ No newline at end of file diff --git a/shaders/pscstandard_fs.glsl b/shaders/pscstandard_fs.glsl index 6a3faef107..26a3d1987d 100644 --- a/shaders/pscstandard_fs.glsl +++ b/shaders/pscstandard_fs.glsl @@ -1,115 +1,49 @@ -/** -Copyright (C) 2012-2014 Jonas Strandstedt +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ -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: +#version 430 -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. -*/ -#version 400 core - -uniform mat4 ViewProjection; -uniform mat4 ModelTransform; -uniform vec4 campos; -uniform vec4 objpos; uniform float time; uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform float TessLevel; -uniform bool Wireframe; -uniform bool Lightsource; -uniform bool UseTexture; in vec2 vs_st; -//in vec3 vs_stp; in vec4 vs_normal; -in vec4 vs_position; +in vec3 vs_position; +in float s; -out vec4 diffuse; - -const float k = 10.0; - -vec4 psc_normlization(vec4 invec) { - - float xymax = max(invec.x,invec.y); - - if(invec.z > 0.0f || invec.z < 0.0f) { - return invec / abs(invec.z); - } else if (xymax != 0.0f) { - return invec / xymax; - } else { - return invec / -.0; - } -} +#include "ABuffer/abufferStruct.hglsl" +#include "ABuffer/abufferAddToBuffer.hglsl" +#include "PowerScaling/powerScaling_fs.hglsl" void main() { + vec4 position = vec4(vs_position,s); + float depth = pscDepth(position); + vec4 diffuse = texture(texture1, vs_st); - // Observable universe is 10^27m, setting the far value to extremely high, aka 30!! ERMAHGERD! - float s_far = 27.0; //= gl_DepthRange.far; // 40 - float s_farcutoff = 12.0; - float s_nearcutoff = 7.0; - float s_near = 0.0f;// gl_DepthRange.near; // 0.1 - float depth; + ABufferStruct_t frag = createGeometryFragment(diffuse, position, depth); + addToBuffer(frag); - // the value can be normalized to 1 - - vec4 p = vs_position; - if(vs_position.w <= 0.5) { - //depth = abs(vs_position.z * pow(10, vs_position.w)) / pow(k,s_far); - depth = (vs_position.w+log(abs(vs_position.z)))/pow(k, vs_position.w); - } else if(vs_position.w < 3.0) { - depth = vs_position.w+log(abs(vs_position.z))/pow(k, vs_position.w); - } else { - depth = vs_position.w+log(abs(vs_position.z)); - } - - - // DEBUG - float depth_orig = depth; - float x = 0.0f; - float cutoffs = 0.0; - float orig_z = vs_position.z; - - // calculate a normalized depth [0.0 1.0] - if((depth > s_near && depth <= s_nearcutoff) || (depth > s_farcutoff && depth < s_far)) { - - // completely linear interpolation [s_near .. depth .. s_far] - depth = (depth - s_near) / (s_far - s_near); - - } else if(depth > s_nearcutoff && depth < s_farcutoff) { - - // DEBUG - cutoffs = 1.0; - - // interpolate [10^s_nearcutoff .. 10^depth .. 10^s_farcutoff] - // calculate between 0..1 where the depth is - x = (pow(10,depth) - pow(10, s_nearcutoff)) / (pow(10,s_farcutoff) - pow(10, s_nearcutoff)); - - // remap the depth to the 0..1 depth buffer - depth = s_nearcutoff + x * (s_farcutoff - s_nearcutoff); - depth = (depth - s_near) / (s_far - s_near); - - } else { - // where am I? - // do I need to be discarded? - // discard; - } - - - // set the depth - gl_FragDepth = depth; - //gl_FragDepth = 0.5; - - // color - diffuse = texture(texture1, vs_st); - //diffuse = vec4(vs_position.z,0.0, 0.0, 1.0); - // diffuse = vec4(vs_position.xyz * pow(10, vs_position.w), 1.0); - //diffuse = vec4(vs_st, 0.0, 1.0); - //diffuse = vec4(1.0,1.0, 0.0, 1.0); - //diffuse = vec4(depth*5,0.0, 0.0, 1.0); - //diffuse = vec4(vs_position.w,0.0, 0.0, 1.0); - //diffuse = vec4(1.0,0.0,0.0,1.0); + discard; } \ No newline at end of file diff --git a/shaders/pscstandard_vs.glsl b/shaders/pscstandard_vs.glsl index 0c588a7ccd..e9e1745dc9 100644 --- a/shaders/pscstandard_vs.glsl +++ b/shaders/pscstandard_vs.glsl @@ -1,25 +1,28 @@ -/** -Copyright (C) 2012-2014 Jonas Strandstedt +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ -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. -*/ -#version 400 core +#version 430 uniform mat4 ViewProjection; uniform mat4 ModelTransform; @@ -28,13 +31,6 @@ uniform mat4 camrot; uniform vec2 scaling; uniform vec4 objpos; uniform float time; -uniform sampler2D texture1; -uniform sampler2D texture2; -uniform sampler2D texture3; -uniform float TessLevel; -uniform bool Wireframe; -uniform bool Lightsource; -uniform bool UseTexture; layout(location = 0) in vec4 in_position; //in vec3 in_position; @@ -44,72 +40,24 @@ layout(location = 2) in vec3 in_normal; out vec2 vs_st; out vec3 vs_stp; out vec4 vs_normal; -out vec4 vs_position; +out vec3 vs_position; +out float s; -const float k = 10.0; -const float dgr_to_rad = 0.0174532925; - -vec4 psc_addition(vec4 v1, vec4 v2) { - float ds = v2.w - v1.w; - if(ds >= 0) { - float p = pow(k,-ds); - return vec4(v1.x*p + v2.x, v1.y*p + v2.y, v1.z*p + v2.z, v2.w); - } else { - float p = pow(k,ds); - return vec4(v1.x + v2.x*p, v1.y + v2.y*p, v1.z + v2.z*p, v1.w); - } -} - -vec4 psc_to_meter(vec4 v1, vec2 v2) { - float factor = v2.x * pow(k,v2.y + v1.w); - return vec4(v1.xyz * factor, 1.0); -} - -vec4 psc_scaling(vec4 v1, vec2 v2) { - float ds = v2.y - v1.w; - if(ds >= 0) { - return vec4(v1.xyz * v2.x * pow(k,v1.w), v2.y); - } else { - return vec4(v1.xyz * v2.x * pow(k,v2.y), v1.w); - } -} +#include "PowerScaling/powerScaling_vs.hglsl" void main() { // set variables vs_st = in_st; //vs_stp = in_position.xyz; + + // this is wrong for the normal. The normal transform is the transposed inverse of the model transform vs_normal = normalize(ModelTransform * vec4(in_normal,0)); - // fetch model and view translation - //vec4 vertex_translate = ModelTransform[3]; - - // rotate and scale vertex with model transform and add the translation - vec3 local_vertex_pos = mat3(ModelTransform) * in_position.xyz; - //vec4 lvp = ModelTransform * in_position; - - // PSC addition; local vertex position and the object power scaled world position - vs_position = psc_addition(vec4(local_vertex_pos,in_position.w),objpos); - //vs_position = psc_addition(lvp,objpos); - - // PSC addition; rotated and viewscaled vertex and the cmaeras negative position - vs_position = psc_addition(vs_position,vec4(-campos.xyz,campos.w)); - - // rotate the camera - local_vertex_pos = mat3(camrot) * vs_position.xyz; - vs_position = vec4(local_vertex_pos, vs_position.w); - //vs_position = camrot* vs_position; - - // rescales the scene to fit inside the view frustum - // is set from the main program, but these are decent values - // scaling = vec2(1.0, -8.0); - - // project using the rescaled coordinates, - //vec4 vs_position_rescaled = psc_scaling(vs_position, scaling); - vec4 vs_position_rescaled = psc_to_meter(vs_position, scaling); - //vs_position = vs_position_rescaled; - + vec4 position = pscTransform(in_position, campos, scaling, ModelTransform); + vs_position = position.xyz; + s = position.w; // project the position to view space - gl_Position = ViewProjection * vs_position_rescaled; + gl_Position = ViewProjection * position; } \ No newline at end of file diff --git a/shaders/quadFrag.glsl b/shaders/quadFrag.glsl index 0b4adc27c0..a52ce0a5f5 100644 --- a/shaders/quadFrag.glsl +++ b/shaders/quadFrag.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 330 uniform sampler2D quadTex; diff --git a/shaders/quadVert.glsl b/shaders/quadVert.glsl index 2140173049..3221517490 100644 --- a/shaders/quadVert.glsl +++ b/shaders/quadVert.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 330 layout(location = 0) in vec2 texCoordinate; diff --git a/shaders/quadVertFlare.glsl b/shaders/quadVertFlare.glsl index a3c9b18411..12b7b9fe41 100644 --- a/shaders/quadVertFlare.glsl +++ b/shaders/quadVertFlare.glsl @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 330 in vec4 position; diff --git a/shaders/singlepassraycaster.frag b/shaders/singlepassraycaster.frag index 222c459ae3..e910176269 100644 --- a/shaders/singlepassraycaster.frag +++ b/shaders/singlepassraycaster.frag @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 400 core // Based on http://prideout.net/blog/?p=64 diff --git a/shaders/singlepassraycaster.gs b/shaders/singlepassraycaster.gs index a393169a32..fea6d6b415 100644 --- a/shaders/singlepassraycaster.gs +++ b/shaders/singlepassraycaster.gs @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 400 core // Based on http://prideout.net/blog/?p=64 diff --git a/shaders/singlepassraycaster.vert b/shaders/singlepassraycaster.vert index c33d4689b9..df013c63ae 100644 --- a/shaders/singlepassraycaster.vert +++ b/shaders/singlepassraycaster.vert @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 400 core // Based on http://prideout.net/blog/?p=64 diff --git a/shaders/twopassraycaster.frag b/shaders/twopassraycaster.frag index 1e9daf5cdb..1641c013dd 100644 --- a/shaders/twopassraycaster.frag +++ b/shaders/twopassraycaster.frag @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 400 core uniform sampler2D texBack, texFront; diff --git a/shaders/twopassraycaster.vert b/shaders/twopassraycaster.vert index 164a5e8643..f8453e0f57 100644 --- a/shaders/twopassraycaster.vert +++ b/shaders/twopassraycaster.vert @@ -1,3 +1,27 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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. * + ****************************************************************************************/ + #version 400 core layout(location = 0) in vec2 texCoordinate; diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 58bb285bd1..9099e1666d 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -34,6 +34,12 @@ file(GLOB CONFIGURATION_HEADER ${HEADER_ROOT_DIR}/openspace/configuration/*.h) set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${CONFIGURATION_HEADER}) source_group(Configuration FILES ${CONFIGURATION_SOURCE} ${CONFIGURATION_HEADER}) +file(GLOB ABUFFER_SOURCE ${SOURCE_ROOT_DIR}/abuffer/*.cpp) +set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${ABUFFER_SOURCE}) +file(GLOB ABUFFER_HEADER ${HEADER_ROOT_DIR}/openspace/abuffer/*.h) +set(OPENSPACE_HEADER ${OPENSPACE_HEADER} ${ABUFFER_HEADER}) +source_group(ABuffer FILES ${ABUFFER_SOURCE} ${ABUFFER_HEADER}) + file(GLOB ENGINE_SOURCE ${SOURCE_ROOT_DIR}/engine/*.cpp) set(OPENSPACE_SOURCE ${OPENSPACE_SOURCE} ${ENGINE_SOURCE}) file(GLOB ENGINE_HEADER ${HEADER_ROOT_DIR}/openspace/engine/*.h) diff --git a/src/abuffer/abuffer.cpp b/src/abuffer/abuffer.cpp new file mode 100644 index 0000000000..920a87b24d --- /dev/null +++ b/src/abuffer/abuffer.cpp @@ -0,0 +1,379 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 +#include + +#include +#include +#include + +#include +#include +#include + +namespace { + std::string _loggerCat = "ABuffer"; + +std::string padGeneratedString(const std::string& content) { + std::string _content_ = "// GENERATED CONTENT\n" + content + "\n// END GENERATED CONTENT"; + return _content_; +} + +} + +namespace openspace { + +ABuffer::ABuffer(): _validShader(true) { + int x1, xSize, y1, ySize; + sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); + _width = xSize; + _height = ySize; + _totalPixels = _width * _height; + const std::string fragmentShaderSourcePath = absPath("${SHADERS}/ABuffer/abufferResolveFragment.glsl"); + _fragmentShaderFile = new ghoul::filesystem::File(fragmentShaderSourcePath, true); + _fragmentShaderPath = fragmentShaderSourcePath.substr(0, fragmentShaderSourcePath.length()-4) + "gglsl"; +} + +ABuffer::~ABuffer() { + if(_fragmentShaderFile) + delete _fragmentShaderFile; + + if(_resolveShader) + delete _resolveShader; + + for(auto file: _samplerFiles) { + delete file; + } + for(auto file: _shaderFiles) { + delete file; + } + +} + +bool ABuffer::initializeABuffer() { + // ============================ + // SHADERS + // ============================ + auto shaderCallback = [this](const ghoul::filesystem::File& file) { + _validShader = false; + }; + _fragmentShaderFile->setCallback(shaderCallback); + + // Development functionality to update shader for changes in several files + auto addFunc = [this, shaderCallback](const std::string& path) { + ghoul::filesystem::File* f = new ghoul::filesystem::File(path, false); + f->setCallback(shaderCallback); + _shaderFiles.push_back(f); + }; + addFunc("${SHADERS}/ABuffer/abufferSort.hglsl"); + addFunc("${SHADERS}/ABuffer/abufferAddToBuffer.hglsl"); + addFunc("${SHADERS}/ABuffer/abufferStruct.hglsl"); + addFunc("${SHADERS}/PowerScaling/powerScaling_fs.hglsl"); + addFunc("${SHADERS}/PowerScaling/powerScaling_vs.hglsl"); + + _resolveShader = nullptr; + generateShaderSource(); + updateShader(); + + // ============================ + // GEOMETRY (quad) + // ============================ + const GLfloat size = 1.0f; + const GLfloat vertex_data[] = { // square of two triangles (sigh) + // x y z w s t + -size, -size, 0.0f, 1.0f, + size, size, 0.0f, 1.0f, + -size, size, 0.0f, 1.0f, + -size, -size, 0.0f, 1.0f, + size, -size, 0.0f, 1.0f, + size, size, 0.0f, 1.0f, + }; + GLuint vertexPositionBuffer; + glGenVertexArrays(1, &_screenQuad); // generate array + glBindVertexArray(_screenQuad); // bind array + glGenBuffers(1, &vertexPositionBuffer); // generate buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, reinterpret_cast(0)); + glEnableVertexAttribArray(0); + + return true; +} + +void ABuffer::resolve() { + if( ! _validShader) { + _validShader = true; + generateShaderSource(); + updateShader(); + + } + + if(_resolveShader) { + _resolveShader->activate(); + int startAt = 0; + for(int i = 0; i < _volumes.size(); ++i) { + glActiveTexture(GL_TEXTURE0 + i); + _volumes.at(i).second->bind(); + startAt = i + 1; + } + for(int i = 0; i < _transferFunctions.size(); ++i) { + glActiveTexture(GL_TEXTURE0 + startAt + i); + _transferFunctions.at(i).second->bind(); + } + + // Decrease stepsize in volumes if right click is pressed + // TODO: Let the interactionhandler handle this + int val = sgct::Engine::getMouseButton(0, SGCT_MOUSE_BUTTON_RIGHT); + float volumeStepFactor = (val) ? 0.2: 1.0; + if(volumeStepFactor != _volumeStepFactor) { + _volumeStepFactor = volumeStepFactor; + _resolveShader->setUniform("volumeStepFactor", _volumeStepFactor); + } + + glBindVertexArray(_screenQuad); + glDrawArrays(GL_TRIANGLES, 0, 6); + + _resolveShader->deactivate(); + } +} + +void ABuffer::addVolume(const std::string& tag,ghoul::opengl::Texture* volume) { + _volumes.push_back(std::make_pair(tag, volume)); +} + +void ABuffer::addTransferFunction(const std::string& tag,ghoul::opengl::Texture* transferFunction) { + _transferFunctions.push_back(std::make_pair(tag, transferFunction)); +} + +int ABuffer::addSamplerfile(const std::string& filename) { + if( ! FileSys.fileExists(filename)) + return -1; + + auto fileCallback = [this](const ghoul::filesystem::File& file) { + _validShader = false; + }; + ghoul::filesystem::File* file = new ghoul::filesystem::File(filename); + file->setCallback(fileCallback); + _samplerFiles.push_back(file); + _samplers.push_back(""); + + // ID is one more than "actual" position since ID=0 is considered geometry + //return 1 << (_samplers.size()-1); + return _samplers.size(); +} + +bool ABuffer::updateShader() { + + using ghoul::opengl::ShaderObject; + using ghoul::opengl::ProgramObject; + ShaderCreator sc = OsEng.shaderBuilder(); + ghoul::opengl::ProgramObject* resolveShader = sc.buildShader("ABuffer resolve", absPath("${SHADERS}/ABuffer/abufferResolveVertex.glsl"), _fragmentShaderPath); + if( ! resolveShader) { + LERROR("Resolve shader not updated"); + return false; + } + + int startAt = 0; + for(int i = 0; i < _volumes.size(); ++i) { + resolveShader->setUniform(_volumes.at(i).first, i); + startAt = i + 1; + } + for(int i = 0; i < _transferFunctions.size(); ++i) { + resolveShader->setUniform(_transferFunctions.at(i).first, startAt + i); + } + + if(_resolveShader) + delete _resolveShader; + + _resolveShader = resolveShader; + LDEBUG("Successfully updated shader!"); + return true; +} + +void ABuffer::generateShaderSource() { + + for(int i = 0; i < _samplerFiles.size(); ++i) { + std::string line, source = ""; + std::ifstream samplerFile(_samplerFiles.at(i)->path()); + if(samplerFile.is_open()) { + while(std::getline(samplerFile, line)) { + source += line + "\n"; + } + } + samplerFile.close(); + _samplers.at(i) = source; + } + + std::string line, source = ""; + std::ifstream fragmentShaderFile(_fragmentShaderFile->path()); + if(fragmentShaderFile.is_open()) { + while(std::getline(fragmentShaderFile, line)) { + if(line == "#pragma openspace insert HEADERS") { + line = padGeneratedString(openspaceHeaders()); + } else if(line == "#pragma openspace insert SAMPLERCALLS") { + line = padGeneratedString(openspaceSamplerCalls()); + } else if(line == "#pragma openspace insert SAMPLERS") { + line = padGeneratedString(openspaceSamplers()); + } else if(line == "#pragma openspace insert SETTINGS") { + line = padGeneratedString(settings()); + } else if(line == "#pragma openspace insert TRANSFERFUNC") { + line = padGeneratedString(openspaceTransferFunction()); + } + source += line + "\n"; + } + } + fragmentShaderFile.close(); + + std::ofstream fragmentShaderOut(_fragmentShaderPath); + fragmentShaderOut << source; + fragmentShaderOut.close(); +} + +std::string ABuffer::openspaceHeaders() { + + std::string headers; + headers += "#define MAX_VOLUMES " + std::to_string(_samplers.size()) + "\n"; + headers += "#define MAX_TF " + std::to_string(_transferFunctions.size()) + "\n"; + + + for (int i = 0; i < _volumes.size(); ++i) { + headers += "uniform sampler3D " + _volumes.at(i).first + ";\n"; + } + for (int i = 0; i < _transferFunctions.size(); ++i) { + headers += "uniform sampler1D " + _transferFunctions.at(i).first + ";\n"; + } + + for (int i = 0; i < _samplers.size(); ++i) { + auto found = _samplers.at(i).find_first_of('{'); + if(found!=std::string::npos) { + headers += _samplers.at(i).substr(0, found) + ";\n"; + } + } + + if(_volumes.size() < 1) + return headers; + + size_t maxLoop = 0; + headers += "const vec3 volume_dim[] = {\n"; + for (int i = 0; i < _volumes.size(); ++i) { + glm::size3_t size = _volumes.at(i).second->dimensions(); + for(int k = 0; k < 3; ++k) + maxLoop = glm::max(maxLoop, size[k]); + headers += " vec3(" + std::to_string(size[0]) + ".0," + std::to_string(size[1]) + ".0," + + std::to_string(size[2]) + ".0),\n"; + } + headers += "};\n"; + + headers += "#define LOOP_LIMIT " + std::to_string(maxLoop) + "\n"; + + headers += "float volumeStepSize[] = {\n"; + for (int i = 0; i < _volumes.size(); ++i) { + glm::size3_t size = _volumes.at(i).second->dimensions(); + headers += " stepSize,\n"; + } + headers += "};\n"; + + headers += "float volumeStepSizeOriginal[] = {\n"; + for (int i = 0; i < _volumes.size(); ++i) { + glm::size3_t size = _volumes.at(i).second->dimensions(); + headers += " stepSize,\n"; + } + headers += "};\n"; + + return headers; +} + +std::string ABuffer::openspaceSamplerCalls() { + std::string samplercalls; + for (int i = 0; i < _samplers.size(); ++i) { + + auto found1 = _samplers.at(i).find_first_not_of("vec4 "); + auto found2 = _samplers.at(i).find_first_of("(",found1); + if(found1 != std::string::npos && found2 != std::string::npos) { + std::string functionName = _samplers.at(i).substr(found1, found2 - found1); + samplercalls += "#ifndef SKIP_VOLUME_"+std::to_string(i)+"\n"; + samplercalls += "if((currentVolumeBitmask & (1 << " + std::to_string(i) + ")) == "+std::to_string(1 << i)+") {\n"; + samplercalls += " vec4 c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; + // samplercalls += " if(c.a < 0.1) { \n"; + // samplercalls += " if( volumeStepSize[" + std::to_string(i) + "] < 16.0*volumeStepSizeOriginal[" + std::to_string(i) + "]) \n"; + // samplercalls += " volumeStepSize[" + std::to_string(i) + "] *= 2.0; \n"; + // samplercalls += " } else {\n"; + // samplercalls += " //volume_position[" + std::to_string(i) + "] -= volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n"; + // samplercalls += " volumeStepSize[" + std::to_string(i) + "] = volumeStepSizeOriginal[" + std::to_string(i) + "]; \n"; + // samplercalls += " //c = " + functionName + "(final_color,volume_position[" + std::to_string(i) + "]);\n"; + // samplercalls += " } \n"; + // samplercalls += " if(c.a > EPSILON)\n"; + samplercalls += " blendStep(final_color, c, volumeStepSize[" + std::to_string(i) + "]);\n"; + // samplercalls += " blendStep(final_color, c, stepSize);\n"; + // samplercalls += " float aaa = volume_length[i]/myMaxSteps;\n"; + samplercalls += " volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n"; + // float aaa = ray[v].w/myMaxSteps; + // pos[v] += vec4(ray[v].xyz*vec3(aaa),aaa); + // samplercalls += " volume_position[" + std::to_string(i) + "] += volume_direction[" + std::to_string(i) + "]*volumeStepSize[" + std::to_string(i) + "];\n"; + samplercalls += "}\n"; + samplercalls += "#endif\n"; + } + + + } + return samplercalls; +} + +std::string ABuffer::openspaceSamplers() { + std::string samplers; + for (int i = 0; i < _samplers.size(); ++i) { + samplers += _samplers.at(i) + "\n"; + } + return samplers; +} + +std::string ABuffer::openspaceTransferFunction() { + std::string tf; + tf += "float showfunc_size = 20.0;\n"; + tf += "float SCREEN_HEIGHTf = float(SCREEN_HEIGHT);\n"; + tf += "float SCREEN_WIDTHf = float(SCREEN_WIDTH);\n"; + for(int i = 0; i < _transferFunctions.size(); ++i) { + tf += "if( gl_FragCoord.y > SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i+1)+ + " && gl_FragCoord.y < SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i)+") {\n"; + tf += " float normalizedIntensity = gl_FragCoord.x / (SCREEN_WIDTHf-1) ;\n"; + tf += " vec4 tfc = texture("+ _transferFunctions.at(i).first +", normalizedIntensity);\n"; + tf += " final_color = tfc;\n"; + tf += " float cmpf = SCREEN_HEIGHTf-showfunc_size*"+std::to_string(i+1)+" + tfc.a*showfunc_size;\n"; + tf += " if(gl_FragCoord.y > cmpf) {\n"; + tf += " final_color = vec4(0,0,0,0);\n"; + tf += " } else {\n"; + tf += " final_color.a = 1.0;\n"; + tf += " }\n"; + tf += "} else if(ceil(gl_FragCoord.y) == SCREEN_HEIGHTf - showfunc_size*"+std::to_string(i+1)+") {\n"; + tf += " const float intensity = 0.4;\n"; + tf += " final_color = vec4(intensity,intensity,intensity,1.0);\n"; + tf += "}\n"; + } + + return tf; +} + + +} // openspace \ No newline at end of file diff --git a/src/abuffer/abufferSingleLinked.cpp b/src/abuffer/abufferSingleLinked.cpp new file mode 100644 index 0000000000..f1a09b3c2d --- /dev/null +++ b/src/abuffer/abufferSingleLinked.cpp @@ -0,0 +1,124 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 +#include + +#include +#include + +#include +#include +#include + +#define MAX_LAYERS 10 + +namespace { + std::string _loggerCat = "ABufferSingleLinked"; +} + +namespace openspace { + +ABufferSingleLinked::ABufferSingleLinked(): _data(0), _anchorPointerTexture(0), + _anchorPointerTextureInitializer(0), _atomicCounterBuffer(0), _fragmentBuffer(0), + _fragmentTexture(0) +{} + +ABufferSingleLinked::~ABufferSingleLinked() { + if(_data != 0) + delete _data; + + glDeleteTextures(1,&_anchorPointerTexture); + glDeleteTextures(1,&_fragmentTexture); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); + glDeleteBuffers(1,&_atomicCounterBuffer); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); +} + +bool ABufferSingleLinked::initialize() { + // ============================ + // BUFFERS + // ============================ + glGenTextures(1, &_anchorPointerTexture); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + glGenBuffers(1, &_anchorPointerTextureInitializer); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBufferData(GL_PIXEL_UNPACK_BUFFER, _totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW); + + _data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + memset(_data, 0x00, _totalPixels * sizeof(GLuint)); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + glGenBuffers(1, &_atomicCounterBuffer); + glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, _atomicCounterBuffer); + glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY); + + glGenBuffers(1, &_fragmentBuffer); + glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer); + glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*_totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY); + + glGenTextures(1, &_fragmentTexture); + glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer); + glBindTexture(GL_TEXTURE_BUFFER, 0); + + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + + return initializeABuffer(); +} + +void ABufferSingleLinked::clear() { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + static const GLuint zero = 1; + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); + glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(zero), &zero); + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); +} + +void ABufferSingleLinked::preRender() { + + // Bind head-pointer image for read-write + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); + glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); +} + +void ABufferSingleLinked::postRender() { + +} + +std::string ABufferSingleLinked::settings() { + return R"()"; +} + + +} // openspace \ No newline at end of file diff --git a/src/abuffer/abufferdynamic.cpp b/src/abuffer/abufferdynamic.cpp new file mode 100644 index 0000000000..8943905eda --- /dev/null +++ b/src/abuffer/abufferdynamic.cpp @@ -0,0 +1,124 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 +#include + +#include +#include + +#include +#include +#include + +#define MAX_LAYERS 10 + +namespace { + std::string _loggerCat = "ABufferDynamic"; +} + +namespace openspace { + +ABufferDynamic::ABufferDynamic(): _data(0), _anchorPointerTexture(0), + _anchorPointerTextureInitializer(0), _atomicCounterBuffer(0), _fragmentBuffer(0), + _fragmentTexture(0) +{} + +ABufferDynamic::~ABufferDynamic() { + if(_data != 0) + delete _data; + + glDeleteTextures(1,&_anchorPointerTexture); + glDeleteTextures(1,&_fragmentTexture); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); + glDeleteBuffers(1,&_atomicCounterBuffer); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); +} + +bool ABufferDynamic::initialize() { + // ============================ + // BUFFERS + // ============================ + glGenTextures(1, &_anchorPointerTexture); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + glGenBuffers(1, &_anchorPointerTextureInitializer); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBufferData(GL_PIXEL_UNPACK_BUFFER, _totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW); + + _data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + memset(_data, 0x00, _totalPixels * sizeof(GLuint)); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + glGenBuffers(1, &_atomicCounterBuffer); + glBindBuffer(GL_ATOMIC_COUNTER_BUFFER, _atomicCounterBuffer); + glBufferData(GL_ATOMIC_COUNTER_BUFFER, sizeof(GLuint), NULL, GL_DYNAMIC_COPY); + + glGenBuffers(1, &_fragmentBuffer); + glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer); + glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*_totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY); + + glGenTextures(1, &_fragmentTexture); + glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer); + glBindTexture(GL_TEXTURE_BUFFER, 0); + + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + + return initializeABuffer(); +} + +void ABufferDynamic::clear() { + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + static const GLuint zero = 1; + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); + glBufferSubData(GL_ATOMIC_COUNTER_BUFFER, 0, sizeof(zero), &zero); + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, 0); +} + +void ABufferDynamic::preRender() { + + // Bind head-pointer image for read-write + glBindBufferBase(GL_ATOMIC_COUNTER_BUFFER, 0, _atomicCounterBuffer); + glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); +} + +void ABufferDynamic::postRender() { + +} + +std::string ABufferDynamic::settings() { + return R"(#define ABUFFER_SINGLE_LINKED)"; +} + + +} // openspace \ No newline at end of file diff --git a/src/abuffer/abufferfixed.cpp b/src/abuffer/abufferfixed.cpp new file mode 100644 index 0000000000..36c5a7aeae --- /dev/null +++ b/src/abuffer/abufferfixed.cpp @@ -0,0 +1,137 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 +#include + +#include +#include + +#include +#include +#include + +#define MAX_LAYERS 32 + +namespace { + std::string _loggerCat = "ABufferFixed"; +} + +namespace openspace { + +ABufferFixed::ABufferFixed(): _data(0), _anchorPointerTexture(0), + _anchorPointerTextureInitializer(0), _atomicCounterBuffer(0), _fragmentBuffer(0), + _fragmentTexture(0) +{} + +ABufferFixed::~ABufferFixed() { + if(_data != 0) + delete _data; + + glDeleteTextures(1,&_anchorPointerTexture); + glDeleteTextures(1,&_fragmentTexture); + // glDeleteTextures(1,&_atomicCounterTexture); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); + // glDeleteBuffers(1,&_atomicCounterBuffer); + glDeleteBuffers(1,&_anchorPointerTextureInitializer); +} + +bool ABufferFixed::initialize() { + // ============================ + // BUFFERS + // ============================ + glGenTextures(1, &_anchorPointerTexture); + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + glGenBuffers(1, &_anchorPointerTextureInitializer); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + glBufferData(GL_PIXEL_UNPACK_BUFFER, _totalPixels * sizeof(GLuint), NULL, GL_STATIC_DRAW); + + _data = (GLuint*)glMapBuffer(GL_PIXEL_UNPACK_BUFFER, GL_WRITE_ONLY); + memset(_data, 0x00, _totalPixels * sizeof(GLuint)); + glUnmapBuffer(GL_PIXEL_UNPACK_BUFFER); + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + + + // glGenBuffers(1, &_atomicCounterBuffer); + // glBindBuffer(GL_TEXTURE_BUFFER, _atomicCounterBuffer); + // glBufferData(GL_TEXTURE_BUFFER, _totalPixels*sizeof(GLuint), NULL, GL_DYNAMIC_COPY); + + // glGenTextures(1, &_atomicCounterTexture); + // glBindTexture(GL_TEXTURE_2D, _atomicCounterTexture); + // glTexBuffer(GL_TEXTURE_BUFFER, GL_R32UI, _atomicCounterBuffer); + // glBindTexture(GL_TEXTURE_BUFFER, 0); + + + glGenBuffers(1, &_fragmentBuffer); + glBindBuffer(GL_TEXTURE_BUFFER, _fragmentBuffer); + glBufferData(GL_TEXTURE_BUFFER, MAX_LAYERS*_totalPixels*sizeof(GLfloat)*4, NULL, GL_DYNAMIC_COPY); + + glGenTextures(1, &_fragmentTexture); + glBindTexture(GL_TEXTURE_BUFFER, _fragmentTexture); + glTexBuffer(GL_TEXTURE_BUFFER, GL_RGBA32UI, _fragmentBuffer); + glBindTexture(GL_TEXTURE_BUFFER, 0); + + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_WRITE_ONLY, GL_RGBA32UI); + + return initializeABuffer(); +} + +void ABufferFixed::clear() { + + // Bind texture initializer + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, _anchorPointerTextureInitializer); + + // clear _anchorPointerTexture + glBindTexture(GL_TEXTURE_2D, _anchorPointerTexture); + glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + // // clear _atomicCounterTexture + // glBindTexture(GL_TEXTURE_2D, _atomicCounterTexture); + // glTexImage2D(GL_TEXTURE_2D, 0, GL_R32UI, _width, _height, 0, GL_RED_INTEGER, GL_UNSIGNED_INT, NULL); + + // reset GL_PIXEL_UNPACK_BUFFER + glBindBuffer(GL_PIXEL_UNPACK_BUFFER, 0); + +} + +void ABufferFixed::preRender() { + + // Bind head-pointer image for read-write + glBindImageTexture(0, _anchorPointerTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); + glBindImageTexture(1, _fragmentTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_RGBA32UI); + // glBindImageTexture(2, _atomicCounterTexture, 0, GL_FALSE, 0, GL_READ_WRITE, GL_R32UI); +} + +void ABufferFixed::postRender() { + +} + +std::string ABufferFixed::settings() { + return R"()"; +} + + +} // openspace \ No newline at end of file diff --git a/src/engine/openspaceengine.cpp b/src/engine/openspaceengine.cpp index 9ef104ac1a..3ef492befe 100644 --- a/src/engine/openspaceengine.cpp +++ b/src/engine/openspaceengine.cpp @@ -146,7 +146,6 @@ bool OpenSpaceEngine::registerBasePathFromConfigurationFile(const std::string& f if (last == std::string::npos) return false; - std::string basePath = absolutePath.substr(0, last); FileSys.registerPathToken(_basePathToken, basePath); @@ -156,9 +155,7 @@ bool OpenSpaceEngine::registerBasePathFromConfigurationFile(const std::string& f bool OpenSpaceEngine::findConfiguration(std::string& filename) { - if (!filename.empty()) return FileSys.fileExists(filename); - else { std::string currentDirectory = FileSys.absolutePath(FileSys.currentDirectory()); size_t occurrences = std::count(currentDirectory.begin(), currentDirectory.end(), ghoul::filesystem::FileSystem::PathSeparator); @@ -295,6 +292,20 @@ bool OpenSpaceEngine::initialize() glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); GLFWwindow* win = sgct::Engine::instance()->getActiveWindowPtr()->getWindowHandle(); glfwSwapBuffers(win); + int samples = sqrt(sgct::Engine::instance()->getActiveWindowPtr()->getNumberOfAASamples()); + LDEBUG("samples: " << samples); + + int x1, xSize, y1, ySize; + sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); + std::string sourceHeader = ""; + sourceHeader += "#define SCREEN_WIDTH " + std::to_string(xSize) + "\n"; + sourceHeader += "#define SCREEN_HEIGHT " + std::to_string(ySize) + "\n"; + sourceHeader += "#define ABUFFER_SINGLE_LINKED " + std::to_string(ABUFFER_SINGLE_LINKED) + "\n"; + sourceHeader += "#define ABUFFER_FIXED " + std::to_string(ABUFFER_FIXED) + "\n"; + sourceHeader += "#define ABUFFER_DYNAMIC " + std::to_string(ABUFFER_DYNAMIC) + "\n"; + sourceHeader += "#define ABUFFER_IMPLEMENTATION " + std::to_string(ABUFFER_IMPLEMENTATION) + "\n"; + _shaderBuilder.createSourceFile(true); + _shaderBuilder.sourceFileHeader(sourceHeader); // Register the filepaths from static function enables easy testing // registerFilePaths(); @@ -352,7 +363,6 @@ bool OpenSpaceEngine::initialize() _renderEngine->initialize(); sceneGraph->loadScene(sceneDescriptionPath, scenePath); sceneGraph->initialize(); - _renderEngine->setSceneGraph(sceneGraph); #ifdef FLARE_ONLY _flare = new Flare(); @@ -390,6 +400,10 @@ bool OpenSpaceEngine::initialize() } } +#ifdef OPENSPACE_VIDEO_EXPORT + LINFO("OpenSpace compiled with video export; press Print Screen to start/stop recording"); +#endif + return true; } @@ -426,6 +440,13 @@ ScriptEngine& OpenSpaceEngine::scriptEngine() return *_scriptEngine; } + +ShaderCreator& OpenSpaceEngine::shaderBuilder() +{ + // TODO custom assert (ticket #5) + return _shaderBuilder; +} + bool OpenSpaceEngine::initializeGL() { return _renderEngine->initializeGL(); @@ -470,6 +491,17 @@ void OpenSpaceEngine::postDraw() if (sgct::Engine::instance()->isMaster()) { _interactionHandler->unlockControls(); } +#ifdef OPENSPACE_VIDEO_EXPORT + float speed = 0.01; + glm::vec3 euler(0.0, speed, 0.0); + glm::quat rot = glm::quat(euler); + glm::vec3 euler2(0.0, -speed, 0.0); + glm::quat rot2 = glm::quat(euler2); + _interactionHandler->orbit(rot); + _interactionHandler->rotate(rot2); + if(_doVideoExport) + sgct::Engine::instance()->takeScreenshot(); +#endif #ifdef FLARE_ONLY _flare->postDraw(); #endif @@ -480,6 +512,12 @@ void OpenSpaceEngine::keyboardCallback(int key, int action) if (sgct::Engine::instance()->isMaster()) { _interactionHandler->keyboardCallback(key, action); } +#ifdef OPENSPACE_VIDEO_EXPORT + // LDEBUG("key: " << key); + // LDEBUG("SGCT_KEY_PRINT_SCREEN: " << SGCT_KEY_PRINT_SCREEN); + if(action == SGCT_PRESS && key == SGCT_KEY_PRINT_SCREEN) + _doVideoExport = !_doVideoExport; +#endif #ifdef FLARE_ONLY _flare->keyboard(key, action); #endif diff --git a/src/interaction/interactionhandler.cpp b/src/interaction/interactionhandler.cpp index b14d945a7d..ef241cc0bb 100644 --- a/src/interaction/interactionhandler.cpp +++ b/src/interaction/interactionhandler.cpp @@ -179,13 +179,18 @@ void InteractionHandler::distance(const PowerScaledScalar &distance) { } psc relative_origin_coordinate = relative - origin; - glm::vec3 dir(relative_origin_coordinate.direction()); - dir = dir * distance[0]; - relative_origin_coordinate = dir; + const glm::vec3 dir(relative_origin_coordinate.direction()); + glm:: vec3 newdir = dir * distance[0]; + relative_origin_coordinate = newdir; relative_origin_coordinate[3] = distance[1]; relative = relative + relative_origin_coordinate; - camera_->setPosition(relative); + relative_origin_coordinate = relative - origin; + newdir = relative_origin_coordinate.direction(); + + // update only if on the same side of the origin + if(glm::angle(newdir, dir) < 90.0f) + camera_->setPosition(relative); unlockControls(); } @@ -303,62 +308,65 @@ void InteractionHandler::keyboardCallback(int key, int action) { // TODO package in script const double speed = 2.75; const double dt = getDt(); - if (key == 'S') { - glm::vec3 euler(speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == 'W') { - glm::vec3 euler(-speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == 'A') { - glm::vec3 euler(0.0, -speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == 'D') { - glm::vec3 euler(0.0, speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - orbit(rot); - } - if (key == 262) { - glm::vec3 euler(0.0, speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 263) { - glm::vec3 euler(0.0, -speed * dt, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 264) { - glm::vec3 euler(speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 265) { - glm::vec3 euler(-speed * dt, 0.0, 0.0); - glm::quat rot = glm::quat(euler); - rotate(rot); - } - if (key == 'R') { - PowerScaledScalar dist(-speed * dt, 0.0); - distance(dist); - } - if (key == 'F') { - PowerScaledScalar dist(speed * dt, 0.0); - distance(dist); - } - if (key == 'T') { - PowerScaledScalar dist(-speed * 100.0 * dt, 0.0); - distance(dist); - } - if (key == 'G') { - PowerScaledScalar dist(speed * 100.0 * dt, 0.0); - distance(dist); - } + + if(action == SGCT_PRESS || action == SGCT_REPEAT) { + if (key == SGCT_KEY_S) { + glm::vec3 euler(speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + orbit(rot); + } + if (key == SGCT_KEY_W) { + glm::vec3 euler(-speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + orbit(rot); + } + if (key == SGCT_KEY_A) { + glm::vec3 euler(0.0, -speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + orbit(rot); + } + if (key == SGCT_KEY_D) { + glm::vec3 euler(0.0, speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + orbit(rot); + } + if (key == 262) { + glm::vec3 euler(0.0, speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + rotate(rot); + } + if (key == 263) { + glm::vec3 euler(0.0, -speed * dt, 0.0); + glm::quat rot = glm::quat(euler); + rotate(rot); + } + if (key == 264) { + glm::vec3 euler(speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + rotate(rot); + } + if (key == 265) { + glm::vec3 euler(-speed * dt, 0.0, 0.0); + glm::quat rot = glm::quat(euler); + rotate(rot); + } + if (key == SGCT_KEY_R) { + PowerScaledScalar dist(-speed * dt, 0.0); + distance(dist); + } + if (key == SGCT_KEY_F) { + PowerScaledScalar dist(speed * dt, 0.0); + distance(dist); + } + if (key == SGCT_KEY_T) { + PowerScaledScalar dist(-speed * 100.0 * dt, 0.0); + distance(dist); + } + if (key == SGCT_KEY_G) { + PowerScaledScalar dist(speed * 100.0 * dt, 0.0); + distance(dist); + } + } /* if (key == '1') { SceneGraphNode* node = getSceneGraphNode("sun"); @@ -385,15 +393,23 @@ void InteractionHandler::keyboardCallback(int key, int action) { getCamera()->setCameraDirection(glm::vec3(0.0, 0.0, -1.0)); } */ + // std::pair >::iterator, std::multimap >::iterator> ret; + if(action == SGCT_PRESS) { + auto ret = _keyCallbacks.equal_range(key); + for (auto it=ret.first; it!=ret.second; ++it) + it->second(); + } + + } void InteractionHandler::mouseButtonCallback(int key, int action) { //if(mouseControl_ != nullptr) { // mouseControl_->mouseButtonCallback(key,action); //} - if (key == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_PRESS) + if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_PRESS) _leftMouseButtonDown = true; - else if (key == GLFW_MOUSE_BUTTON_LEFT && action == GLFW_RELEASE) { + else if (key == SGCT_MOUSE_BUTTON_LEFT && action == SGCT_RELEASE) { _leftMouseButtonDown = false; _isMouseBeingPressedAndHeld = false; } @@ -412,7 +428,21 @@ void InteractionHandler::mouseScrollWheelCallback(int pos) { //if(mouseControl_ != nullptr) { // mouseControl_->mouseScrollCallback(pos); //} + const double speed = 4.75; + const double dt = getDt(); + if(pos < 0) { + PowerScaledScalar dist(speed * dt, 0.0); + distance(dist); + } else if(pos > 0) { + PowerScaledScalar dist(-speed * dt, 0.0); + distance(dist); + } } +void InteractionHandler::addKeyCallback(int key, std::function f) { + //std::map > > _keyCallbacks; + + _keyCallbacks.insert(std::make_pair(key, f)); +} } // namespace openspace diff --git a/src/main.cpp b/src/main.cpp index 9a69b4328b..d4b5d26af7 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -170,11 +170,11 @@ void mainMousePosCallback(double x, double y) OsEng.mousePositionCallback(static_cast(x), static_cast(y)); } -void mainMouseScrollCallback(double pos, double /*pos2*/) +void mainMouseScrollCallback(double posX, double posY) { // TODO use float instead if (_sgctEngine->isMaster()) - OsEng.mouseScrollWheelCallback(static_cast(pos)); + OsEng.mouseScrollWheelCallback(static_cast(posY)); } void mainEncodeFun() diff --git a/src/rendering/renderable.cpp b/src/rendering/renderable.cpp index 4527b7b3de..f62e26be7a 100644 --- a/src/rendering/renderable.cpp +++ b/src/rendering/renderable.cpp @@ -27,6 +27,8 @@ #include #include +#include + namespace { const std::string _loggerCat = "Renderable"; } @@ -61,6 +63,13 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary) // std::string name; // dictionary.getValue(constants::scenegraphnode::keyName, name); setName("renderable"); + + // get path if available + _relativePath = ""; + if(dictionary.hasKey(constants::scenegraph::keyPathModule)) { + dictionary.getValue(constants::scenegraph::keyPathModule, _relativePath); + _relativePath += "/"; + } } Renderable::~Renderable() @@ -81,4 +90,18 @@ void Renderable::update() { } -} // namespace openspace \ No newline at end of file +std::string Renderable::findPath(const std::string& path) { + std::string tmp = absPath(path); + if(FileSys.fileExists(tmp)) + return tmp; + + tmp = absPath(_relativePath + path); + if(FileSys.fileExists(tmp)) + return tmp; + + LERROR("Could not find file '" << path << "'"); + + return ""; +} + +} // namespace openspace diff --git a/src/rendering/renderablefieldlines.cpp b/src/rendering/renderablefieldlines.cpp new file mode 100644 index 0000000000..c750ddcd9a --- /dev/null +++ b/src/rendering/renderablefieldlines.cpp @@ -0,0 +1,315 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 +#include +#include +#include + +namespace { + std::string _loggerCat = "RenderableFieldlines"; +} + +namespace openspace { + +RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary) : + Renderable(dictionary), _VAO(0), _programUpdateOnSave(false),_update(false) { + + if(dictionary.hasKey("Fieldlines")) { + ghoul::Dictionary fieldlines; + if(dictionary.getValue("Fieldlines", fieldlines)) { + for(auto key: fieldlines.keys()) { + ghoul::Dictionary fieldline; + if(fieldlines.getValue(key, fieldline)) { + if (fieldline.hasKey("File")) { + std::string file = ""; + if (fieldline.getValue("File", file)) { + file = findPath(file); + if (file != "") { + + // read hints into dictionary + ghoul::Dictionary hintsDictionary; + if(fieldline.hasKey("Hints")) + fieldline.getValue("Hints", hintsDictionary); + + _filenames.push_back(file); + _hintsDictionaries.push_back(hintsDictionary); + } else + LERROR("File not found!"); + } + } + } + } + } + } + + std::string vshaderpath = ""; + std::string fshaderpath = ""; + + if (dictionary.hasKey("Shaders")) { + ghoul::Dictionary shaderDictionary; + if(dictionary.getValue("Shaders", shaderDictionary)) { + if (shaderDictionary.hasKey("VertexShader")) + shaderDictionary.getValue("VertexShader", vshaderpath); + + if (shaderDictionary.hasKey("FragmentShader")) + shaderDictionary.getValue("FragmentShader", fshaderpath); + + vshaderpath = findPath(vshaderpath); + fshaderpath = findPath(fshaderpath); + + _vertexSourceFile = new ghoul::filesystem::File(vshaderpath, false); + _fragmentSourceFile = new ghoul::filesystem::File(fshaderpath, false); + + + ShaderCreator sc = OsEng.shaderBuilder(); + _fieldlinesProgram = sc.buildShader("FieldlinesProgram", vshaderpath, fshaderpath); + } + } + + if(dictionary.hasKey("UpdateOnSave")) { + dictionary.getValue("UpdateOnSave", _programUpdateOnSave); + } + + setBoundingSphere(PowerScaledScalar::CreatePSS(5)); // FIXME a non-magic number perhaps +} + +RenderableFieldlines::~RenderableFieldlines() { +} + +bool RenderableFieldlines::initialize() { + assert(_filenames.size() != 0); + assert(_hintsDictionaries.size() != 0); + + int prevEnd = 0; + std::vector vertexData, seedPointsData; + std::vector > fieldlinesData; + glm::vec4 seedPointsColor = glm::vec4(1.0, 0.5, 0.0, 1.0); + + for (int i = 0; i < _filenames.size(); ++i) { + fieldlinesData = getFieldlinesData(_filenames[i], _hintsDictionaries[i]); + + for (int j = 0; j < fieldlinesData.size(); ++j) { + _lineStart.push_back(prevEnd); + _lineCount.push_back(fieldlinesData[j].size()); + prevEnd = prevEnd + fieldlinesData[j].size(); + vertexData.insert( vertexData.end(), fieldlinesData[j].begin(), fieldlinesData[j].end()); + } + // Give seedpoints a color for visualizing as GL_POINTS + for (glm::vec3 seedPoint : _seedPoints) { + seedPointsData.push_back(LinePoint(seedPoint, seedPointsColor)); + } + } + LDEBUG("Number of vertices : " << vertexData.size()); + + // ------ FIELDLINES ----------------- + GLuint vertexPositionBuffer; + glGenVertexArrays(1, &_VAO); // generate array + glBindVertexArray(_VAO); // bind array + glGenBuffers(1, &vertexPositionBuffer); // generate buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer + glBufferData(GL_ARRAY_BUFFER, vertexData.size()*sizeof(LinePoint), &vertexData.front(), GL_STATIC_DRAW); + + // Vertex positions + GLuint vertexLocation = 0; + glEnableVertexAttribArray(vertexLocation); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(LinePoint), reinterpret_cast(0)); + + // Texture coordinates + GLuint texcoordLocation = 1; + glEnableVertexAttribArray(texcoordLocation); + glVertexAttribPointer(texcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(LinePoint), (void*)(sizeof(glm::vec3))); + + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer + glBindVertexArray(0); //unbind array + + // ------ SEEDPOINTS ----------------- + GLuint seedpointPositionBuffer; + glGenVertexArrays(1, &_seedpointVAO); // generate array + glBindVertexArray(_seedpointVAO); // bind array + glGenBuffers(1, &seedpointPositionBuffer); // generate buffer + glBindBuffer(GL_ARRAY_BUFFER, seedpointPositionBuffer); // bind buffer + glBufferData(GL_ARRAY_BUFFER, seedPointsData.size()*sizeof(LinePoint), &seedPointsData.front(), GL_STATIC_DRAW); + + // Vertex positions + glEnableVertexAttribArray(vertexLocation); + glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, sizeof(LinePoint), reinterpret_cast(0)); + + // Texture coordinates + glEnableVertexAttribArray(texcoordLocation); + glVertexAttribPointer(texcoordLocation, 4, GL_FLOAT, GL_FALSE, sizeof(LinePoint), (void*)(3*sizeof(float))); + + glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer + glBindVertexArray(0); //unbind array + + glPointSize(5); // size of seedpoints + + // ------ SETUP SHADERS ----------------- + auto privateCallback = [this](const ghoul::filesystem::File& file) { + _update = true; + }; + if(_programUpdateOnSave) { + _vertexSourceFile->setCallback(privateCallback); + _fragmentSourceFile->setCallback(privateCallback); + } + + _fieldlinesProgram->compileShaderObjects(); + _fieldlinesProgram->linkProgramObject(); + + return true; +} + +bool RenderableFieldlines::deinitialize() { + return true; +} + +void RenderableFieldlines::render(const Camera* camera, const psc& thisPosition) { + if(_update) { + _update = false; + safeShaderCompilation(); + } + + glm::mat4 transform = camera->viewProjectionMatrix(); + glm::mat4 camTransform = camera->viewRotationMatrix(); + psc relative = thisPosition-camera->position(); + + transform = transform*camTransform; + transform = glm::mat4(1.0); + transform = glm::scale(transform, glm::vec3(0.01)); + + psc currentPosition = thisPosition; + psc campos = camera->position(); + glm::mat4 camrot = camera->viewRotationMatrix(); + PowerScaledScalar scaling = camera->scaling(); + + // Activate shader + _fieldlinesProgram->activate(); + + _fieldlinesProgram->setUniform("modelViewProjection", camera->viewProjectionMatrix()); + _fieldlinesProgram->setUniform("modelTransform", transform); + _fieldlinesProgram->setUniform("campos", campos.vec4()); + _fieldlinesProgram->setUniform("objpos", currentPosition.vec4()); + _fieldlinesProgram->setUniform("camrot", camrot); + _fieldlinesProgram->setUniform("scaling", scaling.vec2()); + + // ------ FIELDLINES ----------------- + glBindVertexArray(_VAO); + glMultiDrawArrays(GL_LINE_STRIP, &_lineStart[0], &_lineCount[0], _lineStart.size()); + +// // ------ SEEDPOINTS ----------------- +// glBindVertexArray(_seedpointVAO); +// glMultiDrawArrays(GL_POINTS, &_lineStart[0], &_lineCount[0], _seedPoints.size()); + glBindVertexArray(0); + + // Deactivate shader + _fieldlinesProgram->deactivate(); +} + +void RenderableFieldlines::update() { +} + +void RenderableFieldlines::safeShaderCompilation() { + _fieldlinesProgram->rebuildFromFile(); + _fieldlinesProgram->compileShaderObjects(); + _fieldlinesProgram->linkProgramObject(); +} + +std::vector > RenderableFieldlines::getFieldlinesData(std::string filename, ghoul::Dictionary hintsDictionary) { + std::string modelString; + float stepSize = 0.5; // default if no stepsize is specified in hints + std::string xVariable, yVariable, zVariable; + KameleonWrapper::Model model; + std::vector > fieldlinesData; + + bool classification = false, lorentz = false; + glm::vec4 fieldlineColor = glm::vec4(1.0, 1.0, 1.0, 1.0); // default color if no color or classification is specified + + if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) { + // ------ MODEL ----------------- + if (modelString == "BATSRUS") { + model = KameleonWrapper::Model::BATSRUS; + } else if (modelString == "ENLIL") { + LWARNING("ENLIL model not supported for fieldlines"); + return fieldlinesData; + } else { + LWARNING("Hints does not specify a valid 'Model'"); + return fieldlinesData; + } + + // ------ VARIBLES / LORENTZ ----------------- + if (hintsDictionary.hasKey("Variables")) { + bool xVar, yVar, zVar; + xVar = hintsDictionary.getValue("Variables.1", xVariable); + if (xVar && xVariable == "Lorentz") { + lorentz = true; + } else { + + yVar = hintsDictionary.getValue("Variables.2", yVariable); + zVar = hintsDictionary.getValue("Variables.3", zVariable); + + if (!xVar || !yVar || !zVar) { + LWARNING("Error reading variables! Must be 3 and must exist in CDF data"); + return fieldlinesData; + } + } + } else { + LWARNING("Hints does not specify valid 'Variables'"); + return fieldlinesData; + } + + // ------ STEPSIZE ----------------- + if (!hintsDictionary.hasKey("Stepsize") || !hintsDictionary.getValue("Stepsize", stepSize)) { + LDEBUG("No stepsize set for fieldlines. Setting to default value (" << stepSize << ")"); + } + + // ------ SEEDPOINTS --------------- + ghoul::Dictionary seedpointsDictionary; + _seedPoints.clear(); + if (hintsDictionary.hasKey("Seedpoints") && hintsDictionary.getValue("Seedpoints", seedpointsDictionary)) { + glm::vec3 seedPos; + for (auto index : seedpointsDictionary.keys()) { + hintsDictionary.getValue("Seedpoints."+index, seedPos); + _seedPoints.push_back(seedPos); + } + } + + // ------ CLASSIFICATION & COLOR ----------- + hintsDictionary.getValue("Color", fieldlineColor); + hintsDictionary.getValue("Classification", classification); + } + + KameleonWrapper kw(filename, model); + if (lorentz) { + fieldlinesData = kw.getLorentzTrajectories(_seedPoints, fieldlineColor, stepSize); + } else { + if (classification) + fieldlinesData = kw.getClassifiedFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize); + else + fieldlinesData = kw.getFieldLines(xVariable, yVariable, zVariable, _seedPoints, stepSize, fieldlineColor); + } + + return fieldlinesData; +} + +} // namespace openspace diff --git a/src/rendering/renderablevolume.cpp b/src/rendering/renderablevolume.cpp index c96b8ca7ae..7ecaf4274f 100644 --- a/src/rendering/renderablevolume.cpp +++ b/src/rendering/renderablevolume.cpp @@ -24,17 +24,16 @@ // open space includes #include - -#include -#include - #include #include #include -#include +// ghoul includes +#include +#include #include +#include #include #include #include @@ -73,92 +72,178 @@ namespace { namespace openspace { -RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary) - : Renderable(dictionary) -{ - // get path if available - _relativePath = ""; - if(dictionary.hasKey(constants::scenegraph::keyPathModule)) { - dictionary.getValue(constants::scenegraph::keyPathModule, _relativePath); - _relativePath += "/"; - } +RenderableVolume::RenderableVolume(const ghoul::Dictionary& dictionary) : Renderable(dictionary) { } RenderableVolume::~RenderableVolume() { } -std::string RenderableVolume::findPath(const std::string& path) { - std::string tmp = absPath(path); - if(FileSys.fileExists(tmp)) - return tmp; - - tmp = absPath(_relativePath + path); - if(FileSys.fileExists(tmp)) - return tmp; - - LERROR("Could not find file '" << path << "'"); - - return ""; +ghoul::opengl::Texture* RenderableVolume::loadVolume( + const std::string& filepath, + const ghoul::Dictionary& hintsDictionary) { + + + if( ! FileSys.fileExists(filepath)) { + LWARNING("Could not load volume, could not find '" << filepath << "'"); + return nullptr; + } + + if(hasExtension(filepath, "raw")) { + ghoul::RawVolumeReader::ReadHints hints = readHints(hintsDictionary); + ghoul::RawVolumeReader rawReader(hints); + return rawReader.read(filepath); + } else if(hasExtension(filepath, "cdf")) { + + ghoul::opengl::Texture::FilterMode filtermode = ghoul::opengl::Texture::FilterMode::Linear; + ghoul::opengl::Texture::WrappingMode wrappingmode = ghoul::opengl::Texture::WrappingMode::ClampToEdge; + + glm::size3_t dimensions(1,1,1); + double tempValue; + if (hintsDictionary.hasKey("Dimensions.1") && + hintsDictionary.getValue("Dimensions.1", tempValue)) { + int intVal = static_cast(tempValue); + if(intVal > 0) + dimensions[0] = intVal; + } + if (hintsDictionary.hasKey("Dimensions.2") && + hintsDictionary.getValue("Dimensions.2", tempValue)) { + int intVal = static_cast(tempValue); + if(intVal > 0) + dimensions[1] = intVal; + } + if (hintsDictionary.hasKey("Dimensions.3") && + hintsDictionary.getValue("Dimensions.3", tempValue)) { + int intVal = static_cast(tempValue); + if(intVal > 0) + dimensions[2] = intVal; + } + + std::string modelString = ""; + if (hintsDictionary.hasKey("Model")) + hintsDictionary.getValue("Model", modelString); + + if(modelString == "") { + LWARNING("Model not specified."); + return nullptr; + } + + std::string variableCacheString = ""; + if (hintsDictionary.hasKey("Variable")) { + hintsDictionary.getValue("Variable", variableCacheString); + } else if(hintsDictionary.hasKey("Variables")) { + std::string xVariable, yVariable, zVariable; + bool xVar, yVar, zVar; + xVar = hintsDictionary.getValue("Variables.1", xVariable); + yVar = hintsDictionary.getValue("Variables.2", yVariable); + zVar = hintsDictionary.getValue("Variables.3", zVariable); + if (xVar && yVar && zVar) { + variableCacheString = xVariable + "." + yVariable + "." + zVariable; + } + } + + bool cache = false; + hintsDictionary.hasKey("Cache"); + if (hintsDictionary.hasKey("Cache")) + hintsDictionary.getValue("Cache", cache); + + std::stringstream ss; + ss << "." << dimensions[0] << "x" << dimensions[1] << "x" << dimensions[2] << "." << modelString << "." << variableCacheString << ".cache"; + std::string cachepath = filepath + ss.str(); + if( cache && FileSys.fileExists(cachepath)) { + + FILE* file = fopen (cachepath.c_str(), "rb"); + + int length = dimensions[0] *dimensions[1] *dimensions[2]; + float* data = new float[length]; + + for(int i = 0; i< length; i++){ + float f; + fread(&f, sizeof(float), 1, file); + data[i] = f; + } + + fclose(file); + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, filtermode, wrappingmode); + } + + KameleonWrapper::Model model; + if (modelString == "BATSRUS") { + model = KameleonWrapper::Model::BATSRUS; + } else if (modelString == "ENLIL") { + model = KameleonWrapper::Model::ENLIL; + } else { + LWARNING("Hints does not specify a valid 'Model'"); + return nullptr; + } + + KameleonWrapper kw(filepath, model); + std::string variableString; + if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) { + float* data = kw.getUniformSampledValues(variableString, dimensions); + if(cache) { + FILE* file = fopen (cachepath.c_str(), "wb"); + int length = dimensions[0] *dimensions[1] *dimensions[2]; + fwrite(data, sizeof(float), length, file); + fclose(file); + } + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT, filtermode, wrappingmode); + } else if (hintsDictionary.hasKey("Variables")) { + std::string xVariable, yVariable, zVariable; + bool xVar, yVar, zVar; + xVar = hintsDictionary.getValue("Variables.1", xVariable); + yVar = hintsDictionary.getValue("Variables.2", yVariable); + zVar = hintsDictionary.getValue("Variables.3", zVariable); + + if (!xVar || !yVar || !zVar) { + LERROR("Error reading variables! Must be 3 and must exist in CDF data"); + } else { + + float* data = kw.getUniformSampledVectorValues(xVariable, yVariable, zVariable, dimensions); + if(cache) { + FILE* file = fopen (cachepath.c_str(), "wb"); + int length = dimensions[0] *dimensions[1] *dimensions[2]; + fwrite(data, sizeof(float), length, file); + fclose(file); + } + + return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::RGBA, GL_RGBA, GL_FLOAT, filtermode, wrappingmode); + } + + } else { + LWARNING("Hints does not specify a 'Variable' or 'Variables'"); + } + } else { + LWARNING("No valid file extension."); + } + return nullptr; } -ghoul::opengl::Texture* RenderableVolume::loadVolume(const std::string& filepath, const ghoul::Dictionary& hintsDictionary) { - if( ! FileSys.fileExists(filepath)) { - LWARNING("Could not load volume, could not find '" << filepath << "'"); - return nullptr; - } - - if(hasExtension(filepath, "raw")) { - ghoul::RawVolumeReader::ReadHints hints = readHints(hintsDictionary); - ghoul::RawVolumeReader rawReader(hints); - return rawReader.read(filepath); - } else if(hasExtension(filepath, "cdf")) { - - std::string modelString; - if (hintsDictionary.hasKey("Model") && hintsDictionary.getValue("Model", modelString)) { - KameleonWrapper::Model model; - if (modelString == "BATSRUS") { - model = KameleonWrapper::Model::BATSRUS; - } else if (modelString == "ENLIL") { - model = KameleonWrapper::Model::ENLIL; - } else { - LWARNING("Hints does not specify a valid 'Model'"); - return nullptr; - } - - std::string variableString; - if (hintsDictionary.hasKey("Variable") && hintsDictionary.getValue("Variable", variableString)) { - glm::size3_t dimensions(1,1,1); - double tempValue; - if (hintsDictionary.hasKey("Dimensions.1") && hintsDictionary.getValue("Dimensions.1", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[0] = intVal; - } - if (hintsDictionary.hasKey("Dimensions.2") && hintsDictionary.getValue("Dimensions.2", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[1] = intVal; - } - if (hintsDictionary.hasKey("Dimensions.3") && hintsDictionary.getValue("Dimensions.3", tempValue)) { - int intVal = static_cast(tempValue); - if(intVal > 0) - dimensions[2] = intVal; - } - - KameleonWrapper kw(filepath, model); - float* data = kw.getUniformSampledValues(variableString, dimensions); - return new ghoul::opengl::Texture(data, dimensions, ghoul::opengl::Texture::Format::Red, GL_RED, GL_FLOAT); - } else { - LWARNING("Hints does not specify a 'Variable'"); - } - - - } - LWARNING("Hints does not specify a 'Model'"); - } else { - LWARNING("No valid file extension."); - } - return nullptr; +glm::vec3 RenderableVolume::getVolumeOffset( + const std::string& filepath, + const ghoul::Dictionary& hintsDictionary) { + + std::string modelString = ""; + if (hintsDictionary.hasKey("Model")) + hintsDictionary.getValue("Model", modelString); + + if(modelString == "") { + LWARNING("Model not specified."); + return glm::vec3(0); + } + KameleonWrapper::Model model; + if (modelString == "BATSRUS") { + model = KameleonWrapper::Model::BATSRUS; + } else if (modelString == "ENLIL") { + model = KameleonWrapper::Model::ENLIL; + return glm::vec3(0); + } else { + LWARNING("Hints does not specify a valid 'Model'"); + return glm::vec3(0); + } + + KameleonWrapper kw(filepath, model); + + return kw.getModelBarycenterOffset(); } ghoul::RawVolumeReader::ReadHints RenderableVolume::readHints(const ghoul::Dictionary& dictionary) { @@ -228,10 +313,15 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string if ( ! FileSys.fileExists(f)) { return nullptr; } + ghoul::opengl::Texture::FilterMode filtermode = ghoul::opengl::Texture::FilterMode::Linear; + ghoul::opengl::Texture::WrappingMode wrappingmode = ghoul::opengl::Texture::WrappingMode::ClampToEdge; + // check if not a txt based texture if ( ! hasExtension(filepath, "txt")) { - return ghoul::opengl::loadTexture(f); + ghoul::opengl::Texture* t = ghoul::opengl::loadTexture(f); + t->setWrapping(wrappingmode); + return t; } // it is a txt based texture @@ -259,7 +349,7 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string auto widthValidator = [](size_t in) { if(in > 0) return in; return static_cast(1); }; auto upperLowerValidator = [](float in) { return glm::clamp(in, 0.0f, 1.0f); }; - auto intensityValidator = [](float in) { if(in > 0.0f) return in; return 1.0f; }; + auto intensityValidator = [](float in) { return glm::clamp(in, 0.0f, 1.0f); }; std::string line; while (std::getline(in, line)) { @@ -294,15 +384,26 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string if (mappingKeys.size() < 1) { return nullptr; } + + // for(auto key: mappingKeys) { + // glm::vec4 rgba = key.color; + // LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")"); + // } + // LDEBUG("insert...."); - mappingKeys.insert(mappingKeys.begin(), {lower}); - mappingKeys.push_back({upper}); - - - for(auto key: mappingKeys) { - glm::vec4 rgba = key.color; -// LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")"); + if (mappingKeys.front().position > lower){ + mappingKeys.insert(mappingKeys.begin(), {lower,mappingKeys.front().color}); } + + if (mappingKeys.back().position < upper){ + mappingKeys.push_back({upper,mappingKeys.back().color}); + } + + + // for(auto key: mappingKeys) { + // glm::vec4 rgba = key.color; + // LDEBUG("i: " << key.position << ", rgba: (" << rgba[0] << ", " << rgba[1] << ", " << rgba[2] << ", " << rgba[3] << ")"); + // } // allocate new float array with zeros float* transferFunction = new float[width*4](); @@ -310,8 +411,8 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string transferFunction[i] = 0.0f; } - size_t lowerIndex = static_cast(floorf(lower*static_cast(width))); - size_t upperIndex = static_cast(floorf(upper*static_cast(width))); + size_t lowerIndex = static_cast(floorf(lower*static_cast(width-1))); + size_t upperIndex = static_cast(floorf(upper*static_cast(width-1))); // LDEBUG("width: " << width); // LDEBUG("lower: " << lower); @@ -324,9 +425,9 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string auto currentKey = prevKey + 1; auto lastKey = mappingKeys.end() -1; - for (size_t i=lowerIndex; i(i)/static_cast(width); + float fpos = static_cast(i)/static_cast(width-1); if (fpos > (*currentKey).position) { prevKey = currentKey; @@ -361,16 +462,25 @@ ghoul::opengl::Texture* RenderableVolume::loadTransferFunction(const std::string //LDEBUG("["<< position <<"] " << value); } -// LDEBUG(weight << ", (" << -// transferFunction[4*i+0] << ", " << -// transferFunction[4*i+1] << ", " << -// transferFunction[4*i+2] << ", " << -// transferFunction[4*i+3] << ")"); + // LDEBUG(std::fixed << std::setw(10) << std::left << std::setprecision(8) << weight << ", (" << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+0] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+1] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+2] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+3] << ")"); } + // for (int i = 0; i <= width; ++i) { + + // LDEBUG(std::fixed << "(" << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+0] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+1] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+2] << ", " << + // std::setw(10) << std::left << std::setprecision(8) << transferFunction[4*i+3] << ")"); + // } + return new ghoul::opengl::Texture(transferFunction, glm::size3_t(width,1,1),ghoul::opengl::Texture::Format::RGBA, - GL_RGBA, GL_FLOAT);; + GL_RGBA, GL_FLOAT,filtermode, wrappingmode); } } // namespace openspace diff --git a/src/rendering/renderablevolumeexpert.cpp b/src/rendering/renderablevolumeexpert.cpp index c3f268ae4a..d1d33c9e51 100644 --- a/src/rendering/renderablevolumeexpert.cpp +++ b/src/rendering/renderablevolumeexpert.cpp @@ -210,7 +210,7 @@ RenderableVolumeExpert::RenderableVolumeExpert(const ghoul::Dictionary& dictiona } } - setBoundingSphere(PowerScaledScalar::CreatePSS(_boxScaling.length())); + setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling))); } RenderableVolumeExpert::~RenderableVolumeExpert() { @@ -253,9 +253,11 @@ bool RenderableVolumeExpert::initialize() { LDEBUG("Creating CL texture from GL texture with path '" << _volumePaths.at(i) << "'"); cl_mem volumeTexture = _context.createTextureFromGLTexture(CL_MEM_READ_ONLY, *volume); - + _volumes.push_back(volume); _clVolumes.push_back(volumeTexture); + } else { + LERROR("Invalid volume"); } } diff --git a/src/rendering/renderablevolumegl.cpp b/src/rendering/renderablevolumegl.cpp index 0d1ae60475..9e4bca99a0 100644 --- a/src/rendering/renderablevolumegl.cpp +++ b/src/rendering/renderablevolumegl.cpp @@ -24,17 +24,18 @@ // open space includes #include - #include +#include +#include #include #include #include -#include - #include +#include + namespace { std::string _loggerCat = "RenderableVolumeGL"; } @@ -42,11 +43,8 @@ namespace { namespace openspace { RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): - RenderableVolume(dictionary), - _backTexture(nullptr), _frontTexture(nullptr), _screenQuad(0), - _programUpdateOnSave(false) { - - _shaderMutex = new std::mutex; + RenderableVolume(dictionary), _boxScaling(1.0, 1.0, 1.0), + _updateTransferfunction(false), _id(-1) { _filename = ""; if(dictionary.hasKey("Volume")) { @@ -54,230 +52,233 @@ RenderableVolumeGL::RenderableVolumeGL(const ghoul::Dictionary& dictionary): _filename = findPath(_filename); } } - + LDEBUG("filename: " << _filename); - ghoul::Dictionary hintsDictionary; if(dictionary.hasKey("Hints")) - dictionary.getValue("Hints", hintsDictionary); - _hints = readHints(hintsDictionary); + dictionary.getValue("Hints", _hintsDictionary); - std::string vshaderpath = ""; - std::string fshaderpath = ""; - - if (dictionary.hasKey("Shaders")) { - ghoul::Dictionary shaderDictionary; - if(dictionary.getValue("Shaders", shaderDictionary)) { - if (shaderDictionary.hasKey("VertexShader")) { - shaderDictionary.getValue("VertexShader", vshaderpath); - } - if (shaderDictionary.hasKey("FragmentShader")) { - shaderDictionary.getValue("FragmentShader", fshaderpath); - } - - vshaderpath = findPath(vshaderpath); - fshaderpath = findPath(fshaderpath); - - _vertexSourceFile = new ghoul::filesystem::File(vshaderpath, false); - _fragmentSourceFile = new ghoul::filesystem::File(fshaderpath, false); - - _twopassProgram = new ghoul::opengl::ProgramObject("TwoPassProgram"); - ghoul::opengl::ShaderObject* vertexShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeVertex,vshaderpath); - ghoul::opengl::ShaderObject* fragmentShader = new ghoul::opengl::ShaderObject(ghoul::opengl::ShaderObject::ShaderTypeFragment,fshaderpath); - _twopassProgram->attachObject(vertexShader); - _twopassProgram->attachObject(fragmentShader); + _transferFunction = nullptr; + _transferFunctionFile = nullptr; + _transferFunctionPath = ""; + if (dictionary.hasKey("TransferFunction")) { + std::string transferFunctionPath = ""; + if(dictionary.getValue("TransferFunction", transferFunctionPath)) { + _transferFunctionPath = findPath(transferFunctionPath); } - - } - - if(dictionary.hasKey("UpdateOnSave")) { - dictionary.getValue("UpdateOnSave", _programUpdateOnSave); + _samplerFilename = ""; + if (dictionary.hasKey("Sampler")) { + if(dictionary.getValue("Sampler", _samplerFilename)) { + _samplerFilename = findPath(_samplerFilename); + } + } + if( _transferFunctionPath == "") { + LERROR("No transferFunction!"); + } else { + _transferFunctionFile = new ghoul::filesystem::File(_transferFunctionPath, true); + } + if( _samplerFilename == "") { + LERROR("No samplerfile!"); } + double tempValue; + if(dictionary.hasKey("BoxScaling.1") && dictionary.getValue("BoxScaling.1", tempValue)) { + if(tempValue > 0.0) + _boxScaling[0] = tempValue; + } + if(dictionary.hasKey("BoxScaling.2") && dictionary.getValue("BoxScaling.2", tempValue)) { + if(tempValue > 0.0) + _boxScaling[1] = tempValue; + } + if(dictionary.hasKey("BoxScaling.3") && dictionary.getValue("BoxScaling.3", tempValue)) { + if(tempValue > 0.0) + _boxScaling[2] = tempValue; + } + if(dictionary.hasKey("BoxScaling.4") && dictionary.getValue("BoxScaling.4", tempValue)) { + _w = tempValue; + } + + _volumeName = ""; + if (dictionary.hasKey("VolumeName")) + dictionary.getValue("VolumeName", _volumeName); + _transferFunctionName = ""; + if (dictionary.hasKey("TransferFunctionName")) + dictionary.getValue("TransferFunctionName", _transferFunctionName); + + setBoundingSphere(PowerScaledScalar::CreatePSS(glm::length(_boxScaling)*pow(10,_w))); } RenderableVolumeGL::~RenderableVolumeGL() { deinitialize(); - if(_fbo) - delete _fbo; - if(_backTexture) - delete _backTexture; - if(_frontTexture) - delete _frontTexture; if(_volume) delete _volume; - if(_boundingBox) - delete _boundingBox; + if(_transferFunctionFile) + delete _transferFunctionFile; + if(_transferFunction) + delete _transferFunction; } bool RenderableVolumeGL::initialize() { - assert(_filename != ""); + // assert(_filename != ""); // ------ VOLUME READING ---------------- - ghoul::RawVolumeReader rawReader(_hints); - _volume = rawReader.read(_filename); - - // ------ SETUP GEOMETRY ---------------- - const GLfloat size = 1.0f; - const GLfloat vertex_texcoord_data[] = { // square of two triangles (sigh) - // x y z s t - -size, -size, 0.0f, 0.0f, 0.0f, - size, size, 0.0f, 1.0f, 1.0f, - -size, size, 0.0f, 0.0f, 1.0f, - -size, -size, 0.0f, 0.0f, 0.0f, - size, -size, 0.0f, 1.0f, 0.0f, - size, size, 0.0f, 1.0f, 1.0f - }; - - GLuint vertexPositionBuffer; - glGenVertexArrays(1, &_screenQuad); // generate array - glBindVertexArray(_screenQuad); // bind array - glGenBuffers(1, &vertexPositionBuffer); // generate buffer - glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer - glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_texcoord_data), vertex_texcoord_data, GL_STATIC_DRAW); - - // Vertex positions - GLuint vertexLocation = 2; - glEnableVertexAttribArray(vertexLocation); - glVertexAttribPointer(vertexLocation, 3, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), reinterpret_cast(0)); - - // Texture coordinates - GLuint texcoordLocation = 0; - glEnableVertexAttribArray(texcoordLocation); - glVertexAttribPointer(texcoordLocation, 2, GL_FLOAT, GL_FALSE, 5*sizeof(GLfloat), (void*)(3*sizeof(GLfloat))); - - glBindBuffer(GL_ARRAY_BUFFER, 0); //unbind buffer - glBindVertexArray(0); //unbind array - - _boundingBox = new sgct_utils::SGCTBox(1.0f, sgct_utils::SGCTBox::Regular); - - // ------ SETUP SHADERS ----------------- - // TODO error control or better design pattern - OsEng.ref().configurationManager().getValue("RaycastProgram", _fboProgram); - - auto privateCallback = [this](const ghoul::filesystem::File& file) { - safeShaderCompilation(); - }; - if(_programUpdateOnSave) { - _vertexSourceFile->setCallback(privateCallback); - _fragmentSourceFile->setCallback(privateCallback); - } - - _twopassProgram->compileShaderObjects(); - _twopassProgram->linkProgramObject(); - _twopassProgram->setUniform("texBack", 0); - _twopassProgram->setUniform("texFront", 1); - _twopassProgram->setUniform("texVolume", 2); - //OsEng.ref().configurationManager().getValue("TwoPassProgram", _twopassProgram); - - // ------ SETUP FBO --------------------- - _fbo = new ghoul::opengl::FramebufferObject(); - _fbo->activate(); - - int x = sgct::Engine::instance()->getActiveXResolution(); - int y = sgct::Engine::instance()->getActiveYResolution(); - _backTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1)); - _frontTexture = new ghoul::opengl::Texture(glm::size3_t(x,y,1)); - _backTexture->uploadTexture(); - _frontTexture->uploadTexture(); - _fbo->attachTexture(_backTexture, GL_COLOR_ATTACHMENT0); - _fbo->attachTexture(_frontTexture, GL_COLOR_ATTACHMENT1); - - _fbo->deactivate(); +// <<<<<<< HEAD +// ======= +// _volume = loadVolume(_filename, _hintsDictionary); +// _volume->uploadTexture(); +// _transferFunction = loadTransferFunction(_transferFunctionPath); +// _transferFunction->uploadTexture(); +// >>>>>>> feature/fieldlines + // TODO: fix volume an transferfunction names + if(_filename != "") { + _volume = loadVolume(_filename, _hintsDictionary); + _boxOffset = getVolumeOffset(_filename, _hintsDictionary); + _volume->uploadTexture(); + OsEng.renderEngine().abuffer()->addVolume(_volumeName, _volume); + } + + if(_transferFunctionPath != "") { + _transferFunction = loadTransferFunction(_transferFunctionPath); + _transferFunction->uploadTexture(); + OsEng.renderEngine().abuffer()->addTransferFunction(_transferFunctionName, _transferFunction); + + auto textureCallback = [this](const ghoul::filesystem::File& file) { + _updateTransferfunction = true; + }; + _transferFunctionFile->setCallback(textureCallback); + } + + // add the sampler and get the ID + _id = OsEng.renderEngine().abuffer()->addSamplerfile(_samplerFilename); + + OsEng.configurationManager().getValue("RaycastProgram", _boxProgram); + _MVPLocation = _boxProgram->uniformLocation("modelViewProjection"); + _modelTransformLocation = _boxProgram->uniformLocation("modelTransform"); + _typeLocation = _boxProgram->uniformLocation("volumeType"); + + // ============================ + // GEOMETRY (quad) + // ============================ + const GLfloat size = 0.5f; + const GLfloat vertex_data[] = { // square of two triangles (sigh) + // x, y, z, s, + -size, -size, size, _w, + size, size, size, _w, + -size, size, size, _w, + -size, -size, size, _w, + size, -size, size, _w, + size, size, size, _w, + + -size, -size, -size, _w, + size, size, -size, _w, + -size, size, -size, _w, + -size, -size, -size, _w, + size, -size, -size, _w, + size, size, -size, _w, + + size, -size, -size, _w, + size, size, size, _w, + size, -size, size, _w, + size, -size, -size, _w, + size, size, -size, _w, + size, size, size, _w, + + -size, -size, -size, _w, + -size, size, size, _w, + -size, -size, size, _w, + -size, -size, -size, _w, + -size, size, -size, _w, + -size, size, size, _w, + + -size, size, -size, _w, + size, size, size, _w, + -size, size, size, _w, + -size, size, -size, _w, + size, size, -size, _w, + size, size, size, _w, + + -size, -size, -size, _w, + size, -size, size, _w, + -size, -size, size, _w, + -size, -size, -size, _w, + size, -size, -size, _w, + size, -size, size, _w, + }; + GLuint vertexPositionBuffer; + glGenVertexArrays(1, &_boxArray); // generate array + glBindVertexArray(_boxArray); // bind array + glGenBuffers(1, &vertexPositionBuffer); // generate buffer + glBindBuffer(GL_ARRAY_BUFFER, vertexPositionBuffer); // bind buffer + glBufferData(GL_ARRAY_BUFFER, sizeof(vertex_data), vertex_data, GL_STATIC_DRAW); + glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, sizeof(GLfloat)*4, reinterpret_cast(0)); + glEnableVertexAttribArray(0); return true; } bool RenderableVolumeGL::deinitialize() { - - return true; } void RenderableVolumeGL::render(const Camera *camera, const psc &thisPosition) { - - float speed = 50.0f; - float time = sgct::Engine::getTime(); - glm::mat4 transform = camera->viewProjectionMatrix(); - - double factor = pow(10.0,thisPosition[3]); - transform = glm::translate(transform, glm::vec3(thisPosition[0]*factor, thisPosition[1]*factor, thisPosition[2]*factor)); - transform = glm::rotate(transform, time*speed, glm::vec3(0.0f, 1.0f, 0.0f)); - - - _stepSize = 0.01f; - - // ------ DRAW TO FBO ------------------- - GLuint sgctFBO = ghoul::opengl::FramebufferObject::getActiveObject(); // Save SGCTs main FBO - _fbo->activate(); - _fboProgram->activate(); - _fboProgram->setUniform("modelViewProjection", transform); - - // Draw backface - glDrawBuffer(GL_COLOR_ATTACHMENT0); - glClearColor(0.2f, 0.2f, 0.2f, 0); - glClear(GL_COLOR_BUFFER_BIT); - glEnable(GL_CULL_FACE); - glCullFace(GL_FRONT); - _boundingBox->draw(); - glDisable(GL_CULL_FACE); - - // Draw frontface - glDrawBuffer(GL_COLOR_ATTACHMENT1); - glClear(GL_COLOR_BUFFER_BIT); - glClearColor(0.2f, 0.2f, 0.2f, 0); - glEnable(GL_CULL_FACE); - glCullFace(GL_BACK); - _boundingBox->draw(); - glDisable(GL_CULL_FACE); - - _fboProgram->deactivate(); - _fbo->deactivate(); - - // ------ DRAW TO SCREEN ---------------- - glBindFramebuffer(GL_FRAMEBUFFER, sgctFBO); // Re-bind SGCTs main FBO - - // Draw screenquad - glClearColor(0.2f, 0.2f, 0.2f, 0); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); - - _shaderMutex->lock(); - _twopassProgram->activate(); - _twopassProgram->setUniform("stepSize", _stepSize); - - // Set textures - glActiveTexture(GL_TEXTURE0); - _backTexture->bind(); - glActiveTexture(GL_TEXTURE1); - _frontTexture->bind(); - glActiveTexture(GL_TEXTURE2); - _volume->bind(); - - glBindVertexArray(_screenQuad); - glDrawArrays(GL_TRIANGLES, 0, 6); - glBindVertexArray(0); - - _twopassProgram->deactivate(); - _shaderMutex->unlock(); + if(_updateTransferfunction) { + _updateTransferfunction = false; + ghoul::opengl::Texture* transferFunction = loadTransferFunction(_transferFunctionPath); + if(transferFunction) { + const void* data = transferFunction->pixelData(); + glBindBuffer(GL_COPY_READ_BUFFER, *transferFunction); + _transferFunction->bind(); + glTexImage1D( GL_TEXTURE_1D, 0, _transferFunction->internalFormat(), + _transferFunction->width(),0, _transferFunction->format(), + _transferFunction->dataType(), data); + delete transferFunction; + LDEBUG("Updated transferfunction!"); + } + } + + glm::mat4 transform = glm::mat4(1.0); + transform = glm::scale(transform, _boxScaling); + + // fetch data + psc currentPosition = thisPosition; + psc campos = camera->position(); + glm::mat4 camrot = camera->viewRotationMatrix(); + PowerScaledScalar scaling = camera->scaling(); + + // psc addon(-1.1,0.0,0.0,0.0); + // currentPosition += addon; + psc addon(_boxOffset/100.0f); // TODO: Proper scaling/units + currentPosition += addon; // Move box to model barycenter + + // TODO: Use _id to identify this volume + _boxProgram->activate(); + _boxProgram->setUniform(_typeLocation, _id); + + _boxProgram->setUniform("modelViewProjection", camera->viewProjectionMatrix()); + _boxProgram->setUniform("modelTransform", transform); + _boxProgram->setUniform("campos", campos.vec4()); + _boxProgram->setUniform("objpos", currentPosition.vec4()); + _boxProgram->setUniform("camrot", camrot); + _boxProgram->setUniform("scaling", scaling.vec2()); + + // make sure GL_CULL_FACE is enabled (it should be) + glEnable(GL_CULL_FACE); + + // Draw backface + glCullFace(GL_FRONT); + glBindVertexArray(_boxArray); + glDrawArrays(GL_TRIANGLES, 0, 6*6); + + // Draw frontface (now the normal cull face is is set) + glCullFace(GL_BACK); + glDrawArrays(GL_TRIANGLES, 0, 6*6); + + _boxProgram->deactivate(); } void RenderableVolumeGL::update() { - } -void RenderableVolumeGL::safeShaderCompilation() { - _shaderMutex->lock(); - _twopassProgram->rebuildFromFile(); - _twopassProgram->compileShaderObjects(); - _twopassProgram->linkProgramObject(); - _twopassProgram->setUniform("texBack", 0); - _twopassProgram->setUniform("texFront", 1); - _twopassProgram->setUniform("texVolume", 2); - _shaderMutex->unlock(); -} - - - -} // namespace openspace \ No newline at end of file +} // namespace openspace diff --git a/src/rendering/renderengine.cpp b/src/rendering/renderengine.cpp index c56e5c84bd..9c5524e0f0 100644 --- a/src/rendering/renderengine.cpp +++ b/src/rendering/renderengine.cpp @@ -34,6 +34,10 @@ #include +#include +#include +#include + namespace { const std::string _loggerCat = "RenderEngine"; } @@ -42,6 +46,7 @@ namespace openspace { RenderEngine::RenderEngine() : _mainCamera(nullptr) , _sceneGraph(nullptr) + , _abuffer(nullptr) { } @@ -52,6 +57,7 @@ RenderEngine::~RenderEngine() bool RenderEngine::initialize() { + // LDEBUG("RenderEngine::initialize()"); // init camera and set temporary position and scaling _mainCamera = new Camera(); _mainCamera->setScaling(glm::vec2(1.0, -8.0)); @@ -61,11 +67,19 @@ bool RenderEngine::initialize() //if (sgct::Engine::instance()->isMaster()) OsEng.interactionHandler().setCamera(_mainCamera); +#if ABUFFER_IMPLEMENTATION == ABUFFER_SINGLE_LINKED + _abuffer = new ABufferSingleLinked(); +#elif ABUFFER_IMPLEMENTATION == ABUFFER_FIXED + _abuffer = new ABufferFixed(); +#elif ABUFFER_IMPLEMENTATION == ABUFFER_DYNAMIC + _abuffer = new ABufferDynamic(); +#endif return true; } bool RenderEngine::initializeGL() { + // LDEBUG("RenderEngine::initializeGL()"); sgct::SGCTWindow* wPtr = sgct::Engine::instance()->getActiveWindowPtr(); // TODO: Fix the power scaled coordinates in such a way that these values can be @@ -75,7 +89,7 @@ bool RenderEngine::initializeGL() // set the close clip plane and the far clip plane to extreme values while in // development // sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f,100.0f); - sgct::Engine::instance()->setNearAndFarClippingPlanes(0.00001f, 100.0f); + sgct::Engine::instance()->setNearAndFarClippingPlanes(0.1f, 200.0f); // calculating the maximum field of view for the camera, used to // determine visibility of objects in the scene graph @@ -132,6 +146,8 @@ bool RenderEngine::initializeGL() _mainCamera->setMaxFov(maxFov); } + _abuffer->initialize(); + // successful init return true; } @@ -150,8 +166,10 @@ void RenderEngine::postSynchronizationPreDraw() void RenderEngine::render() { // SGCT resets certain settings - glEnable(GL_DEPTH_TEST); - glEnable(GL_CULL_FACE); + //glEnable(GL_DEPTH_TEST); + //glEnable(GL_CULL_FACE); + glDisable(GL_DEPTH_TEST); + glDisable(GL_CULL_FACE); // setup the camera for the current frame const glm::vec3 eyePosition @@ -163,8 +181,13 @@ void RenderEngine::render() sgct::Engine::instance()->getActiveModelViewProjectionMatrix() * view); // render the scene starting from the root node + _abuffer->clear(); + _abuffer->preRender(); _sceneGraph->render(_mainCamera); + _abuffer->postRender(); + _abuffer->resolve(); +#ifndef OPENSPACE_VIDEO_EXPORT // Print some useful information on the master viewport if (sgct::Engine::instance()->isMaster()) { // Apple usually has retina screens @@ -200,6 +223,8 @@ void RenderEngine::render() sgct_text::FontManager::instance()->getFont("SGCTFont", FONT_SIZE), FONT_SIZE, FONT_SIZE * 2, "Scaling: (%.10f, %.2f)", scaling[0], scaling[1]); } +#endif + } SceneGraph* RenderEngine::sceneGraph() @@ -388,4 +413,8 @@ Camera* RenderEngine::camera() const { return _mainCamera; } +ABuffer* RenderEngine::abuffer() const { + return _abuffer; +} + } // namespace openspace diff --git a/src/rendering/volumeraycasterbox.cpp b/src/rendering/volumeraycasterbox.cpp index 3e27e0d95d..4fb33a1bde 100644 --- a/src/rendering/volumeraycasterbox.cpp +++ b/src/rendering/volumeraycasterbox.cpp @@ -61,7 +61,9 @@ bool VolumeRaycasterBox::initialize() { // ------ SETUP SHADER ----------------- OsEng.configurationManager().getValue("RaycastProgram", _boxProgram); - _MVPLocation = _boxProgram->uniformLocation("modelViewProjection"); + _MVPLocation = _boxProgram->uniformLocation("modelViewProjection"); + _modelTransformLocation = _boxProgram->uniformLocation("modelTransform"); + _typeLocation = _boxProgram->uniformLocation("volumeType"); // ------ SETUP FBO --------------------- _fbo = new FramebufferObject(); @@ -69,8 +71,6 @@ bool VolumeRaycasterBox::initialize() { // changed from getActiveXResolution to getCurrentViewportPixelCoords because // if there are more viewports in the same screen. - //size_t x = sgct::Engine::instance()->getActiveXResolution(); - //size_t y = sgct::Engine::instance()->getActiveYResolution(); int x1, xSize, y1, ySize; sgct::Engine::instance()->getActiveWindowPtr()->getCurrentViewportPixelCoords(x1, y1, xSize, ySize); size_t x = xSize; @@ -89,11 +89,13 @@ bool VolumeRaycasterBox::initialize() { return true; } -void VolumeRaycasterBox::render(const glm::mat4& MVP) { +void VolumeRaycasterBox::render(const glm::mat4& MVP,const glm::mat4& transform, int type) { GLuint activeFBO = FramebufferObject::getActiveObject(); // Save SGCTs main FBO _fbo->activate(); _boxProgram->activate(); - _boxProgram->setUniform(_MVPLocation, MVP); + _boxProgram->setUniform(_MVPLocation, MVP); + _boxProgram->setUniform(_modelTransformLocation, transform); + _boxProgram->setUniform(_typeLocation, type); sgct_core::Frustum::FrustumMode mode = sgct::Engine::instance()-> getActiveWindowPtr()-> diff --git a/src/scenegraph/scenegraph.cpp b/src/scenegraph/scenegraph.cpp index 71ffbaa5c4..9108e7bc28 100644 --- a/src/scenegraph/scenegraph.cpp +++ b/src/scenegraph/scenegraph.cpp @@ -31,6 +31,7 @@ #include #include #include +#include // ghoul includes #include "ghoul/opengl/programobject.h" @@ -48,21 +49,23 @@ #include #include +#include + #include + namespace { const std::string _loggerCat = "SceneGraph"; const std::string _moduleExtension = ".mod"; +{ + LDEBUGC("Tree", pre << node->name()); + const std::vector& children = node->children(); + for (openspace::SceneGraphNode* child : children) + printTree(child, pre + " "); +} + } namespace openspace { -void printTree(SceneGraphNode* node, std::string pre = "") -{ - LDEBUGC("Tree", pre << node->name()); - const std::vector& children = node->children(); - for (SceneGraphNode* child : children) - printTree(child, pre + " "); -} - SceneGraph::SceneGraph() : _focus(SceneGraphNode::RootNodeName) , _position(SceneGraphNode::RootNodeName) @@ -87,69 +90,110 @@ bool SceneGraph::initialize() using ghoul::opengl::ShaderObject; using ghoul::opengl::ProgramObject; - ProgramObject* po = nullptr; - if (OsEng.ref().configurationManager().hasKey("pscShader") - && OsEng.ref().configurationManager().getValue("pscShader", po)) { - LWARNING("pscShader already in ConfigurationManager, deleting."); + ShaderCreator sc = OsEng.shaderBuilder(); + ProgramObject* tmpProgram; + + typedef std::chrono::high_resolution_clock clock_; + typedef std::chrono::duration > second_; + + std::chrono::time_point beg_(clock_::now()); + + + // pscstandard + tmpProgram = sc.buildShader("pscstandard", + "${SHADERS}/pscstandard_vs.glsl", + "${SHADERS}/pscstandard_fs.glsl"); + if( ! tmpProgram) return false; + OsEng.ref().configurationManager().setValue("pscShader", tmpProgram); + + // RaycastProgram + tmpProgram = sc.buildShader("RaycastProgram", + "${SHADERS}/exitpoints.vert", + "${SHADERS}/exitpoints.frag"); + if( ! tmpProgram) return false; + OsEng.ref().configurationManager().setValue("RaycastProgram", tmpProgram); + + + // // TwoPassProgram + // tmpProgram = sc.buildShader("TwoPassProgram", + // "${SHADERS}/twopassraycaster.vert", + // "${SHADERS}/twopassraycaster.frag"); + // if( ! tmpProgram) return false; + // tmpProgram->setUniform("texBack", 0); + // tmpProgram->setUniform("texFront", 1); + // tmpProgram->setUniform("texVolume", 2); + // OsEng.ref().configurationManager().setValue("TwoPassProgram", tmpProgram); + + // Quad + tmpProgram = sc.buildShader("Quad", + "${SHADERS}/quadVert.glsl", + "${SHADERS}/quadFrag.glsl"); + if( ! tmpProgram) return false; + tmpProgram->setUniform("quadTex", 0); + OsEng.ref().configurationManager().setValue("Quad", tmpProgram); + + + + double elapsed = std::chrono::duration_cast(clock_::now() - beg_).count(); + LERROR("Time to load shaders: " << elapsed); + + /* + + auto programCreator = [] ( const std::string& name, + const std::string& vpath, + const std::string& fpath) + { + const std::string vsPath = absPath(vpath); + const std::string fsPath = absPath(fpath); + const ShaderObject::ShaderType vsType = ShaderObject::ShaderType::ShaderTypeVertex; + const ShaderObject::ShaderType fsType = ShaderObject::ShaderType::ShaderTypeFragment; + + ProgramObject* po = new ProgramObject(name); + ShaderObject* vs = new ShaderObject(vsType, vsPath, name + "Vertex"); + ShaderObject* fs = new ShaderObject(fsType, fsPath, name + "Fragment"); + po->attachObject(vs); + po->attachObject(fs); + if ( po->compileShaderObjects() && po->linkProgramObject()) + return po; + + // unsuccessful compilation, cleanup and return nullptr delete po; po = nullptr; - } + return po; + }; + // pscstandard + tmpProgram = programCreator("pscstandard", + "${SHADERS}/pscstandard_vs.glsl", + "${SHADERS}/pscstandard_fs.glsl"); + if( ! tmpProgram) return false; + OsEng.ref().configurationManager().setValue("pscShader", tmpProgram); - ShaderObject* powerscale_vs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeVertex, - absPath("${SHADERS}/pscstandard_vs.glsl"), "PS Vertex"); - ShaderObject* powerscale_fs - = new ShaderObject(ShaderObject::ShaderType::ShaderTypeFragment, - absPath("${SHADERS}/pscstandard_fs.glsl"), "PS Fragment"); + // RaycastProgram + tmpProgram = programCreator("RaycastProgram", + "${SHADERS}/exitpoints.vert", + "${SHADERS}/exitpoints.frag"); + if( ! tmpProgram) return false; + OsEng.ref().configurationManager().setValue("RaycastProgram", tmpProgram); - po = new ProgramObject; - po->attachObject(powerscale_vs); - po->attachObject(powerscale_fs); - if (!po->compileShaderObjects()) - return false; - if (!po->linkProgramObject()) - return false; + // TwoPassProgram + tmpProgram = programCreator("TwoPassProgram", + "${SHADERS}/twopassraycaster.vert", + "${SHADERS}/twopassraycaster.frag"); + if( ! tmpProgram) return false; + tmpProgram->setUniform("texBack", 0); + tmpProgram->setUniform("texFront", 1); + tmpProgram->setUniform("texVolume", 2); + OsEng.ref().configurationManager().setValue("TwoPassProgram", tmpProgram); - OsEng.ref().configurationManager().setValue("pscShader", po); - - ProgramObject* _fboProgram = new ProgramObject("RaycastProgram"); - ShaderObject* vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex, - absPath("${SHADERS}/exitpoints.vert")); - ShaderObject* fragmentShader = new ShaderObject( - ShaderObject::ShaderTypeFragment, absPath("${SHADERS}/exitpoints.frag")); - _fboProgram->attachObject(vertexShader); - _fboProgram->attachObject(fragmentShader); - _fboProgram->compileShaderObjects(); - _fboProgram->linkProgramObject(); - - ProgramObject* _twopassProgram = new ProgramObject("TwoPassProgram"); - vertexShader = new ShaderObject(ShaderObject::ShaderTypeVertex, - absPath("${SHADERS}/twopassraycaster.vert")); - fragmentShader = new ShaderObject(ShaderObject::ShaderTypeFragment, - absPath("${SHADERS}/twopassraycaster.frag")); - _twopassProgram->attachObject(vertexShader); - _twopassProgram->attachObject(fragmentShader); - _twopassProgram->compileShaderObjects(); - _twopassProgram->linkProgramObject(); - _twopassProgram->setUniform("texBack", 0); - _twopassProgram->setUniform("texFront", 1); - _twopassProgram->setUniform("texVolume", 2); - - ProgramObject* quad = new ProgramObject("Quad"); - ShaderObject* quadv = new ShaderObject(ShaderObject::ShaderTypeVertex, - absPath("${SHADERS}/quadVert.glsl")); - ShaderObject* quadf = new ShaderObject(ShaderObject::ShaderTypeFragment, - absPath("${SHADERS}/quadFrag.glsl")); - quad->attachObject(quadv); - quad->attachObject(quadf); - quad->compileShaderObjects(); - quad->linkProgramObject(); - quad->setUniform("quadTex", 0); - - OsEng.ref().configurationManager().setValue("RaycastProgram", _fboProgram); - OsEng.ref().configurationManager().setValue("TwoPassProgram", _twopassProgram); - OsEng.ref().configurationManager().setValue("Quad", quad); + // Quad + tmpProgram = programCreator("Quad", + "${SHADERS}/quadVert.glsl", + "${SHADERS}/quadFrag.glsl"); + if( ! tmpProgram) return false; + tmpProgram->setUniform("quadTex", 0); + OsEng.ref().configurationManager().setValue("Quad", tmpProgram); + */ // Initialize all nodes for (auto node : _nodes) { diff --git a/src/scenegraph/scenegraphnode.cpp b/src/scenegraph/scenegraphnode.cpp index a47037a30f..0ce7b0f9e6 100644 --- a/src/scenegraph/scenegraphnode.cpp +++ b/src/scenegraph/scenegraphnode.cpp @@ -40,6 +40,8 @@ #include #include +#include + namespace { const std::string _loggerCat = "SceneGraphNode"; } @@ -81,6 +83,53 @@ SceneGraphNode* SceneGraphNode::createFromDictionary(const ghoul::Dictionary& di result->addPropertySubOwner(result->_renderable); LDEBUG("Successfully create renderable for '" << result->name() << "'"); } + + if (dictionary.hasKey("RenderableToggle")) { + std::string val = ""; + dictionary.getValue("RenderableToggle", val); + + if(val.length() > 0) { + auto func = [result]() { + result->_renderableToggle = ! result->_renderableToggle; + }; + int key = SGCT_KEY_UNKNOWN; + + if(val.length() == 1) { + char c = std::toupper(val[0]); + key = static_cast(c); + } else if (boost::iequals(val, "left")) { + key = SGCT_KEY_LEFT; + } else if (boost::iequals(val, "right")) { + key = SGCT_KEY_RIGHT; + } else if (boost::iequals(val, "up")) { + key = SGCT_KEY_UP; + } else if (boost::iequals(val, "down")) { + key = SGCT_KEY_DOWN; + } else if (boost::iequals(val, "space")) { + key = SGCT_KEY_SPACE; + } else if (boost::iequals(val, "enter")) { + key = SGCT_KEY_ENTER; + } else if (boost::iequals(val, "backspace")) { + key = SGCT_KEY_BACKSPACE; + } else if (boost::iequals(val, "del")) { + key = SGCT_KEY_DEL; + } else if (boost::iequals(val, "delete")) { + key = SGCT_KEY_DELETE; + } else { + // Loop through all F keys + for(int i = 0; i < 25; ++i) { + std::string stringKey = "F" + std::to_string(i+1); + if(boost::iequals(val, stringKey)) { + key = SGCT_KEY_F1 + i; + } + } + } + + if(key != SGCT_KEY_UNKNOWN) + OsEng.interactionHandler().addKeyCallback(key, func); + } + } + if (dictionary.hasKey(keyEphemeris)) { ghoul::Dictionary ephemerisDictionary; dictionary.getValue(keyEphemeris, ephemerisDictionary); @@ -120,6 +169,7 @@ SceneGraphNode::SceneGraphNode() , _ephemeris(new StaticEphemeris) , _renderable(nullptr) , _renderableVisible(false) + , _renderableToggle(true) , _boundingSphereVisible(false) { } @@ -178,15 +228,18 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) _boundingSphereVisible = false; _renderableVisible = false; +#ifndef OPENSPACE_VIDEO_EXPORT // check if camera is outside the node boundingsphere if (toCamera.length() > _boundingSphere) { // check if the boudningsphere is visible before avaluating children if (!sphereInsideFrustum(thisPosition, _boundingSphere, camera)) { // the node is completely outside of the camera view, stop evaluating this // node + //LFATAL(_nodeName << " is outside of frustum"); return; } } +#endif // inside boudningsphere or parts of the sphere is visible, individual // children needs to be evaluated @@ -195,13 +248,14 @@ void SceneGraphNode::evaluate(const Camera* camera, const psc& parentPosition) // this node has an renderable if (_renderable) { // check if the renderable boundingsphere is visible - _renderableVisible = sphereInsideFrustum( - thisPosition, _renderable->getBoundingSphere(), camera); + // _renderableVisible = sphereInsideFrustum( + // thisPosition, _renderable->getBoundingSphere(), camera); + _renderableVisible = true; } // evaluate all the children, tail-recursive function(?) for (auto& child : _children) { - child->evaluate(camera, psc()); + child->evaluate(camera, thisPosition); } } @@ -213,7 +267,7 @@ void SceneGraphNode::render(const Camera* camera, const psc& parentPosition) if (!_boundingSphereVisible) { return; } - if (_renderableVisible) { + if (_renderableVisible && _renderableToggle) { // LDEBUG("Render"); _renderable->render(camera, thisPosition); } @@ -283,13 +337,22 @@ PowerScaledScalar SceneGraphNode::calculateBoundingSphere() } } _boundingSphere += maxChild; - } else { // leaf + } - // if has a renderable, use that boundingsphere - if (_renderable) - _boundingSphere += _renderable->getBoundingSphere(); + // if has a renderable, use that boundingsphere + if (_renderable ) { + PowerScaledScalar renderableBS = _renderable->getBoundingSphere(); + if(renderableBS > _boundingSphere) + _boundingSphere = renderableBS; } + + LWARNING(_nodeName << ": " << _boundingSphere); + + return _boundingSphere; +} + +PowerScaledScalar SceneGraphNode::boundingSphere() const{ return _boundingSphere; } diff --git a/src/util/factorymanager.cpp b/src/util/factorymanager.cpp index 46561078dc..4a6e71ff59 100644 --- a/src/util/factorymanager.cpp +++ b/src/util/factorymanager.cpp @@ -27,6 +27,7 @@ #include // renderables +#include #include #include #include @@ -62,6 +63,7 @@ void FactoryManager::initialize() _manager->factory()->registerClass( "RenderableVolumeExpert"); _manager->factory()->registerClass("RenderableFlare"); + _manager->factory()->registerClass("RenderableFieldlines"); // Add Ephimerides _manager->addFactory(new ghoul::TemplateFactory); @@ -102,4 +104,4 @@ void FactoryManager::addFactory(ghoul::TemplateFactoryBase* factory) { } -} // namespace openspace \ No newline at end of file +} // namespace openspace diff --git a/src/util/kameleonwrapper.cpp b/src/util/kameleonwrapper.cpp index 66db1fb2d9..ce0acd5376 100644 --- a/src/util/kameleonwrapper.cpp +++ b/src/util/kameleonwrapper.cpp @@ -31,8 +31,12 @@ #include #define _USE_MATH_DEFINES #include - +#include +#include #include +#include + +#include namespace openspace { @@ -42,23 +46,33 @@ KameleonWrapper::KameleonWrapper(const std::string& filename, Model model): _typ switch (_type) { case Model::BATSRUS: _model = new ccmc::BATSRUS(); - if(!_model) LERROR("BATSRUS:Failed to create model instance"); + if(!_model) LERROR("BATSRUS:Failed to create BATSRUS model instance"); if (_model->open(filename) != ccmc::FileReader::OK) LERROR("BATSRUS:Failed to open "+filename); _interpolator = _model->createNewInterpolator(); - if (!_interpolator) LERROR("BATSRUS:Failed to create interpolator"); + if (!_interpolator) LERROR("BATSRUS:Failed to create BATSRUS interpolator"); break; case Model::ENLIL: _model = new ccmc::ENLIL(); - if(!_model) LERROR("Failed to create model instance"); + if(!_model) LERROR("Failed to create ENLIL model instance"); if (_model->open(filename) != ccmc::FileReader::OK) LERROR("Failed to open "+filename); _interpolator = _model->createNewInterpolator(); - if (!_interpolator) LERROR("Failed to create interpolator"); + if (!_interpolator) LERROR("Failed to create ENLIL interpolator"); break; default: LERROR("No valid model type provided!"); } + + getGridVariables(_xCoordVar, _yCoordVar, _zCoordVar); + _xMin = _model->getVariableAttribute(_xCoordVar, "actual_min").getAttributeFloat(); + _xMax = _model->getVariableAttribute(_xCoordVar, "actual_max").getAttributeFloat(); + _yMin = _model->getVariableAttribute(_yCoordVar, "actual_min").getAttributeFloat(); + _yMax = _model->getVariableAttribute(_yCoordVar, "actual_max").getAttributeFloat(); + _zMin = _model->getVariableAttribute(_zCoordVar, "actual_min").getAttributeFloat(); + _zMax = _model->getVariableAttribute(_zCoordVar, "actual_max").getAttributeFloat(); + + _lastiProgress = -1; // For progressbar } KameleonWrapper::~KameleonWrapper() { @@ -70,93 +84,34 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz assert(_model && _interpolator); assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0); assert(_type == Model::ENLIL || _type == Model::BATSRUS); - LINFO("Loading CDF data"); + LINFO("Loading variable " << var << " from CDF data with a uniform sampling"); int size = outDimensions.x*outDimensions.y*outDimensions.z; float* data = new float[size]; - - // get the grid system string - std::string gridSystem = _model->getGlobalAttribute("grid_system_1").getAttributeString(); - - // remove leading and trailing brackets - gridSystem = gridSystem.substr(1,gridSystem.length()-2); - - // remove all whitespaces - gridSystem.erase(remove_if(gridSystem.begin(), gridSystem.end(), isspace), gridSystem.end()); - - // replace all comma signs with whitespaces - std::replace( gridSystem.begin(), gridSystem.end(), ',', ' '); - - // tokenize - std::istringstream iss(gridSystem); - std::vector tokens{std::istream_iterator{iss},std::istream_iterator{}}; - - // validate - if (tokens.size() != 3) { - LERROR("Something went wrong"); - delete[] data; - return 0; - } + double* doubleData = new double[size]; - std::string v_x = tokens.at(0), v_y = tokens.at(1), v_z = tokens.at(2); - /* - for(auto t: tokens) - LDEBUG("t: " << t); - */ - /* - LERROR("getVariableAttributeNames"); - std::vector attributeNames = _model->getVariableAttributeNames(); - for(auto name : attributeNames) - LDEBUG(name); - */ - //_model->getVa + double varMin = _model->getVariableAttribute(var, "actual_min").getAttributeFloat(); + double varMax = _model->getVariableAttribute(var, "actual_max").getAttributeFloat(); + + double stepX = (_xMax-_xMin)/(static_cast(outDimensions.x)); + double stepY = (_yMax-_yMin)/(static_cast(outDimensions.y)); + double stepZ = (_zMax-_zMin)/(static_cast(outDimensions.z)); - //auto fan = std::find(attributeNames.begin(), attributeNames.end(), ""); - - - //KameleonWrapper (Debug) grid_system_1 - //KameleonWrapper (Debug) grid_1_type - - LDEBUG("Using coordinate system: " << v_x << ", " << v_y << ", " << v_z); - - float xMin = _model->getVariableAttribute(v_x, "actual_min").getAttributeFloat(); - float xMax = _model->getVariableAttribute(v_x, "actual_max").getAttributeFloat(); - float yMin = _model->getVariableAttribute(v_y, "actual_min").getAttributeFloat(); - float yMax = _model->getVariableAttribute(v_y, "actual_max").getAttributeFloat(); - float zMin = _model->getVariableAttribute(v_z, "actual_min").getAttributeFloat(); - float zMax = _model->getVariableAttribute(v_z, "actual_max").getAttributeFloat(); - float varMin = _model->getVariableAttribute(var, "actual_min").getAttributeFloat(); - float varMax = _model->getVariableAttribute(var, "actual_max").getAttributeFloat(); - - float stepX = (xMax-xMin)/(static_cast(outDimensions.x)); - float stepY = (yMax-yMin)/(static_cast(outDimensions.y)); - float stepZ = (zMax-zMin)/(static_cast(outDimensions.z)); - - - LDEBUG(v_x << "Min: " << xMin); - LDEBUG(v_x << "Max: " << xMax); - LDEBUG(v_y << "Min: " << yMin); - LDEBUG(v_y << "Max: " << yMax); - LDEBUG(v_z << "Min: " << zMin); - LDEBUG(v_z << "Max: " << zMax); LDEBUG(var << "Min: " << varMin); LDEBUG(var << "Max: " << varMax); + + // HISTOGRAM + const int bins = 200; + const float truncLim = 0.9; + std::vector histogram (bins,0); + auto mapToHistogram = [varMin, varMax, bins](double val) { + double zeroToOne = (val-varMin)/(varMax-varMin); + zeroToOne *= static_cast(bins); + return static_cast(zeroToOne); + }; - int barWidth = 70; - int lastiProgress = -1; for (int x = 0; x < outDimensions.x; ++x) { - float progress = static_cast(x) / static_cast(outDimensions.x-1); - int iprogress = static_cast(progress*100.0f); - if (iprogress != lastiProgress) { - - int pos = barWidth * progress; - int eqWidth = pos+1; - int spWidth = barWidth - pos + 2; - std::cout << "[" << std::setfill('=') << std::setw(eqWidth) - << ">" << std::setfill(' ') << std::setw(spWidth) - << "] " << iprogress << " % \r" << std::flush; - } - lastiProgress = iprogress; + progressBar(x, outDimensions.x); for (int y = 0; y < outDimensions.y; ++y) { for (int z = 0; z < outDimensions.z; ++z) { @@ -164,46 +119,40 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz int index = x + y*outDimensions.x + z*outDimensions.x*outDimensions.y; if(_type == Model::BATSRUS) { - float xPos = xMin + stepX*x; - float yPos = yMin + stepY*y; - float zPos = zMin + stepZ*z; + double xPos = _xMin + stepX*x; + double yPos = _yMin + stepY*y; + double zPos = _zMin + stepZ*z; // get interpolated data value for (xPos, yPos, zPos) - float value = _interpolator->interpolate(var, xPos, yPos, zPos); - - // scale to [0,1] - data[index] = (value-varMin)/(varMax-varMin); + // swap yPos and zPos because model has Z as up + double value = _interpolator->interpolate(var, xPos, zPos, yPos); + doubleData[index] = value; + histogram[mapToHistogram(value)]++; + } else if (_type == Model::ENLIL) { - //LDEBUG("data: " << theval); - - // Calculate array index - //unsigned int index = r + theta*xDim_ + phi*xDim_*yDim_; // Put r in the [0..sqrt(3)] range - float rNorm = sqrt(3.0)*(float)x/(float)(outDimensions.x-1); + double rNorm = sqrt(3.0)*(double)x/(double)(outDimensions.x-1); // Put theta in the [0..PI] range - float thetaNorm = M_PI*(float)y/(float)(outDimensions.y-1); + double thetaNorm = M_PI*(double)y/(double)(outDimensions.y-1); // Put phi in the [0..2PI] range - float phiNorm = 2.0*M_PI*(float)z/(float)(outDimensions.z-1); + double phiNorm = 2.0*M_PI*(double)z/(double)(outDimensions.z-1); // Go to physical coordinates before sampling - float rPh = xMin + rNorm*(xMax-xMin); - float thetaPh = thetaNorm; - //phi range needs to be mapped to the slightly different - // model range to avoid gaps in the data - // Subtract a small term to avoid rounding errors when comparing - // to phiMax. - float phiPh = zMin + phiNorm/(2.0*M_PI)*(zMax-zMin-0.000001); + double rPh = _xMin + rNorm*(_xMax-_xMin); + double thetaPh = thetaNorm; + // phi range needs to be mapped to the slightly different model + // range to avoid gaps in the data Subtract a small term to + // avoid rounding errors when comparing to phiMax. + double phiPh = _zMin + phiNorm/(2.0*M_PI)*(_zMax-_zMin-0.000001); - // Hardcoded variables (rho or rho - rho_back) - // TODO Don't hardcode, make more flexible - float varValue = 0.f;//, rho_back = 0.f, diff = 0.f; + double value = 0.0; // See if sample point is inside domain - if (rPh < xMin || rPh > xMax || thetaPh < yMin || - thetaPh > yMax || phiPh < zMin || phiPh > zMax) { - if (phiPh > zMax) { + if (rPh < _xMin || rPh > _xMax || thetaPh < _yMin || + thetaPh > _yMax || phiPh < _zMin || phiPh > _zMax) { + if (phiPh > _zMax) { std::cout << "Warning: There might be a gap in the data\n"; } // Leave values at zero if outside domain @@ -217,23 +166,12 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz // Convert from [0, 2pi] rad to [0, 360] degrees phiPh = phiPh*180.f/M_PI; // Sample - varValue = _interpolator->interpolate(var, rPh, thetaPh, phiPh); - //rho_back = _interpolator->interpolate("rho-back",rPh,thetaPh,phiPh); - - // Calculate difference (or just rho) - //diff = rho; - //diff = rho - rho_back; - - // Clamp to 0 - //if (diff < 0.f) diff = 0.f; + value = _interpolator->interpolate(var, rPh, thetaPh, phiPh); + // value = _interpolator->interpolate(var, rPh, phiPh, thetaPh); } - //if(var < 0.0f) var = 0.0f; - //data[index] = var; - data[index] = (varValue-varMin)/(varMax-varMin); - //LDEBUG("varValue:" << varValue); - //LDEBUG("data[index]:" << data[index]); - //data[index] = var; - //data[index] = diff; + + doubleData[index] = value; + histogram[mapToHistogram(value)]++; } } } @@ -241,8 +179,450 @@ float* KameleonWrapper::getUniformSampledValues(const std::string& var, glm::siz std::cout << std::endl; LINFO("Done!"); + // for (int i = 0; i < outDimensions.x * outDimensions.y * outDimensions.z; ++i) + // { + // std::cout << std::setfill(' ') << std::setw(15) << doubleData[i] << ", "; + // if(i % 10 == 0) + // std::cout << std::endl; + // } + // + // for(int i = 0; i < bins-1; ++i) { + // // sum += histogram[i]; + // // if(sum + histogram[i+1] > sumuntil) { + // // stop = i; + // // LDEBUG("===================="); + // // break; + // // } + // LDEBUG("histogram[" << i << "]: " << histogram[i]); + // } + + int sum = 0; + int stop; + const int sumuntil = size * truncLim; + for(int i = 0; i < bins; ++i) { + sum += histogram[i]; + if(sum > sumuntil) { + stop = i; + // LDEBUG("===================="); + break; + } + // LDEBUG("histogram[" << i << "]: " << histogram[i]); + } + + double dist = varMax - varMin; + dist = (dist / static_cast(bins)) * static_cast(stop); + + varMax = varMin + dist; + LDEBUG(var << "Min: " << varMin); + LDEBUG(var << "Max: " << varMax); + for(int i = 0; i < size; ++i) { + double normalizedVal = (doubleData[i]-varMin)/(varMax-varMin); + + data[i] = static_cast(glm::clamp(normalizedVal, 0.0, 1.0)); + if(data[i] < 0.0) { + LERROR("Datapoint " << i << " less than 0"); + } + if(data[i] > 1.0) { + LERROR("Datapoint " << i << " more than 1"); + } + } + + // for(int i = 0; i < size; ++i) { + // double normalizedVal = (doubleData[i]-varMin)/(varMax-varMin); + // // data[i] = static_cast(glm::clamp(normalizedVal, 0.0, 1.0)); + // data[i] = static_cast(normalizedVal); + // } + + delete[] doubleData; return data; } -} // namespace openspace +float* KameleonWrapper::getUniformSampledVectorValues(const std::string& xVar, const std::string& yVar, const std::string& zVar, glm::size3_t outDimensions) { + assert(_model && _interpolator); + assert(outDimensions.x > 0 && outDimensions.y > 0 && outDimensions.z > 0); + assert(_type == Model::ENLIL || _type == Model::BATSRUS); + LINFO("Loading variables " << xVar << " " << yVar << " " << zVar << " from CDF data with a uniform sampling"); + int channels = 4; + int size = channels*outDimensions.x*outDimensions.y*outDimensions.z; + float* data = new float[size]; + + float varXMin = _model->getVariableAttribute(xVar, "actual_min").getAttributeFloat(); + float varXMax = _model->getVariableAttribute(xVar, "actual_max").getAttributeFloat(); + float varYMin = _model->getVariableAttribute(yVar, "actual_min").getAttributeFloat(); + float varYMax = _model->getVariableAttribute(yVar, "actual_max").getAttributeFloat(); + float varZMin = _model->getVariableAttribute(zVar, "actual_min").getAttributeFloat(); + float varZMax = _model->getVariableAttribute(zVar, "actual_max").getAttributeFloat(); + + float stepX = (_xMax-_xMin)/(static_cast(outDimensions.x)); + float stepY = (_yMax-_yMin)/(static_cast(outDimensions.y)); + float stepZ = (_zMax-_zMin)/(static_cast(outDimensions.z)); + + LDEBUG(xVar << "Min: " << varXMin); + LDEBUG(xVar << "Max: " << varXMax); + LDEBUG(yVar << "Min: " << varYMin); + LDEBUG(yVar << "Max: " << varYMax); + LDEBUG(zVar << "Min: " << varZMin); + LDEBUG(zVar << "Max: " << varZMax); + + for (int x = 0; x < outDimensions.x; ++x) { + progressBar(x, outDimensions.x); + + for (int y = 0; y < outDimensions.y; ++y) { + for (int z = 0; z < outDimensions.z; ++z) { + + int index = x*channels + y*channels*outDimensions.x + z*channels*outDimensions.x*outDimensions.y; + + if(_type == Model::BATSRUS) { + float xPos = _xMin + stepX*x; + float yPos = _yMin + stepY*y; + float zPos = _zMin + stepZ*z; + + // get interpolated data value for (xPos, yPos, zPos) + float xValue = _interpolator->interpolate(xVar, xPos, yPos, zPos); + float yValue = _interpolator->interpolate(yVar, xPos, yPos, zPos); + float zValue = _interpolator->interpolate(zVar, xPos, yPos, zPos); + + // scale to [0,1] + data[index] = (xValue-varXMin)/(varXMax-varXMin); // R + data[index + 1] = (yValue-varYMin)/(varYMax-varYMin); // G + data[index + 2] = (zValue-varZMin)/(varZMax-varZMin); // B + data[index + 3] = 1.0; // GL_RGB refuses to work. Workaround by doing a GL_RGBA with hardcoded alpha + } else { + LERROR("Only BATSRUS supported for getUniformSampledVectorValues (for now)"); + return data; + } + } + } + } + std::cout << std::endl; + LINFO("Done!"); + + return data; +} + +std::vector > KameleonWrapper::getClassifiedFieldLines( + const std::string& xVar, const std::string& yVar, + const std::string& zVar, std::vector seedPoints, + float stepSize ) { + assert(_model && _interpolator); + assert(_type == Model::ENLIL || _type == Model::BATSRUS); + LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); + + std::vector fLine, bLine; + std::vector > fieldLines; + glm::vec4 color; + FieldlineEnd forwardEnd, backEnd; + + if (_type == Model::BATSRUS) { + for (glm::vec3 seedPoint : seedPoints) { + fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::FORWARD, forwardEnd); + bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::BACK, backEnd); + + bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend()); + + // classify + color = classifyFieldline(forwardEnd, backEnd); + + // write colors + std::vector line; + for (glm::vec3 position : bLine) { + line.push_back(LinePoint(position, color)); + } + + fieldLines.push_back(line); + } + } else { + LERROR("Fieldlines are only supported for BATSRUS model"); + } + + return fieldLines; +} + +std::vector > KameleonWrapper::getFieldLines( + const std::string& xVar, const std::string& yVar, + const std::string& zVar, std::vector seedPoints, + float stepSize, glm::vec4 color ) { + assert(_model && _interpolator); + assert(_type == Model::ENLIL || _type == Model::BATSRUS); + LINFO("Creating " << seedPoints.size() << " fieldlines from variables " << xVar << " " << yVar << " " << zVar); + + std::vector fLine, bLine; + std::vector > fieldLines; + FieldlineEnd forwardEnd, backEnd; + + if (_type == Model::BATSRUS) { + for (glm::vec3 seedPoint : seedPoints) { + fLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::FORWARD, forwardEnd); + bLine = traceCartesianFieldline(xVar, yVar, zVar, seedPoint, stepSize, TraceDirection::BACK, backEnd); + + bLine.insert(bLine.begin(), fLine.rbegin(), fLine.rend()); + + // write colors + std::vector line; + for (glm::vec3 position : bLine) { + line.push_back(LinePoint(position, color)); + } + + fieldLines.push_back(line); + } + } else { + LERROR("Fieldlines are only supported for BATSRUS model"); + } + + return fieldLines; +} + +std::vector > KameleonWrapper::getLorentzTrajectories( + std::vector seedPoints, glm::vec4 color, float stepsize) { + LINFO("Creating " << seedPoints.size() << " Lorentz force trajectories"); + + std::vector > trajectories; + std::vector plusTraj, minusTraj; + + for (auto seedPoint : seedPoints) { + plusTraj = traceLorentzTrajectory(seedPoint, stepsize, 1.0); + minusTraj = traceLorentzTrajectory(seedPoint, stepsize, -1.0); + + minusTraj.insert(minusTraj.begin(), plusTraj.rbegin(), plusTraj.rend()); + + // write colors + std::vector trajectory; + for (glm::vec3 position : minusTraj) { + trajectory.push_back(LinePoint(position, color)); + } + trajectories.push_back(trajectory); + } + + return trajectories; +} + +glm::vec3 KameleonWrapper::getModelBarycenterOffset() { + glm::vec3 offset; + offset.x = _xMin+(std::abs(_xMin)+std::abs(_xMax))/2.0f; + offset.y = _yMin+(std::abs(_yMin)+std::abs(_yMax))/2.0f; + offset.z = _zMin+(std::abs(_zMin)+std::abs(_zMax))/2.0f; + return offset; +} + +std::vector KameleonWrapper::traceCartesianFieldline( + const std::string& xVar, const std::string& yVar, + const std::string& zVar, glm::vec3 seedPoint, + float stepSize, TraceDirection direction, FieldlineEnd& end) { + + glm::vec3 color, pos, k1, k2, k3, k4; + std::vector line; + float stepX, stepY, stepZ; + int numSteps = 0, maxSteps = 5000; + pos = seedPoint; + + _model->loadVariable(xVar); + _model->loadVariable(yVar); + _model->loadVariable(zVar); + + long int xID = _model->getVariableID(xVar); + long int yID = _model->getVariableID(yVar); + long int zID = _model->getVariableID(zVar); + + // While we are inside the models boundries and not inside earth + while ((pos.x < _xMax && pos.x > _xMin && pos.y < _yMax && pos.y > _yMin && + pos.z < _zMax && pos.z > _zMin) && !(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) { + + // Save position. Model has +Z as up + line.push_back(glm::vec3(pos.x, pos.z, pos.y)); + + // Calculate new position with Runge-Kutta 4th order + k1.x = _interpolator->interpolate(xID, pos.x, pos.y, pos.z, stepX, stepY, stepZ); + k1.y = _interpolator->interpolate(yID, pos.x, pos.y, pos.z); + k1.z = _interpolator->interpolate(zID, pos.x, pos.y, pos.z); + k1 = (float)direction*glm::normalize(k1); + stepX=stepX*stepSize, stepY=stepY*stepSize, stepZ=stepZ*stepSize; + k2.x = _interpolator->interpolate(xID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2.y = _interpolator->interpolate(yID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2.z = _interpolator->interpolate(zID, pos.x+(stepX/2.0)*k1.x, pos.y+(stepY/2.0)*k1.y, pos.z+(stepZ/2.0)*k1.z); + k2 = (float)direction*glm::normalize(k2); + k3.x = _interpolator->interpolate(xID, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3.y = _interpolator->interpolate(yID, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3.z = _interpolator->interpolate(zID, pos.x+(stepX/2.0)*k2.x, pos.y+(stepY/2.0)*k2.y, pos.z+(stepZ/2.0)*k2.z); + k3 = (float)direction*glm::normalize(k3); + k4.x = _interpolator->interpolate(xID, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4.y = _interpolator->interpolate(yID, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4.z = _interpolator->interpolate(zID, pos.x+stepX*k3.x, pos.y+stepY*k3.y, pos.z+stepZ*k3.z); + k4 = (float)direction*glm::normalize(k4); + pos.x = pos.x + (stepX/6.0)*(k1.x + 2.0*k2.x + 2.0*k3.x + k4.x); + pos.y = pos.y + (stepY/6.0)*(k1.y + 2.0*k2.y + 2.0*k3.y + k4.y); + pos.z = pos.z + (stepZ/6.0)*(k1.z + 2.0*k2.z + 2.0*k3.z + k4.z); + + ++numSteps; + if (numSteps > maxSteps) { + LDEBUG("Max number of steps taken (" << maxSteps <<")"); + break; + } + } + // Save last position. Model has +Z as up + line.push_back(glm::vec3(pos.x, pos.z, pos.y)); + + if (pos.z > 0.0 && (pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) + end = FieldlineEnd::NORTH; + else if (pos.z < 0.0 && (pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) + end = FieldlineEnd::SOUTH; + else + end = FieldlineEnd::OUT; + + return line; +} + +std::vector KameleonWrapper::traceLorentzTrajectory(glm::vec3 seedPoint, + float stepsize, float eCharge) { + glm::vec3 B, E, v0, k1, k2, k3, k4, sPos, tmpV; + float stepX = stepsize, stepY = stepsize, stepZ = stepsize; + + long int bxID = _model->getVariableID("bx"); + long int byID = _model->getVariableID("by"); + long int bzID = _model->getVariableID("bz"); + long int jxID = _model->getVariableID("jx"); + long int jyID = _model->getVariableID("jy"); + long int jzID = _model->getVariableID("jz"); + + std::vector trajectory; + glm::vec3 pos = seedPoint; + int numSteps = 0, maxSteps = 5000; + v0.x = _interpolator->interpolate("ux", pos.x, pos.y, pos.z); + v0.y = _interpolator->interpolate("uy", pos.x, pos.y, pos.z); + v0.z = _interpolator->interpolate("uz", pos.x, pos.y, pos.z); + v0 = glm::normalize(v0); + + // While we are inside the models boundries and not inside earth + while ((pos.x < _xMax && pos.x > _xMin && pos.y < _yMax && pos.y > _yMin && + pos.z < _zMax && pos.z > _zMin) && !(pos.x*pos.x + pos.y*pos.y + pos.z*pos.z < 1.0)) { + + // Save position. Model has +Z as up + trajectory.push_back(glm::vec3(pos.x, pos.z, pos.y)); + + // Calculate new position with Lorentz force quation and Runge-Kutta 4th order + B.x = _interpolator->interpolate(bxID, pos.x, pos.y, pos.z); + B.y = _interpolator->interpolate(byID, pos.x, pos.y, pos.z); + B.z = _interpolator->interpolate(bzID, pos.x, pos.y, pos.z); + E.x = _interpolator->interpolate(jxID, pos.x, pos.y, pos.z); + E.y = _interpolator->interpolate(jyID, pos.x, pos.y, pos.z); + E.z = _interpolator->interpolate(jzID, pos.x, pos.y, pos.z); + k1 = eCharge*(E + glm::cross(v0, B)); + k1 = glm::normalize(k1); + + sPos = glm::vec3( pos.x+(stepX/2.0)*v0.x+(stepX*stepX/8.0)*k1.x, + pos.y+(stepY/2.0)*v0.y+(stepY*stepY/8.0)*k1.y, + pos.z+(stepZ/2.0)*v0.z+(stepZ*stepZ/8.0)*k1.z); + B.x = _interpolator->interpolate(bxID, sPos.x, sPos.y, sPos.z); + B.y = _interpolator->interpolate(byID, sPos.x, sPos.y, sPos.z); + B.z = _interpolator->interpolate(bzID, sPos.x, sPos.y, sPos.z); + E.x = _interpolator->interpolate(jxID, sPos.x, sPos.y, sPos.z); + E.y = _interpolator->interpolate(jyID, sPos.x, sPos.y, sPos.z); + E.z = _interpolator->interpolate(jzID, sPos.x, sPos.y, sPos.z); + tmpV = v0+(stepX/2.0f)*k1; + k2 = eCharge*(E + glm::cross(tmpV, B)); + k2 = glm::normalize(k2); + + B.x = _interpolator->interpolate(bxID, sPos.x, sPos.y, sPos.z); + B.y = _interpolator->interpolate(byID, sPos.x, sPos.y, sPos.z); + B.z = _interpolator->interpolate(bzID, sPos.x, sPos.y, sPos.z); + E.x = _interpolator->interpolate(jxID, sPos.x, sPos.y, sPos.z); + E.y = _interpolator->interpolate(jyID, sPos.x, sPos.y, sPos.z); + E.z = _interpolator->interpolate(jzID, sPos.x, sPos.y, sPos.z); + tmpV = v0+(stepX/2.0f)*k2; + k3 = eCharge*(E + glm::cross(tmpV, B)); + k3 = glm::normalize(k3); + + sPos = glm::vec3( pos.x+stepX*v0.x+(stepX*stepX/2.0)*k1.x, + pos.y+stepY*v0.y+(stepY*stepY/2.0)*k1.y, + pos.z+stepZ*v0.z+(stepZ*stepZ/2.0)*k1.z); + B.x = _interpolator->interpolate(bxID, sPos.x, sPos.y, sPos.z); + B.y = _interpolator->interpolate(byID, sPos.x, sPos.y, sPos.z); + B.z = _interpolator->interpolate(bzID, sPos.x, sPos.y, sPos.z); + E.x = _interpolator->interpolate(jxID, sPos.x, sPos.y, sPos.z); + E.y = _interpolator->interpolate(jyID, sPos.x, sPos.y, sPos.z); + E.z = _interpolator->interpolate(jzID, sPos.x, sPos.y, sPos.z); + tmpV = v0+stepX*k3; + k4 = eCharge*(E + glm::cross(tmpV, B)); + k4 = glm::normalize(k4); + + pos.x = pos.x + stepX*v0.x + (stepX*stepX/6.0)*(k1.x + k2.x + k3.x); + pos.y = pos.y + stepY*v0.y + (stepY*stepY/6.0)*(k1.y + k2.y + k3.y); + pos.z = pos.z + stepZ*v0.z + (stepZ*stepZ/6.0)*(k1.z + k2.z + k3.z); + + v0.x = v0.x + (stepX/6.0)*(k1.x + 2.0*k2.x + 2.0*k3.x + k4.z); + v0.y = v0.y + (stepY/6.0)*(k1.y + 2.0*k2.y + 2.0*k3.y + k4.y); + v0.z = v0.z + (stepZ/6.0)*(k1.z + 2.0*k2.z + 2.0*k3.z + k4.z); + + ++numSteps; + if (numSteps > maxSteps) { + LDEBUG("Max number of steps taken (" << maxSteps <<")"); + break; + } + } + // Save last position. Model has +Z as up + trajectory.push_back(glm::vec3(pos.x, pos.z, pos.y)); + return trajectory; +} + +void KameleonWrapper::getGridVariables(std::string& x, std::string& y, std::string& z) { + // get the grid system string + std::string gridSystem = _model->getGlobalAttribute("grid_system_1").getAttributeString(); + + // remove leading and trailing brackets + gridSystem = gridSystem.substr(1,gridSystem.length()-2); + + // remove all whitespaces + gridSystem.erase(remove_if(gridSystem.begin(), gridSystem.end(), isspace), gridSystem.end()); + + // replace all comma signs with whitespaces + std::replace( gridSystem.begin(), gridSystem.end(), ',', ' '); + + // tokenize + std::istringstream iss(gridSystem); + std::vector tokens{std::istream_iterator{iss},std::istream_iterator{}}; + + // validate + if (tokens.size() != 3) LERROR("Something went wrong"); + + x = tokens.at(0); + y = tokens.at(1); + z = tokens.at(2); +} + +void KameleonWrapper::progressBar(int current, int end) { + float progress = static_cast(current) / static_cast(end-1); + int iprogress = static_cast(progress*100.0f); + int barWidth = 70; + if (iprogress != _lastiProgress) { + int pos = barWidth * progress; + int eqWidth = pos+1; + int spWidth = barWidth - pos + 2; + std::cout << "[" << std::setfill('=') << std::setw(eqWidth) + << ">" << std::setfill(' ') << std::setw(spWidth) + << "] " << iprogress << " % \r" << std::flush; + } + _lastiProgress = iprogress; +} + +glm::vec4 KameleonWrapper::classifyFieldline(FieldlineEnd fEnd, FieldlineEnd bEnd) { + glm::vec4 color; + if ( (fEnd == FieldlineEnd::NORTH || fEnd == FieldlineEnd::SOUTH) + && (bEnd == FieldlineEnd::NORTH || bEnd == FieldlineEnd::SOUTH)) { + // closed + color = glm::vec4(1.0, 0.0, 0.0, 1.0); + } else if ((fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::NORTH) + || (bEnd == FieldlineEnd::OUT && fEnd == FieldlineEnd::NORTH)) { + // north + color = glm::vec4(1.0, 1.0, 0.0, 1.0); + } else if ((fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::SOUTH) + || (bEnd == FieldlineEnd::OUT && fEnd == FieldlineEnd::SOUTH)) { + // south + color = glm::vec4(0.0, 1.0, 0.0, 1.0); + } else if (fEnd == FieldlineEnd::OUT && bEnd == FieldlineEnd::OUT) { + // solar wind + color = glm::vec4(0.0, 0.0, 1.0, 1.0); + } + return color; +} + +} // namespace openspace diff --git a/src/util/shadercreator.cpp b/src/util/shadercreator.cpp new file mode 100644 index 0000000000..b4b1b0d930 --- /dev/null +++ b/src/util/shadercreator.cpp @@ -0,0 +1,180 @@ +/***************************************************************************************** + * * + * OpenSpace * + * * + * Copyright (c) 2014 * + * * + * 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 + +#include +#include +#include + +#include +#include +#include +// #include +// #include + +using ghoul::opengl::ProgramObject; +using ghoul::opengl::ShaderObject; + +namespace { + const std::string _loggerCat = "ShaderCreator"; + const std::string defaultSourceFileExtension = "OpenSpaceGenerated.glsl"; + const std::string separator = "//=====================================================================\n"; + const ShaderObject::ShaderType vsType = ShaderObject::ShaderType::ShaderTypeVertex; + const ShaderObject::ShaderType fsType = ShaderObject::ShaderType::ShaderTypeFragment; +} + +namespace openspace { +ShaderCreator::ShaderCreator(): + _createSourceFile(false), + _sourceFileExtension(defaultSourceFileExtension), + _sourceFileHeader(""), + _maxDepth(2) +{ + +} + +ShaderCreator::~ShaderCreator() { + +} + +void ShaderCreator::createSourceFile(bool b) { + _createSourceFile = b; +} + +void ShaderCreator::sourceFileExtension(const std::string& extension) { + if(extension != "") { + _sourceFileExtension = extension; + } +} + +void ShaderCreator::sourceFileHeader(const std::string& header) { + _sourceFileHeader = header; +} + +ghoul::opengl::ProgramObject* ShaderCreator::buildShader( + const std::string& name, const std::string& vpath, const std::string& fpath) +{ + std::string vsPath = absPath(vpath); + std::string fsPath = absPath(fpath); + + if( ! FileSys.fileExists(vsPath)) + return nullptr; + if( ! FileSys.fileExists(fsPath)) + return nullptr; + + if(_createSourceFile) { + _generateSource(vsPath); + _generateSource(fsPath); + + vsPath = _generateFilename(vsPath); + fsPath = _generateFilename(fsPath); + } + + ProgramObject* po = new ProgramObject(name); + ShaderObject* vs = new ShaderObject(vsType, vsPath, name + " Vertex"); + ShaderObject* fs = new ShaderObject(fsType, fsPath, name + " Fragment"); + po->attachObject(vs); + po->attachObject(fs); + if ( po->compileShaderObjects() && po->linkProgramObject()) + return po; + + // unsuccessful compilation, cleanup and return nullptr + delete po; + po = nullptr; + return po; +} + +void ShaderCreator::_generateSource(const std::string& filename) { + std::string generatedSource = ""; + if(_sourceFileHeader != "") + generatedSource += separator + "// HEADER\n" + separator + _sourceFileHeader + "\n"; + generatedSource += _loadSource(filename); + + std::ofstream of(_generateFilename(filename)); + of << generatedSource; + of.close(); +} + +std::string ShaderCreator::_loadSource(const std::string& filename, unsigned int depth) { + std::string contents = "", line; + std::ifstream f(filename); + + // Pre-allocate memory so the return string doesn't have to resize too often + // f.seekg( 0, std::ios::end ); + // unsigned int fsize = f.tellg(); + // f.seekg( 0); + // contents.reserve(fsize*3); + // line.reserve(fsize*3); + + contents += "\n"; + contents += separator; + contents += "// Filename: " + filename + "\n"; + // contents += "// Size: " + std::to_string(fsize) + "\n"; + contents += separator; + if(depth > _maxDepth) { + contents += "// TOO DEEP"; + return contents; + } + + if( ! FileSys.fileExists(filename)){ + contents += "// FILE NOT FOUND\n"; + return contents; + } + + boost::regex e1(R"(^\s*#include \"(.+)\"\s*)"); + boost::regex e2(R"(^\s*#include <(.+)>\s*)"); + while(std::getline(f, line)) { + boost::smatch m; + if(boost::regex_search(line, m, e1)) { + std::string includeFilename = m[1]; + includeFilename = filename.substr(0, filename.find_last_of("/")+1) + includeFilename; + line = _loadSource(includeFilename, depth + 1); + } else if(boost::regex_search(line, m, e2)) { + std::string includeFilename = m[1]; + line = _loadSource(absPath(includeFilename), depth + 1); + } + + contents += line + "\n"; + } + f.close(); + + return contents; +} + +std::string ShaderCreator::_generateFilename(const std::string& filename) { + // If way of confirming and creating a directory this could be a good solution + // to avoid cluttering in folders + // if(_cacheFolder != "") { + // size_t delimiter = filename.find_last_of("/"); + // std::string file = filename.substr(delimiter+1, filename.length() - delimiter); + // std::string path = filename.substr(0, filename.find_last_of("/")); + + // return path + "/" + _cacheFolder + "/" + file + "." + _sourceFileExtension; + // } + + return filename + "." + _sourceFileExtension; +} + +} \ No newline at end of file