Merge branch 'master' of github.com:highfidelity/hifi into update-light-entity-properties

Conflicts:
	libraries/entities-renderer/src/RenderableLightEntityItem.cpp
This commit is contained in:
Ryan Huffman 2015-02-27 12:20:10 -08:00
commit 5c9473cd24
30 changed files with 767 additions and 324 deletions

View file

@ -32,6 +32,7 @@
#include <SharedUtil.h>
#include <ShutdownEventListener.h>
#include <UUID.h>
#include <LogHandler.h>
#include "DomainServerNodeData.h"
@ -943,8 +944,10 @@ void DomainServer::readAvailableDatagrams() {
if (requestAssignment.getType() != Assignment::AgentType
|| noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) {
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex
("Received a request for assignment type [^ ]+ from [^ ]+");
qDebug() << "Received a request for assignment type" << requestAssignment.getType()
<< "from" << senderSockAddr;
<< "from" << senderSockAddr;
noisyMessageTimer.restart();
}
@ -974,6 +977,8 @@ void DomainServer::readAvailableDatagrams() {
} else {
if (requestAssignment.getType() != Assignment::AgentType
|| noisyMessageTimer.elapsed() > NOISY_MESSAGE_INTERVAL_MSECS) {
static QString repeatedMessage = LogHandler::getInstance().addRepeatedMessageRegex
("Unable to fulfill assignment request of type [^ ]+ from [^ ]+");
qDebug() << "Unable to fulfill assignment request of type" << requestAssignment.getType()
<< "from" << senderSockAddr;
noisyMessageTimer.restart();

View file

@ -934,24 +934,37 @@ PropertiesTool = function(opts) {
data = {
type: 'update',
};
if (selectionManager.hasSelection()) {
data.id = selectionManager.selections[0].id;
data.properties = Entities.getEntityProperties(selectionManager.selections[0]);
data.properties.rotation = Quat.safeEulerAngles(data.properties.rotation);
var selections = [];
for (var i = 0; i < selectionManager.selections.length; i++) {
var entity = {};
entity.id = selectionManager.selections[i].id;
entity.properties = Entities.getEntityProperties(selectionManager.selections[i]);
entity.properties.rotation = Quat.safeEulerAngles(entity.properties.rotation);
selections.push(entity);
}
data.selections = selections;
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
});
webView.eventBridge.webEventReceived.connect(function(data) {
print(data);
data = JSON.parse(data);
if (data.type == "update") {
selectionManager.saveProperties();
if (data.properties.rotation !== undefined) {
var rotation = data.properties.rotation;
data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z);
if (selectionManager.selections.length > 1) {
properties = {
locked: data.properties.locked,
visible: data.properties.visible,
};
for (var i = 0; i < selectionManager.selections.length; i++) {
Entities.editEntity(selectionManager.selections[i], properties);
}
} else {
if (data.properties.rotation !== undefined) {
var rotation = data.properties.rotation;
data.properties.rotation = Quat.fromPitchYawRollDegrees(rotation.x, rotation.y, rotation.z);
}
Entities.editEntity(selectionManager.selections[0], data.properties);
}
Entities.editEntity(selectionManager.selections[0], data.properties);
pushCommandForSelections();
selectionManager._update();
} else if (data.type == "action") {

View file

@ -0,0 +1,34 @@
//
// 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 = 115.0;
var latitude = 31.0;
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));
if (hour > 24.0) {
hour = 0.0;
day++;
Scene.setStageYearTime(day);
}
Scene.setStageDayTime(hour);
}
Script.setInterval(ticktack, 41);
*/

View file

@ -20,6 +20,7 @@
elRefresh = document.getElementById("refresh");
elDelete = document.getElementById("delete");
elTeleport = document.getElementById("teleport");
elNoEntitiesMessage = document.getElementById("no-entities");
document.getElementById("entity-type").onclick = function() {
setSortColumn('type');
@ -155,11 +156,18 @@
}
} else if (data.type == "update") {
var newEntities = data.entities;
for (var i = 0; i < newEntities.length; i++) {
var id = newEntities[i].id;
addEntity(id, newEntities[i].type, newEntities[i].url);
if (newEntities.length == 0) {
elEntityTable.style.display = "none";
elNoEntitiesMessage.style.display = "block";
} else {
elEntityTable.style.display = "table";
elNoEntitiesMessage.style.display = "none";
for (var i = 0; i < newEntities.length; i++) {
var id = newEntities[i].id;
addEntity(id, newEntities[i].type, newEntities[i].url);
}
updateSelectedEntities(data.selectedIDs);
}
updateSelectedEntities(data.selectedIDs);
}
});
setTimeout(refreshEntities, 1000);
@ -194,6 +202,8 @@
</tbody>
</table>
</div>
<div id="no-entities">
No entities found within 50 meter radius. Try moving to a different location and refreshing.
</div>
</body>
</html>

View file

@ -132,17 +132,7 @@
var elLightDiffuseGreen = document.getElementById("property-light-diffuse-green");
var elLightDiffuseBlue = document.getElementById("property-light-diffuse-blue");
var elLightAmbientRed = document.getElementById("property-light-ambient-red");
var elLightAmbientGreen = document.getElementById("property-light-ambient-green");
var elLightAmbientBlue = document.getElementById("property-light-ambient-blue");
var elLightSpecularRed = document.getElementById("property-light-specular-red");
var elLightSpecularGreen = document.getElementById("property-light-specular-green");
var elLightSpecularBlue = document.getElementById("property-light-specular-blue");
var elLightConstantAttenuation = document.getElementById("property-light-constant-attenuation");
var elLightLinearAttenuation = document.getElementById("property-light-linear-attenuation");
var elLightQuadraticAttenuation = document.getElementById("property-light-quadratic-attenuation");
var elLightExponent = document.getElementById("property-light-exponent");
var elLightCutoff = document.getElementById("property-light-cutoff");
@ -171,12 +161,37 @@
EventBridge.scriptEventReceived.connect(function(data) {
data = JSON.parse(data);
if (data.type == "update") {
if (data.properties === undefined) {
disableChildren(document.getElementById("properties"), 'input');
} else {
var properties = data.properties;
if (data.selections.length == 0) {
elType.innerHTML = "<i>No Selection</i>";
elID.innerHTML = "";
disableChildren(document.getElementById("properties-list"), 'input');
} else if (data.selections.length > 1) {
var selections = data.selections;
elID.innerHTML = data.id;
var ids = [];
var types = {};
for (var i = 0; i < selections.length; i++) {
ids.push(selections[i].id);
var type = selections[i].properties.type;
if (types[type] === undefined) {
types[type] = 0;
}
types[type]++;
}
elID.innerHTML = ids.join("<br>");
var typeStrs = [];
for (type in types) {
typeStrs.push(type + " (" + types[type] + ")");
}
elType.innerHTML = typeStrs.join(", ");
disableChildren(document.getElementById("properties-list"), 'input');
} else {
var properties = data.selections[0].properties;
elID.innerHTML = properties.id;
elType.innerHTML = properties.type;
@ -294,17 +309,7 @@
elLightDiffuseGreen.value = properties.diffuseColor.green;
elLightDiffuseBlue.value = properties.diffuseColor.blue;
elLightAmbientRed.value = properties.ambientColor.red;
elLightAmbientGreen.value = properties.ambientColor.green;
elLightAmbientBlue.value = properties.ambientColor.blue;
elLightSpecularRed.value = properties.specularColor.red;
elLightSpecularGreen.value = properties.specularColor.green;
elLightSpecularBlue.value = properties.specularColor.blue;
elLightConstantAttenuation.value = properties.constantAttenuation;
elLightLinearAttenuation.value = properties.linearAttenuation;
elLightQuadraticAttenuation.value = properties.quadraticAttenuation;
elLightExponent.value = properties.exponent;
elLightCutoff.value = properties.cutoff;
}
@ -381,21 +386,7 @@
elLightDiffuseGreen.addEventListener('change', lightDiffuseChangeFunction);
elLightDiffuseBlue.addEventListener('change', lightDiffuseChangeFunction);
var lightAmbientChangeFunction = createEmitColorPropertyUpdateFunction(
'ambientColor', elLightAmbientRed, elLightAmbientGreen, elLightAmbientBlue);
elLightAmbientRed.addEventListener('change', lightAmbientChangeFunction);
elLightAmbientGreen.addEventListener('change', lightAmbientChangeFunction);
elLightAmbientBlue.addEventListener('change', lightAmbientChangeFunction);
var lightSpecularChangeFunction = createEmitColorPropertyUpdateFunction(
'specularColor', elLightSpecularRed, elLightSpecularGreen, elLightSpecularBlue);
elLightSpecularRed.addEventListener('change', lightSpecularChangeFunction);
elLightSpecularGreen.addEventListener('change', lightSpecularChangeFunction);
elLightSpecularBlue.addEventListener('change', lightSpecularChangeFunction);
elLightConstantAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('constantAttenuation'));
elLightLinearAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('linearAttenuation'));
elLightQuadraticAttenuation.addEventListener('change', createEmitNumberPropertyUpdateFunction('quadraticAttenuation'));
elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent'));
elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff'));
@ -715,7 +706,7 @@
</div>
</div>
<div class="light-section property">
<div class="label">Diffuse</div>
<div class="label">Color</div>
<div class="value">
<div class="input-area">R <input class="coord" type='number' id="property-light-diffuse-red"></input></div>
<div class="input-area">G <input class="coord" type='number' id="property-light-diffuse-green"></input></div>
@ -723,47 +714,19 @@
</div>
</div>
<div class="light-section property">
<div class="label">Ambient</div>
<div class="value">
<div class="input-area">R <input class="coord" type='number' id="property-light-ambient-red"></input></div>
<div class="input-area">G <input class="coord" type='number' id="property-light-ambient-green"></input></div>
<div class="input-area">B <input class="coord" type='number' id="property-light-ambient-blue"></input></div>
</div>
</div>
<div class="light-section property">
<div class="label">Specular</div>
<div class="value">
<div class="input-area">R <input class="coord" type='number' id="property-light-specular-red"></input></div>
<div class="input-area">G <input class="coord" type='number' id="property-light-specular-green"></input></div>
<div class="input-area">B <input class="coord" type='number' id="property-light-specular-blue"></input></div>
</div>
</div>
<div class="light-section property">
<div class="label">Constant Attenuation</div>
<div class="label">Intensity</div>
<div class="value">
<input class="coord" type='number' id="property-light-constant-attenuation"></input>
</div>
</div>
<div class="light-section property">
<div class="label">Linear Attenuation</div>
<div class="value">
<input class="coord" type='number' id="property-light-linear-attenuation"></input>
</div>
</div>
<div class="light-section property">
<div class="label">Quadratic Attenuation</div>
<div class="value">
<input class="coord" type='number' id="property-light-quadratic-attenuation"></input>
</div>
</div>
<div class="light-section property">
<div class="label">Exponent</div>
<div class="label">Spot Light Exponent</div>
<div class="value">
<input class="coord" type='number' id="property-light-exponent"></input>
</div>
</div>
<div class="light-section property">
<div class="label">Cutoff (degrees)</div>
<div class="label">Spot Light Cutoff (degrees)</div>
<div class="value">
<input class="coord" type='number' id="property-light-cutoff"></input>
</div>

View file

@ -189,6 +189,11 @@ input, textarea {
font-size: 7.5pt;
}
input:disabled, textarea:disabled {
background-color: rgb(102, 102, 102);
color: rgb(160, 160, 160);
}
#properties-list input[type=button] {
cursor: pointer;
background-color: rgb(51, 102, 102);
@ -199,6 +204,11 @@ input, textarea {
color: rgb(204, 204, 204);
}
#properties-list input[type=button]:disabled {
background-color: rgb(41, 82, 82);
color: rgb(160, 160, 160);
}
#properties-list .property {
padding: 6pt 6pt;
border-top: 0.75pt solid rgb(63, 63, 63);
@ -257,3 +267,11 @@ td {
vertical-align: top;
}
#no-entities {
display: none;
font-size: 120%;
padding: 10pt;
font-weight: bold;
font-style: italic;
}

View file

@ -82,6 +82,8 @@
#include <UserActivityLogger.h>
#include <UUID.h>
#include <SceneScriptingInterface.h>
#include "Application.h"
#include "AudioClient.h"
#include "InterfaceVersion.h"
@ -1859,35 +1861,6 @@ void Application::updateMouseRay() {
}
}
void Application::updateFaceshift() {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateFaceshift()");
auto faceshift = DependencyManager::get<Faceshift>();
// Update faceshift
faceshift->update();
// Copy angular velocity if measured by faceshift, to the head
if (faceshift->isActive()) {
_myAvatar->getHead()->setAngularVelocity(faceshift->getHeadAngularVelocity());
}
}
void Application::updateVisage() {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateVisage()");
// Update Visage
DependencyManager::get<Visage>()->update();
}
void Application::updateDDE() {
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
PerformanceWarning warn(showWarnings, "Application::updateDDE()");
// Update Cara
DependencyManager::get<DdeFaceTracker>()->update();
}
void Application::updateMyAvatarLookAtPosition() {
PerformanceTimer perfTimer("lookAt");
bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings);
@ -2067,12 +2040,13 @@ void Application::update(float deltaTime) {
{
PerformanceTimer perfTimer("devices");
DeviceTracker::updateAll();
updateFaceshift();
updateVisage();
FaceTracker* tracker = getActiveFaceTracker();
if (tracker) {
tracker->update(deltaTime);
}
SixenseManager::getInstance().update(deltaTime);
JoystickScriptingInterface::getInstance().update();
_prioVR.update(deltaTime);
}
// Dispatch input events
@ -2491,7 +2465,8 @@ 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<SceneScriptingInterface>()->getSkyStage();
return skyStage->getSunLight()->getDirection();
}
void Application::updateShadowMap() {
@ -2501,7 +2476,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);
@ -2870,7 +2845,9 @@ void Application::displaySide(Camera& theCamera, bool selfAvatarOnly, RenderArgs
{
DependencyManager::get<DeferredLightingEffect>()->setAmbientLightMode(getRenderAmbientLight());
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(-getSunDirection(), GLOBAL_LIGHT_COLOR, GLOBAL_LIGHT_INTENSITY);
auto skyStage = DependencyManager::get<SceneScriptingInterface>()->getSkyStage();
DependencyManager::get<DeferredLightingEffect>()->setGlobalLight(skyStage->getSunLight()->getDirection(), skyStage->getSunLight()->getColor(), skyStage->getSunLight()->getIntensity());
PROFILE_RANGE("DeferredLighting");
PerformanceTimer perfTimer("lighting");
DependencyManager::get<DeferredLightingEffect>()->render();

View file

@ -421,9 +421,6 @@ private:
// Various helper functions called during update()
void updateLOD();
void updateMouseRay();
void updateFaceshift();
void updateVisage();
void updateDDE();
void updateMyAvatarLookAtPosition();
void updateThreads(float deltaTime);
void updateMetavoxels(float deltaTime);

View file

@ -380,8 +380,7 @@ void Avatar::render(const glm::vec3& cameraPosition, RenderMode renderMode, bool
foreach (const AvatarManager::LocalLight& light, DependencyManager::get<AvatarManager>()->getLocalLights()) {
glm::vec3 direction = orientation * light.direction;
DependencyManager::get<DeferredLightingEffect>()->addSpotLight(position - direction * distance,
distance * 2.0f, glm::vec3(), light.color, light.color, 1.0f, 0.5f, 0.0f, direction,
LIGHT_EXPONENT, LIGHT_CUTOFF);
distance * 2.0f, light.color, 0.5f, orientation, LIGHT_EXPONENT, LIGHT_CUTOFF);
}
}

View file

@ -42,7 +42,6 @@ Head::Head(Avatar* owningAvatar) :
_mouth2(0.0f),
_mouth3(0.0f),
_mouth4(0.0f),
_angularVelocity(0,0,0),
_renderLookatVectors(false),
_saccade(0.0f, 0.0f, 0.0f),
_saccadeTarget(0.0f, 0.0f, 0.0f),

View file

@ -55,9 +55,6 @@ public:
/// \return orientationBody * orientationBasePitch
glm::quat getCameraOrientation () const;
const glm::vec3& getAngularVelocity() const { return _angularVelocity; }
void setAngularVelocity(glm::vec3 angularVelocity) { _angularVelocity = angularVelocity; }
void setCorrectedLookAtPosition(glm::vec3 correctedLookAtPosition);
glm::vec3 getCorrectedLookAtPosition();
@ -130,7 +127,6 @@ private:
float _mouth2;
float _mouth3;
float _mouth4;
glm::vec3 _angularVelocity;
bool _renderLookatVectors;
glm::vec3 _saccade;
glm::vec3 _saccadeTarget;

View file

@ -892,13 +892,7 @@ void MyAvatar::updateLookAtTargetAvatar() {
_lookAtTargetAvatar.clear();
_targetAvatarPosition = glm::vec3(0.0f);
glm::quat faceRotation = Application::getInstance()->getViewFrustum()->getOrientation();
FaceTracker* tracker = Application::getInstance()->getActiveFaceTracker();
if (tracker) {
// If faceshift or other face tracker in use, add on the actual angle of the head
faceRotation *= tracker->getHeadRotation();
}
glm::vec3 lookForward = faceRotation * IDENTITY_FRONT;
glm::vec3 lookForward = getHead()->getFinalOrientationInWorldFrame() * IDENTITY_FRONT;
glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
float smallestAngleTo = glm::radians(Application::getInstance()->getCamera()->getFieldOfView()) / 2.0f;
@ -1164,15 +1158,8 @@ void MyAvatar::updateOrientation(float deltaTime) {
pitch *= DEGREES_PER_RADIAN;
roll *= DEGREES_PER_RADIAN;
// Record the angular velocity
Head* head = getHead();
if (deltaTime > 0.0f) {
glm::vec3 angularVelocity(pitch - head->getBasePitch(), yaw - head->getBaseYaw(), roll - head->getBaseRoll());
angularVelocity *= 1.0f / deltaTime;
head->setAngularVelocity(angularVelocity);
}
//Invert yaw and roll when in mirror mode
Head* head = getHead();
if (Application::getInstance()->getCamera()->getMode() == CAMERA_MODE_MIRROR) {
head->setBaseYaw(-yaw);
head->setBasePitch(pitch);

View file

@ -50,6 +50,8 @@ DdeFaceTracker::DdeFaceTracker() :
}
DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
_host(host),
_port(port),
_lastReceiveTimestamp(0),
_reset(false),
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
@ -63,9 +65,7 @@ DdeFaceTracker::DdeFaceTracker(const QHostAddress& host, quint16 port) :
_browUpRightIndex(18),
_mouthSmileLeftIndex(28),
_mouthSmileRightIndex(29),
_jawOpenIndex(21),
_host(host),
_port(port)
_jawOpenIndex(21)
{
_blendshapeCoefficients.resize(NUM_EXPRESSION);
@ -80,18 +80,6 @@ DdeFaceTracker::~DdeFaceTracker() {
}
}
void DdeFaceTracker::init() {
}
void DdeFaceTracker::reset() {
_reset = true;
}
void DdeFaceTracker::update() {
}
void DdeFaceTracker::setEnabled(bool enabled) {
// isOpen() does not work as one might expect on QUdpSocket; don't test isOpen() before closing socket.
_udpSocket.close();

View file

@ -23,12 +23,10 @@ class DdeFaceTracker : public FaceTracker, public Dependency {
SINGLETON_DEPENDENCY
public:
//initialization
void init();
void reset();
void update();
bool isActive() const;
virtual void reset() { _reset = true; }
virtual bool isActive() const;
virtual bool isTracking() const { return isActive(); }
float getLeftBlink() const { return getBlendshapeCoefficient(_leftBlinkIndex); }
float getRightBlink() const { return getBlendshapeCoefficient(_rightBlinkIndex); }

View file

@ -11,7 +11,41 @@
#include "FaceTracker.h"
FaceTracker::FaceTracker() :
_estimatedEyePitch(0.0f),
_estimatedEyeYaw(0.0f) {
inline float FaceTracker::getBlendshapeCoefficient(int index) const {
return isValidBlendshapeIndex(index) ? _blendshapeCoefficients[index] : 0.0f;
}
float FaceTracker::getFadeCoefficient() const {
return _fadeCoefficient;
}
const glm::vec3 FaceTracker::getHeadTranslation() const {
return glm::mix(glm::vec3(0.0f), _headTranslation, getFadeCoefficient());
}
const glm::quat FaceTracker::getHeadRotation() const {
return glm::mix(glm::quat(), _headRotation, getFadeCoefficient());
}
void FaceTracker::update(float deltaTime) {
// Based on exponential distributions: http://en.wikipedia.org/wiki/Exponential_distribution
static const float EPSILON = 0.02f; // MUST BE < 1.0f
static const float INVERSE_AT_EPSILON = -std::log(EPSILON); // So that f(1.0f) = EPSILON ~ 0.0f
static const float RELAXATION_TIME = 0.8f; // sec
if (isTracking()) {
if (_relaxationStatus == 1.0f) {
_fadeCoefficient = 1.0f;
return;
}
_relaxationStatus = glm::clamp(_relaxationStatus + deltaTime / RELAXATION_TIME, 0.0f, 1.0f);
_fadeCoefficient = 1.0f - std::exp(-_relaxationStatus * INVERSE_AT_EPSILON);
} else {
if (_relaxationStatus == 0.0f) {
_fadeCoefficient = 0.0f;
return;
}
_relaxationStatus = glm::clamp(_relaxationStatus - deltaTime / RELAXATION_TIME, 0.0f, 1.0f);
_fadeCoefficient = std::exp(-(1.0f - _relaxationStatus) * INVERSE_AT_EPSILON);
}
}

View file

@ -18,29 +18,40 @@
#include <glm/glm.hpp>
#include <glm/gtc/quaternion.hpp>
/// Base class for face trackers (Faceshift, Visage).
/// Base class for face trackers (Faceshift, Visage, DDE).
class FaceTracker : public QObject {
Q_OBJECT
public:
FaceTracker();
virtual ~FaceTracker() {}
virtual bool isActive() const { return false; }
virtual bool isTracking() const { return false; }
const glm::vec3& getHeadTranslation() const { return _headTranslation; }
const glm::quat& getHeadRotation() const { return _headRotation; }
virtual void init() {}
virtual void update(float deltaTime);
virtual void reset() {}
float getFadeCoefficient() const;
const glm::vec3 getHeadTranslation() const;
const glm::quat getHeadRotation() const;
float getEstimatedEyePitch() const { return _estimatedEyePitch; }
float getEstimatedEyeYaw() const { return _estimatedEyeYaw; }
int getNumBlendshapes() const { return _blendshapeCoefficients.size(); }
bool isValidBlendshapeIndex(int index) const { return index >= 0 && index < getNumBlendshapes(); }
const QVector<float>& getBlendshapeCoefficients() const { return _blendshapeCoefficients; }
float getBlendshapeCoefficient(int index) const;
protected:
glm::vec3 _headTranslation;
glm::quat _headRotation;
float _estimatedEyePitch;
float _estimatedEyeYaw;
glm::vec3 _headTranslation = glm::vec3(0.0f);
glm::quat _headRotation = glm::quat();
float _estimatedEyePitch = 0.0f;
float _estimatedEyeYaw = 0.0f;
QVector<float> _blendshapeCoefficients;
float _relaxationStatus = 0.0f; // Between 0.0f and 1.0f
float _fadeCoefficient = 0.0f; // Between 0.0f and 1.0f
};
#endif // hifi_FaceTracker_h

View file

@ -25,37 +25,11 @@ using namespace fs;
using namespace std;
const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost";
const quint16 FACESHIFT_PORT = 33433;
float STARTING_FACESHIFT_FRAME_TIME = 0.033f;
const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f;
Faceshift::Faceshift() :
_tcpEnabled(true),
_tcpRetryCount(0),
_lastTrackingStateReceived(0),
_averageFrameTime(STARTING_FACESHIFT_FRAME_TIME),
_headAngularVelocity(0),
_headLinearVelocity(0),
_lastHeadTranslation(0),
_filteredHeadTranslation(0),
_eyeGazeLeftPitch(0.0f),
_eyeGazeLeftYaw(0.0f),
_eyeGazeRightPitch(0.0f),
_eyeGazeRightYaw(0.0f),
_leftBlinkIndex(0), // see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
_rightBlinkIndex(1),
_leftEyeOpenIndex(8),
_rightEyeOpenIndex(9),
_browDownLeftIndex(14),
_browDownRightIndex(15),
_browUpCenterIndex(16),
_browUpLeftIndex(17),
_browUpRightIndex(18),
_mouthSmileLeftIndex(28),
_mouthSmileRightIndex(29),
_jawOpenIndex(21),
_longTermAverageEyePitch(0.0f),
_longTermAverageEyeYaw(0.0f),
_longTermAverageInitialized(false),
_eyeDeflection("faceshiftEyeDeflection", DEFAULT_FACESHIFT_EYE_DEFLECTION),
_hostname("faceshiftHostname", DEFAULT_FACESHIFT_HOSTNAME)
{
@ -71,31 +45,17 @@ Faceshift::Faceshift() :
#endif
}
#ifdef HAVE_FACESHIFT
void Faceshift::init() {
#ifdef HAVE_FACESHIFT
setTCPEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Faceshift));
#endif
}
bool Faceshift::isConnectedOrConnecting() const {
return _tcpSocket.state() == QAbstractSocket::ConnectedState ||
(_tcpRetryCount == 0 && _tcpSocket.state() != QAbstractSocket::UnconnectedState);
}
bool Faceshift::isActive() const {
#ifdef HAVE_FACESHIFT
const quint64 ACTIVE_TIMEOUT_USECS = 1000000;
return (usecTimestampNow() - _lastTrackingStateReceived) < ACTIVE_TIMEOUT_USECS;
#else
return false;
#endif
}
void Faceshift::update() {
void Faceshift::update(float deltaTime) {
if (!isActive()) {
return;
}
PerformanceTimer perfTimer("faceshift");
FaceTracker::update(deltaTime);
// get the euler angles relative to the window
glm::vec3 eulers = glm::degrees(safeEulerAngles(_headRotation * glm::quat(glm::radians(glm::vec3(
(_eyeGazeLeftPitch + _eyeGazeRightPitch) / 2.0f, (_eyeGazeLeftYaw + _eyeGazeRightYaw) / 2.0f, 0.0f)))));
@ -116,14 +76,28 @@ void Faceshift::update() {
}
void Faceshift::reset() {
#ifdef HAVE_FACESHIFT
if (_tcpSocket.state() == QAbstractSocket::ConnectedState) {
string message;
fsBinaryStream::encode_message(message, fsMsgCalibrateNeutral());
send(message);
}
_longTermAverageInitialized = false;
}
bool Faceshift::isActive() const {
const quint64 ACTIVE_TIMEOUT_USECS = 1000000;
return (usecTimestampNow() - _lastTrackingStateReceived) < ACTIVE_TIMEOUT_USECS;
}
bool Faceshift::isTracking() const {
return isActive() && _tracking;
}
#endif
bool Faceshift::isConnectedOrConnecting() const {
return _tcpSocket.state() == QAbstractSocket::ConnectedState ||
(_tcpRetryCount == 0 && _tcpSocket.state() != QAbstractSocket::UnconnectedState);
}
void Faceshift::updateFakeCoefficients(float leftBlink, float rightBlink, float browUp,
@ -148,12 +122,13 @@ void Faceshift::updateFakeCoefficients(float leftBlink, float rightBlink, float
}
void Faceshift::setTCPEnabled(bool enabled) {
#ifdef HAVE_FACESHIFT
if ((_tcpEnabled = enabled)) {
connectSocket();
} else {
_tcpSocket.disconnectFromHost();
}
#endif
}
void Faceshift::connectSocket() {
@ -202,10 +177,6 @@ void Faceshift::readFromSocket() {
receive(_tcpSocket.readAll());
}
float Faceshift::getBlendshapeCoefficient(int index) const {
return (index >= 0 && index < (int)_blendshapeCoefficients.size()) ? _blendshapeCoefficients[index] : 0.0f;
}
void Faceshift::send(const std::string& message) {
_tcpSocket.write(message.data(), message.size());
}

View file

@ -24,8 +24,7 @@
#include "FaceTracker.h"
const float DEFAULT_FACESHIFT_EYE_DEFLECTION = 0.25f;
const QString DEFAULT_FACESHIFT_HOSTNAME = "localhost";
const float STARTING_FACESHIFT_FRAME_TIME = 0.033f;
/// Handles interaction with the Faceshift software, which provides head position/orientation and facial features.
class Faceshift : public FaceTracker, public Dependency {
@ -33,11 +32,17 @@ class Faceshift : public FaceTracker, public Dependency {
SINGLETON_DEPENDENCY
public:
void init();
#ifdef HAVE_FACESHIFT
// If we don't have faceshift, use the base class' methods
virtual void init();
virtual void update(float deltaTime);
virtual void reset();
bool isConnectedOrConnecting() const;
virtual bool isActive() const;
virtual bool isTracking() const;
#endif
bool isActive() const;
bool isConnectedOrConnecting() const;
const glm::vec3& getHeadAngularVelocity() const { return _headAngularVelocity; }
@ -68,9 +73,6 @@ public:
QString getHostname() { return _hostname.get(); }
void setHostname(const QString& hostname);
void update();
void reset();
void updateFakeCoefficients(float leftBlink,
float rightBlink,
@ -82,15 +84,12 @@ public:
QVector<float>& coefficients) const;
signals:
void connectionStateChanged();
public slots:
void setTCPEnabled(bool enabled);
private slots:
void connectSocket();
void noteConnected();
void noteError(QAbstractSocket::SocketError error);
@ -101,8 +100,6 @@ private:
Faceshift();
virtual ~Faceshift() {}
float getBlendshapeCoefficient(int index) const;
void send(const std::string& message);
void receive(const QByteArray& buffer);
@ -113,48 +110,48 @@ private:
fs::fsBinaryStream _stream;
#endif
bool _tcpEnabled;
int _tcpRetryCount;
bool _tracking;
quint64 _lastTrackingStateReceived;
float _averageFrameTime;
bool _tcpEnabled = true;
int _tcpRetryCount = 0;
bool _tracking = false;
quint64 _lastTrackingStateReceived = 0;
float _averageFrameTime = STARTING_FACESHIFT_FRAME_TIME;
glm::vec3 _headAngularVelocity;
glm::vec3 _headLinearVelocity;
glm::vec3 _lastHeadTranslation;
glm::vec3 _filteredHeadTranslation;
glm::vec3 _headAngularVelocity = glm::vec3(0.0f);
glm::vec3 _headLinearVelocity = glm::vec3(0.0f);
glm::vec3 _lastHeadTranslation = glm::vec3(0.0f);
glm::vec3 _filteredHeadTranslation = glm::vec3(0.0f);
// degrees
float _eyeGazeLeftPitch;
float _eyeGazeLeftYaw;
float _eyeGazeRightPitch;
float _eyeGazeRightYaw;
int _leftBlinkIndex;
int _rightBlinkIndex;
int _leftEyeOpenIndex;
int _rightEyeOpenIndex;
// Brows
int _browDownLeftIndex;
int _browDownRightIndex;
int _browUpCenterIndex;
int _browUpLeftIndex;
int _browUpRightIndex;
int _mouthSmileLeftIndex;
int _mouthSmileRightIndex;
int _jawOpenIndex;
float _eyeGazeLeftPitch = 0.0f;
float _eyeGazeLeftYaw = 0.0f;
float _eyeGazeRightPitch = 0.0f;
float _eyeGazeRightYaw = 0.0f;
// degrees
float _longTermAverageEyePitch;
float _longTermAverageEyeYaw;
bool _longTermAverageInitialized;
float _longTermAverageEyePitch = 0.0f;
float _longTermAverageEyeYaw = 0.0f;
bool _longTermAverageInitialized = false;
Setting::Handle<float> _eyeDeflection;
Setting::Handle<QString> _hostname;
// see http://support.faceshift.com/support/articles/35129-export-of-blendshapes
int _leftBlinkIndex = 0;
int _rightBlinkIndex = 1;
int _leftEyeOpenIndex = 8;
int _rightEyeOpenIndex = 9;
// Brows
int _browDownLeftIndex = 14;
int _browDownRightIndex = 15;
int _browUpCenterIndex = 16;
int _browUpLeftIndex = 17;
int _browUpRightIndex = 18;
int _mouthSmileLeftIndex = 28;
int _mouthSmileRightIndex = 29;
int _jawOpenIndex = 21;
};
#endif // hifi_Faceshift_h

View file

@ -41,7 +41,6 @@ const glm::vec3 DEFAULT_HEAD_ORIGIN(0.0f, 0.0f, 0.7f);
Visage::Visage() :
_enabled(false),
_active(false),
_headOrigin(DEFAULT_HEAD_ORIGIN) {
#ifdef HAVE_VISAGE
@ -119,20 +118,20 @@ static const QMultiHash<QByteArray, QPair<int, float> >& getActionUnitNameMap()
}
#endif
const float TRANSLATION_SCALE = 20.0f;
#ifdef HAVE_VISAGE
const float TRANSLATION_SCALE = 20.0f;
void Visage::init() {
connect(DependencyManager::get<Faceshift>().data(), SIGNAL(connectionStateChanged()), SLOT(updateEnabled()));
updateEnabled();
}
void Visage::update() {
#ifdef HAVE_VISAGE
_active = (_tracker->getTrackingData(_data) == TRACK_STAT_OK);
if (!_active) {
void Visage::update(float deltaTime) {
if (!isActive()) {
return;
}
PerformanceTimer perfTimer("visage");
FaceTracker::update(deltaTime);
_headRotation = glm::quat(glm::vec3(-_data->faceRotation[0], -_data->faceRotation[1], _data->faceRotation[2]));
_headTranslation = (glm::vec3(_data->faceTranslation[0], _data->faceTranslation[1], _data->faceTranslation[2]) -
_headOrigin) * TRANSLATION_SCALE;
@ -164,12 +163,12 @@ void Visage::update() {
}
_blendshapeCoefficients[leftEyeBlinkIndex] = 1.0f - _data->eyeClosure[1];
_blendshapeCoefficients[rightEyeBlinkIndex] = 1.0f - _data->eyeClosure[0];
#endif
}
void Visage::reset() {
_headOrigin += _headTranslation / TRANSLATION_SCALE;
}
#endif
void Visage::updateEnabled() {
setEnabled(Menu::getInstance()->isOptionChecked(MenuOption::Visage) &&

View file

@ -31,15 +31,16 @@ class Visage : public FaceTracker, public Dependency {
SINGLETON_DEPENDENCY
public:
void init();
#ifdef HAVE_VISAGE
virtual void init();
virtual void update(float deltaTime);
virtual void reset();
bool isActive() const { return _active; }
void update();
void reset();
virtual bool isActive() const { return _tracker->getTrackingData(_data) == TRACK_STAT_OK; }
virtual bool isTracking() const { return isActive(); }
#endif
public slots:
void updateEnabled();
private:
@ -55,7 +56,6 @@ private:
void setEnabled(bool enabled);
bool _enabled;
bool _active;
glm::vec3 _headOrigin;
};

View file

@ -37,24 +37,17 @@ void RenderableLightEntityItem::render(RenderArgs* args) {
float colorB = getColor()[BLUE_INDEX] / MAX_COLOR;
glm::vec3 color = glm::vec3(colorR, colorG, colorB);
glm::vec3 diffuse = color;
glm::vec3 ambient = color;
glm::vec3 specular = color;
glm::vec3 direction = IDENTITY_FRONT * rotation;
float constantAttenuation = 0.0f;
float linearAttenuation = 0.0f;
float quadraticAttenuation = 0.0f;
float intensity = getIntensity();
float exponent = getExponent();
float cutoff = glm::radians(getCutoff());
if (_isSpotlight) {
DependencyManager::get<DeferredLightingEffect>()->addSpotLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation,
direction, exponent, cutoff);
DependencyManager::get<DeferredLightingEffect>()->addSpotLight(position, largestDiameter / 2.0f,
color, intensity, rotation, exponent, cutoff);
} else {
DependencyManager::get<DeferredLightingEffect>()->addPointLight(position, largestDiameter / 2.0f,
ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation);
DependencyManager::get<DeferredLightingEffect>()->addPointLight(position, largestDiameter / 2.0f,
color, intensity);
}
#ifdef WANT_DEBUG

View file

@ -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;

View file

@ -0,0 +1,209 @@
//
// 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 <glm/gtx/transform.hpp>
#include <math.h>
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));
// 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;
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);
// Noun
setDayTime(12.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::setOriginOrientation(const Quat& orientation) {
_earthSunModel.setSurfaceOrientation(orientation);
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 originAlt = _earthSunModel.getAltitude();
_sunLight->setPosition(Vec3(0.0f, originAlt, 0.0f));
}

View file

@ -0,0 +1,161 @@
//
// 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:
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; }
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; }
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;
Quat _surfaceOrientation;
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);
};
// 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; }
// 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(); }
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;
float _dayTime;
int _yearTime;
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

View file

@ -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

View file

@ -126,15 +126,13 @@ void DeferredLightingEffect::renderSolidCone(float base, float height, int slice
releaseSimpleProgram();
}
void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient,
const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation,
float linearAttenuation, float quadraticAttenuation) {
addSpotLight(position, radius, ambient, diffuse, specular, constantAttenuation, linearAttenuation, quadraticAttenuation);
void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& color,
float intensity) {
addSpotLight(position, radius, color, intensity);
}
void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& ambient,
const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation, float linearAttenuation,
float quadraticAttenuation, const glm::vec3& direction, float exponent, float cutoff) {
void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color,
float intensity, const glm::quat& orientation, float exponent, float cutoff) {
int lightID = _pointLights.size() + _spotLights.size() + _globalLights.size();
if (lightID >= _allocatedLights.size()) {
@ -144,8 +142,8 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu
lp->setPosition(position);
lp->setMaximumRadius(radius);
lp->setColor(diffuse);
lp->setIntensity(1.0f);
lp->setColor(color);
lp->setIntensity(intensity);
//lp->setShowContour(quadraticAttenuation);
if (exponent == 0.0f && cutoff == PI) {
@ -153,7 +151,7 @@ void DeferredLightingEffect::addSpotLight(const glm::vec3& position, float radiu
_pointLights.push_back(lightID);
} else {
lp->setDirection(direction);
lp->setOrientation(orientation);
lp->setSpotAngle(cutoff);
lp->setSpotExponent(exponent);
lp->setType(model::Light::SPOT);

View file

@ -57,15 +57,12 @@ public:
void renderSolidCone(float base, float height, int slices, int stacks);
/// Adds a point light to render for the current frame.
void addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f),
const glm::vec3& diffuse = glm::vec3(1.0f, 1.0f, 1.0f), const glm::vec3& specular = glm::vec3(1.0f, 1.0f, 1.0f),
float constantAttenuation = 1.0f, float linearAttenuation = 0.0f, float quadraticAttenuation = 0.0f);
void addPointLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(0.0f, 0.0f, 0.0f),
float intensity = 0.5f);
/// Adds a spot light to render for the current frame.
void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f),
const glm::vec3& diffuse = glm::vec3(1.0f, 1.0f, 1.0f), const glm::vec3& specular = glm::vec3(1.0f, 1.0f, 1.0f),
float constantAttenuation = 1.0f, float linearAttenuation = 0.0f, float quadraticAttenuation = 0.0f,
const glm::vec3& direction = glm::vec3(0.0f, 0.0f, -1.0f), float exponent = 0.0f, float cutoff = PI);
void addSpotLight(const glm::vec3& position, float radius, const glm::vec3& color = glm::vec3(1.0f, 1.0f, 1.0f),
float intensity = 0.5f, const glm::quat& orientation = glm::quat(), float exponent = 0.0f, float cutoff = PI);
/// Adds an object to render after performing the deferred lighting for the current frame (e.g., a translucent object).
void addPostLightingRenderable(PostLightingRenderable* renderable) { _postLightingRenderables.append(renderable); }

View file

@ -0,0 +1,40 @@
//
// 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 <AddressManager.h>
#include "SceneScriptingInterface.h"
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);
}
void SceneScriptingInterface::setSunIntensity(float intensity) {
_skyStage->setSunIntensity(intensity);
}
model::SunSkyStagePointer SceneScriptingInterface::getSkyStage() const {
return _skyStage;
}

View file

@ -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 <qscriptengine.h>
#include <DependencyManager.h>
#include "model/Stage.h"
class SceneScriptingInterface : public QObject, public Dependency {
Q_OBJECT
SINGLETON_DEPENDENCY
public:
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);
model::SunSkyStagePointer getSkyStage() const;
protected:
SceneScriptingInterface() {};
~SceneScriptingInterface() {};
model::SunSkyStagePointer _skyStage = model::SunSkyStagePointer(new model::SunSkyStage());
};
#endif // hifi_SceneScriptingInterface_h

View file

@ -39,6 +39,8 @@
#include "TypedArrays.h"
#include "XMLHttpRequestClass.h"
#include "SceneScriptingInterface.h"
#include "MIDIEvent.h"
@ -310,6 +312,8 @@ void ScriptEngine::init() {
_isInitialized = true;
auto sceneScriptingInterface = DependencyManager::set<SceneScriptingInterface>();
_entityScriptingInterface.init();
// register various meta-types
@ -353,6 +357,7 @@ void ScriptEngine::init() {
registerGlobalObject("Vec3", &_vec3Library);
registerGlobalObject("Uuid", &_uuidLibrary);
registerGlobalObject("AnimationCache", DependencyManager::get<AnimationCache>().data());
registerGlobalObject("Scene", DependencyManager::get<SceneScriptingInterface>().data());
// constants
globalObject().setProperty("TREE_SCALE", newVariant(QVariant(TREE_SCALE)));