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

This commit is contained in:
Andrzej Kapolka 2014-07-08 16:49:14 -07:00
commit 2dbe72a818
24 changed files with 321 additions and 118 deletions

View file

@ -32,14 +32,6 @@ set(CMAKE_INCLUDE_CURRENT_DIR ON)
# Instruct CMake to run moc automatically when needed.
set(CMAKE_AUTOMOC ON)
if (APPLE)
exec_program(uname ARGS -v OUTPUT_VARIABLE DARWIN_VERSION)
string(REGEX MATCH "[0-9]+" DARWIN_VERSION ${DARWIN_VERSION})
if (DARWIN_VERSION GREATER 12)
set(CMAKE_CXX_FLAGS "-stdlib=libstdc++")
endif (DARWIN_VERSION GREATER 12)
endif (APPLE)
# targets not supported on windows
if (NOT WIN32)
add_subdirectory(animation-server)

View file

@ -138,11 +138,14 @@ void AudioMixerClientData::pushBuffersAfterFrameSend() {
// this was a used buffer, push the output pointer forwards
PositionalAudioRingBuffer* audioBuffer = *i;
const int INJECTOR_CONSECUTIVE_NOT_MIXED_THRESHOLD = 100;
if (audioBuffer->willBeAddedToMix()) {
audioBuffer->shiftReadPosition(audioBuffer->getSamplesPerFrame());
audioBuffer->setWillBeAddedToMix(false);
} else if (audioBuffer->getType() == PositionalAudioRingBuffer::Injector
&& audioBuffer->hasStarted() && audioBuffer->isStarved()) {
&& audioBuffer->hasStarted() && audioBuffer->isStarved()
&& audioBuffer->getConsecutiveNotMixedCount() > INJECTOR_CONSECUTIVE_NOT_MIXED_THRESHOLD) {
// this is an empty audio buffer that has starved, safe to delete
// also delete its sequence number stats
QUuid streamIdentifier = ((InjectedAudioRingBuffer*)audioBuffer)->getStreamIdentifier();

View file

@ -26,8 +26,8 @@ else ()
set(RTMIDI_SEARCH_DIRS "${RTMIDI_ROOT_DIR}" "$ENV{HIFI_LIB_DIR}/rtmidi")
find_path(RTMIDI_INCLUDE_DIR RtMidi.h PATH_SUFFIXES include HINTS ${RTMIDI_SEARCH_DIRS})
find_file(RTMIDI_CPP NAMES RtMidi.cpp PATH_SUFFIXES src HINTS ${RTMIDI_SEARCH_DIRS})
find_library(RTMIDI_LIBRARY NAMES rtmidi PATH_SUFFIXES lib HINTS ${RTMIDI_SEARCH_DIRS})
include(FindPackageHandleStandardArgs)
find_package_handle_standard_args(RTMIDI DEFAULT_MSG RTMIDI_INCLUDE_DIR RTMIDI_CPP)
find_package_handle_standard_args(RTMIDI DEFAULT_MSG RTMIDI_INCLUDE_DIR RTMIDI_LIBRARY)
endif ()

View file

@ -10,27 +10,34 @@
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
function length(v) {
return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}
var clapAnimation = "https://s3-us-west-1.amazonaws.com/highfidelity-public/animations/ClapAnimations/ClapHands_Standing.fbx";
var startEndFrames = [];
startEndFrames.push({ start: 0, end: 8});
startEndFrames.push({ start: 10, end: 20});
startEndFrames.push({ start: 20, end: 28});
startEndFrames.push({ start: 30, end: 37});
startEndFrames.push({ start: 41, end: 46});
startEndFrames.push({ start: 53, end: 58});
var lastClapFrame = 0;
var lastAnimFrame = 0;
function printVector(v) {
print(v.x + ", " + v.y + ", " + v.z + "\n");
}
var claps = [];
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap1Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap2Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap3Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap4Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap5Reverb.wav"));
claps.push(new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/Clap6Reverb.wav"));
var numberOfSounds = claps.length;
function vMinus(a, b) {
var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z };
return rval;
}
var clappingNow = false;
var collectedClicks = 0;
// First, load the clap sound from a URL
var clap1 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap1.raw");
var clap2 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap2.raw");
var clap3 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap3.raw");
var clap4 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap4.raw");
var clap5 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap5.raw");
var clap6 = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/claps/clap6.raw");
var clickClappingNow = false;
var CLAP_START_RATE = 15.0;
var clapRate = CLAP_START_RATE;
var startedTimer = false;
var clapping = new Array();
clapping[0] = false;
@ -38,36 +45,94 @@ clapping[1] = false;
function maybePlaySound(deltaTime) {
// Set the location and other info for the sound to play
var palm1Position = Controller.getSpatialControlPosition(0);
var palm2Position = Controller.getSpatialControlPosition(2);
var distanceBetween = length(vMinus(palm1Position, palm2Position));
for (var palm = 0; palm < 2; palm++) {
var palmVelocity = Controller.getSpatialControlVelocity(palm * 2 + 1);
var speed = length(palmVelocity);
const CLAP_SPEED = 0.2;
const CLAP_DISTANCE = 0.2;
var animationDetails = MyAvatar.getAnimationDetails(clapAnimation);
if (!clapping[palm] && (distanceBetween < CLAP_DISTANCE) && (speed > CLAP_SPEED)) {
var options = new AudioInjectionOptions();
options.position = palm1Position;
options.volume = speed / 2.0;
if (options.volume > 1.0) options.volume = 1.0;
which = Math.floor((Math.random() * 6) + 1);
if (which == 1) { Audio.playSound(clap1, options); }
else if (which == 2) { Audio.playSound(clap2, options); }
else if (which == 3) { Audio.playSound(clap3, options); }
else if (which == 4) { Audio.playSound(clap4, options); }
else if (which == 5) { Audio.playSound(clap5, options); }
else { Audio.playSound(clap6, options); }
Audio.playSound(clap, options);
clapping[palm] = true;
} else if (clapping[palm] && (speed < (CLAP_SPEED / 4.0))) {
clapping[palm] = false;
}
var frame = Math.floor(animationDetails.frameIndex);
if (frame != lastAnimFrame) {
print("frame " + frame);
lastAnimFrame = frame;
}
for (var i = 0; i < startEndFrames.length; i++) {
if (frame == startEndFrames[i].start && (frame != lastClapFrame)) {
playClap(1.0, Camera.getPosition());
lastClapFrame = frame;
}
}
var palm1Position = MyAvatar.getLeftPalmPosition();
var palm2Position = MyAvatar.getRightPalmPosition();
var distanceBetween = Vec3.length(Vec3.subtract(palm1Position, palm2Position));
var palm1Velocity = Controller.getSpatialControlVelocity(1);
var palm2Velocity = Controller.getSpatialControlVelocity(3);
var closingVelocity = Vec3.length(Vec3.subtract(palm1Velocity, palm2Velocity));
const CLAP_SPEED = 0.7;
const CLAP_DISTANCE = 0.15;
if ((closingVelocity > CLAP_SPEED) && (distanceBetween < CLAP_DISTANCE) && !clappingNow) {
var volume = closingVelocity / 2.0;
if (volume > 1.0) volume = 1.0;
playClap(volume, palm1Position);
clappingNow = true;
} else if (clappingNow && (distanceBetween > CLAP_DISTANCE * 1.2)) {
clappingNow = false;
}
}
function playClap(volume, position) {
var options = new AudioInjectionOptions();
options.position = position;
options.volume = 1.0;
var clip = Math.floor(Math.random() * numberOfSounds);
Audio.playSound(claps[clip], options);
}
function keepClapping() {
playClap(1.0, Camera.getPosition());
}
Controller.keyPressEvent.connect(function(event) {
if(event.text == "SHIFT") {
if (!clickClappingNow) {
playClap(1.0, Camera.getPosition());
var whichClip = Math.floor(Math.random() * startEndFrames.length);
lastClapFrame = 0;
MyAvatar.startAnimation(clapAnimation, clapRate, 1.0, true, false);
clickClappingNow = true;
} else {
clapRate *= 1.25;
MyAvatar.stopAnimation(clapAnimation);
MyAvatar.startAnimation(clapAnimation, clapRate, 1.0, true, false);
collectedClicks = collectedClicks + 1;
}
}
});
var CLAP_END_WAIT_MSECS = 500;
Controller.keyReleaseEvent.connect(function(event) {
if (event.text == "SHIFT") {
if (!startedTimer) {
startedTimer = true;
collectedClicks = 0;
Script.setTimeout(stopClapping, CLAP_END_WAIT_MSECS);
}
}
});
function stopClapping() {
if (collectedClicks == 0) {
startedTimer = false;
MyAvatar.stopAnimation(clapAnimation);
clapRate = CLAP_START_RATE;
clickClappingNow = false;
} else {
startedTimer = false;
}
}
// Connect a call back that happens every frame
Script.update.connect(maybePlaySound);
Script.update.connect(maybePlaySound);
//Controller.keyPressEvent.connect(keyPressEvent);

View file

@ -57,7 +57,7 @@ var LocationMenu = function(opts) {
y: 0,
width: menuWidth + 10,
height: (menuHeight * (pageSize + 1)) + 10,
color: { red: 0, green: 0, blue: 0},
backgroundColor: { red: 0, green: 0, blue: 0},
topMargin: 4,
leftMargin: 4,
text: "",
@ -71,7 +71,7 @@ var LocationMenu = function(opts) {
y: 0,
width: menuWidth,
height: menuHeight,
color: inactiveColor,
backgroundColor: inactiveColor,
topMargin: margin,
leftMargin: margin,
text: (i == 0) ? "Loading..." : "",
@ -85,7 +85,7 @@ var LocationMenu = function(opts) {
y: 0,
width: menuWidth / 2,
height: menuHeight,
color: disabledColor,
backgroundColor: disabledColor,
topMargin: margin,
leftMargin: margin,
text: "Previous",
@ -97,7 +97,7 @@ var LocationMenu = function(opts) {
y: 0,
width: menuWidth / 2,
height: menuHeight,
color: disabledColor,
backgroundColor: disabledColor,
topMargin: margin,
leftMargin: margin,
text: "Next",
@ -175,10 +175,10 @@ var LocationMenu = function(opts) {
if (start + i < this.locations.length) {
location = this.locations[start + i];
update.text = (start + i + 1) + ". " + location.username;
update.color = inactiveColor;
update.backgroundColor = inactiveColor;
} else {
update.text = "";
update.color = disabledColor;
update.backgroundColor = disabledColor;
}
Overlays.editOverlay(this.menuItems[i].overlay, update);
this.menuItems[i].location = location;
@ -187,8 +187,8 @@ var LocationMenu = function(opts) {
this.previousEnabled = pageNumber > 0;
this.nextEnabled = pageNumber < (this.numPages - 1);
Overlays.editOverlay(this.previousButton, { color: this.previousEnabled ? prevNextColor : disabledColor});
Overlays.editOverlay(this.nextButton, { color: this.nextEnabled ? prevNextColor : disabledColor });
Overlays.editOverlay(this.previousButton, { backgroundColor: this.previousEnabled ? prevNextColor : disabledColor});
Overlays.editOverlay(this.nextButton, { backgroundColor: this.nextEnabled ? prevNextColor : disabledColor });
}
this.mousePressEvent = function(event) {
@ -198,17 +198,17 @@ var LocationMenu = function(opts) {
self.toggleMenu();
} else if (clickedOverlay == self.previousButton) {
if (self.previousEnabled) {
Overlays.editOverlay(clickedOverlay, { color: activeColor });
Overlays.editOverlay(clickedOverlay, { backgroundColor: activeColor });
}
} else if (clickedOverlay == self.nextButton) {
if (self.nextEnabled) {
Overlays.editOverlay(clickedOverlay, { color: activeColor });
Overlays.editOverlay(clickedOverlay, { backgroundColor: activeColor });
}
} else {
for (var i = 0; i < self.menuItems.length; i++) {
if (clickedOverlay == self.menuItems[i].overlay) {
if (self.menuItems[i].location != null) {
Overlays.editOverlay(clickedOverlay, { color: activeColor });
Overlays.editOverlay(clickedOverlay, { backgroundColor: activeColor });
}
break;
}
@ -221,19 +221,19 @@ var LocationMenu = function(opts) {
if (clickedOverlay == self.previousButton) {
if (self.previousEnabled) {
Overlays.editOverlay(clickedOverlay, { color: inactiveColor });
Overlays.editOverlay(clickedOverlay, { backgroundColor: inactiveColor });
self.goToPage(self.page - 1);
}
} else if (clickedOverlay == self.nextButton) {
if (self.nextEnabled) {
Overlays.editOverlay(clickedOverlay, { color: inactiveColor });
Overlays.editOverlay(clickedOverlay, { backgroundColor: inactiveColor });
self.goToPage(self.page + 1);
}
} else {
for (var i = 0; i < self.menuItems.length; i++) {
if (clickedOverlay == self.menuItems[i].overlay) {
if (self.menuItems[i].location != null) {
Overlays.editOverlay(clickedOverlay, { color: inactiveColor });
Overlays.editOverlay(clickedOverlay, { backgroundColor: inactiveColor });
var location = self.menuItems[i].location;
Window.location = "hifi://" + location.domain + "/"
+ location.x + "," + location.y + "," + location.z;

View file

@ -18,13 +18,16 @@ var RIGHT = 1;
var lastLeftFrame = 0;
var lastRightFrame = 0;
var LAST_FRAME = 11.0; // What is the number of the last frame we want to use in the animation?
var SMOOTH_FACTOR = 0.80;
var leftDirection = true;
var rightDirection = true;
var LAST_FRAME = 15.0; // What is the number of the last frame we want to use in the animation?
var SMOOTH_FACTOR = 0.0;
var MAX_FRAMES = 30.0;
Script.update.connect(function(deltaTime) {
var leftTriggerValue = Math.sqrt(Controller.getTriggerValue(LEFT));
var rightTriggerValue = Math.sqrt(Controller.getTriggerValue(RIGHT));
var leftTriggerValue = Controller.getTriggerValue(LEFT);
var rightTriggerValue = Controller.getTriggerValue(RIGHT);
var leftFrame, rightFrame;
@ -32,10 +35,31 @@ Script.update.connect(function(deltaTime) {
leftFrame = (leftTriggerValue * LAST_FRAME) * (1.0 - SMOOTH_FACTOR) + lastLeftFrame * SMOOTH_FACTOR;
rightFrame = (rightTriggerValue * LAST_FRAME) * (1.0 - SMOOTH_FACTOR) + lastRightFrame * SMOOTH_FACTOR;
if (!leftDirection) {
leftFrame = MAX_FRAMES - leftFrame;
}
if (!rightDirection) {
rightFrame = MAX_FRAMES - rightFrame;
}
if ((leftTriggerValue == 1.0) && (leftDirection == true)) {
leftDirection = false;
lastLeftFrame = MAX_FRAMES - leftFrame;
} else if ((leftTriggerValue == 0.0) && (leftDirection == false)) {
leftDirection = true;
lastLeftFrame = leftFrame;
}
if ((rightTriggerValue == 1.0) && (rightDirection == true)) {
rightDirection = false;
lastRightFrame = MAX_FRAMES - rightFrame;
} else if ((rightTriggerValue == 0.0) && (rightDirection == false)) {
rightDirection = true;
lastRightFrame = rightFrame;
}
if ((leftFrame != lastLeftFrame) && leftHandAnimation.length){
MyAvatar.stopAnimation(leftHandAnimation);
MyAvatar.startAnimation(leftHandAnimation, 30.0, 1.0, false, true, leftFrame, leftFrame);
MyAvatar.startAnimation(leftHandAnimation, 30.0, 1.0, false, true, leftFrame, leftFrame);
}
if ((rightFrame != lastRightFrame) && rightHandAnimation.length) {
MyAvatar.stopAnimation(rightHandAnimation);

View file

@ -111,16 +111,6 @@ if (APPLE)
SET(INTERFACE_SRCS ${INTERFACE_SRCS} "${CMAKE_CURRENT_SOURCE_DIR}/interface.icns")
endif()
# RtMidi for scripted MIDI control
find_package(RtMidi)
if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI)
add_definitions(-DHAVE_RTMIDI)
include_directories(SYSTEM ${RTMIDI_INCLUDE_DIR})
set(INTERFACE_SRCS ${INTERFACE_SRCS} "${RTMIDI_CPP}")
endif ()
# create the executable, make it a bundle on OS X
add_executable(${TARGET_NAME} MACOSX_BUNDLE ${INTERFACE_SRCS} ${QM})
@ -151,6 +141,7 @@ find_package(Sixense)
find_package(Visage)
find_package(ZLIB)
find_package(Qxmpp)
find_package(RtMidi)
# include the Sixense library for Razer Hydra if available
if (SIXENSE_FOUND AND NOT DISABLE_SIXENSE)
@ -223,11 +214,18 @@ if (QXMPP_FOUND AND NOT DISABLE_QXMPP)
target_link_libraries(${TARGET_NAME} "${QXMPP_LIBRARY}")
endif (QXMPP_FOUND AND NOT DISABLE_QXMPP)
# link CoreMIDI if we're using RtMidi
if (RTMIDI_FOUND AND APPLE)
find_library(CoreMIDI CoreMIDI)
add_definitions(-D__MACOSX_CORE__)
target_link_libraries(${TARGET_NAME} ${CoreMIDI})
# and with RtMidi for RtMidi control
if (RTMIDI_FOUND AND NOT DISABLE_RTMIDI)
add_definitions(-DHAVE_RTMIDI)
include_directories(SYSTEM ${RTMIDI_INCLUDE_DIR})
target_link_libraries(${TARGET_NAME} "${RTMIDI_LIBRARY}")
if (APPLE)
find_library(CoreMIDI CoreMIDI)
add_definitions(-D__MACOSX_CORE__)
target_link_libraries(${TARGET_NAME} ${CoreMIDI})
endif()
endif()
# include headers for interface and InterfaceConfig.

View file

@ -7,7 +7,9 @@ Stephen Birarda, June 30, 2014
2. Copy RtMidi.h to externals/rtmidi/include.
3. Copy RtMidi.cpp to externals/rtmidi/src
3. Compile the RtMidi library.
3. Copy either librtmidi.dylib (dynamic) or librtmidi.a (static) to externals/rtmidi/lib
4. Delete your build directory, run cmake and build, and you should be all set.

View file

@ -67,7 +67,7 @@ Audio::Audio(int16_t initialJitterBufferSamples, QObject* parent) :
_proceduralAudioOutput(NULL),
_proceduralOutputDevice(NULL),
_inputRingBuffer(0),
_ringBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO),
_ringBuffer(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO, false, 100),
_isStereoInput(false),
_averagedLatency(0.0),
_measuredJitter(0),
@ -869,14 +869,16 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
_numFramesDisplayStarve = 10;
}
// if there is anything in the ring buffer, decide what to do
if (_ringBuffer.samplesAvailable() > 0) {
int numNetworkOutputSamples = _ringBuffer.samplesAvailable();
int numDeviceOutputSamples = numNetworkOutputSamples / networkOutputToOutputRatio;
QByteArray outputBuffer;
outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t));
int numNetworkOutputSamples;
if (Menu::getInstance()->isOptionChecked(MenuOption::DisableQAudioOutputOverflowCheck)) {
numNetworkOutputSamples = _ringBuffer.samplesAvailable();
} else {
int numSamplesAudioOutputRoomFor = _audioOutput->bytesFree() / sizeof(int16_t);
numNetworkOutputSamples = std::min(_ringBuffer.samplesAvailable(), (int)(numSamplesAudioOutputRoomFor * networkOutputToOutputRatio));
}
// if there is data in the ring buffer and room in the audio output, decide what to do
if (numNetworkOutputSamples > 0) {
int numSamplesNeededToStartPlayback = std::min(NETWORK_BUFFER_LENGTH_SAMPLES_STEREO + (_jitterBufferSamples * 2),
_ringBuffer.getSampleCapacity());
@ -885,6 +887,11 @@ void Audio::processReceivedAudio(const QByteArray& audioByteArray) {
// We are still waiting for enough samples to begin playback
// qDebug() << numNetworkOutputSamples << " samples so far, waiting for " << numSamplesNeededToStartPlayback;
} else {
int numDeviceOutputSamples = numNetworkOutputSamples / networkOutputToOutputRatio;
QByteArray outputBuffer;
outputBuffer.resize(numDeviceOutputSamples * sizeof(int16_t));
// We are either already playing back, or we have enough audio to start playing back.
//qDebug() << "pushing " << numNetworkOutputSamples;
_ringBuffer.setIsStarved(false);

35
interface/src/Hair.cpp Normal file
View file

@ -0,0 +1,35 @@
//
// Hair.cpp
// interface/src
//
// Created by Philip on June 26, 2014
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
// Creates single flexible vertlet-integrated strands that can be used for hair/fur/grass
#include "Hair.h"
#include "Util.h"
#include "world.h"
Hair::Hair() {
qDebug() << "Creating Hair";
}
void Hair::simulate(float deltaTime) {
}
void Hair::render() {
//
// Before calling this function, translate/rotate to the origin of the owning object
glPushMatrix();
glColor3f(1.0f, 1.0f, 0.0f);
glutSolidSphere(1.0f, 15, 15);
glPopMatrix();
}

35
interface/src/Hair.h Normal file
View file

@ -0,0 +1,35 @@
//
// Hair.h
// interface/src
//
// Created by Philip on June 26, 2014
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
#ifndef hifi_Hair_h
#define hifi_Hair_h
#include <iostream>
#include <glm/glm.hpp>
#include <SharedUtil.h>
#include "GeometryUtil.h"
#include "InterfaceConfig.h"
#include "Util.h"
class Hair {
public:
Hair();
void simulate(float deltaTime);
void render();
private:
};
#endif // hifi_Hair_h

View file

@ -575,6 +575,8 @@ Menu::Menu() :
Qt::CTRL | Qt::SHIFT | Qt::Key_U,
false);
addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::DisableQAudioOutputOverflowCheck, 0, false);
addActionToQMenuAndActionHash(developerMenu, MenuOption::PasteToVoxel,
Qt::CTRL | Qt::SHIFT | Qt::Key_V,
this,

View file

@ -343,6 +343,7 @@ namespace MenuOption {
const QString DecreaseVoxelSize = "Decrease Voxel Size";
const QString DisableAutoAdjustLOD = "Disable Automatically Adjusting LOD";
const QString DisableNackPackets = "Disable NACK Packets";
const QString DisableQAudioOutputOverflowCheck = "Disable QAudioOutput Overflow Check";
const QString DisplayFrustum = "Display Frustum";
const QString DisplayHands = "Display Hands";
const QString DisplayHandTargets = "Display Hand Targets";

View file

@ -143,6 +143,11 @@ void Avatar::simulate(float deltaTime) {
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
simulateHair(deltaTime);
}
foreach (Hair* hair, _hairs) {
hair->simulate(deltaTime);
}
}
// update position by velocity, and subtract the change added earlier for gravity
@ -380,6 +385,9 @@ void Avatar::renderBody(RenderMode renderMode, float glowLevel) {
getHead()->render(1.0f, modelRenderMode);
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
renderHair();
foreach (Hair* hair, _hairs) {
hair->render();
}
}
}

View file

@ -19,6 +19,7 @@
#include <AvatarData.h>
#include "Hair.h"
#include "Hand.h"
#include "Head.h"
#include "InterfaceConfig.h"
@ -159,6 +160,7 @@ signals:
void collisionWithAvatar(const QUuid& myUUID, const QUuid& theirUUID, const CollisionInfo& collision);
protected:
QVector<Hair*> _hairs;
SkeletonModel _skeletonModel;
QVector<Model*> _attachmentModels;
float _bodyYawDelta;

View file

@ -199,6 +199,9 @@ void MyAvatar::simulate(float deltaTime) {
PerformanceTimer perfTimer("MyAvatar::simulate/hair Simulate");
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
simulateHair(deltaTime);
foreach (Hair* hair, _hairs) {
hair->simulate(deltaTime);
}
}
}
@ -896,6 +899,9 @@ void MyAvatar::renderBody(RenderMode renderMode, float glowLevel) {
getHead()->render(1.0f, modelRenderMode);
if (Menu::getInstance()->isOptionChecked(MenuOption::StringHair)) {
renderHair();
foreach (Hair* hair, _hairs) {
hair->render();
}
}
}
getHand()->render(true, modelRenderMode);

View file

@ -13,14 +13,13 @@
#include "MIDIManager.h"
#ifdef HAVE_RTMIDI
MIDIManager& MIDIManager::getInstance() {
static MIDIManager sharedInstance;
return sharedInstance;
}
void MIDIManager::midiCallback(double deltaTime, std::vector<unsigned char>* message, void* userData) {
#ifdef HAVE_RTMIDI
MIDIEvent callbackEvent;
callbackEvent.deltaTime = deltaTime;
@ -36,15 +35,19 @@ void MIDIManager::midiCallback(double deltaTime, std::vector<unsigned char>* mes
}
emit getInstance().midiEvent(callbackEvent);
#endif
}
MIDIManager::~MIDIManager() {
#ifdef HAVE_RTMIDI
delete _midiInput;
#endif
}
const int DEFAULT_MIDI_PORT = 0;
void MIDIManager::openDefaultPort() {
#ifdef HAVE_RTMIDI
if (!_midiInput) {
_midiInput = new RtMidiIn();
@ -63,6 +66,5 @@ void MIDIManager::openDefaultPort() {
_midiInput = NULL;
}
}
}
#endif
#endif
}

View file

@ -12,14 +12,14 @@
#ifndef hifi_MIDIManager_h
#define hifi_MIDIManager_h
#ifdef HAVE_RTMIDI
#include <QtCore/QObject>
#include <QtScript/QScriptEngine>
#include <MIDIEvent.h>
#ifdef HAVE_RTMIDI
#include <RtMidi.h>
#endif
class MIDIManager : public QObject {
Q_OBJECT
@ -36,7 +36,9 @@ public:
~MIDIManager();
void openDefaultPort();
#ifdef HAVE_RTMIDI
bool hasDevice() const { return !!_midiInput; }
#endif
public slots:
unsigned int NoteOn() const { return 144; }
unsigned int NoteOff() const { return 128; }
@ -46,10 +48,10 @@ signals:
void midiEvent(const MIDIEvent& event);
private:
#ifdef HAVE_RTMIDI
RtMidiIn* _midiInput;
};
#endif
};
#endif // hifi_MIDIManager_h

View file

@ -22,7 +22,7 @@
Overlay::Overlay() :
_parent(NULL),
_alpha(DEFAULT_ALPHA),
_color(DEFAULT_BACKGROUND_COLOR),
_color(DEFAULT_OVERLAY_COLOR),
_visible(true),
_anchor(NO_ANCHOR)
{

View file

@ -21,7 +21,7 @@
#include <SharedUtil.h> // for xColor
const xColor DEFAULT_BACKGROUND_COLOR = { 255, 255, 255 };
const xColor DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
const float DEFAULT_ALPHA = 0.7f;
class Overlay : public QObject {

View file

@ -18,6 +18,7 @@
#include "ui/TextRenderer.h"
TextOverlay::TextOverlay() :
_backgroundColor(DEFAULT_BACKGROUND_COLOR),
_leftMargin(DEFAULT_MARGIN),
_topMargin(DEFAULT_MARGIN),
_fontSize(DEFAULT_FONTSIZE)
@ -33,7 +34,7 @@ void TextOverlay::render() {
}
const float MAX_COLOR = 255;
glColor4f(0 / MAX_COLOR, 0 / MAX_COLOR, 0 / MAX_COLOR, _alpha);
glColor4f(_backgroundColor.red / MAX_COLOR, _backgroundColor.green / MAX_COLOR, _backgroundColor.blue / MAX_COLOR, _alpha);
glBegin(GL_QUADS);
glVertex2f(_bounds.left(), _bounds.top());
@ -82,6 +83,18 @@ void TextOverlay::setProperties(const QScriptValue& properties) {
setText(text.toVariant().toString());
}
QScriptValue backgroundColor = properties.property("backgroundColor");
if (backgroundColor.isValid()) {
QScriptValue red = backgroundColor.property("red");
QScriptValue green = backgroundColor.property("green");
QScriptValue blue = backgroundColor.property("blue");
if (red.isValid() && green.isValid() && blue.isValid()) {
_backgroundColor.red = red.toVariant().toInt();
_backgroundColor.green = green.toVariant().toInt();
_backgroundColor.blue = blue.toVariant().toInt();
}
}
if (properties.property("leftMargin").isValid()) {
setLeftMargin(properties.property("leftMargin").toVariant().toInt());
}

View file

@ -27,6 +27,7 @@
#include "Overlay.h"
#include "Overlay2D.h"
const xColor DEFAULT_BACKGROUND_COLOR = { 0, 0, 0 };
const int DEFAULT_MARGIN = 10;
const int DEFAULT_FONTSIZE = 11;
@ -54,6 +55,7 @@ public:
private:
QString _text;
xColor _backgroundColor;
int _leftMargin;
int _topMargin;
int _fontSize;

View file

@ -99,7 +99,8 @@ PositionalAudioRingBuffer::PositionalAudioRingBuffer(PositionalAudioRingBuffer::
_listenerUnattenuatedZone(NULL),
_desiredJitterBufferFrames(1),
_currentJitterBufferFrames(-1),
_dynamicJitterBuffers(dynamicJitterBuffers)
_dynamicJitterBuffers(dynamicJitterBuffers),
_consecutiveNotMixedCount(0)
{
}
@ -129,7 +130,7 @@ int PositionalAudioRingBuffer::parseData(const QByteArray& packet) {
numSilentSamples = getSamplesPerFrame();
if (numSilentSamples > 0) {
if (_currentJitterBufferFrames > _desiredJitterBufferFrames) {
if (_dynamicJitterBuffers && _currentJitterBufferFrames > _desiredJitterBufferFrames) {
// our current jitter buffer size exceeds its desired value, so ignore some silent
// frames to get that size as close to desired as possible
int samplesPerFrame = getSamplesPerFrame();
@ -206,11 +207,12 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
if (!isNotStarvedOrHasMinimumSamples(samplesPerFrame + desiredJitterBufferSamples)) {
// if the buffer was starved, allow it to accrue at least the desired number of
// jitter buffer frames before we start taking frames from it for mixing
if (_shouldOutputStarveDebug) {
_shouldOutputStarveDebug = false;
}
_consecutiveNotMixedCount++;
return false;
} else if (samplesAvailable() < samplesPerFrame) {
// if the buffer doesn't have a full frame of samples to take for mixing, it is starved
@ -222,6 +224,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
// reset our _shouldOutputStarveDebug to true so the next is printed
_shouldOutputStarveDebug = true;
_consecutiveNotMixedCount++;
return false;
}
@ -231,6 +234,7 @@ bool PositionalAudioRingBuffer::shouldBeAddedToMix() {
// minus one (since a frame will be read immediately after this) is the length of the jitter buffer
_currentJitterBufferFrames = samplesAvailable() / samplesPerFrame - 1;
_isStarved = false;
_consecutiveNotMixedCount = 0;
}
// since we've read data from ring buffer at least once - we've started

View file

@ -83,6 +83,8 @@ public:
int getDesiredJitterBufferFrames() const { return _desiredJitterBufferFrames; }
int getCurrentJitterBufferFrames() const { return _currentJitterBufferFrames; }
int getConsecutiveNotMixedCount() const { return _consecutiveNotMixedCount; }
protected:
// disallow copying of PositionalAudioRingBuffer objects
PositionalAudioRingBuffer(const PositionalAudioRingBuffer&);
@ -107,9 +109,7 @@ protected:
bool _dynamicJitterBuffers;
// extra stats
int _starveCount;
int _silentFramesDropped;
int _consecutiveNotMixedCount;
};
#endif // hifi_PositionalAudioRingBuffer_h