From b0e10187711a7515aa6f4db6e652c1ebb8ba876b Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 24 Jan 2014 11:01:09 -0800 Subject: [PATCH 1/6] Add particle-based bird --- examples/particleBird.js | 172 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 172 insertions(+) create mode 100644 examples/particleBird.js diff --git a/examples/particleBird.js b/examples/particleBird.js new file mode 100644 index 0000000000..a596d2650e --- /dev/null +++ b/examples/particleBird.js @@ -0,0 +1,172 @@ +// +// particleBird.js +// hifi +// +// This sample script moves a voxel around like a bird and sometimes makes tweeting noises +// + +function vLength(v) { + return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); +} + +function printVector(v) { + print(v.x + ", " + v.y + ", " + v.z + "\n"); +} + +// Create a random vector with individual lengths between a,b +function randVector(a, b) { + var rval = { x: a + Math.random() * (b - a), y: a + Math.random() * (b - a), z: a + Math.random() * (b - a) }; + return rval; +} + +function vMinus(a, b) { + var rval = { x: a.x - b.x, y: a.y - b.y, z: a.z - b.z }; + return rval; +} + +function vPlus(a, b) { + var rval = { x: a.x + b.x, y: a.y + b.y, z: a.z + b.z }; + return rval; +} + +function vCopy(a, b) { + a.x = b.x; + a.y = b.y; + a.z = b.z; + return; +} + +// Returns a vector which is fraction of the way between a and b +function vInterpolate(a, b, fraction) { + var rval = { x: a.x + (b.x - a.x) * fraction, y: a.y + (b.y - a.y) * fraction, z: a.z + (b.z - a.z) * fraction }; + return rval; +} + +// Decide what kind of bird we are +var tweet; +var color; +var size; +var which = Math.random(); +if (which < 0.2) { + tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/bushtit_1.raw"); + color = { r: 100, g: 50, b: 120 }; + size = 0.08; +} else if (which < 0.4) { + tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/rosyfacedlovebird.raw"); + color = { r: 100, g: 150, b: 75 }; + size = 0.09; +} else if (which < 0.6) { + tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/saysphoebe.raw"); + color = { r: 84, g: 121, b: 36 }; + size = 0.05; +} else if (which < 0.8) { + tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/mexicanWhipoorwill.raw"); + color = { r: 23, g: 197, b: 230 }; + size = 0.12; +} else { + tweet = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Animals/westernscreechowl.raw"); + color = { r: 50, g: 67, b: 144 }; + size = 0.15; +} + +var startPosition = { x: 0, y: 0, z: 0 }; +var targetPosition = { x: 0, y: 0, z: 0 }; + +var range = 0.7; // Over what distance in meters do you want your bird to fly around +var frame = 0; +var moving = false; +var tweeting = 0; +var moved = false; + +var CHANCE_OF_MOVING = 0.02; +var CHANCE_OF_TWEETING = 0.01; +var START_HEIGHT_ABOVE_ME = 2.0; + +var myPosition = MyAvatar.position; + +var properties = { + position: { x: myPosition.x, y: myPosition.y + START_HEIGHT_ABOVE_ME, z: myPosition.z }, + velocity: { x: 0, y: 0, z: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + radius : 0.1, + color: { red: 0, + green: 255, + blue: 0 }, + lifetime: 60 +}; + +position = properties.position; + +var range = 1.0; // Distance around avatar where I can move + +// Create the actual bird +var particleID = Particles.addParticle(properties); + +function moveBird() { + myPosition = MyAvatar.position; + myPosition.y += START_HEIGHT_ABOVE_ME; + frame++; + if (frame % 3 == 0) { + // Tweeting behavior + if (tweeting == 0) { + if (Math.random() < CHANCE_OF_TWEETING) { + //print("tweet!" + "\n"); + var options = new AudioInjectionOptions();
 + options.position = position; + options.volume = 0.75; + Audio.playSound(tweet, options); + tweeting = 10; + } + } else { + tweeting -= 1; + } + // Moving behavior + if (moving == false) { + if (Math.random() < CHANCE_OF_MOVING) { + targetPosition = randVector(- range, range); + targetPosition = vPlus(targetPosition, myPosition); + //printVector(position); + moving = true; + } + } + if (moving) { + position = vInterpolate(position, targetPosition, 0.5); + if (vLength(vMinus(position, targetPosition)) < (size / 5.0)) { + moved = false; + moving = false; + } else { + moved = true; + } + } + if (moved || (tweeting > 0)) { + if (tweeting > 0) { + var newProperties = { + position: position, + velocity: { x: 0, y: 0, z: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + radius : size * 1.5, + color: { red: Math.random() * 255, green: 0, blue: 0 } + }; + } else { + var newProperties = { + position: position, + velocity: { x: 0, y: 0, z: 0 }, + gravity: { x: 0, y: 0, z: 0 }, + radius : size, + color: { red: color.r, green: color.g, blue: color.b } + }; + } + Particles.editParticle(particleID, newProperties); + moved = false; + } + } +} + +function killBird() { + deleteParticle(particleID); +} + +// register the call back so it fires before each data send +Agent.willSendVisualDataCallback.connect(moveBird); +Agent.scriptEnding.connect(killBird); + From 3f5aa083d777cb7d9704bfe224bbd889b0a9fffb Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Mon, 3 Feb 2014 16:08:59 -0800 Subject: [PATCH 2/6] improved bird behavior --- examples/particleBird.js | 26 ++++++++++++++++++-------- 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/examples/particleBird.js b/examples/particleBird.js index abc43a2767..036b86bf0b 100644 --- a/examples/particleBird.js +++ b/examples/particleBird.js @@ -79,15 +79,18 @@ var moving = false; var tweeting = 0; var moved = false; -var CHANCE_OF_MOVING = 0.05; +var CHANCE_OF_MOVING = 0.00; +var CHANCE_OF_FLAPPING = 0.05; var CHANCE_OF_TWEETING = 0.05; var START_HEIGHT_ABOVE_ME = 1.5; +var BIRD_GRAVITY = -0.1; +var BIRD_FLAP = 1.0; var myPosition = MyAvatar.position; var properties = { lifetime: birdLifetime, position: { x: myPosition.x, y: myPosition.y + START_HEIGHT_ABOVE_ME, z: myPosition.z }, - velocity: { x: 0, y: 0, z: 0 }, - gravity: { x: 0, y: 0, z: 0 }, + velocity: { x: 0, y: Math.random() * BIRD_FLAP, z: 0 }, + gravity: { x: 0, y: BIRD_GRAVITY, z: 0 }, radius : 0.1, color: { red: 0, green: 255, @@ -101,7 +104,7 @@ function moveBird() { // check to see if we've been running long enough that our bird is dead var nowTimeInSeconds = new Date().getTime() / 1000; if ((nowTimeInSeconds - startTimeInSeconds) >= birdLifetime) { - print("our bird is dying, stop our script"); + print("This bird has died, how sad."); Agent.stop(); return; } @@ -122,10 +125,20 @@ function moveBird() { } else { tweeting -= 1; } + if (Math.random() < CHANCE_OF_FLAPPING) { + // Add a little upward impulse to our bird + // TODO: Get velocity + // + var newProperties = { + velocity: { x:0.0, y: Math.random() * BIRD_FLAP, z: 0.0 } + }; + Particles.editParticle(particleID, newProperties); + print("flap!"); + } // Moving behavior if (moving == false) { if (Math.random() < CHANCE_OF_MOVING) { - targetPosition = randVector(- range, range); + targetPosition = randVector(-range, range); targetPosition = vPlus(targetPosition, myPosition); if (targetPosition.x < 0) { @@ -162,15 +175,12 @@ function moveBird() { if (moved || (tweeting > 0)) { if (tweeting > 0) { var newProperties = { - position: position, - radius : size * 1.5, color: { red: Math.random() * 255, green: 0, blue: 0 } }; } else { var newProperties = { - position: position, radius : size, color: { red: color.r, green: color.g, blue: color.b } From 03bc5adf64b88e870405185c579d5bf31211b425 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 8 Feb 2014 16:35:37 -0800 Subject: [PATCH 3/6] Add Audio Noise Reduction --- interface/src/Audio.cpp | 42 ++++++++++++++++++++++++++-- interface/src/Audio.h | 9 +++++- interface/src/Menu.cpp | 5 ++++ interface/src/Menu.h | 1 + libraries/avatars/src/AvatarData.cpp | 2 -- 5 files changed, 53 insertions(+), 6 deletions(-) diff --git a/interface/src/Audio.cpp b/interface/src/Audio.cpp index 9dd3c0377f..6eee4453d4 100644 --- a/interface/src/Audio.cpp +++ b/interface/src/Audio.cpp @@ -65,6 +65,10 @@ Audio::Audio(Oscilloscope* scope, int16_t initialJitterBufferSamples, QObject* p _measuredJitter(0), _jitterBufferSamples(initialJitterBufferSamples), _lastInputLoudness(0), + _averageInputLoudness(0), + _noiseGateOpen(false), + _noiseGateEnabled(true), + _noiseGateFramesToClose(0), _lastVelocity(0), _lastAcceleration(0), _totalPacketsReceived(0), @@ -348,12 +352,40 @@ void Audio::handleAudioInput() { _inputFormat, _desiredInputFormat); float loudness = 0; - + float thisSample = 0; + int samplesOverNoiseGate = 0; + + const float NOISE_GATE_HEIGHT = 3.f; + const int NOISE_GATE_WIDTH = 5; + const int NOISE_GATE_CLOSE_FRAME_DELAY = 30; + for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { - loudness += fabsf(monoAudioSamples[i]); + thisSample = fabsf(monoAudioSamples[i]); + loudness += thisSample; + // Noise Reduction: Count peaks above the average loudness + if (thisSample > (_averageInputLoudness * NOISE_GATE_HEIGHT)) { + samplesOverNoiseGate++; + } } - _lastInputLoudness = loudness / NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; + const float LOUDNESS_AVERAGING_FRAMES = 1000.f; // This will be about 10 seconds + _averageInputLoudness = (1.f - 1.f / LOUDNESS_AVERAGING_FRAMES) * _averageInputLoudness + (1.f / LOUDNESS_AVERAGING_FRAMES) * _lastInputLoudness; + + if (_noiseGateEnabled) { + if (samplesOverNoiseGate > NOISE_GATE_WIDTH) { + _noiseGateOpen = true; + _noiseGateFramesToClose = NOISE_GATE_CLOSE_FRAME_DELAY; + } else { + if (--_noiseGateFramesToClose == 0) { + _noiseGateOpen = false; + } + } + if (!_noiseGateOpen) { + for (int i = 0; i < NETWORK_BUFFER_LENGTH_SAMPLES_PER_CHANNEL; i++) { + monoAudioSamples[i] = 0; + } + } + } // add input data just written to the scope QMetaObject::invokeMethod(_scope, "addSamples", Qt::QueuedConnection, @@ -524,6 +556,10 @@ void Audio::toggleMute() { muteToggled(); } +void Audio::toggleAudioNoiseReduction() { + _noiseGateEnabled = !_noiseGateEnabled; +} + void Audio::render(int screenWidth, int screenHeight) { if (_audioInput && _audioOutput) { glLineWidth(2.0); diff --git a/interface/src/Audio.h b/interface/src/Audio.h index fa4fb62adf..88e2731006 100644 --- a/interface/src/Audio.h +++ b/interface/src/Audio.h @@ -45,7 +45,9 @@ public: void render(int screenWidth, int screenHeight); - float getLastInputLoudness() const { return _lastInputLoudness; } + float getLastInputLoudness() const { return glm::max(_lastInputLoudness - _averageInputLoudness, 0.f); } + + void setNoiseGateEnabled(bool noiseGateEnabled) { _noiseGateEnabled = noiseGateEnabled; } void setLastAcceleration(const glm::vec3 lastAcceleration) { _lastAcceleration = lastAcceleration; } void setLastVelocity(const glm::vec3 lastVelocity) { _lastVelocity = lastVelocity; } @@ -73,6 +75,7 @@ public slots: void handleAudioInput(); void reset(); void toggleMute(); + void toggleAudioNoiseReduction(); virtual void handleAudioByteArray(const QByteArray& audioByteArray); @@ -106,6 +109,10 @@ private: float _measuredJitter; int16_t _jitterBufferSamples; float _lastInputLoudness; + float _averageInputLoudness; + bool _noiseGateOpen; + bool _noiseGateEnabled; + int _noiseGateFramesToClose; glm::vec3 _lastVelocity; glm::vec3 _lastAcceleration; int _totalPacketsReceived; diff --git a/interface/src/Menu.cpp b/interface/src/Menu.cpp index 6640df3468..af41e583b9 100644 --- a/interface/src/Menu.cpp +++ b/interface/src/Menu.cpp @@ -457,6 +457,11 @@ Menu::Menu() : addCheckableActionToQMenuAndActionHash(renderDebugMenu, MenuOption::CoverageMapV2, Qt::SHIFT | Qt::CTRL | Qt::Key_P); QMenu* audioDebugMenu = developerMenu->addMenu("Audio Debugging Tools"); + addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::AudioNoiseReduction, + 0, + true, + appInstance->getAudio(), + SLOT(toggleAudioNoiseReduction())); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoServerAudio); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::EchoLocalAudio); addCheckableActionToQMenuAndActionHash(audioDebugMenu, MenuOption::MuteAudio, diff --git a/interface/src/Menu.h b/interface/src/Menu.h index fcd2d74940..edc6035f60 100644 --- a/interface/src/Menu.h +++ b/interface/src/Menu.h @@ -187,6 +187,7 @@ namespace MenuOption { const QString Enable3DTVMode = "Enable 3DTV Mode"; const QString EnableOcclusionCulling = "Enable Occlusion Culling"; const QString EnableVoxelPacketCompression = "Enable Voxel Packet Compression"; + const QString AudioNoiseReduction = "Audio Noise Reduction"; const QString EchoServerAudio = "Echo Server Audio"; const QString EchoLocalAudio = "Echo Local Audio"; const QString MuteAudio = "Mute Microphone"; diff --git a/libraries/avatars/src/AvatarData.cpp b/libraries/avatars/src/AvatarData.cpp index ca57fff587..b2cd1cf076 100644 --- a/libraries/avatars/src/AvatarData.cpp +++ b/libraries/avatars/src/AvatarData.cpp @@ -107,7 +107,6 @@ QByteArray AvatarData::toByteArray() { destinationBuffer += sizeof(_headData->_lookAtPosition); // Instantaneous audio loudness (used to drive facial animation) - //destinationBuffer += packFloatToByte(destinationBuffer, std::min(MAX_AUDIO_LOUDNESS, _audioLoudness), MAX_AUDIO_LOUDNESS); memcpy(destinationBuffer, &_headData->_audioLoudness, sizeof(float)); destinationBuffer += sizeof(float); @@ -215,7 +214,6 @@ int AvatarData::parseData(const QByteArray& packet) { sourceBuffer += sizeof(_headData->_lookAtPosition); // Instantaneous audio loudness (used to drive facial animation) - //sourceBuffer += unpackFloatFromByte(sourceBuffer, _audioLoudness, MAX_AUDIO_LOUDNESS); memcpy(&_headData->_audioLoudness, sourceBuffer, sizeof(float)); sourceBuffer += sizeof(float); From 9655e934323f51c1b683eef4a49fdba3fd1d0c9f Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 8 Feb 2014 19:13:43 -0800 Subject: [PATCH 4/6] Remove re-coloring of voxels on hover or click, anticipating switch to scripted behavior --- interface/src/Application.cpp | 80 +++-------------------------------- interface/src/Application.h | 2 - 2 files changed, 5 insertions(+), 77 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 6119c83e66..ea327094c2 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -135,7 +135,6 @@ Application::Application(int& argc, char** argv, timeval &startup_time) : _isTouchPressed(false), _mousePressed(false), _isHoverVoxel(false), - _isHoverVoxelSounding(false), _mouseVoxelScale(1.0f / 1024.0f), _mouseVoxelScaleInitialized(false), _justEditedVoxel(false), @@ -1219,11 +1218,6 @@ void Application::mouseMoveEvent(QMouseEvent* event) { } } -const bool MAKE_SOUND_ON_VOXEL_HOVER = false; -const bool MAKE_SOUND_ON_VOXEL_CLICK = true; -const float HOVER_VOXEL_FREQUENCY = 7040.f; -const float HOVER_VOXEL_DECAY = 0.999f; - void Application::mousePressEvent(QMouseEvent* event) { _controllerScriptingInterface.emitMousePressEvent(event); // send events to any registered scripts @@ -1263,37 +1257,6 @@ void Application::mousePressEvent(QMouseEvent* event) { pasteVoxels(); } - if (!Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) && - MAKE_SOUND_ON_VOXEL_CLICK && _isHoverVoxel && !_isHoverVoxelSounding) { - _hoverVoxelOriginalColor[0] = _hoverVoxel.red; - _hoverVoxelOriginalColor[1] = _hoverVoxel.green; - _hoverVoxelOriginalColor[2] = _hoverVoxel.blue; - _hoverVoxelOriginalColor[3] = 1; - const float RED_CLICK_FREQUENCY = 1000.f; - const float GREEN_CLICK_FREQUENCY = 1250.f; - const float BLUE_CLICK_FREQUENCY = 1330.f; - const float MIDDLE_A_FREQUENCY = 440.f; - float frequency = MIDDLE_A_FREQUENCY + - (_hoverVoxel.red / 255.f * RED_CLICK_FREQUENCY + - _hoverVoxel.green / 255.f * GREEN_CLICK_FREQUENCY + - _hoverVoxel.blue / 255.f * BLUE_CLICK_FREQUENCY) / 3.f; - - _audio.startCollisionSound(1.0, frequency, 0.0, HOVER_VOXEL_DECAY, false); - _isHoverVoxelSounding = true; - - const float PERCENTAGE_TO_MOVE_TOWARD = 0.90f; - glm::vec3 newTarget = getMouseVoxelWorldCoordinates(_hoverVoxel); - glm::vec3 myPosition = _myAvatar->getPosition(); - - // If there is not an action tool set (add, delete, color), move to this voxel - if (Menu::getInstance()->isOptionChecked(MenuOption::ClickToFly) && - !(Menu::getInstance()->isOptionChecked(MenuOption::VoxelAddMode) || - Menu::getInstance()->isOptionChecked(MenuOption::VoxelDeleteMode) || - Menu::getInstance()->isOptionChecked(MenuOption::VoxelColorMode))) { - _myAvatar->setMoveTarget(myPosition + (newTarget - myPosition) * PERCENTAGE_TO_MOVE_TOWARD); - } - } - } else if (event->button() == Qt::RightButton && Menu::getInstance()->isVoxelModeActionChecked()) { deleteVoxelUnderCursor(); } @@ -2039,44 +2002,11 @@ void Application::updateHoverVoxels(float deltaTime, float& distance, BoxFace& f bool showWarnings = Menu::getInstance()->isOptionChecked(MenuOption::PipelineWarnings); PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels()"); - // If we have clicked on a voxel, update it's color - if (_isHoverVoxelSounding) { - VoxelTreeElement* hoveredNode = _voxels.getVoxelAt(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s); - if (hoveredNode) { - float bright = _audio.getCollisionSoundMagnitude(); - nodeColor clickColor = { 255 * bright + _hoverVoxelOriginalColor[0] * (1.f - bright), - _hoverVoxelOriginalColor[1] * (1.f - bright), - _hoverVoxelOriginalColor[2] * (1.f - bright), 1 }; - hoveredNode->setColor(clickColor); - if (bright < 0.01f) { - hoveredNode->setColor(_hoverVoxelOriginalColor); - _isHoverVoxelSounding = false; - } - } else { - // Voxel is not found, clear all - _isHoverVoxelSounding = false; - _isHoverVoxel = false; - } - } else { - // Check for a new hover voxel - glm::vec4 oldVoxel(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s); - // only do this work if MAKE_SOUND_ON_VOXEL_HOVER or MAKE_SOUND_ON_VOXEL_CLICK is enabled, - // and make sure the tree is not already busy... because otherwise you'll have to wait. - if (!_mousePressed) { - { - PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()"); - _isHoverVoxel = _voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _hoverVoxel, distance, face); - } - if (MAKE_SOUND_ON_VOXEL_HOVER && _isHoverVoxel && - glm::vec4(_hoverVoxel.x, _hoverVoxel.y, _hoverVoxel.z, _hoverVoxel.s) != oldVoxel) { - - _hoverVoxelOriginalColor[0] = _hoverVoxel.red; - _hoverVoxelOriginalColor[1] = _hoverVoxel.green; - _hoverVoxelOriginalColor[2] = _hoverVoxel.blue; - _hoverVoxelOriginalColor[3] = 1; - _audio.startCollisionSound(1.0, HOVER_VOXEL_FREQUENCY * _hoverVoxel.s * TREE_SCALE, 0.0, HOVER_VOXEL_DECAY, false); - _isHoverVoxelSounding = true; - } + // Check for a new hover voxel + if (!_mousePressed) { + { + PerformanceWarning warn(showWarnings, "Application::updateHoverVoxels() _voxels.findRayIntersection()"); + _isHoverVoxel = _voxels.findRayIntersection(_mouseRayOrigin, _mouseRayDirection, _hoverVoxel, distance, face); } } } diff --git a/interface/src/Application.h b/interface/src/Application.h index 94b5601797..2a8ba2d1bf 100644 --- a/interface/src/Application.h +++ b/interface/src/Application.h @@ -419,8 +419,6 @@ private: VoxelDetail _hoverVoxel; // Stuff about the voxel I am hovering or clicking bool _isHoverVoxel; - bool _isHoverVoxelSounding; - nodeColor _hoverVoxelOriginalColor; VoxelDetail _mouseVoxel; // details of the voxel to be edited float _mouseVoxelScale; // the scale for adding/removing voxels From 6b0c31e6e9b6c44eb1dfddc6095c88db8bce5bd5 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 8 Feb 2014 20:47:02 -0800 Subject: [PATCH 5/6] Script for editing voxels with mouse clicks --- examples/editVoxels.js | 104 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) create mode 100644 examples/editVoxels.js diff --git a/examples/editVoxels.js b/examples/editVoxels.js new file mode 100644 index 0000000000..b43edb3af9 --- /dev/null +++ b/examples/editVoxels.js @@ -0,0 +1,104 @@ +// +// editVoxels.js +// hifi +// +// Created by Philip Rosedale on February 8, 2014 +// Copyright (c) 2014 HighFidelity, Inc. All rights reserved. +// +// Captures mouse clicks and edits voxels accordingly. +// +// click = create a new voxel on this face, same color as old +// Alt + click = delete this voxel +// shift + click = recolor this voxel +// + +var key_alt = false; +var key_shift = false; + +// Create a table of the different colors you can choose +var colors = new Array(); +colors[0] = { red: 255, green: 0, blue: 0 }; +colors[1] = { red: 0, green: 255, blue: 0 }; +colors[2] = { red: 0, green: 0, blue: 255 }; +colors[3] = { red: 255, green: 255, blue: 0 }; +colors[4] = { red: 0, green: 255, blue: 255 }; +colors[5] = { red: 255, green: 0, blue: 255 }; +var numColors = 6; +var whichColor = 0; + +// Create sounds for adding, deleting, recoloring voxels +var addSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Electronic/ElectronicBurst1.raw"); +var deleteSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Bubbles/bubbles1.raw"); +var changeColorSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelity-public/sounds/Electronic/ElectronicBurst6.raw"); +var audioOptions = new AudioInjectionOptions();
 + +function mousePressEvent(event) { + print("mousePressEvent event.x,y=" + event.x + ", " + event.y); + var pickRay = Camera.computePickRay(event.x, event.y); + var intersection = Voxels.findRayIntersection(pickRay); + audioOptions.volume = 1.0; + audioOptions.position = { x: intersection.voxel.x, y: intersection.voxel.y, z: intersection.voxel.z }; + + if (intersection.intersects) { + if (key_alt) { + // Delete voxel + Voxels.eraseVoxel(intersection.voxel.x, intersection.voxel.y, intersection.voxel.z, intersection.voxel.s); + Audio.playSound(deleteSound, audioOptions); + + } else if (key_shift) { + // Recolor Voxel + whichColor++; + if (whichColor == numColors) whichColor = 0; + Voxels.setVoxel(intersection.voxel.x, + intersection.voxel.y, + intersection.voxel.z, + intersection.voxel.s, + colors[whichColor].red, colors[whichColor].green, colors[whichColor].blue); + Audio.playSound(changeColorSound, audioOptions); + } else { + // Add voxel on face + var newVoxel = { + x: intersection.voxel.x, + y: intersection.voxel.y, + z: intersection.voxel.z, + s: intersection.voxel.s, + red: intersection.voxel.red, + green: intersection.voxel.green, + blue: intersection.voxel.blue }; + + if (intersection.face == "MIN_X_FACE") { + newVoxel.x -= newVoxel.s; + } else if (intersection.face == "MAX_X_FACE") { + newVoxel.x += newVoxel.s; + } else if (intersection.face == "MIN_Y_FACE") { + newVoxel.y -= newVoxel.s; + } else if (intersection.face == "MAX_Y_FACE") { + newVoxel.y += newVoxel.s; + } else if (intersection.face == "MIN_Z_FACE") { + newVoxel.z -= newVoxel.s; + } else if (intersection.face == "MAX_Z_FACE") { + newVoxel.z += newVoxel.s; + } + + Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); + Audio.playSound(addSound, audioOptions); + } + } +} + +function keyPressEvent(event) { + key_alt = event.isAlt; + key_shift = event.isShifted; +} +function keyReleaseEvent(event) { + key_alt = false; + key_shift = false; +} + +Controller.mousePressEvent.connect(mousePressEvent); +Controller.keyPressEvent.connect(keyPressEvent); +Controller.keyReleaseEvent.connect(keyReleaseEvent); + +function scriptEnding() { +} +Script.scriptEnding.connect(scriptEnding); From cfa7f5e6ca38afa557e1106a855ffe621caca6a3 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 8 Feb 2014 23:17:04 -0800 Subject: [PATCH 6/6] Add drag to add more voxels, turn off hover orbit voxels until in the script as function key --- examples/editVoxels.js | 80 ++++++++++++++++++++++++++++++++--- interface/src/Application.cpp | 2 +- 2 files changed, 74 insertions(+), 8 deletions(-) diff --git a/examples/editVoxels.js b/examples/editVoxels.js index b43edb3af9..96bb09e6d6 100644 --- a/examples/editVoxels.js +++ b/examples/editVoxels.js @@ -11,18 +11,32 @@ // Alt + click = delete this voxel // shift + click = recolor this voxel // +// Click and drag to create more new voxels in the same direction +// + +function vLength(v) { + return Math.sqrt(v.x * v.x + v.y * v.y + v.z * v.z); +} var key_alt = false; var key_shift = false; +var isAdding = false; + +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 }; // Create a table of the different colors you can choose var colors = new Array(); -colors[0] = { red: 255, green: 0, blue: 0 }; -colors[1] = { red: 0, green: 255, blue: 0 }; -colors[2] = { red: 0, green: 0, blue: 255 }; -colors[3] = { red: 255, green: 255, blue: 0 }; -colors[4] = { red: 0, green: 255, blue: 255 }; -colors[5] = { red: 255, green: 0, blue: 255 }; +colors[0] = { red: 237, green: 175, blue: 0 }; +colors[1] = { red: 61, green: 211, blue: 72 }; +colors[2] = { red: 51, green: 204, blue: 204 }; +colors[3] = { red: 63, green: 169, blue: 245 }; +colors[4] = { red: 193, green: 99, blue: 122 }; +colors[5] = { red: 255, green: 54, blue: 69 }; +colors[6] = { red: 124, green: 36, blue: 36 }; +colors[7] = { red: 63, green: 35, blue: 19 }; var numColors = 6; var whichColor = 0; @@ -33,7 +47,6 @@ var changeColorSound = new Sound("https://s3-us-west-1.amazonaws.com/highfidelit var audioOptions = new AudioInjectionOptions();
 function mousePressEvent(event) { - print("mousePressEvent event.x,y=" + event.x + ", " + event.y); var pickRay = Camera.computePickRay(event.x, event.y); var intersection = Voxels.findRayIntersection(pickRay); audioOptions.volume = 1.0; @@ -81,7 +94,13 @@ function mousePressEvent(event) { } Voxels.setVoxel(newVoxel.x, newVoxel.y, newVoxel.z, newVoxel.s, newVoxel.red, newVoxel.green, newVoxel.blue); + lastVoxelPosition = { x: newVoxel.x, y: newVoxel.y, z: newVoxel.z }; + lastVoxelColor = { red: newVoxel.red, green: newVoxel.green, blue: newVoxel.blue }; + lastVoxelScale = newVoxel.s; + Audio.playSound(addSound, audioOptions); + dragStart = { x: event.x, y: event.y }; + isAdding = true; } } } @@ -94,8 +113,55 @@ function keyReleaseEvent(event) { key_alt = false; key_shift = false; } +function mouseMoveEvent(event) { + if (isAdding) { + var pickRay = Camera.computePickRay(event.x, event.y); + var lastVoxelDistance = { x: pickRay.origin.x - lastVoxelPosition.x, + y: pickRay.origin.y - lastVoxelPosition.y, + z: pickRay.origin.z - lastVoxelPosition.z }; + var distance = vLength(lastVoxelDistance); + var mouseSpot = { x: pickRay.direction.x * distance, y: pickRay.direction.y * distance, z: pickRay.direction.z * distance }; + mouseSpot.x += pickRay.origin.x; + mouseSpot.y += pickRay.origin.y; + mouseSpot.z += pickRay.origin.z; + var dx = mouseSpot.x - lastVoxelPosition.x; + var dy = mouseSpot.y - lastVoxelPosition.y; + var dz = mouseSpot.z - lastVoxelPosition.z; + if (dx > lastVoxelScale) { + lastVoxelPosition.x += lastVoxelScale; + Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, + lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); + } else if (dx < -lastVoxelScale) { + lastVoxelPosition.x -= lastVoxelScale; + Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, + lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); + } else if (dy > lastVoxelScale) { + lastVoxelPosition.y += lastVoxelScale; + Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, + lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); + } else if (dy < -lastVoxelScale) { + lastVoxelPosition.y -= lastVoxelScale; + Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, + lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); + } else if (dz > lastVoxelScale) { + lastVoxelPosition.z += lastVoxelScale; + Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, + lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); + } else if (dz < -lastVoxelScale) { + lastVoxelPosition.z -= lastVoxelScale; + Voxels.setVoxel(lastVoxelPosition.x, lastVoxelPosition.y, lastVoxelPosition.z, + lastVoxelScale, lastVoxelColor.red, lastVoxelColor.green, lastVoxelColor.blue); + } + } +} + +function mouseReleaseEvent(event) { + isAdding = false; +} Controller.mousePressEvent.connect(mousePressEvent); +Controller.mouseReleaseEvent.connect(mouseReleaseEvent); +Controller.mouseMoveEvent.connect(mouseMoveEvent); Controller.keyPressEvent.connect(keyPressEvent); Controller.keyReleaseEvent.connect(keyReleaseEvent); diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index ea327094c2..650372b795 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1198,7 +1198,7 @@ void Application::mouseMoveEvent(QMouseEvent* event) { return; } if (_isHoverVoxel) { - _myAvatar->orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY); + //_myAvatar->orbit(getMouseVoxelWorldCoordinates(_hoverVoxel), deltaX, deltaY); return; } }