mirror of
https://github.com/overte-org/overte.git
synced 2025-08-08 10:37:35 +02:00
merge fix
This commit is contained in:
commit
54957a2fa1
24 changed files with 339 additions and 289 deletions
50
examples/audioMuteExample.js
Normal file
50
examples/audioMuteExample.js
Normal file
|
@ -0,0 +1,50 @@
|
||||||
|
//
|
||||||
|
// audioMuteExample.js
|
||||||
|
// examples
|
||||||
|
//
|
||||||
|
// Created by Thijs Wenker on 10/31/14.
|
||||||
|
// Copyright 2014 High Fidelity, Inc.
|
||||||
|
//
|
||||||
|
// This example shows how to use the AudioDevice mute functions.
|
||||||
|
// Press the MUTE/UNMUTE button to see it function.
|
||||||
|
//
|
||||||
|
// Distributed under the Apache License, Version 2.0.
|
||||||
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
|
//
|
||||||
|
|
||||||
|
var toggleMuteButton = Overlays.addOverlay("text", {
|
||||||
|
x: 50,
|
||||||
|
y: 50,
|
||||||
|
width: 190,
|
||||||
|
height: 50,
|
||||||
|
backgroundColor: { red: 255, green: 255, blue: 255},
|
||||||
|
color: { red: 255, green: 0, blue: 0},
|
||||||
|
font: {size: 30},
|
||||||
|
topMargin: 10
|
||||||
|
});
|
||||||
|
|
||||||
|
function muteButtonText() {
|
||||||
|
print("Audio Muted: " + AudioDevice.getMuted());
|
||||||
|
}
|
||||||
|
|
||||||
|
function onMuteStateChanged() {
|
||||||
|
Overlays.editOverlay(toggleMuteButton,
|
||||||
|
AudioDevice.getMuted() ? {text: "UNMUTE", leftMargin: 10} : {text: "MUTE", leftMargin: 38});
|
||||||
|
print("Audio Muted: " + AudioDevice.getMuted());
|
||||||
|
}
|
||||||
|
|
||||||
|
function mousePressEvent(event) {
|
||||||
|
if (Overlays.getOverlayAtPoint({x: event.x, y: event.y}) == toggleMuteButton) {
|
||||||
|
AudioDevice.toggleMute()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function scriptEnding() {
|
||||||
|
Overlays.deleteOverlay(toggleMuteButton);
|
||||||
|
}
|
||||||
|
|
||||||
|
onMuteStateChanged();
|
||||||
|
|
||||||
|
AudioDevice.muteToggled.connect(onMuteStateChanged);
|
||||||
|
Controller.mousePressEvent.connect(mousePressEvent);
|
||||||
|
Script.scriptEnding.connect(scriptEnding);
|
|
@ -1,167 +0,0 @@
|
||||||
//
|
|
||||||
// voxelDrumming.js
|
|
||||||
// examples
|
|
||||||
//
|
|
||||||
// Created by Brad Hefta-Gaub on 2/14/14.
|
|
||||||
// Copyright 2014 High Fidelity, Inc.
|
|
||||||
//
|
|
||||||
// This is an example script that demonstrates use of the Overlays, Controller, and Audio classes
|
|
||||||
//
|
|
||||||
// It adds Hydra controller "fingertip on voxels" drumming
|
|
||||||
//
|
|
||||||
// Distributed under the Apache License, Version 2.0.
|
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
|
||||||
//
|
|
||||||
|
|
||||||
Menu.addMenuItem({
|
|
||||||
menuName: "Developer > Hand Options",
|
|
||||||
menuItemName: "Voxel Drumming",
|
|
||||||
isCheckable: true,
|
|
||||||
isChecked: false
|
|
||||||
});
|
|
||||||
|
|
||||||
var collisionCenter = new Array();
|
|
||||||
collisionCenter[0] = { x: 0, y: 0, z: 0};
|
|
||||||
collisionCenter[1] = { x: 0, y: 0, z: 0};
|
|
||||||
|
|
||||||
var collisionAge = new Array();
|
|
||||||
collisionAge[0] = 0;
|
|
||||||
collisionAge[1] = 0;
|
|
||||||
|
|
||||||
var collisionDuration = new Array();
|
|
||||||
collisionDuration[0] = 0;
|
|
||||||
collisionDuration[1] = 0;
|
|
||||||
|
|
||||||
var isColliding = new Array();
|
|
||||||
isColliding[0] = false;
|
|
||||||
isColliding[1] = false;
|
|
||||||
|
|
||||||
var highlightVoxel = Overlays.addOverlay("cube",
|
|
||||||
{
|
|
||||||
position: { x: 0, y: 0, z: 0},
|
|
||||||
size: 0,
|
|
||||||
color: { red: 0, green: 0, blue: 0 },
|
|
||||||
visible: false,
|
|
||||||
lineWidth: 3,
|
|
||||||
solid: false
|
|
||||||
});
|
|
||||||
|
|
||||||
var collisionBubble = new Array();
|
|
||||||
collisionBubble[0] = Overlays.addOverlay("sphere",
|
|
||||||
{
|
|
||||||
position: { x: 0, y: 0, z: 0},
|
|
||||||
size: 0,
|
|
||||||
color: { red: 0, green: 0, blue: 0 },
|
|
||||||
alpha: 0.5,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
collisionBubble[1] = Overlays.addOverlay("sphere",
|
|
||||||
{
|
|
||||||
position: { x: 0, y: 0, z: 0},
|
|
||||||
size: 0,
|
|
||||||
color: { red: 0, green: 0, blue: 0 },
|
|
||||||
alpha: 0.5,
|
|
||||||
visible: false
|
|
||||||
});
|
|
||||||
|
|
||||||
var audioOptions = new AudioInjectionOptions();
|
|
||||||
audioOptions.position = { x: MyAvatar.position.x, y: MyAvatar.position.y + 1, z: MyAvatar.position.z };
|
|
||||||
audioOptions.volume = 1;
|
|
||||||
|
|
||||||
|
|
||||||
function clamp(valueToClamp, minValue, maxValue) {
|
|
||||||
return Math.max(minValue, Math.min(maxValue, valueToClamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
function produceCollisionSound(deltaTime, palm, voxelDetail) {
|
|
||||||
// Collision between finger and a voxel plays sound
|
|
||||||
|
|
||||||
var palmVelocity = Controller.getSpatialControlVelocity(palm * 2);
|
|
||||||
var speed = Vec3.length(palmVelocity);
|
|
||||||
var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1);
|
|
||||||
|
|
||||||
var LOWEST_FREQUENCY = 100.0;
|
|
||||||
var HERTZ_PER_RGB = 3.0;
|
|
||||||
var DECAY_PER_SAMPLE = 0.0005;
|
|
||||||
var DURATION_MAX = 2.0;
|
|
||||||
var MIN_VOLUME = 0.1;
|
|
||||||
var volume = MIN_VOLUME + clamp(speed, 0.0, (1.0 - MIN_VOLUME));
|
|
||||||
var duration = volume;
|
|
||||||
|
|
||||||
collisionCenter[palm] = fingerTipPosition;
|
|
||||||
collisionAge[palm] = deltaTime;
|
|
||||||
collisionDuration[palm] = duration;
|
|
||||||
|
|
||||||
var voxelBrightness = voxelDetail.red + voxelDetail.green + voxelDetail.blue;
|
|
||||||
var frequency = LOWEST_FREQUENCY + (voxelBrightness * HERTZ_PER_RGB);
|
|
||||||
|
|
||||||
audioOptions.position = fingerTipPosition;
|
|
||||||
Audio.startDrumSound(volume, frequency, DURATION_MAX, DECAY_PER_SAMPLE, audioOptions);
|
|
||||||
}
|
|
||||||
|
|
||||||
function update(deltaTime) {
|
|
||||||
// Voxel Drumming with fingertips if enabled
|
|
||||||
if (Menu.isOptionChecked("Voxel Drumming")) {
|
|
||||||
|
|
||||||
for (var palm = 0; palm < 2; palm++) {
|
|
||||||
var fingerTipPosition = Controller.getSpatialControlPosition(palm * 2 + 1);
|
|
||||||
|
|
||||||
var voxel = Voxels.getVoxelEnclosingPoint(fingerTipPosition);
|
|
||||||
if (voxel.s > 0) {
|
|
||||||
if (!isColliding[palm]) {
|
|
||||||
// Collision has just started
|
|
||||||
isColliding[palm] = true;
|
|
||||||
produceCollisionSound(deltaTime, palm, voxel);
|
|
||||||
|
|
||||||
// Set highlight voxel
|
|
||||||
Overlays.editOverlay(highlightVoxel,
|
|
||||||
{
|
|
||||||
position: { x: voxel.x, y: voxel.y, z: voxel.z},
|
|
||||||
size: voxel.s + 0.002,
|
|
||||||
color: { red: voxel.red + 128, green: voxel.green + 128, blue: voxel.blue + 128 },
|
|
||||||
visible: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (isColliding[palm]) {
|
|
||||||
// Collision has just ended
|
|
||||||
isColliding[palm] = false;
|
|
||||||
Overlays.editOverlay(highlightVoxel, { visible: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (collisionAge[palm] > 0) {
|
|
||||||
collisionAge[palm] += deltaTime;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If hand/voxel collision has happened, render a little expanding sphere
|
|
||||||
if (collisionAge[palm] > 0) {
|
|
||||||
var opacity = clamp(1 - (collisionAge[palm] / collisionDuration[palm]), 0, 1);
|
|
||||||
var size = collisionAge[palm] * 0.25;
|
|
||||||
|
|
||||||
Overlays.editOverlay(collisionBubble[palm],
|
|
||||||
{
|
|
||||||
position: { x: collisionCenter[palm].x, y: collisionCenter[palm].y, z: collisionCenter[palm].z},
|
|
||||||
size: size,
|
|
||||||
color: { red: 255, green: 0, blue: 0 },
|
|
||||||
alpha: 0.5 * opacity,
|
|
||||||
visible: true
|
|
||||||
});
|
|
||||||
|
|
||||||
if (collisionAge[palm] > collisionDuration[palm]) {
|
|
||||||
collisionAge[palm] = 0;
|
|
||||||
Overlays.editOverlay(collisionBubble[palm], { visible: false });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} // palm loop
|
|
||||||
} // menu item check
|
|
||||||
}
|
|
||||||
Script.update.connect(update);
|
|
||||||
|
|
||||||
function scriptEnding() {
|
|
||||||
Overlays.deleteOverlay(highlightVoxel);
|
|
||||||
Overlays.deleteOverlay(collisionBubble[0]);
|
|
||||||
Overlays.deleteOverlay(collisionBubble[1]);
|
|
||||||
Menu.removeMenuItem("Developer > Hand Options","Voxel Drumming");
|
|
||||||
}
|
|
||||||
Script.scriptEnding.connect(scriptEnding);
|
|
|
@ -11,50 +11,8 @@
|
||||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||||
//
|
//
|
||||||
|
|
||||||
// the radius (hard cutoff) of the light effect
|
|
||||||
uniform float radius;
|
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
// find the right "right" direction
|
gl_Position = ftransform();
|
||||||
vec3 firstRightCandidate = cross(gl_LightSource[1].spotDirection, vec3(0.0, 1.0, 0.0));
|
vec4 projected = gl_Position / gl_Position.w;
|
||||||
vec3 secondRightCandidate = cross(gl_LightSource[1].spotDirection, vec3(1.0, 0.0, 0.0));
|
gl_TexCoord[0] = vec4(dot(projected, gl_ObjectPlaneS[3]), dot(projected, gl_ObjectPlaneT[3]), 0.0, 1.0);
|
||||||
vec3 right = mix(firstRightCandidate, secondRightCandidate, step(length(firstRightCandidate), length(secondRightCandidate)));
|
|
||||||
right = normalize(right);
|
|
||||||
|
|
||||||
// and the "up"
|
|
||||||
vec3 up = cross(right, gl_LightSource[1].spotDirection);
|
|
||||||
|
|
||||||
// and the "back," which depends on whether this is a spot light
|
|
||||||
vec3 back = -gl_LightSource[1].spotDirection * step(gl_LightSource[1].spotCosCutoff, 0.0);
|
|
||||||
|
|
||||||
// find the eight corners of the bounds
|
|
||||||
vec4 c0 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
|
||||||
radius * (-up - right + back), 1.0);
|
|
||||||
vec4 c1 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
|
||||||
radius * (-up + right + back), 1.0);
|
|
||||||
vec4 c2 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
|
||||||
radius * (up - right + back), 1.0);
|
|
||||||
vec4 c3 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
|
||||||
radius * (up + right + back), 1.0);
|
|
||||||
vec4 c4 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
|
||||||
radius * (-up - right + gl_LightSource[1].spotDirection), 1.0);
|
|
||||||
vec4 c5 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
|
||||||
radius * (-up + right + gl_LightSource[1].spotDirection), 1.0);
|
|
||||||
vec4 c6 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
|
||||||
radius * (up - right + gl_LightSource[1].spotDirection), 1.0);
|
|
||||||
vec4 c7 = gl_ProjectionMatrix * vec4(gl_LightSource[1].position.xyz +
|
|
||||||
radius * (up + right + gl_LightSource[1].spotDirection), 1.0);
|
|
||||||
|
|
||||||
// find their projected extents
|
|
||||||
vec2 extents = max(
|
|
||||||
max(max(gl_Vertex.xy * (c0.xy / max(c0.w, 0.001)), gl_Vertex.xy * (c1.xy / max(c1.w, 0.001))),
|
|
||||||
max(gl_Vertex.xy * (c2.xy / max(c2.w, 0.001)), gl_Vertex.xy * (c3.xy / max(c3.w, 0.001)))),
|
|
||||||
max(max(gl_Vertex.xy * (c4.xy / max(c4.w, 0.001)), gl_Vertex.xy * (c5.xy / max(c5.w, 0.001))),
|
|
||||||
max(gl_Vertex.xy * (c6.xy / max(c6.w, 0.001)), gl_Vertex.xy * (c7.xy / max(c7.w, 0.001)))));
|
|
||||||
|
|
||||||
// make sure they don't extend beyond the screen
|
|
||||||
extents = min(extents, vec2(1.0, 1.0));
|
|
||||||
|
|
||||||
gl_Position = vec4(gl_Vertex.xy * extents, 0.0, 1.0);
|
|
||||||
gl_TexCoord[0] = vec4(dot(gl_Position, gl_ObjectPlaneS[3]), dot(gl_Position, gl_ObjectPlaneT[3]), 0.0, 1.0);
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,8 +39,13 @@ uniform vec2 depthTexCoordScale;
|
||||||
uniform float radius;
|
uniform float radius;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
|
// get the depth and exit early if it doesn't pass the test
|
||||||
|
float depth = texture2D(depthMap, gl_TexCoord[0].st).r;
|
||||||
|
if (depth < gl_FragCoord.z) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
// compute the view space position using the depth
|
// compute the view space position using the depth
|
||||||
float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0);
|
float z = near / (depth * depthScale - 1.0);
|
||||||
vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0);
|
vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0);
|
||||||
|
|
||||||
// get the normal from the map
|
// get the normal from the map
|
||||||
|
|
|
@ -39,8 +39,13 @@ uniform vec2 depthTexCoordScale;
|
||||||
uniform float radius;
|
uniform float radius;
|
||||||
|
|
||||||
void main(void) {
|
void main(void) {
|
||||||
|
// get the depth and exit early if it doesn't pass the test
|
||||||
|
float depth = texture2D(depthMap, gl_TexCoord[0].st).r;
|
||||||
|
if (depth < gl_FragCoord.z) {
|
||||||
|
discard;
|
||||||
|
}
|
||||||
// compute the view space position using the depth
|
// compute the view space position using the depth
|
||||||
float z = near / (texture2D(depthMap, gl_TexCoord[0].st).r * depthScale - 1.0);
|
float z = near / (depth * depthScale - 1.0);
|
||||||
vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0);
|
vec4 position = vec4((depthTexCoordOffset + gl_TexCoord[0].st * depthTexCoordScale) * z, z, 1.0);
|
||||||
|
|
||||||
// get the normal from the map
|
// get the normal from the map
|
||||||
|
|
|
@ -450,6 +450,9 @@ Application::~Application() {
|
||||||
_audio.thread()->quit();
|
_audio.thread()->quit();
|
||||||
_audio.thread()->wait();
|
_audio.thread()->wait();
|
||||||
|
|
||||||
|
// kill any audio injectors that are still around
|
||||||
|
AudioScriptingInterface::getInstance().stopAllInjectors();
|
||||||
|
|
||||||
_octreeProcessor.terminate();
|
_octreeProcessor.terminate();
|
||||||
_voxelHideShowThread.terminate();
|
_voxelHideShowThread.terminate();
|
||||||
_voxelEditSender.terminate();
|
_voxelEditSender.terminate();
|
||||||
|
@ -620,8 +623,8 @@ void Application::paintGL() {
|
||||||
|
|
||||||
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
|
||||||
static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f;
|
static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f;
|
||||||
_myCamera.setPosition(_myAvatar->getUprightHeadPosition() +
|
_myCamera.setPosition(_myAvatar->getDefaultEyePosition() +
|
||||||
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * THIRD_PERSON_CAMERA_DISTANCE * _myAvatar->getScale());
|
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * THIRD_PERSON_CAMERA_DISTANCE * _myAvatar->getScale());
|
||||||
if (OculusManager::isConnected()) {
|
if (OculusManager::isConnected()) {
|
||||||
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation());
|
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation());
|
||||||
} else {
|
} else {
|
||||||
|
@ -1980,6 +1983,9 @@ void Application::init() {
|
||||||
connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector,
|
connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector,
|
||||||
&AudioReflector::preProcessOriginalInboundAudio,Qt::DirectConnection);
|
&AudioReflector::preProcessOriginalInboundAudio,Qt::DirectConnection);
|
||||||
|
|
||||||
|
connect(getAudio(), &Audio::muteToggled, AudioDeviceScriptingInterface::getInstance(),
|
||||||
|
&AudioDeviceScriptingInterface::muteToggled, Qt::DirectConnection);
|
||||||
|
|
||||||
// save settings when avatar changes
|
// save settings when avatar changes
|
||||||
connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings);
|
connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1057,10 +1057,6 @@ float Avatar::getPelvisFloatingHeight() const {
|
||||||
return -_skeletonModel.getBindExtents().minimum.y;
|
return -_skeletonModel.getBindExtents().minimum.y;
|
||||||
}
|
}
|
||||||
|
|
||||||
float Avatar::getPelvisToHeadLength() const {
|
|
||||||
return glm::distance(_position, getHead()->getPosition());
|
|
||||||
}
|
|
||||||
|
|
||||||
void Avatar::setShowDisplayName(bool showDisplayName) {
|
void Avatar::setShowDisplayName(bool showDisplayName) {
|
||||||
if (!Menu::getInstance()->isOptionChecked(MenuOption::NamesAboveHeads)) {
|
if (!Menu::getInstance()->isOptionChecked(MenuOption::NamesAboveHeads)) {
|
||||||
_displayNameAlpha = 0.0f;
|
_displayNameAlpha = 0.0f;
|
||||||
|
|
|
@ -230,7 +230,6 @@ protected:
|
||||||
float getSkeletonHeight() const;
|
float getSkeletonHeight() const;
|
||||||
float getHeadHeight() const;
|
float getHeadHeight() const;
|
||||||
float getPelvisFloatingHeight() const;
|
float getPelvisFloatingHeight() const;
|
||||||
float getPelvisToHeadLength() const;
|
|
||||||
glm::vec3 getDisplayNamePosition();
|
glm::vec3 getDisplayNamePosition();
|
||||||
|
|
||||||
void renderDisplayName();
|
void renderDisplayName();
|
||||||
|
|
|
@ -416,7 +416,7 @@ void MyAvatar::renderDebugBodyPoints() {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glColor4f(0, 1, 0, .5f);
|
glColor4f(0, 1, 0, .5f);
|
||||||
glTranslatef(position.x, position.y, position.z);
|
glTranslatef(position.x, position.y, position.z);
|
||||||
Application::getInstance()->getGeometryCache()->renderSphere(0.2, 10, 10);
|
Application::getInstance()->getGeometryCache()->renderSphere(0.2f, 10.0f, 10.0f);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
|
|
||||||
// Head Sphere
|
// Head Sphere
|
||||||
|
@ -424,7 +424,7 @@ void MyAvatar::renderDebugBodyPoints() {
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
glColor4f(0, 1, 0, .5f);
|
glColor4f(0, 1, 0, .5f);
|
||||||
glTranslatef(position.x, position.y, position.z);
|
glTranslatef(position.x, position.y, position.z);
|
||||||
Application::getInstance()->getGeometryCache()->renderSphere(0.15, 10, 10);
|
Application::getInstance()->getGeometryCache()->renderSphere(0.15f, 10.0f, 10.0f);
|
||||||
glPopMatrix();
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1004,10 +1004,6 @@ bool MyAvatar::isLookingAtLeftEye() {
|
||||||
return _isLookingAtLeftEye;
|
return _isLookingAtLeftEye;
|
||||||
}
|
}
|
||||||
|
|
||||||
glm::vec3 MyAvatar::getUprightHeadPosition() const {
|
|
||||||
return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, getPelvisToHeadLength(), 0.0f);
|
|
||||||
}
|
|
||||||
|
|
||||||
glm::vec3 MyAvatar::getDefaultEyePosition() const {
|
glm::vec3 MyAvatar::getDefaultEyePosition() const {
|
||||||
return _position + getWorldAlignedOrientation() * _skeletonModel.getDefaultEyeModelPosition();
|
return _position + getWorldAlignedOrientation() * _skeletonModel.getDefaultEyeModelPosition();
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,7 +66,6 @@ public:
|
||||||
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
|
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
|
||||||
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
|
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
|
||||||
glm::vec3 getGravity() const { return _gravity; }
|
glm::vec3 getGravity() const { return _gravity; }
|
||||||
glm::vec3 getUprightHeadPosition() const;
|
|
||||||
glm::vec3 getDefaultEyePosition() const;
|
glm::vec3 getDefaultEyePosition() const;
|
||||||
bool getShouldRenderLocally() const { return _shouldRender; }
|
bool getShouldRenderLocally() const { return _shouldRender; }
|
||||||
|
|
||||||
|
|
|
@ -126,6 +126,7 @@ void OculusManager::connect() {
|
||||||
|
|
||||||
if (!_camera) {
|
if (!_camera) {
|
||||||
_camera = new Camera;
|
_camera = new Camera;
|
||||||
|
configureCamera(*_camera, 0, 0); // no need to use screen dimensions; they're ignored
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_programInitialized) {
|
if (!_programInitialized) {
|
||||||
|
@ -420,7 +421,7 @@ void OculusManager::endFrameTiming() {
|
||||||
//Sets the camera FoV and aspect ratio
|
//Sets the camera FoV and aspect ratio
|
||||||
void OculusManager::configureCamera(Camera& camera, int screenWidth, int screenHeight) {
|
void OculusManager::configureCamera(Camera& camera, int screenWidth, int screenHeight) {
|
||||||
#ifdef HAVE_LIBOVR
|
#ifdef HAVE_LIBOVR
|
||||||
camera.setAspectRatio((float)_renderTargetSize.w / _renderTargetSize.h);
|
camera.setAspectRatio(_renderTargetSize.w * 0.5f / _renderTargetSize.h);
|
||||||
camera.setFieldOfView(atan(_eyeFov[0].UpTan) * DEGREES_PER_RADIAN * 2.0f);
|
camera.setFieldOfView(atan(_eyeFov[0].UpTan) * DEGREES_PER_RADIAN * 2.0f);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
|
@ -73,6 +73,12 @@ void DeferredLightingEffect::renderWireCube(float size) {
|
||||||
releaseSimpleProgram();
|
releaseSimpleProgram();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DeferredLightingEffect::renderSolidCone(float base, float height, int slices, int stacks) {
|
||||||
|
bindSimpleProgram();
|
||||||
|
Application::getInstance()->getGeometryCache()->renderCone(base, height, slices, stacks);
|
||||||
|
releaseSimpleProgram();
|
||||||
|
}
|
||||||
|
|
||||||
void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient,
|
void DeferredLightingEffect::addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient,
|
||||||
const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation,
|
const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation,
|
||||||
float linearAttenuation, float quadraticAttenuation) {
|
float linearAttenuation, float quadraticAttenuation) {
|
||||||
|
@ -216,11 +222,18 @@ void DeferredLightingEffect::render() {
|
||||||
glEnable(GL_BLEND);
|
glEnable(GL_BLEND);
|
||||||
glBlendFunc(GL_ONE, GL_ONE);
|
glBlendFunc(GL_ONE, GL_ONE);
|
||||||
|
|
||||||
|
glEnable(GL_CULL_FACE);
|
||||||
|
|
||||||
glm::vec4 sCoefficients(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f);
|
glm::vec4 sCoefficients(sWidth / 2.0f, 0.0f, 0.0f, sMin + sWidth / 2.0f);
|
||||||
glm::vec4 tCoefficients(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f);
|
glm::vec4 tCoefficients(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f);
|
||||||
glTexGenfv(GL_S, GL_OBJECT_PLANE, (const GLfloat*)&sCoefficients);
|
glTexGenfv(GL_S, GL_OBJECT_PLANE, (const GLfloat*)&sCoefficients);
|
||||||
glTexGenfv(GL_T, GL_OBJECT_PLANE, (const GLfloat*)&tCoefficients);
|
glTexGenfv(GL_T, GL_OBJECT_PLANE, (const GLfloat*)&tCoefficients);
|
||||||
|
|
||||||
|
// enlarge the scales slightly to account for tesselation
|
||||||
|
const float SCALE_EXPANSION = 0.1f;
|
||||||
|
|
||||||
|
const glm::vec3& eyePoint = Application::getInstance()->getDisplayViewFrustum()->getPosition();
|
||||||
|
|
||||||
if (!_pointLights.isEmpty()) {
|
if (!_pointLights.isEmpty()) {
|
||||||
_pointLight.bind();
|
_pointLight.bind();
|
||||||
_pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal);
|
_pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal);
|
||||||
|
@ -238,7 +251,28 @@ void DeferredLightingEffect::render() {
|
||||||
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation);
|
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation);
|
||||||
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation);
|
glLightf(GL_LIGHT1, GL_QUADRATIC_ATTENUATION, light.quadraticAttenuation);
|
||||||
|
|
||||||
renderFullscreenQuad();
|
glPushMatrix();
|
||||||
|
|
||||||
|
float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION);
|
||||||
|
if (glm::distance(eyePoint, glm::vec3(light.position)) < expandedRadius) {
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(0.0f, 0.0f, -1.0f);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
renderFullscreenQuad();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glTranslatef(light.position.x, light.position.y, light.position.z);
|
||||||
|
Application::getInstance()->getGeometryCache()->renderSphere(expandedRadius, 64, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
_pointLights.clear();
|
_pointLights.clear();
|
||||||
|
|
||||||
|
@ -265,7 +299,34 @@ void DeferredLightingEffect::render() {
|
||||||
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent);
|
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent);
|
||||||
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff));
|
glLightf(GL_LIGHT1, GL_SPOT_CUTOFF, glm::degrees(light.cutoff));
|
||||||
|
|
||||||
renderFullscreenQuad();
|
glPushMatrix();
|
||||||
|
|
||||||
|
float expandedRadius = light.radius * (1.0f + SCALE_EXPANSION);
|
||||||
|
float edgeRadius = expandedRadius / glm::cos(light.cutoff);
|
||||||
|
if (glm::distance(eyePoint, glm::vec3(light.position)) < edgeRadius) {
|
||||||
|
glLoadIdentity();
|
||||||
|
glTranslatef(0.0f, 0.0f, -1.0f);
|
||||||
|
|
||||||
|
glMatrixMode(GL_PROJECTION);
|
||||||
|
glPushMatrix();
|
||||||
|
glLoadIdentity();
|
||||||
|
|
||||||
|
renderFullscreenQuad();
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
glMatrixMode(GL_MODELVIEW);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glTranslatef(light.position.x, light.position.y, light.position.z);
|
||||||
|
glm::quat spotRotation = rotationBetween(glm::vec3(0.0f, 0.0f, -1.0f), light.direction);
|
||||||
|
glm::vec3 axis = glm::axis(spotRotation);
|
||||||
|
glRotatef(glm::degrees(glm::angle(spotRotation)), axis.x, axis.y, axis.z);
|
||||||
|
glTranslatef(0.0f, 0.0f, -light.radius * (1.0f + SCALE_EXPANSION * 0.5f));
|
||||||
|
Application::getInstance()->getGeometryCache()->renderCone(expandedRadius * glm::tan(light.cutoff),
|
||||||
|
expandedRadius, 64, 32);
|
||||||
|
}
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
}
|
}
|
||||||
_spotLights.clear();
|
_spotLights.clear();
|
||||||
|
|
||||||
|
@ -285,6 +346,8 @@ void DeferredLightingEffect::render() {
|
||||||
|
|
||||||
freeFBO->release();
|
freeFBO->release();
|
||||||
|
|
||||||
|
glDisable(GL_CULL_FACE);
|
||||||
|
|
||||||
// now transfer the lit region to the primary fbo
|
// now transfer the lit region to the primary fbo
|
||||||
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
|
||||||
glColorMask(true, true, true, false);
|
glColorMask(true, true, true, false);
|
||||||
|
|
|
@ -47,6 +47,9 @@ public:
|
||||||
|
|
||||||
//// Renders a wireframe cube with the simple program.
|
//// Renders a wireframe cube with the simple program.
|
||||||
void renderWireCube(float size);
|
void renderWireCube(float size);
|
||||||
|
|
||||||
|
//// Renders a solid cone with the simple program.
|
||||||
|
void renderSolidCone(float base, float height, int slices, int stacks);
|
||||||
|
|
||||||
/// Adds a point light to render for the current frame.
|
/// Adds a point light to render for the current frame.
|
||||||
void addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f),
|
void addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f),
|
||||||
|
|
|
@ -110,15 +110,18 @@ void GeometryCache::renderHemisphere(int slices, int stacks) {
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const int NUM_VERTICES_PER_TRIANGLE = 3;
|
||||||
|
const int NUM_TRIANGLES_PER_QUAD = 2;
|
||||||
|
const int NUM_VERTICES_PER_TRIANGULATED_QUAD = NUM_VERTICES_PER_TRIANGLE * NUM_TRIANGLES_PER_QUAD;
|
||||||
|
const int NUM_COORDS_PER_VERTEX = 3;
|
||||||
|
const int NUM_BYTES_PER_VERTEX = NUM_COORDS_PER_VERTEX * sizeof(GLfloat);
|
||||||
|
const int NUM_BYTES_PER_INDEX = sizeof(GLushort);
|
||||||
|
|
||||||
void GeometryCache::renderSphere(float radius, int slices, int stacks) {
|
void GeometryCache::renderSphere(float radius, int slices, int stacks) {
|
||||||
VerticesIndices& vbo = _sphereVBOs[IntPair(slices, stacks)];
|
VerticesIndices& vbo = _sphereVBOs[IntPair(slices, stacks)];
|
||||||
int vertices = slices * (stacks - 1) + 2;
|
int vertices = slices * (stacks - 1) + 2;
|
||||||
const int NUM_VERTICES_PER_TRIANGLE = 3;
|
int indices = slices * stacks * NUM_VERTICES_PER_TRIANGULATED_QUAD;
|
||||||
const int NUM_TRIANGLES_PER_QUAD = 2;
|
if (vbo.first == 0) {
|
||||||
int indices = slices * NUM_TRIANGLES_PER_QUAD * NUM_VERTICES_PER_TRIANGLE * (stacks - 1) + slices * NUM_TRIANGLES_PER_QUAD * NUM_VERTICES_PER_TRIANGLE;
|
|
||||||
if (vbo.first == 0) {
|
|
||||||
const int NUM_COORDS_PER_VERTEX = 3;
|
|
||||||
GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX];
|
GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX];
|
||||||
GLfloat* vertex = vertexData;
|
GLfloat* vertex = vertexData;
|
||||||
|
|
||||||
|
@ -148,8 +151,7 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks) {
|
||||||
|
|
||||||
glGenBuffers(1, &vbo.first);
|
glGenBuffers(1, &vbo.first);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
||||||
const int BYTES_PER_VERTEX = NUM_COORDS_PER_VERTEX * sizeof(GLfloat);
|
glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
|
||||||
delete[] vertexData;
|
delete[] vertexData;
|
||||||
|
|
||||||
GLushort* indexData = new GLushort[indices];
|
GLushort* indexData = new GLushort[indices];
|
||||||
|
@ -192,8 +194,7 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks) {
|
||||||
|
|
||||||
glGenBuffers(1, &vbo.second);
|
glGenBuffers(1, &vbo.second);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
|
||||||
const int BYTES_PER_INDEX = sizeof(GLushort);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
|
||||||
delete[] indexData;
|
delete[] indexData;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -239,8 +240,7 @@ void GeometryCache::renderSquare(int xDivisions, int yDivisions) {
|
||||||
|
|
||||||
glGenBuffers(1, &vbo.first);
|
glGenBuffers(1, &vbo.first);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
||||||
const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat);
|
glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
||||||
glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
|
||||||
delete[] vertexData;
|
delete[] vertexData;
|
||||||
|
|
||||||
GLushort* indexData = new GLushort[indices];
|
GLushort* indexData = new GLushort[indices];
|
||||||
|
@ -263,8 +263,7 @@ void GeometryCache::renderSquare(int xDivisions, int yDivisions) {
|
||||||
|
|
||||||
glGenBuffers(1, &vbo.second);
|
glGenBuffers(1, &vbo.second);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
|
||||||
const int BYTES_PER_INDEX = sizeof(GLushort);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
|
||||||
delete[] indexData;
|
delete[] indexData;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -313,8 +312,7 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) {
|
||||||
|
|
||||||
glGenBuffers(1, &vbo.first);
|
glGenBuffers(1, &vbo.first);
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
||||||
const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat);
|
glBufferData(GL_ARRAY_BUFFER, 2 * vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
||||||
glBufferData(GL_ARRAY_BUFFER, 2 * vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
|
||||||
delete[] vertexData;
|
delete[] vertexData;
|
||||||
|
|
||||||
GLushort* indexData = new GLushort[indices];
|
GLushort* indexData = new GLushort[indices];
|
||||||
|
@ -337,8 +335,7 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) {
|
||||||
|
|
||||||
glGenBuffers(1, &vbo.second);
|
glGenBuffers(1, &vbo.second);
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
|
||||||
const int BYTES_PER_INDEX = sizeof(GLushort);
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
|
||||||
delete[] indexData;
|
delete[] indexData;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -360,6 +357,106 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) {
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void GeometryCache::renderCone(float base, float height, int slices, int stacks) {
|
||||||
|
VerticesIndices& vbo = _halfCylinderVBOs[IntPair(slices, stacks)];
|
||||||
|
int vertices = (stacks + 2) * slices;
|
||||||
|
int baseTriangles = slices - 2;
|
||||||
|
int indices = NUM_VERTICES_PER_TRIANGULATED_QUAD * slices * stacks + NUM_VERTICES_PER_TRIANGLE * baseTriangles;
|
||||||
|
if (vbo.first == 0) {
|
||||||
|
GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX * 2];
|
||||||
|
GLfloat* vertex = vertexData;
|
||||||
|
// cap
|
||||||
|
for (int i = 0; i < slices; i++) {
|
||||||
|
float theta = TWO_PI * i / slices;
|
||||||
|
|
||||||
|
//normals
|
||||||
|
*(vertex++) = 0.0f;
|
||||||
|
*(vertex++) = 0.0f;
|
||||||
|
*(vertex++) = -1.0f;
|
||||||
|
|
||||||
|
// vertices
|
||||||
|
*(vertex++) = cosf(theta);
|
||||||
|
*(vertex++) = sinf(theta);
|
||||||
|
*(vertex++) = 0.0f;
|
||||||
|
}
|
||||||
|
// body
|
||||||
|
for (int i = 0; i <= stacks; i++) {
|
||||||
|
float z = (float)i / stacks;
|
||||||
|
float radius = 1.0f - z;
|
||||||
|
|
||||||
|
for (int j = 0; j < slices; j++) {
|
||||||
|
float theta = TWO_PI * j / slices;
|
||||||
|
|
||||||
|
//normals
|
||||||
|
*(vertex++) = cosf(theta) / SQUARE_ROOT_OF_2;
|
||||||
|
*(vertex++) = sinf(theta) / SQUARE_ROOT_OF_2;
|
||||||
|
*(vertex++) = 1.0f / SQUARE_ROOT_OF_2;
|
||||||
|
|
||||||
|
// vertices
|
||||||
|
*(vertex++) = radius * cosf(theta);
|
||||||
|
*(vertex++) = radius * sinf(theta);
|
||||||
|
*(vertex++) = z;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenBuffers(1, &vbo.first);
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
||||||
|
glBufferData(GL_ARRAY_BUFFER, 2 * vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
|
||||||
|
delete[] vertexData;
|
||||||
|
|
||||||
|
GLushort* indexData = new GLushort[indices];
|
||||||
|
GLushort* index = indexData;
|
||||||
|
for (int i = 0; i < baseTriangles; i++) {
|
||||||
|
*(index++) = 0;
|
||||||
|
*(index++) = i + 1;
|
||||||
|
*(index++) = i + 2;
|
||||||
|
}
|
||||||
|
for (int i = 1; i <= stacks; i++) {
|
||||||
|
GLushort bottom = i * slices;
|
||||||
|
GLushort top = bottom + slices;
|
||||||
|
for (int j = 0; j < slices; j++) {
|
||||||
|
int next = (j + 1) % slices;
|
||||||
|
|
||||||
|
*(index++) = bottom + j;
|
||||||
|
*(index++) = top + next;
|
||||||
|
*(index++) = top + j;
|
||||||
|
|
||||||
|
*(index++) = bottom + j;
|
||||||
|
*(index++) = bottom + next;
|
||||||
|
*(index++) = top + next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
glGenBuffers(1, &vbo.second);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
|
||||||
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
|
||||||
|
delete[] indexData;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
|
||||||
|
}
|
||||||
|
glEnableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glEnableClientState(GL_NORMAL_ARRAY);
|
||||||
|
|
||||||
|
int stride = NUM_VERTICES_PER_TRIANGULATED_QUAD * sizeof(float);
|
||||||
|
glNormalPointer(GL_FLOAT, stride, 0);
|
||||||
|
glVertexPointer(NUM_COORDS_PER_VERTEX, GL_FLOAT, stride, (const void *)(NUM_COORDS_PER_VERTEX * sizeof(float)));
|
||||||
|
|
||||||
|
glPushMatrix();
|
||||||
|
glScalef(base, base, height);
|
||||||
|
|
||||||
|
glDrawRangeElementsEXT(GL_TRIANGLES, 0, vertices - 1, indices, GL_UNSIGNED_SHORT, 0);
|
||||||
|
|
||||||
|
glPopMatrix();
|
||||||
|
|
||||||
|
glDisableClientState(GL_VERTEX_ARRAY);
|
||||||
|
glDisableClientState(GL_NORMAL_ARRAY);
|
||||||
|
|
||||||
|
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||||
|
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||||
|
}
|
||||||
|
|
||||||
void GeometryCache::renderGrid(int xDivisions, int yDivisions) {
|
void GeometryCache::renderGrid(int xDivisions, int yDivisions) {
|
||||||
QOpenGLBuffer& buffer = _gridBuffers[IntPair(xDivisions, yDivisions)];
|
QOpenGLBuffer& buffer = _gridBuffers[IntPair(xDivisions, yDivisions)];
|
||||||
int vertices = (xDivisions + 1 + yDivisions + 1) * 2;
|
int vertices = (xDivisions + 1 + yDivisions + 1) * 2;
|
||||||
|
|
|
@ -42,6 +42,7 @@ public:
|
||||||
void renderSphere(float radius, int slices, int stacks);
|
void renderSphere(float radius, int slices, int stacks);
|
||||||
void renderSquare(int xDivisions, int yDivisions);
|
void renderSquare(int xDivisions, int yDivisions);
|
||||||
void renderHalfCylinder(int slices, int stacks);
|
void renderHalfCylinder(int slices, int stacks);
|
||||||
|
void renderCone(float base, float height, int slices, int stacks);
|
||||||
void renderGrid(int xDivisions, int yDivisions);
|
void renderGrid(int xDivisions, int yDivisions);
|
||||||
|
|
||||||
/// Loads geometry from the specified URL.
|
/// Loads geometry from the specified URL.
|
||||||
|
@ -71,6 +72,7 @@ private:
|
||||||
QHash<IntPair, VerticesIndices> _sphereVBOs;
|
QHash<IntPair, VerticesIndices> _sphereVBOs;
|
||||||
QHash<IntPair, VerticesIndices> _squareVBOs;
|
QHash<IntPair, VerticesIndices> _squareVBOs;
|
||||||
QHash<IntPair, VerticesIndices> _halfCylinderVBOs;
|
QHash<IntPair, VerticesIndices> _halfCylinderVBOs;
|
||||||
|
QHash<IntPair, VerticesIndices> _coneVBOs;
|
||||||
QHash<IntPair, QOpenGLBuffer> _gridBuffers;
|
QHash<IntPair, QOpenGLBuffer> _gridBuffers;
|
||||||
|
|
||||||
QHash<QUrl, QWeakPointer<NetworkGeometry> > _networkGeometry;
|
QHash<QUrl, QWeakPointer<NetworkGeometry> > _networkGeometry;
|
||||||
|
|
|
@ -78,3 +78,11 @@ void AudioDeviceScriptingInterface::setReverb(bool reverb) {
|
||||||
void AudioDeviceScriptingInterface::setReverbOptions(const AudioEffectOptions* options) {
|
void AudioDeviceScriptingInterface::setReverbOptions(const AudioEffectOptions* options) {
|
||||||
Application::getInstance()->getAudio()->setReverbOptions(options);
|
Application::getInstance()->getAudio()->setReverbOptions(options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void AudioDeviceScriptingInterface::toggleMute() {
|
||||||
|
Application::getInstance()->getAudio()->toggleMute();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool AudioDeviceScriptingInterface::getMuted() {
|
||||||
|
return Application::getInstance()->getAudio()->getMuted();
|
||||||
|
}
|
||||||
|
|
|
@ -41,6 +41,12 @@ public slots:
|
||||||
void setInputVolume(float volume);
|
void setInputVolume(float volume);
|
||||||
void setReverb(bool reverb);
|
void setReverb(bool reverb);
|
||||||
void setReverbOptions(const AudioEffectOptions* options);
|
void setReverbOptions(const AudioEffectOptions* options);
|
||||||
|
|
||||||
|
bool getMuted();
|
||||||
|
void toggleMute();
|
||||||
|
|
||||||
|
signals:
|
||||||
|
void muteToggled();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // hifi_AudioDeviceScriptingInterface_h
|
#endif // hifi_AudioDeviceScriptingInterface_h
|
||||||
|
|
|
@ -183,7 +183,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direc
|
||||||
float dist = sqrt(x * x + y * y);
|
float dist = sqrt(x * x + y * y);
|
||||||
float z = -sqrt(1.0f - dist * dist);
|
float z = -sqrt(1.0f - dist * dist);
|
||||||
|
|
||||||
glm::vec3 relativePosition = myAvatar->getHead()->getEyePosition() +
|
glm::vec3 relativePosition = myAvatar->getDefaultEyePosition() +
|
||||||
glm::normalize(myAvatar->getOrientation() * glm::vec3(x, y, z));
|
glm::normalize(myAvatar->getOrientation() * glm::vec3(x, y, z));
|
||||||
|
|
||||||
//Rotate the UI pick ray by the avatar orientation
|
//Rotate the UI pick ray by the avatar orientation
|
||||||
|
@ -380,7 +380,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
|
||||||
|
|
||||||
glPushMatrix();
|
glPushMatrix();
|
||||||
const glm::quat& orientation = myAvatar->getOrientation();
|
const glm::quat& orientation = myAvatar->getOrientation();
|
||||||
const glm::vec3& position = myAvatar->getHead()->getEyePosition();
|
const glm::vec3& position = myAvatar->getDefaultEyePosition();
|
||||||
|
|
||||||
glm::mat4 rotation = glm::toMat4(orientation);
|
glm::mat4 rotation = glm::toMat4(orientation);
|
||||||
|
|
||||||
|
@ -414,7 +414,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
|
||||||
|
|
||||||
renderTexturedHemisphere();
|
renderTexturedHemisphere();
|
||||||
|
|
||||||
renderPointersOculus(myAvatar->getHead()->getEyePosition());
|
renderPointersOculus(myAvatar->getDefaultEyePosition());
|
||||||
|
|
||||||
glDepthMask(GL_TRUE);
|
glDepthMask(GL_TRUE);
|
||||||
glBindTexture(GL_TEXTURE_2D, 0);
|
glBindTexture(GL_TEXTURE_2D, 0);
|
||||||
|
@ -1220,7 +1220,7 @@ void ApplicationOverlay::renderTexturedHemisphere() {
|
||||||
Application* application = Application::getInstance();
|
Application* application = Application::getInstance();
|
||||||
MyAvatar* myAvatar = application->getAvatar();
|
MyAvatar* myAvatar = application->getAvatar();
|
||||||
const glm::quat& orientation = myAvatar->getOrientation();
|
const glm::quat& orientation = myAvatar->getOrientation();
|
||||||
const glm::vec3& position = myAvatar->getHead()->getEyePosition();
|
const glm::vec3& position = myAvatar->getDefaultEyePosition();
|
||||||
|
|
||||||
glm::mat4 rotation = glm::toMat4(orientation);
|
glm::mat4 rotation = glm::toMat4(orientation);
|
||||||
|
|
||||||
|
|
|
@ -26,8 +26,9 @@ AudioInjector::AudioInjector(QObject* parent) :
|
||||||
_sound(NULL),
|
_sound(NULL),
|
||||||
_options(),
|
_options(),
|
||||||
_shouldStop(false),
|
_shouldStop(false),
|
||||||
_currentSendPosition(0),
|
_loudness(0.0f),
|
||||||
_loudness(0.0f)
|
_isFinished(false),
|
||||||
|
_currentSendPosition(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -35,8 +36,9 @@ AudioInjector::AudioInjector(Sound* sound, const AudioInjectorOptions& injectorO
|
||||||
_sound(sound),
|
_sound(sound),
|
||||||
_options(injectorOptions),
|
_options(injectorOptions),
|
||||||
_shouldStop(false),
|
_shouldStop(false),
|
||||||
_currentSendPosition(0),
|
_loudness(0.0f),
|
||||||
_loudness(0.0f)
|
_isFinished(false),
|
||||||
|
_currentSendPosition(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -176,5 +178,6 @@ void AudioInjector::injectAudio() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_isFinished = true;
|
||||||
emit finished();
|
emit finished();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
AudioInjector(QObject* parent);
|
AudioInjector(QObject* parent);
|
||||||
AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions);
|
AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions);
|
||||||
|
|
||||||
|
bool isFinished() const { return _isFinished; }
|
||||||
int getCurrentSendPosition() const { return _currentSendPosition; }
|
int getCurrentSendPosition() const { return _currentSendPosition; }
|
||||||
public slots:
|
public slots:
|
||||||
void injectAudio();
|
void injectAudio();
|
||||||
|
@ -41,8 +42,10 @@ private:
|
||||||
Sound* _sound;
|
Sound* _sound;
|
||||||
AudioInjectorOptions _options;
|
AudioInjectorOptions _options;
|
||||||
bool _shouldStop;
|
bool _shouldStop;
|
||||||
int _currentSendPosition;
|
|
||||||
float _loudness;
|
float _loudness;
|
||||||
|
bool _isFinished;
|
||||||
|
int _currentSendPosition;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_METATYPE(AudioInjector*)
|
Q_DECLARE_METATYPE(AudioInjector*)
|
||||||
|
|
|
@ -11,6 +11,26 @@
|
||||||
|
|
||||||
#include "AudioScriptingInterface.h"
|
#include "AudioScriptingInterface.h"
|
||||||
|
|
||||||
|
AudioScriptingInterface& AudioScriptingInterface::getInstance() {
|
||||||
|
static AudioScriptingInterface staticInstance;
|
||||||
|
return staticInstance;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AudioScriptingInterface::stopAllInjectors() {
|
||||||
|
QList<QPointer<AudioInjector> >::iterator injector = _activeInjectors.begin();
|
||||||
|
while (injector != _activeInjectors.end()) {
|
||||||
|
if (!injector->isNull()) {
|
||||||
|
injector->data()->stop();
|
||||||
|
|
||||||
|
while (injector->data() && !injector->data()->isFinished()) {
|
||||||
|
// wait for this injector to go down
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
injector = _activeInjectors.erase(injector);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions* injectorOptions) {
|
AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjectorOptions* injectorOptions) {
|
||||||
|
|
||||||
if (sound->isStereo()) {
|
if (sound->isStereo()) {
|
||||||
|
@ -23,15 +43,18 @@ AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjec
|
||||||
injector->moveToThread(injectorThread);
|
injector->moveToThread(injectorThread);
|
||||||
|
|
||||||
// start injecting when the injector thread starts
|
// start injecting when the injector thread starts
|
||||||
connect(injectorThread, SIGNAL(started()), injector, SLOT(injectAudio()));
|
connect(injectorThread, &QThread::started, injector, &AudioInjector::injectAudio);
|
||||||
|
|
||||||
// connect the right slots and signals so that the AudioInjector is killed once the injection is complete
|
// connect the right slots and signals so that the AudioInjector is killed once the injection is complete
|
||||||
connect(injector, SIGNAL(finished()), injector, SLOT(deleteLater()));
|
connect(injector, &AudioInjector::finished, injector, &AudioInjector::deleteLater);
|
||||||
connect(injector, SIGNAL(finished()), injectorThread, SLOT(quit()));
|
connect(injector, &AudioInjector::finished, injectorThread, &QThread::quit);
|
||||||
connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater()));
|
connect(injector, &AudioInjector::finished, this, &AudioScriptingInterface::injectorStopped);
|
||||||
|
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
|
||||||
|
|
||||||
injectorThread->start();
|
injectorThread->start();
|
||||||
|
|
||||||
|
_activeInjectors.append(QPointer<AudioInjector>(injector));
|
||||||
|
|
||||||
return injector;
|
return injector;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,24 +76,6 @@ float AudioScriptingInterface::getLoudness(AudioInjector* injector) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay,
|
void AudioScriptingInterface::injectorStopped() {
|
||||||
const AudioInjectorOptions* injectorOptions) {
|
_activeInjectors.removeAll(QPointer<AudioInjector>(reinterpret_cast<AudioInjector*>(sender())));
|
||||||
|
|
||||||
Sound* sound = new Sound(volume, frequency, duration, decay);
|
|
||||||
AudioInjector* injector = new AudioInjector(sound, *injectorOptions);
|
|
||||||
sound->setParent(injector);
|
|
||||||
|
|
||||||
QThread* injectorThread = new QThread();
|
|
||||||
|
|
||||||
injector->moveToThread(injectorThread);
|
|
||||||
|
|
||||||
// start injecting when the injector thread starts
|
|
||||||
connect(injectorThread, SIGNAL(started()), injector, SLOT(injectAudio()));
|
|
||||||
|
|
||||||
// connect the right slots and signals so that the AudioInjector is killed once the injection is complete
|
|
||||||
connect(injector, SIGNAL(finished()), injector, SLOT(deleteLater()));
|
|
||||||
connect(injector, SIGNAL(finished()), injectorThread, SLOT(quit()));
|
|
||||||
connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater()));
|
|
||||||
|
|
||||||
injectorThread->start();
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
#ifndef hifi_AudioScriptingInterface_h
|
#ifndef hifi_AudioScriptingInterface_h
|
||||||
#define hifi_AudioScriptingInterface_h
|
#define hifi_AudioScriptingInterface_h
|
||||||
|
|
||||||
|
#include <qpointer.h>
|
||||||
|
|
||||||
#include "AudioInjector.h"
|
#include "AudioInjector.h"
|
||||||
#include "Sound.h"
|
#include "Sound.h"
|
||||||
|
|
||||||
|
@ -19,13 +21,24 @@ const AudioInjectorOptions DEFAULT_INJECTOR_OPTIONS;
|
||||||
|
|
||||||
class AudioScriptingInterface : public QObject {
|
class AudioScriptingInterface : public QObject {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
static AudioScriptingInterface& getInstance();
|
||||||
|
|
||||||
|
void stopAllInjectors();
|
||||||
public slots:
|
public slots:
|
||||||
static AudioInjector* playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL);
|
|
||||||
static void stopInjector(AudioInjector* injector);
|
|
||||||
static bool isInjectorPlaying(AudioInjector* injector);
|
|
||||||
static float getLoudness(AudioInjector* injector);
|
static float getLoudness(AudioInjector* injector);
|
||||||
static void startDrumSound(float volume, float frequency, float duration, float decay,
|
|
||||||
const AudioInjectorOptions* injectorOptions = NULL);
|
AudioInjector* playSound(Sound* sound, const AudioInjectorOptions* injectorOptions = NULL);
|
||||||
|
void stopInjector(AudioInjector* injector);
|
||||||
|
bool isInjectorPlaying(AudioInjector* injector);
|
||||||
|
|
||||||
|
void injectorStopped();
|
||||||
|
|
||||||
|
private:
|
||||||
|
AudioScriptingInterface() {};
|
||||||
|
QList< QPointer<AudioInjector> > _activeInjectors;
|
||||||
|
|
||||||
|
|
||||||
};
|
};
|
||||||
#endif // hifi_AudioScriptingInterface_h
|
#endif // hifi_AudioScriptingInterface_h
|
||||||
|
|
|
@ -290,7 +290,7 @@ void ScriptEngine::init() {
|
||||||
qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue);
|
qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue);
|
||||||
|
|
||||||
registerGlobalObject("Script", this);
|
registerGlobalObject("Script", this);
|
||||||
registerGlobalObject("Audio", &_audioScriptingInterface);
|
registerGlobalObject("Audio", &AudioScriptingInterface::getInstance());
|
||||||
registerGlobalObject("Controller", _controllerScriptingInterface);
|
registerGlobalObject("Controller", _controllerScriptingInterface);
|
||||||
registerGlobalObject("Entities", &_entityScriptingInterface);
|
registerGlobalObject("Entities", &_entityScriptingInterface);
|
||||||
registerGlobalObject("Quat", &_quatLibrary);
|
registerGlobalObject("Quat", &_quatLibrary);
|
||||||
|
|
|
@ -142,7 +142,6 @@ private:
|
||||||
static EntityScriptingInterface _entityScriptingInterface;
|
static EntityScriptingInterface _entityScriptingInterface;
|
||||||
|
|
||||||
AbstractControllerScriptingInterface* _controllerScriptingInterface;
|
AbstractControllerScriptingInterface* _controllerScriptingInterface;
|
||||||
AudioScriptingInterface _audioScriptingInterface;
|
|
||||||
AvatarData* _avatarData;
|
AvatarData* _avatarData;
|
||||||
QString _scriptName;
|
QString _scriptName;
|
||||||
QString _fileNameString;
|
QString _fileNameString;
|
||||||
|
|
Loading…
Reference in a new issue