Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels

This commit is contained in:
Andrzej Kapolka 2014-07-29 14:28:14 -07:00
commit 2a7847c5b3
8 changed files with 164 additions and 21 deletions

View file

@ -98,6 +98,9 @@ Currently building on Windows has been tested using the following compilers:
Whichever version of Visual Studio you use, first install [Microsoft Windows SDK for Windows 7 and .NET Framework 4](http://www.microsoft.com/en-us/download/details.aspx?id=8279).
######Windows 8.1
You may have already downloaded the Windows 8 SDK (e.g. if you have previously installed Visual Studio 2013). If so, change CMAKE_PREFIX_PATH in %HIFI_DIR%\CMakeLists.txt to point to the Windows 8 SDK binaries. The default path is `C:\Program Files (x86)\Windows Kits\8.1\Lib\winv6.3\um\x86`
#####Visual Studio C++ 2010 Express
Visual Studio C++ 2010 Express can be downloaded [here](http://www.visualstudio.com/en-us/downloads#d-2010-express).
@ -116,6 +119,8 @@ Visual Studio 2013 doesn't have a shortcut to start a Visual Studio Command Prom
"%VS120COMNTOOLS%\vsvars32.bat"
If you experience issues building interface on Visual Studio 2013, try generating the build files with Visual Studio 2010 instead. To do so, download Visual Studio 2010 and run `cmake .. -G "Visual Studio 10"` (Assuming running from %HIFI_DIR%\build).
####Qt
You can use the online installer or the offline installer. If you use the offline installer, be sure to select the "OpenGL" version.

View file

@ -9,6 +9,10 @@ add_definitions(-DGLM_FORCE_RADIANS)
if (WIN32)
add_definitions(-DNOMINMAX -D_CRT_SECURE_NO_WARNINGS)
# set path for Microsoft SDKs
# if get build error about missing 'glu32' this path is likely wrong
# Uncomment the line with 8.1 if running Windows 8.1
#set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "C:\\Program Files (x86)\\Windows Kits\\8.1\\Lib\\winv6.3\\um\\x86")
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "C:\\Program Files\\Microsoft SDKs\\Windows\\v7.1 ")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP")
elseif (CMAKE_COMPILER_IS_GNUCC OR CMAKE_COMPILER_IS_GNUCXX)

View file

@ -29,6 +29,8 @@
#include <ParticlesScriptingInterface.h> // TODO: consider moving to scriptengine.h
#include <ModelsScriptingInterface.h> // TODO: consider moving to scriptengine.h
#include "avatars/ScriptableAvatar.h"
#include "Agent.h"
Agent::Agent(const QByteArray& packet) :
@ -228,7 +230,7 @@ void Agent::run() {
qDebug() << "Downloaded script:" << scriptContents;
// setup an Avatar for the script to use
AvatarData scriptedAvatar;
ScriptableAvatar scriptedAvatar(&_scriptEngine);
scriptedAvatar.setForceFaceshiftConnected(true);
// call model URL setters with empty URLs so our avatar, if user, will have the default models

View file

@ -0,0 +1,88 @@
//
// ScriptableAvatar.cpp
//
//
// Created by Clement on 7/22/14.
// 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 <QThread>
#include "ScriptableAvatar.h"
ScriptableAvatar::ScriptableAvatar(ScriptEngine* scriptEngine) : _scriptEngine(scriptEngine), _animation(NULL) {
connect(_scriptEngine, SIGNAL(update(float)), this, SLOT(update(float)));
}
// hold and priority unused but kept so that client side JS can run.
void ScriptableAvatar::startAnimation(const QString& url, float fps, float priority,
bool loop, bool hold, float firstFrame, float lastFrame, const QStringList& maskedJoints) {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "startAnimation", Q_ARG(const QString&, url), Q_ARG(float, fps),
Q_ARG(float, priority), Q_ARG(bool, loop), Q_ARG(bool, hold), Q_ARG(float, firstFrame),
Q_ARG(float, lastFrame), Q_ARG(const QStringList&, maskedJoints));
return;
}
_animation = _scriptEngine->getAnimationCache()->getAnimation(url);
_animationDetails = AnimationDetails("", QUrl(url), fps, 0, loop, hold, false, firstFrame, lastFrame, true, firstFrame);
_maskedJoints = maskedJoints;
}
void ScriptableAvatar::stopAnimation() {
if (QThread::currentThread() != thread()) {
QMetaObject::invokeMethod(this, "stopAnimation");
return;
}
_animation.clear();
}
AnimationDetails ScriptableAvatar::getAnimationDetails() {
if (QThread::currentThread() != thread()) {
AnimationDetails result;
QMetaObject::invokeMethod(this, "getAnimationDetails", Qt::BlockingQueuedConnection,
Q_RETURN_ARG(AnimationDetails, result));
return result;
}
return _animationDetails;
}
void ScriptableAvatar::update(float deltatime) {
// Run animation
if (_animation != NULL && _animation->isValid() && _animation->getFrames().size() > 0) {
QStringList modelJoints = getJointNames();
QStringList animationJoints = _animation->getJointNames();
if (_jointData.size() != modelJoints.size()) {
_jointData.resize(modelJoints.size());
}
float frameIndex = _animationDetails.frameIndex + deltatime * _animationDetails.fps;
if (_animationDetails.loop || frameIndex < _animationDetails.lastFrame) {
while (frameIndex >= _animationDetails.lastFrame) {
frameIndex -= (_animationDetails.lastFrame - _animationDetails.firstFrame);
}
_animationDetails.frameIndex = frameIndex;
const int frameCount = _animation->getFrames().size();
const FBXAnimationFrame& floorFrame = _animation->getFrames().at((int)glm::floor(frameIndex) % frameCount);
const FBXAnimationFrame& ceilFrame = _animation->getFrames().at((int)glm::ceil(frameIndex) % frameCount);
const float frameFraction = glm::fract(frameIndex);
for (int i = 0; i < modelJoints.size(); i++) {
int mapping = animationJoints.indexOf(modelJoints[i]);
if (mapping != -1 && !_maskedJoints.contains(modelJoints[i])) {
JointData& data = _jointData[i];
data.valid = true;
data.rotation = safeMix(floorFrame.rotations.at(i), ceilFrame.rotations.at(i), frameFraction);
} else {
_jointData[i].valid = false;
}
}
} else {
_animation.clear();
}
}
}

