Merge branch 'master' into thesis/2019/camera-paths

This commit is contained in:
Emma Broman
2020-11-05 11:27:36 +01:00
12 changed files with 317 additions and 64 deletions

View File

@@ -18,6 +18,7 @@ asset.require('scene/solarsystem/dwarf_planets/pluto/charon/default_layers')
asset.require('scene/milkyway/milkyway/volume')
asset.require('scene/milkyway/constellations/constellation_art')
asset.require('scene/milkyway/constellations/constellation_keybinds')
asset.require('scene/milkyway/objects/orionnebula/orionnebula')
asset.require('util/launcher_images')
local assetHelper = asset.require('util/asset_helper')

View File

@@ -550,6 +550,6 @@ asset.meta = {
License = "AMNH Digital Universe",
Identifiers = {"RadioSphere", "OortSphere", "EclipticSphere", "EclipticSphereLabels",
"Equatorial", "EquatorialSphereLabels", "GalacticSphere", "GalacticSphereLabels",
"1ldGrid", "1lmGrid", "1lyGrid", "10lyGrid", "100lyGrid", "1klyGrid" "10klyGrid",
"1ldGrid", "1lmGrid", "1lyGrid", "10lyGrid", "100lyGrid", "1klyGrid", "10klyGrid",
"100klyGrid", "1MlyGrid", "10MlyGrid", "100MlyGrid", "20GlyGrid"}
}

View File

@@ -16,7 +16,7 @@ local OrionClusterStars = {
Type = "RenderableStars",
File = sync .. "/oricluster.speck",
Texture = sync .. "/halo.png",
Texture = sync .. "/colorbv.cmap",
ColorMap = sync .. "/colorbv.cmap",
MagnitudeExponent = 5.02,
SizeComposition = "Distance Modulus",
RenderMethod = "Texture Based"

View File

@@ -54,8 +54,9 @@ local OrionNebulaModel = {
Opacity = 1.0,
DisableFaceCulling = false,
SpecularIntensity = 0.0,
AmbientIntensity = 0.45,
DiffuseIntensity = 0.0,
AmbientIntensity = 0.0,
DiffuseIntensity = 1.0,
--PerformShading = false,
RotationVector = { 0.000000, 22.300000, 0.000000 },
LightSources = LIGHTS;
},
@@ -85,8 +86,9 @@ local OrionNebulaShocksModel = {
Opacity = 1.0,
DisableFaceCulling = false,
SpecularIntensity = 0.0,
AmbientIntensity = 0.19,
DiffuseIntensity = 0.4,
AmbientIntensity = 0.0,
DiffuseIntensity = 1.0,
--PerformShading = false,
RotationVector = { 0.000000, 22.300000, 0.000000 },
LightSources = LIGHTS;
},
@@ -116,8 +118,9 @@ local OrionNebulaProplydsModel = {
Opacity = 1.0,
DisableFaceCulling = false,
SpecularIntensity = 0.0,
AmbientIntensity = 1.0,
AmbientIntensity = 0.0,
DiffuseIntensity = 1.0,
--PerformShading = false,
RotationVector = { 0.000000, 22.300000, 0.000000 },
LightSources = LIGHTS;
},

View File

@@ -137,11 +137,10 @@ glm::vec3 SceneGraphLightSource::directionViewSpace(const RenderData& renderData
const glm::dvec3 renderNodePosition = renderData.modelTransform.translation;
const glm::dvec3 lightDirectionViewSpace = renderData.camera.viewRotationMatrix() *
glm::dvec4((lightPosition - renderNodePosition), 1.0);
const glm::dvec3 viewSpace = glm::dvec3(renderData.camera.combinedViewMatrix() *
glm::dvec4((lightPosition - renderNodePosition), 1.0));
return glm::normalize(lightDirectionViewSpace);
return glm::normalize(viewSpace);
}
} // namespace openspace

View File

