merge fix

This commit is contained in:
Philip Rosedale 2014-11-05 21:08:24 -08:00
commit 54957a2fa1
24 changed files with 339 additions and 289 deletions

View 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);

View file

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

View file

@ -11,50 +11,8 @@
// 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) {
// find the right "right" direction
vec3 firstRightCandidate = cross(gl_LightSource[1].spotDirection, vec3(0.0, 1.0, 0.0));
vec3 secondRightCandidate = cross(gl_LightSource[1].spotDirection, vec3(1.0, 0.0, 0.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);
gl_Position = ftransform();
vec4 projected = gl_Position / gl_Position.w;
gl_TexCoord[0] = vec4(dot(projected, gl_ObjectPlaneS[3]), dot(projected, gl_ObjectPlaneT[3]), 0.0, 1.0);
}

View file

@ -39,8 +39,13 @@ uniform vec2 depthTexCoordScale;
uniform float radius;
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
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);
// get the normal from the map

View file

@ -39,8 +39,13 @@ uniform vec2 depthTexCoordScale;
uniform float radius;
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
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);
// get the normal from the map

View file

@ -450,6 +450,9 @@ Application::~Application() {
_audio.thread()->quit();
_audio.thread()->wait();
// kill any audio injectors that are still around
AudioScriptingInterface::getInstance().stopAllInjectors();
_octreeProcessor.terminate();
_voxelHideShowThread.terminate();
_voxelEditSender.terminate();
@ -620,8 +623,8 @@ void Application::paintGL() {
} else if (_myCamera.getMode() == CAMERA_MODE_THIRD_PERSON) {
static const float THIRD_PERSON_CAMERA_DISTANCE = 1.5f;
_myCamera.setPosition(_myAvatar->getUprightHeadPosition() +
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * THIRD_PERSON_CAMERA_DISTANCE * _myAvatar->getScale());
_myCamera.setPosition(_myAvatar->getDefaultEyePosition() +
_myAvatar->getOrientation() * glm::vec3(0.0f, 0.0f, 1.0f) * THIRD_PERSON_CAMERA_DISTANCE * _myAvatar->getScale());
if (OculusManager::isConnected()) {
_myCamera.setRotation(_myAvatar->getWorldAlignedOrientation());
} else {
@ -1980,6 +1983,9 @@ void Application::init() {
connect(getAudio(), &Audio::preProcessOriginalInboundAudio, &_audioReflector,
&AudioReflector::preProcessOriginalInboundAudio,Qt::DirectConnection);
connect(getAudio(), &Audio::muteToggled, AudioDeviceScriptingInterface::getInstance(),
&AudioDeviceScriptingInterface::muteToggled, Qt::DirectConnection);
// save settings when avatar changes
connect(_myAvatar, &MyAvatar::transformChanged, this, &Application::bumpSettings);
}

View file

@ -1057,10 +1057,6 @@ float Avatar::getPelvisFloatingHeight() const {
return -_skeletonModel.getBindExtents().minimum.y;
}
float Avatar::getPelvisToHeadLength() const {
return glm::distance(_position, getHead()->getPosition());
}
void Avatar::setShowDisplayName(bool showDisplayName) {
if (!Menu::getInstance()->isOptionChecked(MenuOption::NamesAboveHeads)) {
_displayNameAlpha = 0.0f;

View file

@ -230,7 +230,6 @@ protected:
float getSkeletonHeight() const;
float getHeadHeight() const;
float getPelvisFloatingHeight() const;
float getPelvisToHeadLength() const;
glm::vec3 getDisplayNamePosition();
void renderDisplayName();

View file

@ -416,7 +416,7 @@ void MyAvatar::renderDebugBodyPoints() {
glPushMatrix();
glColor4f(0, 1, 0, .5f);
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();
// Head Sphere
@ -424,7 +424,7 @@ void MyAvatar::renderDebugBodyPoints() {
glPushMatrix();
glColor4f(0, 1, 0, .5f);
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();
}
@ -1004,10 +1004,6 @@ bool MyAvatar::isLookingAtLeftEye() {
return _isLookingAtLeftEye;
}
glm::vec3 MyAvatar::getUprightHeadPosition() const {
return _position + getWorldAlignedOrientation() * glm::vec3(0.0f, getPelvisToHeadLength(), 0.0f);
}
glm::vec3 MyAvatar::getDefaultEyePosition() const {
return _position + getWorldAlignedOrientation() * _skeletonModel.getDefaultEyeModelPosition();
}

View file

@ -66,7 +66,6 @@ public:
const glm::vec3& getMouseRayOrigin() const { return _mouseRayOrigin; }
const glm::vec3& getMouseRayDirection() const { return _mouseRayDirection; }
glm::vec3 getGravity() const { return _gravity; }
glm::vec3 getUprightHeadPosition() const;
glm::vec3 getDefaultEyePosition() const;
bool getShouldRenderLocally() const { return _shouldRender; }

View file

@ -126,6 +126,7 @@ void OculusManager::connect() {
if (!_camera) {
_camera = new Camera;
configureCamera(*_camera, 0, 0); // no need to use screen dimensions; they're ignored
}
if (!_programInitialized) {
@ -420,7 +421,7 @@ void OculusManager::endFrameTiming() {
//Sets the camera FoV and aspect ratio
void OculusManager::configureCamera(Camera& camera, int screenWidth, int screenHeight) {
#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);
#endif
}

View file

@ -73,6 +73,12 @@ void DeferredLightingEffect::renderWireCube(float size) {
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,
const glm::vec3& diffuse, const glm::vec3& specular, float constantAttenuation,
float linearAttenuation, float quadraticAttenuation) {
@ -216,11 +222,18 @@ void DeferredLightingEffect::render() {
glEnable(GL_BLEND);
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 tCoefficients(0.0f, tHeight / 2.0f, 0.0f, tMin + tHeight / 2.0f);
glTexGenfv(GL_S, GL_OBJECT_PLANE, (const GLfloat*)&sCoefficients);
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()) {
_pointLight.bind();
_pointLight.setUniformValue(_pointLightLocations.nearLocation, nearVal);
@ -238,7 +251,28 @@ void DeferredLightingEffect::render() {
glLightf(GL_LIGHT1, GL_LINEAR_ATTENUATION, light.linearAttenuation);
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();
@ -265,7 +299,34 @@ void DeferredLightingEffect::render() {
glLightf(GL_LIGHT1, GL_SPOT_EXPONENT, light.exponent);
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();
@ -285,6 +346,8 @@ void DeferredLightingEffect::render() {
freeFBO->release();
glDisable(GL_CULL_FACE);
// now transfer the lit region to the primary fbo
glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_CONSTANT_ALPHA, GL_ONE);
glColorMask(true, true, true, false);

View file

@ -47,6 +47,9 @@ public:
//// Renders a wireframe cube with the simple program.
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.
void addPointLight(const glm::vec3& position, float radius, const glm::vec3& ambient = glm::vec3(0.0f, 0.0f, 0.0f),

View file

@ -110,15 +110,18 @@ void GeometryCache::renderHemisphere(int slices, int stacks) {
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) {
VerticesIndices& vbo = _sphereVBOs[IntPair(slices, stacks)];
int vertices = slices * (stacks - 1) + 2;
const int NUM_VERTICES_PER_TRIANGLE = 3;
const int NUM_TRIANGLES_PER_QUAD = 2;
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;
int vertices = slices * (stacks - 1) + 2;
int indices = slices * stacks * NUM_VERTICES_PER_TRIANGULATED_QUAD;
if (vbo.first == 0) {
GLfloat* vertexData = new GLfloat[vertices * NUM_COORDS_PER_VERTEX];
GLfloat* vertex = vertexData;
@ -148,8 +151,7 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks) {
glGenBuffers(1, &vbo.first);
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
const int BYTES_PER_VERTEX = NUM_COORDS_PER_VERTEX * sizeof(GLfloat);
glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
delete[] vertexData;
GLushort* indexData = new GLushort[indices];
@ -192,8 +194,7 @@ void GeometryCache::renderSphere(float radius, int slices, int stacks) {
glGenBuffers(1, &vbo.second);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
const int BYTES_PER_INDEX = sizeof(GLushort);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
delete[] indexData;
} else {
@ -239,8 +240,7 @@ void GeometryCache::renderSquare(int xDivisions, int yDivisions) {
glGenBuffers(1, &vbo.first);
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat);
glBufferData(GL_ARRAY_BUFFER, vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
delete[] vertexData;
GLushort* indexData = new GLushort[indices];
@ -263,8 +263,7 @@ void GeometryCache::renderSquare(int xDivisions, int yDivisions) {
glGenBuffers(1, &vbo.second);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
const int BYTES_PER_INDEX = sizeof(GLushort);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
delete[] indexData;
} else {
@ -313,8 +312,7 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) {
glGenBuffers(1, &vbo.first);
glBindBuffer(GL_ARRAY_BUFFER, vbo.first);
const int BYTES_PER_VERTEX = 3 * sizeof(GLfloat);
glBufferData(GL_ARRAY_BUFFER, 2 * vertices * BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
glBufferData(GL_ARRAY_BUFFER, 2 * vertices * NUM_BYTES_PER_VERTEX, vertexData, GL_STATIC_DRAW);
delete[] vertexData;
GLushort* indexData = new GLushort[indices];
@ -337,8 +335,7 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) {
glGenBuffers(1, &vbo.second);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo.second);
const int BYTES_PER_INDEX = sizeof(GLushort);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices * NUM_BYTES_PER_INDEX, indexData, GL_STATIC_DRAW);
delete[] indexData;
} else {
@ -360,6 +357,106 @@ void GeometryCache::renderHalfCylinder(int slices, int stacks) {
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) {
QOpenGLBuffer& buffer = _gridBuffers[IntPair(xDivisions, yDivisions)];
int vertices = (xDivisions + 1 + yDivisions + 1) * 2;

View file

@ -42,6 +42,7 @@ public:
void renderSphere(float radius, int slices, int stacks);
void renderSquare(int xDivisions, int yDivisions);
void renderHalfCylinder(int slices, int stacks);
void renderCone(float base, float height, int slices, int stacks);
void renderGrid(int xDivisions, int yDivisions);
/// Loads geometry from the specified URL.
@ -71,6 +72,7 @@ private:
QHash<IntPair, VerticesIndices> _sphereVBOs;
QHash<IntPair, VerticesIndices> _squareVBOs;
QHash<IntPair, VerticesIndices> _halfCylinderVBOs;
QHash<IntPair, VerticesIndices> _coneVBOs;
QHash<IntPair, QOpenGLBuffer> _gridBuffers;
QHash<QUrl, QWeakPointer<NetworkGeometry> > _networkGeometry;

View file

@ -78,3 +78,11 @@ void AudioDeviceScriptingInterface::setReverb(bool reverb) {
void AudioDeviceScriptingInterface::setReverbOptions(const AudioEffectOptions* options) {
Application::getInstance()->getAudio()->setReverbOptions(options);
}
void AudioDeviceScriptingInterface::toggleMute() {
Application::getInstance()->getAudio()->toggleMute();
}
bool AudioDeviceScriptingInterface::getMuted() {
return Application::getInstance()->getAudio()->getMuted();
}

View file

@ -41,6 +41,12 @@ public slots:
void setInputVolume(float volume);
void setReverb(bool reverb);
void setReverbOptions(const AudioEffectOptions* options);
bool getMuted();
void toggleMute();
signals:
void muteToggled();
};
#endif // hifi_AudioDeviceScriptingInterface_h

View file

@ -183,7 +183,7 @@ void ApplicationOverlay::computeOculusPickRay(float x, float y, glm::vec3& direc
float dist = sqrt(x * x + y * y);
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));
//Rotate the UI pick ray by the avatar orientation
@ -380,7 +380,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
glPushMatrix();
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);
@ -414,7 +414,7 @@ void ApplicationOverlay::displayOverlayTextureOculus(Camera& whichCamera) {
renderTexturedHemisphere();
renderPointersOculus(myAvatar->getHead()->getEyePosition());
renderPointersOculus(myAvatar->getDefaultEyePosition());
glDepthMask(GL_TRUE);
glBindTexture(GL_TEXTURE_2D, 0);
@ -1220,7 +1220,7 @@ void ApplicationOverlay::renderTexturedHemisphere() {
Application* application = Application::getInstance();
MyAvatar* myAvatar = application->getAvatar();
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);

View file

@ -26,8 +26,9 @@ AudioInjector::AudioInjector(QObject* parent) :
_sound(NULL),
_options(),
_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),
_options(injectorOptions),
_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();
}

View file

@ -27,6 +27,7 @@ public:
AudioInjector(QObject* parent);
AudioInjector(Sound* sound, const AudioInjectorOptions& injectorOptions);
bool isFinished() const { return _isFinished; }
int getCurrentSendPosition() const { return _currentSendPosition; }
public slots:
void injectAudio();
@ -41,8 +42,10 @@ private:
Sound* _sound;
AudioInjectorOptions _options;
bool _shouldStop;
int _currentSendPosition;
float _loudness;
bool _isFinished;
int _currentSendPosition;
};
Q_DECLARE_METATYPE(AudioInjector*)

View file

@ -11,6 +11,26 @@
#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) {
if (sound->isStereo()) {
@ -23,15 +43,18 @@ AudioInjector* AudioScriptingInterface::playSound(Sound* sound, const AudioInjec
injector->moveToThread(injectorThread);
// 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(injector, SIGNAL(finished()), injector, SLOT(deleteLater()));
connect(injector, SIGNAL(finished()), injectorThread, SLOT(quit()));
connect(injectorThread, SIGNAL(finished()), injectorThread, SLOT(deleteLater()));
connect(injector, &AudioInjector::finished, injector, &AudioInjector::deleteLater);
connect(injector, &AudioInjector::finished, injectorThread, &QThread::quit);
connect(injector, &AudioInjector::finished, this, &AudioScriptingInterface::injectorStopped);
connect(injectorThread, &QThread::finished, injectorThread, &QThread::deleteLater);
injectorThread->start();
_activeInjectors.append(QPointer<AudioInjector>(injector));
return injector;
}
@ -53,24 +76,6 @@ float AudioScriptingInterface::getLoudness(AudioInjector* injector) {
}
}
void AudioScriptingInterface::startDrumSound(float volume, float frequency, float duration, float decay,
const AudioInjectorOptions* injectorOptions) {
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();
void AudioScriptingInterface::injectorStopped() {
_activeInjectors.removeAll(QPointer<AudioInjector>(reinterpret_cast<AudioInjector*>(sender())));
}

View file

@ -12,6 +12,8 @@
#ifndef hifi_AudioScriptingInterface_h
#define hifi_AudioScriptingInterface_h
#include <qpointer.h>
#include "AudioInjector.h"
#include "Sound.h"
@ -19,13 +21,24 @@ const AudioInjectorOptions DEFAULT_INJECTOR_OPTIONS;
class AudioScriptingInterface : public QObject {
Q_OBJECT
public:
static AudioScriptingInterface& getInstance();
void stopAllInjectors();
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 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

View file

@ -290,7 +290,7 @@ void ScriptEngine::init() {
qScriptRegisterMetaType(this, animationDetailsToScriptValue, animationDetailsFromScriptValue);
registerGlobalObject("Script", this);
registerGlobalObject("Audio", &_audioScriptingInterface);
registerGlobalObject("Audio", &AudioScriptingInterface::getInstance());
registerGlobalObject("Controller", _controllerScriptingInterface);
registerGlobalObject("Entities", &_entityScriptingInterface);
registerGlobalObject("Quat", &_quatLibrary);

View file

@ -142,7 +142,6 @@ private:
static EntityScriptingInterface _entityScriptingInterface;
AbstractControllerScriptingInterface* _controllerScriptingInterface;
AudioScriptingInterface _audioScriptingInterface;
AvatarData* _avatarData;
QString _scriptName;
QString _fileNameString;