mirror of
https://github.com/overte-org/overte.git
synced 2025-04-19 15:43:50 +02:00
Merge branch 'master' of https://github.com/highfidelity/hifi into tot
This commit is contained in:
commit
7daff18101
93 changed files with 1060 additions and 389 deletions
|
@ -9,6 +9,8 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include <LogHandler.h>
|
||||
|
||||
#include "AssignmentClientMonitor.h"
|
||||
|
@ -17,9 +19,21 @@ const char* NUM_FORKS_PARAMETER = "-n";
|
|||
|
||||
const QString ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME = "assignment-client-monitor";
|
||||
|
||||
void signalHandler(int param){
|
||||
// get the qApp and cast it to an AssignmentClientMonitor
|
||||
AssignmentClientMonitor* app = qobject_cast<AssignmentClientMonitor*>(qApp);
|
||||
|
||||
// tell it to stop the child processes and then go down
|
||||
app->stopChildProcesses();
|
||||
app->quit();
|
||||
}
|
||||
|
||||
AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks) :
|
||||
QCoreApplication(argc, argv)
|
||||
{
|
||||
// be a signal handler for SIGTERM so we can stop our children when we get it
|
||||
signal(SIGTERM, signalHandler);
|
||||
|
||||
// start the Logging class with the parent's target name
|
||||
LogHandler::getInstance().setTargetName(ASSIGNMENT_CLIENT_MONITOR_TARGET_NAME);
|
||||
|
||||
|
@ -38,9 +52,29 @@ AssignmentClientMonitor::AssignmentClientMonitor(int &argc, char **argv, int num
|
|||
}
|
||||
}
|
||||
|
||||
void AssignmentClientMonitor::stopChildProcesses() {
|
||||
|
||||
QList<QPointer<QProcess> >::Iterator it = _childProcesses.begin();
|
||||
while (it != _childProcesses.end()) {
|
||||
if (!it->isNull()) {
|
||||
qDebug() << "Monitor is terminating child process" << it->data();
|
||||
|
||||
// don't re-spawn this child when it goes down
|
||||
disconnect(it->data(), 0, this, 0);
|
||||
|
||||
it->data()->terminate();
|
||||
it->data()->waitForFinished();
|
||||
}
|
||||
|
||||
it = _childProcesses.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
void AssignmentClientMonitor::spawnChildClient() {
|
||||
QProcess *assignmentClient = new QProcess(this);
|
||||
|
||||
_childProcesses.append(QPointer<QProcess>(assignmentClient));
|
||||
|
||||
// make sure that the output from the child process appears in our output
|
||||
assignmentClient->setProcessChannelMode(QProcess::ForwardedChannels);
|
||||
|
||||
|
@ -55,5 +89,10 @@ void AssignmentClientMonitor::spawnChildClient() {
|
|||
|
||||
void AssignmentClientMonitor::childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus) {
|
||||
qDebug("Replacing dead child assignment client with a new one");
|
||||
|
||||
// remove the old process from our list of child processes
|
||||
qDebug() << "need to remove" << QPointer<QProcess>(qobject_cast<QProcess*>(sender()));
|
||||
_childProcesses.removeOne(QPointer<QProcess>(qobject_cast<QProcess*>(sender())));
|
||||
|
||||
spawnChildClient();
|
||||
}
|
||||
|
|
|
@ -13,6 +13,7 @@
|
|||
#define hifi_AssignmentClientMonitor_h
|
||||
|
||||
#include <QtCore/QCoreApplication>
|
||||
#include <QtCore/qpointer.h>
|
||||
#include <QtCore/QProcess>
|
||||
|
||||
#include <Assignment.h>
|
||||
|
@ -23,10 +24,13 @@ class AssignmentClientMonitor : public QCoreApplication {
|
|||
Q_OBJECT
|
||||
public:
|
||||
AssignmentClientMonitor(int &argc, char **argv, int numAssignmentClientForks);
|
||||
|
||||
void stopChildProcesses();
|
||||
private slots:
|
||||
void childProcessFinished(int exitCode, QProcess::ExitStatus exitStatus);
|
||||
private:
|
||||
void spawnChildClient();
|
||||
QList<QPointer<QProcess> > _childProcesses;
|
||||
|
||||
QStringList _childArguments;
|
||||
};
|
||||
|
|
|
@ -401,8 +401,8 @@ int AudioMixer::addStreamToMixForListeningNodeWithStream(AudioMixerClientData* l
|
|||
|
||||
if (distanceBetween < RADIUS_OF_HEAD) {
|
||||
// Diminish effect if source would be inside head
|
||||
penumbraFilterGainL += (1.f - penumbraFilterGainL) * (1.f - distanceBetween / RADIUS_OF_HEAD);
|
||||
penumbraFilterGainR += (1.f - penumbraFilterGainR) * (1.f - distanceBetween / RADIUS_OF_HEAD);
|
||||
penumbraFilterGainL += (1.0f - penumbraFilterGainL) * (1.0f - distanceBetween / RADIUS_OF_HEAD);
|
||||
penumbraFilterGainR += (1.0f - penumbraFilterGainR) * (1.0f - distanceBetween / RADIUS_OF_HEAD);
|
||||
}
|
||||
|
||||
bool wantDebug = false;
|
||||
|
|
|
@ -146,11 +146,11 @@ void AvatarMixer::broadcastAvatarData() {
|
|||
float distanceToAvatar = glm::length(myPosition - otherPosition);
|
||||
// The full rate distance is the distance at which EVERY update will be sent for this avatar
|
||||
// at a distance of twice the full rate distance, there will be a 50% chance of sending this avatar's update
|
||||
const float FULL_RATE_DISTANCE = 2.f;
|
||||
const float FULL_RATE_DISTANCE = 2.0f;
|
||||
|
||||
// Decide whether to send this avatar's data based on it's distance from us
|
||||
if ((_performanceThrottlingRatio == 0 || randFloat() < (1.0f - _performanceThrottlingRatio))
|
||||
&& (distanceToAvatar == 0.f || randFloat() < FULL_RATE_DISTANCE / distanceToAvatar)) {
|
||||
&& (distanceToAvatar == 0.0f || randFloat() < FULL_RATE_DISTANCE / distanceToAvatar)) {
|
||||
QByteArray avatarByteArray;
|
||||
avatarByteArray.append(otherNode->getUUID().toRfc4122());
|
||||
avatarByteArray.append(otherAvatar.toByteArray());
|
||||
|
|
|
@ -700,8 +700,8 @@ bool OctreeServer::handleHTTPRequest(HTTPConnection* connection, const QUrl& url
|
|||
statsString += "\r\n";
|
||||
|
||||
const char* memoryScaleLabel;
|
||||
const float MEGABYTES = 1000000.f;
|
||||
const float GIGABYTES = 1000000000.f;
|
||||
const float MEGABYTES = 1000000.0f;
|
||||
const float GIGABYTES = 1000000000.0f;
|
||||
float memoryScale;
|
||||
if (OctreeElement::getTotalMemoryUsage() / MEGABYTES < 1000.0f) {
|
||||
memoryScaleLabel = "MB";
|
||||
|
|
|
@ -14,11 +14,10 @@ var position = { x: 700, y: 25, z: 725 };
|
|||
var audioOptions = {
|
||||
position: position,
|
||||
volume: 0.4,
|
||||
loop: true,
|
||||
stereo: false
|
||||
loop: true
|
||||
};
|
||||
|
||||
var sound = SoundCache.getSound(soundURL, audioOptions.isStereo);
|
||||
var sound = SoundCache.getSound(soundURL);
|
||||
var injector = null;
|
||||
var count = 100;
|
||||
|
||||
|
|
125
examples/html/entityList.html
Normal file
125
examples/html/entityList.html
Normal file
|
@ -0,0 +1,125 @@
|
|||
|
||||
<html>
|
||||
<head>
|
||||
<link rel="stylesheet" type="text/css" href="style.css">
|
||||
<script>
|
||||
var entities = {};
|
||||
var selectedEntities = [];
|
||||
|
||||
function loaded() {
|
||||
elEntityTable = document.getElementById("entity-table");
|
||||
elRefresh = document.getElementById("refresh");
|
||||
|
||||
function onRowClicked(e) {
|
||||
var id = this.dataset.entityId;
|
||||
|
||||
var selection = [this.dataset.entityId];
|
||||
if (e.shiftKey) {
|
||||
selection = selection.concat(selectedEntities);
|
||||
}
|
||||
|
||||
selectedEntities = selection;
|
||||
|
||||
entities[id].el.className = 'selected';
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "selectionUpdate",
|
||||
focus: false,
|
||||
entityIds: selection,
|
||||
}));
|
||||
}
|
||||
|
||||
function onRowDoubleClicked() {
|
||||
var id = this.dataset.entityId;
|
||||
|
||||
EventBridge.emitWebEvent(JSON.stringify({
|
||||
type: "selectionUpdate",
|
||||
focus: true,
|
||||
entityIds: [this.dataset.entityId],
|
||||
}));
|
||||
}
|
||||
|
||||
function addEntity(id, type, url) {
|
||||
if (entities[id] === undefined) {
|
||||
var el = document.createElement('tr');
|
||||
el.setAttribute('id', 'entity_' + id);
|
||||
el.innerHTML += "<td>" + type + "</td>";
|
||||
el.innerHTML += "<td>" + url + "</td>";
|
||||
el.dataset.entityId = id;
|
||||
el.onclick = onRowClicked;
|
||||
el.ondblclick = onRowDoubleClicked;
|
||||
elEntityTable.appendChild(el);
|
||||
|
||||
// Add element to local dict
|
||||
entities[id] = {
|
||||
id: id,
|
||||
name: id,
|
||||
el: el,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
function removeEntity(id) {
|
||||
if (entities[id] !== undefined) {
|
||||
elEntityTable.removeChild(entities[id].el);
|
||||
delete entities[id];
|
||||
}
|
||||
}
|
||||
|
||||
function clearEntities() {
|
||||
for (id in entities) {
|
||||
elEntityTable.removeChild(entities[id].el);
|
||||
}
|
||||
entities = {};
|
||||
}
|
||||
|
||||
elRefresh.onclick = function() {
|
||||
clearEntities();
|
||||
EventBridge.emitWebEvent(JSON.stringify({ type: 'refresh' }));
|
||||
}
|
||||
|
||||
if (window.EventBridge !== undefined) {
|
||||
EventBridge.scriptEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
|
||||
if (data.type == "selectionUpdate") {
|
||||
selectedEntities = data.selectedIDs;
|
||||
for (var id in entities) {
|
||||
entities[id].el.className = '';
|
||||
}
|
||||
for (var i = 0; i < data.selectedIDs.length; i++) {
|
||||
var id = data.selectedIDs[i];
|
||||
if (id in entities) {
|
||||
var entity = entities[id];
|
||||
entity.el.className = 'selected';
|
||||
}
|
||||
}
|
||||
} 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);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body onload='loaded();'>
|
||||
<div>
|
||||
<button id="refresh">Refresh</button>
|
||||
</div>
|
||||
|
||||
<table id="entity-table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th id="entity-type">Type</th>
|
||||
<th id="entity-url">URL</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody id="entity-table-body">
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
</body>
|
||||
</html>
|
|
@ -214,7 +214,7 @@
|
|||
elModelSection.style.display = 'block';
|
||||
elModelURL.value = properties.modelURL;
|
||||
elModelAnimationURL.value = properties.animationURL;
|
||||
elModelAnimationPlaying.checked = properties.animationPlaying;
|
||||
elModelAnimationPlaying.checked = properties.animationIsPlaying;
|
||||
elModelAnimationFPS.value = properties.animationFPS;
|
||||
}
|
||||
|
||||
|
|
|
@ -93,3 +93,40 @@ input.coord {
|
|||
width: 6em;
|
||||
height: 2em;
|
||||
}
|
||||
|
||||
table#entity-table {
|
||||
border-collapse: collapse;
|
||||
font-family: Sans-Serif;
|
||||
font-size: 12px;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
#entity-table tr {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
tr.selected {
|
||||
background-color: #AAA;
|
||||
}
|
||||
|
||||
#entity-table th {
|
||||
background-color: #333;
|
||||
color: #fff;
|
||||
border: 0px black solid;
|
||||
text-align: left;
|
||||
word-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
#entity-table td {
|
||||
border: 0px black solid;
|
||||
word-wrap: nowrap;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
th#entity-type {
|
||||
width: 60px;
|
||||
}
|
||||
|
||||
th#entity-url {
|
||||
}
|
||||
|
|
70
examples/libraries/entityList.js
Normal file
70
examples/libraries/entityList.js
Normal file
|
@ -0,0 +1,70 @@
|
|||
EntityListTool = function(opts) {
|
||||
var that = {};
|
||||
|
||||
var url = Script.resolvePath('html/entityList.html');
|
||||
var webView = new WebWindow('Entities', url, 200, 280);
|
||||
|
||||
var visible = false;
|
||||
|
||||
webView.setVisible(visible);
|
||||
|
||||
that.setVisible = function(newVisible) {
|
||||
visible = newVisible;
|
||||
webView.setVisible(visible);
|
||||
};
|
||||
|
||||
selectionManager.addEventListener(function() {
|
||||
var selectedIDs = [];
|
||||
|
||||
for (var i = 0; i < selectionManager.selections.length; i++) {
|
||||
selectedIDs.push(selectionManager.selections[i].id);
|
||||
}
|
||||
|
||||
data = {
|
||||
type: 'selectionUpdate',
|
||||
selectedIDs: selectedIDs,
|
||||
};
|
||||
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
||||
});
|
||||
|
||||
webView.eventBridge.webEventReceived.connect(function(data) {
|
||||
data = JSON.parse(data);
|
||||
if (data.type == "selectionUpdate") {
|
||||
var ids = data.entityIds;
|
||||
var entityIDs = [];
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
var entityID = Entities.getEntityItemID(ids[i]);
|
||||
if (entityID.isKnownID) {
|
||||
entityIDs.push(entityID);
|
||||
} else {
|
||||
print("Tried to select invalid entity: " + ids[i]);
|
||||
}
|
||||
}
|
||||
selectionManager.setSelections(entityIDs);
|
||||
if (data.focus) {
|
||||
cameraManager.focus(selectionManager.worldPosition,
|
||||
selectionManager.worldDimensions,
|
||||
Menu.isOptionChecked(MENU_EASE_ON_FOCUS));
|
||||
}
|
||||
} else if (data.type == "refresh") {
|
||||
var entities = [];
|
||||
var ids = Entities.findEntities(MyAvatar.position, 100);
|
||||
for (var i = 0; i < ids.length; i++) {
|
||||
var id = ids[i];
|
||||
var properties = Entities.getEntityProperties(id);
|
||||
entities.push({
|
||||
id: id.id,
|
||||
type: properties.type,
|
||||
url: properties.type == "Model" ? properties.modelURL : "",
|
||||
});
|
||||
}
|
||||
var data = {
|
||||
type: "update",
|
||||
entities: entities,
|
||||
};
|
||||
webView.eventBridge.emitScriptEvent(JSON.stringify(data));
|
||||
}
|
||||
});
|
||||
|
||||
return that;
|
||||
};
|
|
@ -1242,7 +1242,7 @@ SelectionDisplay = (function () {
|
|||
Quat.getFront(lastCameraOrientation));
|
||||
|
||||
var vector = Vec3.subtract(newIntersection, lastPlaneIntersection);
|
||||
lastPlaneIntersection = newIntersection;
|
||||
vector = grid.snapToGrid(vector);
|
||||
|
||||
// we only care about the Y axis
|
||||
vector.x = 0;
|
||||
|
@ -1258,10 +1258,15 @@ SelectionDisplay = (function () {
|
|||
Vec3.print(" newPosition:", newPosition);
|
||||
}
|
||||
for (var i = 0; i < SelectionManager.selections.length; i++) {
|
||||
var properties = Entities.getEntityProperties(SelectionManager.selections[i]);
|
||||
var id = SelectionManager.selections[i];
|
||||
var properties = selectionManager.savedProperties[id.id];
|
||||
|
||||
var original = properties.position;
|
||||
properties.position = Vec3.sum(properties.position, vector);
|
||||
Entities.editEntity(SelectionManager.selections[i], properties);
|
||||
var newPosition = Vec3.sum(properties.position, vector);
|
||||
|
||||
Entities.editEntity(id, {
|
||||
position: newPosition,
|
||||
});
|
||||
}
|
||||
|
||||
SelectionManager._update();
|
||||
|
|
|
@ -39,18 +39,23 @@ var ORB_SHIFT = { x: 0, y: -1.4, z: -0.8};
|
|||
|
||||
var HELMET_ATTACHMENT_URL = HIFI_PUBLIC_BUCKET + "models/attachments/IronManMaskOnly.fbx"
|
||||
|
||||
var droneSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.raw")
|
||||
var droneSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/drone.stereo.raw")
|
||||
var currentDrone = null;
|
||||
|
||||
var latinSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/latin.raw")
|
||||
var elevatorSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/elevator.raw")
|
||||
var currentMusak = null;
|
||||
var latinSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/latin.stereo.raw")
|
||||
var elevatorSound = SoundCache.getSound(HIFI_PUBLIC_BUCKET + "sounds/Lobby/elevator.stereo.raw")
|
||||
var currentMusakInjector = null;
|
||||
var currentSound = null;
|
||||
|
||||
var inOculusMode = Menu.isOptionChecked("EnableVRMode");
|
||||
|
||||
function reticlePosition() {
|
||||
var RETICLE_DISTANCE = 1;
|
||||
return Vec3.sum(Camera.position, Vec3.multiply(Quat.getFront(Camera.orientation), RETICLE_DISTANCE));
|
||||
}
|
||||
|
||||
var MAX_NUM_PANELS = 21;
|
||||
|
||||
function drawLobby() {
|
||||
if (!panelWall) {
|
||||
print("Adding overlays for the lobby panel wall and orb shell.");
|
||||
|
@ -64,7 +69,7 @@ function drawLobby() {
|
|||
url: HIFI_PUBLIC_BUCKET + "models/sets/Lobby/LobbyPrototype/Lobby5_PanelsWithFrames.fbx",
|
||||
position: Vec3.sum(orbPosition, Vec3.multiplyQbyV(towardsMe, panelsCenterShift)),
|
||||
rotation: towardsMe,
|
||||
dimensions: panelsDimensions
|
||||
dimensions: panelsDimensions,
|
||||
};
|
||||
|
||||
var orbShellProps = {
|
||||
|
@ -77,21 +82,23 @@ function drawLobby() {
|
|||
|
||||
avatarStickPosition = MyAvatar.position;
|
||||
|
||||
panelWall = Overlays.addOverlay("model", panelWallProps);
|
||||
panelWall = Overlays.addOverlay("model", panelWallProps);
|
||||
orbShell = Overlays.addOverlay("model", orbShellProps);
|
||||
|
||||
// for HMD wearers, create a reticle in center of screen
|
||||
var CURSOR_SCALE = 0.025;
|
||||
|
||||
reticle = Overlays.addOverlay("billboard", {
|
||||
url: HIFI_PUBLIC_BUCKET + "images/cursor.svg",
|
||||
position: reticlePosition(),
|
||||
ignoreRayIntersection: true,
|
||||
isFacingAvatar: true,
|
||||
alpha: 1.0,
|
||||
scale: CURSOR_SCALE
|
||||
});
|
||||
if (inOculusMode) {
|
||||
var CURSOR_SCALE = 0.025;
|
||||
|
||||
reticle = Overlays.addOverlay("billboard", {
|
||||
url: HIFI_PUBLIC_BUCKET + "images/cursor.svg",
|
||||
position: reticlePosition(),
|
||||
ignoreRayIntersection: true,
|
||||
isFacingAvatar: true,
|
||||
alpha: 1.0,
|
||||
scale: CURSOR_SCALE
|
||||
});
|
||||
}
|
||||
|
||||
// add an attachment on this avatar so other people see them in the lobby
|
||||
MyAvatar.attach(HELMET_ATTACHMENT_URL, "Neck", {x: 0, y: 0, z: 0}, Quat.fromPitchYawRollDegrees(0, 0, 0), 1.15);
|
||||
|
||||
|
@ -125,39 +132,62 @@ function changeLobbyTextures() {
|
|||
Overlays.editOverlay(panelWall, textureProp);
|
||||
}
|
||||
|
||||
var MUSAK_VOLUME = 0.5;
|
||||
|
||||
function playNextMusak() {
|
||||
if (panelWall) {
|
||||
if (currentSound == latinSound) {
|
||||
if (elevatorSound.downloaded) {
|
||||
currentSound = elevatorSound;
|
||||
}
|
||||
} else if (currentSound == elevatorSound) {
|
||||
if (latinSound.downloaded) {
|
||||
currentSound = latinSound;
|
||||
}
|
||||
}
|
||||
|
||||
currentMusakInjector = Audio.playSound(currentSound, { localOnly: true, volume: MUSAK_VOLUME });
|
||||
}
|
||||
}
|
||||
|
||||
function playRandomMusak() {
|
||||
chosenSound = null;
|
||||
currentSound = null;
|
||||
|
||||
if (latinSound.downloaded && elevatorSound.downloaded) {
|
||||
chosenSound = Math.random < 0.5 ? latinSound : elevatorSound;
|
||||
currentSound = Math.random() < 0.5 ? latinSound : elevatorSound;
|
||||
} else if (latinSound.downloaded) {
|
||||
chosenSound = latinSound;
|
||||
currentSound = latinSound;
|
||||
} else if (elevatorSound.downloaded) {
|
||||
chosenSound = elevatorSound;
|
||||
currentSound = elevatorSound;
|
||||
}
|
||||
|
||||
if (chosenSound) {
|
||||
currentMusak = Audio.playSound(chosenSound, { stereo: true, localOnly: true })
|
||||
if (currentSound) {
|
||||
// pick a random number of seconds from 0-10 to offset the musak
|
||||
var secondOffset = Math.random() * 10;
|
||||
currentMusakInjector = Audio.playSound(currentSound, { localOnly: true, secondOffset: secondOffset, volume: MUSAK_VOLUME });
|
||||
} else {
|
||||
currentMusak = null;
|
||||
currentMusakInjector = null;
|
||||
}
|
||||
}
|
||||
|
||||
function cleanupLobby() {
|
||||
Overlays.deleteOverlay(panelWall);
|
||||
Overlays.deleteOverlay(orbShell);
|
||||
Overlays.deleteOverlay(reticle);
|
||||
|
||||
Audio.stopInjector(currentDrone);
|
||||
currentDrone = null;
|
||||
|
||||
Audio.stopInjector(currentMusak);
|
||||
currentMusak = null;
|
||||
if (reticle) {
|
||||
Overlays.deleteOverlay(reticle);
|
||||
}
|
||||
|
||||
panelWall = false;
|
||||
orbShell = false;
|
||||
reticle = false;
|
||||
|
||||
Audio.stopInjector(currentDrone);
|
||||
currentDrone = null;
|
||||
|
||||
Audio.stopInjector(currentMusakInjector);
|
||||
currentMusakInjector = null;
|
||||
|
||||
locations = {};
|
||||
toggleEnvironmentRendering(true);
|
||||
|
||||
|
@ -218,10 +248,18 @@ function toggleEnvironmentRendering(shouldRender) {
|
|||
|
||||
function update(deltaTime) {
|
||||
maybeCleanupLobby();
|
||||
if (reticle) {
|
||||
Overlays.editOverlay(reticle, {
|
||||
position: reticlePosition()
|
||||
});
|
||||
if (panelWall) {
|
||||
|
||||
if (reticle) {
|
||||
Overlays.editOverlay(reticle, {
|
||||
position: reticlePosition()
|
||||
});
|
||||
}
|
||||
|
||||
// if the reticle is up then we may need to play the next musak
|
||||
if (!Audio.isInjectorPlaying(currentMusakInjector)) {
|
||||
playNextMusak();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -39,6 +39,9 @@ Script.include("libraries/gridTool.js");
|
|||
var grid = Grid();
|
||||
gridTool = GridTool({ horizontalGrid: grid });
|
||||
|
||||
Script.include("libraries/entityList.js");
|
||||
var entityListTool = EntityListTool();
|
||||
|
||||
selectionManager.addEventListener(selectionDisplay.updateHandles);
|
||||
|
||||
var windowDimensions = Controller.getViewportDimensions();
|
||||
|
@ -283,6 +286,7 @@ var toolBar = (function () {
|
|||
if (activeButton === toolBar.clicked(clickedOverlay)) {
|
||||
isActive = !isActive;
|
||||
if (!isActive) {
|
||||
entityListTool.setVisible(false);
|
||||
gridTool.setVisible(false);
|
||||
grid.setEnabled(false);
|
||||
propertiesTool.setVisible(false);
|
||||
|
@ -290,6 +294,7 @@ var toolBar = (function () {
|
|||
cameraManager.disable();
|
||||
} else {
|
||||
cameraManager.enable();
|
||||
entityListTool.setVisible(true);
|
||||
gridTool.setVisible(true);
|
||||
grid.setEnabled(true);
|
||||
propertiesTool.setVisible(true);
|
||||
|
|
|
@ -12,13 +12,12 @@
|
|||
Script.include("libraries/globals.js");
|
||||
|
||||
var modelURL = HIFI_PUBLIC_BUCKET + "models/entities/radio/Speakers.fbx";
|
||||
var soundURL = HIFI_PUBLIC_BUCKET + "sounds/FamilyStereo.raw";
|
||||
var soundURL = HIFI_PUBLIC_BUCKET + "sounds/family.stereo.raw";
|
||||
|
||||
var AudioRotationOffset = Quat.fromPitchYawRollDegrees(0, -90, 0);
|
||||
var audioOptions = {
|
||||
volume: 0.5,
|
||||
loop: true,
|
||||
stereo: true
|
||||
loop: true
|
||||
}
|
||||
|
||||
var injector = null;
|
||||
|
|
|
@ -604,7 +604,7 @@ void Application::initializeGL() {
|
|||
}
|
||||
|
||||
// update before the first render
|
||||
update(1.f / _fps);
|
||||
update(1.0f / _fps);
|
||||
|
||||
InfoView::showFirstTime(INFO_HELP_PATH);
|
||||
}
|
||||
|
@ -668,7 +668,7 @@ void Application::paintGL() {
|
|||
|
||||
// Update camera position
|
||||
if (!OculusManager::isConnected()) {
|
||||
_myCamera.update(1.f / _fps);
|
||||
_myCamera.update(1.0f / _fps);
|
||||
}
|
||||
|
||||
// Note: whichCamera is used to pick between the normal camera myCamera for our
|
||||
|
@ -693,7 +693,7 @@ void Application::paintGL() {
|
|||
|
||||
_viewFrustumOffsetCamera.setRotation(_myCamera.getRotation() * frustumRotation);
|
||||
|
||||
_viewFrustumOffsetCamera.update(1.f/_fps);
|
||||
_viewFrustumOffsetCamera.update(1.0f/_fps);
|
||||
whichCamera = &_viewFrustumOffsetCamera;
|
||||
}
|
||||
|
||||
|
@ -712,7 +712,7 @@ void Application::paintGL() {
|
|||
} else {
|
||||
OculusManager::display(_myAvatar->getWorldAlignedOrientation(), _myAvatar->getDefaultEyePosition(), *whichCamera);
|
||||
}
|
||||
_myCamera.update(1.f / _fps);
|
||||
_myCamera.update(1.0f / _fps);
|
||||
|
||||
} else if (TV3DManager::isConnected()) {
|
||||
|
||||
|
@ -918,7 +918,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
if (!_myAvatar->getDriveKeys(UP)) {
|
||||
_myAvatar->jump();
|
||||
}
|
||||
_myAvatar->setDriveKeys(UP, 1.f);
|
||||
_myAvatar->setDriveKeys(UP, 1.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_Asterisk:
|
||||
|
@ -927,14 +927,14 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
|
||||
case Qt::Key_C:
|
||||
case Qt::Key_PageDown:
|
||||
_myAvatar->setDriveKeys(DOWN, 1.f);
|
||||
_myAvatar->setDriveKeys(DOWN, 1.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_W:
|
||||
if (isOption && !isShifted && !isMeta) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::Wireframe);
|
||||
} else {
|
||||
_myAvatar->setDriveKeys(FWD, 1.f);
|
||||
_myAvatar->setDriveKeys(FWD, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -946,7 +946,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
} else if (!isOption && !isShifted && isMeta) {
|
||||
takeSnapshot();
|
||||
} else {
|
||||
_myAvatar->setDriveKeys(BACK, 1.f);
|
||||
_myAvatar->setDriveKeys(BACK, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -964,13 +964,13 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
if (isShifted) {
|
||||
Menu::getInstance()->triggerOption(MenuOption::Atmosphere);
|
||||
} else {
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, 1.f);
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_D:
|
||||
if (!isMeta) {
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, 1.f);
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -998,7 +998,7 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
_raiseMirror += 0.05f;
|
||||
}
|
||||
} else {
|
||||
_myAvatar->setDriveKeys(isShifted ? UP : FWD, 1.f);
|
||||
_myAvatar->setDriveKeys(isShifted ? UP : FWD, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1010,23 +1010,23 @@ void Application::keyPressEvent(QKeyEvent* event) {
|
|||
_raiseMirror -= 0.05f;
|
||||
}
|
||||
} else {
|
||||
_myAvatar->setDriveKeys(isShifted ? DOWN : BACK, 1.f);
|
||||
_myAvatar->setDriveKeys(isShifted ? DOWN : BACK, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_Left:
|
||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
_rotateMirror += PI / 20.f;
|
||||
_rotateMirror += PI / 20.0f;
|
||||
} else {
|
||||
_myAvatar->setDriveKeys(isShifted ? LEFT : ROT_LEFT, 1.f);
|
||||
_myAvatar->setDriveKeys(isShifted ? LEFT : ROT_LEFT, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
case Qt::Key_Right:
|
||||
if (_myCamera.getMode() == CAMERA_MODE_MIRROR) {
|
||||
_rotateMirror -= PI / 20.f;
|
||||
_rotateMirror -= PI / 20.0f;
|
||||
} else {
|
||||
_myAvatar->setDriveKeys(isShifted ? RIGHT : ROT_RIGHT, 1.f);
|
||||
_myAvatar->setDriveKeys(isShifted ? RIGHT : ROT_RIGHT, 1.0f);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -1177,48 +1177,48 @@ void Application::keyReleaseEvent(QKeyEvent* event) {
|
|||
switch (event->key()) {
|
||||
case Qt::Key_E:
|
||||
case Qt::Key_PageUp:
|
||||
_myAvatar->setDriveKeys(UP, 0.f);
|
||||
_myAvatar->setDriveKeys(UP, 0.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_C:
|
||||
case Qt::Key_PageDown:
|
||||
_myAvatar->setDriveKeys(DOWN, 0.f);
|
||||
_myAvatar->setDriveKeys(DOWN, 0.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_W:
|
||||
_myAvatar->setDriveKeys(FWD, 0.f);
|
||||
_myAvatar->setDriveKeys(FWD, 0.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_S:
|
||||
_myAvatar->setDriveKeys(BACK, 0.f);
|
||||
_myAvatar->setDriveKeys(BACK, 0.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_A:
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, 0.f);
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, 0.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_D:
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, 0.f);
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, 0.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_Up:
|
||||
_myAvatar->setDriveKeys(FWD, 0.f);
|
||||
_myAvatar->setDriveKeys(UP, 0.f);
|
||||
_myAvatar->setDriveKeys(FWD, 0.0f);
|
||||
_myAvatar->setDriveKeys(UP, 0.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_Down:
|
||||
_myAvatar->setDriveKeys(BACK, 0.f);
|
||||
_myAvatar->setDriveKeys(DOWN, 0.f);
|
||||
_myAvatar->setDriveKeys(BACK, 0.0f);
|
||||
_myAvatar->setDriveKeys(DOWN, 0.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_Left:
|
||||
_myAvatar->setDriveKeys(LEFT, 0.f);
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, 0.f);
|
||||
_myAvatar->setDriveKeys(LEFT, 0.0f);
|
||||
_myAvatar->setDriveKeys(ROT_LEFT, 0.0f);
|
||||
break;
|
||||
|
||||
case Qt::Key_Right:
|
||||
_myAvatar->setDriveKeys(RIGHT, 0.f);
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, 0.f);
|
||||
_myAvatar->setDriveKeys(RIGHT, 0.0f);
|
||||
_myAvatar->setDriveKeys(ROT_RIGHT, 0.0f);
|
||||
break;
|
||||
case Qt::Key_Control:
|
||||
case Qt::Key_Shift:
|
||||
|
@ -1522,7 +1522,7 @@ void Application::idle() {
|
|||
PerformanceTimer perfTimer("update");
|
||||
PerformanceWarning warn(showWarnings, "Application::idle()... update()");
|
||||
const float BIGGEST_DELTA_TIME_SECS = 0.25f;
|
||||
update(glm::clamp((float)timeSinceLastUpdate / 1000.f, 0.f, BIGGEST_DELTA_TIME_SECS));
|
||||
update(glm::clamp((float)timeSinceLastUpdate / 1000.0f, 0.0f, BIGGEST_DELTA_TIME_SECS));
|
||||
}
|
||||
{
|
||||
PerformanceTimer perfTimer("updateGL");
|
||||
|
@ -1653,8 +1653,8 @@ void Application::makeVoxel(glm::vec3 position,
|
|||
}
|
||||
|
||||
glm::vec3 Application::getMouseVoxelWorldCoordinates(const VoxelDetail& mouseVoxel) {
|
||||
return glm::vec3((mouseVoxel.x + mouseVoxel.s / 2.f) * TREE_SCALE, (mouseVoxel.y + mouseVoxel.s / 2.f) * TREE_SCALE,
|
||||
(mouseVoxel.z + mouseVoxel.s / 2.f) * TREE_SCALE);
|
||||
return glm::vec3((mouseVoxel.x + mouseVoxel.s / 2.0f) * TREE_SCALE, (mouseVoxel.y + mouseVoxel.s / 2.0f) * TREE_SCALE,
|
||||
(mouseVoxel.z + mouseVoxel.s / 2.0f) * TREE_SCALE);
|
||||
}
|
||||
|
||||
FaceTracker* Application::getActiveFaceTracker() {
|
||||
|
@ -1867,7 +1867,7 @@ void Application::init() {
|
|||
3.0f * TREE_SCALE / 2.0f));
|
||||
_sharedVoxelSystemViewFrustum.setNearClip(TREE_SCALE / 2.0f);
|
||||
_sharedVoxelSystemViewFrustum.setFarClip(3.0f * TREE_SCALE / 2.0f);
|
||||
_sharedVoxelSystemViewFrustum.setFieldOfView(90.f);
|
||||
_sharedVoxelSystemViewFrustum.setFieldOfView(90.0f);
|
||||
_sharedVoxelSystemViewFrustum.setOrientation(glm::quat());
|
||||
_sharedVoxelSystemViewFrustum.calculate();
|
||||
_sharedVoxelSystem.setViewFrustum(&_sharedVoxelSystemViewFrustum);
|
||||
|
@ -2163,7 +2163,7 @@ void Application::updateMyAvatarLookAtPosition() {
|
|||
} else {
|
||||
// I am not looking at anyone else, so just look forward
|
||||
lookAtSpot = _myAvatar->getHead()->getEyePosition() +
|
||||
(_myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.f, 0.f, -TREE_SCALE));
|
||||
(_myAvatar->getHead()->getFinalOrientationInWorldFrame() * glm::vec3(0.0f, 0.0f, -TREE_SCALE));
|
||||
}
|
||||
}
|
||||
//
|
||||
|
@ -2673,6 +2673,14 @@ void Application::queryOctree(NodeType_t serverType, PacketType packetType, Node
|
|||
}
|
||||
}
|
||||
|
||||
bool Application::isHMDMode() const {
|
||||
if (OculusManager::isConnected()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////////
|
||||
// loadViewFrustum()
|
||||
//
|
||||
|
@ -3201,12 +3209,12 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
|||
if (billboard) {
|
||||
_mirrorCamera.setFieldOfView(BILLBOARD_FIELD_OF_VIEW); // degees
|
||||
_mirrorCamera.setPosition(_myAvatar->getPosition() +
|
||||
_myAvatar->getOrientation() * glm::vec3(0.f, 0.f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale());
|
||||
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * BILLBOARD_DISTANCE * _myAvatar->getScale());
|
||||
|
||||
} else if (_rearMirrorTools->getZoomLevel() == BODY) {
|
||||
_mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees
|
||||
_mirrorCamera.setPosition(_myAvatar->getChestPosition() +
|
||||
_myAvatar->getOrientation() * glm::vec3(0.f, 0.f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale());
|
||||
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_BODY_DISTANCE * _myAvatar->getScale());
|
||||
|
||||
} else { // HEAD zoom level
|
||||
_mirrorCamera.setFieldOfView(MIRROR_FIELD_OF_VIEW); // degrees
|
||||
|
@ -3214,11 +3222,11 @@ void Application::renderRearViewMirror(const QRect& region, bool billboard) {
|
|||
// as a hack until we have a better way of dealing with coordinate precision issues, reposition the
|
||||
// face/body so that the average eye position lies at the origin
|
||||
eyeRelativeCamera = true;
|
||||
_mirrorCamera.setPosition(_myAvatar->getOrientation() * glm::vec3(0.f, 0.f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale());
|
||||
_mirrorCamera.setPosition(_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale());
|
||||
|
||||
} else {
|
||||
_mirrorCamera.setPosition(_myAvatar->getHead()->getEyePosition() +
|
||||
_myAvatar->getOrientation() * glm::vec3(0.f, 0.f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale());
|
||||
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, -1.0f) * MIRROR_REARVIEW_DISTANCE * _myAvatar->getScale());
|
||||
}
|
||||
}
|
||||
_mirrorCamera.setAspectRatio((float)region.width() / region.height());
|
||||
|
@ -4214,7 +4222,7 @@ void Application::toggleLogDialog() {
|
|||
}
|
||||
|
||||
void Application::initAvatarAndViewFrustum() {
|
||||
updateMyAvatar(0.f);
|
||||
updateMyAvatar(0.0f);
|
||||
}
|
||||
|
||||
void Application::checkVersion() {
|
||||
|
@ -4388,7 +4396,7 @@ unsigned int Application::getRenderTargetFramerate() const {
|
|||
|
||||
float Application::getRenderResolutionScale() const {
|
||||
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionOne)) {
|
||||
return 1.f;
|
||||
return 1.0f;
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionTwoThird)) {
|
||||
return 0.666f;
|
||||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionHalf)) {
|
||||
|
@ -4398,6 +4406,6 @@ float Application::getRenderResolutionScale() const {
|
|||
} else if (Menu::getInstance()->isOptionChecked(MenuOption::RenderResolutionQuarter)) {
|
||||
return 0.25f;
|
||||
} else {
|
||||
return 1.f;
|
||||
return 1.0f;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -316,6 +316,11 @@ public:
|
|||
|
||||
void registerScriptEngineWithApplicationServices(ScriptEngine* scriptEngine);
|
||||
|
||||
// the isHMDmode is true whenever we use the interface from an HMD and not a standard flat display
|
||||
// rendering of several elements depend on that
|
||||
// TODO: carry that information on the Camera as a setting
|
||||
bool isHMDMode() const;
|
||||
|
||||
signals:
|
||||
|
||||
/// Fired when we're simulating; allows external parties to hook in.
|
||||
|
|
|
@ -81,7 +81,7 @@ public:
|
|||
// setup for audio I/O
|
||||
Audio(QObject* parent = 0);
|
||||
|
||||
float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _noiseGateMeasuredFloor, 0.f); }
|
||||
float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _noiseGateMeasuredFloor, 0.0f); }
|
||||
float getTimeSinceLastClip() const { return _timeSinceLastClip; }
|
||||
float getAudioAverageInputLoudness() const { return _lastInputLoudness; }
|
||||
|
||||
|
|
|
@ -80,14 +80,14 @@ void Environment::renderAtmospheres(Camera& camera) {
|
|||
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.f, -1.f, 0.f);
|
||||
const glm::vec3 DEFAULT_GRAVITY(0.0f, -1.0f, 0.0f);
|
||||
glm::vec3 gravity(DEFAULT_GRAVITY);
|
||||
float DEFAULT_SURFACE_RADIUS = 30.f;
|
||||
float DEFAULT_SURFACE_RADIUS = 30.0f;
|
||||
float gravityStrength;
|
||||
|
||||
// Weaken gravity with height
|
||||
if (position.y > 0.f) {
|
||||
gravityStrength = 1.f / powf((DEFAULT_SURFACE_RADIUS + position.y) / DEFAULT_SURFACE_RADIUS, 2.f);
|
||||
if (position.y > 0.0f) {
|
||||
gravityStrength = 1.0f / powf((DEFAULT_SURFACE_RADIUS + position.y) / DEFAULT_SURFACE_RADIUS, 2.0f);
|
||||
gravity *= gravityStrength;
|
||||
}
|
||||
|
||||
|
@ -103,7 +103,7 @@ glm::vec3 Environment::getGravity (const glm::vec3& position) {
|
|||
gravity += glm::normalize(vector) * environmentData.getGravity();
|
||||
} else {
|
||||
// Outside a planet, the gravity falls off with distance
|
||||
gravityStrength = 1.f / powf(glm::length(vector) / surfaceRadius, 2.f);
|
||||
gravityStrength = 1.0f / powf(glm::length(vector) / surfaceRadius, 2.0f);
|
||||
gravity += glm::normalize(vector) * environmentData.getGravity() * gravityStrength;
|
||||
}
|
||||
}
|
||||
|
@ -261,7 +261,7 @@ void Environment::renderAtmosphere(Camera& camera, const EnvironmentData& data)
|
|||
|
||||
glDepthMask(GL_FALSE);
|
||||
glDisable(GL_DEPTH_TEST);
|
||||
Application::getInstance()->getGeometryCache()->renderSphere(1.f, 100, 50); //Draw a unit sphere
|
||||
Application::getInstance()->getGeometryCache()->renderSphere(1.0f, 100, 50); //Draw a unit sphere
|
||||
glDepthMask(GL_TRUE);
|
||||
|
||||
program->release();
|
||||
|
|
|
@ -78,7 +78,7 @@ Hair::Hair(int strands,
|
|||
}
|
||||
_hairOriginalPosition[vertexIndex] = _hairLastPosition[vertexIndex] = _hairPosition[vertexIndex] = thisVertex;
|
||||
|
||||
_hairQuadDelta[vertexIndex] = glm::vec3(cos(strandAngle) * _hairThickness, 0.f, sin(strandAngle) * _hairThickness);
|
||||
_hairQuadDelta[vertexIndex] = glm::vec3(cos(strandAngle) * _hairThickness, 0.0f, sin(strandAngle) * _hairThickness);
|
||||
_hairQuadDelta[vertexIndex] *= ((float)link / _links);
|
||||
_hairNormals[vertexIndex] = glm::normalize(randVector());
|
||||
if (randFloat() < elevation / PI_OVER_TWO) {
|
||||
|
@ -155,7 +155,7 @@ void Hair::simulate(float deltaTime) {
|
|||
|
||||
// Add stiffness to return to original position
|
||||
_hairPosition[vertexIndex] += (_hairOriginalPosition[vertexIndex] - _hairPosition[vertexIndex])
|
||||
* powf(1.f - (float)link / _links, 2.f) * HAIR_STIFFNESS;
|
||||
* powf(1.0f - (float)link / _links, 2.0f) * HAIR_STIFFNESS;
|
||||
|
||||
// Add angular acceleration
|
||||
const float ANGULAR_VELOCITY_MIN = 0.001f;
|
||||
|
@ -163,30 +163,30 @@ void Hair::simulate(float deltaTime) {
|
|||
glm::vec3 yawVector = _hairPosition[vertexIndex];
|
||||
glm::vec3 angularVelocity = _angularVelocity * HAIR_ANGULAR_VELOCITY_COUPLING;
|
||||
glm::vec3 angularAcceleration = _angularAcceleration * HAIR_ANGULAR_ACCELERATION_COUPLING;
|
||||
yawVector.y = 0.f;
|
||||
yawVector.y = 0.0f;
|
||||
if (glm::length(yawVector) > EPSILON) {
|
||||
float radius = glm::length(yawVector);
|
||||
yawVector = glm::normalize(yawVector);
|
||||
float angle = atan2f(yawVector.x, -yawVector.z) + PI;
|
||||
glm::vec3 delta = glm::vec3(-1.f, 0.f, 0.f) * glm::angleAxis(angle, glm::vec3(0, 1, 0));
|
||||
glm::vec3 delta = glm::vec3(-1.0f, 0.0f, 0.0f) * glm::angleAxis(angle, glm::vec3(0, 1, 0));
|
||||
_hairPosition[vertexIndex] -= delta * radius * (angularVelocity.y - angularAcceleration.y) * deltaTime;
|
||||
}
|
||||
glm::vec3 pitchVector = _hairPosition[vertexIndex];
|
||||
pitchVector.x = 0.f;
|
||||
pitchVector.x = 0.0f;
|
||||
if (glm::length(pitchVector) > EPSILON) {
|
||||
float radius = glm::length(pitchVector);
|
||||
pitchVector = glm::normalize(pitchVector);
|
||||
float angle = atan2f(pitchVector.y, -pitchVector.z) + PI;
|
||||
glm::vec3 delta = glm::vec3(0.0f, 1.0f, 0.f) * glm::angleAxis(angle, glm::vec3(1, 0, 0));
|
||||
glm::vec3 delta = glm::vec3(0.0f, 1.0f, 0.0f) * glm::angleAxis(angle, glm::vec3(1, 0, 0));
|
||||
_hairPosition[vertexIndex] -= delta * radius * (angularVelocity.x - angularAcceleration.x) * deltaTime;
|
||||
}
|
||||
glm::vec3 rollVector = _hairPosition[vertexIndex];
|
||||
rollVector.z = 0.f;
|
||||
rollVector.z = 0.0f;
|
||||
if (glm::length(rollVector) > EPSILON) {
|
||||
float radius = glm::length(rollVector);
|
||||
pitchVector = glm::normalize(rollVector);
|
||||
float angle = atan2f(rollVector.x, rollVector.y) + PI;
|
||||
glm::vec3 delta = glm::vec3(-1.0f, 0.0f, 0.f) * glm::angleAxis(angle, glm::vec3(0, 0, 1));
|
||||
glm::vec3 delta = glm::vec3(-1.0f, 0.0f, 0.0f) * glm::angleAxis(angle, glm::vec3(0, 0, 1));
|
||||
_hairPosition[vertexIndex] -= delta * radius * (angularVelocity.z - angularAcceleration.z) * deltaTime;
|
||||
}
|
||||
}
|
||||
|
@ -216,16 +216,16 @@ void Hair::render() {
|
|||
const float HAIR_SETBACK = 0.0f;
|
||||
int sparkleIndex = (int) (randFloat() * SPARKLE_EVERY);
|
||||
glPushMatrix();
|
||||
glTranslatef(0.f, 0.f, HAIR_SETBACK);
|
||||
glTranslatef(0.0f, 0.0f, HAIR_SETBACK);
|
||||
glBegin(GL_QUADS);
|
||||
for (int strand = 0; strand < _strands; strand++) {
|
||||
for (int link = 0; link < _links - 1; link++) {
|
||||
int vertexIndex = strand * _links + link;
|
||||
glm::vec3 thisColor = _hairColors[vertexIndex];
|
||||
if (sparkleIndex % SPARKLE_EVERY == 0) {
|
||||
thisColor.x += (1.f - thisColor.x) * loudnessFactor;
|
||||
thisColor.y += (1.f - thisColor.y) * loudnessFactor;
|
||||
thisColor.z += (1.f - thisColor.z) * loudnessFactor;
|
||||
thisColor.x += (1.0f - thisColor.x) * loudnessFactor;
|
||||
thisColor.y += (1.0f - thisColor.y) * loudnessFactor;
|
||||
thisColor.z += (1.0f - thisColor.z) * loudnessFactor;
|
||||
}
|
||||
glColor3fv(&thisColor.x);
|
||||
glNormal3fv(&_hairNormals[vertexIndex].x);
|
||||
|
|
|
@ -297,6 +297,8 @@ Menu::Menu() :
|
|||
avatar, SLOT(updateMotionBehavior()));
|
||||
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::StandOnNearbyFloors, 0, true,
|
||||
avatar, SLOT(updateMotionBehavior()));
|
||||
addCheckableActionToQMenuAndActionHash(avatarMenu, MenuOption::ShiftHipsForIdleAnimations, 0, false,
|
||||
avatar, SLOT(updateMotionBehavior()));
|
||||
|
||||
QMenu* collisionsMenu = avatarMenu->addMenu("Collide With...");
|
||||
addCheckableActionToQMenuAndActionHash(collisionsMenu, MenuOption::CollideAsRagdoll, 0, false,
|
||||
|
|
|
@ -484,6 +484,7 @@ namespace MenuOption {
|
|||
const QString SixenseMouseInput = "Enable Sixense Mouse Input";
|
||||
const QString SixenseLasers = "Enable Sixense UI Lasers";
|
||||
const QString StandOnNearbyFloors = "Stand on nearby floors";
|
||||
const QString ShiftHipsForIdleAnimations = "Shift hips for idle animations";
|
||||
const QString Stars = "Stars";
|
||||
const QString Stats = "Stats";
|
||||
const QString StereoAudio = "Stereo Audio";
|
||||
|
|
|
@ -23,7 +23,7 @@
|
|||
void applyStaticFriction(float deltaTime, glm::vec3& velocity, float maxVelocity, float strength) {
|
||||
float v = glm::length(velocity);
|
||||
if (v < maxVelocity) {
|
||||
velocity *= glm::clamp((1.0f - deltaTime * strength * (1.f - v / maxVelocity)), 0.0f, 1.0f);
|
||||
velocity *= glm::clamp((1.0f - deltaTime * strength * (1.0f - v / maxVelocity)), 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -32,10 +32,10 @@ void applyStaticFriction(float deltaTime, glm::vec3& velocity, float maxVelocity
|
|||
//
|
||||
|
||||
void applyDamping(float deltaTime, glm::vec3& velocity, float linearStrength, float squaredStrength) {
|
||||
if (squaredStrength == 0.f) {
|
||||
velocity *= glm::clamp(1.f - deltaTime * linearStrength, 0.f, 1.f);
|
||||
if (squaredStrength == 0.0f) {
|
||||
velocity *= glm::clamp(1.0f - deltaTime * linearStrength, 0.0f, 1.0f);
|
||||
} else {
|
||||
velocity *= glm::clamp(1.f - deltaTime * (linearStrength + glm::length(velocity) * squaredStrength), 0.f, 1.f);
|
||||
velocity *= glm::clamp(1.0f - deltaTime * (linearStrength + glm::length(velocity) * squaredStrength), 0.0f, 1.0f);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -65,7 +65,7 @@ void renderWorldBox() {
|
|||
glVertex3f(TREE_SCALE, 0, 0);
|
||||
glEnd();
|
||||
// Draw meter markers along the 3 axis to help with measuring things
|
||||
const float MARKER_DISTANCE = 1.f;
|
||||
const float MARKER_DISTANCE = 1.0f;
|
||||
const float MARKER_RADIUS = 0.05f;
|
||||
glEnable(GL_LIGHTING);
|
||||
glPushMatrix();
|
||||
|
@ -93,7 +93,7 @@ void renderWorldBox() {
|
|||
|
||||
// Return a random vector of average length 1
|
||||
const glm::vec3 randVector() {
|
||||
return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.f;
|
||||
return glm::vec3(randFloat() - 0.5f, randFloat() - 0.5f, randFloat() - 0.5f) * 2.0f;
|
||||
}
|
||||
|
||||
static TextRenderer* textRenderer(int mono) {
|
||||
|
@ -125,7 +125,7 @@ void drawText(int x, int y, float scale, float radians, int mono,
|
|||
glTranslatef(static_cast<float>(x), static_cast<float>(y), 0.0f);
|
||||
glColor3fv(color);
|
||||
glRotated(double(radians * DEGREES_PER_RADIAN), 0.0, 0.0, 1.0);
|
||||
glScalef(scale / 0.1f, scale / 0.1f, 1.f);
|
||||
glScalef(scale / 0.1f, scale / 0.1f, 1.0f);
|
||||
textRenderer(mono)->draw(0, 0, string);
|
||||
glPopMatrix();
|
||||
}
|
||||
|
|
|
@ -655,7 +655,10 @@ void Avatar::renderDisplayName() {
|
|||
if (_displayName.isEmpty() || _displayNameAlpha == 0.0f) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
// which viewing mode?
|
||||
bool inHMD = Application::getInstance()->isHMDMode();
|
||||
|
||||
glDisable(GL_LIGHTING);
|
||||
|
||||
glPushMatrix();
|
||||
|
@ -664,18 +667,19 @@ void Avatar::renderDisplayName() {
|
|||
glTranslatef(textPosition.x, textPosition.y, textPosition.z);
|
||||
|
||||
// we need "always facing camera": we must remove the camera rotation from the stack
|
||||
glm::quat rotation = Application::getInstance()->getCamera()->getRotation();
|
||||
|
||||
|
||||
glm::vec3 frontAxis(1.f, 0.f, 0.f);
|
||||
frontAxis = glm::rotate(rotation, frontAxis);
|
||||
frontAxis = glm::normalize(glm::vec3(frontAxis.x, 0.f, frontAxis.z));
|
||||
glm::vec3 frontAxis(0.0f, 0.0f, 1.0f);
|
||||
if (inHMD) {
|
||||
glm::vec3 camPosition = Application::getInstance()->getCamera()->getPosition();
|
||||
frontAxis = camPosition - textPosition;
|
||||
} else {
|
||||
glm::quat rotation = Application::getInstance()->getCamera()->getRotation();
|
||||
frontAxis = glm::rotate(rotation, frontAxis);
|
||||
}
|
||||
|
||||
// TODO : test this secodn solution which should be better wfor occulus
|
||||
//glm::vec3 camPosition = Application::getInstance()->getCamera()->getPosition();
|
||||
//glm::vec3 frontAxis = camPosition - textPosition;
|
||||
//frontAxis = glm::normalize(glm::vec3(frontAxis.z, 0.f, -frontAxis.x));
|
||||
|
||||
float angle = acos(frontAxis.x) * ((frontAxis.z < 0) ? 1.f : -1.f);
|
||||
frontAxis = glm::normalize(glm::vec3(frontAxis.z, 0.0f, -frontAxis.x));
|
||||
float angle = acos(frontAxis.x) * ((frontAxis.z < 0) ? 1.0f : -1.0f);
|
||||
glRotatef(glm::degrees(angle), 0.0f, 1.0f, 0.0f);
|
||||
|
||||
// We need to compute the scale factor such as the text remains with fixed size respect to window coordinates
|
||||
|
@ -706,10 +710,16 @@ void Avatar::renderDisplayName() {
|
|||
|
||||
if (success) {
|
||||
double textWindowHeight = abs(result1[1] - result0[1]);
|
||||
float scaleFactor = Application::getInstance()->getRenderResolutionScale() * // Scale compensate for the resolution
|
||||
QApplication::desktop()->windowHandle()->devicePixelRatio() * // And the device pixel ratio
|
||||
// need to scale to compensate for the font resolution due to the device
|
||||
float scaleFactor = QApplication::desktop()->windowHandle()->devicePixelRatio() *
|
||||
((textWindowHeight > EPSILON) ? 1.0f / textWindowHeight : 1.0f);
|
||||
glScalef(scaleFactor, scaleFactor, 1.0);
|
||||
if (inHMD) {
|
||||
const float HMDMODE_NAME_SCALE = 0.65f;
|
||||
scaleFactor *= HMDMODE_NAME_SCALE;
|
||||
} else {
|
||||
scaleFactor *= Application::getInstance()->getRenderResolutionScale();
|
||||
}
|
||||
glScalef(scaleFactor, scaleFactor, 1.0);
|
||||
|
||||
glScalef(1.0f, -1.0f, 1.0f); // TextRenderer::draw paints the text upside down in y axis
|
||||
|
||||
|
@ -787,7 +797,10 @@ void Avatar::setSkeletonOffset(const glm::vec3& offset) {
|
|||
}
|
||||
|
||||
glm::vec3 Avatar::getSkeletonPosition() const {
|
||||
return _position + _skeletonOffset;
|
||||
// The avatar is rotated PI about the yAxis, so we have to correct for it
|
||||
// to get the skeleton offset contribution in the world-frame.
|
||||
const glm::quat FLIP = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
return _position + getOrientation() * FLIP * _skeletonOffset;
|
||||
}
|
||||
|
||||
QVector<glm::quat> Avatar::getJointRotations() const {
|
||||
|
|
|
@ -68,7 +68,7 @@ void Hand::collideAgainstAvatar(Avatar* avatar, bool isMyHand) {
|
|||
skeletonModel.getHandShapes(jointIndex, shapes);
|
||||
|
||||
if (avatar->findCollisions(shapes, handCollisions)) {
|
||||
glm::vec3 totalPenetration(0.f);
|
||||
glm::vec3 totalPenetration(0.0f);
|
||||
glm::vec3 averageContactPoint;
|
||||
for (int j = 0; j < handCollisions.size(); ++j) {
|
||||
CollisionInfo* collision = handCollisions.getCollision(j);
|
||||
|
@ -151,7 +151,7 @@ void Hand::renderHandTargets(bool isMine) {
|
|||
|
||||
const float collisionRadius = 0.05f;
|
||||
glColor4f(0.5f,0.5f,0.5f, alpha);
|
||||
glutWireSphere(collisionRadius, 10.f, 10.f);
|
||||
glutWireSphere(collisionRadius, 10.0f, 10.0f);
|
||||
glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -45,11 +45,11 @@ Head::Head(Avatar* owningAvatar) :
|
|||
_leftEyeBlinkVelocity(0.0f),
|
||||
_rightEyeBlinkVelocity(0.0f),
|
||||
_timeWithoutTalking(0.0f),
|
||||
_deltaPitch(0.f),
|
||||
_deltaYaw(0.f),
|
||||
_deltaRoll(0.f),
|
||||
_deltaLeanSideways(0.f),
|
||||
_deltaLeanForward(0.f),
|
||||
_deltaPitch(0.0f),
|
||||
_deltaYaw(0.0f),
|
||||
_deltaRoll(0.0f),
|
||||
_deltaLeanSideways(0.0f),
|
||||
_deltaLeanForward(0.0f),
|
||||
_isCameraMoving(false),
|
||||
_isLookingAtMe(false),
|
||||
_faceModel(this)
|
||||
|
@ -86,7 +86,7 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
}
|
||||
// Update audio trailing average for rendering facial animations
|
||||
const float AUDIO_AVERAGING_SECS = 0.05f;
|
||||
const float AUDIO_LONG_TERM_AVERAGING_SECS = 30.f;
|
||||
const float AUDIO_LONG_TERM_AVERAGING_SECS = 30.0f;
|
||||
_averageLoudness = glm::mix(_averageLoudness, _audioLoudness, glm::min(deltaTime / AUDIO_AVERAGING_SECS, 1.0f));
|
||||
|
||||
if (_longTermAverageLoudness == -1.0) {
|
||||
|
@ -204,6 +204,8 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
_mouth3,
|
||||
_mouth4,
|
||||
_blendshapeCoefficients);
|
||||
} else {
|
||||
_saccade = glm::vec3();
|
||||
}
|
||||
|
||||
if (!isMine) {
|
||||
|
@ -223,7 +225,7 @@ void Head::simulate(float deltaTime, bool isMine, bool billboard) {
|
|||
void Head::relaxLean(float deltaTime) {
|
||||
// restore rotation, lean to neutral positions
|
||||
const float LEAN_RELAXATION_PERIOD = 0.25f; // seconds
|
||||
float relaxationFactor = 1.f - glm::min(deltaTime / LEAN_RELAXATION_PERIOD, 1.f);
|
||||
float relaxationFactor = 1.0f - glm::min(deltaTime / LEAN_RELAXATION_PERIOD, 1.0f);
|
||||
_deltaYaw *= relaxationFactor;
|
||||
_deltaPitch *= relaxationFactor;
|
||||
_deltaRoll *= relaxationFactor;
|
||||
|
@ -276,7 +278,7 @@ glm::quat Head::getCameraOrientation () const {
|
|||
return getOrientation();
|
||||
}
|
||||
Avatar* owningAvatar = static_cast<Avatar*>(_owningAvatar);
|
||||
return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.f, 0.0f)));
|
||||
return owningAvatar->getWorldAlignedOrientation() * glm::quat(glm::radians(glm::vec3(_basePitch, 0.0f, 0.0f)));
|
||||
}
|
||||
|
||||
glm::quat Head::getEyeRotation(const glm::vec3& eyePosition) const {
|
||||
|
@ -323,13 +325,13 @@ void Head::renderLookatVectors(glm::vec3 leftEyePosition, glm::vec3 rightEyePosi
|
|||
|
||||
glLineWidth(2.0);
|
||||
glBegin(GL_LINES);
|
||||
glColor4f(0.2f, 0.2f, 0.2f, 1.f);
|
||||
glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
glVertex3f(leftEyePosition.x, leftEyePosition.y, leftEyePosition.z);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.f);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
glVertex3f(lookatPosition.x, lookatPosition.y, lookatPosition.z);
|
||||
glColor4f(0.2f, 0.2f, 0.2f, 1.f);
|
||||
glColor4f(0.2f, 0.2f, 0.2f, 1.0f);
|
||||
glVertex3f(rightEyePosition.x, rightEyePosition.y, rightEyePosition.z);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.f);
|
||||
glColor4f(1.0f, 1.0f, 1.0f, 0.0f);
|
||||
glVertex3f(lookatPosition.x, lookatPosition.y, lookatPosition.z);
|
||||
glEnd();
|
||||
|
||||
|
|
|
@ -89,6 +89,7 @@ MyAvatar::MyAvatar() :
|
|||
_billboardValid(false),
|
||||
_physicsSimulation(),
|
||||
_voxelShapeManager(),
|
||||
_feetTouchFloor(true),
|
||||
_isLookingAtLeftEye(true)
|
||||
{
|
||||
ShapeCollider::initDispatchTable();
|
||||
|
@ -115,7 +116,7 @@ QByteArray MyAvatar::toByteArray() {
|
|||
if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT) {
|
||||
// fake the avatar position that is sent up to the AvatarMixer
|
||||
glm::vec3 oldPosition = _position;
|
||||
_position += _skeletonOffset;
|
||||
_position = getSkeletonPosition();
|
||||
QByteArray array = AvatarData::toByteArray();
|
||||
// copy the correct position back
|
||||
_position = oldPosition;
|
||||
|
@ -132,8 +133,8 @@ void MyAvatar::reset() {
|
|||
setThrust(glm::vec3(0.0f));
|
||||
// Reset the pitch and roll components of the avatar's orientation, preserve yaw direction
|
||||
glm::vec3 eulers = safeEulerAngles(getOrientation());
|
||||
eulers.x = 0.f;
|
||||
eulers.z = 0.f;
|
||||
eulers.x = 0.0f;
|
||||
eulers.z = 0.0f;
|
||||
setOrientation(glm::quat(eulers));
|
||||
}
|
||||
|
||||
|
@ -155,6 +156,9 @@ void MyAvatar::update(float deltaTime) {
|
|||
}
|
||||
|
||||
simulate(deltaTime);
|
||||
if (_feetTouchFloor) {
|
||||
_skeletonModel.updateStandingFoot();
|
||||
}
|
||||
}
|
||||
|
||||
void MyAvatar::simulate(float deltaTime) {
|
||||
|
@ -925,7 +929,7 @@ void MyAvatar::updateLookAtTargetAvatar() {
|
|||
}
|
||||
glm::vec3 lookForward = faceRotation * IDENTITY_FRONT;
|
||||
glm::vec3 cameraPosition = Application::getInstance()->getCamera()->getPosition();
|
||||
float smallestAngleTo = glm::radians(Application::getInstance()->getCamera()->getFieldOfView()) / 2.f;
|
||||
float smallestAngleTo = glm::radians(Application::getInstance()->getCamera()->getFieldOfView()) / 2.0f;
|
||||
|
||||
int howManyLookingAtMe = 0;
|
||||
foreach (const AvatarSharedPointer& avatarPointer, Application::getInstance()->getAvatarManager().getAvatarHash()) {
|
||||
|
@ -1034,7 +1038,14 @@ void MyAvatar::setAttachmentData(const QVector<AttachmentData>& attachmentData)
|
|||
glm::vec3 MyAvatar::getSkeletonPosition() const {
|
||||
CameraMode mode = Application::getInstance()->getCamera()->getMode();
|
||||
if (mode == CAMERA_MODE_THIRD_PERSON || mode == CAMERA_MODE_INDEPENDENT) {
|
||||
return Avatar::getSkeletonPosition();
|
||||
// The avatar is rotated PI about the yAxis, so we have to correct for it
|
||||
// to get the skeleton offset contribution in the world-frame.
|
||||
const glm::quat FLIP = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f));
|
||||
glm::vec3 skeletonOffset = _skeletonOffset;
|
||||
if (_feetTouchFloor) {
|
||||
skeletonOffset += _skeletonModel.getStandingOffset();
|
||||
}
|
||||
return _position + getOrientation() * FLIP * skeletonOffset;
|
||||
}
|
||||
return Avatar::getPosition();
|
||||
}
|
||||
|
@ -1939,6 +1950,7 @@ void MyAvatar::updateMotionBehavior() {
|
|||
} else {
|
||||
_motionBehaviors &= ~AVATAR_MOTION_SCRIPTED_MOTOR_ENABLED;
|
||||
}
|
||||
_feetTouchFloor = menu->isOptionChecked(MenuOption::ShiftHipsForIdleAnimations);
|
||||
}
|
||||
|
||||
void MyAvatar::onToggleRagdoll() {
|
||||
|
|
|
@ -101,7 +101,7 @@ public:
|
|||
// Set what driving keys are being pressed to control thrust levels
|
||||
void clearDriveKeys();
|
||||
void setDriveKeys(int key, float val) { _driveKeys[key] = val; };
|
||||
bool getDriveKeys(int key) { return _driveKeys[key] != 0.f; };
|
||||
bool getDriveKeys(int key) { return _driveKeys[key] != 0.0f; };
|
||||
void jump() { _shouldJump = true; };
|
||||
|
||||
bool isMyAvatar() { return true; }
|
||||
|
@ -235,6 +235,7 @@ private:
|
|||
PhysicsSimulation _physicsSimulation;
|
||||
VoxelShapeManager _voxelShapeManager;
|
||||
|
||||
bool _feetTouchFloor;
|
||||
bool _isLookingAtLeftEye;
|
||||
|
||||
RecorderPointer _recorder;
|
||||
|
|
|
@ -22,13 +22,22 @@
|
|||
#include "SkeletonModel.h"
|
||||
#include "SkeletonRagdoll.h"
|
||||
|
||||
enum StandingFootState {
|
||||
LEFT_FOOT,
|
||||
RIGHT_FOOT,
|
||||
NO_FOOT
|
||||
};
|
||||
|
||||
SkeletonModel::SkeletonModel(Avatar* owningAvatar, QObject* parent) :
|
||||
Model(parent),
|
||||
_owningAvatar(owningAvatar),
|
||||
_boundingShape(),
|
||||
_boundingShapeLocalOffset(0.0f),
|
||||
_ragdoll(NULL),
|
||||
_defaultEyeModelPosition(glm::vec3(0.f, 0.f, 0.f)) {
|
||||
_defaultEyeModelPosition(glm::vec3(0.0f, 0.0f, 0.0f)),
|
||||
_standingFoot(NO_FOOT),
|
||||
_standingOffset(0.0f),
|
||||
_clampedFootPosition(0.0f) {
|
||||
}
|
||||
|
||||
SkeletonModel::~SkeletonModel() {
|
||||
|
@ -45,7 +54,7 @@ void SkeletonModel::setJointStates(QVector<JointState> states) {
|
|||
|
||||
glm::vec3 leftEyePosition, rightEyePosition;
|
||||
getEyeModelPositions(leftEyePosition, rightEyePosition);
|
||||
glm::vec3 midEyePosition = (leftEyePosition + rightEyePosition) / 2.f;
|
||||
glm::vec3 midEyePosition = (leftEyePosition + rightEyePosition) / 2.0f;
|
||||
|
||||
int rootJointIndex = _geometry->getFBXGeometry().rootJointIndex;
|
||||
glm::vec3 rootModelPosition;
|
||||
|
@ -607,6 +616,62 @@ void SkeletonModel::updateVisibleJointStates() {
|
|||
}
|
||||
}
|
||||
|
||||
/// \return offset of hips after foot animation
|
||||
void SkeletonModel::updateStandingFoot() {
|
||||
glm::vec3 offset(0.0f);
|
||||
int leftFootIndex = _geometry->getFBXGeometry().leftToeJointIndex;
|
||||
int rightFootIndex = _geometry->getFBXGeometry().rightToeJointIndex;
|
||||
|
||||
if (leftFootIndex != -1 && rightFootIndex != -1) {
|
||||
glm::vec3 leftPosition, rightPosition;
|
||||
getJointPosition(leftFootIndex, leftPosition);
|
||||
getJointPosition(rightFootIndex, rightPosition);
|
||||
|
||||
int lowestFoot = (leftPosition.y < rightPosition.y) ? LEFT_FOOT : RIGHT_FOOT;
|
||||
const float MIN_STEP_HEIGHT_THRESHOLD = 0.05f;
|
||||
bool oneFoot = fabsf(leftPosition.y - rightPosition.y) > MIN_STEP_HEIGHT_THRESHOLD;
|
||||
int currentFoot = oneFoot ? lowestFoot : _standingFoot;
|
||||
|
||||
if (_standingFoot == NO_FOOT) {
|
||||
currentFoot = lowestFoot;
|
||||
}
|
||||
if (currentFoot != _standingFoot) {
|
||||
if (_standingFoot == NO_FOOT) {
|
||||
// pick the lowest foot
|
||||
glm::vec3 lowestPosition = (currentFoot == LEFT_FOOT) ? leftPosition : rightPosition;
|
||||
// we ignore zero length positions which can happen for a few frames until skeleton is fully loaded
|
||||
if (glm::length(lowestPosition) > 0.0f) {
|
||||
_standingFoot = currentFoot;
|
||||
_clampedFootPosition = lowestPosition;
|
||||
}
|
||||
} else {
|
||||
// swap feet
|
||||
_standingFoot = currentFoot;
|
||||
glm::vec3 nextPosition = leftPosition;
|
||||
glm::vec3 prevPosition = rightPosition;
|
||||
if (_standingFoot == RIGHT_FOOT) {
|
||||
nextPosition = rightPosition;
|
||||
prevPosition = leftPosition;
|
||||
}
|
||||
glm::vec3 oldOffset = _clampedFootPosition - prevPosition;
|
||||
_clampedFootPosition = oldOffset + nextPosition;
|
||||
offset = _clampedFootPosition - nextPosition;
|
||||
}
|
||||
} else {
|
||||
glm::vec3 nextPosition = (_standingFoot == LEFT_FOOT) ? leftPosition : rightPosition;
|
||||
offset = _clampedFootPosition - nextPosition;
|
||||
}
|
||||
|
||||
// clamp the offset to not exceed some max distance
|
||||
const float MAX_STEP_OFFSET = 1.0f;
|
||||
float stepDistance = glm::length(offset);
|
||||
if (stepDistance > MAX_STEP_OFFSET) {
|
||||
offset *= (MAX_STEP_OFFSET / stepDistance);
|
||||
}
|
||||
}
|
||||
_standingOffset = offset;
|
||||
}
|
||||
|
||||
SkeletonRagdoll* SkeletonModel::buildRagdoll() {
|
||||
if (!_ragdoll) {
|
||||
_ragdoll = new SkeletonRagdoll(this);
|
||||
|
|
|
@ -101,6 +101,10 @@ public:
|
|||
/// \return whether or not the head was found.
|
||||
glm::vec3 getDefaultEyeModelPosition() const;
|
||||
|
||||
/// skeleton offset caused by moving feet
|
||||
void updateStandingFoot();
|
||||
const glm::vec3& getStandingOffset() const { return _standingOffset; }
|
||||
|
||||
virtual void updateVisibleJointStates();
|
||||
|
||||
SkeletonRagdoll* buildRagdoll();
|
||||
|
@ -154,6 +158,9 @@ private:
|
|||
SkeletonRagdoll* _ragdoll;
|
||||
|
||||
glm::vec3 _defaultEyeModelPosition;
|
||||
int _standingFoot;
|
||||
glm::vec3 _standingOffset;
|
||||
glm::vec3 _clampedFootPosition;
|
||||
};
|
||||
|
||||
#endif // hifi_SkeletonModel_h
|
||||
|
|
|
@ -191,7 +191,7 @@ void resetCoefficient(float * coefficient, float currentValue) {
|
|||
float updateAndGetCoefficient(float * coefficient, float currentValue, bool scaleToRange = false) {
|
||||
coefficient[MIN] = (currentValue < coefficient[MIN]) ? currentValue : coefficient[MIN];
|
||||
coefficient[MAX] = (currentValue > coefficient[MAX]) ? currentValue : coefficient[MAX];
|
||||
coefficient[AVG] = LONG_TERM_AVERAGE * coefficient[AVG] + (1.f - LONG_TERM_AVERAGE) * currentValue;
|
||||
coefficient[AVG] = LONG_TERM_AVERAGE * coefficient[AVG] + (1.0f - LONG_TERM_AVERAGE) * currentValue;
|
||||
if (coefficient[MAX] > coefficient[MIN]) {
|
||||
if (scaleToRange) {
|
||||
return glm::clamp((currentValue - coefficient[AVG]) / (coefficient[MAX] - coefficient[MIN]), 0.0f, 1.0f);
|
||||
|
|
|
@ -156,7 +156,7 @@ void Leapmotion::update() {
|
|||
if (lastFrameID >= newFrameID)
|
||||
return;
|
||||
|
||||
glm::vec3 delta(0.f);
|
||||
glm::vec3 delta(0.0f);
|
||||
glm::quat handOri;
|
||||
if (!frame.hands().isEmpty()) {
|
||||
for (int handNum = 0; handNum < frame.hands().count(); handNum++) {
|
||||
|
|
|
@ -167,9 +167,9 @@ MotionTracker::Frame::Frame() :
|
|||
|
||||
void MotionTracker::Frame::setRotation(const glm::quat& rotation) {
|
||||
glm::mat3x3 rot = glm::mat3_cast(rotation);
|
||||
_transform[0] = glm::vec4(rot[0], 0.f);
|
||||
_transform[1] = glm::vec4(rot[1], 0.f);
|
||||
_transform[2] = glm::vec4(rot[2], 0.f);
|
||||
_transform[0] = glm::vec4(rot[0], 0.0f);
|
||||
_transform[1] = glm::vec4(rot[1], 0.0f);
|
||||
_transform[2] = glm::vec4(rot[2], 0.0f);
|
||||
}
|
||||
|
||||
void MotionTracker::Frame::getRotation(glm::quat& rotation) const {
|
||||
|
@ -177,7 +177,7 @@ void MotionTracker::Frame::getRotation(glm::quat& rotation) const {
|
|||
}
|
||||
|
||||
void MotionTracker::Frame::setTranslation(const glm::vec3& translation) {
|
||||
_transform[3] = glm::vec4(translation, 1.f);
|
||||
_transform[3] = glm::vec4(translation, 1.0f);
|
||||
}
|
||||
|
||||
void MotionTracker::Frame::getTranslation(glm::vec3& translation) const {
|
||||
|
|
|
@ -56,7 +56,7 @@ Camera* OculusManager::_camera = NULL;
|
|||
int OculusManager::_activeEyeIndex = -1;
|
||||
|
||||
float OculusManager::CALIBRATION_DELTA_MINIMUM_LENGTH = 0.02f;
|
||||
float OculusManager::CALIBRATION_DELTA_MINIMUM_ANGLE = 5.f * RADIANS_PER_DEGREE;
|
||||
float OculusManager::CALIBRATION_DELTA_MINIMUM_ANGLE = 5.0f * RADIANS_PER_DEGREE;
|
||||
float OculusManager::CALIBRATION_ZERO_MAXIMUM_LENGTH = 0.01f;
|
||||
float OculusManager::CALIBRATION_ZERO_MAXIMUM_ANGLE = 2.0f * RADIANS_PER_DEGREE;
|
||||
quint64 OculusManager::CALIBRATION_ZERO_HOLD_TIME = 3000000; // usec
|
||||
|
@ -196,7 +196,7 @@ void OculusManager::positionCalibrationBillboard(Text3DOverlay* billboard) {
|
|||
headOrientation.z = 0;
|
||||
glm::normalize(headOrientation);
|
||||
billboard->setPosition(Application::getInstance()->getAvatar()->getHeadPosition()
|
||||
+ headOrientation * glm::vec3(0.f, 0.f, -CALIBRATION_MESSAGE_DISTANCE));
|
||||
+ headOrientation * glm::vec3(0.0f, 0.0f, -CALIBRATION_MESSAGE_DISTANCE));
|
||||
billboard->setRotation(headOrientation);
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -106,7 +106,7 @@ static void setPalm(float deltaTime, int index) {
|
|||
|
||||
// Compute current velocity from position change
|
||||
glm::vec3 rawVelocity;
|
||||
if (deltaTime > 0.f) {
|
||||
if (deltaTime > 0.0f) {
|
||||
rawVelocity = (position - palm->getRawPosition()) / deltaTime;
|
||||
} else {
|
||||
rawVelocity = glm::vec3(0.0f);
|
||||
|
@ -119,10 +119,10 @@ static void setPalm(float deltaTime, int index) {
|
|||
const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH);
|
||||
const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR;
|
||||
glm::vec3 oldTipPosition = palm->getTipRawPosition();
|
||||
if (deltaTime > 0.f) {
|
||||
if (deltaTime > 0.0f) {
|
||||
palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime);
|
||||
} else {
|
||||
palm->setTipVelocity(glm::vec3(0.f));
|
||||
palm->setTipVelocity(glm::vec3(0.0f));
|
||||
}
|
||||
palm->setTipPosition(newTipPosition);
|
||||
}
|
||||
|
|
|
@ -241,16 +241,16 @@ void SixenseManager::update(float deltaTime) {
|
|||
// Transform the measured position into body frame.
|
||||
glm::vec3 neck = _neckBase;
|
||||
// Zeroing y component of the "neck" effectively raises the measured position a little bit.
|
||||
neck.y = 0.f;
|
||||
neck.y = 0.0f;
|
||||
position = _orbRotation * (position - neck);
|
||||
|
||||
// Rotation of Palm
|
||||
glm::quat rotation(data->rot_quat[3], -data->rot_quat[0], data->rot_quat[1], -data->rot_quat[2]);
|
||||
rotation = glm::angleAxis(PI, glm::vec3(0.f, 1.f, 0.f)) * _orbRotation * rotation;
|
||||
rotation = glm::angleAxis(PI, glm::vec3(0.0f, 1.0f, 0.0f)) * _orbRotation * rotation;
|
||||
|
||||
// Compute current velocity from position change
|
||||
glm::vec3 rawVelocity;
|
||||
if (deltaTime > 0.f) {
|
||||
if (deltaTime > 0.0f) {
|
||||
rawVelocity = (position - palm->getRawPosition()) / deltaTime;
|
||||
} else {
|
||||
rawVelocity = glm::vec3(0.0f);
|
||||
|
@ -287,10 +287,10 @@ void SixenseManager::update(float deltaTime) {
|
|||
const glm::vec3 FINGER_VECTOR(0.0f, 0.0f, FINGER_LENGTH);
|
||||
const glm::vec3 newTipPosition = position + rotation * FINGER_VECTOR;
|
||||
glm::vec3 oldTipPosition = palm->getTipRawPosition();
|
||||
if (deltaTime > 0.f) {
|
||||
if (deltaTime > 0.0f) {
|
||||
palm->setTipVelocity((newTipPosition - oldTipPosition) / deltaTime);
|
||||
} else {
|
||||
palm->setTipVelocity(glm::vec3(0.f));
|
||||
palm->setTipVelocity(glm::vec3(0.0f));
|
||||
}
|
||||
palm->setTipPosition(newTipPosition);
|
||||
}
|
||||
|
@ -348,7 +348,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers)
|
|||
// to also handle the case where left and right controllers have been reversed.
|
||||
_neckBase = 0.5f * (_reachLeft + _reachRight); // neck is midway between right and left reaches
|
||||
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
|
||||
glm::vec3 yAxis(0.f, 1.f, 0.f);
|
||||
glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, yAxis));
|
||||
xAxis = glm::normalize(glm::cross(yAxis, zAxis));
|
||||
_orbRotation = glm::inverse(glm::quat_cast(glm::mat3(xAxis, yAxis, zAxis)));
|
||||
|
@ -405,7 +405,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers)
|
|||
} else if (now > _lockExpiry) {
|
||||
// lock has expired so clamp the data and move on
|
||||
_lockExpiry = now + LOCK_DURATION;
|
||||
_lastDistance = 0.f;
|
||||
_lastDistance = 0.0f;
|
||||
_reachUp = 0.5f * (_reachLeft + _reachRight);
|
||||
_calibrationState = CALIBRATION_STATE_Y;
|
||||
qDebug("success: sixense calibration: left");
|
||||
|
@ -424,7 +424,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers)
|
|||
if (_lastDistance > MINIMUM_ARM_REACH) {
|
||||
// lock has expired so clamp the data and move on
|
||||
_reachForward = _reachUp;
|
||||
_lastDistance = 0.f;
|
||||
_lastDistance = 0.0f;
|
||||
_lockExpiry = now + LOCK_DURATION;
|
||||
_calibrationState = CALIBRATION_STATE_Z;
|
||||
qDebug("success: sixense calibration: up");
|
||||
|
@ -435,7 +435,7 @@ void SixenseManager::updateCalibration(const sixenseControllerData* controllers)
|
|||
glm::vec3 xAxis = glm::normalize(_reachRight - _reachLeft);
|
||||
glm::vec3 torso = 0.5f * (_reachLeft + _reachRight);
|
||||
//glm::vec3 yAxis = glm::normalize(_reachUp - torso);
|
||||
glm::vec3 yAxis(0.f, 1.f, 0.f);
|
||||
glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||
glm::vec3 zAxis = glm::normalize(glm::cross(xAxis, yAxis));
|
||||
|
||||
glm::vec3 averagePosition = 0.5f * (_averageLeft + _averageRight);
|
||||
|
|
|
@ -82,7 +82,7 @@ void EntityTreeRenderer::init() {
|
|||
// make sure our "last avatar position" is something other than our current position, so that on our
|
||||
// first chance, we'll check for enter/leave entity events.
|
||||
glm::vec3 avatarPosition = Application::getInstance()->getAvatar()->getPosition();
|
||||
_lastAvatarPosition = avatarPosition + glm::vec3(1.f, 1.f, 1.f);
|
||||
_lastAvatarPosition = avatarPosition + glm::vec3(1.0f, 1.0f, 1.0f);
|
||||
|
||||
connect(entityTree, &EntityTree::deletingEntity, this, &EntityTreeRenderer::deletingEntity);
|
||||
connect(entityTree, &EntityTree::addingEntity, this, &EntityTreeRenderer::checkAndCallPreload);
|
||||
|
|
|
@ -248,9 +248,9 @@ void DeferredLightingEffect::render() {
|
|||
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.f ? light.constantAttenuation : 0.f));
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.f ? light.linearAttenuation : 0.f));
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.f ? light.quadraticAttenuation : 0.f));
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.0f ? light.constantAttenuation : 0.0f));
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.0f ? light.linearAttenuation : 0.0f));
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.0f ? light.quadraticAttenuation : 0.0f));
|
||||
|
||||
glPushMatrix();
|
||||
|
||||
|
@ -293,9 +293,9 @@ void DeferredLightingEffect::render() {
|
|||
glLightfv(GL_LIGHT1, GL_DIFFUSE, (const GLfloat*)&light.diffuse);
|
||||
glLightfv(GL_LIGHT1, GL_SPECULAR, (const GLfloat*)&light.specular);
|
||||
glLightfv(GL_LIGHT1, GL_POSITION, (const GLfloat*)&light.position);
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.f ? light.constantAttenuation : 0.f));
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.f ? light.linearAttenuation : 0.f));
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.f ? light.quadraticAttenuation : 0.f));
|
||||
glLightf(GL_LIGHT1, GL_CONSTANT_ATTENUATION, (light.constantAttenuation > 0.0f ? light.constantAttenuation : 0.0f));
|
||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, (light.linearAttenuation > 0.0f ? light.linearAttenuation : 0.0f));
|
||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, (light.quadraticAttenuation > 0.0f ? light.quadraticAttenuation : 0.0f));
|
||||
glLightfv(GL_LIGHT1, GL_SPOT_DIRECTION, (const GLfloat*)&light.direction);
|
||||
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent);
|
||||
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff));
|
||||
|
|
|
@ -296,7 +296,7 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) {
|
|||
float y = (float)i / (stacks - 1);
|
||||
|
||||
for (int j = 0; j <= slices; j++) {
|
||||
float theta = 3.f * PI_OVER_TWO + PI * (float)j / (float)slices;
|
||||
float theta = 3.0f * PI_OVER_TWO + PI * (float)j / (float)slices;
|
||||
|
||||
//normals
|
||||
*(vertex++) = sinf(theta);
|
||||
|
|
|
@ -1424,7 +1424,7 @@ void Model::inverseKinematics(int endIndex, glm::vec3 targetPosition, const glm:
|
|||
centerOfMass += _jointStates[massIndex].getPosition() - pivot;
|
||||
}
|
||||
// the gravitational effect is a rotation that tends to align the two cross products
|
||||
const glm::vec3 worldAlignment = glm::vec3(0.0f, -1.f, 0.0f);
|
||||
const glm::vec3 worldAlignment = glm::vec3(0.0f, -1.0f, 0.0f);
|
||||
glm::quat gravityDelta = rotationBetween(glm::cross(centerOfMass, leverArm),
|
||||
glm::cross(worldAlignment, leverArm));
|
||||
|
||||
|
@ -2430,7 +2430,7 @@ int Model::renderMeshesFromList(QVector<int>& list, gpu::Batch& batch, RenderMod
|
|||
GLBATCH(glMaterialfv)(GL_FRONT, GL_AMBIENT, (const float*)&diffuse);
|
||||
GLBATCH(glMaterialfv)(GL_FRONT, GL_DIFFUSE, (const float*)&diffuse);
|
||||
GLBATCH(glMaterialfv)(GL_FRONT, GL_SPECULAR, (const float*)&specular);
|
||||
GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, (part.shininess > 128.f ? 128.f: part.shininess));
|
||||
GLBATCH(glMaterialf)(GL_FRONT, GL_SHININESS, (part.shininess > 128.0f ? 128.0f: part.shininess));
|
||||
|
||||
Texture* diffuseMap = networkPart.diffuseTexture.data();
|
||||
if (mesh.isEye && diffuseMap) {
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
using namespace starfield;
|
||||
|
||||
const float Generator::STAR_COLORIZATION = 0.1f;
|
||||
const float PI_OVER_180 = 3.14159265358979f / 180.f;
|
||||
const float PI_OVER_180 = 3.14159265358979f / 180.0f;
|
||||
|
||||
void Generator::computeStarPositions(InputVertices& destination, unsigned limit, unsigned seed) {
|
||||
InputVertices* vertices = & destination;
|
||||
|
@ -44,9 +44,9 @@ void Generator::computeStarPositions(InputVertices& destination, unsigned limit,
|
|||
|
||||
for(int star = 0; star < ceil(limit * MILKY_WAY_RATIO); ++star) {
|
||||
float azimuth = ((float)rand() / (float) RAND_MAX) * NUM_DEGREES;
|
||||
float altitude = powf(randFloat()*0.5f, 2.f)/0.25f * MILKY_WAY_WIDTH;
|
||||
float altitude = powf(randFloat()*0.5f, 2.0f)/0.25f * MILKY_WAY_WIDTH;
|
||||
if (randFloat() > 0.5f) {
|
||||
altitude *= -1.f;
|
||||
altitude *= -1.0f;
|
||||
}
|
||||
|
||||
// we need to rotate the Milky Way band to the correct orientation in the sky
|
||||
|
|
|
@ -999,26 +999,26 @@ void ApplicationOverlay::renderAudioMeter() {
|
|||
const float AUDIO_RED_START = 0.80 * AUDIO_METER_SCALE_WIDTH;
|
||||
const float CLIPPING_INDICATOR_TIME = 1.0f;
|
||||
const float AUDIO_METER_AVERAGING = 0.5;
|
||||
const float LOG2 = log(2.f);
|
||||
const float METER_LOUDNESS_SCALE = 2.8f / 5.f;
|
||||
const float LOG2_LOUDNESS_FLOOR = 11.f;
|
||||
float audioLevel = 0.f;
|
||||
float loudness = audio->getLastInputLoudness() + 1.f;
|
||||
const float LOG2 = log(2.0f);
|
||||
const float METER_LOUDNESS_SCALE = 2.8f / 5.0f;
|
||||
const float LOG2_LOUDNESS_FLOOR = 11.0f;
|
||||
float audioLevel = 0.0f;
|
||||
float loudness = audio->getLastInputLoudness() + 1.0f;
|
||||
|
||||
_trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.f - AUDIO_METER_AVERAGING) * loudness;
|
||||
_trailingAudioLoudness = AUDIO_METER_AVERAGING * _trailingAudioLoudness + (1.0f - AUDIO_METER_AVERAGING) * loudness;
|
||||
float log2loudness = log(_trailingAudioLoudness) / LOG2;
|
||||
|
||||
if (log2loudness <= LOG2_LOUDNESS_FLOOR) {
|
||||
audioLevel = (log2loudness / LOG2_LOUDNESS_FLOOR) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH;
|
||||
} else {
|
||||
audioLevel = (log2loudness - (LOG2_LOUDNESS_FLOOR - 1.f)) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH;
|
||||
audioLevel = (log2loudness - (LOG2_LOUDNESS_FLOOR - 1.0f)) * METER_LOUDNESS_SCALE * AUDIO_METER_SCALE_WIDTH;
|
||||
}
|
||||
if (audioLevel > AUDIO_METER_SCALE_WIDTH) {
|
||||
audioLevel = AUDIO_METER_SCALE_WIDTH;
|
||||
}
|
||||
bool isClipping = ((audio->getTimeSinceLastClip() > 0.f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME));
|
||||
bool isClipping = ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME));
|
||||
|
||||
if ((audio->getTimeSinceLastClip() > 0.f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) {
|
||||
if ((audio->getTimeSinceLastClip() > 0.0f) && (audio->getTimeSinceLastClip() < CLIPPING_INDICATOR_TIME)) {
|
||||
const float MAX_MAGNITUDE = 0.7f;
|
||||
float magnitude = MAX_MAGNITUDE * (1 - audio->getTimeSinceLastClip() / CLIPPING_INDICATOR_TIME);
|
||||
renderCollisionOverlay(glWidget->width(), glWidget->height(), magnitude, 1.0f);
|
||||
|
|
|
@ -130,22 +130,22 @@ void OctreeStatsDialog::paintEvent(QPaintEvent* event) {
|
|||
|
||||
// Voxels Rendered
|
||||
label = _labels[_voxelsRendered];
|
||||
statsValue << "Max: " << voxels->getMaxVoxels() / 1000.f << "K " <<
|
||||
"Drawn: " << voxels->getVoxelsWritten() / 1000.f << "K " <<
|
||||
"Abandoned: " << voxels->getAbandonedVoxels() / 1000.f << "K " <<
|
||||
"ReadBuffer: " << voxels->getVoxelsRendered() / 1000.f << "K " <<
|
||||
"Changed: " << voxels->getVoxelsUpdated() / 1000.f << "K ";
|
||||
statsValue << "Max: " << voxels->getMaxVoxels() / 1000.0f << "K " <<
|
||||
"Drawn: " << voxels->getVoxelsWritten() / 1000.0f << "K " <<
|
||||
"Abandoned: " << voxels->getAbandonedVoxels() / 1000.0f << "K " <<
|
||||
"ReadBuffer: " << voxels->getVoxelsRendered() / 1000.0f << "K " <<
|
||||
"Changed: " << voxels->getVoxelsUpdated() / 1000.0f << "K ";
|
||||
label->setText(statsValue.str().c_str());
|
||||
|
||||
// Voxels Memory Usage
|
||||
label = _labels[_localVoxelsMemory];
|
||||
statsValue.str("");
|
||||
statsValue <<
|
||||
"Elements RAM: " << OctreeElement::getTotalMemoryUsage() / 1000000.f << "MB "
|
||||
"Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.f << "MB " <<
|
||||
"VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.f << "MB ";
|
||||
"Elements RAM: " << OctreeElement::getTotalMemoryUsage() / 1000000.0f << "MB "
|
||||
"Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.0f << "MB " <<
|
||||
"VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.0f << "MB ";
|
||||
if (voxels->hasVoxelMemoryUsageGPU()) {
|
||||
statsValue << "GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.f << "MB ";
|
||||
statsValue << "GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.0f << "MB ";
|
||||
}
|
||||
label->setText(statsValue.str().c_str());
|
||||
|
||||
|
|
|
@ -264,7 +264,7 @@ void Stats::display(
|
|||
char packetsPerSecondString[30];
|
||||
sprintf(packetsPerSecondString, "Pkts/sec: %d", packetsPerSecond);
|
||||
char averageMegabitsPerSecond[30];
|
||||
sprintf(averageMegabitsPerSecond, "Mbps: %3.2f", (float)bytesPerSecond * 8.f / 1000000.f);
|
||||
sprintf(averageMegabitsPerSecond, "Mbps: %3.2f", (float)bytesPerSecond * 8.0f / 1000000.0f);
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, packetsPerSecondString, color);
|
||||
|
@ -501,24 +501,24 @@ void Stats::display(
|
|||
|
||||
voxelStats.str("");
|
||||
voxelStats.precision(4);
|
||||
voxelStats << "Voxels Drawn: " << voxels->getVoxelsWritten() / 1000.f << "K " <<
|
||||
"Abandoned: " << voxels->getAbandonedVoxels() / 1000.f << "K ";
|
||||
voxelStats << "Voxels Drawn: " << voxels->getVoxelsWritten() / 1000.0f << "K " <<
|
||||
"Abandoned: " << voxels->getAbandonedVoxels() / 1000.0f << "K ";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
if (_expanded) {
|
||||
// Local Voxel Memory Usage
|
||||
voxelStats.str("");
|
||||
voxelStats << " Voxels Memory Nodes: " << VoxelTreeElement::getTotalMemoryUsage() / 1000000.f << "MB";
|
||||
voxelStats << " Voxels Memory Nodes: " << VoxelTreeElement::getTotalMemoryUsage() / 1000000.0f << "MB";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
||||
voxelStats.str("");
|
||||
voxelStats <<
|
||||
" Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.f << "MB / " <<
|
||||
"VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.f << "MB";
|
||||
" Geometry RAM: " << voxels->getVoxelMemoryUsageRAM() / 1000000.0f << "MB / " <<
|
||||
"VBO: " << voxels->getVoxelMemoryUsageVBO() / 1000000.0f << "MB";
|
||||
if (voxels->hasVoxelMemoryUsageGPU()) {
|
||||
voxelStats << " / GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.f << "MB";
|
||||
voxelStats << " / GPU: " << voxels->getVoxelMemoryUsageGPU() / 1000000.0f << "MB";
|
||||
}
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
|
@ -526,7 +526,7 @@ void Stats::display(
|
|||
// Voxel Rendering
|
||||
voxelStats.str("");
|
||||
voxelStats.precision(4);
|
||||
voxelStats << " Voxel Rendering Slots Max: " << voxels->getMaxVoxels() / 1000.f << "K";
|
||||
voxelStats << " Voxel Rendering Slots Max: " << voxels->getMaxVoxels() / 1000.0f << "K";
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, scale, rotation, font, (char*)voxelStats.str().c_str(), color);
|
||||
}
|
||||
|
@ -746,7 +746,7 @@ void Stats::display(
|
|||
audioReflector->getEchoesAttenuation());
|
||||
|
||||
verticalOffset += STATS_PELS_PER_LINE;
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.f, 2.f, reflectionsStatus, color);
|
||||
drawText(horizontalOffset, verticalOffset, 0.10f, 0.0f, 2.0f, reflectionsStatus, color);
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -73,12 +73,12 @@ int TextRenderer::draw(int x, int y, const char* str, float alpha) {
|
|||
// Grab the current color
|
||||
float currentColor[4];
|
||||
glGetFloatv(GL_CURRENT_COLOR, currentColor);
|
||||
alpha = std::max(0.f, std::min(alpha, 1.f));
|
||||
alpha = std::max(0.0f, std::min(alpha, 1.0f));
|
||||
currentColor[3] *= alpha;
|
||||
int compactColor = ((int(currentColor[0] * 255.f) & 0xFF)) |
|
||||
((int(currentColor[1] * 255.f) & 0xFF) << 8) |
|
||||
((int(currentColor[2] * 255.f) & 0xFF) << 16) |
|
||||
((int(currentColor[3] * 255.f) & 0xFF) << 24);
|
||||
int compactColor = ((int(currentColor[0] * 255.0f) & 0xFF)) |
|
||||
((int(currentColor[1] * 255.0f) & 0xFF) << 8) |
|
||||
((int(currentColor[2] * 255.0f) & 0xFF) << 16) |
|
||||
((int(currentColor[3] * 255.0f) & 0xFF) << 24);
|
||||
|
||||
// TODO: Remove that code once we test for performance improvments
|
||||
//glEnable(GL_TEXTURE_2D);
|
||||
|
|
|
@ -63,7 +63,7 @@ public:
|
|||
int calculateHeight(const char* str);
|
||||
|
||||
// also returns the height of the tallest character
|
||||
int draw(int x, int y, const char* str, float alpha = 1.f);
|
||||
int draw(int x, int y, const char* str, float alpha = 1.0f);
|
||||
|
||||
int computeWidth(char ch);
|
||||
int computeWidth(const char* str);
|
||||
|
|
|
@ -78,6 +78,17 @@ float AudioInjector::getLoudness() {
|
|||
}
|
||||
|
||||
void AudioInjector::injectAudio() {
|
||||
|
||||
// check if we need to offset the sound by some number of seconds
|
||||
if (_options.secondOffset > 0.0f) {
|
||||
|
||||
// convert the offset into a number of bytes
|
||||
int byteOffset = (int) floorf(SAMPLE_RATE * _options.secondOffset * (_options.stereo ? 2.0f : 1.0f));
|
||||
byteOffset *= sizeof(int16_t);
|
||||
|
||||
_currentSendPosition = byteOffset;
|
||||
}
|
||||
|
||||
if (_options.localOnly) {
|
||||
injectLocally();
|
||||
} else {
|
||||
|
@ -89,10 +100,14 @@ void AudioInjector::injectLocally() {
|
|||
bool success = false;
|
||||
if (_localAudioInterface) {
|
||||
if (_audioData.size() > 0) {
|
||||
|
||||
_localBuffer = new AudioInjectorLocalBuffer(_audioData, this);
|
||||
_localBuffer->open(QIODevice::ReadOnly);
|
||||
_localBuffer->setShouldLoop(_options.loop);
|
||||
|
||||
// give our current send position to the local buffer
|
||||
_localBuffer->setCurrentOffset(_currentSendPosition);
|
||||
|
||||
QMetaObject::invokeMethod(_localAudioInterface, "outputLocalInjector",
|
||||
Qt::BlockingQueuedConnection,
|
||||
Q_RETURN_ARG(bool, success),
|
||||
|
@ -100,7 +115,8 @@ void AudioInjector::injectLocally() {
|
|||
Q_ARG(qreal, _options.volume),
|
||||
Q_ARG(AudioInjector*, this));
|
||||
|
||||
|
||||
// if we're not looping and the buffer tells us it is empty then emit finished
|
||||
connect(_localBuffer, &AudioInjectorLocalBuffer::bufferEmpty, this, &AudioInjector::stop);
|
||||
|
||||
if (!success) {
|
||||
qDebug() << "AudioInjector::injectLocally could not output locally via _localAudioInterface";
|
||||
|
|
|
@ -47,6 +47,11 @@ qint64 AudioInjectorLocalBuffer::readData(char* data, qint64 maxSize) {
|
|||
_currentOffset += bytesRead;
|
||||
}
|
||||
|
||||
if (!_shouldLoop && bytesRead == bytesToEnd) {
|
||||
// we hit the end of the buffer, emit a signal
|
||||
emit bufferEmpty();
|
||||
}
|
||||
|
||||
return bytesRead;
|
||||
} else {
|
||||
return 0;
|
||||
|
|
|
@ -26,6 +26,9 @@ public:
|
|||
|
||||
void setShouldLoop(bool shouldLoop) { _shouldLoop = shouldLoop; }
|
||||
|
||||
void setCurrentOffset(int currentOffset) { _currentOffset = currentOffset; }
|
||||
signals:
|
||||
void bufferEmpty();
|
||||
private:
|
||||
|
||||
qint64 recursiveReadFromFront(char* data, qint64 maxSize);
|
||||
|
|
|
@ -20,7 +20,8 @@ AudioInjectorOptions::AudioInjectorOptions() :
|
|||
orientation(glm::vec3(0.0f, 0.0f, 0.0f)),
|
||||
stereo(false),
|
||||
ignorePenumbra(false),
|
||||
localOnly(false)
|
||||
localOnly(false),
|
||||
secondOffset(0.0)
|
||||
{
|
||||
|
||||
}
|
||||
|
@ -31,9 +32,9 @@ QScriptValue injectorOptionsToScriptValue(QScriptEngine* engine, const AudioInje
|
|||
obj.setProperty("volume", injectorOptions.volume);
|
||||
obj.setProperty("loop", injectorOptions.loop);
|
||||
obj.setProperty("orientation", quatToScriptValue(engine, injectorOptions.orientation));
|
||||
obj.setProperty("stereo", injectorOptions.stereo);
|
||||
obj.setProperty("ignorePenumbra", injectorOptions.ignorePenumbra);
|
||||
obj.setProperty("localOnly", injectorOptions.localOnly);
|
||||
obj.setProperty("secondOffset", injectorOptions.secondOffset);
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
@ -54,10 +55,6 @@ void injectorOptionsFromScriptValue(const QScriptValue& object, AudioInjectorOpt
|
|||
quatFromScriptValue(object.property("orientation"), injectorOptions.orientation);
|
||||
}
|
||||
|
||||
if (object.property("stereo").isValid()) {
|
||||
injectorOptions.stereo = object.property("stereo").toBool();
|
||||
}
|
||||
|
||||
if (object.property("ignorePenumbra").isValid()) {
|
||||
injectorOptions.ignorePenumbra = object.property("ignorePenumbra").toBool();
|
||||
}
|
||||
|
@ -65,4 +62,8 @@ void injectorOptionsFromScriptValue(const QScriptValue& object, AudioInjectorOpt
|
|||
if (object.property("localOnly").isValid()) {
|
||||
injectorOptions.localOnly = object.property("localOnly").toBool();
|
||||
}
|
||||
|
||||
if (object.property("secondOffset").isValid()) {
|
||||
injectorOptions.secondOffset = object.property("secondOffset").toNumber();
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ public:
|
|||
bool stereo;
|
||||
bool ignorePenumbra;
|
||||
bool localOnly;
|
||||
float secondOffset;
|
||||
};
|
||||
|
||||
Q_DECLARE_METATYPE(AudioInjectorOptions);
|
||||
|
|
|
@ -44,7 +44,11 @@ void AudioScriptingInterface::stopAllInjectors() {
|
|||
|
||||
AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions& injectorOptions) {
|
||||
if (sound) {
|
||||
AudioInjector* injector = new AudioInjector(sound, injectorOptions);
|
||||
// stereo option isn't set from script, this comes from sound metadata or filename
|
||||
AudioInjectorOptions optionsCopy = injectorOptions;
|
||||
optionsCopy.stereo = sound->isStereo();
|
||||
|
||||
AudioInjector* injector = new AudioInjector(sound, optionsCopy);
|
||||
injector->setLocalAudioInterface(_localAudioInterface);
|
||||
|
||||
QThread* injectorThread = new QThread();
|
||||
|
|
|
@ -169,9 +169,16 @@ int InboundAudioStream::parseData(const QByteArray& packet) {
|
|||
}
|
||||
|
||||
int InboundAudioStream::parseStreamProperties(PacketType type, const QByteArray& packetAfterSeqNum, int& numAudioSamples) {
|
||||
// mixed audio packets do not have any info between the seq num and the audio data.
|
||||
numAudioSamples = packetAfterSeqNum.size() / sizeof(int16_t);
|
||||
return 0;
|
||||
if (type == PacketTypeSilentAudioFrame) {
|
||||
quint16 numSilentSamples = 0;
|
||||
memcpy(&numSilentSamples, packetAfterSeqNum.constData(), sizeof(quint16));
|
||||
numAudioSamples = numSilentSamples;
|
||||
return sizeof(quint16);
|
||||
} else {
|
||||
// mixed audio packets do not have any info between the seq num and the audio data.
|
||||
numAudioSamples = packetAfterSeqNum.size() / sizeof(int16_t);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int InboundAudioStream::parseAudioData(PacketType type, const QByteArray& packetAfterStreamProperties, int numAudioSamples) {
|
||||
|
|
|
@ -64,7 +64,14 @@ void Sound::downloadFinished(QNetworkReply* reply) {
|
|||
interpretAsWav(rawAudioByteArray, outputAudioByteArray);
|
||||
downSample(outputAudioByteArray);
|
||||
} else {
|
||||
// Process as RAW file
|
||||
// check if this was a stereo raw file
|
||||
// since it's raw the only way for us to know that is if the file was called .stereo.raw
|
||||
if (reply->url().fileName().toLower().endsWith("stereo.raw")) {
|
||||
_isStereo = true;
|
||||
qDebug() << "Processing sound from" << reply->url() << "as stereo audio file.";
|
||||
}
|
||||
|
||||
// Process as RAW file
|
||||
downSample(rawAudioByteArray);
|
||||
}
|
||||
trimFrames();
|
||||
|
@ -206,10 +213,12 @@ void Sound::interpretAsWav(const QByteArray& inputAudioByteArray, QByteArray& ou
|
|||
qDebug() << "Currently not supporting non PCM audio files.";
|
||||
return;
|
||||
}
|
||||
if (qFromLittleEndian<quint16>(fileHeader.wave.numChannels) != 1) {
|
||||
qDebug() << "Currently not supporting stereo audio files.";
|
||||
return;
|
||||
if (qFromLittleEndian<quint16>(fileHeader.wave.numChannels) == 2) {
|
||||
_isStereo = true;
|
||||
} else if (qFromLittleEndian<quint16>(fileHeader.wave.numChannels) > 2) {
|
||||
qDebug() << "Currently not support audio files with more than 2 channels.";
|
||||
}
|
||||
|
||||
if (qFromLittleEndian<quint16>(fileHeader.wave.bitsPerSample) != 16) {
|
||||
qDebug() << "Currently not supporting non 16bit audio files.";
|
||||
return;
|
||||
|
|
|
@ -25,7 +25,7 @@ class Sound : public Resource {
|
|||
public:
|
||||
Sound(const QUrl& url, bool isStereo = false);
|
||||
|
||||
bool isStereo() const { return _isStereo; }
|
||||
bool isStereo() const { return _isStereo; }
|
||||
bool isReady() const { return _isReady; }
|
||||
|
||||
const QByteArray& getByteArray() { return _byteArray; }
|
||||
|
|
|
@ -38,7 +38,7 @@ AvatarData::AvatarData() :
|
|||
_position(0.0f),
|
||||
_handPosition(0.0f),
|
||||
_referential(NULL),
|
||||
_bodyYaw(-90.f),
|
||||
_bodyYaw(-90.0f),
|
||||
_bodyPitch(0.0f),
|
||||
_bodyRoll(0.0f),
|
||||
_targetScale(1.0f),
|
||||
|
|
|
@ -83,7 +83,7 @@ const int IS_FACESHIFT_CONNECTED = 4; // 5th bit
|
|||
const int IS_CHAT_CIRCLING_ENABLED = 5; // 6th bit
|
||||
const int HAS_REFERENTIAL = 6; // 7th bit
|
||||
|
||||
static const float MAX_AVATAR_SCALE = 1000.f;
|
||||
static const float MAX_AVATAR_SCALE = 1000.0f;
|
||||
static const float MIN_AVATAR_SCALE = .005f;
|
||||
|
||||
const float MAX_AUDIO_LOUDNESS = 1000.0; // close enough for mouth animation
|
||||
|
@ -281,7 +281,7 @@ public:
|
|||
|
||||
QElapsedTimer& getLastUpdateTimer() { return _lastUpdateTimer; }
|
||||
|
||||
virtual float getBoundingRadius() const { return 1.f; }
|
||||
virtual float getBoundingRadius() const { return 1.0f; }
|
||||
|
||||
const Referential* getReferential() const { return _referential; }
|
||||
|
||||
|
|
|
@ -64,11 +64,11 @@ void HandData::getLeftRightPalmIndices(int& leftPalmIndex, int& rightPalmIndex)
|
|||
}
|
||||
|
||||
PalmData::PalmData(HandData* owningHandData) :
|
||||
_rawRotation(0.f, 0.f, 0.f, 1.f),
|
||||
_rawPosition(0.f),
|
||||
_rawVelocity(0.f),
|
||||
_rotationalVelocity(0.f),
|
||||
_totalPenetration(0.f),
|
||||
_rawRotation(0.0f, 0.0f, 0.0f, 1.0f),
|
||||
_rawPosition(0.0f),
|
||||
_rawVelocity(0.0f),
|
||||
_rotationalVelocity(0.0f),
|
||||
_totalPenetration(0.0f),
|
||||
_controllerButtons(0),
|
||||
_isActive(false),
|
||||
_sixenseID(SIXENSEID_INVALID),
|
||||
|
|
|
@ -100,7 +100,7 @@ public:
|
|||
void addToPosition(const glm::vec3& delta);
|
||||
|
||||
void addToPenetration(const glm::vec3& penetration) { _totalPenetration += penetration; }
|
||||
void resolvePenetrations() { addToPosition(-_totalPenetration); _totalPenetration = glm::vec3(0.f); }
|
||||
void resolvePenetrations() { addToPosition(-_totalPenetration); _totalPenetration = glm::vec3(0.0f); }
|
||||
|
||||
void setTipPosition(const glm::vec3& position) { _tipPosition = position; }
|
||||
const glm::vec3 getTipPosition() const { return _owningHandData->localToWorldPosition(_tipPosition); }
|
||||
|
|
|
@ -20,12 +20,12 @@
|
|||
#include <glm/gtc/quaternion.hpp>
|
||||
|
||||
// degrees
|
||||
const float MIN_HEAD_YAW = -180.f;
|
||||
const float MAX_HEAD_YAW = 180.f;
|
||||
const float MIN_HEAD_PITCH = -60.f;
|
||||
const float MAX_HEAD_PITCH = 60.f;
|
||||
const float MIN_HEAD_ROLL = -50.f;
|
||||
const float MAX_HEAD_ROLL = 50.f;
|
||||
const float MIN_HEAD_YAW = -180.0f;
|
||||
const float MAX_HEAD_YAW = 180.0f;
|
||||
const float MIN_HEAD_PITCH = -60.0f;
|
||||
const float MAX_HEAD_PITCH = 60.0f;
|
||||
const float MIN_HEAD_ROLL = -50.0f;
|
||||
const float MAX_HEAD_ROLL = 50.0f;
|
||||
|
||||
class AvatarData;
|
||||
|
||||
|
|
|
@ -265,7 +265,7 @@ void EntityCollisionSystem::updateCollisionWithAvatars(EntityItem* entity) {
|
|||
collision->_addedVelocity /= (float)(TREE_SCALE);
|
||||
glm::vec3 relativeVelocity = collision->_addedVelocity - entity->getVelocity();
|
||||
|
||||
if (glm::dot(relativeVelocity, collision->_penetration) <= 0.f) {
|
||||
if (glm::dot(relativeVelocity, collision->_penetration) <= 0.0f) {
|
||||
// only collide when Entity and collision point are moving toward each other
|
||||
// (doing this prevents some "collision snagging" when Entity penetrates the object)
|
||||
collision->_penetration /= (float)(TREE_SCALE);
|
||||
|
|
|
@ -90,6 +90,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID) {
|
|||
_lastEditedFromRemoteInRemoteTime = 0;
|
||||
_lastUpdated = 0;
|
||||
_created = 0;
|
||||
_updateFlags = 0;
|
||||
_changedOnServer = 0;
|
||||
initFromEntityItemID(entityItemID);
|
||||
_simulationState = EntityItem::Static;
|
||||
|
@ -102,6 +103,7 @@ EntityItem::EntityItem(const EntityItemID& entityItemID, const EntityItemPropert
|
|||
_lastEditedFromRemoteInRemoteTime = 0;
|
||||
_lastUpdated = 0;
|
||||
_created = properties.getCreated();
|
||||
_updateFlags = 0;
|
||||
_changedOnServer = 0;
|
||||
initFromEntityItemID(entityItemID);
|
||||
setProperties(properties, true); // force copy
|
||||
|
@ -465,7 +467,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
dataAt += propertyFlags.getEncodedLength();
|
||||
bytesRead += propertyFlags.getEncodedLength();
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_POSITION, glm::vec3, _position);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_POSITION, glm::vec3, updatePosition);
|
||||
|
||||
// Old bitstreams had PROP_RADIUS, new bitstreams have PROP_DIMENSIONS
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_SUPPORT_DIMENSIONS) {
|
||||
|
@ -484,7 +486,7 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
|
||||
}
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY(PROP_DIMENSIONS, glm::vec3, _dimensions);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_DIMENSIONS, glm::vec3, setDimensions);
|
||||
if (wantDebug) {
|
||||
qDebug() << " readEntityDataFromBuffer() NEW FORMAT... look for PROP_DIMENSIONS";
|
||||
}
|
||||
|
@ -494,19 +496,19 @@ int EntityItem::readEntityDataFromBuffer(const unsigned char* data, int bytesLef
|
|||
qDebug() << " readEntityDataFromBuffer() _dimensions:" << getDimensionsInMeters() << " in meters";
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_QUAT(PROP_ROTATION, _rotation);
|
||||
READ_ENTITY_PROPERTY(PROP_MASS, float, _mass);
|
||||
READ_ENTITY_PROPERTY(PROP_VELOCITY, glm::vec3, _velocity);
|
||||
READ_ENTITY_PROPERTY(PROP_GRAVITY, glm::vec3, _gravity);
|
||||
READ_ENTITY_PROPERTY_QUAT_SETTER(PROP_ROTATION, updateRotation);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_MASS, float, updateMass);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_VELOCITY, glm::vec3, updateVelocity);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_GRAVITY, glm::vec3, updateGravity);
|
||||
READ_ENTITY_PROPERTY(PROP_DAMPING, float, _damping);
|
||||
READ_ENTITY_PROPERTY(PROP_LIFETIME, float, _lifetime);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_LIFETIME, float, updateLifetime);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_SCRIPT,setScript);
|
||||
READ_ENTITY_PROPERTY(PROP_REGISTRATION_POINT, glm::vec3, _registrationPoint);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_VELOCITY, glm::vec3, _angularVelocity);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_ANGULAR_VELOCITY, glm::vec3, updateAngularVelocity);
|
||||
READ_ENTITY_PROPERTY(PROP_ANGULAR_DAMPING, float, _angularDamping);
|
||||
READ_ENTITY_PROPERTY(PROP_VISIBLE, bool, _visible);
|
||||
READ_ENTITY_PROPERTY(PROP_IGNORE_FOR_COLLISIONS, bool, _ignoreForCollisions);
|
||||
READ_ENTITY_PROPERTY(PROP_COLLISIONS_WILL_MOVE, bool, _collisionsWillMove);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_IGNORE_FOR_COLLISIONS, bool, updateIgnoreForCollisions);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_COLLISIONS_WILL_MOVE, bool, updateCollisionsWillMove);
|
||||
READ_ENTITY_PROPERTY(PROP_LOCKED, bool, _locked);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_USER_DATA,setUserData);
|
||||
|
||||
|
@ -731,11 +733,6 @@ bool EntityItem::lifetimeHasExpired() const {
|
|||
return isMortal() && (getAge() > getLifetime());
|
||||
}
|
||||
|
||||
|
||||
void EntityItem::copyChangedProperties(const EntityItem& other) {
|
||||
*this = other;
|
||||
}
|
||||
|
||||
EntityItemProperties EntityItem::getProperties() const {
|
||||
EntityItemProperties properties;
|
||||
properties._id = getID();
|
||||
|
@ -947,4 +944,111 @@ void EntityItem::recalculateCollisionShape() {
|
|||
_collisionShape.setScale(entityAACube.getScale());
|
||||
}
|
||||
|
||||
void EntityItem::updatePosition(const glm::vec3& value) {
|
||||
if (_position != value) {
|
||||
_position = value;
|
||||
recalculateCollisionShape();
|
||||
_updateFlags |= EntityItem::UPDATE_POSITION;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updatePositionInMeters(const glm::vec3& value) {
|
||||
glm::vec3 position = glm::clamp(value / (float) TREE_SCALE, 0.0f, 1.0f);
|
||||
if (_position != position) {
|
||||
_position = position;
|
||||
recalculateCollisionShape();
|
||||
_updateFlags |= EntityItem::UPDATE_POSITION;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateDimensions(const glm::vec3& value) {
|
||||
if (_dimensions != value) {
|
||||
_dimensions = value;
|
||||
recalculateCollisionShape();
|
||||
_updateFlags |= EntityItem::UPDATE_SHAPE;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateDimensionsInMeters(const glm::vec3& value) {
|
||||
glm::vec3 dimensions = value / (float) TREE_SCALE;
|
||||
if (_dimensions != dimensions) {
|
||||
_dimensions = dimensions;
|
||||
recalculateCollisionShape();
|
||||
_updateFlags |= EntityItem::UPDATE_SHAPE;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateRotation(const glm::quat& rotation) {
|
||||
if (_rotation != rotation) {
|
||||
_rotation = rotation;
|
||||
recalculateCollisionShape();
|
||||
_updateFlags |= EntityItem::UPDATE_POSITION;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateMass(float value) {
|
||||
if (_mass != value) {
|
||||
_mass = value;
|
||||
_updateFlags |= EntityItem::UPDATE_MASS;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateVelocity(const glm::vec3& value) {
|
||||
if (_velocity != value) {
|
||||
_velocity = value;
|
||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateVelocityInMeters(const glm::vec3& value) {
|
||||
glm::vec3 velocity = value / (float) TREE_SCALE;
|
||||
if (_velocity != velocity) {
|
||||
_velocity = velocity;
|
||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateGravity(const glm::vec3& value) {
|
||||
if (_gravity != value) {
|
||||
_gravity = value;
|
||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateGravityInMeters(const glm::vec3& value) {
|
||||
glm::vec3 gravity = value / (float) TREE_SCALE;
|
||||
if (_gravity != gravity) {
|
||||
_gravity = gravity;
|
||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateAngularVelocity(const glm::vec3& value) {
|
||||
if (_angularVelocity != value) {
|
||||
_angularVelocity = value;
|
||||
_updateFlags |= EntityItem::UPDATE_VELOCITY;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateIgnoreForCollisions(bool value) {
|
||||
if (_ignoreForCollisions != value) {
|
||||
_ignoreForCollisions = value;
|
||||
_updateFlags |= EntityItem::UPDATE_COLLISION_GROUP;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateCollisionsWillMove(bool value) {
|
||||
if (_collisionsWillMove != value) {
|
||||
_collisionsWillMove = value;
|
||||
_updateFlags |= EntityItem::UPDATE_MOTION_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::updateLifetime(float value) {
|
||||
if (_lifetime != value) {
|
||||
_lifetime = value;
|
||||
_updateFlags |= EntityItem::UPDATE_LIFETIME;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -35,13 +35,23 @@ class EntityTreeElementExtraEncodeData;
|
|||
#define DONT_ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() = 0;
|
||||
#define ALLOW_INSTANTIATION virtual void pureVirtualFunctionPlaceHolder() { };
|
||||
|
||||
|
||||
/// EntityItem class this is the base class for all entity types. It handles the basic properties and functionality available
|
||||
/// to all other entity types. In particular: postion, size, rotation, age, lifetime, velocity, gravity. You can not instantiate
|
||||
/// one directly, instead you must only construct one of it's derived classes with additional features.
|
||||
class EntityItem {
|
||||
|
||||
public:
|
||||
enum EntityUpdateFlags {
|
||||
UPDATE_POSITION = 0x0001,
|
||||
UPDATE_VELOCITY = 0x0002,
|
||||
UPDATE_MASS = 0x0004,
|
||||
UPDATE_COLLISION_GROUP = 0x0008,
|
||||
UPDATE_MOTION_TYPE = 0x0010,
|
||||
UPDATE_SHAPE = 0x0020,
|
||||
UPDATE_LIFETIME = 0x0040
|
||||
//UPDATE_APPEARANCE = 0x8000,
|
||||
};
|
||||
|
||||
DONT_ALLOW_INSTANTIATION // This class can not be instantiated directly
|
||||
|
||||
EntityItem(const EntityItemID& entityItemID);
|
||||
|
@ -125,9 +135,6 @@ public:
|
|||
|
||||
virtual void debugDump() const;
|
||||
|
||||
// similar to assignment/copy, but it handles keeping lifetime accurate
|
||||
void copyChangedProperties(const EntityItem& other);
|
||||
|
||||
// attributes applicable to all entity types
|
||||
EntityTypes::EntityType getType() const { return _type; }
|
||||
const glm::vec3& getPosition() const { return _position; } /// get position in domain scale units (0.0 - 1.0)
|
||||
|
@ -266,6 +273,30 @@ public:
|
|||
virtual const Shape& getCollisionShapeInMeters() const { return _collisionShape; }
|
||||
virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); }
|
||||
|
||||
// updateFoo() methods to be used when changes need to be accumulated in the _updateFlags
|
||||
void updatePosition(const glm::vec3& value);
|
||||
void updatePositionInMeters(const glm::vec3& value);
|
||||
void updateDimensions(const glm::vec3& value);
|
||||
void updateDimensionsInMeters(const glm::vec3& value);
|
||||
void updateRotation(const glm::quat& rotation);
|
||||
void updateMass(float value);
|
||||
void updateVelocity(const glm::vec3& value);
|
||||
void updateVelocityInMeters(const glm::vec3& value);
|
||||
void updateGravity(const glm::vec3& value);
|
||||
void updateGravityInMeters(const glm::vec3& value);
|
||||
void updateAngularVelocity(const glm::vec3& value);
|
||||
void updateIgnoreForCollisions(bool value);
|
||||
void updateCollisionsWillMove(bool value);
|
||||
void updateLifetime(float value);
|
||||
|
||||
uint32_t getUpdateFlags() const { return _updateFlags; }
|
||||
void clearUpdateFlags() { _updateFlags = 0; }
|
||||
|
||||
#ifdef USE_BULLET_PHYSICS
|
||||
EntityMotionState* getMotionState() const { return _motionState; }
|
||||
virtual EntityMotionState* createMotionState() { return NULL; }
|
||||
void destroyMotionState();
|
||||
#endif // USE_BULLET_PHYSICS
|
||||
SimulationState getSimulationState() const { return _simulationState; }
|
||||
|
||||
protected:
|
||||
|
@ -314,6 +345,10 @@ protected:
|
|||
|
||||
AACubeShape _collisionShape;
|
||||
SimulationState _simulationState; // only set by EntityTree
|
||||
|
||||
// UpdateFlags are set whenever a property changes that requires the change to be communicated to other
|
||||
// data structures. It is the responsibility of the EntityTree to relay changes entity and clear flags.
|
||||
uint32_t _updateFlags;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -63,6 +63,17 @@
|
|||
} \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_QUAT_SETTER(P,M) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
glm::quat fromBuffer; \
|
||||
int bytes = unpackOrientationQuatFromBytes(dataAt, fromBuffer); \
|
||||
dataAt += bytes; \
|
||||
bytesRead += bytes; \
|
||||
if (overwriteLocalData) { \
|
||||
M(fromBuffer); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define READ_ENTITY_PROPERTY_STRING(P,O) \
|
||||
if (propertyFlags.getHasProperty(P)) { \
|
||||
uint16_t length; \
|
||||
|
|
|
@ -44,6 +44,20 @@ EntityItemID EntityScriptingInterface::addEntity(const EntityItemProperties& pro
|
|||
return id;
|
||||
}
|
||||
|
||||
EntityItemID EntityScriptingInterface::getEntityItemID(const QString& uuid) {
|
||||
EntityItemID entityID = EntityItemID(QUuid(uuid), UNKNOWN_ENTITY_TOKEN, false);
|
||||
|
||||
_entityTree->lockForRead();
|
||||
EntityItem* entity = const_cast<EntityItem*>(_entityTree->findEntityByEntityItemID(entityID));
|
||||
_entityTree->unlock();
|
||||
|
||||
if (entity) {
|
||||
return entity->getEntityItemID();
|
||||
}
|
||||
|
||||
return entityID;
|
||||
}
|
||||
|
||||
EntityItemID EntityScriptingInterface::identifyEntity(EntityItemID entityID) {
|
||||
EntityItemID actualID = entityID;
|
||||
|
||||
|
|
|
@ -64,6 +64,9 @@ public slots:
|
|||
/// adds a model with the specific properties
|
||||
Q_INVOKABLE EntityItemID addEntity(const EntityItemProperties& properties);
|
||||
|
||||
// Get EntityItemID from uuid string
|
||||
Q_INVOKABLE EntityItemID getEntityItemID(const QString& entityID);
|
||||
|
||||
/// identify a recently created model to determine its true ID
|
||||
Q_INVOKABLE EntityItemID identifyEntity(EntityItemID entityID);
|
||||
|
||||
|
|
|
@ -657,12 +657,13 @@ void EntityTree::updateChangedEntities(quint64 now, QSet<EntityItemID>& entities
|
|||
foreach (EntityItem* thisEntity, _changedEntities) {
|
||||
// check to see if the lifetime has expired, for immortal entities this is always false
|
||||
if (thisEntity->lifetimeHasExpired()) {
|
||||
qDebug() << "Lifetime has expired for thisEntity:" << thisEntity->getEntityItemID();
|
||||
qDebug() << "Lifetime has expired for entity:" << thisEntity->getEntityItemID();
|
||||
entitiesToDelete << thisEntity->getEntityItemID();
|
||||
clearEntityState(thisEntity);
|
||||
} else {
|
||||
updateEntityState(thisEntity);
|
||||
}
|
||||
thisEntity->clearUpdateFlags();
|
||||
}
|
||||
_changedEntities.clear();
|
||||
}
|
||||
|
|
|
@ -621,7 +621,7 @@ void EntityTreeElement::getEntities(const AACube& box, QVector<EntityItem*>& fou
|
|||
// NOTE: we actually do cube-cube collision queries here, which is sloppy but good enough for now
|
||||
// TODO: decide whether to replace entityCube-cube query with sphere-cube (requires a square root
|
||||
// but will be slightly more accurate).
|
||||
entityCube.setBox(entity->getPosition() - glm::vec3(radius), 2.f * radius);
|
||||
entityCube.setBox(entity->getPosition() - glm::vec3(radius), 2.0f * radius);
|
||||
if (entityCube.touches(box)) {
|
||||
foundEntities.push_back(entity);
|
||||
}
|
||||
|
@ -739,8 +739,9 @@ int EntityTreeElement::readElementDataFromBuffer(const unsigned char* data, int
|
|||
EntityTreeElement* currentContainingElement = _myTree->getContainingElement(entityItemID);
|
||||
|
||||
bytesForThisEntity = entityItem->readEntityDataFromBuffer(dataAt, bytesLeftToRead, args);
|
||||
// TODO: Andrew to only set changed if something has actually changed
|
||||
_myTree->entityChanged(entityItem);
|
||||
if (entityItem->getUpdateFlags()) {
|
||||
_myTree->entityChanged(entityItem);
|
||||
}
|
||||
bool bestFitAfter = bestFitEntityBounds(entityItem);
|
||||
|
||||
if (bestFitBefore != bestFitAfter) {
|
||||
|
|
|
@ -47,6 +47,13 @@ UpdateEntityOperator::UpdateEntityOperator(EntityTree* tree,
|
|||
// the getMaximumAACube is the relaxed form.
|
||||
_oldEntityCube = _existingEntity->getMaximumAACube();
|
||||
_oldEntityBox = _oldEntityCube.clamp(0.0f, 1.0f); // clamp to domain bounds
|
||||
|
||||
// If the old properties doesn't contain the properties required to calculate a bounding box,
|
||||
// get them from the existing entity. Registration point is required to correctly calculate
|
||||
// the bounding box.
|
||||
if (!_properties.registrationPointChanged()) {
|
||||
_properties.setRegistrationPoint(_existingEntity->getRegistrationPoint());
|
||||
}
|
||||
|
||||
// If the new properties has position OR dimension changes, but not both, we need to
|
||||
// get the old property value and set it in our properties in order for our bounds
|
||||
|
|
|
@ -993,7 +993,7 @@ class JointShapeInfo {
|
|||
public:
|
||||
JointShapeInfo() : numVertices(0),
|
||||
sumVertexWeights(0.0f), sumWeightedRadii(0.0f), numVertexWeights(0),
|
||||
averageVertex(0.f), boneBegin(0.f), averageRadius(0.f) {
|
||||
averageVertex(0.0f), boneBegin(0.0f), averageRadius(0.0f) {
|
||||
}
|
||||
|
||||
// NOTE: the points here are in the "joint frame" which has the "jointEnd" at the origin
|
||||
|
@ -1077,6 +1077,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
QString jointHeadID;
|
||||
QString jointLeftHandID;
|
||||
QString jointRightHandID;
|
||||
QString jointLeftToeID;
|
||||
QString jointRightToeID;
|
||||
|
||||
QVector<QString> humanIKJointNames;
|
||||
for (int i = 0;; i++) {
|
||||
|
@ -1176,11 +1178,17 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
} else if (name == jointHeadName) {
|
||||
jointHeadID = getID(object.properties);
|
||||
|
||||
} else if (name == jointLeftHandName) {
|
||||
} else if (name == jointLeftHandName || name == "LeftHand" || name == "joint_L_hand") {
|
||||
jointLeftHandID = getID(object.properties);
|
||||
|
||||
} else if (name == jointRightHandName) {
|
||||
} else if (name == jointRightHandName || name == "RightHand" || name == "joint_R_hand") {
|
||||
jointRightHandID = getID(object.properties);
|
||||
|
||||
} else if (name == "LeftToe" || name == "joint_L_toe" || name == "LeftToe_End") {
|
||||
jointLeftToeID = getID(object.properties);
|
||||
|
||||
} else if (name == "RightToe" || name == "joint_R_toe" || name == "RightToe_End") {
|
||||
jointRightToeID = getID(object.properties);
|
||||
}
|
||||
int humanIKJointIndex = humanIKJointNames.indexOf(name);
|
||||
if (humanIKJointIndex != -1) {
|
||||
|
@ -1576,7 +1584,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
joint.boneRadius = 0.0f;
|
||||
joint.inverseBindRotation = joint.inverseDefaultRotation;
|
||||
joint.name = model.name;
|
||||
joint.shapePosition = glm::vec3(0.f);
|
||||
joint.shapePosition = glm::vec3(0.0f);
|
||||
joint.shapeType = SHAPE_TYPE_UNKNOWN;
|
||||
|
||||
foreach (const QString& childID, childMap.values(modelID)) {
|
||||
|
@ -1615,6 +1623,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
geometry.headJointIndex = modelIDs.indexOf(jointHeadID);
|
||||
geometry.leftHandJointIndex = modelIDs.indexOf(jointLeftHandID);
|
||||
geometry.rightHandJointIndex = modelIDs.indexOf(jointRightHandID);
|
||||
geometry.leftToeJointIndex = modelIDs.indexOf(jointLeftToeID);
|
||||
geometry.rightToeJointIndex = modelIDs.indexOf(jointRightToeID);
|
||||
|
||||
foreach (const QString& id, humanIKJointIDs) {
|
||||
geometry.humanIKJointIndices.append(modelIDs.indexOf(id));
|
||||
|
@ -1917,7 +1927,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
}
|
||||
float radiusScale = extractUniformScale(joint.transform * firstFBXCluster.inverseBindMatrix);
|
||||
|
||||
glm::vec3 averageVertex(0.f);
|
||||
glm::vec3 averageVertex(0.0f);
|
||||
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
||||
float proj = glm::dot(boneDirection, boneEnd - vertex);
|
||||
float radiusWeight = (proj < 0.0f || proj > boneLength) ? 0.5f : 1.0f;
|
||||
|
@ -1933,7 +1943,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
jointShapeInfo.numVertices = numVertices;
|
||||
if (numVertices > 0) {
|
||||
averageVertex /= (float)jointShapeInfo.numVertices;
|
||||
float averageRadius = 0.f;
|
||||
float averageRadius = 0.0f;
|
||||
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
|
||||
averageRadius += glm::distance(vertex, averageVertex);
|
||||
}
|
||||
|
@ -1949,7 +1959,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
}
|
||||
|
||||
// now that all joints have been scanned, compute a collision shape for each joint
|
||||
glm::vec3 defaultCapsuleAxis(0.f, 1.f, 0.f);
|
||||
glm::vec3 defaultCapsuleAxis(0.0f, 1.0f, 0.0f);
|
||||
for (int i = 0; i < geometry.joints.size(); ++i) {
|
||||
FBXJoint& joint = geometry.joints[i];
|
||||
JointShapeInfo& jointShapeInfo = jointShapeInfos[i];
|
||||
|
@ -1982,7 +1992,7 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
|
|||
jointShapeInfo.averageVertex /= (float)jointShapeInfo.numVertices;
|
||||
joint.shapePosition = jointShapeInfo.averageVertex;
|
||||
} else {
|
||||
joint.shapePosition = glm::vec3(0.f);
|
||||
joint.shapePosition = glm::vec3(0.0f);
|
||||
}
|
||||
if (jointShapeInfo.numVertexWeights == 0
|
||||
&& jointShapeInfo.numVertices > 0) {
|
||||
|
|
|
@ -203,6 +203,8 @@ public:
|
|||
int headJointIndex;
|
||||
int leftHandJointIndex;
|
||||
int rightHandJointIndex;
|
||||
int leftToeJointIndex;
|
||||
int rightToeJointIndex;
|
||||
|
||||
QVector<int> humanIKJointIndices;
|
||||
|
||||
|
|
|
@ -131,7 +131,7 @@ bool AddressManager::handleUrl(const QUrl& lookupUrl) {
|
|||
void AddressManager::handleLookupString(const QString& lookupString) {
|
||||
if (!lookupString.isEmpty()) {
|
||||
// make this a valid hifi URL and handle it off to handleUrl
|
||||
QString sanitizedString = lookupString;
|
||||
QString sanitizedString = lookupString.trimmed();
|
||||
QUrl lookupURL;
|
||||
|
||||
if (!lookupString.startsWith('/')) {
|
||||
|
|
|
@ -21,57 +21,57 @@
|
|||
// NOTE: if adding a new packet type, you can replace one marked usable or add at the end
|
||||
// NOTE: if you want the name of the packet type to be available for debugging or logging, update nameForPacketType() as well
|
||||
enum PacketType {
|
||||
PacketTypeUnknown,
|
||||
PacketTypeUnknown, // 0
|
||||
PacketTypeStunResponse,
|
||||
PacketTypeDomainList,
|
||||
PacketTypePing,
|
||||
PacketTypePingReply,
|
||||
PacketTypeKillAvatar,
|
||||
PacketTypeKillAvatar, // 5
|
||||
PacketTypeAvatarData,
|
||||
PacketTypeInjectAudio,
|
||||
PacketTypeMixedAudio,
|
||||
PacketTypeMicrophoneAudioNoEcho,
|
||||
PacketTypeMicrophoneAudioWithEcho,
|
||||
PacketTypeMicrophoneAudioWithEcho, // 10
|
||||
PacketTypeBulkAvatarData,
|
||||
PacketTypeSilentAudioFrame,
|
||||
PacketTypeEnvironmentData,
|
||||
PacketTypeDomainListRequest,
|
||||
PacketTypeRequestAssignment,
|
||||
PacketTypeRequestAssignment, // 15
|
||||
PacketTypeCreateAssignment,
|
||||
PacketTypeDomainConnectionDenied,
|
||||
PacketTypeMuteEnvironment,
|
||||
PacketTypeAudioStreamStats,
|
||||
PacketTypeDataServerConfirm,
|
||||
PacketTypeDataServerConfirm, // 20
|
||||
PacketTypeVoxelQuery,
|
||||
PacketTypeVoxelData,
|
||||
PacketTypeVoxelSet,
|
||||
PacketTypeVoxelSetDestructive,
|
||||
PacketTypeVoxelErase,
|
||||
PacketTypeOctreeStats, // 26
|
||||
PacketTypeVoxelErase, // 25
|
||||
PacketTypeOctreeStats,
|
||||
PacketTypeJurisdiction,
|
||||
PacketTypeJurisdictionRequest,
|
||||
UNUSED_1,
|
||||
UNUSED_2,
|
||||
UNUSED_2, // 30
|
||||
UNUSED_3,
|
||||
UNUSED_4,
|
||||
PacketTypeNoisyMute,
|
||||
PacketTypeMetavoxelData,
|
||||
PacketTypeAvatarIdentity,
|
||||
PacketTypeAvatarIdentity, // 35
|
||||
PacketTypeAvatarBillboard,
|
||||
PacketTypeDomainConnectRequest,
|
||||
PacketTypeDomainServerRequireDTLS,
|
||||
PacketTypeNodeJsonStats,
|
||||
PacketTypeEntityQuery,
|
||||
PacketTypeEntityData, // 41
|
||||
PacketTypeEntityQuery, // 40
|
||||
PacketTypeEntityData,
|
||||
PacketTypeEntityAddOrEdit,
|
||||
PacketTypeEntityErase,
|
||||
PacketTypeEntityAddResponse,
|
||||
PacketTypeOctreeDataNack, // 45
|
||||
PacketTypeVoxelEditNack,
|
||||
PacketTypeAudioEnvironment,
|
||||
PacketTypeEntityEditNack, // 48
|
||||
PacketTypeEntityEditNack,
|
||||
PacketTypeSignedTransactionPayment,
|
||||
PacketTypeIceServerHeartbeat,
|
||||
PacketTypeIceServerHeartbeat, // 50
|
||||
PacketTypeIceServerHeartbeatResponse,
|
||||
PacketTypeUnverifiedPing,
|
||||
PacketTypeUnverifiedPingReply
|
||||
|
|
|
@ -24,7 +24,7 @@ bool CoverageMap::wantDebugging = false;
|
|||
|
||||
const int MAX_POLYGONS_PER_REGION = 50;
|
||||
|
||||
const BoundingBox CoverageMap::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.f,-1.f), glm::vec2(2.f,2.f));
|
||||
const BoundingBox CoverageMap::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.0f,-1.0f), glm::vec2(2.0f,2.0f));
|
||||
|
||||
// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space.
|
||||
//
|
||||
|
|
|
@ -23,7 +23,7 @@ int CoverageMapV2::_checkMapRootCalls = 0;
|
|||
int CoverageMapV2::_notAllInView = 0;
|
||||
bool CoverageMapV2::wantDebugging = false;
|
||||
|
||||
const BoundingBox CoverageMapV2::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.f,-1.f), glm::vec2(2.f,2.f));
|
||||
const BoundingBox CoverageMapV2::ROOT_BOUNDING_BOX = BoundingBox(glm::vec2(-1.0f,-1.0f), glm::vec2(2.0f,2.0f));
|
||||
|
||||
// Coverage Map's polygon coordinates are from -1 to 1 in the following mapping to screen space.
|
||||
//
|
||||
|
|
|
@ -27,8 +27,8 @@
|
|||
|
||||
const float DEFAULT_KEYHOLE_RADIUS = 3.0f;
|
||||
const float DEFAULT_FIELD_OF_VIEW_DEGREES = 45.0f;
|
||||
const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.f;
|
||||
const float DEFAULT_ASPECT_RATIO = 16.f/9.f;
|
||||
const float DEFAULT_REAL_WORLD_FIELD_OF_VIEW_DEGREES = 30.0f;
|
||||
const float DEFAULT_ASPECT_RATIO = 16.0f/9.0f;
|
||||
const float DEFAULT_NEAR_CLIP = 0.08f;
|
||||
const float DEFAULT_FAR_CLIP = TREE_SCALE;
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ CollisionInfo::CollisionInfo() :
|
|||
_intData(0),
|
||||
_shapeA(NULL),
|
||||
_shapeB(NULL),
|
||||
_damping(0.f),
|
||||
_elasticity(1.f),
|
||||
_contactPoint(0.f),
|
||||
_penetration(0.f),
|
||||
_addedVelocity(0.f) {
|
||||
_damping(0.0f),
|
||||
_elasticity(1.0f),
|
||||
_contactPoint(0.0f),
|
||||
_penetration(0.0f),
|
||||
_addedVelocity(0.0f) {
|
||||
}
|
||||
|
||||
quint64 CollisionInfo::getShapePairKey() const {
|
||||
|
|
|
@ -73,11 +73,11 @@ void ListShape::clear() {
|
|||
delete _subShapeEntries[i]._shape;
|
||||
}
|
||||
_subShapeEntries.clear();
|
||||
setBoundingRadius(0.f);
|
||||
setBoundingRadius(0.0f);
|
||||
}
|
||||
|
||||
void ListShape::computeBoundingRadius() {
|
||||
float maxRadius = 0.f;
|
||||
float maxRadius = 0.0f;
|
||||
for (int i = 0; i < _subShapeEntries.size(); ++i) {
|
||||
ListShapeEntry& entry = _subShapeEntries[i];
|
||||
float radius = glm::length(entry._localPosition) + entry._shape->getBoundingRadius();
|
||||
|
|
|
@ -39,8 +39,8 @@ public:
|
|||
|
||||
static quint32 getNextID() { static quint32 nextID = 0; return ++nextID; }
|
||||
|
||||
Shape() : _type(UNKNOWN_SHAPE), _owningEntity(NULL), _boundingRadius(0.f),
|
||||
_translation(0.f), _rotation(), _mass(MAX_SHAPE_MASS) {
|
||||
Shape() : _type(UNKNOWN_SHAPE), _owningEntity(NULL), _boundingRadius(0.0f),
|
||||
_translation(0.0f), _rotation(), _mass(MAX_SHAPE_MASS) {
|
||||
_id = getNextID();
|
||||
}
|
||||
virtual ~Shape() { }
|
||||
|
@ -87,20 +87,20 @@ public:
|
|||
protected:
|
||||
// these ctors are protected (used by derived classes only)
|
||||
Shape(Type type) : _type(type), _owningEntity(NULL),
|
||||
_boundingRadius(0.f), _translation(0.f),
|
||||
_boundingRadius(0.0f), _translation(0.0f),
|
||||
_rotation(), _mass(MAX_SHAPE_MASS) {
|
||||
_id = getNextID();
|
||||
}
|
||||
|
||||
Shape(Type type, const glm::vec3& position) :
|
||||
_type(type), _owningEntity(NULL),
|
||||
_boundingRadius(0.f), _translation(position),
|
||||
_boundingRadius(0.0f), _translation(position),
|
||||
_rotation(), _mass(MAX_SHAPE_MASS) {
|
||||
_id = getNextID();
|
||||
}
|
||||
|
||||
Shape(Type type, const glm::vec3& position, const glm::quat& rotation) : _type(type), _owningEntity(NULL),
|
||||
_boundingRadius(0.f), _translation(position),
|
||||
_boundingRadius(0.0f), _translation(position),
|
||||
_rotation(rotation), _mass(MAX_SHAPE_MASS) {
|
||||
_id = getNextID();
|
||||
}
|
||||
|
|
|
@ -1139,7 +1139,7 @@ bool sphereAACube_StarkAngles(const glm::vec3& sphereCenter, float sphereRadius,
|
|||
glm::vec3 surfaceB = cubeCenter - (0.5f * cubeSide / maxBA) * BA;
|
||||
// collision happens when "vector to surfaceA from surfaceB" dots with BA to produce a positive value
|
||||
glm::vec3 surfaceAB = surfaceA - surfaceB;
|
||||
if (glm::dot(surfaceAB, BA) > 0.f) {
|
||||
if (glm::dot(surfaceAB, BA) > 0.0f) {
|
||||
CollisionInfo* collision = collisions.getNewCollision();
|
||||
if (collision) {
|
||||
// penetration is parallel to box side direction
|
||||
|
|
|
@ -72,27 +72,27 @@ int unpackFloatVec3FromSignedTwoByteFixed(const unsigned char* sourceBuffer, glm
|
|||
|
||||
|
||||
int packFloatAngleToTwoByte(unsigned char* buffer, float degrees) {
|
||||
const float ANGLE_CONVERSION_RATIO = (std::numeric_limits<uint16_t>::max() / 360.f);
|
||||
const float ANGLE_CONVERSION_RATIO = (std::numeric_limits<uint16_t>::max() / 360.0f);
|
||||
|
||||
uint16_t angleHolder = floorf((degrees + 180.f) * ANGLE_CONVERSION_RATIO);
|
||||
uint16_t angleHolder = floorf((degrees + 180.0f) * ANGLE_CONVERSION_RATIO);
|
||||
memcpy(buffer, &angleHolder, sizeof(uint16_t));
|
||||
|
||||
return sizeof(uint16_t);
|
||||
}
|
||||
|
||||
int unpackFloatAngleFromTwoByte(const uint16_t* byteAnglePointer, float* destinationPointer) {
|
||||
*destinationPointer = (*byteAnglePointer / (float) std::numeric_limits<uint16_t>::max()) * 360.f - 180.f;
|
||||
*destinationPointer = (*byteAnglePointer / (float) std::numeric_limits<uint16_t>::max()) * 360.0f - 180.0f;
|
||||
return sizeof(uint16_t);
|
||||
}
|
||||
|
||||
int packOrientationQuatToBytes(unsigned char* buffer, const glm::quat& quatInput) {
|
||||
glm::quat quatNormalized = glm::normalize(quatInput);
|
||||
const float QUAT_PART_CONVERSION_RATIO = (std::numeric_limits<uint16_t>::max() / 2.f);
|
||||
const float QUAT_PART_CONVERSION_RATIO = (std::numeric_limits<uint16_t>::max() / 2.0f);
|
||||
uint16_t quatParts[4];
|
||||
quatParts[0] = floorf((quatNormalized.x + 1.f) * QUAT_PART_CONVERSION_RATIO);
|
||||
quatParts[1] = floorf((quatNormalized.y + 1.f) * QUAT_PART_CONVERSION_RATIO);
|
||||
quatParts[2] = floorf((quatNormalized.z + 1.f) * QUAT_PART_CONVERSION_RATIO);
|
||||
quatParts[3] = floorf((quatNormalized.w + 1.f) * QUAT_PART_CONVERSION_RATIO);
|
||||
quatParts[0] = floorf((quatNormalized.x + 1.0f) * QUAT_PART_CONVERSION_RATIO);
|
||||
quatParts[1] = floorf((quatNormalized.y + 1.0f) * QUAT_PART_CONVERSION_RATIO);
|
||||
quatParts[2] = floorf((quatNormalized.z + 1.0f) * QUAT_PART_CONVERSION_RATIO);
|
||||
quatParts[3] = floorf((quatNormalized.w + 1.0f) * QUAT_PART_CONVERSION_RATIO);
|
||||
|
||||
memcpy(buffer, &quatParts, sizeof(quatParts));
|
||||
return sizeof(quatParts);
|
||||
|
@ -102,10 +102,10 @@ int unpackOrientationQuatFromBytes(const unsigned char* buffer, glm::quat& quatO
|
|||
uint16_t quatParts[4];
|
||||
memcpy(&quatParts, buffer, sizeof(quatParts));
|
||||
|
||||
quatOutput.x = ((quatParts[0] / (float) std::numeric_limits<uint16_t>::max()) * 2.f) - 1.f;
|
||||
quatOutput.y = ((quatParts[1] / (float) std::numeric_limits<uint16_t>::max()) * 2.f) - 1.f;
|
||||
quatOutput.z = ((quatParts[2] / (float) std::numeric_limits<uint16_t>::max()) * 2.f) - 1.f;
|
||||
quatOutput.w = ((quatParts[3] / (float) std::numeric_limits<uint16_t>::max()) * 2.f) - 1.f;
|
||||
quatOutput.x = ((quatParts[0] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
|
||||
quatOutput.y = ((quatParts[1] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
|
||||
quatOutput.z = ((quatParts[2] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
|
||||
quatOutput.w = ((quatParts[3] / (float) std::numeric_limits<uint16_t>::max()) * 2.0f) - 1.0f;
|
||||
|
||||
return sizeof(quatParts);
|
||||
}
|
||||
|
|
|
@ -131,9 +131,9 @@ bool findSphereDiskPenetration(const glm::vec3& sphereCenter, float sphereRadius
|
|||
if (glm::length(localCenter - axialOffset) < diskRadius) {
|
||||
// yes, hit the disk
|
||||
penetration = (std::fabs(axialDistance) - (sphereRadius + 0.5f * diskThickness) ) * diskNormal;
|
||||
if (axialDistance < 0.f) {
|
||||
if (axialDistance < 0.0f) {
|
||||
// hit the backside of the disk, so negate penetration vector
|
||||
penetration *= -1.f;
|
||||
penetration *= -1.0f;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -98,7 +98,7 @@ quint64 usecTimestampNow(bool wantDebug) {
|
|||
}
|
||||
|
||||
float randFloat() {
|
||||
return (rand() % 10000)/10000.f;
|
||||
return (rand() % 10000)/10000.0f;
|
||||
}
|
||||
|
||||
int randIntInRange (int min, int max) {
|
||||
|
@ -106,7 +106,7 @@ int randIntInRange (int min, int max) {
|
|||
}
|
||||
|
||||
float randFloatInRange (float min,float max) {
|
||||
return min + ((rand() % 10000)/10000.f * (max-min));
|
||||
return min + ((rand() % 10000)/10000.0f * (max-min));
|
||||
}
|
||||
|
||||
float randomSign() {
|
||||
|
@ -501,8 +501,8 @@ int removeFromSortedArrays(void* value, void** valueArray, float* keyArray, int*
|
|||
return -1; // error case
|
||||
}
|
||||
|
||||
float SMALL_LIMIT = 10.f;
|
||||
float LARGE_LIMIT = 1000.f;
|
||||
float SMALL_LIMIT = 10.0f;
|
||||
float LARGE_LIMIT = 1000.0f;
|
||||
|
||||
int packFloatRatioToTwoByte(unsigned char* buffer, float ratio) {
|
||||
// if the ratio is less than 10, then encode it as a positive number scaled from 0 to int16::max()
|
||||
|
|
|
@ -49,14 +49,14 @@ static const float ONE_HALF = 0.5f;
|
|||
static const float ONE_THIRD = 0.333333f;
|
||||
|
||||
static const float PI = 3.14159265358979f;
|
||||
static const float TWO_PI = 2.f * PI;
|
||||
static const float TWO_PI = 2.0f * PI;
|
||||
static const float PI_OVER_TWO = ONE_HALF * PI;
|
||||
static const float RADIANS_PER_DEGREE = PI / 180.0f;
|
||||
static const float DEGREES_PER_RADIAN = 180.0f / PI;
|
||||
|
||||
static const float EPSILON = 0.000001f; //smallish positive number - used as margin of error for some computations
|
||||
static const float SQUARE_ROOT_OF_2 = (float)sqrt(2.f);
|
||||
static const float SQUARE_ROOT_OF_3 = (float)sqrt(3.f);
|
||||
static const float SQUARE_ROOT_OF_2 = (float)sqrt(2.0f);
|
||||
static const float SQUARE_ROOT_OF_3 = (float)sqrt(3.0f);
|
||||
static const float METERS_PER_DECIMETER = 0.1f;
|
||||
static const float METERS_PER_CENTIMETER = 0.01f;
|
||||
static const float METERS_PER_MILLIMETER = 0.001f;
|
||||
|
|
|
@ -86,7 +86,7 @@ std::ostream& operator<<(std::ostream& s, const SphereShape& sphere) {
|
|||
std::ostream& operator<<(std::ostream& s, const CapsuleShape& capsule) {
|
||||
s << "{type='capsule', center=" << capsule.getPosition()
|
||||
<< ", radius=" << capsule.getRadius()
|
||||
<< ", length=" << (2.f * capsule.getHalfHeight())
|
||||
<< ", length=" << (2.0f * capsule.getHalfHeight())
|
||||
<< ", begin=" << capsule.getStartPoint()
|
||||
<< ", end=" << capsule.getEndPoint()
|
||||
<< "}";
|
||||
|
|
|
@ -15,28 +15,28 @@
|
|||
void Transform::evalRotationScale(Quat& rotation, Vec3& scale, const Mat3& rotationScaleMatrix) {
|
||||
const float ACCURACY_THREASHOLD = 0.00001f;
|
||||
|
||||
// Following technique taken from:
|
||||
// http://callumhay.blogspot.com/2010/10/decomposing-affine-transforms.html
|
||||
// Extract the rotation component - this is done using polar decompostion, where
|
||||
// we successively average the matrix with its inverse transpose until there is
|
||||
// no/a very small difference between successive averages
|
||||
float norm;
|
||||
int count = 0;
|
||||
Mat3 rotationMat = rotationScaleMatrix;
|
||||
do {
|
||||
Mat3 currInvTranspose = glm::inverse(glm::transpose(rotationMat));
|
||||
|
||||
Mat3 nextRotation = 0.5f * (rotationMat + currInvTranspose);
|
||||
|
||||
norm = 0.0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
float n = static_cast<float>(
|
||||
fabs(rotationMat[0][i] - nextRotation[0][i]) +
|
||||
fabs(rotationMat[1][i] - nextRotation[1][i]) +
|
||||
fabs(rotationMat[2][i] - nextRotation[2][i]));
|
||||
norm = (norm > n ? norm : n);
|
||||
}
|
||||
rotationMat = nextRotation;
|
||||
// Following technique taken from:
|
||||
// http://callumhay.blogspot.com/2010/10/decomposing-affine-transforms.html
|
||||
// Extract the rotation component - this is done using polar decompostion, where
|
||||
// we successively average the matrix with its inverse transpose until there is
|
||||
// no/a very small difference between successive averages
|
||||
float norm;
|
||||
int count = 0;
|
||||
Mat3 rotationMat = rotationScaleMatrix;
|
||||
do {
|
||||
Mat3 currInvTranspose = glm::inverse(glm::transpose(rotationMat));
|
||||
|
||||
Mat3 nextRotation = 0.5f * (rotationMat + currInvTranspose);
|
||||
|
||||
norm = 0.0;
|
||||
for (int i = 0; i < 3; i++) {
|
||||
float n = static_cast<float>(
|
||||
fabs(rotationMat[0][i] - nextRotation[0][i]) +
|
||||
fabs(rotationMat[1][i] - nextRotation[1][i]) +
|
||||
fabs(rotationMat[2][i] - nextRotation[2][i]));
|
||||
norm = (norm > n ? norm : n);
|
||||
}
|
||||
rotationMat = nextRotation;
|
||||
} while (count < 100 && norm > ACCURACY_THREASHOLD);
|
||||
|
||||
|
||||
|
@ -49,14 +49,14 @@ void Transform::evalRotationScale(Quat& rotation, Vec3& scale, const Mat3& rotat
|
|||
Mat3 matRot(
|
||||
rotationScaleMatrix[0] / scale.x,
|
||||
rotationScaleMatrix[1] / scale.y,
|
||||
rotationScaleMatrix[2] / scale.z);
|
||||
|
||||
// Beware!!! needs to detect for the case there is a negative scale
|
||||
// Based on the determinant sign we just can flip the scale sign of one component: we choose X axis
|
||||
float determinant = glm::determinant(matRot);
|
||||
if (determinant < 0.f) {
|
||||
scale.x = -scale.x;
|
||||
matRot[0] *= -1.f;
|
||||
rotationScaleMatrix[2] / scale.z);
|
||||
|
||||
// Beware!!! needs to detect for the case there is a negative scale
|
||||
// Based on the determinant sign we just can flip the scale sign of one component: we choose X axis
|
||||
float determinant = glm::determinant(matRot);
|
||||
if (determinant < 0.0f) {
|
||||
scale.x = -scale.x;
|
||||
matRot[0] *= -1.0f;
|
||||
}
|
||||
|
||||
// Beware: even though the matRot is supposed to be normalized at that point,
|
||||
|
|
|
@ -292,13 +292,13 @@ inline Transform::Mat4& Transform::getMatrix(Transform::Mat4& result) const {
|
|||
rot[2] *= _scale.z;
|
||||
}
|
||||
|
||||
result[0] = Vec4(rot[0], 0.f);
|
||||
result[1] = Vec4(rot[1], 0.f);
|
||||
result[2] = Vec4(rot[2], 0.f);
|
||||
result[0] = Vec4(rot[0], 0.0f);
|
||||
result[1] = Vec4(rot[1], 0.0f);
|
||||
result[2] = Vec4(rot[2], 0.0f);
|
||||
} else {
|
||||
result[0] = Vec4(_scale.x, 0.f, 0.f, 0.f);
|
||||
result[1] = Vec4(0.f, _scale.y, 0.f, 0.f);
|
||||
result[2] = Vec4(0.f, 0.f, _scale.z, 0.f);
|
||||
result[0] = Vec4(_scale.x, 0.0f, 0.0f, 0.0f);
|
||||
result[1] = Vec4(0.0f, _scale.y, 0.0f, 0.0f);
|
||||
result[2] = Vec4(0.0f, 0.0f, _scale.z, 0.0f);
|
||||
}
|
||||
|
||||
result[3] = Vec4(_translation, 1.0f);
|
||||
|
@ -313,7 +313,7 @@ inline Transform::Mat4& Transform::getInverseMatrix(Transform::Mat4& result) con
|
|||
|
||||
inline void Transform::evalFromRawMatrix(const Mat4& matrix) {
|
||||
// for now works only in the case of TRS transformation
|
||||
if ((matrix[0][3] == 0) && (matrix[1][3] == 0) && (matrix[2][3] == 0) && (matrix[3][3] == 1.f)) {
|
||||
if ((matrix[0][3] == 0) && (matrix[1][3] == 0) && (matrix[2][3] == 0) && (matrix[3][3] == 1.0f)) {
|
||||
setTranslation(Vec3(matrix[3]));
|
||||
evalFromRawMatrix(Mat3(matrix));
|
||||
}
|
||||
|
|
|
@ -23,9 +23,9 @@
|
|||
|
||||
/*
|
||||
|
||||
static glm::vec3 xAxis(1.f, 0.f, 0.f);
|
||||
static glm::vec3 xZxis(0.f, 1.f, 0.f);
|
||||
static glm::vec3 xYxis(0.f, 0.f, 1.f);
|
||||
static glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
|
||||
static glm::vec3 xZxis(0.0f, 1.0f, 0.0f);
|
||||
static glm::vec3 xYxis(0.0f, 0.0f, 1.0f);
|
||||
|
||||
void CollisionInfoTests::rotateThenTranslate() {
|
||||
CollisionInfo collision;
|
||||
|
@ -34,7 +34,7 @@ void CollisionInfoTests::rotateThenTranslate() {
|
|||
collision._addedVelocity = xAxis + yAxis + zAxis;
|
||||
|
||||
glm::quat rotation = glm::angleAxis(PI_OVER_TWO, zAxis);
|
||||
float distance = 3.f;
|
||||
float distance = 3.0f;
|
||||
glm::vec3 translation = distance * yAxis;
|
||||
|
||||
collision.rotateThenTranslate(rotation, translation);
|
||||
|
@ -73,7 +73,7 @@ void CollisionInfoTests::translateThenRotate() {
|
|||
collision._addedVelocity = xAxis + yAxis + zAxis;
|
||||
|
||||
glm::quat rotation = glm::angleAxis( -PI_OVER_TWO, zAxis);
|
||||
float distance = 3.f;
|
||||
float distance = 3.0f;
|
||||
glm::vec3 translation = distance * yAxis;
|
||||
|
||||
collision.translateThenRotate(translation, rotation);
|
||||
|
@ -86,7 +86,7 @@ void CollisionInfoTests::translateThenRotate() {
|
|||
<< std::endl;
|
||||
}
|
||||
|
||||
glm::vec3 expectedContactPoint = (1.f + distance) * xAxis;
|
||||
glm::vec3 expectedContactPoint = (1.0f + distance) * xAxis;
|
||||
error = glm::distance(collision._contactPoint, expectedContactPoint);
|
||||
if (error > EPSILON) {
|
||||
std::cout << __FILE__ << ":" << __LINE__
|
||||
|
|
|
@ -17,9 +17,9 @@
|
|||
|
||||
#include <CollisionInfo.h>
|
||||
|
||||
const glm::vec3 xAxis(1.f, 0.f, 0.f);
|
||||
const glm::vec3 yAxis(0.f, 1.f, 0.f);
|
||||
const glm::vec3 zAxis(0.f, 0.f, 1.f);
|
||||
const glm::vec3 xAxis(1.0f, 0.0f, 0.0f);
|
||||
const glm::vec3 yAxis(0.0f, 1.0f, 0.0f);
|
||||
const glm::vec3 zAxis(0.0f, 0.0f, 1.0f);
|
||||
|
||||
std::ostream& operator<<(std::ostream& s, const CollisionInfo& c);
|
||||
|
||||
|
|
|
@ -2342,7 +2342,7 @@ void ShapeColliderTests::rayMissesAACube() {
|
|||
//glm::vec3 cubeCenter(1.23f, 4.56f, 7.89f);
|
||||
//float cubeSide = 2.127f;
|
||||
glm::vec3 cubeCenter(0.0f);
|
||||
float cubeSide = 2.f;
|
||||
float cubeSide = 2.0f;
|
||||
AACubeShape cube(cubeSide, cubeCenter);
|
||||
|
||||
float rayOffset = 3.796f;
|
||||
|
|
|
@ -37,7 +37,7 @@ void VerletShapeTests::setSpherePosition() {
|
|||
VerletPoint point;
|
||||
VerletSphereShape sphere(radius, &point);
|
||||
|
||||
point._position = glm::vec3(0.f);
|
||||
point._position = glm::vec3(0.0f);
|
||||
float d = glm::distance(glm::vec3(0.0f), sphere.getTranslation());
|
||||
if (d != 0.0f) {
|
||||
std::cout << __FILE__ << ":" << __LINE__ << " ERROR: sphere should be at origin" << std::endl;
|
||||
|
|
|
@ -47,7 +47,7 @@ void AngularConstraintTests::testHingeConstraint() {
|
|||
}
|
||||
}
|
||||
{ // test just inside min edge of constraint
|
||||
float angle = minAngle + 10.f * EPSILON;
|
||||
float angle = minAngle + 10.0f * EPSILON;
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
|
@ -62,7 +62,7 @@ void AngularConstraintTests::testHingeConstraint() {
|
|||
}
|
||||
}
|
||||
{ // test just inside max edge of constraint
|
||||
float angle = maxAngle - 10.f * EPSILON;
|
||||
float angle = maxAngle - 10.0f * EPSILON;
|
||||
glm::quat rotation = glm::angleAxis(angle, yAxis);
|
||||
|
||||
glm::quat newRotation = rotation;
|
||||
|
|
|
@ -34,7 +34,7 @@ void addCornersAndAxisLines(VoxelTree* tree) {
|
|||
|
||||
void addSurfaceScene(VoxelTree * tree) {
|
||||
qDebug("adding surface scene...");
|
||||
float voxelSize = 1.f / (8 * TREE_SCALE);
|
||||
float voxelSize = 1.0f / (8 * TREE_SCALE);
|
||||
|
||||
// color 1= blue, color 2=green
|
||||
unsigned char r1, g1, b1, r2, g2, b2, red, green, blue;
|
||||
|
@ -45,7 +45,7 @@ void addSurfaceScene(VoxelTree * tree) {
|
|||
for (float z = 0.0; z < 1.0; z += voxelSize) {
|
||||
|
||||
glm::vec2 position = glm::vec2(x, z);
|
||||
float perlin = glm::perlin(position) + .25f * glm::perlin(position * 4.f) + .125f * glm::perlin(position * 16.f);
|
||||
float perlin = glm::perlin(position) + .25f * glm::perlin(position * 4.0f) + .125f * glm::perlin(position * 16.0f);
|
||||
float gradient = (1.0f + perlin)/ 2.0f;
|
||||
red = (unsigned char)std::min(255, std::max(0, (int)(r1 + ((r2 - r1) * gradient))));
|
||||
green = (unsigned char)std::min(255, std::max(0, (int)(g1 + ((g2 - g1) * gradient))));
|
||||
|
|
Loading…
Reference in a new issue