View file

@ -0,0 +1,40 @@
//
// ScriptableAvatar.h
//
//
// Created by Clement on 7/22/14.
// 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_ScriptableAvatar_h
#define hifi_ScriptableAvatar_h
#include <AnimationCache.h>
#include <AvatarData.h>
#include <ScriptEngine.h>
class ScriptableAvatar : public AvatarData {
Q_OBJECT
public:
ScriptableAvatar(ScriptEngine* scriptEngine);
/// Allows scripts to run animations.
Q_INVOKABLE void startAnimation(const QString& url, float fps = 30.0f, float priority = 1.0f, bool loop = false,
bool hold = false, float firstFrame = 0.0f, float lastFrame = FLT_MAX, const QStringList& maskedJoints = QStringList());
Q_INVOKABLE void stopAnimation();
Q_INVOKABLE AnimationDetails getAnimationDetails();
private slots:
void update(float deltatime);
private:
ScriptEngine* _scriptEngine;
AnimationPointer _animation;
AnimationDetails _animationDetails;
QStringList _maskedJoints;
};
#endif // hifi_ScriptableAvatar_h

View file

@ -748,18 +748,19 @@ function Tooltip() {
this.updateText = function(properties) {
var angles = Quat.safeEulerAngles(properties.modelRotation);
var text = "Model Properties:\n"
text += "x: " + properties.position.x.toFixed(this.decimals) + "\n"
text += "y: " + properties.position.y.toFixed(this.decimals) + "\n"
text += "z: " + properties.position.z.toFixed(this.decimals) + "\n"
text += "pitch: " + angles.x.toFixed(this.decimals) + "\n"
text += "yaw: " + angles.y.toFixed(this.decimals) + "\n"
text += "roll: " + angles.z.toFixed(this.decimals) + "\n"
text += "X: " + properties.position.x.toFixed(this.decimals) + "\n"
text += "Y: " + properties.position.y.toFixed(this.decimals) + "\n"
text += "Z: " + properties.position.z.toFixed(this.decimals) + "\n"
text += "Pitch: " + angles.x.toFixed(this.decimals) + "\n"
text += "Yaw: " + angles.y.toFixed(this.decimals) + "\n"
text += "Roll: " + angles.z.toFixed(this.decimals) + "\n"
text += "Scale: " + 2 * properties.radius.toFixed(this.decimals) + "\n"
text += "ID: " + properties.id + "\n"
text += "model url: " + properties.modelURL + "\n"
text += "animation url: " + properties.animationURL + "\n"
text += "Model URL: " + properties.modelURL + "\n"
text += "Animation URL: " + properties.animationURL + "\n"
text += "Animation is playing: " + properties.animationIsPlaying + "\n"
if (properties.sittingPoints.length > 0) {
text += properties.sittingPoints.length + " sitting points: "
text += properties.sittingPoints.length + " Sitting points: "
for (var i = 0; i < properties.sittingPoints.length; ++i) {
text += properties.sittingPoints[i].name + " "
}
@ -1146,6 +1147,7 @@ function handeMenuEvent(menuItem){
var decimals = 3;
array.push({ label: "Model URL:", value: selectedModelProperties.modelURL });
array.push({ label: "Animation URL:", value: selectedModelProperties.animationURL });
array.push({ label: "Animation is playing:", value: selectedModelProperties.animationIsPlaying });
array.push({ label: "X:", value: selectedModelProperties.position.x.toFixed(decimals) });
array.push({ label: "Y:", value: selectedModelProperties.position.y.toFixed(decimals) });
array.push({ label: "Z:", value: selectedModelProperties.position.z.toFixed(decimals) });
@ -1158,16 +1160,18 @@ function handeMenuEvent(menuItem){
var propertyName = Window.form("Edit Properties", array);
modelSelected = false;
selectedModelProperties.modelURL = array[0].value;
selectedModelProperties.animationURL = array[1].value;
selectedModelProperties.position.x = array[2].value;
selectedModelProperties.position.y = array[3].value;
selectedModelProperties.position.z = array[4].value;
angles.x = array[5].value;
angles.y = array[6].value;
angles.z = array[7].value;
var index = 0;
selectedModelProperties.modelURL = array[index++].value;
selectedModelProperties.animationURL = array[index++].value;
selectedModelProperties.animationIsPlaying = array[index++].value;
selectedModelProperties.position.x = array[index++].value;
selectedModelProperties.position.y = array[index++].value;
selectedModelProperties.position.z = array[index++].value;
angles.x = array[index++].value;
angles.y = array[index++].value;
angles.z = array[index++].value;
selectedModelProperties.modelRotation = Quat.fromVec3Degrees(angles);
selectedModelProperties.radius = array[8].value / 2;
selectedModelProperties.radius = array[index++].value / 2;
Models.editModel(selectedModelID, selectedModelProperties);
}
@ -1200,6 +1204,7 @@ Controller.keyPressEvent.connect(function(event) {
somethingChanged = true;
}
});
Controller.keyReleaseEvent.connect(function(event) {
if (event.text == "z" || event.text == "Z") {
zIsPressed = false;

View file

@ -1878,8 +1878,6 @@ void MyAvatar::renderLaserPointers() {
//Gets the tip position for the laser pointer
glm::vec3 MyAvatar::getLaserPointerTipPosition(const PalmData* palm) {
const ApplicationOverlay& applicationOverlay = Application::getInstance()->getApplicationOverlay();
const float PALM_TIP_ROD_LENGTH_MULT = 40.0f;
glm::vec3 direction = glm::normalize(palm->getTipPosition() - palm->getPosition());
glm::vec3 position = palm->getPosition();

View file

@ -58,6 +58,7 @@ public:
static ModelsScriptingInterface* getModelsScriptingInterface() { return &_modelsScriptingInterface; }
ArrayBufferClass* getArrayBufferClass() { return _arrayBufferClass; }
AnimationCache* getAnimationCache() { return &_animationCache; }
/// sets the script contents, will return false if failed, will fail if script is already running
bool setScriptContents(const QString& scriptContents, const QString& fileNameString = QString(""));