@@ -34,11 +34,11 @@
#include <openspace/util/updatestructures.h>
#include <openspace/scene/scene.h>
#include <openspace/scene/lightsource.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/misc/invariants.h>
#include <ghoul/misc/profiling.h>
#include <ghoul/opengl/openglstatecache.h>
#include <ghoul/opengl/programobject.h>
#include <ghoul/opengl/textureunit.h>
@@ -46,11 +46,25 @@ namespace {
constexpr const char* ProgramName = "ModelProgram";
constexpr const char* KeyGeometry = "Geometry";
constexpr const std::array<const char*, 12> UniformNames = {
constexpr const int DefaultBlending = 0;
constexpr const int AdditiveBlending = 1;
constexpr const int PointsAndLinesBlending = 2;
constexpr const int PolygonBlending = 3;
constexpr const int ColorAddingBlending = 4;
std::map<std::string, int> BlendingMapping = {
{ "Default", DefaultBlending },
{ "Additive", AdditiveBlending },
{ "Points and Lines", PointsAndLinesBlending },
{ "Polygon", PolygonBlending },
{ "Color Adding", ColorAddingBlending }
};
constexpr const std::array<const char*, 13> UniformNames = {
"opacity", "nLightSources", "lightDirectionsViewSpace", "lightIntensities",
"modelViewTransform", "crippedModelViewTransform", "projectionTransform",
"modelViewTransform", "normalTransform", "projectionTransform",
"performShading", "texture1", "ambientIntensity", "diffuseIntensity",
"specularIntensity"
"specularIntensity", "opacityBlending"
};
constexpr openspace::properties::Property::PropertyInfo AmbientIntensityInfo = {
@@ -102,6 +116,24 @@ namespace {
"Light Sources",
"A list of light sources that this model should accept light from."
};
constexpr openspace::properties::Property::PropertyInfo DisableDepthTestInfo = {
"DisableDepthTest",
"Disable Depth Test",
"Disable Depth Testing for the Model."
};
constexpr openspace::properties::Property::PropertyInfo BlendingOptionInfo = {
"BledingOption",
"Blending Options",
"Debug option for blending colors."
};
constexpr openspace::properties::Property::PropertyInfo EnableOpacityBlendingInfo = {
"EnableOpacityBlending",
"Enable Opacity Blending",
"Enable Opacity Blending."
};
} // namespace
namespace openspace {
@@ -177,7 +209,25 @@ documentation::Documentation RenderableModel::Documentation() {
}),
Optional::Yes,
LightSourcesInfo.description
}
},
{
DisableDepthTestInfo.identifier,
new BoolVerifier,
Optional::Yes,
DisableDepthTestInfo.description
},
{
BlendingOptionInfo.identifier,
new StringVerifier,
Optional::Yes,
BlendingOptionInfo.description
},
{
EnableOpacityBlendingInfo.identifier,
new BoolVerifier,
Optional::Yes,
EnableOpacityBlendingInfo.description
},
}
};
}
@@ -196,6 +246,12 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
glm::dmat3(1.0)
)
, _rotationVec(RotationVecInfo, glm::dvec3(0.0), glm::dvec3(0.0), glm::dvec3(360.0))
, _enableOpacityBlending(EnableOpacityBlendingInfo, false)
, _disableDepthTest(DisableDepthTestInfo, false)
, _blendingFuncOption(
BlendingOptionInfo,
properties::OptionProperty::DisplayType::Dropdown
)
, _lightSourcePropertyOwner({ "LightSources", "Light Sources" })
{
documentation::testSpecificationAndThrow(
@@ -235,6 +291,10 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
_performShading = dictionary.value<bool>(ShadingInfo.identifier);
}
if (dictionary.hasKey(DisableDepthTestInfo.identifier)) {
_disableDepthTest = dictionary.value<bool>(DisableDepthTestInfo.identifier);
}
if (dictionary.hasKey(DisableFaceCullingInfo.identifier)) {
_disableFaceCulling = dictionary.value<bool>(DisableFaceCullingInfo.identifier);
}
@@ -252,14 +312,13 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
}
}
addPropertySubOwner(_lightSourcePropertyOwner);
addProperty(_ambientIntensity);
addProperty(_diffuseIntensity);
addProperty(_specularIntensity);
addProperty(_performShading);
addProperty(_disableFaceCulling);
addProperty(_disableDepthTest);
addProperty(_modelTransform);
addProperty(_rotationVec);
@@ -271,6 +330,29 @@ RenderableModel::RenderableModel(const ghoul::Dictionary& dictionary)
if (dictionary.hasKey(RotationVecInfo.identifier)) {
_rotationVec = dictionary.value<glm::vec3>(RotationVecInfo.identifier);
}
_blendingFuncOption.addOption(DefaultBlending, "Default");
_blendingFuncOption.addOption(AdditiveBlending, "Additive");
_blendingFuncOption.addOption(PointsAndLinesBlending, "Points and Lines");
_blendingFuncOption.addOption(PolygonBlending, "Polygon");
_blendingFuncOption.addOption(ColorAddingBlending, "Color Adding");
addProperty(_blendingFuncOption);
if (dictionary.hasKey(BlendingOptionInfo.identifier)) {
const std::string blendingOpt = dictionary.value<std::string>(
BlendingOptionInfo.identifier
);
_blendingFuncOption.set(BlendingMapping[blendingOpt]);
}
if (dictionary.hasKey(DisableDepthTestInfo.identifier)) {
_enableOpacityBlending = dictionary.value<bool>(
EnableOpacityBlendingInfo.identifier
);
}
addProperty(_enableOpacityBlending);
}
bool RenderableModel::isReady() const {
@@ -369,13 +451,11 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
glm::mat4(modelViewTransform)
);
glm::dmat4 crippedModelViewTransform = glm::transpose(glm::inverse(
glm::dmat4(glm::inverse(data.camera.sgctInternal.viewMatrix())) * modelViewTransform
));
glm::dmat4 normalTransform = glm::transpose(glm::inverse(modelViewTransform));
_program->setUniform(
_uniformCache.crippedModelViewTransform,
glm::mat4(crippedModelViewTransform)
_uniformCache.normalTransform,
glm::mat4(normalTransform)
);
_program->setUniform(
@@ -386,11 +466,35 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
_program->setUniform(_uniformCache.diffuseIntensity, _diffuseIntensity);
_program->setUniform(_uniformCache.specularIntensity, _specularIntensity);
_program->setUniform(_uniformCache.performShading, _performShading);
_program->setUniform(_uniformCache.opacityBlending, _enableOpacityBlending);
if (_disableFaceCulling) {
glDisable(GL_CULL_FACE);
}
glEnablei(GL_BLEND, 0);
switch (_blendingFuncOption) {
case DefaultBlending:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case AdditiveBlending:
glBlendFunc(GL_ONE, GL_ONE);
break;
case PointsAndLinesBlending:
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
break;
case PolygonBlending:
glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE);
break;
case ColorAddingBlending:
glBlendFunc(GL_SRC_COLOR, GL_DST_COLOR);
break;
};
if (_disableDepthTest) {
glDisable(GL_DEPTH_TEST);
}
ghoul::opengl::TextureUnit unit;
unit.activate();
_program->setUniform(_uniformCache.texture, unit);
@@ -403,6 +507,12 @@ void RenderableModel::render(const RenderData& data, RendererTasks&) {
glEnable(GL_CULL_FACE);
}
global::renderEngine->openglStateCache().resetBlendState();
if (_disableDepthTest) {
glEnable(GL_DEPTH_TEST);
}
_program->deactivate();
}

