From 6b29e314c20b672cf83a870724f966d2ad250357 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 25 Feb 2015 19:05:27 -0800 Subject: [PATCH 01/11] Adding the Stage of the Scene and exposing control of the sun light from javascript --- interface/src/Application.cpp | 15 +- libraries/gpu/src/gpu/Context.h | 2 +- libraries/gpu/src/gpu/GLBackend.h | 4 +- libraries/model/src/model/Stage.cpp | 442 ++++++++++++++++++ libraries/model/src/model/Stage.h | 200 ++++++++ .../src/SceneScriptingInterface.cpp | 36 ++ .../src/SceneScriptingInterface.h | 43 ++ libraries/script-engine/src/ScriptEngine.cpp | 5 + 8 files changed, 741 insertions(+), 6 deletions(-) create mode 100644 libraries/model/src/model/Stage.cpp create mode 100644 libraries/model/src/model/Stage.h create mode 100644 libraries/script-engine/src/SceneScriptingInterface.cpp create mode 100644 libraries/script-engine/src/SceneScriptingInterface.h diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index a7e73da1bd..9b27c6c570 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -82,6 +82,8 @@ #include #include +#include + #include "Application.h" #include "AudioClient.h" #include "InterfaceVersion.h" @@ -2495,7 +2497,10 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { glm::vec3 Application::getSunDirection() { // Sun direction is in fact just the location of the sun relative to the origin - return glm::normalize(_environment.getClosestData(_myCamera.getPosition()).getSunLocation(_myCamera.getPosition())); + // return glm::normalize(_environment.getClosestData(_myCamera.getPosition()).getSunLocation(_myCamera.getPosition())); + + auto skyStage = DependencyManager::get()->getSkyStage(); + return skyStage->getSunLight()->getDirection(); } void Application::updateShadowMap() { @@ -2505,7 +2510,7 @@ void Application::updateShadowMap() { glEnable(GL_DEPTH_TEST); glClear(GL_DEPTH_BUFFER_BIT); - glm::vec3 lightDirection = -getSunDirection(); + glm::vec3 lightDirection = getSunDirection(); glm::quat rotation = rotationBetween(IDENTITY_FRONT, lightDirection); glm::quat inverseRotation = glm::inverse(rotation); @@ -2875,7 +2880,11 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs { DependencyManager::get()->setAmbientLightMode(getRenderAmbientLight()); - DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, GLOBAL_LIGHT_INTENSITY); + // DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, GLOBAL_LIGHT_INTENSITY); + auto skyStage = DependencyManager::get()->getSkyStage(); +// DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, skyStage->_light->getIntensity()); + DependencyManager::get()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity()); + PROFILE_RANGE("DeferredLighting"); PerformanceTimer perfTimer("lighting"); DependencyManager::get()->render(); diff --git a/libraries/gpu/src/gpu/Context.h b/libraries/gpu/src/gpu/Context.h index b8cba3ded1..8140c91bf6 100644 --- a/libraries/gpu/src/gpu/Context.h +++ b/libraries/gpu/src/gpu/Context.h @@ -21,7 +21,7 @@ namespace gpu { class GPUObject { public: GPUObject() {} - ~GPUObject() {} + virtual ~GPUObject() {} }; class Batch; diff --git a/libraries/gpu/src/gpu/GLBackend.h b/libraries/gpu/src/gpu/GLBackend.h index e3450ae71a..806ba0b1eb 100644 --- a/libraries/gpu/src/gpu/GLBackend.h +++ b/libraries/gpu/src/gpu/GLBackend.h @@ -32,7 +32,7 @@ public: static void checkGLError(); - class GLBuffer { + class GLBuffer : public GPUObject { public: Stamp _stamp; GLuint _buffer; @@ -44,7 +44,7 @@ public: static void syncGPUObject(const Buffer& buffer); static GLuint getBufferID(const Buffer& buffer); - class GLTexture { + class GLTexture : public GPUObject { public: Stamp _storageStamp; Stamp _contentStamp; diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp new file mode 100644 index 0000000000..64aa504965 --- /dev/null +++ b/libraries/model/src/model/Stage.cpp @@ -0,0 +1,442 @@ +// +// Stage.cpp +// libraries/model/src/model +// +// Created by Sam Gateau on 2/24/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "Stage.h" + +#include +using namespace model; + + +void EarthSunModel::updateAll() const { + updateWorldToSurface(); + updateSurfaceToEye(); + updateSun(); +} + +Mat4d EarthSunModel::evalWorldToGeoLocationMat(double longitude, double latitude, double absAltitude, double scale) { + + + // Longitude is along Z axis but - from east to west + Mat4d rotLon = glm::rotate(glm::radians(longitude), Vec3d(0.0, 0.0, 1.0)); + + // latitude is along X axis + from south to north + Mat4d rotLat = glm::rotate(-glm::radians(latitude), Vec3d(1.0, 0.0, 0.0)); + + // translation is movin to the earth surface + altiture at the radius along Y axis + Mat4d surfaceT = glm::translate(Vec3d(0.0, -absAltitude, 0.0)); + + // Mat4d worldScale = glm::scale(Vec3d(scale)); + + Mat4d worldToGeoLocMat = surfaceT * rotLat * rotLon; + + return worldToGeoLocMat; +} + +void EarthSunModel::updateWorldToSurface() const { + // Check if the final position is too close to the earth center ? + double absAltitude = _earthRadius + _altitude; + if ( absAltitude < 0.01) { + absAltitude = 0.01; + } + + // Final world to local Frame + _worldToSurfaceMat = evalWorldToGeoLocationMat(_longitude, _latitude, absAltitude, _scale); + // and the inverse + _surfaceToWorldMat = glm::inverse(_worldToSurfaceMat); + + _surfacePos = Vec3d(_surfaceToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0)); +} + +void EarthSunModel::updateSurfaceToEye() const +{ + + _surfaceToEyeMat = glm::inverse(_eyeToSurfaceMat); + _worldToEyeMat = _surfaceToEyeMat * _worldToSurfaceMat; + _eyeToWorldMat = _surfaceToWorldMat * _eyeToSurfaceMat; + _eyePos = Vec3d(_eyeToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0) ); + _eyeDir = Vec3d(_eyeToWorldMat * Vec4d(0.0, 0.0, -1.0, 0.0) ); +} + +void EarthSunModel::updateSun() const { + // Longitude is along Y axis but - from east to west + Mat4d rotSunLon; + + Mat4d rotSun = evalWorldToGeoLocationMat(_sunLongitude, _sunLatitude, _earthRadius, _scale); + rotSun = glm::inverse(rotSun); + + _sunDir = Vec3d(rotSun * Vec4d(0.0, 1.0, 0.0, 0.0)); + + // sun direction is looking up toward Y axis at the specified sun lat, long + Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); + _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); +} + + +float moduloRange(float val, float minVal, float maxVal) { + float range = maxVal - minVal; + float rval = (val - minVal) / range; + float intval; + return modf(rval, &intval) * range + minVal; +} + +void EarthSunModel::setLatitude(float lat) { + _latitude = moduloRange(lat, -90.0f, 90.0f); + invalidate(); +} +void EarthSunModel::setLongitude(float lon) { + _longitude = moduloRange(lon, -180.0f, 180.0f); + invalidate(); +} +void EarthSunModel::setAltitude(float altitude) { + _altitude = moduloRange(altitude, -1000.f, 100000.f); + invalidate(); +} + +void EarthSunModel::setSunLatitude(float lat) { + _sunLatitude = moduloRange(lat, -90.0f, 90.0f); + invalidate(); +} +void EarthSunModel::setSunLongitude(float lon) { + _sunLongitude = moduloRange(lon, -180.0f, 180.0f); + invalidate(); +} + +const int NUM_DAYS_PER_YEAR = 365; +const float NUM_HOURS_PER_DAY = 24.0f; + +SunSkyStage::SunSkyStage() : + _sunLight(new Light()) +{ + _sunLight->setType(Light::SUN); + + setSunIntensity(1.0f); + setSunColor(Vec3(1.0f, 1.0f, 1.0f)); + + // setOriginLocation(45.0f, 20.0f, 1.0f); + setDayTime(18.0f); + setYearTime(60.0f); +} + +SunSkyStage::~SunSkyStage() { +} + +void SunSkyStage::setDayTime(float hour) { + _dayTime = moduloRange(hour, 0.f, NUM_HOURS_PER_DAY); + invalidate(); +} + +void SunSkyStage::setYearTime(unsigned int day) { + _yearTime = day % NUM_DAYS_PER_YEAR; + invalidate(); +} + +void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { + _earthSunModel.setLongitude(longitude); + _earthSunModel.setLatitude(latitude); + _earthSunModel.setAltitude(altitude); + invalidate(); +} + +void SunSkyStage::setSunColor(const Vec3& color) { + _sunLight->setColor(color); +} +void SunSkyStage::setSunIntensity(float intensity) { + _sunLight->setIntensity(intensity); +} + +void SunSkyStage::updateGraphicsObject() const { + // Always update the sunLongitude based on the current dayTIme and the current origin + _earthSunModel.setSunLongitude(_earthSunModel.getLongitude() + (-180.0 + 360.0 * _dayTime / NUM_HOURS_PER_DAY)); + + // And update the sunLAtitude as the declinaison depending of the time of the year + _earthSunModel.setSunLatitude(-(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(_yearTime + 10)))); + + Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); + + _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); +} + + + + + + +// +// Environment.cpp +// interface/src +// +// Created by Andrzej Kapolka on 5/6/13. +// Copyright 2013 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "InterfaceConfig.h" + +#include +#include +#include + +#include +#include +#include +#include +#include + +#include "Application.h" +#include "Camera.h" +#include "world.h" + +#include "Environment.h" + +uint qHash(const HifiSockAddr& sockAddr) { + if (sockAddr.getAddress().isNull()) { + return 0; // shouldn't happen, but if it does, zero is a perfectly valid hash + } + quint32 address = sockAddr.getAddress().toIPv4Address(); + return sockAddr.getPort() + qHash(QByteArray::fromRawData((char*) &address, + sizeof(address))); +} + +Environment::Environment() + : _initialized(false) { +} + +Environment::~Environment() { + if (_initialized) { + delete _skyFromAtmosphereProgram; + delete _skyFromSpaceProgram; + } +} + +void Environment::init() { + if (_initialized) { + qDebug("[ERROR] Environment is already initialized."); + return; + } + + _skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations); + _skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations); + + // start off with a default-constructed environment data + _data[HifiSockAddr()][0]; + + _initialized = true; +} + +void Environment::resetToDefault() { + _data.clear(); + _data[HifiSockAddr()][0]; +} + +void Environment::renderAtmospheres(Camera& camera) { + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + foreach (const ServerData& serverData, _data) { + // TODO: do something about EnvironmentData + foreach (const EnvironmentData& environmentData, serverData) { + renderAtmosphere(camera, environmentData); + } + } +} + +glm::vec3 Environment::getGravity (const glm::vec3& position) { + // + // 'Default' gravity pulls you downward in Y when you are near the X/Z plane + const glm::vec3 DEFAULT_GRAVITY(0.0f, -1.0f, 0.0f); + glm::vec3 gravity(DEFAULT_GRAVITY); + float DEFAULT_SURFACE_RADIUS = 30.0f; + float gravityStrength; + + // Weaken gravity with height + if (position.y > 0.0f) { + gravityStrength = 1.0f / powf((DEFAULT_SURFACE_RADIUS + position.y) / DEFAULT_SURFACE_RADIUS, 2.0f); + gravity *= gravityStrength; + } + + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + glm::vec3 vector = environmentData.getAtmosphereCenter(position) - position; + float surfaceRadius = environmentData.getAtmosphereInnerRadius(); + if (glm::length(vector) <= surfaceRadius) { + // At or inside a planet, gravity is as set for the planet + gravity += glm::normalize(vector) * environmentData.getGravity(); + } else { + // Outside a planet, the gravity falls off with distance + gravityStrength = 1.0f / powf(glm::length(vector) / surfaceRadius, 2.0f); + gravity += glm::normalize(vector) * environmentData.getGravity() * gravityStrength; + } + } + } + + return gravity; +} + +const EnvironmentData Environment::getClosestData(const glm::vec3& position) { + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + EnvironmentData closest; + float closestDistance = FLT_MAX; + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + float distance = glm::distance(position, environmentData.getAtmosphereCenter(position)) - + environmentData.getAtmosphereOuterRadius(); + if (distance < closestDistance) { + closest = environmentData; + closestDistance = distance; + } + } + } + return closest; +} + +bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, + float radius, glm::vec3& penetration) { + // collide with the "floor" + bool found = findCapsulePlanePenetration(start, end, radius, glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), penetration); + + glm::vec3 middle = (start + end) * 0.5f; + + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + foreach (const ServerData& serverData, _data) { + foreach (const EnvironmentData& environmentData, serverData) { + if (environmentData.getGravity() == 0.0f) { + continue; // don't bother colliding with gravity-less environments + } + glm::vec3 environmentPenetration; + if (findCapsuleSpherePenetration(start, end, radius, environmentData.getAtmosphereCenter(middle), + environmentData.getAtmosphereInnerRadius(), environmentPenetration)) { + penetration = addPenetrations(penetration, environmentPenetration); + found = true; + } + } + } + return found; +} + +int Environment::parseData(const HifiSockAddr& senderAddress, const QByteArray& packet) { + // push past the packet header + int bytesRead = numBytesForPacketHeader(packet); + + // push past flags, sequence, timestamp + bytesRead += sizeof(OCTREE_PACKET_FLAGS); + bytesRead += sizeof(OCTREE_PACKET_SEQUENCE); + bytesRead += sizeof(OCTREE_PACKET_SENT_TIME); + + // get the lock for the duration of the call + QMutexLocker locker(&_mutex); + + EnvironmentData newData; + while (bytesRead < packet.size()) { + int dataLength = newData.parseData(reinterpret_cast(packet.data()) + bytesRead, + packet.size() - bytesRead); + + // update the mapping by address/ID + _data[senderAddress][newData.getID()] = newData; + + bytesRead += dataLength; + } + + // remove the default mapping, if any + _data.remove(HifiSockAddr()); + + return bytesRead; +} + +ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { + ProgramObject* program = new ProgramObject(); + QByteArray prefix = QString(PathUtils::resourcesPath() + "/shaders/SkyFrom" + from).toUtf8(); + program->addShaderFromSourceFile(QGLShader::Vertex, prefix + ".vert"); + program->addShaderFromSourceFile(QGLShader::Fragment, prefix + ".frag"); + program->link(); + + locations[CAMERA_POS_LOCATION] = program->uniformLocation("v3CameraPos"); + locations[LIGHT_POS_LOCATION] = program->uniformLocation("v3LightPos"); + locations[INV_WAVELENGTH_LOCATION] = program->uniformLocation("v3InvWavelength"); + locations[CAMERA_HEIGHT2_LOCATION] = program->uniformLocation("fCameraHeight2"); + locations[OUTER_RADIUS_LOCATION] = program->uniformLocation("fOuterRadius"); + locations[OUTER_RADIUS2_LOCATION] = program->uniformLocation("fOuterRadius2"); + locations[INNER_RADIUS_LOCATION] = program->uniformLocation("fInnerRadius"); + locations[KR_ESUN_LOCATION] = program->uniformLocation("fKrESun"); + locations[KM_ESUN_LOCATION] = program->uniformLocation("fKmESun"); + locations[KR_4PI_LOCATION] = program->uniformLocation("fKr4PI"); + locations[KM_4PI_LOCATION] = program->uniformLocation("fKm4PI"); + locations[SCALE_LOCATION] = program->uniformLocation("fScale"); + locations[SCALE_DEPTH_LOCATION] = program->uniformLocation("fScaleDepth"); + locations[SCALE_OVER_SCALE_DEPTH_LOCATION] = program->uniformLocation("fScaleOverScaleDepth"); + locations[G_LOCATION] = program->uniformLocation("g"); + locations[G2_LOCATION] = program->uniformLocation("g2"); + + return program; +} + +void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) { + glm::vec3 center = data.getAtmosphereCenter(camera.getPosition()); + + glPushMatrix(); + glTranslatef(center.x, center.y, center.z); + + glm::vec3 relativeCameraPos = camera.getPosition() - center; + float height = glm::length(relativeCameraPos); + + // use the appropriate shader depending on whether we're inside or outside + ProgramObject* program; + int* locations; + if (height < data.getAtmosphereOuterRadius()) { + program = _skyFromAtmosphereProgram; + locations = _skyFromAtmosphereUniformLocations; + + } else { + program = _skyFromSpaceProgram; + locations = _skyFromSpaceUniformLocations; + } + + // the constants here are from Sean O'Neil's GPU Gems entry + // (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp + program->bind(); + program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos); + glm::vec3 lightDirection = glm::normalize(data.getSunLocation()); + program->setUniform(locations[LIGHT_POS_LOCATION], lightDirection); + program->setUniformValue(locations[INV_WAVELENGTH_LOCATION], + 1 / powf(data.getScatteringWavelengths().r, 4.0f), + 1 / powf(data.getScatteringWavelengths().g, 4.0f), + 1 / powf(data.getScatteringWavelengths().b, 4.0f)); + program->setUniformValue(locations[CAMERA_HEIGHT2_LOCATION], height * height); + program->setUniformValue(locations[OUTER_RADIUS_LOCATION], data.getAtmosphereOuterRadius()); + program->setUniformValue(locations[OUTER_RADIUS2_LOCATION], data.getAtmosphereOuterRadius() * data.getAtmosphereOuterRadius()); + program->setUniformValue(locations[INNER_RADIUS_LOCATION], data.getAtmosphereInnerRadius()); + program->setUniformValue(locations[KR_ESUN_LOCATION], data.getRayleighScattering() * data.getSunBrightness()); + program->setUniformValue(locations[KM_ESUN_LOCATION], data.getMieScattering() * data.getSunBrightness()); + program->setUniformValue(locations[KR_4PI_LOCATION], data.getRayleighScattering() * 4.0f * PI); + program->setUniformValue(locations[KM_4PI_LOCATION], data.getMieScattering() * 4.0f * PI); + program->setUniformValue(locations[SCALE_LOCATION], 1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())); + program->setUniformValue(locations[SCALE_DEPTH_LOCATION], 0.25f); + program->setUniformValue(locations[SCALE_OVER_SCALE_DEPTH_LOCATION], + (1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f); + program->setUniformValue(locations[G_LOCATION], -0.990f); + program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); + + glDepthMask(GL_FALSE); + glDisable(GL_DEPTH_TEST); + DependencyManager::get()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere + glDepthMask(GL_TRUE); + + program->release(); + + glPopMatrix(); +} diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h new file mode 100644 index 0000000000..9b2922e163 --- /dev/null +++ b/libraries/model/src/model/Stage.h @@ -0,0 +1,200 @@ +// +// Stage.h +// libraries/model/src/model +// +// Created by Sam Gateau on 2/24/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#ifndef hifi_model_Stage_h +#define hifi_model_Stage_h + +#include "Light.h" + +namespace model { + +typedef glm::dvec3 Vec3d; +typedef glm::dvec4 Vec4d; +typedef glm::dmat4 Mat4d; +typedef glm::mat4 Mat4; + +class EarthSunModel { +public: + enum Preset + { + Toulouse = 0, + SanFrancisco, + Sydney, + Num_Presets, + }; + static const std::string PresetNames[Num_Presets]; + //void assignPreset( Preset p); + //Preset preset() const { return mPreset; } + + void setScale(float scale); + float getScale() const { return _scale; } + + void setLatitude(float lat); + float getLatitude() const { return _latitude; } + void setLongitude(float lon); + float getLongitude() const { return _longitude; } + void setAltitude(float altitude); + float getAltitude() const { return _altitude; } + + const Vec3d& getSurfacePos() const { valid(); return _surfacePos; } + + const Mat4d& getSurfaceToWorldMat() const { valid(); return _surfaceToWorldMat; } + const Mat4d& getWoldToSurfaceMat() const { valid(); return _worldToSurfaceMat; } + + const Mat4d& getEyeToSurfaceMat() const { valid(); return _eyeToSurfaceMat; } + const Mat4d& getSurfaceToEyeMat() const { valid(); return _surfaceToEyeMat; } + + const Mat4d& getEyeToWorldMat() const { valid(); return _eyeToWorldMat; } + const Mat4d& getWorldToEyeMat() const { valid(); return _worldToEyeMat; } + + + //or set the surfaceToEye mat directly + void setEyeToSurfaceMat( const Mat4d& e2s); + + const Vec3d& getEyePos() const { valid(); return _eyePos; } + const Vec3d& getEyeDir() const { valid(); return _eyeDir; } + + void setSunLongitude(float lon); + float getSunLongitude() const { return _sunLongitude; } + + void setSunLatitude(float lat); + float getSunLatitude() const { return _sunLatitude; } + + const Vec3d& getWorldSunDir() const { valid(); return _sunDir; } + const Vec3d& getSurfaceSunDir() const { valid(); return _surfaceSunDir; } + + + EarthSunModel() { valid(); } + +protected: + double _scale = 1000.0; //Km + double _earthRadius = 6360.0; + + double _longitude = 0.0; + double _latitude = 0.0; + double _altitude = 0.01; + mutable Vec3d _surfacePos; + mutable Mat4d _worldToSurfaceMat; + mutable Mat4d _surfaceToWorldMat; + void updateWorldToSurface() const; + + mutable Mat4d _surfaceToEyeMat; + mutable Mat4d _eyeToSurfaceMat; + mutable Vec3d _eyeDir; + mutable Vec3d _eyePos; + void updateSurfaceToEye() const; + + mutable Mat4d _worldToEyeMat; + mutable Mat4d _eyeToWorldMat; + + double _sunLongitude = 0.0; + double _sunLatitude = 0.0; + mutable Vec3d _sunDir; + mutable Vec3d _surfaceSunDir; + void updateSun() const; + + mutable bool _invalid = true; + void invalidate() const { _invalid = true; } + void valid() const { if (_invalid) { updateAll(); _invalid = false; } } + void updateAll() const; + + static Mat4d evalWorldToGeoLocationMat(double longitude, double latitude, double altitude, double scale); +}; + +namespace gpu { + class Batch; +}; + +class ProgramObject; + +class Skybox { +public: + void recordBatch(gpu::Batch& batch, const Transform& viewTransform, const Mat4& projection); + + Skybox(); + ~Skybox(); +protected: + ProgramObject* createSkyProgram(const char* from, int* locations); + ProgramObject* _skyFromAtmosphereProgram; + ProgramObject* _skyFromSpaceProgram; + enum { + CAMERA_POS_LOCATION, + LIGHT_POS_LOCATION, + INV_WAVELENGTH_LOCATION, + CAMERA_HEIGHT2_LOCATION, + OUTER_RADIUS_LOCATION, + OUTER_RADIUS2_LOCATION, + INNER_RADIUS_LOCATION, + KR_ESUN_LOCATION, + KM_ESUN_LOCATION, + KR_4PI_LOCATION, + KM_4PI_LOCATION, + SCALE_LOCATION, + SCALE_DEPTH_LOCATION, + SCALE_OVER_SCALE_DEPTH_LOCATION, + G_LOCATION, + G2_LOCATION, + LOCATION_COUNT + }; + + int _skyFromAtmosphereUniformLocations[LOCATION_COUNT]; + int _skyFromSpaceUniformLocations[LOCATION_COUNT]; +}; + +// Sun sky stage generates the rendering primitives to display a scene realistically +// at the specified location and time around earth +class SunSkyStage { +public: + + SunSkyStage(); + ~SunSkyStage(); + + // time of the day (local to the position) expressed in decimal hour in the range [0.0, 24.0] + void setDayTime(float hour); + float getDayTime() const { return _dayTime; } + + // time of the year expressed in day in the range [0, 365] + void setYearTime(unsigned int day); + unsigned int getYearTime() const { return _yearTime; } + + // Location used to define the sun & sky is a longitude and latitude [rad] and a earth surface altitude [km] + void setOriginLocation(float longitude, float latitude, float surfaceAltitude); + float getOriginLatitude() const { return _earthSunModel.getLatitude(); } + float getOriginLongitude() const { return _earthSunModel.getLongitude(); } + float getOriginSurfaceAltitude() const { return _earthSunModel.getAltitude(); } + + // Sun properties + void setSunColor(const Vec3& color); + const Vec3& getSunColor() const { return getSunLight()->getColor(); } + void setSunIntensity(float intensity); + float getSunIntensity() const { return getSunLight()->getIntensity(); } + + LightPointer getSunLight() const { valid(); return _sunLight; } + +protected: + LightPointer _sunLight; + + // default day is 1st of january at noun + float _dayTime = 12.0f; + int _yearTime = 0; + + mutable EarthSunModel _earthSunModel; + + mutable bool _invalid = true; + void invalidate() const { _invalid = true; } + void valid() const { if (_invalid) { updateGraphicsObject(); _invalid = false; } } + void updateGraphicsObject() const; +}; + +typedef QSharedPointer< SunSkyStage > SunSkyStagePointer; + +}; + +#endif diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp new file mode 100644 index 0000000000..ff255a3e5e --- /dev/null +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -0,0 +1,36 @@ +// +// SceneScriptingInterface.cpp +// interface/src/scripting +// +// Created by Sam Gateau on 2/24/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include + +#include "SceneScriptingInterface.h" + + Q_INVOKABLE void setOriginGeoLocation(float longitude, float latitude, float altitude); +void SceneScriptingInterface::setOriginLocation(float longitude, float latitude, float altitude) { + _skyStage->setOriginLocation(longitude, latitude, altitude); +} +void SceneScriptingInterface::setSunColor(const glm::vec3& color) { + _skyStage->setSunColor(color); +} +void SceneScriptingInterface::setSunIntensity(float intensity) { + _skyStage->setSunIntensity(intensity); +} + +void SceneScriptingInterface::setDayTime(float hour) { + _skyStage->setDayTime(hour); +} +void SceneScriptingInterface::setYearTime(int day) { + _skyStage->setYearTime(day); +} + +model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const { + return _skyStage; +} \ No newline at end of file diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h new file mode 100644 index 0000000000..3fc909f9a0 --- /dev/null +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -0,0 +1,43 @@ +// +// SceneScriptingInterface.h +// interface/src/scripting +// +// Created by Sam Gateau on 2/24/15. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_SceneScriptingInterface_h +#define hifi_SceneScriptingInterface_h + +#include + +#include + +#include "model/Stage.h" + +class SceneScriptingInterface : public QObject, public Dependency { + Q_OBJECT + SINGLETON_DEPENDENCY + +public: + Q_INVOKABLE void setOriginLocation(float longitude, float latitude, float altitude); + + Q_INVOKABLE void setSunColor(const glm::vec3& color); + Q_INVOKABLE void setSunIntensity(float intensity); + + Q_INVOKABLE void setDayTime(float hour); + Q_INVOKABLE void setYearTime(int day); + + model::SunSkyStagePointer getSkyStage() const; + +protected: + SceneScriptingInterface() {}; + ~SceneScriptingInterface() {}; + + model::SunSkyStagePointer _skyStage = model::SunSkyStagePointer(new model::SunSkyStage()); +}; + +#endif // hifi_SceneScriptingInterface_h diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 0956374238..aed5d91410 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -39,6 +39,8 @@ #include "TypedArrays.h" #include "XMLHttpRequestClass.h" +#include "SceneScriptingInterface.h" + #include "MIDIEvent.h" EntityScriptingInterface ScriptEngine::_entityScriptingInterface; @@ -208,6 +210,8 @@ void ScriptEngine::init() { _isInitialized = true; + auto sceneScriptingInterface = DependencyManager::set(); + _entityScriptingInterface.init(); // register various meta-types @@ -251,6 +255,7 @@ void ScriptEngine::init() { registerGlobalObject("Vec3", &_vec3Library); registerGlobalObject("Uuid", &_uuidLibrary); registerGlobalObject("AnimationCache", DependencyManager::get().data()); + registerGlobalObject("Scene", DependencyManager::get().data()); // constants globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE))); From b4cb5ca9d1e455ec7425a950259bdbc7bb65c9f7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 25 Feb 2015 19:09:18 -0800 Subject: [PATCH 02/11] add an example script to control the sun light --- examples/example/misc/sunLightExample.js | 32 ++++++++++++++++++++++++ 1 file changed, 32 insertions(+) create mode 100644 examples/example/misc/sunLightExample.js diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js new file mode 100644 index 0000000000..0bc3b0dfea --- /dev/null +++ b/examples/example/misc/sunLightExample.js @@ -0,0 +1,32 @@ +// +// SunLightExample.js +// examples +// Sam Gateau +// Copyright 2015 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +var intensity = 1.0; +var day = 0.0; +var hour = 12.0; +var longitude = 0.0; +var latitude = -45.0; + +Scene.setDayTime(hour); +Scene.setOriginLocation(longitude, latitude, 0.0); + +function ticktack() { + hour += 0.1; + //Scene.setSunIntensity(Math.cos(time)); + if (hour > 24.0) { + hour = 0.0; + day++; + Scene.setYearTime(day); + } + Scene.setDayTime(hour); + +} + +Script.setInterval(ticktack, 41); From 4959e2924e0bd00ab17ed7812763c35cfae5300b Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Wed, 25 Feb 2015 19:17:38 -0800 Subject: [PATCH 03/11] add an example script to control the sun light --- libraries/model/src/model/Stage.cpp | 277 ---------------------------- 1 file changed, 277 deletions(-) diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 64aa504965..dcd633f35c 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -163,280 +163,3 @@ void SunSkyStage::updateGraphicsObject() const { _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); } - - - - - -// -// Environment.cpp -// interface/src -// -// Created by Andrzej Kapolka on 5/6/13. -// Copyright 2013 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// - -#include "InterfaceConfig.h" - -#include -#include -#include - -#include -#include -#include -#include -#include - -#include "Application.h" -#include "Camera.h" -#include "world.h" - -#include "Environment.h" - -uint qHash(const HifiSockAddr& sockAddr) { - if (sockAddr.getAddress().isNull()) { - return 0; // shouldn't happen, but if it does, zero is a perfectly valid hash - } - quint32 address = sockAddr.getAddress().toIPv4Address(); - return sockAddr.getPort() + qHash(QByteArray::fromRawData((char*) &address, - sizeof(address))); -} - -Environment::Environment() - : _initialized(false) { -} - -Environment::~Environment() { - if (_initialized) { - delete _skyFromAtmosphereProgram; - delete _skyFromSpaceProgram; - } -} - -void Environment::init() { - if (_initialized) { - qDebug("[ERROR] Environment is already initialized."); - return; - } - - _skyFromAtmosphereProgram = createSkyProgram("Atmosphere", _skyFromAtmosphereUniformLocations); - _skyFromSpaceProgram = createSkyProgram("Space", _skyFromSpaceUniformLocations); - - // start off with a default-constructed environment data - _data[HifiSockAddr()][0]; - - _initialized = true; -} - -void Environment::resetToDefault() { - _data.clear(); - _data[HifiSockAddr()][0]; -} - -void Environment::renderAtmospheres(Camera& camera) { - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - foreach (const ServerData& serverData, _data) { - // TODO: do something about EnvironmentData - foreach (const EnvironmentData& environmentData, serverData) { - renderAtmosphere(camera, environmentData); - } - } -} - -glm::vec3 Environment::getGravity (const glm::vec3& position) { - // - // 'Default' gravity pulls you downward in Y when you are near the X/Z plane - const glm::vec3 DEFAULT_GRAVITY(0.0f, -1.0f, 0.0f); - glm::vec3 gravity(DEFAULT_GRAVITY); - float DEFAULT_SURFACE_RADIUS = 30.0f; - float gravityStrength; - - // Weaken gravity with height - if (position.y > 0.0f) { - gravityStrength = 1.0f / powf((DEFAULT_SURFACE_RADIUS + position.y) / DEFAULT_SURFACE_RADIUS, 2.0f); - gravity *= gravityStrength; - } - - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - foreach (const ServerData& serverData, _data) { - foreach (const EnvironmentData& environmentData, serverData) { - glm::vec3 vector = environmentData.getAtmosphereCenter(position) - position; - float surfaceRadius = environmentData.getAtmosphereInnerRadius(); - if (glm::length(vector) <= surfaceRadius) { - // At or inside a planet, gravity is as set for the planet - gravity += glm::normalize(vector) * environmentData.getGravity(); - } else { - // Outside a planet, the gravity falls off with distance - gravityStrength = 1.0f / powf(glm::length(vector) / surfaceRadius, 2.0f); - gravity += glm::normalize(vector) * environmentData.getGravity() * gravityStrength; - } - } - } - - return gravity; -} - -const EnvironmentData Environment::getClosestData(const glm::vec3& position) { - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - EnvironmentData closest; - float closestDistance = FLT_MAX; - foreach (const ServerData& serverData, _data) { - foreach (const EnvironmentData& environmentData, serverData) { - float distance = glm::distance(position, environmentData.getAtmosphereCenter(position)) - - environmentData.getAtmosphereOuterRadius(); - if (distance < closestDistance) { - closest = environmentData; - closestDistance = distance; - } - } - } - return closest; -} - -bool Environment::findCapsulePenetration(const glm::vec3& start, const glm::vec3& end, - float radius, glm::vec3& penetration) { - // collide with the "floor" - bool found = findCapsulePlanePenetration(start, end, radius, glm::vec4(0.0f, 1.0f, 0.0f, 0.0f), penetration); - - glm::vec3 middle = (start + end) * 0.5f; - - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - foreach (const ServerData& serverData, _data) { - foreach (const EnvironmentData& environmentData, serverData) { - if (environmentData.getGravity() == 0.0f) { - continue; // don't bother colliding with gravity-less environments - } - glm::vec3 environmentPenetration; - if (findCapsuleSpherePenetration(start, end, radius, environmentData.getAtmosphereCenter(middle), - environmentData.getAtmosphereInnerRadius(), environmentPenetration)) { - penetration = addPenetrations(penetration, environmentPenetration); - found = true; - } - } - } - return found; -} - -int Environment::parseData(const HifiSockAddr& senderAddress, const QByteArray& packet) { - // push past the packet header - int bytesRead = numBytesForPacketHeader(packet); - - // push past flags, sequence, timestamp - bytesRead += sizeof(OCTREE_PACKET_FLAGS); - bytesRead += sizeof(OCTREE_PACKET_SEQUENCE); - bytesRead += sizeof(OCTREE_PACKET_SENT_TIME); - - // get the lock for the duration of the call - QMutexLocker locker(&_mutex); - - EnvironmentData newData; - while (bytesRead < packet.size()) { - int dataLength = newData.parseData(reinterpret_cast(packet.data()) + bytesRead, - packet.size() - bytesRead); - - // update the mapping by address/ID - _data[senderAddress][newData.getID()] = newData; - - bytesRead += dataLength; - } - - // remove the default mapping, if any - _data.remove(HifiSockAddr()); - - return bytesRead; -} - -ProgramObject* Environment::createSkyProgram(const char* from, int* locations) { - ProgramObject* program = new ProgramObject(); - QByteArray prefix = QString(PathUtils::resourcesPath() + "/shaders/SkyFrom" + from).toUtf8(); - program->addShaderFromSourceFile(QGLShader::Vertex, prefix + ".vert"); - program->addShaderFromSourceFile(QGLShader::Fragment, prefix + ".frag"); - program->link(); - - locations[CAMERA_POS_LOCATION] = program->uniformLocation("v3CameraPos"); - locations[LIGHT_POS_LOCATION] = program->uniformLocation("v3LightPos"); - locations[INV_WAVELENGTH_LOCATION] = program->uniformLocation("v3InvWavelength"); - locations[CAMERA_HEIGHT2_LOCATION] = program->uniformLocation("fCameraHeight2"); - locations[OUTER_RADIUS_LOCATION] = program->uniformLocation("fOuterRadius"); - locations[OUTER_RADIUS2_LOCATION] = program->uniformLocation("fOuterRadius2"); - locations[INNER_RADIUS_LOCATION] = program->uniformLocation("fInnerRadius"); - locations[KR_ESUN_LOCATION] = program->uniformLocation("fKrESun"); - locations[KM_ESUN_LOCATION] = program->uniformLocation("fKmESun"); - locations[KR_4PI_LOCATION] = program->uniformLocation("fKr4PI"); - locations[KM_4PI_LOCATION] = program->uniformLocation("fKm4PI"); - locations[SCALE_LOCATION] = program->uniformLocation("fScale"); - locations[SCALE_DEPTH_LOCATION] = program->uniformLocation("fScaleDepth"); - locations[SCALE_OVER_SCALE_DEPTH_LOCATION] = program->uniformLocation("fScaleOverScaleDepth"); - locations[G_LOCATION] = program->uniformLocation("g"); - locations[G2_LOCATION] = program->uniformLocation("g2"); - - return program; -} - -void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data) { - glm::vec3 center = data.getAtmosphereCenter(camera.getPosition()); - - glPushMatrix(); - glTranslatef(center.x, center.y, center.z); - - glm::vec3 relativeCameraPos = camera.getPosition() - center; - float height = glm::length(relativeCameraPos); - - // use the appropriate shader depending on whether we're inside or outside - ProgramObject* program; - int* locations; - if (height < data.getAtmosphereOuterRadius()) { - program = _skyFromAtmosphereProgram; - locations = _skyFromAtmosphereUniformLocations; - - } else { - program = _skyFromSpaceProgram; - locations = _skyFromSpaceUniformLocations; - } - - // the constants here are from Sean O'Neil's GPU Gems entry - // (http://http.developer.nvidia.com/GPUGems2/gpugems2_chapter16.html), GameEngine.cpp - program->bind(); - program->setUniform(locations[CAMERA_POS_LOCATION], relativeCameraPos); - glm::vec3 lightDirection = glm::normalize(data.getSunLocation()); - program->setUniform(locations[LIGHT_POS_LOCATION], lightDirection); - program->setUniformValue(locations[INV_WAVELENGTH_LOCATION], - 1 / powf(data.getScatteringWavelengths().r, 4.0f), - 1 / powf(data.getScatteringWavelengths().g, 4.0f), - 1 / powf(data.getScatteringWavelengths().b, 4.0f)); - program->setUniformValue(locations[CAMERA_HEIGHT2_LOCATION], height * height); - program->setUniformValue(locations[OUTER_RADIUS_LOCATION], data.getAtmosphereOuterRadius()); - program->setUniformValue(locations[OUTER_RADIUS2_LOCATION], data.getAtmosphereOuterRadius() * data.getAtmosphereOuterRadius()); - program->setUniformValue(locations[INNER_RADIUS_LOCATION], data.getAtmosphereInnerRadius()); - program->setUniformValue(locations[KR_ESUN_LOCATION], data.getRayleighScattering() * data.getSunBrightness()); - program->setUniformValue(locations[KM_ESUN_LOCATION], data.getMieScattering() * data.getSunBrightness()); - program->setUniformValue(locations[KR_4PI_LOCATION], data.getRayleighScattering() * 4.0f * PI); - program->setUniformValue(locations[KM_4PI_LOCATION], data.getMieScattering() * 4.0f * PI); - program->setUniformValue(locations[SCALE_LOCATION], 1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())); - program->setUniformValue(locations[SCALE_DEPTH_LOCATION], 0.25f); - program->setUniformValue(locations[SCALE_OVER_SCALE_DEPTH_LOCATION], - (1.0f / (data.getAtmosphereOuterRadius() - data.getAtmosphereInnerRadius())) / 0.25f); - program->setUniformValue(locations[G_LOCATION], -0.990f); - program->setUniformValue(locations[G2_LOCATION], -0.990f * -0.990f); - - glDepthMask(GL_FALSE); - glDisable(GL_DEPTH_TEST); - DependencyManager::get()->renderSphere(1.0f, 100, 50, glm::vec4(1.0f, 1.0f, 1.0f, 1.0f)); //Draw a unit sphere - glDepthMask(GL_TRUE); - - program->release(); - - glPopMatrix(); -} From fcb293d0b2155d4334610dc6448a2073356bbca7 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 10:45:00 -0800 Subject: [PATCH 04/11] CLean up before pr --- examples/example/misc/sunLightExample.js | 1 - interface/src/Application.cpp | 4 -- libraries/model/src/model/Stage.cpp | 56 +++++++++++++++++------- libraries/model/src/model/Stage.h | 55 +---------------------- 4 files changed, 42 insertions(+), 74 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 0bc3b0dfea..7f38211052 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -26,7 +26,6 @@ function ticktack() { Scene.setYearTime(day); } Scene.setDayTime(hour); - } Script.setInterval(ticktack, 41); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 298814f484..46fec006ca 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -2493,8 +2493,6 @@ void Application::loadViewFrustum(Camera& camera, ViewFrustum& viewFrustum) { glm::vec3 Application::getSunDirection() { // Sun direction is in fact just the location of the sun relative to the origin - // return glm::normalize(_environment.getClosestData(_myCamera.getPosition()).getSunLocation(_myCamera.getPosition())); - auto skyStage = DependencyManager::get()->getSkyStage(); return skyStage->getSunLight()->getDirection(); } @@ -2875,9 +2873,7 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs { DependencyManager::get()->setAmbientLightMode(getRenderAmbientLight()); - // DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, GLOBAL_LIGHT_INTENSITY); auto skyStage = DependencyManager::get()->getSkyStage(); -// DependencyManager::get()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, skyStage->_light->getIntensity()); DependencyManager::get()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity()); PROFILE_RANGE("DeferredLighting"); diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index dcd633f35c..12ed186cf6 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -21,8 +21,6 @@ void EarthSunModel::updateAll() const { } Mat4d EarthSunModel::evalWorldToGeoLocationMat(double longitude, double latitude, double absAltitude, double scale) { - - // Longitude is along Z axis but - from east to west Mat4d rotLon = glm::rotate(glm::radians(longitude), Vec3d(0.0, 0.0, 1.0)); @@ -54,9 +52,7 @@ void EarthSunModel::updateWorldToSurface() const { _surfacePos = Vec3d(_surfaceToWorldMat * Vec4d(0.0, 0.0, 0.0, 1.0)); } -void EarthSunModel::updateSurfaceToEye() const -{ - +void EarthSunModel::updateSurfaceToEye() const { _surfaceToEyeMat = glm::inverse(_eyeToSurfaceMat); _worldToEyeMat = _surfaceToEyeMat * _worldToSurfaceMat; _eyeToWorldMat = _surfaceToWorldMat * _eyeToSurfaceMat; @@ -76,8 +72,7 @@ void EarthSunModel::updateSun() const { // sun direction is looking up toward Y axis at the specified sun lat, long Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); -} - +} float moduloRange(float val, float minVal, float maxVal) { float range = maxVal - minVal; @@ -86,30 +81,48 @@ float moduloRange(float val, float minVal, float maxVal) { return modf(rval, &intval) * range + minVal; } +const float MAX_LONGITUDE = 180.0f; +const float MAX_LATITUDE = 90.0f; + +float validateLongitude(float lon) { + return moduloRange(lon, -MAX_LONGITUDE, MAX_LONGITUDE); +} + +float validateLatitude(float lat) { + return moduloRange(lat, -MAX_LATITUDE, MAX_LATITUDE); +} + +float validateAltitude(float altitude) { + const float MIN_ALTITUDE = -1000.0f; + const float MAX_ALTITUDE = 100000.0f; + return std::min(std::max(altitude, MIN_ALTITUDE), MAX_ALTITUDE); +} + void EarthSunModel::setLatitude(float lat) { - _latitude = moduloRange(lat, -90.0f, 90.0f); + _latitude = validateLatitude(lat); invalidate(); } void EarthSunModel::setLongitude(float lon) { - _longitude = moduloRange(lon, -180.0f, 180.0f); + _longitude = validateLongitude(lon); invalidate(); } void EarthSunModel::setAltitude(float altitude) { - _altitude = moduloRange(altitude, -1000.f, 100000.f); + _altitude = validateAltitude(altitude); invalidate(); } void EarthSunModel::setSunLatitude(float lat) { - _sunLatitude = moduloRange(lat, -90.0f, 90.0f); + _sunLatitude = validateLatitude(lat); invalidate(); } void EarthSunModel::setSunLongitude(float lon) { - _sunLongitude = moduloRange(lon, -180.0f, 180.0f); + _sunLongitude = validateLongitude(lon); invalidate(); } const int NUM_DAYS_PER_YEAR = 365; const float NUM_HOURS_PER_DAY = 24.0f; +const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f; SunSkyStage::SunSkyStage() : _sunLight(new Light()) @@ -119,8 +132,11 @@ SunSkyStage::SunSkyStage() : setSunIntensity(1.0f); setSunColor(Vec3(1.0f, 1.0f, 1.0f)); - // setOriginLocation(45.0f, 20.0f, 1.0f); + // Default origin location is a special place in the world... + setOriginLocation(122.407f, 37.777f, 0.03f); + // 6pm setDayTime(18.0f); + // Begining of march setYearTime(60.0f); } @@ -151,12 +167,20 @@ void SunSkyStage::setSunIntensity(float intensity) { _sunLight->setIntensity(intensity); } +// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun +double evalSunDeclinaison(double dayNumber) { + return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); +} + void SunSkyStage::updateGraphicsObject() const { - // Always update the sunLongitude based on the current dayTIme and the current origin - _earthSunModel.setSunLongitude(_earthSunModel.getLongitude() + (-180.0 + 360.0 * _dayTime / NUM_HOURS_PER_DAY)); + // Always update the sunLongitude based on the current dayTime and the current origin + // The day time is supposed to be local at the origin + double signedNormalizedDayTime = (_dayTime - NUM_HOURS_PER_HALF_DAY) / NUM_HOURS_PER_HALF_DAY; + double sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); + _earthSunModel.setSunLongitude(sunLongitude); // And update the sunLAtitude as the declinaison depending of the time of the year - _earthSunModel.setSunLatitude(-(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(_yearTime + 10)))); + _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index 9b2922e163..f99d2c1648 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -22,16 +22,6 @@ typedef glm::mat4 Mat4; class EarthSunModel { public: - enum Preset - { - Toulouse = 0, - SanFrancisco, - Sydney, - Num_Presets, - }; - static const std::string PresetNames[Num_Presets]; - //void assignPreset( Preset p); - //Preset preset() const { return mPreset; } void setScale(float scale); float getScale() const { return _scale; } @@ -108,46 +98,6 @@ protected: static Mat4d evalWorldToGeoLocationMat(double longitude, double latitude, double altitude, double scale); }; -namespace gpu { - class Batch; -}; - -class ProgramObject; - -class Skybox { -public: - void recordBatch(gpu::Batch& batch, const Transform& viewTransform, const Mat4& projection); - - Skybox(); - ~Skybox(); -protected: - ProgramObject* createSkyProgram(const char* from, int* locations); - ProgramObject* _skyFromAtmosphereProgram; - ProgramObject* _skyFromSpaceProgram; - enum { - CAMERA_POS_LOCATION, - LIGHT_POS_LOCATION, - INV_WAVELENGTH_LOCATION, - CAMERA_HEIGHT2_LOCATION, - OUTER_RADIUS_LOCATION, - OUTER_RADIUS2_LOCATION, - INNER_RADIUS_LOCATION, - KR_ESUN_LOCATION, - KM_ESUN_LOCATION, - KR_4PI_LOCATION, - KM_4PI_LOCATION, - SCALE_LOCATION, - SCALE_DEPTH_LOCATION, - SCALE_OVER_SCALE_DEPTH_LOCATION, - G_LOCATION, - G2_LOCATION, - LOCATION_COUNT - }; - - int _skyFromAtmosphereUniformLocations[LOCATION_COUNT]; - int _skyFromSpaceUniformLocations[LOCATION_COUNT]; -}; - // Sun sky stage generates the rendering primitives to display a scene realistically // at the specified location and time around earth class SunSkyStage { @@ -181,9 +131,8 @@ public: protected: LightPointer _sunLight; - // default day is 1st of january at noun - float _dayTime = 12.0f; - int _yearTime = 0; + float _dayTime; + int _yearTime; mutable EarthSunModel _earthSunModel; From b04dbf7a34b85ee5c013e12aedd0f66f1f14dbee Mon Sep 17 00:00:00 2001 From: dev Date: Thu, 26 Feb 2015 11:27:40 -0800 Subject: [PATCH 05/11] fixing compilation issue on macos --- libraries/model/src/model/Stage.cpp | 264 ++++++++++++++-------------- 1 file changed, 133 insertions(+), 131 deletions(-) diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 12ed186cf6..dd5a44a0cb 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -1,19 +1,21 @@ -// -// Stage.cpp -// libraries/model/src/model -// -// Created by Sam Gateau on 2/24/2015. -// Copyright 2014 High Fidelity, Inc. -// -// Distributed under the Apache License, Version 2.0. -// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html -// -#include "Stage.h" - -#include -using namespace model; - - +// +// Stage.cpp +// libraries/model/src/model +// +// Created by Sam Gateau on 2/24/2015. +// Copyright 2014 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// +#include "Stage.h" + +#include +#include + +using namespace model; + + void EarthSunModel::updateAll() const { updateWorldToSurface(); updateSurfaceToEye(); @@ -72,118 +74,118 @@ void EarthSunModel::updateSun() const { // sun direction is looking up toward Y axis at the specified sun lat, long Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); -} - -float moduloRange(float val, float minVal, float maxVal) { - float range = maxVal - minVal; - float rval = (val - minVal) / range; - float intval; - return modf(rval, &intval) * range + minVal; -} - -const float MAX_LONGITUDE = 180.0f; -const float MAX_LATITUDE = 90.0f; - -float validateLongitude(float lon) { - return moduloRange(lon, -MAX_LONGITUDE, MAX_LONGITUDE); -} - -float validateLatitude(float lat) { - return moduloRange(lat, -MAX_LATITUDE, MAX_LATITUDE); -} - -float validateAltitude(float altitude) { - const float MIN_ALTITUDE = -1000.0f; - const float MAX_ALTITUDE = 100000.0f; - return std::min(std::max(altitude, MIN_ALTITUDE), MAX_ALTITUDE); -} - -void EarthSunModel::setLatitude(float lat) { - _latitude = validateLatitude(lat); - invalidate(); -} -void EarthSunModel::setLongitude(float lon) { - _longitude = validateLongitude(lon); - invalidate(); -} -void EarthSunModel::setAltitude(float altitude) { - _altitude = validateAltitude(altitude); - invalidate(); -} - -void EarthSunModel::setSunLatitude(float lat) { - _sunLatitude = validateLatitude(lat); - invalidate(); -} -void EarthSunModel::setSunLongitude(float lon) { - _sunLongitude = validateLongitude(lon); - invalidate(); -} - -const int NUM_DAYS_PER_YEAR = 365; -const float NUM_HOURS_PER_DAY = 24.0f; -const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f; - -SunSkyStage::SunSkyStage() : - _sunLight(new Light()) -{ - _sunLight->setType(Light::SUN); - - setSunIntensity(1.0f); - setSunColor(Vec3(1.0f, 1.0f, 1.0f)); - - // Default origin location is a special place in the world... - setOriginLocation(122.407f, 37.777f, 0.03f); - // 6pm - setDayTime(18.0f); - // Begining of march - setYearTime(60.0f); -} - -SunSkyStage::~SunSkyStage() { -} - -void SunSkyStage::setDayTime(float hour) { - _dayTime = moduloRange(hour, 0.f, NUM_HOURS_PER_DAY); - invalidate(); -} - -void SunSkyStage::setYearTime(unsigned int day) { - _yearTime = day % NUM_DAYS_PER_YEAR; - invalidate(); -} - -void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { - _earthSunModel.setLongitude(longitude); - _earthSunModel.setLatitude(latitude); - _earthSunModel.setAltitude(altitude); - invalidate(); -} - -void SunSkyStage::setSunColor(const Vec3& color) { - _sunLight->setColor(color); -} -void SunSkyStage::setSunIntensity(float intensity) { - _sunLight->setIntensity(intensity); -} - -// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun -double evalSunDeclinaison(double dayNumber) { - return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); -} - -void SunSkyStage::updateGraphicsObject() const { - // Always update the sunLongitude based on the current dayTime and the current origin - // The day time is supposed to be local at the origin - double signedNormalizedDayTime = (_dayTime - NUM_HOURS_PER_HALF_DAY) / NUM_HOURS_PER_HALF_DAY; - double sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); - _earthSunModel.setSunLongitude(sunLongitude); - - // And update the sunLAtitude as the declinaison depending of the time of the year - _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); - - Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); - - _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); -} - +} + +double moduloRange(double val, double minVal, double maxVal) { + double range = maxVal - minVal; + double rval = (val - minVal) / range; + double intval; + return modf(rval, &intval) * range + minVal; +} + +const float MAX_LONGITUDE = 180.0f; +const float MAX_LATITUDE = 90.0f; + +float validateLongitude(float lon) { + return moduloRange(lon, -MAX_LONGITUDE, MAX_LONGITUDE); +} + +float validateLatitude(float lat) { + return moduloRange(lat, -MAX_LATITUDE, MAX_LATITUDE); +} + +float validateAltitude(float altitude) { + const float MIN_ALTITUDE = -1000.0f; + const float MAX_ALTITUDE = 100000.0f; + return std::min(std::max(altitude, MIN_ALTITUDE), MAX_ALTITUDE); +} + +void EarthSunModel::setLatitude(float lat) { + _latitude = validateLatitude(lat); + invalidate(); +} +void EarthSunModel::setLongitude(float lon) { + _longitude = validateLongitude(lon); + invalidate(); +} +void EarthSunModel::setAltitude(float altitude) { + _altitude = validateAltitude(altitude); + invalidate(); +} + +void EarthSunModel::setSunLatitude(float lat) { + _sunLatitude = validateLatitude(lat); + invalidate(); +} +void EarthSunModel::setSunLongitude(float lon) { + _sunLongitude = validateLongitude(lon); + invalidate(); +} + +const int NUM_DAYS_PER_YEAR = 365; +const float NUM_HOURS_PER_DAY = 24.0f; +const float NUM_HOURS_PER_HALF_DAY = NUM_HOURS_PER_DAY * 0.5f; + +SunSkyStage::SunSkyStage() : + _sunLight(new Light()) +{ + _sunLight->setType(Light::SUN); + + setSunIntensity(1.0f); + setSunColor(Vec3(1.0f, 1.0f, 1.0f)); + + // Default origin location is a special place in the world... + setOriginLocation(122.407f, 37.777f, 0.03f); + // 6pm + setDayTime(18.0f); + // Begining of march + setYearTime(60.0f); +} + +SunSkyStage::~SunSkyStage() { +} + +void SunSkyStage::setDayTime(float hour) { + _dayTime = moduloRange(hour, 0.f, NUM_HOURS_PER_DAY); + invalidate(); +} + +void SunSkyStage::setYearTime(unsigned int day) { + _yearTime = day % NUM_DAYS_PER_YEAR; + invalidate(); +} + +void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { + _earthSunModel.setLongitude(longitude); + _earthSunModel.setLatitude(latitude); + _earthSunModel.setAltitude(altitude); + invalidate(); +} + +void SunSkyStage::setSunColor(const Vec3& color) { + _sunLight->setColor(color); +} +void SunSkyStage::setSunIntensity(float intensity) { + _sunLight->setIntensity(intensity); +} + +// THe sun declinaison calculus is taken from https://en.wikipedia.org/wiki/Position_of_the_Sun +double evalSunDeclinaison(double dayNumber) { + return -(23.0 + 44.0/60.0)*cos(glm::radians((360.0/365.0)*(dayNumber + 10.0))); +} + +void SunSkyStage::updateGraphicsObject() const { + // Always update the sunLongitude based on the current dayTime and the current origin + // The day time is supposed to be local at the origin + double signedNormalizedDayTime = (_dayTime - NUM_HOURS_PER_HALF_DAY) / NUM_HOURS_PER_HALF_DAY; + double sunLongitude = _earthSunModel.getLongitude() + (MAX_LONGITUDE * signedNormalizedDayTime); + _earthSunModel.setSunLongitude(sunLongitude); + + // And update the sunLAtitude as the declinaison depending of the time of the year + _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); + + Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); + + _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); +} + From bc8d688cdea8dab4871523a66c6a123198b6ecc2 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 12:04:33 -0800 Subject: [PATCH 06/11] fixing tab maybe --- examples/example/misc/sunLightExample.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 7f38211052..bc00a39246 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -11,21 +11,21 @@ var intensity = 1.0; var day = 0.0; var hour = 12.0; -var longitude = 0.0; -var latitude = -45.0; +var longitude = -115.0; +var latitude = -31.0; Scene.setDayTime(hour); -Scene.setOriginLocation(longitude, latitude, 0.0); +//Scene.setOriginLocation(longitude, latitude, 0.0); function ticktack() { hour += 0.1; - //Scene.setSunIntensity(Math.cos(time)); - if (hour > 24.0) { - hour = 0.0; - day++; - Scene.setYearTime(day); - } - Scene.setDayTime(hour); + //Scene.setSunIntensity(Math.cos(time)); + if (hour > 24.0) { + hour = 0.0; + day++; + Scene.setYearTime(day); + } + Scene.setDayTime(hour); } Script.setInterval(ticktack, 41); From 96d5a2ab4221e214d364e4437374a5059454209f Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 12:10:08 -0800 Subject: [PATCH 07/11] fixing tab maybe --- examples/example/misc/sunLightExample.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index bc00a39246..47fbb9761e 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -18,7 +18,7 @@ Scene.setDayTime(hour); //Scene.setOriginLocation(longitude, latitude, 0.0); function ticktack() { - hour += 0.1; + hour += 0.1; //Scene.setSunIntensity(Math.cos(time)); if (hour > 24.0) { hour = 0.0; From e3b3c8e1ef8f23324f188efd7f01ad5f9e3b34f5 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 16:09:21 -0800 Subject: [PATCH 08/11] Setting the defalt at a better time of the day --- libraries/model/src/model/Stage.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index dd5a44a0cb..8befec2ed3 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -136,8 +136,8 @@ SunSkyStage::SunSkyStage() : // Default origin location is a special place in the world... setOriginLocation(122.407f, 37.777f, 0.03f); - // 6pm - setDayTime(18.0f); + // Noun + setDayTime(12.0f); // Begining of march setYearTime(60.0f); } @@ -185,7 +185,10 @@ void SunSkyStage::updateGraphicsObject() const { _earthSunModel.setSunLatitude(evalSunDeclinaison(_yearTime)); Vec3d sunLightDir = -_earthSunModel.getSurfaceSunDir(); - _sunLight->setDirection(Vec3(sunLightDir.x, sunLightDir.y, sunLightDir.z)); + + double originAlt = _earthSunModel.getAltitude(); + _sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f)); + } From f6a9bd187090049e807c8ff51e32d3d5647ea276 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 17:26:41 -0800 Subject: [PATCH 09/11] REfining the naming and introducing an orientation offset --- examples/example/misc/sunLightExample.js | 10 ++++++---- libraries/model/src/model/Stage.cpp | 15 ++++++++++++++ libraries/model/src/model/Stage.h | 12 +++++++++++ .../src/SceneScriptingInterface.cpp | 20 +++++++++++-------- .../src/SceneScriptingInterface.h | 8 ++++---- 5 files changed, 49 insertions(+), 16 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 47fbb9761e..9c58d0bac3 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -13,9 +13,11 @@ var day = 0.0; var hour = 12.0; var longitude = -115.0; var latitude = -31.0; +var stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 180.0, 0.0); -Scene.setDayTime(hour); -//Scene.setOriginLocation(longitude, latitude, 0.0); +Scene.setStageDayTime(hour); +Scene.setStageOrientation(stageOrientation); +Scene.setStageLocation(longitude, latitude, 0.0); function ticktack() { hour += 0.1; @@ -23,9 +25,9 @@ function ticktack() { if (hour > 24.0) { hour = 0.0; day++; - Scene.setYearTime(day); + Scene.setStageYearTime(day); } - Scene.setDayTime(hour); + Scene.setStageDayTime(hour); } Script.setInterval(ticktack, 41); diff --git a/libraries/model/src/model/Stage.cpp b/libraries/model/src/model/Stage.cpp index 8befec2ed3..d867056e8a 100644 --- a/libraries/model/src/model/Stage.cpp +++ b/libraries/model/src/model/Stage.cpp @@ -73,9 +73,19 @@ void EarthSunModel::updateSun() const { // sun direction is looking up toward Y axis at the specified sun lat, long Vec3d lssd = Vec3d(_worldToSurfaceMat * Vec4d(_sunDir.x, _sunDir.y, _sunDir.z, 0.0)); + + // apply surface rotation offset + glm::dquat dSurfOrient(_surfaceOrientation); + lssd = glm::rotate(dSurfOrient, lssd); + _surfaceSunDir = glm::normalize(Vec3(lssd.x, lssd.y, lssd.z)); } +void EarthSunModel::setSurfaceOrientation(const Quat& orientation) { + _surfaceOrientation = orientation; + invalidate(); +} + double moduloRange(double val, double minVal, double maxVal) { double range = maxVal - minVal; double rval = (val - minVal) / range; @@ -155,6 +165,11 @@ void SunSkyStage::setYearTime(unsigned int day) { invalidate(); } +void SunSkyStage::setOriginOrientation(const Quat& orientation) { + _earthSunModel.setSurfaceOrientation(orientation); + invalidate(); +} + void SunSkyStage::setOriginLocation(float longitude, float latitude, float altitude) { _earthSunModel.setLongitude(longitude); _earthSunModel.setLatitude(latitude); diff --git a/libraries/model/src/model/Stage.h b/libraries/model/src/model/Stage.h index f99d2c1648..762e2d9717 100644 --- a/libraries/model/src/model/Stage.h +++ b/libraries/model/src/model/Stage.h @@ -33,6 +33,10 @@ public: void setAltitude(float altitude); float getAltitude() const { return _altitude; } + + void setSurfaceOrientation(const Quat& orientation); + const Quat& getSurfaceOrientation() const { valid(); return _surfaceOrientation; } + const Vec3d& getSurfacePos() const { valid(); return _surfacePos; } const Mat4d& getSurfaceToWorldMat() const { valid(); return _surfaceToWorldMat; } @@ -67,6 +71,8 @@ protected: double _scale = 1000.0; //Km double _earthRadius = 6360.0; + Quat _surfaceOrientation; + double _longitude = 0.0; double _latitude = 0.0; double _altitude = 0.01; @@ -114,6 +120,12 @@ public: void setYearTime(unsigned int day); unsigned int getYearTime() const { return _yearTime; } + // Origin orientation used to modify the cardinal axis alignement used. + // THe default is north along +Z axis and west along +X axis. this orientation gets added + // to the transform stack producing the sun light direction. + void setOriginOrientation(const Quat& orientation); + const Quat& getOriginOrientation() const { return _earthSunModel.getSurfaceOrientation(); } + // Location used to define the sun & sky is a longitude and latitude [rad] and a earth surface altitude [km] void setOriginLocation(float longitude, float latitude, float surfaceAltitude); float getOriginLatitude() const { return _earthSunModel.getLatitude(); } diff --git a/libraries/script-engine/src/SceneScriptingInterface.cpp b/libraries/script-engine/src/SceneScriptingInterface.cpp index ff255a3e5e..9cac521225 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.cpp +++ b/libraries/script-engine/src/SceneScriptingInterface.cpp @@ -13,10 +13,20 @@ #include "SceneScriptingInterface.h" - Q_INVOKABLE void setOriginGeoLocation(float longitude, float latitude, float altitude); -void SceneScriptingInterface::setOriginLocation(float longitude, float latitude, float altitude) { +void SceneScriptingInterface::setStageOrientation(const glm::quat& orientation) { + _skyStage->setOriginOrientation(orientation); +} +void SceneScriptingInterface::setStageLocation(float longitude, float latitude, float altitude) { _skyStage->setOriginLocation(longitude, latitude, altitude); } + +void SceneScriptingInterface::setStageDayTime(float hour) { + _skyStage->setDayTime(hour); +} +void SceneScriptingInterface::setStageYearTime(int day) { + _skyStage->setYearTime(day); +} + void SceneScriptingInterface::setSunColor(const glm::vec3& color) { _skyStage->setSunColor(color); } @@ -24,12 +34,6 @@ void SceneScriptingInterface::setSunIntensity(float intensity) { _skyStage->setSunIntensity(intensity); } -void SceneScriptingInterface::setDayTime(float hour) { - _skyStage->setDayTime(hour); -} -void SceneScriptingInterface::setYearTime(int day) { - _skyStage->setYearTime(day); -} model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const { return _skyStage; diff --git a/libraries/script-engine/src/SceneScriptingInterface.h b/libraries/script-engine/src/SceneScriptingInterface.h index 3fc909f9a0..8ae9424c95 100644 --- a/libraries/script-engine/src/SceneScriptingInterface.h +++ b/libraries/script-engine/src/SceneScriptingInterface.h @@ -23,14 +23,14 @@ class SceneScriptingInterface : public QObject, public Dependency { SINGLETON_DEPENDENCY public: - Q_INVOKABLE void setOriginLocation(float longitude, float latitude, float altitude); + Q_INVOKABLE void setStageOrientation(const glm::quat& orientation); + Q_INVOKABLE void setStageLocation(float longitude, float latitude, float altitude); + Q_INVOKABLE void setStageDayTime(float hour); + Q_INVOKABLE void setStageYearTime(int day); Q_INVOKABLE void setSunColor(const glm::vec3& color); Q_INVOKABLE void setSunIntensity(float intensity); - Q_INVOKABLE void setDayTime(float hour); - Q_INVOKABLE void setYearTime(int day); - model::SunSkyStagePointer getSkyStage() const; protected: From 74f0d98fd6ff65ae26dfda6374edc03c2a1d5ec9 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 17:44:04 -0800 Subject: [PATCH 10/11] REfining the naming and introducing an orientation offset --- examples/example/misc/sunLightExample.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 9c58d0bac3..93fc06d088 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -11,8 +11,8 @@ var intensity = 1.0; var day = 0.0; var hour = 12.0; -var longitude = -115.0; -var latitude = -31.0; +var longitude = 115.0; +var latitude = 31.0; var stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 180.0, 0.0); Scene.setStageDayTime(hour); From c7eeebe52cc4b030a6bd6f3436497b4ee8047426 Mon Sep 17 00:00:00 2001 From: Sam Gateau Date: Thu, 26 Feb 2015 18:07:43 -0800 Subject: [PATCH 11/11] and fixing a bug with shadowing of lightmapped surface --- examples/example/misc/sunLightExample.js | 3 ++- libraries/render-utils/src/DeferredGlobalLight.slh | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/examples/example/misc/sunLightExample.js b/examples/example/misc/sunLightExample.js index 93fc06d088..42837c6836 100644 --- a/examples/example/misc/sunLightExample.js +++ b/examples/example/misc/sunLightExample.js @@ -18,7 +18,7 @@ var stageOrientation = Quat.fromPitchYawRollDegrees(0.0, 180.0, 0.0); Scene.setStageDayTime(hour); Scene.setStageOrientation(stageOrientation); Scene.setStageLocation(longitude, latitude, 0.0); - +/* function ticktack() { hour += 0.1; //Scene.setSunIntensity(Math.cos(time)); @@ -31,3 +31,4 @@ function ticktack() { } Script.setInterval(ticktack, 41); +*/ \ No newline at end of file diff --git a/libraries/render-utils/src/DeferredGlobalLight.slh b/libraries/render-utils/src/DeferredGlobalLight.slh index 6868b96c24..0fe2d18e74 100755 --- a/libraries/render-utils/src/DeferredGlobalLight.slh +++ b/libraries/render-utils/src/DeferredGlobalLight.slh @@ -95,7 +95,8 @@ vec3 evalAmbienSphereGlobalColor(float shadowAttenuation, vec3 position, vec3 no vec3 evalLightmappedColor(float shadowAttenuation, vec3 normal, vec3 diffuse, vec3 lightmap) { Light light = getLight(); - float diffuseDot = dot(normal, getLightDirection(light)); + vec3 fragNormal = vec3(invViewMat * vec4(normal, 0.0)); + float diffuseDot = dot(fragNormal, -getLightDirection(light)); // need to catch normals perpendicular to the projection plane hence the magic number for the threshold // it should be just 0, but we have innacurracy so we need to overshoot