diff --git a/examples/editVoxels.js b/examples/editVoxels.js index 80f37a76a3..5f389654cc 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -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); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 99e3f5be12..9a26c1407f 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -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(); diff --git a/interface/src/Application.h b/interface/src/Application.h index f3f4f3dbb2..c342f1f7e8 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -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 diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 22148609c8..1089eeab70 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -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) { diff --git a/interface/src/Audio.h b/interface/src/Audio.h index fd77cfb3b8..3d1166f647 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -110,6 +110,7 @@ private: float _measuredJitter; int16_t _jitterBufferSamples; float _lastInputLoudness; + float _dcOffset; float _noiseGateMeasuredFloor; float* _noiseSampleFrames; int _noiseGateSampleCounter; diff --git a/interface/src/BuckyBalls.cpp b/interface/src/BuckyBalls.cpp index fec77d97f3..4c7797d062 100644 --- a/interface/src/BuckyBalls.cpp +++ b/interface/src/BuckyBalls.cpp @@ -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) { diff --git a/interface/src/BuckyBalls.h b/interface/src/BuckyBalls.h index 19a589035d..705f85517f 100644 --- a/interface/src/BuckyBalls.h +++ b/interface/src/BuckyBalls.h @@ -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(); diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index efbdfa2438..9c62551b00 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -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(); @@ -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++) { diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 9888c9f054..059a83f18a 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -20,7 +20,6 @@ #include #include -#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& handPositions, const std::vector& handNormals); diff --git a/interface/src/avatar/Head.cpp b/interface/src/avatar/Head.cpp index de3f3cd3d8..e27c625bae 100644 --- a/interface/src/avatar/Head.cpp +++ b/interface/src/avatar/Head.cpp @@ -10,6 +10,7 @@ #include "Application.h" #include "Avatar.h" +#include "GeometryUtil.h" #include "Head.h" #include "Menu.h" #include "Util.h" diff --git a/libraries/script-engine/src/Vec3.cpp b/libraries/script-engine/src/Vec3.cpp index 1ed3ae6915..2c5bf172fd 100644 --- a/libraries/script-engine/src/Vec3.cpp +++ b/libraries/script-engine/src/Vec3.cpp @@ -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) {