View File

@@ -26,7 +26,8 @@
#define __OPENSPACE_MODULE_BASE___RENDERABLEMODEL___H__
#include <openspace/rendering/renderable.h>
#include <openspace/properties/optionproperty.h>
#include <openspace/properties/stringproperty.h>
#include <openspace/properties/matrix/dmat4property.h>
#include <openspace/properties/matrix/mat3property.h>
#include <openspace/properties/scalar/boolproperty.h>
@@ -79,11 +80,15 @@ private:
properties::DMat4Property _modelTransform;
properties::Vec3Property _rotationVec;
properties::BoolProperty _disableDepthTest;
properties::BoolProperty _enableOpacityBlending;
properties::OptionProperty _blendingFuncOption;
ghoul::opengl::ProgramObject* _program = nullptr;
UniformCache(opacity, nLightSources, lightDirectionsViewSpace, lightIntensities,
modelViewTransform, crippedModelViewTransform, projectionTransform,
modelViewTransform, normalTransform, projectionTransform,
performShading, texture, ambientIntensity, diffuseIntensity,
specularIntensity) _uniformCache;
specularIntensity, opacityBlending) _uniformCache;
std::vector<std::unique_ptr<LightSource>> _lightSources;

View File

@@ -34,6 +34,7 @@ uniform float diffuseIntensity = 1.0;
uniform float specularIntensity = 1.0;
uniform bool performShading = true;
uniform bool opacityBlending = false;
uniform sampler2D texture1;
@@ -46,6 +47,10 @@ uniform float opacity = 1.0;
const vec3 SpecularAlbedo = vec3(1.0);
Fragment getFragment() {
if (opacity == 0.0) {
discard;
}
vec3 diffuseAlbedo = texture(texture1, vs_st).rgb;
Fragment frag;
@@ -84,12 +89,22 @@ Fragment getFragment() {
frag.color.rgb = diffuseAlbedo;
}
frag.color.a = opacity;
if (opacityBlending) {
// frag.color.a = opacity * (frag.color.r + frag.color.g + frag.color.b)/3.0;
frag.color.a = opacity * max(max(frag.color.r, frag.color.g), frag.color.b);
}
else {
frag.color.a = opacity;
}
if (frag.color.a < 0.1) {
discard;
}
frag.depth = vs_screenSpaceDepth;
frag.gPosition = vs_positionCameraSpace;
frag.gNormal = vec4(vs_normalViewSpace, 0.0);
frag.disableLDR2HDR = true;
return frag;
}
}

