mirror of
https://github.com/OpenSpace/OpenSpace.git
synced 2026-03-03 02:48:32 -06:00
merge with master
This commit is contained in:
@@ -74,6 +74,7 @@ target_compile_definitions(${APPLICATION_NAME} PUBLIC ${SGCT_OPENVR_DEFINITIONS}
|
||||
|
||||
|
||||
if (MSVC)
|
||||
target_link_libraries(${APPLICATION_NAME} Dbghelp.lib)
|
||||
set_target_properties(${APPLICATION_NAME} PROPERTIES LINK_FLAGS
|
||||
"/NODEFAULTLIB:LIBCMTD.lib /NODEFAULTLIB:LIBCMT.lib"
|
||||
)
|
||||
|
||||
@@ -32,6 +32,22 @@
|
||||
|
||||
#include <sgct.h>
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
#include <openspace/openspace.h>
|
||||
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/misc/stacktrace.h>
|
||||
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <Windows.h>
|
||||
#include <dbghelp.h>
|
||||
#include <shellapi.h>
|
||||
#include <shlobj.h>
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef OPENVR_SUPPORT
|
||||
#include <SGCTOpenVR.h>
|
||||
#endif // OPENVR_SUPPORT
|
||||
@@ -43,6 +59,73 @@ namespace {
|
||||
const char* _loggerCat = "main";
|
||||
|
||||
sgct::Engine* SgctEngine;
|
||||
|
||||
#ifdef WIN32
|
||||
|
||||
LONG WINAPI generateMiniDump(EXCEPTION_POINTERS* exceptionPointers) {
|
||||
SYSTEMTIME stLocalTime;
|
||||
GetLocalTime(&stLocalTime);
|
||||
|
||||
|
||||
LFATAL("Printing Stack Trace that lead to the crash:");
|
||||
std::vector<std::string> stackTrace = ghoul::stackTrace();
|
||||
for (const std::string& s : stackTrace) {
|
||||
LINFO(s);
|
||||
}
|
||||
|
||||
std::string dumpFile = fmt::format(
|
||||
"OpenSpace_{}_{}_{}-{}-{}-{}-{}-{}-{}--{}--{}.dmp",
|
||||
openspace::OPENSPACE_VERSION_MAJOR,
|
||||
openspace::OPENSPACE_VERSION_MINOR,
|
||||
openspace::OPENSPACE_VERSION_PATCH,
|
||||
stLocalTime.wYear,
|
||||
stLocalTime.wMonth,
|
||||
stLocalTime.wDay,
|
||||
stLocalTime.wHour,
|
||||
stLocalTime.wMinute,
|
||||
stLocalTime.wSecond,
|
||||
GetCurrentProcessId(),
|
||||
GetCurrentThreadId()
|
||||
);
|
||||
|
||||
LINFO("Creating dump file: " << dumpFile);
|
||||
|
||||
HANDLE hDumpFile = CreateFile(
|
||||
dumpFile.c_str(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
FILE_SHARE_WRITE | FILE_SHARE_READ,
|
||||
0,
|
||||
CREATE_ALWAYS,
|
||||
0,
|
||||
0
|
||||
);
|
||||
|
||||
MINIDUMP_EXCEPTION_INFORMATION exceptionParameter;
|
||||
exceptionParameter.ThreadId = GetCurrentThreadId();
|
||||
exceptionParameter.ExceptionPointers = exceptionPointers;
|
||||
exceptionParameter.ClientPointers = TRUE;
|
||||
|
||||
BOOL success = MiniDumpWriteDump(
|
||||
GetCurrentProcess(),
|
||||
GetCurrentProcessId(),
|
||||
hDumpFile,
|
||||
MiniDumpWithDataSegs,
|
||||
&exceptionParameter,
|
||||
nullptr,
|
||||
nullptr
|
||||
);
|
||||
|
||||
if (success) {
|
||||
LINFO("Created successfully");
|
||||
}
|
||||
else {
|
||||
LERROR("Dumpfile created unsuccessfully");
|
||||
}
|
||||
|
||||
return EXCEPTION_EXECUTE_HANDLER;
|
||||
}
|
||||
|
||||
#endif // WIN32
|
||||
|
||||
#ifdef OPENVR_SUPPORT
|
||||
sgct::SGCTWindow* FirstOpenVRWindow = nullptr;
|
||||
@@ -175,13 +258,11 @@ void mainRenderFunc() {
|
||||
}
|
||||
#endif
|
||||
|
||||
if (SgctEngine->isMaster()) {
|
||||
OsEng.render(viewMatrix, projectionMatrix);
|
||||
}
|
||||
else {
|
||||
glm::mat4 sceneMatrix = SgctEngine->getModelMatrix();
|
||||
OsEng.render(viewMatrix * sceneMatrix, projectionMatrix);
|
||||
}
|
||||
OsEng.render(
|
||||
SgctEngine->getModelMatrix(),
|
||||
viewMatrix,
|
||||
projectionMatrix
|
||||
);
|
||||
LTRACE("main::mainRenderFunc(end)");
|
||||
}
|
||||
|
||||
@@ -397,6 +478,10 @@ int main_main(int argc, char** argv) {
|
||||
} // namespace
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
#ifdef WIN32
|
||||
SetUnhandledExceptionFilter(generateMiniDump);
|
||||
#endif // WIN32
|
||||
|
||||
// If we are working as a developer, we don't want to catch the exceptions in order to
|
||||
// find the locations where the exceptions are raised.
|
||||
// If we are not in developer mode, we want to catch and at least log the error before
|
||||
|
||||
@@ -49,6 +49,7 @@ return {
|
||||
MieColor = {1.0, 1.0, 1.0}
|
||||
}
|
||||
},
|
||||
Tag = {"planet_solarSystem", "planet_terrestrial"},
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
@@ -78,9 +79,10 @@ return {
|
||||
-- EndTime = "2017 JAN 01 12:00:00.000",
|
||||
-- SampleInterval = 3600
|
||||
Period = 365.242,
|
||||
Resolution = 1000
|
||||
Resolution = 1000,
|
||||
Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"}
|
||||
},
|
||||
GuiName = "/Solar/EarthTrail"
|
||||
GuiName = "/Solar/EarthTrail",
|
||||
},
|
||||
--[[
|
||||
{
|
||||
|
||||
@@ -35,6 +35,7 @@ return {
|
||||
MieColor = {1.0, 1.0, 1.0}
|
||||
}
|
||||
},
|
||||
Tag = "planet_solarSystem",
|
||||
Transform = {
|
||||
Translation = {
|
||||
Type = "StaticTranslation",
|
||||
@@ -64,7 +65,8 @@ return {
|
||||
},
|
||||
Color = { 0.8, 0.7, 0.7 },
|
||||
Period = 4330.595,
|
||||
Resolution = 1000
|
||||
}
|
||||
Resolution = 1000,
|
||||
},
|
||||
Tag = "planetTrail_solarSystem"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -76,10 +76,6 @@ return {
|
||||
FilePath = "map_service_configs/ESRI/ESRI_Imagery_World_2D.wms",
|
||||
Name = "ESRI",
|
||||
},
|
||||
{
|
||||
Name = "ESRI Imagery World 2D",
|
||||
FilePath = "map_service_configs/ESRI/ESRI_Imagery_World_2D.wms",
|
||||
},
|
||||
{
|
||||
Name = "ESRI Imagery World",
|
||||
FilePath = "map_service_configs/ESRI/ESRI_Imagery_World_2D.wms"
|
||||
@@ -94,6 +90,11 @@ return {
|
||||
Name = "Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature",
|
||||
FilePath = "map_service_configs/GIBS/Temporal_GHRSST_L4_MUR_Sea_Surface_Temperature.xml",
|
||||
},
|
||||
{
|
||||
Type = "Temporal",
|
||||
Name = "Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration",
|
||||
FilePath = "map_service_configs/GIBS/Temporal_AMSR2_GCOM_W1_Sea_Ice_Concentration.xml",
|
||||
},
|
||||
-- {
|
||||
-- Type = "SingleImage",
|
||||
-- Name = "Debug Tiles",
|
||||
@@ -120,7 +121,7 @@ return {
|
||||
{
|
||||
Type = "Temporal",
|
||||
Name = "Temporal Earth at Night",
|
||||
FilePath = "map_service_configs/GIBS/Temporal_VIIRS_CityLights.xml"
|
||||
FilePath = "map_service_configs/GIBS/Temporal_VIIRS_SNPP_DayNightBand_ENCC.xml"
|
||||
}
|
||||
},
|
||||
WaterMasks = {
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<OpenSpaceTemporalGDALDataset>
|
||||
<OpenSpaceTimeStart>2012-05-08</OpenSpaceTimeStart>
|
||||
<OpenSpaceTimeEnd></OpenSpaceTimeEnd>
|
||||
<OpenSpaceTimeResolution>1d</OpenSpaceTimeResolution>
|
||||
<OpenSpaceTimeIdFormat>YYYY-MM-DD</OpenSpaceTimeIdFormat>
|
||||
<GDAL_WMS>
|
||||
<Service name="TMS">
|
||||
<ServerUrl>https://gibs.earthdata.nasa.gov/wmts/epsg4326/best/AMSR2_Sea_Ice_Concentration_12km/default/${OpenSpaceTimeId}/2km/${z}/${y}/${x}.png</ServerUrl>
|
||||
</Service>
|
||||
<DataWindow>
|
||||
<UpperLeftX>-180.0</UpperLeftX>
|
||||
<UpperLeftY>90</UpperLeftY>
|
||||
<LowerRightX>396.0</LowerRightX>
|
||||
<LowerRightY>-198</LowerRightY>
|
||||
<TileLevel>8</TileLevel>
|
||||
<TileCountX>2</TileCountX>
|
||||
<TileCountY>1</TileCountY>
|
||||
<YOrigin>top</YOrigin>
|
||||
</DataWindow>
|
||||
<Projection>EPSG:4326</Projection>
|
||||
<BlockSizeX>512</BlockSizeX>
|
||||
<BlockSizeY>512</BlockSizeY>
|
||||
<BandsCount>3</BandsCount>
|
||||
<UnsafeSSL>true</UnsafeSSL>
|
||||
<ZeroBlockHttpCodes>400</ZeroBlockHttpCodes>
|
||||
<ZeroBlockOnServerException>true</ZeroBlockOnServerException>
|
||||
</GDAL_WMS>
|
||||
</OpenSpaceTemporalGDALDataset>
|
||||
@@ -62,4 +62,10 @@
|
||||
</DataWindow>
|
||||
<BlockSizeX>512</BlockSizeX>
|
||||
<BlockSizeY>512</BlockSizeY>
|
||||
|
||||
<Cache>
|
||||
<Path>./GDAL_Cache/OnMoonColor</Path>
|
||||
<Depth>4</Depth>
|
||||
<Extension>.png</Extension>
|
||||
</Cache>
|
||||
</GDAL_WMS>
|
||||
@@ -16,4 +16,9 @@
|
||||
<TileCountY>1</TileCountY>
|
||||
<YOrigin>top</YOrigin>
|
||||
</DataWindow>
|
||||
<Cache>
|
||||
<Path>./GDAL_Cache/OnMoonHeight</Path>
|
||||
<Depth>4</Depth>
|
||||
<Extension>.png</Extension>
|
||||
</Cache>
|
||||
</GDAL_WMS>
|
||||
@@ -35,12 +35,17 @@ return {
|
||||
MieColor = {1.0, 1.0, 1.0}
|
||||
}
|
||||
},
|
||||
Tag = {"planet_solarSystem", "planet_terrestrial"},
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "IAU_MARS",
|
||||
DestinationFrame = "GALACTIC",
|
||||
},
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
-- MarsTrail module
|
||||
@@ -56,7 +61,8 @@ return {
|
||||
},
|
||||
Color = { 0.814, 0.305, 0.220 },
|
||||
Period = 686.973,
|
||||
Resolution = 1000
|
||||
Resolution = 1000,
|
||||
Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ return {
|
||||
MieColor = {1.0, 1.0, 1.0}
|
||||
}
|
||||
},
|
||||
Tag = {"planet_solarSystem", "planet_terrestrial"},
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
@@ -60,7 +61,8 @@ return {
|
||||
},
|
||||
Color = {0.6, 0.5, 0.5 },
|
||||
Period = 87.968,
|
||||
Resolution = 100
|
||||
Resolution = 100,
|
||||
Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -29,14 +29,19 @@ return {
|
||||
Textures = {
|
||||
Type = "simple",
|
||||
Color = "textures/neptune.jpg",
|
||||
},
|
||||
}
|
||||
},
|
||||
Translation = {
|
||||
Tag = "planet_solarSystem",
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "IAU_NEPTUNE",
|
||||
DestinationFrame = "GALACTIC"
|
||||
},
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = 1,
|
||||
},
|
||||
}
|
||||
},
|
||||
-- NeptuneTrail module
|
||||
@@ -52,7 +57,8 @@ return {
|
||||
},
|
||||
Color = {0.2, 0.5, 1.0 },
|
||||
Period = 60200,
|
||||
Resolution = 1000
|
||||
},
|
||||
Resolution = 1000,
|
||||
Tag = "planetTrail_solarSystem"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ return {
|
||||
MieColor = {1.0, 1.0, 1.0}
|
||||
}
|
||||
},
|
||||
Tag = "planet_solarSystem",
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
@@ -73,7 +74,8 @@ return {
|
||||
},
|
||||
Color = {0.85,0.75,0.51 },
|
||||
Period = 10746.94,
|
||||
Resolution = 1000
|
||||
Resolution = 1000,
|
||||
Tag = "planetTrail_solarSystem"
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,12 +36,17 @@ return {
|
||||
MieColor = {1.0, 1.0, 1.0}
|
||||
}
|
||||
},
|
||||
Tag = "planet_solarSystem",
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "IAU_URANUS",
|
||||
DestinationFrame = "ECLIPJ2000",
|
||||
}
|
||||
},
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -58,7 +63,8 @@ return {
|
||||
},
|
||||
Color = {0.60, 0.95, 1.00 },
|
||||
Period = 30588.740,
|
||||
Resolution = 1000
|
||||
},
|
||||
Resolution = 1000,
|
||||
Tag = "planetTrail_solarSystem"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,10 +36,17 @@ return {
|
||||
MieColor = {1.0, 1.0, 1.0}
|
||||
}
|
||||
},
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
Frame = "IAU_VENUS",
|
||||
Reference = "GALACTIC"
|
||||
Tag = {"planet_solarSystem", "planet_terrestrial"},
|
||||
Transform = {
|
||||
Rotation = {
|
||||
Type = "SpiceRotation",
|
||||
SourceFrame = "IAU_VENUS",
|
||||
DestinationFrame = "GALACTIC"
|
||||
},
|
||||
Scale = {
|
||||
Type = "StaticScale",
|
||||
Scale = 1,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -56,7 +63,8 @@ return {
|
||||
},
|
||||
Color = { 1.0, 0.5, 0.2 },
|
||||
Period = 224.695,
|
||||
Resolution = 1000
|
||||
Resolution = 1000,
|
||||
Tag = {"planetTrail_solarSystem", "planetTrail_terrestrial"}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Submodule ext/ghoul updated: c37ff8beb5...20131b6897
@@ -216,6 +216,19 @@ struct StringListVerifier : public TableVerifier {
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
/**
|
||||
* A Verifier that checks whether all values contained in a Table are of type \c int.
|
||||
*/
|
||||
struct IntListVerifier : public TableVerifier {
|
||||
/**
|
||||
* Constructor for a IntListVerifier.
|
||||
* \param elementDocumentation The documentation for each string in the list
|
||||
*/
|
||||
IntListVerifier(std::string elementDocumentation = "");
|
||||
|
||||
std::string type() const override;
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------------------------
|
||||
// Vector verifiers
|
||||
//----------------------------------------------------------------------------------------
|
||||
|
||||
@@ -104,6 +104,8 @@ public:
|
||||
/// The key that stores whether the master node should perform rendering just function
|
||||
/// as a pure manager
|
||||
static const std::string KeyDisableMasterRendering;
|
||||
/// The key that stores whether the master node should apply the scene transformation
|
||||
static const std::string KeyDisableSceneOnMaster;
|
||||
/// The key that sets the request URL that is used to request additional data to be
|
||||
/// downloaded
|
||||
static const std::string KeyDownloadRequestURL;
|
||||
@@ -124,7 +126,22 @@ public:
|
||||
static const std::string PartHttpProxyUser;
|
||||
/// The key that stores the password to use for authentication to access the http proxy
|
||||
static const std::string PartHttpProxyPassword;
|
||||
|
||||
/// The key that stores the dictionary containing information about debug contexts
|
||||
static const std::string KeyOpenGLDebugContext;
|
||||
/// The part of the key storing whether an OpenGL Debug context should be created
|
||||
static const std::string PartActivate;
|
||||
/// The part of the key storing whether the debug callbacks are performed synchronous
|
||||
static const std::string PartSynchronous;
|
||||
/// The part of the key storing a list of identifiers that should be filtered out
|
||||
static const std::string PartFilterIdentifier;
|
||||
/// The part of the key that stores the source of the ignored identifier
|
||||
static const std::string PartFilterIdentifierSource;
|
||||
/// The part of the key that stores the type of the ignored identifier
|
||||
static const std::string PartFilterIdentifierType;
|
||||
/// The part of the key that stores the identifier of the ignored identifier
|
||||
static const std::string PartFilterIdentifierIdentifier;
|
||||
/// The part of the key storing a list of severities that should be filtered out
|
||||
static const std::string PartFilterSeverity;
|
||||
|
||||
/**
|
||||
* Iteratively walks the directory structure starting with \p filename to find the
|
||||
|
||||
@@ -88,7 +88,8 @@ public:
|
||||
void deinitialize();
|
||||
void preSynchronization();
|
||||
void postSynchronizationPreDraw();
|
||||
void render(const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix);
|
||||
void render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix,
|
||||
const glm::mat4& projectionMatrix);
|
||||
void postDraw();
|
||||
void keyboardCallback(Key key, KeyModifier mod, KeyAction action);
|
||||
void charCallback(unsigned int codepoint, KeyModifier mod);
|
||||
|
||||
@@ -65,6 +65,7 @@ public:
|
||||
// Interaction mode setters
|
||||
void setCameraStateFromDictionary(const ghoul::Dictionary& cameraDict);
|
||||
void setInteractionMode(const std::string& interactionModeKey);
|
||||
InteractionMode* interactionMode();
|
||||
|
||||
void goToChunk(int x, int y, int level);
|
||||
void goToGeo(double latitude, double longitude);
|
||||
@@ -72,7 +73,9 @@ public:
|
||||
void resetKeyBindings();
|
||||
|
||||
void addKeyframe(const datamessagestructures::CameraKeyframe &kf);
|
||||
void removeKeyframesAfter(double timestamp);
|
||||
void clearKeyframes();
|
||||
const std::vector<datamessagestructures::CameraKeyframe>& keyframes() const;
|
||||
|
||||
void bindKeyLocal(
|
||||
Key key,
|
||||
@@ -96,6 +99,8 @@ public:
|
||||
// Accessors
|
||||
ghoul::Dictionary getCameraStateDictionary();
|
||||
SceneGraphNode* const focusNode() const;
|
||||
glm::dvec3 focusNodeToCameraVector() const;
|
||||
glm::quat focusNodeToCameraRotation() const;
|
||||
Camera* const camera() const;
|
||||
std::shared_ptr<InteractionMode> interactionmode();
|
||||
const InputState& inputState() const;
|
||||
|
||||
@@ -82,9 +82,12 @@ namespace interaction {
|
||||
|
||||
// Mutators
|
||||
void addKeyframe(const datamessagestructures::CameraKeyframe &kf);
|
||||
void removeKeyframesAfter(double timestamp);
|
||||
void clearKeyframes();
|
||||
void clearOldKeyframes();
|
||||
|
||||
static bool compareKeyframeTimes(const datamessagestructures::CameraKeyframe& a, const datamessagestructures::CameraKeyframe& b);
|
||||
|
||||
// Accessors
|
||||
const std::list<std::pair<Key, KeyModifier> >& getPressedKeys() const;
|
||||
const std::list<MouseButton>& getPressedMouseButtons() const;
|
||||
@@ -119,6 +122,7 @@ public:
|
||||
// Accessors
|
||||
SceneGraphNode* focusNode();
|
||||
Interpolator<double>& rotateToFocusNodeInterpolator();
|
||||
virtual bool followingNodeRotation() const = 0;
|
||||
|
||||
virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime) = 0;
|
||||
virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime) = 0;
|
||||
@@ -195,6 +199,7 @@ public:
|
||||
|
||||
virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime);
|
||||
virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime);
|
||||
bool followingNodeRotation() const override;
|
||||
|
||||
private:
|
||||
std::vector<datamessagestructures::CameraKeyframe> _keyframes;
|
||||
@@ -245,6 +250,7 @@ public:
|
||||
|
||||
virtual void updateMouseStatesFromInput(const InputState& inputState, double deltaTime);
|
||||
virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime);
|
||||
bool followingNodeRotation() const override;
|
||||
|
||||
protected:
|
||||
//void updateCameraStateFromMouseStates(Camera& camera, double deltaTime);
|
||||
@@ -260,6 +266,7 @@ public:
|
||||
virtual void setFocusNode(SceneGraphNode* focusNode);
|
||||
//virtual void update(Camera& camera, const InputState& inputState, double deltaTime);
|
||||
virtual void updateCameraStateFromMouseStates(Camera& camera, double deltaTime);
|
||||
bool followingNodeRotation() const override;
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
void goToChunk(Camera& camera, globebrowsing::TileIndex ti, glm::vec2 uv,
|
||||
bool resetCameraDirection);
|
||||
|
||||
@@ -53,7 +53,7 @@ private:
|
||||
void addToCommand(std::string c);
|
||||
|
||||
properties::BoolProperty _isVisible;
|
||||
bool _remoteScripting;
|
||||
properties::BoolProperty _remoteScripting;
|
||||
|
||||
size_t _inputPosition;
|
||||
std::vector<std::string> _commandsHistory;
|
||||
|
||||
@@ -51,16 +51,28 @@ struct CameraKeyframe {
|
||||
|
||||
glm::dvec3 _position;
|
||||
glm::dquat _rotation;
|
||||
bool _followNodeRotation;
|
||||
std::string _focusNode;
|
||||
|
||||
double _timestamp;
|
||||
|
||||
void serialize(std::vector<char> &buffer){
|
||||
//add position
|
||||
// Add position
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_position), reinterpret_cast<char*>(&_position) + sizeof(_position));
|
||||
|
||||
//add orientation
|
||||
// Add orientation
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_rotation), reinterpret_cast<char*>(&_rotation) + sizeof(_rotation));
|
||||
|
||||
//add timestamp
|
||||
|
||||
// Follow focus node rotation?
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_followNodeRotation), reinterpret_cast<char*>(&_followNodeRotation) + sizeof(_followNodeRotation));
|
||||
|
||||
int nodeNameLength = _focusNode.size();
|
||||
|
||||
// Add focus node
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&nodeNameLength), reinterpret_cast<char*>(&nodeNameLength) + sizeof(nodeNameLength));
|
||||
buffer.insert(buffer.end(), _focusNode.data(), _focusNode.data() + nodeNameLength);
|
||||
|
||||
// Add timestamp
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_timestamp), reinterpret_cast<char*>(&_timestamp) + sizeof(_timestamp));
|
||||
};
|
||||
|
||||
@@ -68,17 +80,31 @@ struct CameraKeyframe {
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
|
||||
//position
|
||||
// Position
|
||||
size = sizeof(_position);
|
||||
memcpy(&_position, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
//orientation
|
||||
|
||||
// Orientation
|
||||
size = sizeof(_rotation);
|
||||
memcpy(&_rotation, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
// Follow focus node rotation?
|
||||
size = sizeof(_followNodeRotation);
|
||||
memcpy(&_followNodeRotation, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
// Focus node
|
||||
int nodeNameLength;
|
||||
size = sizeof(int);
|
||||
memcpy(&nodeNameLength, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
size = nodeNameLength;
|
||||
_focusNode = std::string(buffer.data() + offset, buffer.data() + offset + size);
|
||||
offset += size;
|
||||
|
||||
//timestamp
|
||||
// Timestamp
|
||||
size = sizeof(_timestamp);
|
||||
memcpy(&_timestamp, buffer.data() + offset, size);
|
||||
};
|
||||
@@ -97,19 +123,19 @@ struct TimeKeyframe {
|
||||
double _timestamp;
|
||||
|
||||
void serialize(std::vector<char> &buffer){
|
||||
//add current time
|
||||
// Add current time
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_time), reinterpret_cast<char*>(&_time) + sizeof(_time));
|
||||
|
||||
//add delta time
|
||||
// Add delta time
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_dt), reinterpret_cast<char*>(&_dt) + sizeof(_dt));
|
||||
|
||||
//add wether time is paused or not
|
||||
// Add whether time is paused or not
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_paused), reinterpret_cast<char*>(&_paused) + sizeof(_paused));
|
||||
|
||||
//add wether a time jump is necessary (recompute paths etc)
|
||||
// Add whether a time jump is necessary (recompute paths etc)
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_requiresTimeJump), reinterpret_cast<char*>(&_requiresTimeJump) + sizeof(_requiresTimeJump));
|
||||
|
||||
//add timestamp
|
||||
// Add timestamp
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_timestamp), reinterpret_cast<char*>(&_timestamp) + sizeof(_timestamp));
|
||||
};
|
||||
|
||||
@@ -117,27 +143,27 @@ struct TimeKeyframe {
|
||||
int offset = 0;
|
||||
int size = 0;
|
||||
|
||||
//current time
|
||||
// Current time
|
||||
size = sizeof(_time);
|
||||
memcpy(&_time, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
//delta time
|
||||
// Delta time
|
||||
size = sizeof(_dt);
|
||||
memcpy(&_dt, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
//is time paused?
|
||||
// Is time paused?
|
||||
size = sizeof(_paused);
|
||||
memcpy(&_paused, buffer.data() + offset, size);
|
||||
offset += sizeof(_paused);
|
||||
|
||||
//is a time jump required?
|
||||
// Is a time jump required?
|
||||
size = sizeof(_requiresTimeJump);
|
||||
memcpy(&_requiresTimeJump, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
// timestamp
|
||||
// Timestamp
|
||||
size = sizeof(_timestamp);
|
||||
memcpy(&_timestamp, buffer.data() + offset, size);
|
||||
offset += size;
|
||||
|
||||
@@ -27,6 +27,9 @@
|
||||
|
||||
//openspace includes
|
||||
#include <openspace/network/messagestructures.h>
|
||||
#include <openspace/properties/propertyowner.h>
|
||||
#include <openspace/properties/stringproperty.h>
|
||||
#include <openspace/properties/numericalproperty.h>
|
||||
|
||||
//glm includes
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
@@ -57,7 +60,7 @@ struct addrinfo;
|
||||
|
||||
namespace openspace {
|
||||
|
||||
class ParallelConnection {
|
||||
class ParallelConnection : public properties::PropertyOwner {
|
||||
public:
|
||||
enum class Status : uint32_t {
|
||||
Disconnected = 0,
|
||||
@@ -99,17 +102,21 @@ class ParallelConnection {
|
||||
ParallelConnection();
|
||||
~ParallelConnection();
|
||||
void clientConnect();
|
||||
void setPort(const std::string &port);
|
||||
void setAddress(const std::string &address);
|
||||
void setName(const std::string& name);
|
||||
void setPort(std::string port);
|
||||
void setAddress(std::string address);
|
||||
void setName(std::string name);
|
||||
bool isHost();
|
||||
const std::string& hostName();
|
||||
void requestHostship(const std::string &password);
|
||||
void requestHostship();
|
||||
void resignHostship();
|
||||
void setPassword(const std::string &password);
|
||||
void setPassword(std::string password);
|
||||
void setHostPassword(std::string hostPassword);
|
||||
void signalDisconnect();
|
||||
void preSynchronization();
|
||||
void sendScript(const std::string& script);
|
||||
void sendScript(std::string script);
|
||||
void resetTimeOffset();
|
||||
double latencyStandardDeviation() const;
|
||||
double timeTolerance() const;
|
||||
|
||||
/**
|
||||
* Returns the Lua library that contains all Lua functions available to affect the
|
||||
@@ -145,7 +152,6 @@ private:
|
||||
void connectionStatusMessageReceived(const std::vector<char>& messageContent);
|
||||
void nConnectionsMessageReceived(const std::vector<char>& messageContent);
|
||||
|
||||
void broadcast();
|
||||
void sendCameraKeyframe();
|
||||
void sendTimeKeyframe();
|
||||
|
||||
@@ -158,10 +164,18 @@ private:
|
||||
|
||||
double calculateBufferedKeyframeTime(double originalTime);
|
||||
|
||||
uint32_t _passCode;
|
||||
std::string _port;
|
||||
std::string _address;
|
||||
std::string _name;
|
||||
properties::StringProperty _password;
|
||||
properties::StringProperty _hostPassword;
|
||||
properties::StringProperty _port;
|
||||
properties::StringProperty _address;
|
||||
properties::StringProperty _name;
|
||||
properties::FloatProperty _bufferTime;
|
||||
properties::FloatProperty _timeKeyframeInterval;
|
||||
properties::FloatProperty _cameraKeyframeInterval;
|
||||
properties::FloatProperty _timeTolerance;
|
||||
|
||||
double _lastTimeKeyframeTimestamp;
|
||||
double _lastCameraKeyframeTimestamp;
|
||||
|
||||
_SOCKET _clientSocket;
|
||||
|
||||
@@ -191,7 +205,6 @@ private:
|
||||
double _initialTimeDiff;
|
||||
|
||||
std::unique_ptr<std::thread> _connectionThread;
|
||||
std::unique_ptr<std::thread> _broadcastThread;
|
||||
std::unique_ptr<std::thread> _sendThread;
|
||||
std::unique_ptr<std::thread> _listenThread;
|
||||
std::unique_ptr<std::thread> _handlerThread;
|
||||
|
||||
@@ -207,6 +207,20 @@ public:
|
||||
/// \see PropertyOwner::removePropertySubOwner(PropertyOwner*)
|
||||
void removePropertySubOwner(PropertyOwner& owner);
|
||||
|
||||
/**
|
||||
* Returns a list of all tags that have been assigned to the Property. Useful for
|
||||
* trying to find a match for a desired batch operation on Properties.
|
||||
* \return Pointer to vector of string tags that were assigned to the Property
|
||||
*/
|
||||
std::vector<std::string> tags() const;
|
||||
|
||||
/**
|
||||
* Adds a tag to the Property's list of assigned tags. Tags are useful for creating
|
||||
* groups of Properties that can be used in batch operations.
|
||||
* \param tag The string that is to be assigned to the Property
|
||||
*/
|
||||
void addTag(std::string tag);
|
||||
|
||||
private:
|
||||
/// The name of this PropertyOwner
|
||||
std::string _name;
|
||||
@@ -218,6 +232,8 @@ private:
|
||||
std::vector<PropertyOwner*> _subOwners;
|
||||
/// The associations between group identifiers of Property's and human-readable names
|
||||
std::map<std::string, std::string> _groupNames;
|
||||
/// Collection of string tag(s) assigned to this property
|
||||
std::vector<std::string> _tags;
|
||||
};
|
||||
|
||||
} // namespace properties
|
||||
|
||||
@@ -98,7 +98,8 @@ public:
|
||||
void updateFade();
|
||||
void updateRenderer();
|
||||
void updateScreenSpaceRenderables();
|
||||
void render(const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix);
|
||||
void render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix,
|
||||
const glm::mat4& projectionMatrix);
|
||||
|
||||
void renderScreenLog();
|
||||
void renderShutdownInformation(float timer, float fullTime);
|
||||
@@ -211,6 +212,7 @@ private:
|
||||
properties::BoolProperty _applyWarping;
|
||||
properties::BoolProperty _showFrameNumber;
|
||||
properties::BoolProperty _disableMasterRendering;
|
||||
properties::BoolProperty _disableSceneOnMaster;
|
||||
|
||||
float _globalBlackOutFactor;
|
||||
float _fadeDuration;
|
||||
|
||||
@@ -61,6 +61,7 @@ public:
|
||||
static const std::string KeyName;
|
||||
static const std::string KeyParentName;
|
||||
static const std::string KeyDependencies;
|
||||
static const std::string KeyTag;
|
||||
|
||||
SceneGraphNode();
|
||||
~SceneGraphNode();
|
||||
@@ -97,6 +98,8 @@ public:
|
||||
|
||||
glm::dvec3 worldPosition() const;
|
||||
const glm::dmat3& worldRotationMatrix() const;
|
||||
glm::dmat4 modelTransform() const;
|
||||
glm::dmat4 inverseModelTransform() const;
|
||||
double worldScale() const;
|
||||
|
||||
SceneGraphNode* parent() const;
|
||||
@@ -140,6 +143,9 @@ private:
|
||||
glm::dvec3 _worldPositionCached;
|
||||
glm::dmat3 _worldRotationCached;
|
||||
double _worldScaleCached;
|
||||
|
||||
glm::dmat4 _modelTransformCached;
|
||||
glm::dmat4 _inverseModelTransformCached;
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
namespace openspace {
|
||||
|
||||
namespace distanceconstants {
|
||||
const float EarthRadius = 6371;
|
||||
const float LightYear = 9.4607304725808E15;
|
||||
const float AstronomicalUnit = 1.495978707E11;
|
||||
const float Parsec = 3.0856776E16;
|
||||
const float EarthRadius = 6371;
|
||||
const float LightYear = 9.4607304725808E15;
|
||||
const float AstronomicalUnit = 1.495978707E11;
|
||||
const float Parsec = 3.0856776E16;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#ifndef __OPENSPACE_CORE___TIMEMANAGER___H__
|
||||
#define __OPENSPACE_CORE___TIMEMANAGER___H__
|
||||
|
||||
#include <vector>
|
||||
#include <deque>
|
||||
#include <openspace/network/messagestructures.h>
|
||||
|
||||
@@ -35,7 +36,9 @@ public:
|
||||
void preSynchronization(double dt);
|
||||
void addKeyframe(const datamessagestructures::TimeKeyframe& kf);
|
||||
void removeKeyframesBefore(double timestamp);
|
||||
void removeKeyframesAfter(double timestamp);
|
||||
void clearKeyframes();
|
||||
const std::deque<datamessagestructures::TimeKeyframe>& keyframes() const;
|
||||
private:
|
||||
void consumeKeyframes(double dt);
|
||||
std::deque<datamessagestructures::TimeKeyframe> _keyframes;
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
#include <ghoul/filesystem/filesystem>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "ScreenSpaceImage";
|
||||
|
||||
const char* KeyName = "Name";
|
||||
const char* KeyTexturePath = "TexturePath";
|
||||
const char* KeyUrl = "URL";
|
||||
@@ -46,6 +44,7 @@ ScreenSpaceImage::ScreenSpaceImage(const ghoul::Dictionary& dictionary)
|
||||
: ScreenSpaceRenderable(dictionary)
|
||||
, _texturePath("texturePath", "Texture path", "")
|
||||
, _downloadImage(false)
|
||||
, _textureIsDirty(false)
|
||||
{
|
||||
std::string name;
|
||||
if (dictionary.getValue(KeyName, name)) {
|
||||
@@ -61,7 +60,7 @@ ScreenSpaceImage::ScreenSpaceImage(const ghoul::Dictionary& dictionary)
|
||||
std::string texturePath;
|
||||
if (dictionary.getValue(KeyTexturePath, texturePath)) {
|
||||
_texturePath = texturePath;
|
||||
_texturePath.onChange([this](){ loadTexture(); });
|
||||
_texturePath.onChange([this]() { _textureIsDirty = true; });
|
||||
}
|
||||
|
||||
if (dictionary.getValue(KeyUrl, _url)) {
|
||||
@@ -82,7 +81,6 @@ bool ScreenSpaceImage::initialize() {
|
||||
}
|
||||
|
||||
bool ScreenSpaceImage::deinitialize() {
|
||||
|
||||
glDeleteVertexArrays(1, &_quad);
|
||||
_quad = 0;
|
||||
|
||||
@@ -106,7 +104,7 @@ void ScreenSpaceImage::render() {
|
||||
|
||||
void ScreenSpaceImage::update() {
|
||||
bool download = _downloadImage ? (_futureImage.valid() && DownloadManager::futureReady(_futureImage)) : true;
|
||||
if (download) {
|
||||
if (download && _textureIsDirty) {
|
||||
loadTexture();
|
||||
}
|
||||
}
|
||||
@@ -130,6 +128,7 @@ void ScreenSpaceImage::loadTexture() {
|
||||
texture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
|
||||
|
||||
_texture = std::move(texture);
|
||||
_textureIsDirty = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -178,10 +177,16 @@ std::future<DownloadManager::MemoryFile> ScreenSpaceImage::downloadImageToMemory
|
||||
return std::move(OsEng.downloadManager().fetchFile(
|
||||
url,
|
||||
[url](const DownloadManager::MemoryFile& file) {
|
||||
LDEBUG("Download to memory finished for screen space image");
|
||||
LDEBUGC(
|
||||
"ScreenSpaceImage",
|
||||
"Download to memory finished for screen space image"
|
||||
);
|
||||
},
|
||||
[url](const std::string& err) {
|
||||
LDEBUG("Download to memory failer for screen space image: " +err);
|
||||
LDEBUGC(
|
||||
"ScreenSpaceImage",
|
||||
"Download to memory failer for screen space image: " + err
|
||||
);
|
||||
}
|
||||
));
|
||||
}
|
||||
|
||||
@@ -51,6 +51,7 @@ protected:
|
||||
|
||||
std::string _url;
|
||||
bool _downloadImage;
|
||||
bool _textureIsDirty;
|
||||
std::future<DownloadManager::MemoryFile> _futureImage;
|
||||
|
||||
private:
|
||||
@@ -59,6 +60,8 @@ private:
|
||||
std::unique_ptr<ghoul::opengl::Texture> loadFromMemory();
|
||||
|
||||
properties::StringProperty _texturePath;
|
||||
|
||||
|
||||
};
|
||||
|
||||
} // namespace openspace
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#version __CONTEXT__
|
||||
|
||||
uniform sampler2D texture1;
|
||||
uniform float OcclusionDepth;
|
||||
uniform float Alpha;
|
||||
|
||||
@@ -121,7 +121,7 @@ RenderableFieldlines::RenderableFieldlines(const ghoul::Dictionary& dictionary)
|
||||
}
|
||||
|
||||
// @TODO a non-magic number perhaps ---abock
|
||||
setBoundingSphere(PowerScaledScalar::CreatePSS(250.f*6371000.f));
|
||||
setBoundingSphere(250.f*6371000.f);
|
||||
|
||||
_seedPointSource.addOption(SeedPointSourceFile, "File");
|
||||
_seedPointSource.addOption(SeedPointSourceTable, "Lua Table");
|
||||
|
||||
@@ -101,6 +101,7 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/loadjob.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/tileloadjob.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.h
|
||||
@@ -166,6 +167,7 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/asynctiledataprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/pixelregion.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/rawtile.cpp
|
||||
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tile.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tilediskcache.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileindex.cpp
|
||||
@@ -174,6 +176,7 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/diskcachedtileloadjob.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/loadjob/tileloadjob.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/cachingtileprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/presentationslideprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/singleimageprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/sizereferencetileprovider.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/tile/tileprovider/temporaltileprovider.cpp
|
||||
|
||||
@@ -38,17 +38,17 @@ namespace cache {
|
||||
*/
|
||||
class MemoryAwareCacheable {
|
||||
public:
|
||||
/**
|
||||
* \param memoryImpact is the memory impact of the object. Can for example be given
|
||||
* in kilobytes.
|
||||
*/
|
||||
MemoryAwareCacheable(size_t memoryImpact) : _memoryImpact(memoryImpact) {};
|
||||
~MemoryAwareCacheable() {};
|
||||
/**
|
||||
* \param memoryImpact is the memory impact of the object. Can for example be given
|
||||
* in kilobytes.
|
||||
*/
|
||||
MemoryAwareCacheable(size_t memoryImpact) : _memoryImpact(memoryImpact) {};
|
||||
~MemoryAwareCacheable() {};
|
||||
|
||||
size_t memoryImpact() { return _memoryImpact; };
|
||||
|
||||
size_t memoryImpact() { return _memoryImpact; };
|
||||
|
||||
protected:
|
||||
size_t _memoryImpact;
|
||||
size_t _memoryImpact;
|
||||
};
|
||||
|
||||
} // namespace cache
|
||||
|
||||
@@ -103,7 +103,7 @@ private:
|
||||
|
||||
static MemoryAwareTileCache* _singleton;
|
||||
MemoryAwareLRUCache<ProviderTileKey, Tile, ProviderTileHasher> _tileCache;
|
||||
static std::mutex _mutexLock;
|
||||
static std::mutex _mutexLock;
|
||||
};
|
||||
|
||||
} // namespace cache
|
||||
|
||||
36
modules/globebrowsing/ext/gdal/gdal.h
Normal file
36
modules/globebrowsing/ext/gdal/gdal.h
Normal file
@@ -0,0 +1,36 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2017 *
|
||||
* *
|
||||
* 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 __OPENSPACE_MODULE_GLOBEBROWSING___GDAL___H__
|
||||
#define __OPENSPACE_MODULE_GLOBEBROWSING___GDAL___H__
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(push, 0)
|
||||
#endif // WIN32
|
||||
|
||||
#include <gdal_priv.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#pragma warning(pop)
|
||||
#endif // WIN32
|
||||
@@ -37,6 +37,7 @@
|
||||
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
|
||||
#include <modules/globebrowsing/tile/tileprovider/tileproviderbylevel.h>
|
||||
#include <modules/globebrowsing/tile/tileprovider/tileproviderbyindex.h>
|
||||
#include <modules/globebrowsing/tile/tileprovider/presentationslideprovider.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
@@ -89,7 +90,7 @@ void GlobeBrowsingModule::internalInitialize() {
|
||||
CpuCap.installedMainMemory() * 0.25 * 1024 * 1024); // 25% of total RAM
|
||||
addPropertySubOwner(GdalWrapper::ref());
|
||||
#endif // GLOBEBROWSING_USE_GDAL
|
||||
});
|
||||
});
|
||||
|
||||
OsEng.registerModuleCallback(OpenSpaceEngine::CallbackOption::Deinitialize, [&]{
|
||||
cache::MemoryAwareTileCache::ref().clear();
|
||||
@@ -118,7 +119,7 @@ void GlobeBrowsingModule::internalInitialize() {
|
||||
// Combining Tile Providers
|
||||
fTileProvider->registerClass<tileprovider::TileProviderByLevel>("ByLevel");
|
||||
fTileProvider->registerClass<tileprovider::TileProviderByIndex>("ByIndex");
|
||||
|
||||
fTileProvider->registerClass<tileprovider::PresentationSlideProvider>("PresentationSlides");
|
||||
FactoryManager::ref().addFactory(std::move(fTileProvider));
|
||||
}
|
||||
|
||||
|
||||
@@ -107,18 +107,18 @@ ghoul::opengl::ProgramObject* ChunkRenderer::getActivatedProgramWithTileData(
|
||||
std::to_string(debugProps.showHeightResolution));
|
||||
pairs.emplace_back("showHeightIntensities",
|
||||
std::to_string(debugProps.showHeightIntensities));
|
||||
pairs.emplace_back("defaultHeight", std::to_string(Chunk::DEFAULT_HEIGHT));
|
||||
pairs.emplace_back("defaultHeight", std::to_string(Chunk::DEFAULT_HEIGHT));
|
||||
|
||||
pairs.emplace_back("tilePaddingStart",
|
||||
"ivec2(" +
|
||||
std::to_string(RawTileDataReader::padding.start.x) + "," +
|
||||
std::to_string(RawTileDataReader::padding.start.y) + ")"
|
||||
);
|
||||
pairs.emplace_back("tilePaddingSizeDiff",
|
||||
"ivec2(" +
|
||||
std::to_string(RawTileDataReader::padding.numPixels.x) + "," +
|
||||
std::to_string(RawTileDataReader::padding.numPixels.y) + ")"
|
||||
);
|
||||
pairs.emplace_back("tilePaddingStart",
|
||||
"ivec2(" +
|
||||
std::to_string(RawTileDataReader::padding.start.x) + "," +
|
||||
std::to_string(RawTileDataReader::padding.start.y) + ")"
|
||||
);
|
||||
pairs.emplace_back("tilePaddingSizeDiff",
|
||||
"ivec2(" +
|
||||
std::to_string(RawTileDataReader::padding.numPixels.x) + "," +
|
||||
std::to_string(RawTileDataReader::padding.numPixels.y) + ")"
|
||||
);
|
||||
|
||||
// Now the shader program can be accessed
|
||||
ghoul::opengl::ProgramObject* programObject =
|
||||
|
||||
@@ -39,23 +39,23 @@ LayerRenderSettings::LayerRenderSettings()
|
||||
}
|
||||
|
||||
float LayerRenderSettings::performLayerSettings(float currentValue) const {
|
||||
float newValue = currentValue;
|
||||
float newValue = currentValue;
|
||||
|
||||
newValue = glm::sign(newValue) * glm::pow(glm::abs(newValue), gamma);
|
||||
newValue = newValue * multiplier;
|
||||
newValue = newValue * opacity;
|
||||
newValue = glm::sign(newValue) * glm::pow(glm::abs(newValue), gamma);
|
||||
newValue = newValue * multiplier;
|
||||
newValue = newValue * opacity;
|
||||
|
||||
return newValue;
|
||||
return newValue;
|
||||
}
|
||||
|
||||
glm::vec4 LayerRenderSettings::performLayerSettings(glm::vec4 currentValue) const {
|
||||
glm::vec4 newValue = glm::vec4(
|
||||
performLayerSettings(currentValue.r),
|
||||
performLayerSettings(currentValue.g),
|
||||
performLayerSettings(currentValue.b),
|
||||
performLayerSettings(currentValue.a));
|
||||
glm::vec4 newValue = glm::vec4(
|
||||
performLayerSettings(currentValue.r),
|
||||
performLayerSettings(currentValue.g),
|
||||
performLayerSettings(currentValue.b),
|
||||
performLayerSettings(currentValue.a));
|
||||
|
||||
return newValue;
|
||||
return newValue;
|
||||
}
|
||||
|
||||
} // namespace globebrowsing
|
||||
|
||||
@@ -41,7 +41,7 @@ struct LayerRenderSettings : public properties::PropertyOwner {
|
||||
/// This function matches the function with the same name in the
|
||||
/// shader code
|
||||
float performLayerSettings(float currentValue) const;
|
||||
/// This function matches the function with the same name in the
|
||||
/// This function matches the function with the same name in the
|
||||
/// shader code
|
||||
glm::vec4 performLayerSettings(glm::vec4 currentValue) const;
|
||||
};
|
||||
|
||||
@@ -34,11 +34,11 @@ namespace openspace {
|
||||
namespace globebrowsing {
|
||||
|
||||
struct ChunkTile {
|
||||
ChunkTile() : tile(Tile::TileUnavailable) {};
|
||||
ChunkTile(Tile tile, TileUvTransform uvTransform, TileDepthTransform depthTransform) :
|
||||
tile(tile),
|
||||
uvTransform(uvTransform),
|
||||
depthTransform(depthTransform) {};
|
||||
ChunkTile() : tile(Tile::TileUnavailable) {};
|
||||
ChunkTile(Tile tile, TileUvTransform uvTransform, TileDepthTransform depthTransform) :
|
||||
tile(tile),
|
||||
uvTransform(uvTransform),
|
||||
depthTransform(depthTransform) {};
|
||||
|
||||
Tile tile;
|
||||
TileUvTransform uvTransform;
|
||||
|
||||
@@ -31,8 +31,8 @@ namespace globebrowsing {
|
||||
|
||||
TileLoadJob::TileLoadJob(std::shared_ptr<RawTileDataReader> rawTileDataReader,
|
||||
const TileIndex& tileIndex)
|
||||
: _rawTileDataReader(rawTileDataReader)
|
||||
, _chunkIndex(tileIndex) {}
|
||||
: _rawTileDataReader(rawTileDataReader)
|
||||
, _chunkIndex(tileIndex) {}
|
||||
|
||||
void TileLoadJob::execute() {
|
||||
_rawTile = _rawTileDataReader->readTileData(_chunkIndex);
|
||||
|
||||
@@ -54,13 +54,16 @@ std::ostream& operator<<(std::ostream& os, const PixelRegion& pr) {
|
||||
", " << pr.numPixels.y;
|
||||
}
|
||||
|
||||
GdalRawTileDataReader::GdalRawTileDataReader(
|
||||
const std::string& filePath, const Configuration& config)
|
||||
GdalRawTileDataReader::GdalRawTileDataReader(const std::string& filePath,
|
||||
const Configuration& config,
|
||||
const std::string& baseDirectory)
|
||||
: RawTileDataReader(config)
|
||||
, _dataset(nullptr)
|
||||
{
|
||||
_initData = { "", filePath, config.tilePixelSize, config.dataType };
|
||||
_initData.initDirectory = CPLGetCurrentDir();
|
||||
|
||||
std::string initDir = baseDirectory.empty() ? CPLGetCurrentDir() : baseDirectory;
|
||||
|
||||
_initData = { initDir, filePath, config.tilePixelSize, config.dataType };
|
||||
ensureInitialized();
|
||||
}
|
||||
|
||||
@@ -303,6 +306,7 @@ GDALDataset* GdalRawTileDataReader::openGdalDataset(const std::string& filePath)
|
||||
std::string correctedPath = FileSystem::ref().pathByAppendingComponent(
|
||||
_initData.initDirectory, filePath
|
||||
);
|
||||
|
||||
dataset = (GDALDataset *)GDALOpen(correctedPath.c_str(), GA_ReadOnly);
|
||||
if (!dataset) {
|
||||
throw ghoul::RuntimeError("Failed to load dataset:\n" + filePath);
|
||||
|
||||
@@ -60,8 +60,10 @@ public:
|
||||
*
|
||||
* \param filePath, a path to a specific file GDAL can read
|
||||
* \param config, Configuration used for initialization
|
||||
* \param baseDirectory, the base directory to use in future loading operations
|
||||
*/
|
||||
GdalRawTileDataReader(const std::string& filePath, const Configuration& config);
|
||||
GdalRawTileDataReader(const std::string& filePath, const Configuration& config,
|
||||
const std::string& baseDirectory = "");
|
||||
|
||||
virtual ~GdalRawTileDataReader() override;
|
||||
|
||||
|
||||
@@ -105,6 +105,10 @@ GdalWrapper::GdalWrapper(size_t maximumCacheSize,
|
||||
"GDAL_DATA",
|
||||
absPath("${MODULE_GLOBEBROWSING}/gdal_data").c_str()
|
||||
);
|
||||
CPLSetConfigOption(
|
||||
"CPL_TMPDIR",
|
||||
absPath("${BASE_PATH}").c_str()
|
||||
);
|
||||
setGdalProxyConfiguration();
|
||||
CPLSetErrorHandler(gdalErrorHandler);
|
||||
|
||||
|
||||
@@ -132,9 +132,9 @@ TileDepthTransform RawTileDataReader::getDepthTransform() const {
|
||||
|
||||
std::array<double, 6> RawTileDataReader::getGeoTransform() const {
|
||||
std::array<double, 6> padfTransform;
|
||||
|
||||
|
||||
GeodeticPatch globalCoverage(Geodetic2(0,0), Geodetic2(M_PI / 2.0, M_PI));
|
||||
padfTransform[1] = Angle<double>::fromRadians(
|
||||
padfTransform[1] = Angle<double>::fromRadians(
|
||||
globalCoverage.size().lon).asDegrees() / rasterXSize();
|
||||
padfTransform[5] = -Angle<double>::fromRadians(
|
||||
globalCoverage.size().lat).asDegrees() / rasterYSize();
|
||||
|
||||
@@ -51,42 +51,42 @@ public:
|
||||
* Describe if this Tile is good for usage (OK) or otherwise
|
||||
* the reason why it is not.
|
||||
*/
|
||||
enum class Status {
|
||||
/**
|
||||
* E.g when texture data is not currently in memory.
|
||||
* texture and tileMetaData are both null
|
||||
*/
|
||||
Unavailable,
|
||||
enum class Status {
|
||||
/**
|
||||
* E.g when texture data is not currently in memory.
|
||||
* texture and tileMetaData are both null
|
||||
*/
|
||||
Unavailable,
|
||||
|
||||
/**
|
||||
* Can be set by <code>TileProvider</code>s if the requested
|
||||
* <code>TileIndex</code> is undefined for that particular
|
||||
* provider.
|
||||
* texture and metaData are both null
|
||||
*/
|
||||
OutOfRange,
|
||||
/**
|
||||
* Can be set by <code>TileProvider</code>s if the requested
|
||||
* <code>TileIndex</code> is undefined for that particular
|
||||
* provider.
|
||||
* texture and metaData are both null
|
||||
*/
|
||||
OutOfRange,
|
||||
|
||||
/**
|
||||
* An IO Error happend
|
||||
* texture and metaData are both null
|
||||
*/
|
||||
IOError,
|
||||
/**
|
||||
* An IO Error happend
|
||||
* texture and metaData are both null
|
||||
*/
|
||||
IOError,
|
||||
|
||||
/**
|
||||
* The Texture is uploaded to the GPU and good for usage.
|
||||
* texture is defined. metaData may be defined.
|
||||
*/
|
||||
OK
|
||||
};
|
||||
/**
|
||||
* The Texture is uploaded to the GPU and good for usage.
|
||||
* texture is defined. metaData may be defined.
|
||||
*/
|
||||
OK
|
||||
};
|
||||
|
||||
Tile(std::shared_ptr<ghoul::opengl::Texture> texture,
|
||||
std::shared_ptr<TileMetaData> metaData,
|
||||
Status status);
|
||||
~Tile() = default;
|
||||
|
||||
std::shared_ptr<TileMetaData> metaData() const { return _metaData; };
|
||||
Status status() const { return _status; };
|
||||
std::shared_ptr<ghoul::opengl::Texture> texture() const { return _texture; };
|
||||
std::shared_ptr<TileMetaData> metaData() const { return _metaData; };
|
||||
Status status() const { return _status; };
|
||||
std::shared_ptr<ghoul::opengl::Texture> texture() const { return _texture; };
|
||||
|
||||
/**
|
||||
* Instantiates a new tile with a single color.
|
||||
@@ -102,16 +102,16 @@ public:
|
||||
glm::vec2 sizeDiff, glm::uvec2 resolution, glm::vec2 tileUV);
|
||||
static glm::vec2 TileUvToTextureSamplePosition(const TileUvTransform& uvTransform,
|
||||
glm::vec2 tileUV, glm::uvec2 resolution);
|
||||
/**
|
||||
* A tile with status unavailable that any user can return to
|
||||
* indicate that a tile was unavailable.
|
||||
*/
|
||||
static const Tile TileUnavailable;
|
||||
/**
|
||||
* A tile with status unavailable that any user can return to
|
||||
* indicate that a tile was unavailable.
|
||||
*/
|
||||
static const Tile TileUnavailable;
|
||||
|
||||
private:
|
||||
std::shared_ptr<ghoul::opengl::Texture> _texture;
|
||||
std::shared_ptr<TileMetaData> _metaData;
|
||||
Status _status;
|
||||
std::shared_ptr<ghoul::opengl::Texture> _texture;
|
||||
std::shared_ptr<TileMetaData> _metaData;
|
||||
Status _status;
|
||||
};
|
||||
|
||||
} // namespace globebrowsing
|
||||
|
||||
@@ -40,7 +40,9 @@ namespace {
|
||||
const char* KeyDoPreProcessing = "DoPreProcessing";
|
||||
const char* KeyTilePixelSize = "TilePixelSize";
|
||||
const char* KeyFilePath = "FilePath";
|
||||
const char* KeyBasePath = "BasePath";
|
||||
const char* KeyFlushInterval = "FlushInterval";
|
||||
const char* KeyPreCacheLevel = "PreCacheLevel";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
@@ -50,7 +52,7 @@ namespace tileprovider {
|
||||
CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary)
|
||||
: TileProvider(dictionary)
|
||||
, _framesSinceLastRequestFlush(0)
|
||||
, _defaultTile(Tile::TileUnavailable)
|
||||
, _defaultTile(Tile::TileUnavailable)
|
||||
{
|
||||
std::string name = "Name unspecified";
|
||||
dictionary.getValue("Name", name);
|
||||
@@ -84,9 +86,12 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary)
|
||||
framesUntilRequestFlush);
|
||||
}
|
||||
|
||||
std::string basePath;
|
||||
dictionary.getValue(KeyBasePath, basePath);
|
||||
|
||||
// Initialize instance variables
|
||||
#ifdef GLOBEBROWSING_USE_GDAL
|
||||
auto tileDataset = std::make_shared<GdalRawTileDataReader>(filePath, config);
|
||||
auto tileDataset = std::make_shared<GdalRawTileDataReader>(filePath, config, basePath);
|
||||
#else // GLOBEBROWSING_USE_GDAL
|
||||
auto tileDataset = std::make_shared<SimpleRawTileDataReader>(filePath, config);
|
||||
#endif // GLOBEBROWSING_USE_GDAL
|
||||
@@ -99,6 +104,18 @@ CachingTileProvider::CachingTileProvider(const ghoul::Dictionary& dictionary)
|
||||
_asyncTextureDataProvider = std::make_shared<AsyncTileDataProvider>(
|
||||
tileDataset, threadPool);
|
||||
_framesUntilRequestFlush = framesUntilRequestFlush;
|
||||
|
||||
if (dictionary.hasKeyAndValue<double>(KeyPreCacheLevel)) {
|
||||
int preCacheLevel = static_cast<int>(dictionary.value<double>(KeyPreCacheLevel));
|
||||
LDEBUG("Precaching '" << filePath << "' with level '" << preCacheLevel << "'");
|
||||
for (int level = 0; level <= preCacheLevel; ++level) {
|
||||
for (int x = 0; x <= level * 2; ++x) {
|
||||
for (int y = 0; y <= level; ++y) {
|
||||
_asyncTextureDataProvider->enqueueTileIO({ x, y, level });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CachingTileProvider::CachingTileProvider(
|
||||
|
||||
@@ -0,0 +1,118 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/globebrowsing/geometry/geodetic2.h>
|
||||
#include <modules/globebrowsing/tile/tileprovider/presentationslideprovider.h>
|
||||
#include <modules/globebrowsing/tile/tileindex.h>
|
||||
|
||||
#include <ghoul/io/texture/texturereader.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "PresentationSlideProvider";
|
||||
|
||||
const std::string KeyDefaultProvider = "DefaultProvider";
|
||||
const std::string KeySlideProviders = "SlideProviders";
|
||||
const std::string KeyTileIndex = "TileIndex";
|
||||
const std::string KeyTileProvider = "TileProvider";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
namespace globebrowsing {
|
||||
namespace tileprovider {
|
||||
|
||||
PresentationSlideProvider::PresentationSlideProvider(const ghoul::Dictionary& dictionary)
|
||||
: _slideIndex("slideIndex", "slideIndex", 0, 0, _slideProviders.size() - 1)
|
||||
{
|
||||
setName("SlideProvider");
|
||||
ghoul::Dictionary defaultProviderDict = dictionary.value<ghoul::Dictionary>(KeyDefaultProvider);
|
||||
_defaultProvider = TileProvider::createFromDictionary(defaultProviderDict);
|
||||
|
||||
ghoul::Dictionary tileIndexDict = dictionary.value<ghoul::Dictionary>(KeyTileIndex);
|
||||
_tileIndex = TileIndex(tileIndexDict);
|
||||
|
||||
ghoul::Dictionary slideProvidersDict = dictionary.value<ghoul::Dictionary>(KeySlideProviders);
|
||||
_slideProviders.resize(slideProvidersDict.size());
|
||||
for (size_t i = 0; i < slideProvidersDict.size(); i++) {
|
||||
std::string dictKey = std::to_string(i + 1);
|
||||
ghoul::Dictionary providerDict = slideProvidersDict.value<ghoul::Dictionary>(dictKey);
|
||||
_slideProviders[i] = TileProvider::createFromDictionary(providerDict);
|
||||
}
|
||||
|
||||
_slideIndex.setMaxValue(_slideProviders.size() - 1);
|
||||
addProperty(_slideIndex);
|
||||
}
|
||||
|
||||
Tile PresentationSlideProvider::getTile(const TileIndex& tileIndex) {
|
||||
if(tileIndex == _tileIndex){
|
||||
return slideProvider()->getTile(tileIndex);
|
||||
}
|
||||
return Tile::TileUnavailable;
|
||||
|
||||
}
|
||||
|
||||
Tile PresentationSlideProvider::getDefaultTile() {
|
||||
return _defaultProvider->getDefaultTile();
|
||||
}
|
||||
|
||||
Tile::Status PresentationSlideProvider::getTileStatus(const TileIndex& tileIndex) {
|
||||
if(tileIndex == _tileIndex){
|
||||
return slideProvider()->getTileStatus(tileIndex);
|
||||
}
|
||||
return Tile::Status::Unavailable;
|
||||
}
|
||||
|
||||
TileDepthTransform PresentationSlideProvider::depthTransform() {
|
||||
return slideProvider()->depthTransform();
|
||||
}
|
||||
|
||||
void PresentationSlideProvider::update() {
|
||||
slideProvider()->update();
|
||||
_defaultProvider->update();
|
||||
}
|
||||
|
||||
void PresentationSlideProvider::reset() {
|
||||
for(auto& tp : _slideProviders){
|
||||
tp->reset();
|
||||
}
|
||||
_defaultProvider->reset();
|
||||
}
|
||||
|
||||
int PresentationSlideProvider::maxLevel() {
|
||||
return _defaultProvider->maxLevel();
|
||||
}
|
||||
|
||||
TileProvider* PresentationSlideProvider::slideProvider() {
|
||||
int maxIndex = (int)_slideProviders.size() - 1;
|
||||
int clampedIndex = std::max(0, std::min(_slideIndex.value(), maxIndex));
|
||||
_slideIndex.setValue(clampedIndex);
|
||||
return _slideProviders[clampedIndex].get();
|
||||
}
|
||||
|
||||
} // namespace tileprovider
|
||||
} // namespace globebrowsing
|
||||
} // namespace openspace
|
||||
@@ -0,0 +1,70 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2016 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#ifndef __PRESENTATION_SLIDE_PROVIDER__
|
||||
#define __PRESENTATION_SLIDE_PROVIDER__
|
||||
|
||||
#include <modules/globebrowsing/geometry/geodetic2.h>
|
||||
#include <modules/globebrowsing/tile/tileprovider/tileprovider.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/opengl/texture.h>
|
||||
|
||||
#include <openspace/properties/scalarproperty.h>
|
||||
|
||||
#include <memory>
|
||||
#include <unordered_map>
|
||||
|
||||
namespace openspace {
|
||||
namespace globebrowsing {
|
||||
namespace tileprovider {
|
||||
|
||||
class PresentationSlideProvider : public TileProvider {
|
||||
public:
|
||||
PresentationSlideProvider(const ghoul::Dictionary& dictionary);
|
||||
PresentationSlideProvider(const std::string& imagePath);
|
||||
virtual ~PresentationSlideProvider() { }
|
||||
|
||||
virtual Tile getTile(const TileIndex& tileIndex);
|
||||
virtual Tile getDefaultTile();
|
||||
virtual Tile::Status getTileStatus(const TileIndex& index);
|
||||
virtual TileDepthTransform depthTransform();
|
||||
virtual void update();
|
||||
virtual void reset();
|
||||
virtual int maxLevel();
|
||||
|
||||
private:
|
||||
TileProvider* slideProvider();
|
||||
|
||||
TileIndex _tileIndex;
|
||||
properties::IntProperty _slideIndex;
|
||||
std::vector<std::unique_ptr<TileProvider>> _slideProviders;
|
||||
std::unique_ptr<TileProvider> _defaultProvider;
|
||||
};
|
||||
|
||||
} // namespace tileprovider
|
||||
} // namespace globebrowsing
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __PRESENTATION_SLIDE_PROVIDER__
|
||||
@@ -112,7 +112,7 @@ documentation::Documentation ProjectionTileProvider::Documentation() {
|
||||
ProjectionTileProvider::ProjectionTileProvider(const ghoul::Dictionary& dictionary)
|
||||
: _fboProgramObject(nullptr)
|
||||
, _capture(false)
|
||||
, _defaultTile(Tile::TileUnavailable)
|
||||
, _defaultTile(Tile::TileUnavailable)
|
||||
{
|
||||
|
||||
ghoul::Dictionary geometryDictionary;
|
||||
|
||||
@@ -49,7 +49,7 @@ SingleImageProvider::SingleImageProvider(const ghoul::Dictionary& dictionary)
|
||||
|
||||
SingleImageProvider::SingleImageProvider(const std::string& imagePath)
|
||||
: _imagePath(imagePath)
|
||||
, _tile(nullptr, nullptr, Tile::Status::Unavailable)
|
||||
, _tile(nullptr, nullptr, Tile::Status::Unavailable)
|
||||
{
|
||||
reset();
|
||||
}
|
||||
@@ -87,7 +87,7 @@ void SingleImageProvider::reset() {
|
||||
tileTexture->uploadTexture();
|
||||
tileTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
|
||||
|
||||
_tile = Tile(tileTexture, tileMetaData, tileStatus);
|
||||
_tile = Tile(tileTexture, tileMetaData, tileStatus);
|
||||
}
|
||||
|
||||
int SingleImageProvider::maxLevel() {
|
||||
|
||||
@@ -46,7 +46,7 @@ namespace {
|
||||
}
|
||||
|
||||
SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& dictionary)
|
||||
: _backgroundTile(Tile::TileUnavailable)
|
||||
: _backgroundTile(Tile::TileUnavailable)
|
||||
{
|
||||
_fontSize = 50;
|
||||
_font = OsEng.fontManager().font("Mono", _fontSize);
|
||||
@@ -58,9 +58,9 @@ SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& di
|
||||
_ellipsoid = Ellipsoid(radii);
|
||||
|
||||
auto backgroundTileStatus = Tile::Status::Unavailable;
|
||||
std::shared_ptr<ghoul::opengl::Texture> backgroundTileTexture;
|
||||
std::shared_ptr<ghoul::opengl::Texture> backgroundTileTexture;
|
||||
|
||||
std::string backgroundImagePath;
|
||||
std::string backgroundImagePath;
|
||||
if (dictionary.getValue(KeyBackgroundImagePath, backgroundImagePath)) {
|
||||
using namespace ghoul::io;
|
||||
std::string imgAbsPath = absPath(backgroundImagePath);
|
||||
@@ -69,7 +69,7 @@ SizeReferenceTileProvider::SizeReferenceTileProvider(const ghoul::Dictionary& di
|
||||
backgroundTileTexture->setFilter(ghoul::opengl::Texture::FilterMode::Linear);
|
||||
backgroundTileStatus = Tile::Status::OK;
|
||||
}
|
||||
_backgroundTile = Tile(backgroundTileTexture, nullptr, backgroundTileStatus);
|
||||
_backgroundTile = Tile(backgroundTileTexture, nullptr, backgroundTileStatus);
|
||||
}
|
||||
|
||||
void SizeReferenceTileProvider::renderText(const ghoul::fontrendering::FontRenderer&
|
||||
|
||||
@@ -41,8 +41,11 @@ namespace {
|
||||
const char* KeyDoPreProcessing = "DoPreProcessing";
|
||||
const char* KeyMinimumPixelSize = "MinimumPixelSize";
|
||||
const char* KeyFilePath = "FilePath";
|
||||
const char* KeyBasePath = "BasePath";
|
||||
const char* KeyCacheSize = "CacheSize";
|
||||
const char* KeyFlushInterval = "FlushInterval";
|
||||
const char* KeyPreCacheStartTime = "PreCacheStartTime";
|
||||
const char* KeyPreCacheEndTime = "PreCacheEndTime";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
@@ -64,6 +67,8 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
|
||||
throw std::runtime_error(std::string("Must define key '") + KeyFilePath + "'");
|
||||
}
|
||||
|
||||
_datasetFile = absPath(_datasetFile);
|
||||
|
||||
std::ifstream in(_datasetFile.c_str());
|
||||
if (!in.is_open()) {
|
||||
throw ghoul::FileNotFoundError(_datasetFile);
|
||||
@@ -74,7 +79,29 @@ TemporalTileProvider::TemporalTileProvider(const ghoul::Dictionary& dictionary)
|
||||
std::istreambuf_iterator<char>(in),
|
||||
(std::istreambuf_iterator<char>())
|
||||
);
|
||||
|
||||
_initDict.setValue<std::string>(
|
||||
KeyBasePath,
|
||||
ghoul::filesystem::File(_datasetFile).directoryName()
|
||||
);
|
||||
|
||||
_gdalXmlTemplate = consumeTemporalMetaData(xml);
|
||||
|
||||
const bool hasStart = dictionary.hasKeyAndValue<std::string>(KeyPreCacheStartTime);
|
||||
const bool hasEnd = dictionary.hasKeyAndValue<std::string>(KeyPreCacheEndTime);
|
||||
if (hasStart && hasEnd) {
|
||||
const std::string start = dictionary.value<std::string>(KeyPreCacheStartTime);
|
||||
const std::string end = dictionary.value<std::string>(KeyPreCacheEndTime);
|
||||
std::vector<Time> preCacheTimes = _timeQuantizer.quantized(
|
||||
Time(Time::convertTime(start)),
|
||||
Time(Time::convertTime(end))
|
||||
);
|
||||
|
||||
LINFO("Preloading: " << _datasetFile);
|
||||
for (Time& t : preCacheTimes) {
|
||||
getTileProvider(t);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::string TemporalTileProvider::consumeTemporalMetaData(const std::string& xml) {
|
||||
@@ -166,7 +193,7 @@ Tile TemporalTileProvider::getTile(const TileIndex& tileIndex) {
|
||||
}
|
||||
|
||||
Tile TemporalTileProvider::getDefaultTile() {
|
||||
return getTileProvider()->getDefaultTile();
|
||||
return getTileProvider()->getDefaultTile();
|
||||
}
|
||||
|
||||
int TemporalTileProvider::maxLevel() {
|
||||
@@ -228,33 +255,20 @@ std::shared_ptr<TileProvider> TemporalTileProvider::getTileProvider(TimeKey time
|
||||
}
|
||||
|
||||
std::shared_ptr<TileProvider> TemporalTileProvider::initTileProvider(TimeKey timekey) {
|
||||
static const std::vector<std::string> AllowedToken = {
|
||||
// From: http://www.gdal.org/frmt_wms.html
|
||||
// @FRAGILE: What happens if a user specifies one of these as path tokens?
|
||||
// ---abock
|
||||
"${x}",
|
||||
"${y}",
|
||||
"${z}",
|
||||
"${version}",
|
||||
"${format}",
|
||||
"${layer}"
|
||||
};
|
||||
|
||||
std::string gdalDatasetXml = getGdalDatasetXML(timekey);
|
||||
try {
|
||||
gdalDatasetXml = absPath(gdalDatasetXml);
|
||||
}
|
||||
catch (ghoul::filesystem::FileSystem::ResolveTokenException& e) {
|
||||
const std::vector<std::string> AllowedToken = {
|
||||
// From: http://www.gdal.org/frmt_wms.html
|
||||
// @FRAGILE: What happens if a user specifies one of these as path tokens?
|
||||
// ---abock
|
||||
"${x}",
|
||||
"${y}",
|
||||
"${z}",
|
||||
"${version}",
|
||||
"${format}",
|
||||
"${layer}"
|
||||
};
|
||||
|
||||
auto it = std::find(AllowedToken.begin(), AllowedToken.end(), e.token);
|
||||
if (it == AllowedToken.end()) {
|
||||
throw;
|
||||
}
|
||||
LINFOC(
|
||||
"TemporalTileProvider",
|
||||
fmt::format("Ignoring '{}' in absolute path resolve", e.token)
|
||||
);
|
||||
}
|
||||
|
||||
FileSys.expandPathTokens(gdalDatasetXml, AllowedToken);
|
||||
|
||||
_initDict.setValue<std::string>(KeyFilePath, gdalDatasetXml);
|
||||
auto tileProvider = std::make_shared<CachingTileProvider>(_initDict);
|
||||
@@ -282,6 +296,16 @@ std::string YYYY_MM_DD::stringify(const Time& t) const {
|
||||
return t.ISO8601().substr(0, 10);
|
||||
}
|
||||
|
||||
std::string YYYYMMDD_hhmmss::stringify(const Time& t) const {
|
||||
std::string ts = t.ISO8601().substr(0, 19);
|
||||
|
||||
// YYYY_MM_DDThh_mm_ss -> YYYYMMDD_hhmmss
|
||||
ts.erase(std::remove(ts.begin(), ts.end(), '-'), ts.end());
|
||||
ts.erase(std::remove(ts.begin(), ts.end(), ':'), ts.end());
|
||||
replace(ts.begin(), ts.end(), 'T', '_');
|
||||
return ts;
|
||||
}
|
||||
|
||||
std::string YYYY_MM_DDThhColonmmColonssZ::stringify(const Time& t) const {
|
||||
return t.ISO8601().substr(0, 19) + "Z";
|
||||
}
|
||||
@@ -305,10 +329,12 @@ void TimeIdProviderFactory::init() {
|
||||
_timeIdProviderMap.insert(std::pair<std::string, std::unique_ptr<TimeFormat>>(
|
||||
{ "YYYY-MM-DDThh:mm:ssZ", std::make_unique<YYYY_MM_DDThhColonmmColonssZ>() }
|
||||
));
|
||||
initialized = true;
|
||||
_timeIdProviderMap.insert(std::pair<std::string, std::unique_ptr<TimeFormat>>(
|
||||
{ "YYYY-MM-DDThh_mm_ssZ", std::make_unique<YYYY_MM_DDThh_mm_ssZ>() }
|
||||
));
|
||||
_timeIdProviderMap.insert(std::pair<std::string, std::unique_ptr<TimeFormat>>(
|
||||
{ "YYYYMMDD_hhmmss", std::make_unique<YYYYMMDD_hhmmss>() }
|
||||
));
|
||||
initialized = true;
|
||||
}
|
||||
|
||||
@@ -379,6 +405,28 @@ bool TimeQuantizer::quantize(Time& t, bool clamp) const {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Time> TimeQuantizer::quantized(const Time& start, const Time& end) const {
|
||||
Time s = start;
|
||||
quantize(s, true);
|
||||
|
||||
Time e = end;
|
||||
quantize(e, true);
|
||||
|
||||
const double startSeconds = s.j2000Seconds();
|
||||
const double endSeconds = e.j2000Seconds();
|
||||
const double delta = endSeconds - startSeconds;
|
||||
|
||||
ghoul_assert(int(delta) % int(_resolution) == 0, "Quantization error");
|
||||
const int nSteps = delta / _resolution;
|
||||
|
||||
std::vector<Time> result(nSteps + 1);
|
||||
for (int i = 0; i <= nSteps; ++i) {
|
||||
result[i].setTime(startSeconds + i * _resolution, false);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace tileprovider
|
||||
} // namespace globebrowsing
|
||||
} // namespace openspace
|
||||
|
||||
@@ -66,6 +66,14 @@ struct YYYY_MM_DD : public TimeFormat {
|
||||
virtual std::string stringify(const Time& t) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stringifies OpenSpace to the format "YYYYMMDD_hhmmss"
|
||||
* Example: 20160908_230505
|
||||
*/
|
||||
struct YYYYMMDD_hhmmss : public TimeFormat {
|
||||
virtual std::string stringify(const Time& t) const;
|
||||
};
|
||||
|
||||
/**
|
||||
* Stringifies OpenSpace to the format "YYYY-MM-DDThh:mm:ssZ"
|
||||
* Example: 2016-09-08T23:05:05Z
|
||||
@@ -143,6 +151,15 @@ struct TimeQuantizer {
|
||||
*/
|
||||
bool quantize(Time& t, bool clamp) const;
|
||||
|
||||
/**
|
||||
* Returns a list of quantized Time objects that represent all the valid quantized
|
||||
* Time%s between \p start and \p end.
|
||||
* \param start The start time for the time range quantization
|
||||
* \param end The end time for the time range quantization
|
||||
* \return A list of quantized times between \p start and \end
|
||||
*/
|
||||
std::vector<Time> quantized(const Time& start, const Time& end) const;
|
||||
|
||||
private:
|
||||
TimeRange _timerange;
|
||||
double _resolution;
|
||||
|
||||
@@ -34,8 +34,6 @@
|
||||
#include <climits>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "TileProvider";
|
||||
|
||||
const char* KeyType = "Type";
|
||||
}
|
||||
|
||||
@@ -50,18 +48,13 @@ std::unique_ptr<TileProvider> TileProvider::createFromDictionary(const ghoul::Di
|
||||
dictionary.getValue(KeyType, type);
|
||||
auto factory = FactoryManager::ref().factory<TileProvider>();
|
||||
std::unique_ptr<TileProvider> result = factory->create(type, dictionary);
|
||||
|
||||
if (result == nullptr) {
|
||||
LERROR("Failed creating TileProvider of type '" << type << "'");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
TileProvider::TileProvider() :
|
||||
properties::PropertyOwner("tileProvider"),
|
||||
_initialized(false) {
|
||||
TileProvider::TileProvider()
|
||||
: properties::PropertyOwner("tileProvider")
|
||||
, _initialized(false)
|
||||
{
|
||||
initialize();
|
||||
}
|
||||
|
||||
|
||||
@@ -41,10 +41,10 @@ namespace tileselector {
|
||||
ChunkTile getHighestResolutionTile(const LayerGroup& layerGroup, const TileIndex& tileIndex);
|
||||
|
||||
std::vector<ChunkTile> getTilesSortedByHighestResolution(const LayerGroup& layerGroup,
|
||||
const TileIndex& tileIndex);
|
||||
const TileIndex& tileIndex);
|
||||
std::vector<std::pair<ChunkTile, const LayerRenderSettings*> >
|
||||
getTilesAndSettingsSortedByHighestResolution(const LayerGroup& layerGroup,
|
||||
const TileIndex& tileIndex);
|
||||
getTilesAndSettingsSortedByHighestResolution(const LayerGroup& layerGroup,
|
||||
const TileIndex& tileIndex);
|
||||
|
||||
void ascendToParent(TileIndex& tileIndex, TileUvTransform& uv);
|
||||
|
||||
|
||||
@@ -109,7 +109,7 @@ void KameleonDocumentationTask::perform(const Task::ProgressCallback & progressC
|
||||
file.exceptions(~std::ofstream::goodbit);
|
||||
file.open(_outputPath);
|
||||
|
||||
std::stringstream html;
|
||||
std::stringstream html;
|
||||
html << "<!DOCTYPE html>\n"
|
||||
<< "<html>\n"
|
||||
<< "\t<head>\n"
|
||||
|
||||
@@ -30,6 +30,7 @@ set(HEADER_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guihelpcomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guiorigincomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guiperformancecomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guiparallelcomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guipropertycomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guitimecomponent.h
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/include/guiiswacomponent.h
|
||||
@@ -44,6 +45,7 @@ set(SOURCE_FILES
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guihelpcomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guiorigincomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guiperformancecomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guiparallelcomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guipropertycomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guitimecomponent.cpp
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/src/guiiswacomponent.cpp
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#include <modules/onscreengui/include/guiorigincomponent.h>
|
||||
#include <modules/onscreengui/include/guitimecomponent.h>
|
||||
#include <modules/onscreengui/include/guiiswacomponent.h>
|
||||
#include <modules/onscreengui/include/guiparallelcomponent.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
#include <openspace/properties/property.h>
|
||||
|
||||
@@ -72,6 +73,7 @@ public:
|
||||
GuiPropertyComponent _virtualProperty;
|
||||
GuiTimeComponent _time;
|
||||
GuiIswaComponent _iswa;
|
||||
GuiParallelComponent _parallel;
|
||||
|
||||
private:
|
||||
void renderAndUpdatePropertyVisibility();
|
||||
|
||||
51
modules/onscreengui/include/guiparallelcomponent.h
Normal file
51
modules/onscreengui/include/guiparallelcomponent.h
Normal file
@@ -0,0 +1,51 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2017 *
|
||||
* *
|
||||
* 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 __OPENSPACE_MODULE_ONSCREENGUI___GUIPARALLELCOMPONENT___H__
|
||||
#define __OPENSPACE_MODULE_ONSCREENGUI___GUIPARALLELCOMPONENT___H__
|
||||
|
||||
#include <modules/onscreengui/include/guicomponent.h>
|
||||
#include <modules/onscreengui/include/guipropertycomponent.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace openspace {
|
||||
namespace gui {
|
||||
|
||||
class GuiParallelComponent : public GuiPropertyComponent {
|
||||
public:
|
||||
GuiParallelComponent();
|
||||
void render() override;
|
||||
private:
|
||||
void renderDisconnected();
|
||||
void renderClientWithHost();
|
||||
void renderClientWithoutHost();
|
||||
void renderClientCommon();
|
||||
void renderHost();
|
||||
};
|
||||
|
||||
} // namespace gui
|
||||
} // namespace openspace
|
||||
|
||||
#endif // __OPENSPACE_MODULE_ONSCREENGUI___GUIPARALLELCOMPONENT___H__
|
||||
@@ -31,6 +31,7 @@
|
||||
#include <openspace/engine/virtualpropertymanager.h>
|
||||
#include <openspace/engine/wrapper/windowwrapper.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/rendering/renderengine.h>
|
||||
#include <openspace/rendering/screenspacerenderable.h>
|
||||
#include <openspace/scene/scene.h>
|
||||
@@ -59,7 +60,8 @@ OnScreenGUIModule::OnScreenGUIModule()
|
||||
&(OsEng.windowWrapper()),
|
||||
&(OsEng.settingsEngine()),
|
||||
&(OsEng.interactionHandler()),
|
||||
&(OsEng.renderEngine())
|
||||
&(OsEng.renderEngine()),
|
||||
&(OsEng.parallelConnection())
|
||||
};
|
||||
return res;
|
||||
}
|
||||
@@ -118,11 +120,14 @@ OnScreenGUIModule::OnScreenGUIModule()
|
||||
);
|
||||
|
||||
OsEng.registerModuleCallback(
|
||||
OpenSpaceEngine::CallbackOption::Render,
|
||||
// This is done in the PostDraw phase so that it will render it on top of
|
||||
// everything else in the case of fisheyes. With this being in the Render callback
|
||||
// the GUI would be rendered on top of each of the cube faces
|
||||
OpenSpaceEngine::CallbackOption::PostDraw,
|
||||
[](){
|
||||
WindowWrapper& wrapper = OsEng.windowWrapper();
|
||||
bool showGui = wrapper.hasGuiWindow() ? wrapper.isGuiWindow() : true;
|
||||
if (wrapper.isMaster() && wrapper.isRegularRendering() && showGui ) {
|
||||
if (wrapper.isMaster() && showGui ) {
|
||||
glm::vec2 mousePosition = wrapper.mousePosition();
|
||||
//glm::ivec2 drawBufferResolution = _windowWrapper->currentDrawBufferResolution();
|
||||
glm::ivec2 windowSize = wrapper.currentWindowSize();
|
||||
|
||||
@@ -322,6 +322,7 @@ void GUI::initialize() {
|
||||
_virtualProperty.initialize();
|
||||
_performance.initialize();
|
||||
_help.initialize();
|
||||
_parallel.initialize();
|
||||
_iswa.initialize();
|
||||
}
|
||||
|
||||
@@ -329,6 +330,7 @@ void GUI::deinitialize() {
|
||||
ImGui::Shutdown();
|
||||
|
||||
_iswa.deinitialize();
|
||||
_parallel.deinitialize();
|
||||
_help.deinitialize();
|
||||
_performance.deinitialize();
|
||||
_globalProperty.deinitialize();
|
||||
@@ -408,6 +410,7 @@ void GUI::initializeGL() {
|
||||
_globalProperty.initializeGL();
|
||||
_performance.initializeGL();
|
||||
_help.initializeGL();
|
||||
_parallel.initializeGL();
|
||||
_iswa.initializeGL();
|
||||
}
|
||||
|
||||
@@ -426,6 +429,7 @@ void GUI::deinitializeGL() {
|
||||
}
|
||||
|
||||
_iswa.deinitializeGL();
|
||||
_parallel.deinitializeGL();
|
||||
_help.deinitializeGL();
|
||||
_performance.deinitializeGL();
|
||||
_globalProperty.deinitializeGL();
|
||||
@@ -471,14 +475,15 @@ void GUI::endFrame() {
|
||||
if (_screenSpaceProperty.isEnabled()) {
|
||||
_screenSpaceProperty.render();
|
||||
}
|
||||
|
||||
if (_virtualProperty.isEnabled()) {
|
||||
_virtualProperty.render();
|
||||
}
|
||||
|
||||
if (_help.isEnabled()) {
|
||||
_help.render();
|
||||
}
|
||||
if (_parallel.isEnabled()) {
|
||||
_parallel.render();
|
||||
}
|
||||
if (_iswa.isEnabled()) {
|
||||
_iswa.render();
|
||||
}
|
||||
@@ -570,6 +575,10 @@ void GUI::render() {
|
||||
ImGui::Checkbox("Global Properties", &globalProperty);
|
||||
_globalProperty.setEnabled(globalProperty);
|
||||
|
||||
bool parallel = _parallel.isEnabled();
|
||||
ImGui::Checkbox("Parallel Connection", ¶llel);
|
||||
_parallel.setEnabled(parallel);
|
||||
|
||||
bool virtualProperty = _virtualProperty.isEnabled();
|
||||
ImGui::Checkbox("Virtual Properties", &virtualProperty);
|
||||
_virtualProperty.setEnabled(virtualProperty);
|
||||
|
||||
191
modules/onscreengui/src/guiparallelcomponent.cpp
Normal file
191
modules/onscreengui/src/guiparallelcomponent.cpp
Normal file
@@ -0,0 +1,191 @@
|
||||
/*****************************************************************************************
|
||||
* *
|
||||
* OpenSpace *
|
||||
* *
|
||||
* Copyright (c) 2014-2017 *
|
||||
* *
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this *
|
||||
* software and associated documentation files (the "Software"), to deal in the Software *
|
||||
* without restriction, including without limitation the rights to use, copy, modify, *
|
||||
* merge, publish, distribute, sublicense, and/or sell copies of the Software, and to *
|
||||
* permit persons to whom the Software is furnished to do so, subject to the following *
|
||||
* conditions: *
|
||||
* *
|
||||
* The above copyright notice and this permission notice shall be included in all copies *
|
||||
* or substantial portions of the Software. *
|
||||
* *
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, *
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A *
|
||||
* PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT *
|
||||
* HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF *
|
||||
* CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE *
|
||||
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
|
||||
****************************************************************************************/
|
||||
|
||||
#include <modules/onscreengui/include/guiparallelcomponent.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/network/messagestructures.h>
|
||||
|
||||
#include <imgui.h>
|
||||
#include <fmt/format.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <numeric>
|
||||
|
||||
namespace {
|
||||
const std::string _loggerCat = "GuiParallelComponent";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
namespace gui {
|
||||
|
||||
GuiParallelComponent::GuiParallelComponent()
|
||||
: GuiPropertyComponent("GuiParallelComponent")
|
||||
{
|
||||
setVisibility(properties::Property::Visibility::All);
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderDisconnected() {
|
||||
ImGui::Text("Not connected");
|
||||
|
||||
const bool connect = ImGui::Button("Connect");
|
||||
|
||||
if (connect) {
|
||||
OsEng.parallelConnection().clientConnect();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderClientWithHost() {
|
||||
|
||||
ParallelConnection& parallel = OsEng.parallelConnection();
|
||||
|
||||
std::string connectionInfo = "Session hosted by \"" + parallel.hostName() + "\"\n";
|
||||
size_t nConnections = parallel.nConnections();
|
||||
size_t nClients = nConnections - 1;
|
||||
|
||||
if (nClients > 2) {
|
||||
std::string c = std::to_string(nClients - 1);
|
||||
connectionInfo += "You and " + c + " more clients are connected";
|
||||
}
|
||||
else if (nClients == 2) {
|
||||
std::string c = std::to_string(nClients - 1);
|
||||
connectionInfo += "You and " + c + " more client are connected";
|
||||
}
|
||||
else if (nClients == 1) {
|
||||
connectionInfo += "You are the only client";
|
||||
}
|
||||
|
||||
ImGui::Text(connectionInfo.c_str());
|
||||
renderClientCommon();
|
||||
|
||||
const std::deque<datamessagestructures::TimeKeyframe> timeKeyframes = OsEng.timeManager().keyframes();
|
||||
const std::vector<datamessagestructures::CameraKeyframe> cameraKeyframes = OsEng.interactionHandler().keyframes();
|
||||
|
||||
std::string timeKeyframeInfo = "TimeKeyframes : " + std::to_string(timeKeyframes.size());
|
||||
std::string cameraKeyframeInfo = "CameraKeyframes : " + std::to_string(cameraKeyframes.size());
|
||||
std::string latencyStandardDeviation = "Latency standard deviation: " + std::to_string(parallel.latencyStandardDeviation()) + " s";
|
||||
|
||||
const bool resetTimeOffset = ImGui::Button("Reset time offset");
|
||||
|
||||
if (resetTimeOffset) {
|
||||
parallel.resetTimeOffset();
|
||||
}
|
||||
|
||||
ImGui::Text(timeKeyframeInfo.c_str());
|
||||
ImGui::Text(cameraKeyframeInfo.c_str());
|
||||
ImGui::Text(latencyStandardDeviation.c_str());
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderClientWithoutHost() {
|
||||
ParallelConnection& parallel = OsEng.parallelConnection();
|
||||
|
||||
std::string connectionInfo = "Connected to parallel session with no host\n";
|
||||
size_t nConnections = parallel.nConnections();
|
||||
|
||||
if (nConnections > 2) {
|
||||
std::string c = std::to_string(nConnections - 1);
|
||||
connectionInfo += "You and " + c + " more users are connected";
|
||||
}
|
||||
else if (nConnections == 2) {
|
||||
std::string c = std::to_string(nConnections - 1);
|
||||
connectionInfo += "You and " + c + " more users are connected";
|
||||
}
|
||||
else if (nConnections == 1) {
|
||||
connectionInfo += "You are the only one here";
|
||||
}
|
||||
|
||||
ImGui::Text(connectionInfo.c_str());
|
||||
|
||||
renderClientCommon();
|
||||
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderClientCommon() {
|
||||
ParallelConnection& parallel = OsEng.parallelConnection();
|
||||
|
||||
bool requestHostship = ImGui::Button("Request hostship");
|
||||
const bool disconnect = ImGui::Button("Disconnect");
|
||||
|
||||
if (requestHostship) {
|
||||
parallel.requestHostship();
|
||||
}
|
||||
|
||||
if (disconnect) {
|
||||
parallel.signalDisconnect();
|
||||
}
|
||||
}
|
||||
|
||||
void GuiParallelComponent::renderHost() {
|
||||
ParallelConnection& parallel = OsEng.parallelConnection();
|
||||
size_t nConnections = parallel.nConnections();
|
||||
|
||||
std::string connectionInfo = "";
|
||||
size_t nClients = nConnections - 1;
|
||||
if (nClients == 1) {
|
||||
connectionInfo = "Hosting session with 1 client";
|
||||
} else {
|
||||
connectionInfo =
|
||||
"Hosting session with " + std::to_string(nClients) + " clients";
|
||||
}
|
||||
|
||||
ImGui::Text(connectionInfo.c_str());
|
||||
|
||||
const bool resignHostship = ImGui::Button("Resign hostship");
|
||||
if (resignHostship) {
|
||||
parallel.resignHostship();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GuiParallelComponent::render() {
|
||||
bool v = _isEnabled;
|
||||
ImGui::Begin("Parallel Connection", &v);
|
||||
_isEnabled = v;
|
||||
|
||||
ParallelConnection::Status status = OsEng.parallelConnection().status();
|
||||
|
||||
switch (status) {
|
||||
case ParallelConnection::Status::Disconnected:
|
||||
renderDisconnected();
|
||||
break;
|
||||
case ParallelConnection::Status::ClientWithHost:
|
||||
renderClientWithHost();
|
||||
break;
|
||||
case ParallelConnection::Status::ClientWithoutHost:
|
||||
renderClientWithoutHost();
|
||||
break;
|
||||
case ParallelConnection::Status::Host:
|
||||
renderHost();
|
||||
break;
|
||||
}
|
||||
|
||||
GuiPropertyComponent::renderPropertyOwner(&OsEng.parallelConnection());
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
} // namespace gui
|
||||
} // namespace openspace
|
||||
@@ -91,7 +91,16 @@ return {
|
||||
-- OnScreenTextScaling = "framebuffer",
|
||||
-- PerSceneCache = true,
|
||||
-- DisableRenderingOnMaster = true,
|
||||
KeyDisableSceneOnMaster = true,
|
||||
DownloadRequestURL = "http://data.openspaceproject.com/request.cgi",
|
||||
RenderingMethod = "Framebuffer"
|
||||
RenderingMethod = "Framebuffer",
|
||||
OpenGLDebugContext = {
|
||||
Activate = true,
|
||||
FilterIdentifier = {
|
||||
{ Type = "Other", Source = "API", Identifier = 131185 }
|
||||
},
|
||||
-- FilterSeverity = { }
|
||||
|
||||
}
|
||||
--RenderingMethod = "ABuffer" -- alternative: "Framebuffer"
|
||||
}
|
||||
|
||||
@@ -206,6 +206,14 @@ std::string StringListVerifier::type() const {
|
||||
return "List of strings";
|
||||
}
|
||||
|
||||
IntListVerifier::IntListVerifier(std::string elementDocumentation)
|
||||
: TableVerifier({ { "*", new IntVerifier, std::move(elementDocumentation) } })
|
||||
{}
|
||||
|
||||
std::string IntListVerifier::type() const {
|
||||
return "List of ints";
|
||||
}
|
||||
|
||||
ReferencingVerifier::ReferencingVerifier(std::string id)
|
||||
: identifier(std::move(id))
|
||||
{
|
||||
|
||||
@@ -73,6 +73,7 @@ const string ConfigurationManager::KeyCapabilitiesVerbosity =
|
||||
|
||||
const string ConfigurationManager::KeyShutdownCountdown = "ShutdownCountdown";
|
||||
const string ConfigurationManager::KeyDisableMasterRendering = "DisableRenderingOnMaster";
|
||||
const string ConfigurationManager::KeyDisableSceneOnMaster = "DisableSceneOnMaster";
|
||||
const string ConfigurationManager::KeyDownloadRequestURL = "DownloadRequestURL";
|
||||
const string ConfigurationManager::KeyPerSceneCache = "PerSceneCache";
|
||||
const string ConfigurationManager::KeyRenderingMethod = "RenderingMethod";
|
||||
@@ -86,6 +87,15 @@ const string ConfigurationManager::PartHttpProxyAuthentication = "Authentication
|
||||
const string ConfigurationManager::PartHttpProxyUser = "User";
|
||||
const string ConfigurationManager::PartHttpProxyPassword = "Password";
|
||||
|
||||
const string ConfigurationManager::KeyOpenGLDebugContext = "OpenGLDebugContext";
|
||||
const string ConfigurationManager::PartActivate = "Activate";
|
||||
const string ConfigurationManager::PartSynchronous = "Synchronous";
|
||||
const string ConfigurationManager::PartFilterIdentifier = "FilterIdentifier";
|
||||
const string ConfigurationManager::PartFilterIdentifierSource = "Source";
|
||||
const string ConfigurationManager::PartFilterIdentifierType = "Type";
|
||||
const string ConfigurationManager::PartFilterIdentifierIdentifier = "Identifier";
|
||||
const string ConfigurationManager::PartFilterSeverity = "PartFilterSeverity";
|
||||
|
||||
string ConfigurationManager::findConfiguration(const string& filename) {
|
||||
using ghoul::filesystem::Directory;
|
||||
|
||||
|
||||
@@ -338,6 +338,16 @@ documentation::Documentation ConfigurationManager::Documentation() {
|
||||
"the master computer does not have the resources to render a scene.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyDisableSceneOnMaster,
|
||||
new BoolVerifier,
|
||||
"Toggles whether a potential scene transformation matrix, for example as "
|
||||
"specified in an SGCT configuration file, should apply to the master node. "
|
||||
"With some configurations, applying such a transformation complicates the "
|
||||
"interaction and it is thus desired to disable the transformation. The "
|
||||
"default is false.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyHttpProxy,
|
||||
new TableVerifier({
|
||||
@@ -375,7 +385,80 @@ documentation::Documentation ConfigurationManager::Documentation() {
|
||||
"This defines the use for a proxy when fetching data over http."
|
||||
"No proxy will be used if this is left out.",
|
||||
Optional::Yes
|
||||
}
|
||||
},
|
||||
{
|
||||
ConfigurationManager::KeyOpenGLDebugContext,
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartActivate,
|
||||
new BoolVerifier,
|
||||
"Determines whether the OpenGL context should be a debug context",
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartSynchronous,
|
||||
new BoolVerifier,
|
||||
"Determines whether the OpenGL debug callbacks are performed "
|
||||
"synchronously. If set to <True> the callbacks are in the same thead "
|
||||
"as the context and in the scope of the OpenGL function that "
|
||||
"triggered the message. The default value is <True>.",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFilterIdentifier,
|
||||
new TableVerifier({{
|
||||
"*",
|
||||
new TableVerifier({
|
||||
{
|
||||
ConfigurationManager::PartFilterIdentifierIdentifier,
|
||||
new IntVerifier,
|
||||
"The identifier that is to be filtered",
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFilterIdentifierSource,
|
||||
new StringInListVerifier({
|
||||
// Taken from ghoul::debugcontext.cpp
|
||||
"API", "Window System", "Shader Compiler",
|
||||
"Third Party", "Application", "Other", "Don't care"
|
||||
}),
|
||||
"The source of the identifier to be filtered",
|
||||
Optional::No
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFilterIdentifierType,
|
||||
new StringInListVerifier({
|
||||
// Taken from ghoul::debugcontext.cpp
|
||||
"Error", "Deprecated", "Undefined", "Portability",
|
||||
"Performance", "Marker", "Push group", "Pop group",
|
||||
"Other", "Don't care"
|
||||
}),
|
||||
"The type of the identifier to be filtered"
|
||||
}
|
||||
}),
|
||||
"Individual OpenGL debug message identifiers"
|
||||
}}),
|
||||
"A list of OpenGL debug messages identifiers that are filtered",
|
||||
Optional::Yes
|
||||
},
|
||||
{
|
||||
ConfigurationManager::PartFilterSeverity,
|
||||
new TableVerifier({
|
||||
{
|
||||
"*",
|
||||
new StringInListVerifier(
|
||||
// ghoul::debugcontext.cpp
|
||||
{ "High", "Medium", "Low", "Notification" }
|
||||
)
|
||||
}
|
||||
}),
|
||||
"A list of severities that can are filtered out",
|
||||
Optional::Yes
|
||||
}
|
||||
}),
|
||||
"Determines the settings for the creation of an OpenGL debug context.",
|
||||
Optional::Yes
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/interaction/luaconsole.h>
|
||||
#include <openspace/network/networkengine.h>
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/rendering/renderable.h>
|
||||
#include <openspace/scripting/scriptscheduler.h>
|
||||
#include <openspace/scripting/scriptengine.h>
|
||||
@@ -66,6 +67,7 @@
|
||||
#include <ghoul/font/fontrenderer.h>
|
||||
#include <ghoul/logging/consolelog.h>
|
||||
#include <ghoul/logging/visualstudiooutputlog.h>
|
||||
#include <ghoul/opengl/debugcontext.h>
|
||||
#include <ghoul/systemcapabilities/systemcapabilities>
|
||||
|
||||
|
||||
@@ -133,7 +135,7 @@ OpenSpaceEngine::OpenSpaceEngine(
|
||||
, _settingsEngine(new SettingsEngine)
|
||||
, _timeManager(new TimeManager)
|
||||
, _downloadManager(nullptr)
|
||||
, _parallelConnection(new ParallelConnection)
|
||||
, _parallelConnection(std::make_unique<ParallelConnection>())
|
||||
, _windowWrapper(std::move(windowWrapper))
|
||||
, _globalPropertyNamespace(new properties::PropertyOwner(""))
|
||||
, _virtualPropertyManager(new VirtualPropertyManager)
|
||||
@@ -150,7 +152,8 @@ OpenSpaceEngine::OpenSpaceEngine(
|
||||
_globalPropertyNamespace->addPropertySubOwner(_settingsEngine.get());
|
||||
_globalPropertyNamespace->addPropertySubOwner(_renderEngine.get());
|
||||
_globalPropertyNamespace->addPropertySubOwner(_windowWrapper.get());
|
||||
|
||||
_globalPropertyNamespace->addPropertySubOwner(_parallelConnection.get());
|
||||
|
||||
FactoryManager::initialize();
|
||||
FactoryManager::ref().addFactory(
|
||||
std::make_unique<ghoul::TemplateFactory<Renderable>>(),
|
||||
@@ -369,6 +372,10 @@ void OpenSpaceEngine::create(int argc, char** argv,
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::destroy() {
|
||||
if (_engine->parallelConnection().status() != ParallelConnection::Status::Disconnected) {
|
||||
_engine->parallelConnection().signalDisconnect();
|
||||
}
|
||||
|
||||
LTRACE("OpenSpaceEngine::destroy(begin)");
|
||||
for (const auto& func : _engine->_moduleCallbacks.deinitializeGL) {
|
||||
func();
|
||||
@@ -901,6 +908,111 @@ void OpenSpaceEngine::configureLogging() {
|
||||
void OpenSpaceEngine::initializeGL() {
|
||||
LTRACE("OpenSpaceEngine::initializeGL(begin)");
|
||||
|
||||
const std::string key = ConfigurationManager::KeyOpenGLDebugContext;
|
||||
if (_configurationManager->hasKey(key)) {
|
||||
ghoul::Dictionary dict = _configurationManager->value<ghoul::Dictionary>(key);
|
||||
bool debug = dict.value<bool>(ConfigurationManager::PartActivate);
|
||||
|
||||
// Debug output is not available before 4.3
|
||||
const ghoul::systemcapabilities::Version minVersion = { 4, 3, 0 };
|
||||
if (OpenGLCap.openGLVersion() < minVersion) {
|
||||
LINFO("OpenGL Debug context requested, but insufficient version available");
|
||||
debug = false;
|
||||
}
|
||||
|
||||
if (debug) {
|
||||
using namespace ghoul::opengl::debug;
|
||||
|
||||
bool synchronous = true;
|
||||
if (dict.hasKey(ConfigurationManager::PartSynchronous)) {
|
||||
synchronous = dict.value<bool>(ConfigurationManager::PartSynchronous);
|
||||
}
|
||||
|
||||
setDebugOutput(DebugOutput(debug), SynchronousOutput(synchronous));
|
||||
|
||||
|
||||
if (dict.hasKey(ConfigurationManager::PartFilterIdentifier)) {
|
||||
ghoul::Dictionary filterDict = dict.value<ghoul::Dictionary>(
|
||||
ConfigurationManager::PartFilterIdentifier
|
||||
);
|
||||
|
||||
for (int i = 1; i <= filterDict.size(); ++i) {
|
||||
ghoul::Dictionary id = filterDict.value<ghoul::Dictionary>(
|
||||
std::to_string(i)
|
||||
);
|
||||
|
||||
const unsigned int identifier = static_cast<unsigned int>(
|
||||
id.value<double>(
|
||||
ConfigurationManager::PartFilterIdentifierIdentifier
|
||||
)
|
||||
);
|
||||
|
||||
const std::string s = id.value<std::string>(
|
||||
ConfigurationManager::PartFilterIdentifierSource
|
||||
);
|
||||
|
||||
const std::string t = id.value<std::string>(
|
||||
ConfigurationManager::PartFilterIdentifierType
|
||||
);
|
||||
|
||||
setDebugMessageControl(
|
||||
ghoul::from_string<Source>(s),
|
||||
ghoul::from_string<Type>(t),
|
||||
{ identifier },
|
||||
Enabled::No
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
if (dict.hasKey(ConfigurationManager::PartFilterSeverity)) {
|
||||
ghoul::Dictionary filterDict = dict.value<ghoul::Dictionary>(
|
||||
ConfigurationManager::PartFilterIdentifier
|
||||
);
|
||||
|
||||
for (int i = 1; i <= filterDict.size(); ++i) {
|
||||
std::string severity = filterDict.value<std::string>(
|
||||
std::to_string(i)
|
||||
);
|
||||
|
||||
setDebugMessageControl(
|
||||
Source::DontCare,
|
||||
Type::DontCare,
|
||||
ghoul::from_string<Severity>(severity),
|
||||
Enabled::No
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
auto callback = [](Source source, Type type, Severity severity,
|
||||
unsigned int id, std::string message) -> void
|
||||
{
|
||||
const std::string s = std::to_string(source);
|
||||
const std::string t = std::to_string(type);
|
||||
|
||||
const std::string category =
|
||||
"OpenGL (" + s + ") [" + t + "] {" + std::to_string(id) + "}";
|
||||
switch (severity) {
|
||||
case Severity::High:
|
||||
LERRORC(category, std::string(message));
|
||||
break;
|
||||
case Severity::Medium:
|
||||
LWARNINGC(category, std::string(message));
|
||||
break;
|
||||
case Severity::Low:
|
||||
LINFOC(category, std::string(message));
|
||||
break;
|
||||
case Severity::Notification:
|
||||
LDEBUGC(category, std::string(message));
|
||||
break;
|
||||
default:
|
||||
ghoul_assert(false, "Missing case label");
|
||||
}
|
||||
};
|
||||
ghoul::opengl::debug::setDebugCallback(callback);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
LINFO("Initializing Rendering Engine");
|
||||
// @CLEANUP: Remove the return statement and replace with exceptions ---abock
|
||||
_renderEngine->initializeGL();
|
||||
@@ -1025,11 +1137,12 @@ void OpenSpaceEngine::postSynchronizationPreDraw() {
|
||||
LTRACE("OpenSpaceEngine::postSynchronizationPreDraw(end)");
|
||||
}
|
||||
|
||||
void OpenSpaceEngine::render(const glm::mat4& viewMatrix,
|
||||
void OpenSpaceEngine::render(const glm::mat4& sceneMatrix,
|
||||
const glm::mat4& viewMatrix,
|
||||
const glm::mat4& projectionMatrix)
|
||||
{
|
||||
LTRACE("OpenSpaceEngine::render(begin)");
|
||||
_renderEngine->render(viewMatrix, projectionMatrix);
|
||||
_renderEngine->render(sceneMatrix, viewMatrix, projectionMatrix);
|
||||
|
||||
for (const auto& func : _moduleCallbacks.render) {
|
||||
func();
|
||||
|
||||
@@ -156,13 +156,12 @@ int SGCTWindowWrapper::currentNumberOfAaSamples() const {
|
||||
}
|
||||
|
||||
bool SGCTWindowWrapper::isRegularRendering() const {
|
||||
// TODO: Needs to implement the nonlinear rendering check ---abock
|
||||
|
||||
// sgct::SGCTWindow* w = sgct::Engine::instance()->getCurrentWindowPtr();
|
||||
// !w->isUsingFisheyeRendering() does not exist anymore ---abock
|
||||
// if (_isMaster && !w->isUsingFisheyeRendering() && _console->isVisible()) {
|
||||
|
||||
return true;
|
||||
sgct::SGCTWindow* w = sgct::Engine::instance()->getCurrentWindowPtr();
|
||||
std::size_t nViewports = w->getNumberOfViewports();
|
||||
ghoul_assert(nViewports > 0, "At least one viewport must exist at this time");
|
||||
sgct_core::Viewport* vp = w->getViewport(0);
|
||||
sgct_core::NonLinearProjection* nlp = vp->getNonLinearProjectionPtr();
|
||||
return nlp == nullptr;
|
||||
}
|
||||
|
||||
bool SGCTWindowWrapper::hasGuiWindow() const {
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
#include <ghoul/misc/interpolator.h>
|
||||
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/string_cast.hpp>
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
#include <modules/globebrowsing/geometry/geodetic2.h>
|
||||
@@ -188,6 +188,10 @@ void InteractionHandler::setInteractionMode(std::shared_ptr<InteractionMode> int
|
||||
_currentInteractionMode->setFocusNode(focusNode);
|
||||
}
|
||||
|
||||
InteractionMode * InteractionHandler::interactionMode() {
|
||||
return _currentInteractionMode.get();
|
||||
}
|
||||
|
||||
void InteractionHandler::setInteractionMode(const std::string& interactionModeKey) {
|
||||
if (_interactionModes.find(interactionModeKey) != _interactionModes.end()) {
|
||||
setInteractionMode(_interactionModes[interactionModeKey]);
|
||||
@@ -265,6 +269,15 @@ SceneGraphNode* const InteractionHandler::focusNode() const {
|
||||
return _currentInteractionMode->focusNode();
|
||||
}
|
||||
|
||||
glm::dvec3 InteractionHandler::focusNodeToCameraVector() const {
|
||||
return _camera->positionVec3() - focusNode()->worldPosition();
|
||||
}
|
||||
|
||||
glm::quat InteractionHandler::focusNodeToCameraRotation() const {
|
||||
glm::dmat4 invWorldRotation = glm::inverse(focusNode()->worldRotationMatrix());
|
||||
return glm::quat(invWorldRotation) * glm::quat(_camera->rotationQuaternion());
|
||||
}
|
||||
|
||||
Camera* const InteractionHandler::camera() const {
|
||||
return _camera;
|
||||
}
|
||||
@@ -625,9 +638,17 @@ void InteractionHandler::addKeyframe(const datamessagestructures::CameraKeyframe
|
||||
_inputState->addKeyframe(kf);
|
||||
}
|
||||
|
||||
void InteractionHandler::removeKeyframesAfter(double timestamp) {
|
||||
_inputState->removeKeyframesAfter(timestamp);
|
||||
}
|
||||
|
||||
void InteractionHandler::clearKeyframes() {
|
||||
_inputState->clearKeyframes();
|
||||
}
|
||||
|
||||
const std::vector<datamessagestructures::CameraKeyframe>& InteractionHandler::keyframes() const {
|
||||
return _inputState->keyframes();
|
||||
}
|
||||
|
||||
} // namespace interaction
|
||||
} // namespace openspace
|
||||
|
||||
@@ -66,16 +66,21 @@ namespace interaction {
|
||||
|
||||
void InputState::addKeyframe(const datamessagestructures::CameraKeyframe &kf) {
|
||||
clearOldKeyframes();
|
||||
if (kf._timestamp < OsEng.runTime()) {
|
||||
return;
|
||||
}
|
||||
_keyframes.insert(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &InputState::compareKeyframeTimes), kf);
|
||||
}
|
||||
|
||||
auto compareTimestamps = [](const datamessagestructures::CameraKeyframe a,
|
||||
datamessagestructures::CameraKeyframe b) {
|
||||
return a._timestamp < b._timestamp;
|
||||
};
|
||||
|
||||
void InputState::removeKeyframesAfter(double timestamp) {
|
||||
datamessagestructures::CameraKeyframe kf;
|
||||
kf._timestamp = timestamp;
|
||||
// Remove keyframes after the inserted keyframe.
|
||||
_keyframes.erase(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, compareTimestamps), _keyframes.end());
|
||||
_keyframes.erase(std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &InputState::compareKeyframeTimes), _keyframes.end());
|
||||
}
|
||||
|
||||
_keyframes.push_back(kf);
|
||||
bool InputState::compareKeyframeTimes(const datamessagestructures::CameraKeyframe& a, const datamessagestructures::CameraKeyframe& b) {
|
||||
return a._timestamp < b._timestamp;
|
||||
}
|
||||
|
||||
void InputState::clearOldKeyframes() {
|
||||
@@ -170,9 +175,6 @@ namespace interaction {
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
InteractionMode::InteractionMode()
|
||||
: _rotateToFocusNodeInterpolator(Interpolator<double>([](double t){
|
||||
return pow(t, 2);
|
||||
@@ -242,8 +244,40 @@ void KeyframeInteractionMode::updateCameraStateFromMouseStates(Camera& camera, d
|
||||
|
||||
double t = (now - prevTime) / (nextTime - prevTime);
|
||||
|
||||
camera.setPositionVec3(prevKeyframe->_position * (1 - t) + nextKeyframe->_position * t);
|
||||
camera.setRotation(glm::slerp(prevKeyframe->_rotation, nextKeyframe->_rotation, t));
|
||||
Scene* scene = camera.parent()->scene();
|
||||
SceneGraphNode* prevFocusNode = scene->sceneGraphNode(prevKeyframe->_focusNode);
|
||||
SceneGraphNode* nextFocusNode = scene->sceneGraphNode(nextKeyframe->_focusNode);
|
||||
|
||||
if (!prevFocusNode || !nextFocusNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::dvec3 prevKeyframeCameraPosition = prevKeyframe->_position;
|
||||
glm::dvec3 nextKeyframeCameraPosition = nextKeyframe->_position;
|
||||
glm::dquat prevKeyframeCameraRotation = prevKeyframe->_rotation;
|
||||
glm::dquat nextKeyframeCameraRotation = nextKeyframe->_rotation;
|
||||
|
||||
// Transform position and rotation based on focus node rotation (if following rotation)
|
||||
if (prevKeyframe->_followNodeRotation) {
|
||||
prevKeyframeCameraRotation = prevFocusNode->worldRotationMatrix() * glm::dmat3(prevKeyframe->_rotation);
|
||||
prevKeyframeCameraPosition = prevFocusNode->worldRotationMatrix() * prevKeyframeCameraPosition;
|
||||
}
|
||||
if (nextKeyframe->_followNodeRotation) {
|
||||
nextKeyframeCameraRotation = nextFocusNode->worldRotationMatrix() * glm::dmat3(nextKeyframe->_rotation);
|
||||
nextKeyframeCameraPosition = nextFocusNode->worldRotationMatrix() * nextKeyframeCameraPosition;
|
||||
}
|
||||
|
||||
// Transform position based on focus node position
|
||||
prevKeyframeCameraPosition += prevFocusNode->worldPosition();
|
||||
nextKeyframeCameraPosition += nextFocusNode->worldPosition();
|
||||
|
||||
// Linear interpolation
|
||||
camera.setPositionVec3(prevKeyframeCameraPosition * (1 - t) + nextKeyframeCameraPosition * t);
|
||||
camera.setRotation(glm::slerp(prevKeyframeCameraRotation, nextKeyframeCameraRotation, t));
|
||||
}
|
||||
|
||||
bool KeyframeInteractionMode::followingNodeRotation() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
// OrbitalInteractionMode
|
||||
@@ -487,6 +521,10 @@ void OrbitalInteractionMode::updateCameraStateFromMouseStates(Camera& camera, do
|
||||
}
|
||||
}
|
||||
|
||||
bool OrbitalInteractionMode::followingNodeRotation() const {
|
||||
return false;
|
||||
}
|
||||
|
||||
void OrbitalInteractionMode::updateMouseStatesFromInput(const InputState& inputState, double deltaTime) {
|
||||
_mouseStates->updateMouseStatesFromInput(inputState, deltaTime);
|
||||
}
|
||||
@@ -688,6 +726,10 @@ void GlobeBrowsingInteractionMode::updateCameraStateFromMouseStates(Camera& came
|
||||
#endif // OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
}
|
||||
|
||||
bool GlobeBrowsingInteractionMode::followingNodeRotation() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifdef OPENSPACE_MODULE_GLOBEBROWSING_ENABLED
|
||||
void GlobeBrowsingInteractionMode::goToChunk(Camera& camera,
|
||||
globebrowsing::TileIndex ti, glm::vec2 uv, bool resetCameraDirection) {
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include <openspace/interaction/luaconsole.h>
|
||||
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
|
||||
#include <ghoul/filesystem/cachemanager.h>
|
||||
#include <ghoul/filesystem/filesystem.h>
|
||||
@@ -57,19 +58,13 @@ namespace openspace {
|
||||
LuaConsole::LuaConsole()
|
||||
: properties::PropertyOwner("LuaConsole")
|
||||
, _isVisible("isVisible", "Is Visible", false)
|
||||
, _remoteScripting(true)
|
||||
, _remoteScripting("remoteScripting", "Remote scripting", false)
|
||||
, _inputPosition(0)
|
||||
, _activeCommand(0)
|
||||
, _autoCompleteInfo({NoAutoComplete, false, ""})
|
||||
{
|
||||
_isVisible.onChange([this](){
|
||||
if (_isVisible) {
|
||||
_remoteScripting = false;
|
||||
} else {
|
||||
_remoteScripting = OsEng.parallelConnection().isHost();
|
||||
}
|
||||
});
|
||||
addProperty(_isVisible);
|
||||
addProperty(_remoteScripting);
|
||||
}
|
||||
|
||||
void LuaConsole::initialize() {
|
||||
@@ -164,7 +159,19 @@ bool LuaConsole::keyboardCallback(Key key, KeyModifier modifier, KeyAction actio
|
||||
if (key == CommandInputButton) {
|
||||
// Button left of 1 and above TAB
|
||||
// How to deal with different keyboard languages? ---abock
|
||||
_isVisible = !_isVisible;
|
||||
if (_isVisible) {
|
||||
if (_remoteScripting) {
|
||||
_remoteScripting = false;
|
||||
} else {
|
||||
_isVisible = false;
|
||||
}
|
||||
} else {
|
||||
_isVisible = true;
|
||||
if (OsEng.parallelConnection().status() == ParallelConnection::Status::Host) {
|
||||
_remoteScripting = true;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -61,14 +61,17 @@
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
|
||||
//openspace includes
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/engine/wrapper/windowwrapper.h>
|
||||
#include <openspace/interaction/interactionhandler.h>
|
||||
#include <openspace/interaction/interactionmode.h>
|
||||
#include <openspace/scene/scenegraphnode.h>
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/util/time.h>
|
||||
#include <openspace/openspace.h>
|
||||
#include <openspace/scripting/script_helper.h>
|
||||
|
||||
#include <ghoul/logging/logmanager.h>
|
||||
|
||||
//lua functions
|
||||
@@ -77,22 +80,26 @@
|
||||
namespace {
|
||||
const uint32_t ProtocolVersion = 2;
|
||||
const size_t MaxLatencyDiffs = 64;
|
||||
const double BroadcastIntervalMilliseconds = 100;
|
||||
const std::string _loggerCat = "ParallelConnection";
|
||||
const int nFrametimesBuffer = 4;
|
||||
const int nBroadcastIntervalsBuffer = 2;
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
|
||||
ParallelConnection::ParallelConnection()
|
||||
: _passCode(0)
|
||||
, _port("20501")
|
||||
, _address("127.0.0.1")
|
||||
, _name("Local Connection")
|
||||
: properties::PropertyOwner("ParallelConnection")
|
||||
, _password("password", "Password")
|
||||
, _hostPassword("hostPassword", "Host Password")
|
||||
, _port("port", "Port", "20501")
|
||||
, _address("address", "Address", "localhost")
|
||||
, _name("name", "Connection name", "Anonymous")
|
||||
, _bufferTime("bufferTime", "Buffer Time", 1, 0.5, 10)
|
||||
, _timeKeyframeInterval("timeKeyframeInterval", "Time keyframe interval", 0.1, 0, 1)
|
||||
, _cameraKeyframeInterval("cameraKeyframeInterval", "Camera Keyframe interval", 0.1, 0, 1)
|
||||
, _timeTolerance("timeTolerance", "Time tolerance", 1, 0.5, 5)
|
||||
, _lastTimeKeyframeTimestamp(0)
|
||||
, _lastCameraKeyframeTimestamp(0)
|
||||
, _clientSocket(INVALID_SOCKET)
|
||||
, _connectionThread(nullptr)
|
||||
, _broadcastThread(nullptr)
|
||||
, _sendThread(nullptr)
|
||||
, _listenThread(nullptr)
|
||||
, _handlerThread(nullptr)
|
||||
@@ -105,6 +112,19 @@ ParallelConnection::ParallelConnection()
|
||||
, _disconnect(false)
|
||||
, _initializationTimejumpRequired(false)
|
||||
{
|
||||
addProperty(_name);
|
||||
|
||||
addProperty(_port);
|
||||
addProperty(_address);
|
||||
addProperty(_bufferTime);
|
||||
|
||||
addProperty(_password);
|
||||
addProperty(_hostPassword);
|
||||
|
||||
addProperty(_timeKeyframeInterval);
|
||||
addProperty(_cameraKeyframeInterval);
|
||||
addProperty(_timeTolerance);
|
||||
|
||||
_connectionEvent = std::make_shared<ghoul::Event<>>();
|
||||
_handlerThread = std::make_unique<std::thread>(&ParallelConnection::threadManagement, this);
|
||||
}
|
||||
@@ -186,8 +206,7 @@ void ParallelConnection::disconnect(){
|
||||
|
||||
//tell send thread to stop sending and listen thread to stop listenin
|
||||
_isConnected.store(false);
|
||||
|
||||
//tell broadcast thread to stop broadcasting (we're no longer host)
|
||||
|
||||
setStatus(Status::Disconnected);
|
||||
|
||||
//join connection thread and delete it
|
||||
@@ -207,13 +226,7 @@ void ParallelConnection::disconnect(){
|
||||
_listenThread->join();
|
||||
_listenThread = nullptr;
|
||||
}
|
||||
|
||||
//join broadcast thread and delete it
|
||||
if(_broadcastThread != nullptr){
|
||||
_broadcastThread->join();
|
||||
_broadcastThread = nullptr;
|
||||
}
|
||||
|
||||
|
||||
// disconnect and cleanup completed
|
||||
_disconnect = false;
|
||||
}
|
||||
@@ -241,7 +254,7 @@ void ParallelConnection::clientConnect(){
|
||||
hints.ai_flags = AI_PASSIVE;
|
||||
|
||||
// Resolve the local address and port to be used by the server
|
||||
int result = getaddrinfo(_address.c_str(), _port.c_str(), &hints, &addresult);
|
||||
int result = getaddrinfo(_address.value().c_str(), _port.value().c_str(), &hints, &addresult);
|
||||
if (result != 0)
|
||||
{
|
||||
LERROR("Failed to parse hints for Parallel Connection");
|
||||
@@ -308,57 +321,39 @@ void ParallelConnection::establishConnection(addrinfo *info){
|
||||
LERROR("Failed to set socket option 'keep alive'. Error code: " << _ERRNO);
|
||||
|
||||
|
||||
//while the connection thread is still running
|
||||
while (_tryConnect.load()){
|
||||
|
||||
LINFO("Attempting to connect to server "<< _address << " on port " << _port);
|
||||
LINFO("Attempting to connect to server "<< _address << " on port " << _port);
|
||||
|
||||
//try to connect
|
||||
result = connect(_clientSocket, info->ai_addr, (int)info->ai_addrlen);
|
||||
//try to connect
|
||||
result = connect(_clientSocket, info->ai_addr, (int)info->ai_addrlen);
|
||||
|
||||
//if the connection was successfull
|
||||
if (result != SOCKET_ERROR)
|
||||
{
|
||||
//if the connection was successfull
|
||||
if (result != SOCKET_ERROR)
|
||||
{
|
||||
|
||||
LINFO("Connection established with server at ip: "<< _address);
|
||||
LINFO("Connection established with server at ip: "<< _address);
|
||||
|
||||
//we're connected
|
||||
_isConnected.store(true);
|
||||
//we're connected
|
||||
_isConnected.store(true);
|
||||
|
||||
//start sending messages
|
||||
_sendThread = std::make_unique<std::thread>(&ParallelConnection::sendFunc, this);
|
||||
//start sending messages
|
||||
_sendThread = std::make_unique<std::thread>(&ParallelConnection::sendFunc, this);
|
||||
|
||||
//start listening for communication
|
||||
_listenThread = std::make_unique<std::thread>(&ParallelConnection::listenCommunication, this);
|
||||
//start listening for communication
|
||||
_listenThread = std::make_unique<std::thread>(&ParallelConnection::listenCommunication, this);
|
||||
|
||||
//we no longer need to try to establish connection
|
||||
_tryConnect.store(false);
|
||||
//we no longer need to try to establish connection
|
||||
_tryConnect.store(false);
|
||||
|
||||
_sendBufferMutex.lock();
|
||||
_sendBuffer.clear();
|
||||
_sendBufferMutex.unlock();
|
||||
_sendBufferMutex.lock();
|
||||
_sendBuffer.clear();
|
||||
_sendBufferMutex.unlock();
|
||||
|
||||
//send authentication
|
||||
sendAuthentication();
|
||||
} else {
|
||||
LINFO("Connection attempt failed.");
|
||||
}
|
||||
|
||||
#ifdef WIN32
|
||||
//on windows: try to connect once per second
|
||||
std::this_thread::sleep_for(std::chrono::seconds(1));
|
||||
#else
|
||||
if(!_isConnected.load()){
|
||||
//on unix disconnect and display error message if we're not connected
|
||||
LERROR("Failed to establish a connection with server "<< _address << " on port " << _port<<", terminating connection.");
|
||||
|
||||
//signal disconnect
|
||||
signalDisconnect();
|
||||
|
||||
//stop loop
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
//send authentication
|
||||
sendAuthentication();
|
||||
} else {
|
||||
LINFO("Connection attempt failed.");
|
||||
signalDisconnect();
|
||||
}
|
||||
|
||||
//cleanup
|
||||
@@ -366,8 +361,10 @@ void ParallelConnection::establishConnection(addrinfo *info){
|
||||
}
|
||||
|
||||
void ParallelConnection::sendAuthentication() {
|
||||
|
||||
std::string name = _name.value();
|
||||
//length of this nodes name
|
||||
uint32_t nameLength = static_cast<uint32_t>(_name.length());
|
||||
uint32_t nameLength = static_cast<uint32_t>(name.length());
|
||||
|
||||
//total size of the buffer: (passcode + namelength + name)
|
||||
size_t size = 2 * sizeof(uint32_t) + nameLength;
|
||||
@@ -376,14 +373,16 @@ void ParallelConnection::sendAuthentication() {
|
||||
std::vector<char> buffer;
|
||||
buffer.reserve(size);
|
||||
|
||||
uint32_t passCode = hash(_password.value());
|
||||
|
||||
//write passcode to buffer
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&_passCode), reinterpret_cast<char*>(&_passCode) + sizeof(uint32_t));
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&passCode), reinterpret_cast<char*>(&passCode) + sizeof(uint32_t));
|
||||
|
||||
//write the length of the nodes name to buffer
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&nameLength), reinterpret_cast<char*>(&nameLength) + sizeof(uint32_t));
|
||||
|
||||
//write this node's name to buffer
|
||||
buffer.insert(buffer.end(), _name.begin(), _name.end());
|
||||
buffer.insert(buffer.end(), name.begin(), name.end());
|
||||
|
||||
//send buffer
|
||||
queueOutMessage(Message(MessageType::Authentication, buffer));
|
||||
@@ -505,6 +504,10 @@ double ParallelConnection::calculateBufferedKeyframeTime(double originalTime) {
|
||||
}
|
||||
_latencyDiffs.push_back(latencyDiff);
|
||||
|
||||
return originalTime + timeDiff + latencyDiff + _bufferTime;
|
||||
}
|
||||
|
||||
double ParallelConnection::latencyStandardDeviation() const {
|
||||
double accumulatedLatencyDiffSquared = 0;
|
||||
double accumulatedLatencyDiff = 0;
|
||||
for (double diff : _latencyDiffs) {
|
||||
@@ -516,16 +519,14 @@ double ParallelConnection::calculateBufferedKeyframeTime(double originalTime) {
|
||||
|
||||
// V(X) = E(x^2) - E(x)^2
|
||||
double latencyVariance = expectedLatencyDiffSquared - expectedLatencyDiff*expectedLatencyDiff;
|
||||
double latencyStandardDeviation = std::sqrt(latencyVariance);
|
||||
|
||||
double frametime = OsEng.windowWrapper().averageDeltaTime();
|
||||
|
||||
double latencyCompensation = std::max(expectedLatencyDiff + 2 * latencyStandardDeviation, latencyDiff);
|
||||
|
||||
return originalTime + timeDiff + nBroadcastIntervalsBuffer * BroadcastIntervalMilliseconds / 1000 + latencyCompensation + nFrametimesBuffer * frametime;
|
||||
|
||||
return std::sqrt(latencyVariance);
|
||||
}
|
||||
|
||||
double ParallelConnection::timeTolerance() const {
|
||||
return _timeTolerance;
|
||||
}
|
||||
|
||||
|
||||
void ParallelConnection::dataMessageReceived(const std::vector<char>& messageContent) {
|
||||
|
||||
//the type of data message received
|
||||
@@ -534,26 +535,26 @@ void ParallelConnection::dataMessageReceived(const std::vector<char>& messageCon
|
||||
|
||||
switch(static_cast<datamessagestructures::Type>(type)) {
|
||||
case datamessagestructures::Type::CameraData: {
|
||||
|
||||
datamessagestructures::CameraKeyframe kf(buffer);
|
||||
kf._timestamp = calculateBufferedKeyframeTime(kf._timestamp);
|
||||
|
||||
OsEng.interactionHandler().removeKeyframesAfter(kf._timestamp);
|
||||
OsEng.interactionHandler().addKeyframe(kf);
|
||||
break;
|
||||
}
|
||||
case datamessagestructures::Type::TimeData: {
|
||||
|
||||
datamessagestructures::TimeKeyframe kf(buffer);
|
||||
kf._timestamp = calculateBufferedKeyframeTime(kf._timestamp);
|
||||
|
||||
OsEng.timeManager().removeKeyframesAfter(kf._timestamp);
|
||||
OsEng.timeManager().addKeyframe(kf);
|
||||
break;
|
||||
}
|
||||
case datamessagestructures::Type::ScriptData: {
|
||||
datamessagestructures::ScriptMessage sm;
|
||||
sm.deserialize(buffer);
|
||||
OsEng.scriptEngine().queueScript(sm._script, scripting::ScriptEngine::RemoteScripting::No);
|
||||
|
||||
|
||||
OsEng.scriptEngine().queueScript(sm._script, scripting::ScriptEngine::RemoteScripting::No);
|
||||
break;
|
||||
}
|
||||
default:{
|
||||
@@ -691,17 +692,6 @@ void ParallelConnection::connectionStatusMessageReceived(const std::vector<char>
|
||||
|
||||
setStatus(status);
|
||||
|
||||
if (status == Status::Host) { // assigned as host
|
||||
_broadcastThread = std::make_unique<std::thread>(&ParallelConnection::broadcast, this);
|
||||
} else { // assigned as client
|
||||
|
||||
// delete broadcasting thread
|
||||
// (the thread is allowed to terminate once the status is set to non-host.)
|
||||
if (_broadcastThread != nullptr) {
|
||||
_broadcastThread->join();
|
||||
_broadcastThread = nullptr;
|
||||
}
|
||||
}
|
||||
OsEng.interactionHandler().clearKeyframes();
|
||||
OsEng.timeManager().clearKeyframes();
|
||||
|
||||
@@ -879,22 +869,22 @@ int ParallelConnection::receiveData(_SOCKET & socket, std::vector<char> &buffer,
|
||||
return result;
|
||||
}
|
||||
|
||||
void ParallelConnection::setPort(const std::string &port){
|
||||
_port = port;
|
||||
void ParallelConnection::setPort(std::string port){
|
||||
_port = std::move(port);
|
||||
}
|
||||
|
||||
void ParallelConnection::setAddress(const std::string &address){
|
||||
_address = address;
|
||||
void ParallelConnection::setAddress(std::string address){
|
||||
_address = std::move(address);
|
||||
}
|
||||
|
||||
void ParallelConnection::setName(const std::string& name){
|
||||
_name = name;
|
||||
void ParallelConnection::setName(std::string name){
|
||||
_name = std::move(name);
|
||||
}
|
||||
|
||||
|
||||
void ParallelConnection::requestHostship(const std::string &password){
|
||||
void ParallelConnection::requestHostship(){
|
||||
std::vector<char> buffer;
|
||||
uint32_t passcode = hash(password);
|
||||
uint32_t passcode = hash(_hostPassword);
|
||||
buffer.insert(buffer.end(), reinterpret_cast<char*>(&passcode), reinterpret_cast<char*>(&passcode) + sizeof(uint32_t));
|
||||
queueOutMessage(Message(MessageType::HostshipRequest, buffer));
|
||||
}
|
||||
@@ -904,8 +894,12 @@ void ParallelConnection::resignHostship() {
|
||||
queueOutMessage(Message(MessageType::HostshipResignation, buffer));
|
||||
}
|
||||
|
||||
void ParallelConnection::setPassword(const std::string& pwd){
|
||||
_passCode = hash(pwd);
|
||||
void ParallelConnection::setPassword(std::string pwd){
|
||||
_password = std::move(pwd);
|
||||
}
|
||||
|
||||
void ParallelConnection::setHostPassword(std::string pwd) {
|
||||
_hostPassword = std::move(pwd);
|
||||
}
|
||||
|
||||
bool ParallelConnection::initNetworkAPI(){
|
||||
@@ -934,11 +928,11 @@ bool ParallelConnection::initNetworkAPI(){
|
||||
return true;
|
||||
}
|
||||
|
||||
void ParallelConnection::sendScript(const std::string& script) {
|
||||
void ParallelConnection::sendScript(std::string script) {
|
||||
if (!isHost()) return;
|
||||
|
||||
datamessagestructures::ScriptMessage sm;
|
||||
sm._script = script;
|
||||
sm._script = std::move(script);
|
||||
|
||||
std::vector<char> buffer;
|
||||
sm.serialize(buffer);
|
||||
@@ -946,6 +940,13 @@ void ParallelConnection::sendScript(const std::string& script) {
|
||||
queueOutDataMessage(DataMessage(datamessagestructures::Type::ScriptData, buffer));
|
||||
}
|
||||
|
||||
void ParallelConnection::resetTimeOffset() {
|
||||
OsEng.interactionHandler().clearKeyframes();
|
||||
OsEng.timeManager().clearKeyframes();
|
||||
std::lock_guard<std::mutex> latencyLock(_latencyMutex);
|
||||
_latencyDiffs.clear();
|
||||
}
|
||||
|
||||
void ParallelConnection::preSynchronization(){
|
||||
|
||||
std::unique_lock<std::mutex> unqlock(_receiveBufferMutex);
|
||||
@@ -959,12 +960,23 @@ void ParallelConnection::preSynchronization(){
|
||||
if (Time::ref().timeJumped()) {
|
||||
_timeJumped = true;
|
||||
}
|
||||
double now = OsEng.runTime();
|
||||
|
||||
if (_lastCameraKeyframeTimestamp + _cameraKeyframeInterval < now) {
|
||||
sendCameraKeyframe();
|
||||
_lastCameraKeyframeTimestamp = now;
|
||||
}
|
||||
if (_lastTimeKeyframeTimestamp + _timeKeyframeInterval < now) {
|
||||
sendTimeKeyframe();
|
||||
_lastTimeKeyframeTimestamp = now;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ParallelConnection::setStatus(Status status) {
|
||||
if (_status != status) {
|
||||
_status = status;
|
||||
_timeJumped = true;
|
||||
_connectionEvent->publish("statusChanged");
|
||||
}
|
||||
}
|
||||
@@ -1000,26 +1012,40 @@ const std::string& ParallelConnection::hostName() {
|
||||
}
|
||||
|
||||
void ParallelConnection::sendCameraKeyframe() {
|
||||
//create a keyframe with current position and orientation of camera
|
||||
datamessagestructures::CameraKeyframe kf;
|
||||
kf._position = OsEng.interactionHandler().camera()->positionVec3();
|
||||
kf._rotation = OsEng.interactionHandler().camera()->rotationQuaternion();
|
||||
SceneGraphNode* focusNode = OsEng.interactionHandler().focusNode();
|
||||
if (!focusNode) {
|
||||
return;
|
||||
}
|
||||
|
||||
//timestamp as current runtime of OpenSpace instance
|
||||
// Create a keyframe with current position and orientation of camera
|
||||
datamessagestructures::CameraKeyframe kf;
|
||||
kf._position = OsEng.interactionHandler().focusNodeToCameraVector();
|
||||
|
||||
kf._followNodeRotation = OsEng.interactionHandler().interactionMode()->followingNodeRotation();
|
||||
if (kf._followNodeRotation) {
|
||||
kf._position = glm::inverse(focusNode->worldRotationMatrix()) * kf._position;
|
||||
kf._rotation = OsEng.interactionHandler().focusNodeToCameraRotation();
|
||||
} else {
|
||||
kf._rotation = OsEng.interactionHandler().camera()->rotationQuaternion();
|
||||
}
|
||||
|
||||
kf._focusNode = focusNode->name();
|
||||
|
||||
// Timestamp as current runtime of OpenSpace instance
|
||||
kf._timestamp = OsEng.runTime();
|
||||
|
||||
//create a buffer for the keyframe
|
||||
// Create a buffer for the keyframe
|
||||
std::vector<char> buffer;
|
||||
|
||||
//fill the keyframe buffer
|
||||
// Fill the keyframe buffer
|
||||
kf.serialize(buffer);
|
||||
|
||||
//send message
|
||||
// Send message
|
||||
queueOutDataMessage(DataMessage(datamessagestructures::Type::CameraData, buffer));
|
||||
}
|
||||
|
||||
void ParallelConnection::sendTimeKeyframe() {
|
||||
//create a keyframe with current position and orientation of camera
|
||||
// Create a keyframe with current position and orientation of camera
|
||||
datamessagestructures::TimeKeyframe kf;
|
||||
|
||||
kf._dt = Time::ref().deltaTime();
|
||||
@@ -1027,33 +1053,20 @@ void ParallelConnection::sendTimeKeyframe() {
|
||||
kf._requiresTimeJump = _timeJumped;
|
||||
kf._time = Time::ref().j2000Seconds();
|
||||
|
||||
//timestamp as current runtime of OpenSpace instance
|
||||
// Timestamp as current runtime of OpenSpace instance
|
||||
kf._timestamp = OsEng.runTime();
|
||||
|
||||
//create a buffer for the keyframe
|
||||
// Create a buffer for the keyframe
|
||||
std::vector<char> buffer;
|
||||
|
||||
//fill the keyframe buffer
|
||||
// Fill the keyframe buffer
|
||||
kf.serialize(buffer);
|
||||
|
||||
//send message
|
||||
// Send message
|
||||
queueOutDataMessage(DataMessage(datamessagestructures::Type::TimeData, buffer));
|
||||
_timeJumped = false;
|
||||
}
|
||||
|
||||
|
||||
void ParallelConnection::broadcast(){
|
||||
_timeJumped = true;
|
||||
//while we're still connected and we're the host
|
||||
while (_isConnected && isHost()) {
|
||||
sendCameraKeyframe();
|
||||
sendTimeKeyframe();
|
||||
|
||||
//100 ms sleep - send keyframes 10 times per second
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(static_cast<int>(BroadcastIntervalMilliseconds)));
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t ParallelConnection::hash(const std::string &val) {
|
||||
uint32_t hashVal = 0, i;
|
||||
size_t len = val.length();
|
||||
@@ -1080,30 +1093,6 @@ scripting::LuaLibrary ParallelConnection::luaLibrary() {
|
||||
return {
|
||||
"parallel",
|
||||
{
|
||||
{
|
||||
"setPort",
|
||||
&luascriptfunctions::setPort,
|
||||
"number",
|
||||
"Set the port for the parallel connection"
|
||||
},
|
||||
{
|
||||
"setAddress",
|
||||
&luascriptfunctions::setAddress,
|
||||
"string",
|
||||
"Set the address for the parallel connection"
|
||||
},
|
||||
{
|
||||
"setPassword",
|
||||
&luascriptfunctions::setPassword,
|
||||
"string",
|
||||
"Set the password for the parallel connection"
|
||||
},
|
||||
{
|
||||
"setDisplayName",
|
||||
&luascriptfunctions::setDisplayName,
|
||||
"string",
|
||||
"Set your display name for the parallel connection"
|
||||
},
|
||||
{
|
||||
"connect",
|
||||
&luascriptfunctions::connect,
|
||||
@@ -1119,7 +1108,7 @@ scripting::LuaLibrary ParallelConnection::luaLibrary() {
|
||||
{
|
||||
"requestHostship",
|
||||
&luascriptfunctions::requestHostship,
|
||||
"string",
|
||||
"",
|
||||
"Request to be the host for this session"
|
||||
},
|
||||
{
|
||||
|
||||
@@ -26,109 +26,10 @@ namespace openspace {
|
||||
|
||||
namespace luascriptfunctions {
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* setPort():
|
||||
* Set the port for parallel connection
|
||||
*/
|
||||
int setPort(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
bool isNumber = (lua_isnumber(L, -1) != 0);
|
||||
if (isNumber) {
|
||||
int value = static_cast<int>(lua_tonumber(L, -1));
|
||||
std::string port = std::to_string(value);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().setPort(port);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TNUMBER), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int setAddress(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
int type = lua_type(L, -1);
|
||||
if (type == LUA_TSTRING) {
|
||||
std::string address = luaL_checkstring(L, -1);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().setAddress(address);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TSTRING), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int setPassword(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
int type = lua_type(L, -1);
|
||||
if (type == LUA_TSTRING) {
|
||||
std::string pwd = luaL_checkstring(L, -1);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().setPassword(pwd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TSTRING), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int setDisplayName(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
int type = lua_type(L, -1);
|
||||
if (type == LUA_TSTRING) {
|
||||
std::string name = luaL_checkstring(L, -1);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().setName(name);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TSTRING), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
}
|
||||
}
|
||||
|
||||
int connect(lua_State* L) {
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 0) {
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
|
||||
}
|
||||
SCRIPT_CHECK_ARGUMENTS("connect", L, 0, nArguments);
|
||||
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().clientConnect();
|
||||
}
|
||||
@@ -137,9 +38,8 @@ int connect(lua_State* L) {
|
||||
|
||||
int disconnect(lua_State* L) {
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 0) {
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
|
||||
}
|
||||
SCRIPT_CHECK_ARGUMENTS("disconnect", L, 0, nArguments);
|
||||
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().signalDisconnect();
|
||||
}
|
||||
@@ -147,33 +47,19 @@ int disconnect(lua_State* L) {
|
||||
}
|
||||
|
||||
int requestHostship(lua_State* L) {
|
||||
bool isFunction = (lua_isfunction(L, -1) != 0);
|
||||
if (isFunction) {
|
||||
// If the top of the stack is a function, it is ourself
|
||||
const char* msg = lua_pushfstring(L, "method called without argument");
|
||||
return luaL_error(L, "bad argument (%s)", msg);
|
||||
}
|
||||
|
||||
int type = lua_type(L, -1);
|
||||
if (type == LUA_TSTRING) {
|
||||
std::string pwd = luaL_checkstring(L, -1);
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().requestHostship(pwd);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
const char* msg = lua_pushfstring(L, "%s expected, got %s",
|
||||
lua_typename(L, LUA_TSTRING), luaL_typename(L, -1));
|
||||
return luaL_error(L, "bad argument #%d (%s)", 1, msg);
|
||||
int nArguments = lua_gettop(L);
|
||||
SCRIPT_CHECK_ARGUMENTS("requestHostship", L, 0, nArguments);
|
||||
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().requestHostship();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int resignHostship(lua_State* L) {
|
||||
int nArguments = lua_gettop(L);
|
||||
if (nArguments != 0) {
|
||||
return luaL_error(L, "Expected %i arguments, got %i", 0, nArguments);
|
||||
}
|
||||
SCRIPT_CHECK_ARGUMENTS("resignHostship", L, 0, nArguments);
|
||||
|
||||
if (OsEng.windowWrapper().isMaster()) {
|
||||
OsEng.parallelConnection().resignHostship();
|
||||
}
|
||||
|
||||
@@ -324,5 +324,13 @@ const std::string& PropertyOwner::name() const {
|
||||
return _name;
|
||||
}
|
||||
|
||||
std::vector<std::string> PropertyOwner::tags() const {
|
||||
return _tags;
|
||||
}
|
||||
|
||||
void PropertyOwner::addTag(std::string tag) {
|
||||
_tags.push_back(std::move(tag));
|
||||
}
|
||||
|
||||
} // namespace properties
|
||||
} // namespace openspace
|
||||
|
||||
@@ -41,6 +41,7 @@ namespace {
|
||||
const char* keyStart = "StartTime";
|
||||
const char* keyEnd = "EndTime";
|
||||
const char* KeyType = "Type";
|
||||
const char* KeyTag = "Tag";
|
||||
}
|
||||
|
||||
namespace openspace {
|
||||
@@ -112,6 +113,21 @@ Renderable::Renderable(const ghoul::Dictionary& dictionary)
|
||||
dictionary.getValue(keyStart, _startTime);
|
||||
dictionary.getValue(keyEnd, _endTime);
|
||||
|
||||
if (dictionary.hasKeyAndValue<std::string>(KeyTag)) {
|
||||
std::string tagName = dictionary.value<std::string>(KeyTag);
|
||||
if (!tagName.empty())
|
||||
addTag(std::move(tagName));
|
||||
} else if (dictionary.hasKeyAndValue<ghoul::Dictionary>(KeyTag)) {
|
||||
ghoul::Dictionary tagNames = dictionary.value<ghoul::Dictionary>(KeyTag);
|
||||
std::vector<std::string> keys = tagNames.keys();
|
||||
std::string tagName;
|
||||
for (const std::string& key : keys) {
|
||||
tagName = tagNames.value<std::string>(key);
|
||||
if (!tagName.empty())
|
||||
addTag(std::move(tagName));
|
||||
}
|
||||
}
|
||||
|
||||
if (_startTime != "" && _endTime != "") {
|
||||
_hasTimeInterval = true;
|
||||
}
|
||||
|
||||
@@ -108,6 +108,7 @@ RenderEngine::RenderEngine()
|
||||
, _takeScreenshot("takeScreenshot", "Take Screenshot")
|
||||
, _showFrameNumber("showFrameNumber", "Show Frame Number", false)
|
||||
, _disableMasterRendering("disableMasterRendering", "Disable Master Rendering", false)
|
||||
, _disableSceneOnMaster("disableSceneOnMaster", "Disable Scene on Master", false)
|
||||
, _shouldTakeScreenshot(false)
|
||||
, _renderer(nullptr)
|
||||
, _rendererImplementation(RendererImplementation::Invalid)
|
||||
@@ -165,6 +166,7 @@ RenderEngine::RenderEngine()
|
||||
addProperty(_showFrameNumber);
|
||||
|
||||
addProperty(_disableMasterRendering);
|
||||
addProperty(_disableSceneOnMaster);
|
||||
}
|
||||
|
||||
void RenderEngine::setRendererFromString(const std::string& renderingMethod) {
|
||||
@@ -211,6 +213,12 @@ void RenderEngine::initialize() {
|
||||
);
|
||||
}
|
||||
|
||||
if (confManager.hasKey(ConfigurationManager::KeyDisableSceneOnMaster)) {
|
||||
_disableSceneOnMaster = confManager.value<bool>(
|
||||
ConfigurationManager::KeyDisableSceneOnMaster
|
||||
);
|
||||
}
|
||||
|
||||
_raycasterManager = std::make_unique<RaycasterManager>();
|
||||
_nAaSamples = OsEng.windowWrapper().currentNumberOfAaSamples();
|
||||
|
||||
@@ -383,12 +391,20 @@ void RenderEngine::updateFade() {
|
||||
|
||||
|
||||
|
||||
void RenderEngine::render(const glm::mat4& viewMatrix, const glm::mat4& projectionMatrix) {
|
||||
void RenderEngine::render(const glm::mat4& sceneMatrix, const glm::mat4& viewMatrix,
|
||||
const glm::mat4& projectionMatrix)
|
||||
{
|
||||
LTRACE("RenderEngine::render(begin)");
|
||||
_camera->sgctInternal.setViewMatrix(viewMatrix);
|
||||
WindowWrapper& wrapper = OsEng.windowWrapper();
|
||||
|
||||
if (_disableSceneOnMaster && wrapper.isMaster()) {
|
||||
_camera->sgctInternal.setViewMatrix(viewMatrix);
|
||||
}
|
||||
else {
|
||||
_camera->sgctInternal.setViewMatrix(viewMatrix * sceneMatrix);
|
||||
}
|
||||
_camera->sgctInternal.setProjectionMatrix(projectionMatrix);
|
||||
|
||||
WindowWrapper& wrapper = OsEng.windowWrapper();
|
||||
|
||||
if (!(wrapper.isMaster() && _disableMasterRendering) && !wrapper.isGuiWindow()) {
|
||||
_renderer->render(_globalBlackOutFactor, _performanceManager != nullptr);
|
||||
|
||||
@@ -47,7 +47,7 @@ namespace {
|
||||
const char* KeyScale = "Scale";
|
||||
const char* KeyDepth = "Depth";
|
||||
const char* KeyAlpha = "Alpha";
|
||||
|
||||
const char* KeyTag = "Tag";
|
||||
const float PlaneDepth = -2.f;
|
||||
}
|
||||
|
||||
@@ -146,6 +146,21 @@ ScreenSpaceRenderable::ScreenSpaceRenderable(const ghoul::Dictionary& dictionary
|
||||
dictionary.getValue(KeyDepth, _depth);
|
||||
dictionary.getValue(KeyAlpha, _alpha);
|
||||
|
||||
if (dictionary.hasKeyAndValue<std::string>(KeyTag)) {
|
||||
std::string tagName = dictionary.value<std::string>(KeyTag);
|
||||
if (!tagName.empty())
|
||||
addTag(std::move(tagName));
|
||||
} else if (dictionary.hasKeyAndValue<ghoul::Dictionary>(KeyTag)) {
|
||||
ghoul::Dictionary tagNames = dictionary.value<ghoul::Dictionary>(KeyTag);
|
||||
std::vector<std::string> keys = tagNames.keys();
|
||||
std::string tagName;
|
||||
for (const std::string& key : keys) {
|
||||
tagName = tagNames.value<std::string>(key);
|
||||
if (!tagName.empty())
|
||||
addTag(std::move(tagName));
|
||||
}
|
||||
}
|
||||
|
||||
// Setting spherical/euclidean onchange handler
|
||||
_useFlatScreen.onChange([this](){
|
||||
if (_useFlatScreen) {
|
||||
|
||||
@@ -435,26 +435,38 @@ scripting::LuaLibrary Scene::luaLibrary() {
|
||||
"setPropertyValue",
|
||||
&luascriptfunctions::property_setValue,
|
||||
"string, *",
|
||||
"Sets all properties identified by the URI (with potential wildcards) in "
|
||||
"the first argument. The second argument can be any type, but it has to "
|
||||
"match the type that the property (or properties) expect."
|
||||
"Sets all property(s) identified by the URI (with potential wildcards) "
|
||||
"in the first argument. The second argument can be any type, but it has "
|
||||
"to match the type that the property (or properties) expect. If the "
|
||||
"first term (separated by '.') in the uri is bracketed with { }, then "
|
||||
"this term is treated as a group tag name, and the function will "
|
||||
"search through all property owners to find those that are tagged with "
|
||||
"this group name, and set their property values accordingly."
|
||||
},
|
||||
{
|
||||
"setPropertyValueRegex",
|
||||
&luascriptfunctions::property_setValueRegex,
|
||||
"string, *",
|
||||
"Sets all properties that pass the regular expression in the first "
|
||||
"argument. The second argument can be any type, but it has to match the "
|
||||
"type of the properties that matched the regular expression. The regular "
|
||||
"expression has to be of the ECMAScript grammar."
|
||||
"Sets all property(s) that pass the regular expression in the first "
|
||||
"argument. The second argument can be any type, but it has to match "
|
||||
"the type of the properties that matched the regular expression. "
|
||||
"The regular expression has to be of the ECMAScript grammar. If the "
|
||||
"first term (separated by '.') in the uri is bracketed with { }, then "
|
||||
"this term is treated as a group tag name, and the function will search "
|
||||
"through all property owners to find those that are tagged with this "
|
||||
"group name, and set their property values accordingly."
|
||||
},
|
||||
{
|
||||
"setPropertyValueSingle",
|
||||
&luascriptfunctions::property_setValueSingle,
|
||||
"string, *",
|
||||
"Sets a property identified by the URI in "
|
||||
"the first argument. The second argument can be any type, but it has to "
|
||||
"match the type that the property expects.",
|
||||
"Sets all property(s) identified by the URI in the first argument to the "
|
||||
"value passed in the second argument. The type of the second argument is "
|
||||
"arbitrary, but it must agree with the type the denoted Property expects."
|
||||
" If the first term (separated by '.') in the uri is bracketed with { }, "
|
||||
" then this term is treated as a group tag name, and the function will "
|
||||
"search through all property owners to find those that are tagged with "
|
||||
"this group name, and set their property values accordingly."
|
||||
},
|
||||
{
|
||||
"getPropertyValue",
|
||||
|
||||
@@ -28,17 +28,67 @@ namespace openspace {
|
||||
|
||||
namespace {
|
||||
|
||||
void applyRegularExpression(lua_State* L, std::regex regex, std::vector<properties::Property*> properties, int type) {
|
||||
void executePropertySet(properties::Property* prop, lua_State* L) {
|
||||
prop->setLuaValue(L);
|
||||
//ensure properties are synced over parallel connection
|
||||
std::string value;
|
||||
prop->getStringValue(value);
|
||||
/*OsEng.parallelConnection().scriptMessage(
|
||||
prop->fullyQualifiedIdentifier(),
|
||||
value
|
||||
);*/
|
||||
}
|
||||
|
||||
template <class T>
|
||||
properties::PropertyOwner* findPropertyOwnerWithMatchingGroupTag(T* prop,
|
||||
const std::string& tagToMatch)
|
||||
{
|
||||
properties::PropertyOwner* tagMatchOwner = nullptr;
|
||||
properties::PropertyOwner* owner = prop->owner();
|
||||
|
||||
if (owner) {
|
||||
std::vector<std::string> tags = owner->tags();
|
||||
for (std::string& currTag : tags) {
|
||||
if (tagToMatch.compare(currTag) == 0) {
|
||||
tagMatchOwner = owner;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//Call recursively until we find an owner with matching tag or the top of the
|
||||
// ownership list
|
||||
if (tagMatchOwner == nullptr)
|
||||
tagMatchOwner = findPropertyOwnerWithMatchingGroupTag(owner, tagToMatch);
|
||||
}
|
||||
return tagMatchOwner;
|
||||
}
|
||||
|
||||
void applyRegularExpression(lua_State* L, std::regex regex,
|
||||
std::vector<properties::Property*> properties, int type,
|
||||
std::string groupName = "")
|
||||
{
|
||||
using ghoul::lua::errorLocation;
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
bool isGroupMode = !groupName.empty();
|
||||
|
||||
for (properties::Property* prop : properties) {
|
||||
// Check the regular expression for all properties
|
||||
std::string id = prop->fullyQualifiedIdentifier();
|
||||
|
||||
if (std::regex_match(id, regex)) {
|
||||
// If the fully qualified id matches the regular expression, we queue the
|
||||
// value change if the types agree
|
||||
|
||||
if (isGroupMode) {
|
||||
properties::PropertyOwner* matchingTaggedOwner =
|
||||
findPropertyOwnerWithMatchingGroupTag(
|
||||
prop,
|
||||
groupName
|
||||
);
|
||||
if (!matchingTaggedOwner) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (type != prop->typeLua()) {
|
||||
LERRORC("property_setValue",
|
||||
errorLocation(L) << "Property '" <<
|
||||
@@ -46,55 +96,50 @@ void applyRegularExpression(lua_State* L, std::regex regex, std::vector<properti
|
||||
"' does not accept input of type '" << luaTypeToString(type) <<
|
||||
"'. Requested type: '" << luaTypeToString(prop->typeLua()) << "'"
|
||||
);
|
||||
} else {
|
||||
executePropertySet(prop, L);
|
||||
}
|
||||
else {
|
||||
prop->setLuaValue(L);
|
||||
//ensure properties are synced over parallel connection
|
||||
std::string value;
|
||||
prop->getStringValue(value);
|
||||
/* OsEng.parallelConnection().scriptMessage(
|
||||
prop->fullyQualifiedIdentifier(),
|
||||
value
|
||||
);*/
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//Checks to see if URI contains a group tag (with { } around the first term). If so,
|
||||
// returns true and sets groupName with the tag
|
||||
bool doesUriContainGroupTag(const std::string& command, std::string& groupName) {
|
||||
std::string name = command.substr(0, command.find_first_of("."));
|
||||
if (name.front() == '{' && name.back() == '}') {
|
||||
groupName = name.substr(1, name.length() - 2);
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
std::string replaceUriWithGroupName(std::string uri, std::string ownerName) {
|
||||
size_t pos = uri.find_first_of(".");
|
||||
return ownerName + "." + uri.substr(pos);
|
||||
}
|
||||
|
||||
std::string extractUriWithoutGroupName(std::string uri) {
|
||||
size_t pos = uri.find_first_of(".");
|
||||
return uri.substr(pos);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
namespace luascriptfunctions {
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* setPropertyValueSingle(string, *):
|
||||
* Sets the property identified by the URI in the first argument to the value passed to
|
||||
* the second argument. The type of the second argument is arbitrary, but it must agree
|
||||
* with the type the denoted Property expects
|
||||
*/
|
||||
int property_setValueSingle(lua_State* L) {
|
||||
int setPropertyCall_single(properties::Property* prop, std::string uri, lua_State* L,
|
||||
const int type)
|
||||
{
|
||||
using ghoul::lua::errorLocation;
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
int nArguments = lua_gettop(L);
|
||||
SCRIPT_CHECK_ARGUMENTS("property_setValueSingle", L, 2, nArguments);
|
||||
|
||||
std::string uri = luaL_checkstring(L, -2);
|
||||
const int type = lua_type(L, -1);
|
||||
|
||||
properties::Property* prop = property(uri);
|
||||
if (!prop) {
|
||||
LERRORC("property_setValue", errorLocation(L) << "Property with URI '" << uri << "' was not found");
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (type != prop->typeLua()) {
|
||||
LERRORC("property_setValue", errorLocation(L) << "Property '" << uri <<
|
||||
"' does not accept input of type '" << luaTypeToString(type) <<
|
||||
"'. Requested type: '" << luaTypeToString(prop->typeLua()) << "'");
|
||||
return 0;
|
||||
}
|
||||
else {
|
||||
prop->setLuaValue(L);
|
||||
@@ -107,12 +152,116 @@ int property_setValueSingle(lua_State* L) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* setPropertyValueSingle(string, *):
|
||||
* Sets all property(s) identified by the URI in the first argument to the value passed
|
||||
* in the second argument. The type of the second argument is arbitrary, but it must
|
||||
* agree with the type the denoted Property expects.
|
||||
* If the first term (separated by '.') in the uri is bracketed with { }, then this
|
||||
* term is treated as a group tag name, and the function will search through all
|
||||
* property owners to find those that are tagged with this group name, and set their
|
||||
* property values accordingly.
|
||||
*/
|
||||
int property_setValueSingle(lua_State* L) {
|
||||
using ghoul::lua::errorLocation;
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
int nArguments = lua_gettop(L);
|
||||
SCRIPT_CHECK_ARGUMENTS("property_setValueSingle", L, 2, nArguments);
|
||||
|
||||
std::string uri = luaL_checkstring(L, -2);
|
||||
const int type = lua_type(L, -1);
|
||||
std::string tagToMatch;
|
||||
|
||||
if (doesUriContainGroupTag(uri, tagToMatch)) {
|
||||
std::string pathRemainderToMatch = extractUriWithoutGroupName(uri);
|
||||
for (properties::Property* prop : allProperties()) {
|
||||
std::string propFullId = prop->fullyQualifiedIdentifier();
|
||||
//Look for a match in the uri with the group name (first term) removed
|
||||
int propMatchLength = propFullId.length() - pathRemainderToMatch.length();
|
||||
|
||||
if (propMatchLength >= 0) {
|
||||
std::string thisPropMatchId = propFullId.substr(propMatchLength);
|
||||
//If remainder of uri matches (with group name removed),
|
||||
if (pathRemainderToMatch.compare(thisPropMatchId) == 0) {
|
||||
properties::PropertyOwner* matchingTaggedOwner
|
||||
= findPropertyOwnerWithMatchingGroupTag(prop, tagToMatch);
|
||||
if (matchingTaggedOwner) {
|
||||
setPropertyCall_single(prop, uri, L, type);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
properties::Property* prop = property(uri);
|
||||
if (!prop) {
|
||||
LERRORC("property_setValue", errorLocation(L) << "Property with URI '"
|
||||
<< uri << "' was not found");
|
||||
return 0;
|
||||
}
|
||||
setPropertyCall_single(prop, uri, L, type);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* setPropertyValue(string, *):
|
||||
* Sets all property(s) identified by the URI (with potential wildcards) in the first
|
||||
* argument. The second argument can be any type, but it has to match the type that the
|
||||
* property (or properties) expect.
|
||||
* If the first term (separated by '.') in the uri is bracketed with { }, then this
|
||||
* term is treated as a group tag name, and the function will search through all
|
||||
* property owners to find those that are tagged with this group name, and set their
|
||||
* property values accordingly.
|
||||
*/
|
||||
|
||||
int property_setValue(lua_State* L) {
|
||||
using ghoul::lua::errorLocation;
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
int nArguments = lua_gettop(L);
|
||||
SCRIPT_CHECK_ARGUMENTS("property_setGroup", L, 2, nArguments);
|
||||
std::string regex = luaL_checkstring(L, -2);
|
||||
std::string groupName;
|
||||
|
||||
// Replace all wildcards * with the correct regex (.*)
|
||||
size_t startPos = regex.find("*");
|
||||
while (startPos != std::string::npos) {
|
||||
regex.replace(startPos, 1, "(.*)");
|
||||
startPos += 4;
|
||||
startPos = regex.find("*", startPos);
|
||||
}
|
||||
|
||||
if (doesUriContainGroupTag(regex, groupName)) {
|
||||
std::string pathRemainderToMatch = extractUriWithoutGroupName(regex);
|
||||
//Remove group name from start of regex and replace with '.*'
|
||||
regex = replaceUriWithGroupName(regex, ".*");
|
||||
}
|
||||
|
||||
applyRegularExpression(
|
||||
L,
|
||||
std::regex(regex/*, std::regex_constants::optimize*/),
|
||||
allProperties(),
|
||||
lua_type(L, -1),
|
||||
groupName
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* setPropertyValueRegex(string, *):
|
||||
* Sets all properties that pass the regular expression in the first argument. The second
|
||||
* Sets all property(s) that pass the regular expression in the first argument. The second
|
||||
* argument can be any type, but it has to match the type of the properties that matched
|
||||
* the regular expression. The regular expression has to be of the ECMAScript grammar.
|
||||
* If the first term (separated by '.') in the uri is bracketed with { }, then this
|
||||
* term is treated as a group tag name, and the function will search through all
|
||||
* property owners to find those that are tagged with this group name, and set their
|
||||
* property values accordingly.
|
||||
*/
|
||||
int property_setValueRegex(lua_State* L) {
|
||||
using ghoul::lua::errorLocation;
|
||||
@@ -120,63 +269,32 @@ int property_setValueRegex(lua_State* L) {
|
||||
|
||||
int nArguments = lua_gettop(L);
|
||||
SCRIPT_CHECK_ARGUMENTS("property_setValueRegex<", L, 2, nArguments);
|
||||
|
||||
std::string regex = luaL_checkstring(L, -2);
|
||||
std::string groupName;
|
||||
|
||||
if (doesUriContainGroupTag(regex, groupName)) {
|
||||
std::string pathRemainderToMatch = extractUriWithoutGroupName(regex);
|
||||
//Remove group name from start of regex and replace with '.*'
|
||||
regex = replaceUriWithGroupName(regex, ".*");
|
||||
}
|
||||
|
||||
try {
|
||||
applyRegularExpression(
|
||||
L,
|
||||
std::regex(regex, std::regex_constants::optimize),
|
||||
allProperties(),
|
||||
lua_type(L, -1)
|
||||
lua_type(L, -1),
|
||||
groupName
|
||||
);
|
||||
}
|
||||
catch (const std::regex_error&) {
|
||||
LERRORC(
|
||||
"property_setValueRegex",
|
||||
"Malformed regular expression: '" << regex << "'"
|
||||
);
|
||||
catch (const std::regex_error& e) {
|
||||
LERRORC("property_setValueRegex", "Malformed regular expression: '"
|
||||
<< regex << "'");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* setPropertyValue(string, *):
|
||||
* Sets all properties identified by the URI (with potential wildcards) in the first
|
||||
* argument. The second argument can be any type, but it has to match the type that the
|
||||
* property (or properties) expect.
|
||||
*/
|
||||
|
||||
int property_setValue(lua_State* L) {
|
||||
using ghoul::lua::errorLocation;
|
||||
using ghoul::lua::luaTypeToString;
|
||||
|
||||
int nArguments = lua_gettop(L);
|
||||
SCRIPT_CHECK_ARGUMENTS("property_setValue", L, 2, nArguments);
|
||||
|
||||
std::string regex = luaL_checkstring(L, -2);
|
||||
|
||||
// Replace all wildcards * with the correct regex (.*)
|
||||
size_t startPos = regex.find("*");
|
||||
while (startPos != std::string::npos) {
|
||||
regex.replace(startPos, 1, "(.*)");
|
||||
startPos += 4;
|
||||
|
||||
startPos = regex.find("*", startPos);
|
||||
}
|
||||
|
||||
|
||||
applyRegularExpression(
|
||||
L,
|
||||
std::regex(regex/*, std::regex_constants::optimize*/),
|
||||
allProperties(),
|
||||
lua_type(L, -1)
|
||||
);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* \ingroup LuaScripts
|
||||
* getPropertyValue(string):
|
||||
|
||||
@@ -64,6 +64,7 @@ const std::string SceneGraphNode::RootNodeName = "Root";
|
||||
const std::string SceneGraphNode::KeyName = "Name";
|
||||
const std::string SceneGraphNode::KeyParentName = "Parent";
|
||||
const std::string SceneGraphNode::KeyDependencies = "Dependencies";
|
||||
const std::string SceneGraphNode::KeyTag = "Tag";
|
||||
|
||||
std::unique_ptr<SceneGraphNode> SceneGraphNode::createFromDictionary(const ghoul::Dictionary& dictionary){
|
||||
openspace::documentation::testSpecificationAndThrow(
|
||||
@@ -135,6 +136,25 @@ std::unique_ptr<SceneGraphNode> SceneGraphNode::createFromDictionary(const ghoul
|
||||
LDEBUG("Successfully created scale for '" << result->name() << "'");
|
||||
}
|
||||
|
||||
if (dictionary.hasKey(KeyTag)) {
|
||||
if (dictionary.hasKeyAndValue<std::string>(KeyTag)) {
|
||||
std::string tagName = dictionary.value<std::string>(KeyTag);
|
||||
if (!tagName.empty()) {
|
||||
result->addTag(std::move(tagName));
|
||||
}
|
||||
} else if (dictionary.hasKeyAndValue<ghoul::Dictionary>(KeyTag)) {
|
||||
ghoul::Dictionary tagNames = dictionary.value<ghoul::Dictionary>(KeyTag);
|
||||
std::vector<std::string> keys = tagNames.keys();
|
||||
std::string tagName;
|
||||
for (const std::string& key : keys) {
|
||||
tagName = tagNames.value<std::string>(key);
|
||||
if (!tagName.empty()) {
|
||||
result->addTag(std::move(tagName));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
LDEBUG("Successfully created SceneGraphNode '"
|
||||
<< result->name() << "'");
|
||||
return std::move(result);
|
||||
@@ -263,7 +283,17 @@ void SceneGraphNode::update(const UpdateData& data) {
|
||||
|
||||
newUpdateData.modelTransform.translation = worldPosition();
|
||||
newUpdateData.modelTransform.rotation = worldRotationMatrix();
|
||||
newUpdateData.modelTransform .scale = worldScale();
|
||||
newUpdateData.modelTransform.scale = worldScale();
|
||||
|
||||
glm::dmat4 translation =
|
||||
glm::translate(glm::dmat4(1.0), newUpdateData.modelTransform.translation);
|
||||
glm::dmat4 rotation = glm::dmat4(newUpdateData.modelTransform.rotation);
|
||||
glm::dmat4 scaling =
|
||||
glm::scale(glm::dmat4(1.0), glm::dvec3(newUpdateData.modelTransform.scale,
|
||||
newUpdateData.modelTransform.scale, newUpdateData.modelTransform.scale));
|
||||
|
||||
_modelTransformCached = translation * rotation * scaling;
|
||||
_inverseModelTransformCached = glm::inverse(_modelTransformCached);
|
||||
|
||||
if (_renderable && _renderable->isReady()) {
|
||||
if (data.doPerformanceMeasurement) {
|
||||
@@ -476,6 +506,14 @@ const glm::dmat3& SceneGraphNode::worldRotationMatrix() const
|
||||
return _worldRotationCached;
|
||||
}
|
||||
|
||||
glm::dmat4 SceneGraphNode::modelTransform() const {
|
||||
return _modelTransformCached;
|
||||
}
|
||||
|
||||
glm::dmat4 SceneGraphNode::inverseModelTransform() const {
|
||||
return _inverseModelTransformCached;
|
||||
}
|
||||
|
||||
double SceneGraphNode::worldScale() const
|
||||
{
|
||||
return _worldScaleCached;
|
||||
|
||||
@@ -25,10 +25,7 @@
|
||||
#include <openspace/util/timemanager.h>
|
||||
#include <openspace/engine/openspaceengine.h>
|
||||
#include <openspace/util/time.h>
|
||||
|
||||
namespace {
|
||||
double SecondsOffTolerance = 0.1;
|
||||
}
|
||||
#include <openspace/network/parallelconnection.h>
|
||||
|
||||
namespace openspace {
|
||||
|
||||
@@ -96,8 +93,10 @@ void TimeManager::consumeKeyframes(double dt) {
|
||||
return;
|
||||
}
|
||||
|
||||
const double secondsOffTolerance = OsEng.parallelConnection().timeTolerance();
|
||||
|
||||
double predictedTime = time.j2000Seconds() + time.deltaTime() * (next._timestamp - now);
|
||||
bool withinTolerance = std::abs(predictedTime - next._time) < std::abs(next._dt * SecondsOffTolerance);
|
||||
bool withinTolerance = std::abs(predictedTime - next._time) < std::abs(next._dt * secondsOffTolerance);
|
||||
|
||||
if (next._dt == time.deltaTime() && withinTolerance) {
|
||||
Time::ref().advanceTime(dt);
|
||||
@@ -121,6 +120,7 @@ void TimeManager::consumeKeyframes(double dt) {
|
||||
|
||||
time.setDeltaTime(y1Prime);
|
||||
time.setTime(y1, false);
|
||||
// std::cout << "Correcting time to " << y1 << ", dt=" << y1Prime << "." << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,6 +133,13 @@ void TimeManager::addKeyframe(const TimeKeyframe& kf) {
|
||||
_keyframes.insert(iter, kf);
|
||||
}
|
||||
|
||||
void TimeManager::removeKeyframesAfter(double timestamp) {
|
||||
datamessagestructures::TimeKeyframe kf;
|
||||
kf._timestamp = timestamp;
|
||||
auto iter = std::upper_bound(_keyframes.begin(), _keyframes.end(), kf, &TimeManager::compareKeyframeTimes);
|
||||
_keyframes.erase(iter, _keyframes.end());
|
||||
}
|
||||
|
||||
|
||||
void TimeManager::removeKeyframesBefore(double timestamp) {
|
||||
datamessagestructures::TimeKeyframe kf;
|
||||
@@ -145,8 +152,11 @@ void TimeManager::clearKeyframes() {
|
||||
_keyframes.clear();
|
||||
}
|
||||
|
||||
bool TimeManager::compareKeyframeTimes(const TimeKeyframe& a, const TimeKeyframe& b)
|
||||
{
|
||||
const std::deque<datamessagestructures::TimeKeyframe>& TimeManager::keyframes() const {
|
||||
return _keyframes;
|
||||
}
|
||||
|
||||
bool TimeManager::compareKeyframeTimes(const TimeKeyframe& a, const TimeKeyframe& b) {
|
||||
return a._timestamp < b._timestamp;
|
||||
}
|
||||
|
||||
|
||||
@@ -80,6 +80,9 @@ TEST_F(DocumentationTest, Constructor) {
|
||||
doc.entries.emplace_back("NotInListInt", new IntNotInListVerifier({ 0, 1 }));
|
||||
doc.entries.emplace_back("NotInListString", new StringNotInListVerifier({ "", "a" }));
|
||||
|
||||
doc.entries.emplace_back("StringListVerifier", new StringListVerifier);
|
||||
doc.entries.emplace_back("IntListVerifier", new IntListVerifier);
|
||||
|
||||
// Range Verifiers
|
||||
doc.entries.emplace_back("InListDouble", new DoubleInRangeVerifier({ 0.0, 1.0 }));
|
||||
doc.entries.emplace_back("InListInt", new IntInRangeVerifier({ 0, 1 }));
|
||||
@@ -393,6 +396,63 @@ TEST_F(DocumentationTest, StringListVerifierType) {
|
||||
EXPECT_EQ(TestResult::Offense::Reason::MissingKey, negativeRes.offenses[0].reason);
|
||||
}
|
||||
|
||||
TEST_F(DocumentationTest, IntListVerifierType) {
|
||||
using namespace openspace::documentation;
|
||||
using namespace std::string_literals;
|
||||
|
||||
Documentation doc {
|
||||
{ { "IntList", new IntListVerifier } }
|
||||
};
|
||||
|
||||
ghoul::Dictionary positive {
|
||||
{
|
||||
"IntList",
|
||||
ghoul::Dictionary{
|
||||
{ "1", 1 },
|
||||
{ "2", 2 },
|
||||
{ "3", 3 }
|
||||
}
|
||||
}
|
||||
};
|
||||
TestResult positiveRes = testSpecification(doc, positive);
|
||||
EXPECT_TRUE(positiveRes.success);
|
||||
EXPECT_EQ(0, positiveRes.offenses.size());
|
||||
|
||||
ghoul::Dictionary negative{
|
||||
{ "IntList", 0 }
|
||||
};
|
||||
TestResult negativeRes = testSpecification(doc, negative);
|
||||
EXPECT_FALSE(negativeRes.success);
|
||||
ASSERT_EQ(1, negativeRes.offenses.size());
|
||||
EXPECT_EQ("IntList", negativeRes.offenses[0].offender);
|
||||
EXPECT_EQ(TestResult::Offense::Reason::WrongType, negativeRes.offenses[0].reason);
|
||||
|
||||
ghoul::Dictionary negative2 {
|
||||
{
|
||||
"IntList",
|
||||
ghoul::Dictionary{
|
||||
{ "1", "a"s },
|
||||
{ "2", 1 },
|
||||
{ "3", 2 }
|
||||
}
|
||||
}
|
||||
};
|
||||
negativeRes = testSpecification(doc, negative2);
|
||||
EXPECT_FALSE(negativeRes.success);
|
||||
ASSERT_EQ(1, negativeRes.offenses.size());
|
||||
EXPECT_EQ("IntList.1", negativeRes.offenses[0].offender);
|
||||
EXPECT_EQ(TestResult::Offense::Reason::WrongType, negativeRes.offenses[0].reason);
|
||||
|
||||
ghoul::Dictionary negativeExist {
|
||||
{ "IntList2", ghoul::Dictionary{} }
|
||||
};
|
||||
negativeRes = testSpecification(doc, negativeExist);
|
||||
EXPECT_FALSE(negativeRes.success);
|
||||
ASSERT_EQ(1, negativeRes.offenses.size());
|
||||
EXPECT_EQ("IntList", negativeRes.offenses[0].offender);
|
||||
EXPECT_EQ(TestResult::Offense::Reason::MissingKey, negativeRes.offenses[0].reason);
|
||||
}
|
||||
|
||||
TEST_F(DocumentationTest, MixedVerifiers) {
|
||||
using namespace openspace::documentation;
|
||||
using namespace std::string_literals;
|
||||
|
||||
Reference in New Issue
Block a user