Merge pull request #2061 from PhilipRosedale/master

Added DC offset correction for crappy sound input devices, mousewheel voxel edit size
This commit is contained in:
ZappoMan 2014-02-24 17:32:16 -08:00
commit 3a5bbfd989
11 changed files with 90 additions and 29 deletions

View file

@ -23,6 +23,9 @@ var NEW_VOXEL_DISTANCE_FROM_CAMERA = 3.0;
var ORBIT_RATE_ALTITUDE = 200.0;
var ORBIT_RATE_AZIMUTH = 90.0;
var PIXELS_PER_EXTRUDE_VOXEL = 16;
var WHEEL_PIXELS_PER_SCALE_CHANGE = 100;
var MAX_VOXEL_SCALE = 1.0;
var MIN_VOXEL_SCALE = 1.0 / Math.pow(2.0, 8.0);
var zFightingSizeAdjust = 0.002; // used to adjust preview voxels to prevent z fighting
var previewLineWidth = 1.5;
@ -41,6 +44,7 @@ var orbitAzimuth = 0.0;
var orbitAltitude = 0.0;
var orbitCenter = { x: 0, y: 0, z: 0 };
var orbitPosition = { x: 0, y: 0, z: 0 };
var torsoToEyeVector = { x: 0, y: 0, z: 0 };
var orbitRadius = 0.0;
var extrudeDirection = { x: 0, y: 0, z: 0 };
var extrudeScale = 0.0;
@ -48,6 +52,8 @@ var lastVoxelPosition = { x: 0, y: 0, z: 0 };
var lastVoxelColor = { red: 0, green: 0, blue: 0 };
var lastVoxelScale = 0;
var dragStart = { x: 0, y: 0 };
var wheelPixelsMoved = 0;
var mouseX = 0;
var mouseY = 0;
@ -66,16 +72,15 @@ var numColors = 8;
var whichColor = -1; // Starting color is 'Copy' mode
// Create sounds for adding, deleting, recoloring voxels
var addSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create.raw");
var deleteSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+delete.raw");
var changeColorSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+edit.raw");
var addSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+create+2.raw");
var deleteSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+delete+2.raw");
var changeColorSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Voxels/voxel+edit+2.raw");
var clickSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Switches+and+sliders/toggle+switch+-+medium.raw");
var audioOptions = new AudioInjectionOptions();
audioOptions.volume = 0.5;
audioOptions.position = Vec3.sum(MyAvatar.position, { x: 0, y: 1, z: 0 } ); // start with audio slightly above the avatar
var editToolsOn = false; // starts out off
var editToolsOn = true; // starts out off
// previewAsVoxel - by default, we will preview adds/deletes/recolors as just 4 lines on the intersecting face. But if you
// the preview to show a full voxel then set this to true and the voxel will be displayed for voxel editing
@ -270,11 +275,16 @@ var pointerVoxelScale = 0; // this is the voxel scale used for click to add or d
var pointerVoxelScaleSet = false; // if voxel scale has not yet been set, we use the intersection size
var pointerVoxelScaleSteps = 8; // the number of slider position steps
var pointerVoxelScaleOriginStep = 3; // the position of slider for the 1 meter size voxel
var pointerVoxelScaleOriginStep = 8; // the position of slider for the 1 meter size voxel
var pointerVoxelScaleMin = Math.pow(2, (1-pointerVoxelScaleOriginStep));
var pointerVoxelScaleMax = Math.pow(2, (pointerVoxelScaleSteps-pointerVoxelScaleOriginStep));
var thumbDeltaPerStep = thumbExtents / (pointerVoxelScaleSteps - 1);
if (editToolsOn) {
moveTools();
}
function calcThumbFromScale(scale) {
var scaleLog = Math.log(scale)/Math.log(2);
var thumbStep = scaleLog + pointerVoxelScaleOriginStep;
@ -703,6 +713,9 @@ function startOrbitMode(event) {
// start orbit camera!
var cameraPosition = Camera.getPosition();
torsoToEyeVector = Vec3.subtract(cameraPosition, MyAvatar.position);
torsoToEyeVector.x = 0.0;
torsoToEyeVector.z = 0.0;
oldMode = Camera.getMode();
Camera.setMode("independent");
Camera.keepLookingAt(intersection.intersection);
@ -729,6 +742,7 @@ function handleOrbitingMove(event) {
z:(Math.cos(orbitAltitude) * Math.sin(orbitAzimuth)) * orbitRadius };
orbitPosition = Vec3.sum(orbitCenter, orbitVector);
Camera.setPosition(orbitPosition);
mouseX = event.x;
mouseY = event.y;
//print("handleOrbitingMove...");
@ -736,7 +750,7 @@ function handleOrbitingMove(event) {
function endOrbitMode(event) {
var cameraOrientation = Camera.getOrientation();
MyAvatar.position = Camera.getPosition();
MyAvatar.position = Vec3.subtract(Camera.getPosition(), torsoToEyeVector);
MyAvatar.headOrientation = cameraOrientation;
Camera.stopLooking();
Camera.setMode(oldMode);
@ -795,8 +809,7 @@ function mousePressEvent(event) {
if (!trackAsOrbitOrPan) {
var clickedOnSomething = false;
var clickedOverlay = Overlays.getOverlayAtPoint({x: event.x, y: event.y});
print("clickedOverlay="+clickedOverlay);
// If the user clicked on the thumb, handle the slider logic
if (clickedOverlay == thumb) {
@ -1318,6 +1331,32 @@ function update() {
}
}
function wheelEvent(event) {
wheelPixelsMoved += event.delta;
if (Math.abs(wheelPixelsMoved) > WHEEL_PIXELS_PER_SCALE_CHANGE)
{
if (!pointerVoxelScaleSet) {
pointerVoxelScale = 1.0;
pointerVoxelScaleSet = true;
}
if (wheelPixelsMoved > 0) {
pointerVoxelScale /= 2.0;
if (pointerVoxelScale < MIN_VOXEL_SCALE) {
pointerVoxelScale = MIN_VOXEL_SCALE;
}
} else {
pointerVoxelScale *= 2.0;
if (pointerVoxelScale > MAX_VOXEL_SCALE) {
pointerVoxelScale = MAX_VOXEL_SCALE;
}
}
calcThumbFromScale(pointerVoxelScale);
trackMouseEvent(event);
wheelPixelsMoved = 0;
}
}
Controller.wheelEvent.connect(wheelEvent);
Controller.mousePressEvent.connect(mousePressEvent);
Controller.mouseReleaseEvent.connect(mouseReleaseEvent);
Controller.mouseMoveEvent.connect(mouseMoveEvent);

View file

@ -1492,6 +1492,8 @@ void Application::idle() {
_idleLoopMeasuredJitter = _idleLoopStdev.getStDev();
_idleLoopStdev.reset();
}
_buckyBalls.simulate(timeSinceLastUpdate / 1000.f, Application::getInstance()->getAvatar()->getHandData());
// After finishing all of the above work, restart the idle timer, allowing 2ms to process events.
idleTimer->start(2);
@ -2814,6 +2816,8 @@ void Application::displaySide(Camera& whichCamera, bool selfAvatarOnly) {
"Application::displaySide() ... metavoxels...");
_metavoxels.render();
}
_buckyBalls.render();
// render particles...
_particles.render();

View file

@ -32,6 +32,7 @@
#include "Audio.h"
#include "BandwidthMeter.h"
#include "BuckyBalls.h"
#include "Camera.h"
#include "DatagramProcessor.h"
#include "Environment.h"
@ -381,6 +382,8 @@ private:
bool _justStarted;
Stars _stars;
BuckyBalls _buckyBalls;
VoxelSystem _voxels;
VoxelTree _clipboard; // if I copy/paste

View file

@ -67,6 +67,7 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p
_measuredJitter(0),
_jitterBufferSamples(initialJitterBufferSamples),
_lastInputLoudness(0),
_dcOffset(0),
_noiseGateMeasuredFloor(0),
_noiseGateSampleCounter(0),
_noiseGateOpen(false),
@ -383,8 +384,13 @@ void Audio::handleAudioInput() {
const int NOISE_GATE_WIDTH = 5;
const int NOISE_GATE_CLOSE_FRAME_DELAY = 5;
const int NOISE_GATE_FRAMES_TO_AVERAGE = 5;
const float DC_OFFSET_AVERAGING = 0.99f;
float measuredDcOffset = 0.f;
for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) {
measuredDcOffset += monoAudioSamples[i];
monoAudioSamples[i] -= (int16_t) _dcOffset;
thisSample = fabsf(monoAudioSamples[i]);
loudness += thisSample;
// Noise Reduction: Count peaks above the average loudness
@ -392,7 +398,17 @@ void Audio::handleAudioInput() {
samplesOverNoiseGate++;
}
}
_lastInputLoudness = loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
measuredDcOffset /= NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL;
if (_dcOffset == 0.f) {
// On first frame, copy over measured offset
_dcOffset = measuredDcOffset;
} else {
_dcOffset = DC_OFFSET_AVERAGING * _dcOffset + (1.f - DC_OFFSET_AVERAGING) * measuredDcOffset;
}
//
_lastInputLoudness = fabs(loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL);
float averageOfAllSampleFrames = 0.f;
_noiseSampleFrames[_noiseGateSampleCounter++] = _lastInputLoudness;
@ -413,7 +429,7 @@ void Audio::handleAudioInput() {
averageOfAllSampleFrames /= NUMBER_OF_NOISE_SAMPLE_FRAMES;
_noiseGateMeasuredFloor = smallestSample;
_noiseGateSampleCounter = 0;
//qDebug("smallest sample = %.1f, avg of all = %.1f", _noiseGateMeasuredFloor, averageOfAllSampleFrames);
}
if (_noiseGateEnabled) {

View file

@ -110,6 +110,7 @@ private:
float _measuredJitter;
int16_t _jitterBufferSamples;
float _lastInputLoudness;
float _dcOffset;
float _noiseGateMeasuredFloor;
float* _noiseSampleFrames;
int _noiseGateSampleCounter;

View file

@ -54,9 +54,12 @@ BuckyBalls::BuckyBalls() {
}
}
void BuckyBalls::grab(PalmData& palm, const glm::vec3& fingerTipPosition, glm::quat avatarOrientation, float deltaTime) {
void BuckyBalls::grab(PalmData& palm, float deltaTime) {
float penetration;
glm::vec3 diff;
FingerData& finger = palm.getFingers()[0]; // Sixense has only one finger
glm::vec3 fingerTipPosition = finger.getTipPosition();
if (palm.getControllerButtons() & BUTTON_FWD) {
if (!_bballIsGrabbed[palm.getSixenseID()]) {
// Look for a ball to grab
@ -89,7 +92,13 @@ const float COLLISION_BLEND_RATE = 0.5f;
const float ATTRACTION_BLEND_RATE = 0.9f;
const float ATTRACTION_VELOCITY_BLEND_RATE = 0.10f;
void BuckyBalls::simulate(float deltaTime) {
void BuckyBalls::simulate(float deltaTime, const HandData* handData) {
// First, update the grab behavior from the hand controllers
for (size_t i = 0; i < handData->getNumPalms(); ++i) {
PalmData palm = handData->getPalms()[i];
grab(palm, deltaTime);
}
// Look for collisions
for (int i = 0; i < NUM_BBALLS; i++) {
if (_bballElement[i] != 1) {

View file

@ -26,8 +26,8 @@ const int NUM_BBALLS = 200;
class BuckyBalls {
public:
BuckyBalls();
void grab(PalmData& palm, const glm::vec3& fingerTipPosition, glm::quat avatarOrientation, float deltaTime);
void simulate(float deltaTime);
void grab(PalmData& palm, float deltaTime);
void simulate(float deltaTime, const HandData* handData);
void render();

View file

@ -55,10 +55,6 @@ void Hand::simulate(float deltaTime, bool isMine) {
_collisionAge += deltaTime;
}
if (isMine) {
_buckyBalls.simulate(deltaTime);
}
calculateGeometry();
if (isMine) {
@ -69,8 +65,7 @@ void Hand::simulate(float deltaTime, bool isMine) {
FingerData& finger = palm.getFingers()[0]; // Sixense has only one finger
glm::vec3 fingerTipPosition = finger.getTipPosition();
_buckyBalls.grab(palm, fingerTipPosition, _owningAvatar->getOrientation(), deltaTime);
if (palm.getControllerButtons() & BUTTON_1) {
if (glm::length(fingerTipPosition - _lastFingerAddVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) {
QColor paintColor = Menu::getInstance()->getActionForOption(MenuOption::VoxelPaintColor)->data().value<QColor>();
@ -309,10 +304,6 @@ void Hand::render(bool isMine) {
_renderAlpha = 1.0;
if (isMine) {
_buckyBalls.render();
}
if (Menu::getInstance()->isOptionChecked(MenuOption::RenderSkeletonCollisionProxies)) {
// draw a green sphere at hand joint location, which is actually near the wrist)
for (size_t i = 0; i < getNumPalms(); i++) {

View file

@ -20,7 +20,6 @@
#include <AudioScriptingInterface.h>
#include <HandData.h>
#include "BuckyBalls.h"
#include "InterfaceConfig.h"
#include "world.h"
#include "VoxelSystem.h"
@ -81,8 +80,6 @@ private:
float _collisionAge;
float _collisionDuration;
BuckyBalls _buckyBalls;
// private methods
void setLeapHands(const std::vector<glm::vec3>& handPositions,
const std::vector<glm::vec3>& handNormals);

View file

@ -10,6 +10,7 @@
#include "Application.h"
#include "Avatar.h"
#include "GeometryUtil.h"
#include "Head.h"
#include "Menu.h"
#include "Util.h"

View file

@ -23,7 +23,7 @@ glm::vec3 Vec3::multiplyQbyV(const glm::quat& q, const glm::vec3& v) {
return q * v;
}
glm::vec3 Vec3::sum(const glm::vec3& v1, const glm::vec3& v2) {
glm::vec3 Vec3::sum(const glm::vec3& v1, const glm::vec3& v2) {
return v1 + v2;
}
glm::vec3 Vec3::subtract(const glm::vec3& v1, const glm::vec3& v2) {