View File

@@ -37,7 +37,7 @@ out vec4 vs_positionCameraSpace;
uniform mat4 modelViewTransform;
uniform mat4 projectionTransform;
uniform mat4 crippedModelViewTransform;
uniform mat4 normalTransform;
void main() {
vs_positionCameraSpace = modelViewTransform * in_position;
@@ -48,6 +48,5 @@ void main() {
vs_st = in_st;
vs_screenSpaceDepth = positionScreenSpace.w;
//vs_normalViewSpace = normalize(transpose(inverse(mat3(crippedModelViewTransform))) * in_normal);
vs_normalViewSpace = normalize(mat3(crippedModelViewTransform) * in_normal);
vs_normalViewSpace = normalize(mat3(normalTransform) * in_normal);
}

View File

@@ -28,6 +28,7 @@
#include <openspace/documentation/verifier.h>
#include <openspace/util/updatestructures.h>
#include <ghoul/fmt.h>
#include <ghoul/filesystem/cachemanager.h>
#include <ghoul/filesystem/filesystem.h>
#include <ghoul/logging/logmanager.h>
#include <ghoul/lua/ghoul_lua.h>
@@ -83,7 +84,7 @@ HorizonsTranslation::HorizonsTranslation()
requireUpdate();
notifyObservers();
});
readHorizonsTextFile(_horizonsTextFile);
loadData();
});
}
@@ -99,9 +100,6 @@ HorizonsTranslation::HorizonsTranslation(const ghoul::Dictionary& dictionary)
_horizonsTextFile = absPath(
dictionary.value<std::string>(HorizonsTextFileInfo.identifier)
);
// Read specified file and store it in memory.
readHorizonsTextFile(_horizonsTextFile);
}
glm::dvec3 HorizonsTranslation::position(const UpdateData& data) const {
@@ -130,12 +128,48 @@ glm::dvec3 HorizonsTranslation::position(const UpdateData& data) const {
return interpolatedPos;
}
void HorizonsTranslation::readHorizonsTextFile(const std::string& horizonsTextFilePath) {
std::ifstream fileStream(horizonsTextFilePath);
void HorizonsTranslation::loadData() {
std::string file = _horizonsTextFile;
if (!FileSys.fileExists(absPath(file))) {
return;
}
std::string cachedFile = FileSys.cacheManager()->cachedFilename(
file,
ghoul::filesystem::CacheManager::Persistent::Yes
);
bool hasCachedFile = FileSys.fileExists(cachedFile);
if (hasCachedFile) {
LINFO(fmt::format("Cached file '{}' used for Horizon file '{}'", cachedFile, file));
bool success = loadCachedFile(cachedFile);
if (success) {
return;
}
else {
FileSys.cacheManager()->removeCacheFile(file);
// Intentional fall-through to the 'else' computation to generate the cache
// file for the next run
}
}
else {
LINFO(fmt::format("Cache for Horizon file '{}' not found", file));
}
LINFO(fmt::format("Loading Horizon file '{}'", file));
readHorizonsTextFile();
LINFO("Saving cache");
saveCachedFile(cachedFile);
}
void HorizonsTranslation::readHorizonsTextFile() {
std::ifstream fileStream(_horizonsTextFile);
if (!fileStream.good()) {
LERROR(fmt::format(
"Failed to open Horizons text file '{}'", horizonsTextFilePath
"Failed to open Horizons text file '{}'", _horizonsTextFile
));
return;
}
@@ -186,4 +220,81 @@ void HorizonsTranslation::readHorizonsTextFile(const std::string& horizonsTextFi
fileStream.close();
}
bool HorizonsTranslation::loadCachedFile(const std::string& file) {
std::ifstream fileStream(file, std::ifstream::binary);
if (!fileStream.good()) {
LERROR(fmt::format("Error opening file '{}' for loading cache file", file));
return false;
}
// Read how many keyframes to read
int32_t nKeyframes = 0;
fileStream.read(reinterpret_cast<char*>(&nKeyframes), sizeof(int32_t));
if (nKeyframes == 0) {
throw ghoul::RuntimeError("Error reading cache: No values were loaded");
}
// Read the values in same order as they were written
for (int i = 0; i < nKeyframes; ++i) {
double timestamp, x, y, z;
glm::dvec3 gPos;
// Timestamp
fileStream.read(reinterpret_cast<char*>(&timestamp), sizeof(double));
// Position vector components
fileStream.read(reinterpret_cast<char*>(&x), sizeof(double));
fileStream.read(reinterpret_cast<char*>(&y), sizeof(double));
fileStream.read(reinterpret_cast<char*>(&z), sizeof(double));
// Recreate the position vector
gPos = glm::dvec3(x, y, z);
// Add keyframe in timeline
_timeline.addKeyframe(timestamp, std::move(gPos));
}
return fileStream.good();
}
void HorizonsTranslation::saveCachedFile(const std::string& file) const {
std::ofstream fileStream(file, std::ofstream::binary);
if (!fileStream.good()) {
LERROR(fmt::format("Error opening file '{}' for save cache file", file));
return;
}
// Write how many keyframes are to be written
int32_t nKeyframes = static_cast<int32_t>(_timeline.nKeyframes());
if (nKeyframes == 0) {
throw ghoul::RuntimeError("Error writing cache: No values were loaded");
}
fileStream.write(reinterpret_cast<const char*>(&nKeyframes), sizeof(int32_t));
// Write data
std::deque<Keyframe<glm::dvec3>> keyframes = _timeline.keyframes();
for (int i = 0; i < nKeyframes; i++) {
// First write timestamp
fileStream.write(reinterpret_cast<const char*>(
&keyframes[i].timestamp),
sizeof(double)
);
// and then the components of the position vector one by one
fileStream.write(reinterpret_cast<const char*>(
&keyframes[i].data.x),
sizeof(double)
);
fileStream.write(reinterpret_cast<const char*>(
&keyframes[i].data.y),
sizeof(double)
);
fileStream.write(reinterpret_cast<const char*>(
&keyframes[i].data.z),
sizeof(double)
);
}
}
} // namespace openspace

View File

@@ -59,7 +59,10 @@ public:
static documentation::Documentation Documentation();
private:
void readHorizonsTextFile(const std::string& _horizonsTextFilePath);
void loadData();
void readHorizonsTextFile();
bool loadCachedFile(const std::string& file);
void saveCachedFile(const std::string& file) const;
properties::StringProperty _horizonsTextFile;
std::unique_ptr<ghoul::filesystem::File> _fileHandle;

View File

@@ -35,6 +35,7 @@
#include <thread>
#include <tchar.h>
#include <tpcshrd.h>
#include <debugapi.h>
// #define ENABLE_TUIOMESSAGES
#define ENABLE_DIRECTMSG
@@ -230,25 +231,31 @@ Win32TouchHook::Win32TouchHook(void* nativeWindow) {
GetCurrentThreadId()
);
// In theory, if our UI is pumped from a different thread, we can
// handle Low-level mouse events in that thread as well.
// this might help reduce mouse lag while running OpenSpace?
// gMouseHookThread = new std::thread([](){
// gMouseHook = SetWindowsHookExW(
// WH_MOUSE_LL,
// LowLevelMouseProc,
// GetModuleHandleW(NULL),
// 0 //<- Global thread id (low-level mouse is global only)
// );
// if (!gMouseHook) {
// LINFO("Could not setup mousehook!");
// }
// Attach a lowlevel mouse hook.
// This mouse hook prevents injected mouse events (touch-to-mouse),
// since we cannot catch it in our messageloop.
// Since this is attached to windows global thread, this will block lowlevel mouse
// access to all running applications if we stall in this thread.
// Debug breakpoints typically freeze our application, in which case we simply don't
// create this if a debugger is attached.
if (!IsDebuggerPresent()) {
gMouseHookThread = new std::thread([](){
gMouseHook = SetWindowsHookExW(
WH_MOUSE_LL,
LowLevelMouseProc,
GetModuleHandleW(NULL),
0 //<- Global thread id (low-level mouse is global only)
);
if (!gMouseHook) {
LINFO("Could not setup mousehook!");
}
// MSG msg;
// while (GetMessage(&msg, NULL, 0, 0)) {
// DispatchMessage(&msg);
// }
// });
MSG msg;
while (GetMessage(&msg, NULL, 0, 0)) {
DispatchMessage(&msg);
}
});
}
if (!gTouchHook) {
LINFO(fmt::format("Failed to setup WindowsHook for touch input redirection"));
@@ -272,13 +279,13 @@ Win32TouchHook::~Win32TouchHook() {
}
// Low-level mouse hook is "needed" if we want to stop mousecursor from moving
// when we get a touch-input on our window A negative effect is that this
// function is for global threads, meaning our application will cause Windows to
// stall the mouse cursor when this function can't be scheduled. This is not yet
// fail-proof...might be a race-condition on message pumping?
// when we get a touch-input on our window.
// A negative effect is that this function is for global threads, meaning our
// application will cause Windows to stall the mouse cursor when this
// function can't be scheduled (i.e. when debugger hits a breakpoint).
// This is not yet fail-proof...might be a race-condition on message pumping?
// - Seems to move the cursor when we get two fingers as input..
// - If we ourselves would pump windows for events, we can handle this in the
// pump-loop
// - If we ourselves would pump windows for events, we can handle this.
LRESULT CALLBACK LowLevelMouseProc(int nCode, WPARAM wParam, LPARAM lParam) {
constexpr const LONG_PTR SIGNATURE_MASK = 0xFFFFFF00;
constexpr const LONG_PTR MOUSEEVENTF_FROMTOUCH = 0xFF515700;