From bad47bd527b99b89e54f8a3358d2c3bc6a892c62 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 20 Dec 2013 15:33:56 -0800 Subject: [PATCH 01/14] Fixed chat height --- interface/src/avatar/Avatar.cpp | 8 ++++---- interface/src/avatar/Avatar.h | 4 ++-- interface/src/avatar/Hand.cpp | 2 +- interface/src/avatar/MyAvatar.cpp | 4 ++-- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index 7762f5afbc..ec0c19cb7a 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -59,8 +59,8 @@ const float HEAD_RATE_MAX = 50.f; const float SKIN_COLOR[] = {1.0, 0.84, 0.66}; const float DARK_SKIN_COLOR[] = {0.9, 0.78, 0.63}; const int NUM_BODY_CONE_SIDES = 9; -const float chatMessageScale = 0.0015; -const float chatMessageHeight = 0.4f; +const float CHAT_MESSAGE_SCALE = 0.0015; +const float CHAT_MESSAGE_HEIGHT = 0.1f; void Avatar::sendAvatarURLsMessage(const QUrl& voxelURL) { QByteArray message; @@ -303,7 +303,7 @@ void Avatar::render(bool forceRenderHead) { } glPushMatrix(); - glm::vec3 chatPosition = getPosition() + getBodyUpDirection() * chatMessageHeight * _scale; + glm::vec3 chatPosition = getHead().getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale; glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z); glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation(); glm::vec3 chatAxis = glm::axis(chatRotation); @@ -313,7 +313,7 @@ void Avatar::render(bool forceRenderHead) { glColor3f(0, 0.8, 0); glRotatef(180, 0, 1, 0); glRotatef(180, 0, 0, 1); - glScalef(_scale * chatMessageScale, _scale * chatMessageScale, 1.0f); + glScalef(_scale * CHAT_MESSAGE_SCALE, _scale * CHAT_MESSAGE_SCALE, 1.0f); glDisable(GL_LIGHTING); glDepthMask(false); diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index c435191a18..c23e30f60b 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -58,8 +58,8 @@ const float BODY_BALL_RADIUS_RIGHT_TOES = 0.025; extern const bool usingBigSphereCollisionTest; -extern const float chatMessageScale; -extern const float chatMessageHeight; +extern const float CHAT_MESSAGE_SCALE; +extern const float CHAT_MESSAGE_HEIGHT; enum AvatarBodyBallID { BODY_BALL_NULL = -1, diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 136d59bc37..50bbe541f2 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -208,7 +208,7 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f TOY_BALL_UPDATE_SCRIPT); // after releasing the ball, we free our ParticleEditHandle so we can't edit it further - // note: deleting the edit handle doesn't effect the actual particle + // note: deleting the edit handle doesn't effect the act ual particle delete _ballParticleEditHandles[handID]; _ballParticleEditHandles[handID] = NULL; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index c668eb5956..6c2bc78090 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -474,7 +474,7 @@ void MyAvatar::render(bool forceRenderHead) { } glPushMatrix(); - glm::vec3 chatPosition = getPosition() + getBodyUpDirection() * chatMessageHeight * _scale; + glm::vec3 chatPosition = getHead().getEyePosition() + getBodyUpDirection() * CHAT_MESSAGE_HEIGHT * _scale; glTranslatef(chatPosition.x, chatPosition.y, chatPosition.z); glm::quat chatRotation = Application::getInstance()->getCamera()->getRotation(); glm::vec3 chatAxis = glm::axis(chatRotation); @@ -484,7 +484,7 @@ void MyAvatar::render(bool forceRenderHead) { glColor3f(0, 0.8, 0); glRotatef(180, 0, 1, 0); glRotatef(180, 0, 0, 1); - glScalef(_scale * chatMessageScale, _scale * chatMessageScale, 1.0f); + glScalef(_scale * CHAT_MESSAGE_SCALE, _scale * CHAT_MESSAGE_SCALE, 1.0f); glDisable(GL_LIGHTING); glDepthMask(false); From 03d192574d09ec803a30009a0a2446b8f2981f92 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Fri, 20 Dec 2013 22:57:35 -0800 Subject: [PATCH 02/14] typo --- interface/src/avatar/Hand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 50bbe541f2..136d59bc37 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -208,7 +208,7 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f TOY_BALL_UPDATE_SCRIPT); // after releasing the ball, we free our ParticleEditHandle so we can't edit it further - // note: deleting the edit handle doesn't effect the act ual particle + // note: deleting the edit handle doesn't effect the actual particle delete _ballParticleEditHandles[handID]; _ballParticleEditHandles[handID] = NULL; From 58a73dfede6cec91d23ff1398773d3f3108f8d40 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 21 Dec 2013 18:06:04 -0800 Subject: [PATCH 03/14] yet again remove the test _balls now that we have a particle server --- interface/src/Balls.cpp | 147 ------------------------------ interface/src/Balls.h | 37 -------- interface/src/avatar/Avatar.cpp | 26 +----- interface/src/avatar/Avatar.h | 1 - interface/src/avatar/MyAvatar.cpp | 20 ---- 5 files changed, 1 insertion(+), 230 deletions(-) delete mode 100644 interface/src/Balls.cpp delete mode 100644 interface/src/Balls.h diff --git a/interface/src/Balls.cpp b/interface/src/Balls.cpp deleted file mode 100644 index 693b38462b..0000000000 --- a/interface/src/Balls.cpp +++ /dev/null @@ -1,147 +0,0 @@ -// -// Balls.cpp -// hifi -// -// Created by Philip on 4/25/13. -// -// A cloud of spring-mass spheres to simulate the avatar body/skin. Each ball -// connects to as many as 4 neighbors, and executes motion according to a damped -// spring, while responding physically to other avatars. -// - -#include - -#include - -#include "Balls.h" -#include "InterfaceConfig.h" -#include "Util.h" -#include "world.h" - -const float INITIAL_AREA = 0.2f; -const float BALL_RADIUS = 0.016f; -const glm::vec3 INITIAL_COLOR(0.62f, 0.74f, 0.91f); - -Balls::Balls(int numberOfBalls) { - _numberOfBalls = numberOfBalls; - _balls = new Ball[_numberOfBalls]; - for (unsigned int i = 0; i < _numberOfBalls; ++i) { - _balls[i].position = randVector() * INITIAL_AREA; - _balls[i].targetPosition = _balls[i].position; - _balls[i].velocity = glm::vec3(0, 0, 0); - _balls[i].radius = BALL_RADIUS; - for (unsigned int j = 0; j < NUMBER_SPRINGS; ++j) { - _balls[i].links[j] = 0; - } - } - _color = INITIAL_COLOR; - _origin = glm::vec3(0, 0, 0); -} - -Balls::~Balls() { - delete[] _balls; -} - -void Balls::moveOrigin(const glm::vec3& newOrigin) { - glm::vec3 delta = newOrigin - _origin; - if (glm::length(delta) > EPSILON) { - _origin = newOrigin; - for (unsigned int i = 0; i < _numberOfBalls; ++i) { - _balls[i].targetPosition += delta; - } - } -} - -const bool RENDER_SPRINGS = false; - -void Balls::render() { - - // Render Balls NOTE: This needs to become something other that GlutSpheres! - glColor3fv(&_color.x); - for (unsigned int i = 0; i < _numberOfBalls; ++i) { - glPushMatrix(); - glTranslatef(_balls[i].position.x, _balls[i].position.y, _balls[i].position.z); - glutSolidSphere(_balls[i].radius, 8, 8); - glPopMatrix(); - } - - // Render springs - if (RENDER_SPRINGS) { - glColor3f(0.74, 0.91, 0.62); - for (unsigned int i = 0; i < _numberOfBalls; ++i) { - glBegin(GL_LINES); - for (unsigned int j = 0; j < NUMBER_SPRINGS; ++j) { - if(_balls[i].links[j] > 0) { - glVertex3f(_balls[i].position.x, - _balls[i].position.y, - _balls[i].position.z); - glVertex3f(_balls[_balls[i].links[j]-1].position.x, - _balls[_balls[i].links[j]-1].position.y, - _balls[_balls[i].links[j]-1].position.z); - } - } - glEnd(); - } - } - -} - -const float CONSTANT_VELOCITY_DAMPING = 1.0f; -const float NOISE_SCALE = 0.06; -const float SPRING_FORCE = 30.0; -const float ORIGIN_DISTANCE = 0.1; -const float SPRING_DAMPING = 1.0; - -void Balls::simulate(float deltaTime) { - for (unsigned int i = 0; i < _numberOfBalls; ++i) { - - // Move particles - _balls[i].position += _balls[i].velocity * deltaTime; - _balls[i].targetPosition += _balls[i].velocity * deltaTime; - - // Drag: decay velocity - _balls[i].velocity *= (1.f - CONSTANT_VELOCITY_DAMPING * deltaTime); - - // Add noise - _balls[i].velocity += randVector() * NOISE_SCALE; - - // spring force to origin - float separation = glm::distance(_balls[i].position, - _origin); - - _balls[i].velocity += - glm::normalize(_balls[i].position - _origin) - * deltaTime - * - SPRING_FORCE * - (ORIGIN_DISTANCE - separation); - - // Approach target position -// for (unsigned int i = 0; i < _numberOfBalls; ++i) { -// _balls[i].position += randFloat() * deltaTime * (_balls[i].targetPosition - _balls[i].position); -// } - - // Spring Force - - /* - for (unsigned int j = 0; j < NUMBER_SPRINGS; ++j) { - if(_balls[i].links[j] > 0) { - float separation = glm::distance(_balls[i].position, - _balls[_balls[i].links[j]-1].position); - _balls[i].velocity += glm::normalize(_balls[i].position - - _balls[_balls[i].links[j]-1].position) * - deltaTime * - SPRING_FORCE * - (_balls[i].springLength[j] - separation); - - //_balls[i].velocity *= (1.f - SPRING_DAMPING*deltaTime); - - } - } */ - - - - - } -} - diff --git a/interface/src/Balls.h b/interface/src/Balls.h deleted file mode 100644 index eefa71828a..0000000000 --- a/interface/src/Balls.h +++ /dev/null @@ -1,37 +0,0 @@ -// -// Balls.h -// hifi -// -// Created by Philip on 4/25/13. -// -// - -#ifndef hifi_Balls_h -#define hifi_Balls_h - -const int NUMBER_SPRINGS = 4; - -class Balls { -public: - Balls(int numberOfBalls); - ~Balls(); - - void simulate(float deltaTime); - void render(); - - void setColor(const glm::vec3& c) { _color = c; }; - void moveOrigin(const glm::vec3& newOrigin); - -private: - struct Ball { - glm::vec3 position, targetPosition, velocity; - int links[NUMBER_SPRINGS]; - float springLength[NUMBER_SPRINGS]; - float radius; - } *_balls; - int _numberOfBalls; - glm::vec3 _origin; - glm::vec3 _color; -}; - -#endif diff --git a/interface/src/avatar/Avatar.cpp b/interface/src/avatar/Avatar.cpp index ec0c19cb7a..5a9a689775 100755 --- a/interface/src/avatar/Avatar.cpp +++ b/interface/src/avatar/Avatar.cpp @@ -118,18 +118,12 @@ Avatar::Avatar(Node* owningNode) : _pelvisFloatingHeight = _skeleton.getPelvisFloatingHeight(); _pelvisToHeadLength = _skeleton.getPelvisToHeadLength(); - if (BALLS_ON) { - _balls = new Balls(100); - } else { - _balls = NULL; - } } Avatar::~Avatar() { _headData = NULL; _handData = NULL; - delete _balls; } void Avatar::deleteOrDeleteLater() { @@ -180,18 +174,6 @@ void Avatar::simulate(float deltaTime, Transmitter* transmitter) { // copy velocity so we can use it later for acceleration glm::vec3 oldVelocity = getVelocity(); - // update balls - if (_balls) { - _balls->moveOrigin(_position); - glm::vec3 lookAt = _head.getLookAtPosition(); - if (glm::length(lookAt) > EPSILON) { - _balls->moveOrigin(lookAt); - } else { - _balls->moveOrigin(_position); - } - _balls->simulate(deltaTime); - } - // update torso rotation based on head lean _skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::radians(glm::vec3( _head.getLeanForward(), 0.0f, _head.getLeanSideways()))); @@ -288,13 +270,7 @@ void Avatar::render(bool forceRenderHead) { } } - // Render the balls - if (_balls) { - glPushMatrix(); - _balls->render(); - glPopMatrix(); - } - + if (!_chatMessage.empty()) { int width = 0; int lastWidth = 0; diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index c23e30f60b..af40cb121f 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -214,7 +214,6 @@ protected: float _pelvisToHeadLength; float _scale; float _height; - Balls* _balls; glm::vec3 _worldUpDirection; glm::vec3 _mouseRayOrigin; glm::vec3 _mouseRayDirection; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 6c2bc78090..28529cd00b 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -111,18 +111,6 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { // calculate speed _speed = glm::length(_velocity); - // update balls - if (_balls) { - _balls->moveOrigin(_position); - glm::vec3 lookAt = _head.getLookAtPosition(); - if (glm::length(lookAt) > EPSILON) { - _balls->moveOrigin(lookAt); - } else { - _balls->moveOrigin(_position); - } - _balls->simulate(deltaTime); - } - // update torso rotation based on head lean _skeleton.joint[AVATAR_JOINT_TORSO].rotation = glm::quat(glm::radians(glm::vec3( _head.getLeanForward(), 0.0f, _head.getLeanSideways()))); @@ -455,17 +443,9 @@ void MyAvatar::render(bool forceRenderHead) { // render body renderBody(forceRenderHead); - - // Render the balls - if (_balls) { - glPushMatrix(); - _balls->render(); - glPopMatrix(); - } //renderDebugBodyPoints(); - if (!_chatMessage.empty()) { int width = 0; int lastWidth = 0; From 9b3973c2e476ee7f737cf3b805406f07cd2837ce Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Sat, 21 Dec 2013 18:07:40 -0800 Subject: [PATCH 04/14] removed headers --- interface/src/avatar/Avatar.h | 1 - interface/src/avatar/Hand.h | 1 - 2 files changed, 2 deletions(-) diff --git a/interface/src/avatar/Avatar.h b/interface/src/avatar/Avatar.h index af40cb121f..b0448563cf 100755 --- a/interface/src/avatar/Avatar.h +++ b/interface/src/avatar/Avatar.h @@ -15,7 +15,6 @@ #include -#include "Balls.h" #include "Hand.h" #include "Head.h" #include "InterfaceConfig.h" diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 884d710381..428132ba13 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -21,7 +21,6 @@ #include #include -#include "Balls.h" #include "InterfaceConfig.h" #include "ParticleSystem.h" #include "world.h" From 74380260b3c65d8de3f4ca19278045e6fb92174d Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 26 Dec 2013 19:07:02 -0800 Subject: [PATCH 05/14] Grab includes rotation --- interface/src/avatar/Hand.cpp | 15 ++++++++++++++- interface/src/avatar/Hand.h | 3 +++ interface/src/avatar/MyAvatar.cpp | 10 ++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 136d59bc37..20f034989b 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -52,6 +52,8 @@ Hand::Hand(Avatar* owningAvatar) : _pitchUpdate(0), _grabDelta(0, 0, 0), _grabDeltaVelocity(0, 0, 0), + _grabStartRotation(0, 0, 0, 1), + _grabCurrentRotation(0, 0, 0, 1), _throwInjector(QUrl("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/throw.raw")), _catchInjector(QUrl("https://dl.dropboxusercontent.com/u/1864924/hifi-sounds/catch.raw")) { @@ -227,7 +229,7 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f } glm::vec3 Hand::getAndResetGrabDelta() { - const float HAND_GRAB_SCALE_DISTANCE = 5.f; + const float HAND_GRAB_SCALE_DISTANCE = 2.f; glm::vec3 delta = _grabDelta * _owningAvatar->getScale() * HAND_GRAB_SCALE_DISTANCE; _grabDelta = glm::vec3(0,0,0); glm::quat avatarRotation = _owningAvatar->getOrientation(); @@ -242,6 +244,11 @@ glm::vec3 Hand::getAndResetGrabDeltaVelocity() { return avatarRotation * -delta; } +glm::quat Hand::getAndResetGrabRotation() { + glm::quat diff = _grabCurrentRotation * glm::inverse(_grabStartRotation); + _grabStartRotation = _grabCurrentRotation; + return diff; +} void Hand::simulate(float deltaTime, bool isMine) { @@ -275,10 +282,16 @@ void Hand::simulate(float deltaTime, bool isMine) { if (palm.getControllerButtons() & BUTTON_4) { _grabDelta += palm.getRawVelocity() * deltaTime; + _grabCurrentRotation = palm.getRawRotation(); } if ((palm.getLastControllerButtons() & BUTTON_4) && !(palm.getControllerButtons() & BUTTON_4)) { + // Just ending grab, capture velocity _grabDeltaVelocity = palm.getRawVelocity(); } + if (!(palm.getLastControllerButtons() & BUTTON_4) && (palm.getControllerButtons() & BUTTON_4)) { + // Just starting grab, capture starting rotation + _grabStartRotation = palm.getRawRotation(); + } if (palm.getControllerButtons() & BUTTON_1) { if (glm::length(fingerTipPosition - _lastFingerAddVoxel) > (FINGERTIP_VOXEL_SIZE / 2.f)) { diff --git a/interface/src/avatar/Hand.h b/interface/src/avatar/Hand.h index 428132ba13..e938135a29 100755 --- a/interface/src/avatar/Hand.h +++ b/interface/src/avatar/Hand.h @@ -64,6 +64,7 @@ public: // Get the drag distance to move glm::vec3 getAndResetGrabDelta(); glm::vec3 getAndResetGrabDeltaVelocity(); + glm::quat getAndResetGrabRotation(); private: // disallow copies of the Hand, copy of owning Avatar is disallowed too @@ -110,6 +111,8 @@ private: glm::vec3 _grabDelta; glm::vec3 _grabDeltaVelocity; + glm::quat _grabStartRotation; + glm::quat _grabCurrentRotation; AudioInjector _throwInjector; AudioInjector _catchInjector; diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 28529cd00b..42337f304e 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -258,14 +258,20 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } updateChatCircle(deltaTime); - - // Get any position or velocity update from Grab controller + + // Get any position, velocity, or rotation update from Grab Drag controller glm::vec3 moveFromGrab = _hand.getAndResetGrabDelta(); if (glm::length(moveFromGrab) > EPSILON) { _position += moveFromGrab; _velocity = glm::vec3(0, 0, 0); } _velocity += _hand.getAndResetGrabDeltaVelocity(); + glm::quat deltaRotation = _hand.getAndResetGrabRotation(); + glm::vec3 euler = safeEulerAngles(deltaRotation); + // Adjust body yaw by yaw from controller + setOrientation(glm::angleAxis(euler.y, glm::vec3(0, 1, 0)) * getOrientation()); + // Adjust head pitch from controller + getHead().setMousePitch(getHead().getMousePitch() + euler.x); _position += _velocity * deltaTime; From e3a77ef139135d70e7de4e20b24925a4d7709695 Mon Sep 17 00:00:00 2001 From: Philip Rosedale Date: Thu, 26 Dec 2013 20:20:57 -0800 Subject: [PATCH 06/14] tuning --- interface/src/avatar/MyAvatar.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/interface/src/avatar/MyAvatar.cpp b/interface/src/avatar/MyAvatar.cpp index 42337f304e..0efa8b09cf 100644 --- a/interface/src/avatar/MyAvatar.cpp +++ b/interface/src/avatar/MyAvatar.cpp @@ -267,11 +267,12 @@ void MyAvatar::simulate(float deltaTime, Transmitter* transmitter) { } _velocity += _hand.getAndResetGrabDeltaVelocity(); glm::quat deltaRotation = _hand.getAndResetGrabRotation(); - glm::vec3 euler = safeEulerAngles(deltaRotation); + const float GRAB_CONTROLLER_TURN_SCALING = 0.5f; + glm::vec3 euler = safeEulerAngles(deltaRotation) * GRAB_CONTROLLER_TURN_SCALING; // Adjust body yaw by yaw from controller - setOrientation(glm::angleAxis(euler.y, glm::vec3(0, 1, 0)) * getOrientation()); + setOrientation(glm::angleAxis(-euler.y, glm::vec3(0, 1, 0)) * getOrientation()); // Adjust head pitch from controller - getHead().setMousePitch(getHead().getMousePitch() + euler.x); + getHead().setMousePitch(getHead().getMousePitch() - euler.x); _position += _velocity * deltaTime; From f4b28041fa6c5906923999029fb8131a40eedf20 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 30 Dec 2013 14:59:00 -0800 Subject: [PATCH 07/14] first cut at running scripts on particle collisions --- libraries/particles/src/Particle.cpp | 56 ++++++++++++++----- libraries/particles/src/Particle.h | 19 +++++-- .../particles/src/ParticleCollisionSystem.cpp | 5 ++ 3 files changed, 61 insertions(+), 19 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index f2ee1c1fb4..9f5af61042 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -53,8 +53,9 @@ void Particle::init(glm::vec3 position, float radius, rgbColor color, glm::vec3 _velocity = velocity; _damping = damping; _gravity = gravity; - _updateScript = updateScript; + _script = updateScript; _inHand = inHand; + _shouldDie = false; } @@ -95,10 +96,10 @@ bool Particle::appendParticleData(OctreePacketData* packetData) const { success = packetData->appendValue(getInHand()); } if (success) { - uint16_t scriptLength = _updateScript.size() + 1; // include NULL + uint16_t scriptLength = _script.size() + 1; // include NULL success = packetData->appendValue(scriptLength); if (success) { - success = packetData->appendRawData((const unsigned char*)qPrintable(_updateScript), scriptLength); + success = packetData->appendRawData((const unsigned char*)qPrintable(_script), scriptLength); } } return success; @@ -206,7 +207,7 @@ int Particle::readParticleDataFromBuffer(const unsigned char* data, int bytesLef dataAt += sizeof(scriptLength); bytesRead += sizeof(scriptLength); QString tempString((const char*)dataAt); - _updateScript = tempString; + _script = tempString; dataAt += scriptLength; bytesRead += scriptLength; @@ -299,7 +300,7 @@ Particle Particle::fromEditPacket(unsigned char* data, int length, int& processe dataAt += sizeof(scriptLength); processedBytes += sizeof(scriptLength); QString tempString((const char*)dataAt); - newParticle._updateScript = tempString; + newParticle._script = tempString; dataAt += scriptLength; processedBytes += scriptLength; @@ -472,7 +473,7 @@ void Particle::update() { const float REALLY_OLD = 30.0f; // 30 seconds bool isReallyOld = (getLifetime() > REALLY_OLD); bool isInHand = getInHand(); - bool shouldDie = !isInHand && !isStillMoving && isReallyOld; + bool shouldDie = getShouldDie() || (!isInHand && !isStillMoving && isReallyOld); setShouldDie(shouldDie); const bool wantDebug = false; @@ -483,7 +484,7 @@ void Particle::update() { debug::valueOf(isReallyOld), debug::valueOf(shouldDie)); } - runScript(); // allow the javascript to alter our state + runUpdateScript(); // allow the javascript to alter our state // If the ball is in hand, it doesn't move or have gravity effect it if (!isInHand) { @@ -507,11 +508,9 @@ void Particle::update() { _lastUpdated = now; } -void Particle::runScript() { - if (!_updateScript.isEmpty()) { - - //qDebug() << "Script: " << _updateScript << "\n"; - +void Particle::runUpdateScript() { + if (!_script.isEmpty()) { + QScriptEngine engine; // register meta-type for glm::vec3 and rgbColor conversions @@ -524,9 +523,9 @@ void Particle::runScript() { QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); - //qDebug() << "Downloaded script:" << _updateScript << "\n"; - QScriptValue result = engine.evaluate(_updateScript); - //qDebug() << "Evaluated script.\n"; + QScriptValue result = engine.evaluate(_script); + + particleScriptable.emitUpdate(); if (engine.hasUncaughtException()) { int line = engine.uncaughtExceptionLineNumber(); @@ -535,6 +534,33 @@ void Particle::runScript() { } } +void Particle::collisionWithParticle(unsigned int otherID) { + if (!_script.isEmpty()) { + + QScriptEngine engine; + + // register meta-type for glm::vec3 and rgbColor conversions + registerMetaTypes(&engine); + + ParticleScriptObject particleScriptable(this); + QScriptValue particleValue = engine.newQObject(&particleScriptable); + engine.globalObject().setProperty("Particle", particleValue); + + QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); + engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); + + QScriptValue result = engine.evaluate(_script); + + particleScriptable.emitCollisionWithParticle(otherID); + + if (engine.hasUncaughtException()) { + int line = engine.uncaughtExceptionLineNumber(); + qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n"; + } + } +} + + void Particle::setLifetime(float lifetime) { uint64_t lifetimeInUsecs = lifetime * USECS_PER_SECOND; _created = usecTimestampNow() - lifetimeInUsecs; diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 0d50413b4f..51d7cd4a30 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -79,7 +79,7 @@ public: float getEditedAgo() const { return (float)(usecTimestampNow() - _lastEdited) / (float)USECS_PER_SECOND; } uint32_t getID() const { return _id; } bool getShouldDie() const { return _shouldDie; } - QString getUpdateScript() const { return _updateScript; } + QString getUpdateScript() const { return _script; } uint32_t getCreatorTokenID() const { return _creatorTokenID; } bool isNewlyCreated() const { return _newlyCreated; } @@ -96,7 +96,7 @@ public: void setInHand(bool inHand) { _inHand = inHand; } void setDamping(float value) { _damping = value; } void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; } - void setUpdateScript(QString updateScript) { _updateScript = updateScript; } + void setUpdateScript(QString updateScript) { _script = updateScript; } void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; } bool appendParticleData(OctreePacketData* packetData) const; @@ -110,6 +110,7 @@ public: static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew); void update(); + void collisionWithParticle(unsigned int otherID); void debugDump() const; @@ -117,7 +118,7 @@ public: void copyChangedProperties(const Particle& other); protected: - void runScript(); + void runUpdateScript(); static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3); static void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3); static QScriptValue xColorToScriptValue(QScriptEngine *engine, const xColor& color); @@ -134,7 +135,7 @@ protected: bool _shouldDie; glm::vec3 _gravity; float _damping; - QString _updateScript; + QString _script; bool _inHand; uint32_t _creatorTokenID; @@ -152,7 +153,12 @@ class ParticleScriptObject : public QObject { public: ParticleScriptObject(Particle* particle) { _particle = particle; } + void emitUpdate() { emit update(); } + void emitCollisionWithParticle(uint32_t otherID) { emit collisionWithParticle(otherID); } + void emitCollisionWithVoxel() { emit collisionWithVoxel(); } + public slots: + unsigned int getID() const { return _particle->getID(); } glm::vec3 getPosition() const { return _particle->getPosition(); } glm::vec3 getVelocity() const { return _particle->getVelocity(); } xColor getColor() const { return _particle->getXColor(); } @@ -170,6 +176,11 @@ public slots: void setRadius(float value) { _particle->setRadius(value); } void setShouldDie(bool value) { _particle->setShouldDie(value); } +signals: + void update(); + void collisionWithVoxel(); + void collisionWithParticle(unsigned int otherID); + private: Particle* _particle; }; diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index b3ad9a9740..c477804325 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -90,6 +90,11 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { glm::vec3 penetration; Particle* penetratedParticle; if (_particles->findSpherePenetration(center, radius, penetration, (void**)&penetratedParticle)) { + + // let the particles run their collision scripts if they have them + particle->collisionWithParticle(penetratedParticle->getID()); + penetratedParticle->collisionWithParticle(particle->getID()); + penetration /= (float)TREE_SCALE; updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); // apply a hard collision to both particles of half the penetration each From 8e6f924c7306f2546ee0fc16bc04074e6127e9ac Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 30 Dec 2013 15:48:50 -0800 Subject: [PATCH 08/14] add access to Voxels and Particles inside of collision scripts --- libraries/particles/src/Particle.cpp | 32 +++++++++++++++++-- libraries/particles/src/Particle.h | 16 ++++++++++ .../src/ParticleScriptingInterface.cpp | 24 +++++++++++--- .../src/ParticleScriptingInterface.h | 7 ++-- libraries/script-engine/src/ScriptEngine.cpp | 12 +++++++ libraries/script-engine/src/ScriptEngine.h | 4 +-- 6 files changed, 84 insertions(+), 11 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 9f5af61042..72ffe71555 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -14,9 +14,14 @@ #include // usecTimestampNow() #include +#include +#include "ParticleScriptingInterface.h" + #include "Particle.h" uint32_t Particle::_nextID = 0; +VoxelScriptingInterface* Particle::_voxelScriptingInterface = NULL; +ParticleScriptingInterface* Particle::_particlesScriptingInterface = NULL; Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity, @@ -321,6 +326,7 @@ void Particle::debugDump() const { printf(" position:%f,%f,%f\n", _position.x, _position.y, _position.z); printf(" velocity:%f,%f,%f\n", _velocity.x, _velocity.y, _velocity.z); printf(" gravity:%f,%f,%f\n", _gravity.x, _gravity.y, _gravity.z); + printf(" color:%d,%d,%d\n", _color[0], _color[1], _color[2]); } bool Particle::encodeParticleEditMessageDetails(PACKET_TYPE command, int count, const ParticleDetail* details, @@ -548,11 +554,33 @@ void Particle::collisionWithParticle(unsigned int otherID) { QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); - + + + if (getVoxelsScriptingInterface()) { + QScriptValue voxelScripterValue = engine.newQObject(getVoxelsScriptingInterface()); + engine.globalObject().setProperty("Voxels", voxelScripterValue); + } + + if (getParticlesScriptingInterface()) { + QScriptValue particleScripterValue = engine.newQObject(getParticlesScriptingInterface()); + engine.globalObject().setProperty("Particles", particleScripterValue); + printf("has Particles...\n"); + } else { + printf("no Particles...\n"); + } + QScriptValue result = engine.evaluate(_script); particleScriptable.emitCollisionWithParticle(otherID); - + + if (getVoxelsScriptingInterface()) { + getVoxelsScriptingInterface()->getPacketSender()->releaseQueuedMessages(); + } + + if (getParticlesScriptingInterface()) { + getParticlesScriptingInterface()->getPacketSender()->releaseQueuedMessages(); + } + if (engine.hasUncaughtException()) { int line = engine.uncaughtExceptionLineNumber(); qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n"; diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 51d7cd4a30..5e0c45d9a9 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -19,6 +19,10 @@ #include #include +class VoxelScriptingInterface; +class ParticleScriptingInterface; + + const uint32_t NEW_PARTICLE = 0xFFFFFFFF; const uint32_t UNKNOWN_TOKEN = 0xFFFFFFFF; @@ -117,7 +121,19 @@ public: // similar to assignment/copy, but it handles keeping lifetime accurate void copyChangedProperties(const Particle& other); + static VoxelScriptingInterface* getVoxelsScriptingInterface() { return _voxelScriptingInterface; } + static ParticleScriptingInterface* getParticlesScriptingInterface() { return _particlesScriptingInterface; } + + static void setVoxelsScriptingInterface(VoxelScriptingInterface* interface) + { _voxelScriptingInterface = interface; } + + static void setParticlesScriptingInterface(ParticleScriptingInterface* interface) + { _particlesScriptingInterface = interface; } + protected: + static VoxelScriptingInterface* _voxelScriptingInterface; + static ParticleScriptingInterface* _particlesScriptingInterface; + void runUpdateScript(); static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3); static void vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3); diff --git a/libraries/particles/src/ParticleScriptingInterface.cpp b/libraries/particles/src/ParticleScriptingInterface.cpp index 8edfae3b88..ff31a82995 100644 --- a/libraries/particles/src/ParticleScriptingInterface.cpp +++ b/libraries/particles/src/ParticleScriptingInterface.cpp @@ -10,12 +10,12 @@ -void ParticleScriptingInterface::queueParticleAdd(PACKET_TYPE addPacketType, ParticleDetail& addParticleDetails) { - getParticlePacketSender()->queueParticleEditMessages(addPacketType, 1, &addParticleDetails); +void ParticleScriptingInterface::queueParticleMessage(PACKET_TYPE packetType, ParticleDetail& particleDetails) { + getParticlePacketSender()->queueParticleEditMessages(packetType, 1, &particleDetails); } unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, float radius, - xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString updateScript) { + xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString script) { // The application will keep track of creatorTokenID uint32_t creatorTokenID = _nextCreatorTokenID; @@ -25,10 +25,24 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl uint64_t now = usecTimestampNow(); ParticleDetail addParticleDetail = { NEW_PARTICLE, now, position, radius, {color.red, color.green, color.blue }, velocity, - gravity, damping, inHand, updateScript, creatorTokenID }; + gravity, damping, inHand, script, creatorTokenID }; // queue the packet - queueParticleAdd(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, addParticleDetail); + queueParticleMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, addParticleDetail); return creatorTokenID; } + + +void ParticleScriptingInterface::queueParticleEdit(unsigned int particleID, glm::vec3 position, float radius, + xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString script) { + + // setup a ParticleDetail struct with the data + uint64_t now = usecTimestampNow(); + ParticleDetail editParticleDetail = { particleID, now, + position, radius, {color.red, color.green, color.blue }, velocity, + gravity, damping, inHand, script, UNKNOWN_TOKEN }; + + // queue the packet + queueParticleMessage(PACKET_TYPE_PARTICLE_ADD_OR_EDIT, editParticleDetail); +} diff --git a/libraries/particles/src/ParticleScriptingInterface.h b/libraries/particles/src/ParticleScriptingInterface.h index 68b8318ebe..4f36af95f3 100644 --- a/libraries/particles/src/ParticleScriptingInterface.h +++ b/libraries/particles/src/ParticleScriptingInterface.h @@ -27,10 +27,13 @@ public slots: /// queues the creation of a Particle which will be sent by calling process on the PacketSender /// returns the creatorTokenID for the newly created particle unsigned int queueParticleAdd(glm::vec3 position, float radius, - xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString updateScript); + xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString script); + + void queueParticleEdit(unsigned int particleID, glm::vec3 position, float radius, + xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString script); private: - void queueParticleAdd(PACKET_TYPE addPacketType, ParticleDetail& addParticleDetails); + void queueParticleMessage(PACKET_TYPE packetType, ParticleDetail& particleDetails); uint32_t _nextCreatorTokenID; }; diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 24c4fcf1d9..80076cc2f6 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -23,6 +23,9 @@ #include "ScriptEngine.h" int ScriptEngine::_scriptNumber = 1; +VoxelScriptingInterface ScriptEngine::_voxelScriptingInterface; +ParticleScriptingInterface ScriptEngine::_particleScriptingInterface; + ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, const char* scriptMenuName, AbstractMenuInterface* menu, @@ -43,6 +46,15 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, } _menu = menu; _controllerScriptingInterface = controllerScriptingInterface; + + // hook up our interfaces + if (!Particle::getVoxelsScriptingInterface()) { + Particle::setVoxelsScriptingInterface(getVoxelScriptingInterface()); + } + + if (!Particle::getParticlesScriptingInterface()) { + Particle::setParticlesScriptingInterface(getParticleScriptingInterface()); + } } ScriptEngine::~ScriptEngine() { diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index c5172a5772..70aa226f6f 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -58,8 +58,8 @@ protected: private: - VoxelScriptingInterface _voxelScriptingInterface; - ParticleScriptingInterface _particleScriptingInterface; + static VoxelScriptingInterface _voxelScriptingInterface; + static ParticleScriptingInterface _particleScriptingInterface; AbstractControllerScriptingInterface* _controllerScriptingInterface; bool _wantMenuItems; QString _scriptMenuName; From cd115456138cc6182bf80e97553a78874de02b15 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 30 Dec 2013 15:55:46 -0800 Subject: [PATCH 09/14] change to setScript() since it does more than update --- libraries/particles/src/Particle.h | 5 +++-- libraries/particles/src/ParticleCollisionSystem.cpp | 2 +- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 5e0c45d9a9..99a192741a 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -83,7 +83,7 @@ public: float getEditedAgo() const { return (float)(usecTimestampNow() - _lastEdited) / (float)USECS_PER_SECOND; } uint32_t getID() const { return _id; } bool getShouldDie() const { return _shouldDie; } - QString getUpdateScript() const { return _script; } + QString getScript() const { return _script; } uint32_t getCreatorTokenID() const { return _creatorTokenID; } bool isNewlyCreated() const { return _newlyCreated; } @@ -100,7 +100,7 @@ public: void setInHand(bool inHand) { _inHand = inHand; } void setDamping(float value) { _damping = value; } void setShouldDie(bool shouldDie) { _shouldDie = shouldDie; } - void setUpdateScript(QString updateScript) { _script = updateScript; } + void setScript(QString updateScript) { _script = updateScript; } void setCreatorTokenID(uint32_t creatorTokenID) { _creatorTokenID = creatorTokenID; } bool appendParticleData(OctreePacketData* packetData) const; @@ -191,6 +191,7 @@ public slots: void setColor(xColor value) { _particle->setColor(value); } void setRadius(float value) { _particle->setRadius(value); } void setShouldDie(bool value) { _particle->setShouldDie(value); } + void setScript(const QString& script) { _particle->setScript(script); } signals: void update(); diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index c477804325..bde0f6d21a 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -227,7 +227,7 @@ void ParticleCollisionSystem::applyHardCollision(Particle* particle, const glm:: ParticleEditHandle particleEditHandle(_packetSender, _particles, particle->getID()); particleEditHandle.updateParticle(position, particle->getRadius(), particle->getXColor(), velocity, - particle->getGravity(), particle->getDamping(), particle->getInHand(), particle->getUpdateScript()); + particle->getGravity(), particle->getDamping(), particle->getInHand(), particle->getScript()); } From 9194a534105ee81f75bb31f7995820923e68e531 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 30 Dec 2013 15:55:57 -0800 Subject: [PATCH 10/14] change to setScript() since it does more than update --- interface/src/avatar/Hand.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/interface/src/avatar/Hand.cpp b/interface/src/avatar/Hand.cpp index 20f034989b..6d71cd2aef 100644 --- a/interface/src/avatar/Hand.cpp +++ b/interface/src/avatar/Hand.cpp @@ -118,7 +118,7 @@ void Hand::simulateToyBall(PalmData& palm, const glm::vec3& fingerTipPosition, f NO_GRAVITY, NO_DAMPING, IN_HAND, // we just grabbed it! - closestParticle->getUpdateScript()); + closestParticle->getScript()); // now tell our hand about us having caught it... From 5057517b78aef5ce1c5e893729609dfb53ff18e3 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Mon, 30 Dec 2013 16:35:58 -0800 Subject: [PATCH 11/14] pass scriptable particle on collisions --- libraries/particles/src/Particle.cpp | 8 +++----- libraries/particles/src/Particle.h | 6 +++--- libraries/particles/src/ParticleCollisionSystem.cpp | 4 ++-- 3 files changed, 8 insertions(+), 10 deletions(-) diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 72ffe71555..032f44a33d 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -540,7 +540,7 @@ void Particle::runUpdateScript() { } } -void Particle::collisionWithParticle(unsigned int otherID) { +void Particle::collisionWithParticle(Particle* other) { if (!_script.isEmpty()) { QScriptEngine engine; @@ -564,14 +564,12 @@ void Particle::collisionWithParticle(unsigned int otherID) { if (getParticlesScriptingInterface()) { QScriptValue particleScripterValue = engine.newQObject(getParticlesScriptingInterface()); engine.globalObject().setProperty("Particles", particleScripterValue); - printf("has Particles...\n"); - } else { - printf("no Particles...\n"); } QScriptValue result = engine.evaluate(_script); - particleScriptable.emitCollisionWithParticle(otherID); + ParticleScriptObject otherParticleScriptable(other); + particleScriptable.emitCollisionWithParticle(&otherParticleScriptable); if (getVoxelsScriptingInterface()) { getVoxelsScriptingInterface()->getPacketSender()->releaseQueuedMessages(); diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 99a192741a..8f797c27a3 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -114,7 +114,7 @@ public: static void adjustEditPacketForClockSkew(unsigned char* codeColorBuffer, ssize_t length, int clockSkew); void update(); - void collisionWithParticle(unsigned int otherID); + void collisionWithParticle(Particle* other); void debugDump() const; @@ -170,7 +170,7 @@ public: ParticleScriptObject(Particle* particle) { _particle = particle; } void emitUpdate() { emit update(); } - void emitCollisionWithParticle(uint32_t otherID) { emit collisionWithParticle(otherID); } + void emitCollisionWithParticle(QObject* other) { emit collisionWithParticle(other); } void emitCollisionWithVoxel() { emit collisionWithVoxel(); } public slots: @@ -196,7 +196,7 @@ public slots: signals: void update(); void collisionWithVoxel(); - void collisionWithParticle(unsigned int otherID); + void collisionWithParticle(QObject* other); private: Particle* _particle; diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index bde0f6d21a..bd4a1165da 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -92,8 +92,8 @@ void ParticleCollisionSystem::updateCollisionWithParticles(Particle* particle) { if (_particles->findSpherePenetration(center, radius, penetration, (void**)&penetratedParticle)) { // let the particles run their collision scripts if they have them - particle->collisionWithParticle(penetratedParticle->getID()); - penetratedParticle->collisionWithParticle(particle->getID()); + particle->collisionWithParticle(penetratedParticle); + penetratedParticle->collisionWithParticle(particle); penetration /= (float)TREE_SCALE; updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); From 651d2d0c81bb146fa9ffbeb0c0b7ebbb000e15dd Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 31 Dec 2013 09:41:35 -0800 Subject: [PATCH 12/14] rename voxels and particles scripting interfaces --- assignment-client/src/Agent.cpp | 4 +- assignment-client/src/Agent.h | 3 -- interface/src/Application.cpp | 4 +- libraries/particles/src/Particle.cpp | 8 ++-- libraries/particles/src/Particle.h | 18 ++++----- ...ce.cpp => ParticlesScriptingInterface.cpp} | 10 ++--- ...erface.h => ParticlesScriptingInterface.h} | 10 ++--- libraries/script-engine/src/ScriptEngine.cpp | 38 +++++++++---------- libraries/script-engine/src/ScriptEngine.h | 16 ++++---- ...rface.cpp => VoxelsScriptingInterface.cpp} | 12 +++--- ...Interface.h => VoxelsScriptingInterface.h} | 10 ++--- 11 files changed, 65 insertions(+), 68 deletions(-) rename libraries/particles/src/{ParticleScriptingInterface.cpp => ParticlesScriptingInterface.cpp} (79%) rename libraries/particles/src/{ParticleScriptingInterface.h => ParticlesScriptingInterface.h} (84%) rename libraries/voxels/src/{VoxelScriptingInterface.cpp => VoxelsScriptingInterface.cpp} (66%) rename libraries/voxels/src/{VoxelScriptingInterface.h => VoxelsScriptingInterface.h} (90%) diff --git a/assignment-client/src/Agent.cpp b/assignment-client/src/Agent.cpp index e8bffc8eb2..0a85a81692 100644 --- a/assignment-client/src/Agent.cpp +++ b/assignment-client/src/Agent.cpp @@ -32,12 +32,12 @@ void Agent::processDatagram(const QByteArray& dataByteArray, const HifiSockAddr& // PACKET_TYPE_JURISDICTION, first byte is the node type... switch (dataByteArray[headerBytes]) { case NODE_TYPE_VOXEL_SERVER: - _scriptEngine.getVoxelScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr, + _scriptEngine.getVoxelsScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size()); break; case NODE_TYPE_PARTICLE_SERVER: - _scriptEngine.getParticleScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr, + _scriptEngine.getParticlesScriptingInterface()->getJurisdictionListener()->queueReceivedPacket(senderSockAddr, (unsigned char*) dataByteArray.data(), dataByteArray.size()); break; diff --git a/assignment-client/src/Agent.h b/assignment-client/src/Agent.h index 0bcd1af78e..980885fcf3 100644 --- a/assignment-client/src/Agent.h +++ b/assignment-client/src/Agent.h @@ -18,9 +18,6 @@ #include #include -#include -#include - class Agent : public ThreadedAssignment { Q_OBJECT public: diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 08ffa436dc..0d3c20eb01 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -4455,8 +4455,8 @@ void Application::loadScript() { // setup the packet senders and jurisdiction listeners of the script engine's scripting interfaces so // we can use the same ones from the application. - scriptEngine->getVoxelScriptingInterface()->setPacketSender(&_voxelEditSender); - scriptEngine->getParticleScriptingInterface()->setPacketSender(&_particleEditSender); + scriptEngine->getVoxelsScriptingInterface()->setPacketSender(&_voxelEditSender); + scriptEngine->getParticlesScriptingInterface()->setPacketSender(&_particleEditSender); QThread* workerThread = new QThread(this); diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 032f44a33d..59974072f5 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -14,14 +14,14 @@ #include // usecTimestampNow() #include -#include -#include "ParticleScriptingInterface.h" +#include +#include "ParticlesScriptingInterface.h" #include "Particle.h" uint32_t Particle::_nextID = 0; -VoxelScriptingInterface* Particle::_voxelScriptingInterface = NULL; -ParticleScriptingInterface* Particle::_particlesScriptingInterface = NULL; +VoxelsScriptingInterface* Particle::_voxelsScriptingInterface = NULL; +ParticlesScriptingInterface* Particle::_particlesScriptingInterface = NULL; Particle::Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity, glm::vec3 gravity, diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 8f797c27a3..4c8ad7c7f4 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -19,8 +19,8 @@ #include #include -class VoxelScriptingInterface; -class ParticleScriptingInterface; +class VoxelsScriptingInterface; +class ParticlesScriptingInterface; const uint32_t NEW_PARTICLE = 0xFFFFFFFF; @@ -121,18 +121,18 @@ public: // similar to assignment/copy, but it handles keeping lifetime accurate void copyChangedProperties(const Particle& other); - static VoxelScriptingInterface* getVoxelsScriptingInterface() { return _voxelScriptingInterface; } - static ParticleScriptingInterface* getParticlesScriptingInterface() { return _particlesScriptingInterface; } + static VoxelsScriptingInterface* getVoxelsScriptingInterface() { return _voxelsScriptingInterface; } + static ParticlesScriptingInterface* getParticlesScriptingInterface() { return _particlesScriptingInterface; } - static void setVoxelsScriptingInterface(VoxelScriptingInterface* interface) - { _voxelScriptingInterface = interface; } + static void setVoxelsScriptingInterface(VoxelsScriptingInterface* interface) + { _voxelsScriptingInterface = interface; } - static void setParticlesScriptingInterface(ParticleScriptingInterface* interface) + static void setParticlesScriptingInterface(ParticlesScriptingInterface* interface) { _particlesScriptingInterface = interface; } protected: - static VoxelScriptingInterface* _voxelScriptingInterface; - static ParticleScriptingInterface* _particlesScriptingInterface; + static VoxelsScriptingInterface* _voxelsScriptingInterface; + static ParticlesScriptingInterface* _particlesScriptingInterface; void runUpdateScript(); static QScriptValue vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3); diff --git a/libraries/particles/src/ParticleScriptingInterface.cpp b/libraries/particles/src/ParticlesScriptingInterface.cpp similarity index 79% rename from libraries/particles/src/ParticleScriptingInterface.cpp rename to libraries/particles/src/ParticlesScriptingInterface.cpp index ff31a82995..7f8c435a12 100644 --- a/libraries/particles/src/ParticleScriptingInterface.cpp +++ b/libraries/particles/src/ParticlesScriptingInterface.cpp @@ -1,20 +1,20 @@ // -// ParticleScriptingInterface.cpp +// ParticlesScriptingInterface.cpp // hifi // // Created by Brad Hefta-Gaub on 12/6/13 // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#include "ParticleScriptingInterface.h" +#include "ParticlesScriptingInterface.h" -void ParticleScriptingInterface::queueParticleMessage(PACKET_TYPE packetType, ParticleDetail& particleDetails) { +void ParticlesScriptingInterface::queueParticleMessage(PACKET_TYPE packetType, ParticleDetail& particleDetails) { getParticlePacketSender()->queueParticleEditMessages(packetType, 1, &particleDetails); } -unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, float radius, +unsigned int ParticlesScriptingInterface::queueParticleAdd(glm::vec3 position, float radius, xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString script) { // The application will keep track of creatorTokenID @@ -34,7 +34,7 @@ unsigned int ParticleScriptingInterface::queueParticleAdd(glm::vec3 position, fl } -void ParticleScriptingInterface::queueParticleEdit(unsigned int particleID, glm::vec3 position, float radius, +void ParticlesScriptingInterface::queueParticleEdit(unsigned int particleID, glm::vec3 position, float radius, xColor color, glm::vec3 velocity, glm::vec3 gravity, float damping, bool inHand, QString script) { // setup a ParticleDetail struct with the data diff --git a/libraries/particles/src/ParticleScriptingInterface.h b/libraries/particles/src/ParticlesScriptingInterface.h similarity index 84% rename from libraries/particles/src/ParticleScriptingInterface.h rename to libraries/particles/src/ParticlesScriptingInterface.h index 4f36af95f3..265f5a7ca4 100644 --- a/libraries/particles/src/ParticleScriptingInterface.h +++ b/libraries/particles/src/ParticlesScriptingInterface.h @@ -1,13 +1,13 @@ // -// ParticleScriptingInterface.h +// ParticlesScriptingInterface.h // hifi // // Created by Brad Hefta-Gaub on 12/6/13 // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#ifndef __hifi__ParticleScriptingInterface__ -#define __hifi__ParticleScriptingInterface__ +#ifndef __hifi__ParticlesScriptingInterface__ +#define __hifi__ParticlesScriptingInterface__ #include @@ -16,7 +16,7 @@ #include "ParticleEditPacketSender.h" /// handles scripting of Particle commands from JS passed to assigned clients -class ParticleScriptingInterface : public OctreeScriptingInterface { +class ParticlesScriptingInterface : public OctreeScriptingInterface { Q_OBJECT public: ParticleEditPacketSender* getParticlePacketSender() const { return (ParticleEditPacketSender*)getPacketSender(); } @@ -38,4 +38,4 @@ private: uint32_t _nextCreatorTokenID; }; -#endif /* defined(__hifi__ParticleScriptingInterface__) */ +#endif /* defined(__hifi__ParticlesScriptingInterface__) */ diff --git a/libraries/script-engine/src/ScriptEngine.cpp b/libraries/script-engine/src/ScriptEngine.cpp index 80076cc2f6..eec0c22359 100644 --- a/libraries/script-engine/src/ScriptEngine.cpp +++ b/libraries/script-engine/src/ScriptEngine.cpp @@ -1,5 +1,5 @@ // -// Agent.cpp +// ScriptEngine.cpp // hifi // // Created by Brad Hefta-Gaub on 12/14/13. @@ -23,8 +23,8 @@ #include "ScriptEngine.h" int ScriptEngine::_scriptNumber = 1; -VoxelScriptingInterface ScriptEngine::_voxelScriptingInterface; -ParticleScriptingInterface ScriptEngine::_particleScriptingInterface; +VoxelsScriptingInterface ScriptEngine::_voxelsScriptingInterface; +ParticlesScriptingInterface ScriptEngine::_particlesScriptingInterface; ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, @@ -49,11 +49,11 @@ ScriptEngine::ScriptEngine(const QString& scriptContents, bool wantMenuItems, // hook up our interfaces if (!Particle::getVoxelsScriptingInterface()) { - Particle::setVoxelsScriptingInterface(getVoxelScriptingInterface()); + Particle::setVoxelsScriptingInterface(getVoxelsScriptingInterface()); } if (!Particle::getParticlesScriptingInterface()) { - Particle::setParticlesScriptingInterface(getParticleScriptingInterface()); + Particle::setParticlesScriptingInterface(getParticlesScriptingInterface()); } } @@ -86,8 +86,8 @@ void ScriptEngine::run() { _isRunning = true; QScriptEngine engine; - _voxelScriptingInterface.init(); - _particleScriptingInterface.init(); + _voxelsScriptingInterface.init(); + _particlesScriptingInterface.init(); // register meta-type for glm::vec3 conversions registerMetaTypes(&engine); @@ -95,10 +95,10 @@ void ScriptEngine::run() { QScriptValue agentValue = engine.newQObject(this); engine.globalObject().setProperty("Agent", agentValue); - QScriptValue voxelScripterValue = engine.newQObject(&_voxelScriptingInterface); + QScriptValue voxelScripterValue = engine.newQObject(&_voxelsScriptingInterface); engine.globalObject().setProperty("Voxels", voxelScripterValue); - QScriptValue particleScripterValue = engine.newQObject(&_particleScriptingInterface); + QScriptValue particleScripterValue = engine.newQObject(&_particlesScriptingInterface); engine.globalObject().setProperty("Particles", particleScripterValue); if (_controllerScriptingInterface) { @@ -112,8 +112,8 @@ void ScriptEngine::run() { const unsigned int VISUAL_DATA_CALLBACK_USECS = (1.0 / 60.0) * 1000 * 1000; // let the VoxelPacketSender know how frequently we plan to call it - _voxelScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS); - _particleScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS); + _voxelsScriptingInterface.getVoxelPacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS); + _particlesScriptingInterface.getParticlePacketSender()->setProcessCallIntervalHint(VISUAL_DATA_CALLBACK_USECS); //qDebug() << "Script:\n" << _scriptContents << "\n"; @@ -147,29 +147,29 @@ void ScriptEngine::run() { } bool willSendVisualDataCallBack = false; - if (_voxelScriptingInterface.getVoxelPacketSender()->serversExist()) { + if (_voxelsScriptingInterface.getVoxelPacketSender()->serversExist()) { // allow the scripter's call back to setup visual data willSendVisualDataCallBack = true; // release the queue of edit voxel messages. - _voxelScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages(); + _voxelsScriptingInterface.getVoxelPacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent - if (!_voxelScriptingInterface.getVoxelPacketSender()->isThreaded()) { - _voxelScriptingInterface.getVoxelPacketSender()->process(); + if (!_voxelsScriptingInterface.getVoxelPacketSender()->isThreaded()) { + _voxelsScriptingInterface.getVoxelPacketSender()->process(); } } - if (_particleScriptingInterface.getParticlePacketSender()->serversExist()) { + if (_particlesScriptingInterface.getParticlePacketSender()->serversExist()) { // allow the scripter's call back to setup visual data willSendVisualDataCallBack = true; // release the queue of edit voxel messages. - _particleScriptingInterface.getParticlePacketSender()->releaseQueuedMessages(); + _particlesScriptingInterface.getParticlePacketSender()->releaseQueuedMessages(); // since we're in non-threaded mode, call process so that the packets are sent - if (!_particleScriptingInterface.getParticlePacketSender()->isThreaded()) { - _particleScriptingInterface.getParticlePacketSender()->process(); + if (!_particlesScriptingInterface.getParticlePacketSender()->isThreaded()) { + _particlesScriptingInterface.getParticlePacketSender()->process(); } } diff --git a/libraries/script-engine/src/ScriptEngine.h b/libraries/script-engine/src/ScriptEngine.h index 70aa226f6f..44172de180 100644 --- a/libraries/script-engine/src/ScriptEngine.h +++ b/libraries/script-engine/src/ScriptEngine.h @@ -16,8 +16,8 @@ #include #include -#include -#include +#include +#include #include "AbstractControllerScriptingInterface.h" const QString NO_SCRIPT(""); @@ -31,11 +31,11 @@ public: ~ScriptEngine(); - /// Access the VoxelScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener - VoxelScriptingInterface* getVoxelScriptingInterface() { return &_voxelScriptingInterface; } + /// Access the VoxelsScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener + VoxelsScriptingInterface* getVoxelsScriptingInterface() { return &_voxelsScriptingInterface; } - /// Access the ParticleScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener - ParticleScriptingInterface* getParticleScriptingInterface() { return &_particleScriptingInterface; } + /// Access the ParticlesScriptingInterface in order to initialize it with a custom packet sender and jurisdiction listener + ParticlesScriptingInterface* getParticlesScriptingInterface() { return &_particlesScriptingInterface; } /// sets the script contents, will return false if failed, will fail if script is already running bool setScriptContents(const QString& scriptContents); @@ -58,8 +58,8 @@ protected: private: - static VoxelScriptingInterface _voxelScriptingInterface; - static ParticleScriptingInterface _particleScriptingInterface; + static VoxelsScriptingInterface _voxelsScriptingInterface; + static ParticlesScriptingInterface _particlesScriptingInterface; AbstractControllerScriptingInterface* _controllerScriptingInterface; bool _wantMenuItems; QString _scriptMenuName; diff --git a/libraries/voxels/src/VoxelScriptingInterface.cpp b/libraries/voxels/src/VoxelsScriptingInterface.cpp similarity index 66% rename from libraries/voxels/src/VoxelScriptingInterface.cpp rename to libraries/voxels/src/VoxelsScriptingInterface.cpp index 9c2ca45418..b17e40c036 100644 --- a/libraries/voxels/src/VoxelScriptingInterface.cpp +++ b/libraries/voxels/src/VoxelsScriptingInterface.cpp @@ -1,18 +1,18 @@ // -// VoxelScriptingInterface.cpp +// VoxelsScriptingInterface.cpp // hifi // // Created by Stephen Birarda on 9/17/13. // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#include "VoxelScriptingInterface.h" +#include "VoxelsScriptingInterface.h" -void VoxelScriptingInterface::queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails) { +void VoxelsScriptingInterface::queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails) { getVoxelPacketSender()->queueVoxelEditMessages(addPacketType, 1, &addVoxelDetails); } -void VoxelScriptingInterface::queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue) { +void VoxelsScriptingInterface::queueVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue) { // setup a VoxelDetail struct with the data VoxelDetail addVoxelDetail = {x, y, z, scale, red, green, blue}; @@ -20,7 +20,7 @@ void VoxelScriptingInterface::queueVoxelAdd(float x, float y, float z, float sca queueVoxelAdd(PACKET_TYPE_VOXEL_SET, addVoxelDetail); } -void VoxelScriptingInterface::queueDestructiveVoxelAdd(float x, float y, float z, float scale, +void VoxelsScriptingInterface::queueDestructiveVoxelAdd(float x, float y, float z, float scale, uchar red, uchar green, uchar blue) { // setup a VoxelDetail struct with the data VoxelDetail addVoxelDetail = {x, y, z, scale, red, green, blue}; @@ -29,7 +29,7 @@ void VoxelScriptingInterface::queueDestructiveVoxelAdd(float x, float y, float z queueVoxelAdd(PACKET_TYPE_VOXEL_SET_DESTRUCTIVE, addVoxelDetail); } -void VoxelScriptingInterface::queueVoxelDelete(float x, float y, float z, float scale) { +void VoxelsScriptingInterface::queueVoxelDelete(float x, float y, float z, float scale) { // setup a VoxelDetail struct with data VoxelDetail deleteVoxelDetail = {x, y, z, scale, 0, 0, 0}; diff --git a/libraries/voxels/src/VoxelScriptingInterface.h b/libraries/voxels/src/VoxelsScriptingInterface.h similarity index 90% rename from libraries/voxels/src/VoxelScriptingInterface.h rename to libraries/voxels/src/VoxelsScriptingInterface.h index db2835b7dd..34b16d1496 100644 --- a/libraries/voxels/src/VoxelScriptingInterface.h +++ b/libraries/voxels/src/VoxelsScriptingInterface.h @@ -1,13 +1,13 @@ // -// VoxelScriptingInterface.h +// VoxelsScriptingInterface.h // hifi // // Created by Stephen Birarda on 9/17/13. // Copyright (c) 2013 HighFidelity, Inc. All rights reserved. // -#ifndef __hifi__VoxelScriptingInterface__ -#define __hifi__VoxelScriptingInterface__ +#ifndef __hifi__VoxelsScriptingInterface__ +#define __hifi__VoxelsScriptingInterface__ #include @@ -16,7 +16,7 @@ #include "VoxelEditPacketSender.h" /// handles scripting of voxel commands from JS passed to assigned clients -class VoxelScriptingInterface : public OctreeScriptingInterface { +class VoxelsScriptingInterface : public OctreeScriptingInterface { Q_OBJECT public: VoxelEditPacketSender* getVoxelPacketSender() { return (VoxelEditPacketSender*)getPacketSender(); } @@ -56,4 +56,4 @@ private: void queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails); }; -#endif /* defined(__hifi__VoxelScriptingInterface__) */ +#endif /* defined(__hifi__VoxelsScriptingInterface__) */ From 48b2d7d3fa7b3830331503777cb5a4dddae8aa54 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 31 Dec 2013 11:33:43 -0800 Subject: [PATCH 13/14] scripting for particle to voxel collisions --- interface/src/Application.cpp | 15 +++++- libraries/particles/src/Particle.cpp | 47 +++++++++++++++++++ libraries/particles/src/Particle.h | 5 +- .../particles/src/ParticleCollisionSystem.cpp | 10 +++- libraries/voxels/src/VoxelTreeElement.cpp | 23 +++++++++ libraries/voxels/src/VoxelTreeElement.h | 4 ++ .../voxels/src/VoxelsScriptingInterface.h | 14 ++++++ 7 files changed, 112 insertions(+), 6 deletions(-) diff --git a/interface/src/Application.cpp b/interface/src/Application.cpp index 0d3c20eb01..9463c19dc6 100644 --- a/interface/src/Application.cpp +++ b/interface/src/Application.cpp @@ -1518,10 +1518,21 @@ void Application::shootParticle() { glm::vec3 velocity = lookingAt - position; glm::vec3 gravity = DEFAULT_GRAVITY * 0.f; float damping = DEFAULT_DAMPING * 0.01f; - QString updateScript(""); + QString script( + " function collisionWithVoxel(voxel) { " + " print('collisionWithVoxel(voxel)... '); " + " print('myID=' + Particle.getID() + '\\n'); " + " var voxelColor = voxel.getColor();" + " print('voxelColor=' + voxelColor.red + ', ' + voxelColor.green + ', ' + voxelColor.blue + '\\n'); " + " var myColor = Particle.getColor();" + " print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " + " Particle.setColor(voxelColor); " + " } " + " Particle.collisionWithVoxel.connect(collisionWithVoxel); " ); + ParticleEditHandle* particleEditHandle = makeParticle(position / (float)TREE_SCALE, radius, color, - velocity / (float)TREE_SCALE, gravity, damping, NOT_IN_HAND, updateScript); + velocity / (float)TREE_SCALE, gravity, damping, NOT_IN_HAND, script); // If we wanted to be able to edit this particle after shooting, then we could store this value // and use it for editing later. But we don't care about that for "shooting" and therefore we just diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index 59974072f5..2e4a341d4d 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -586,6 +586,53 @@ void Particle::collisionWithParticle(Particle* other) { } } +void Particle::collisionWithVoxel(VoxelDetail* voxelDetails) { + if (!_script.isEmpty()) { + + QScriptEngine engine; + + // register meta-type for glm::vec3 and rgbColor conversions + registerMetaTypes(&engine); + + ParticleScriptObject particleScriptable(this); + QScriptValue particleValue = engine.newQObject(&particleScriptable); + engine.globalObject().setProperty("Particle", particleValue); + + QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); + engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); + + + if (getVoxelsScriptingInterface()) { + QScriptValue voxelScripterValue = engine.newQObject(getVoxelsScriptingInterface()); + engine.globalObject().setProperty("Voxels", voxelScripterValue); + } + + if (getParticlesScriptingInterface()) { + QScriptValue particleScripterValue = engine.newQObject(getParticlesScriptingInterface()); + engine.globalObject().setProperty("Particles", particleScripterValue); + } + + QScriptValue result = engine.evaluate(_script); + + VoxelDetailScriptObject voxelDetailsScriptable(voxelDetails); + particleScriptable.emitCollisionWithVoxel(&voxelDetailsScriptable); + + if (getVoxelsScriptingInterface()) { + getVoxelsScriptingInterface()->getPacketSender()->releaseQueuedMessages(); + } + + if (getParticlesScriptingInterface()) { + getParticlesScriptingInterface()->getPacketSender()->releaseQueuedMessages(); + } + + if (engine.hasUncaughtException()) { + int line = engine.uncaughtExceptionLineNumber(); + qDebug() << "Uncaught exception at line" << line << ":" << result.toString() << "\n"; + } + } +} + + void Particle::setLifetime(float lifetime) { uint64_t lifetimeInUsecs = lifetime * USECS_PER_SECOND; diff --git a/libraries/particles/src/Particle.h b/libraries/particles/src/Particle.h index 4c8ad7c7f4..06709b4c06 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -115,6 +115,7 @@ public: void update(); void collisionWithParticle(Particle* other); + void collisionWithVoxel(VoxelDetail* voxel); void debugDump() const; @@ -171,7 +172,7 @@ public: void emitUpdate() { emit update(); } void emitCollisionWithParticle(QObject* other) { emit collisionWithParticle(other); } - void emitCollisionWithVoxel() { emit collisionWithVoxel(); } + void emitCollisionWithVoxel(QObject* voxel) { emit collisionWithVoxel(voxel); } public slots: unsigned int getID() const { return _particle->getID(); } @@ -195,7 +196,7 @@ public slots: signals: void update(); - void collisionWithVoxel(); + void collisionWithVoxel(QObject* voxel); void collisionWithParticle(QObject* other); private: diff --git a/libraries/particles/src/ParticleCollisionSystem.cpp b/libraries/particles/src/ParticleCollisionSystem.cpp index bd4a1165da..0a9b8ea1e2 100644 --- a/libraries/particles/src/ParticleCollisionSystem.cpp +++ b/libraries/particles/src/ParticleCollisionSystem.cpp @@ -73,11 +73,17 @@ void ParticleCollisionSystem::updateCollisionWithVoxels(Particle* particle) { const float VOXEL_DAMPING = 0.0; const float VOXEL_COLLISION_FREQUENCY = 0.5f; glm::vec3 penetration; - if (_voxels->findSpherePenetration(center, radius, penetration)) { + VoxelDetail* voxelDetails = NULL; + if (_voxels->findSpherePenetration(center, radius, penetration, (void**)&voxelDetails)) { + + // let the particles run their collision scripts if they have them + particle->collisionWithVoxel(voxelDetails); + penetration /= (float)TREE_SCALE; updateCollisionSound(particle, penetration, VOXEL_COLLISION_FREQUENCY); - //qDebug("voxel collision\n"); applyHardCollision(particle, penetration, VOXEL_ELASTICITY, VOXEL_DAMPING); + + delete voxelDetails; // cleanup returned details } } diff --git a/libraries/voxels/src/VoxelTreeElement.cpp b/libraries/voxels/src/VoxelTreeElement.cpp index bbf2b8695d..4641cabdf7 100644 --- a/libraries/voxels/src/VoxelTreeElement.cpp +++ b/libraries/voxels/src/VoxelTreeElement.cpp @@ -239,3 +239,26 @@ bool VoxelTreeElement::collapseChildren() { return allChildrenMatch; } + +bool VoxelTreeElement::findSpherePenetration(const glm::vec3& center, float radius, + glm::vec3& penetration, void** penetratedObject) const { + if (_box.findSpherePenetration(center, radius, penetration)) { + + // if the caller wants details about the voxel, then return them here... + if (penetratedObject) { + VoxelDetail* voxelDetails = new VoxelDetail; + voxelDetails->x = _box.getCorner().x; + voxelDetails->y = _box.getCorner().y; + voxelDetails->z = _box.getCorner().z; + voxelDetails->s = _box.getScale(); + voxelDetails->red = getTrueColor()[RED_INDEX]; + voxelDetails->green = getTrueColor()[GREEN_INDEX]; + voxelDetails->blue = getTrueColor()[BLUE_INDEX]; + + *penetratedObject = (void*)voxelDetails; + } + return true; + } + return false; +} + diff --git a/libraries/voxels/src/VoxelTreeElement.h b/libraries/voxels/src/VoxelTreeElement.h index a365e23510..1eee7e4a5b 100644 --- a/libraries/voxels/src/VoxelTreeElement.h +++ b/libraries/voxels/src/VoxelTreeElement.h @@ -44,6 +44,9 @@ public: virtual int readElementDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); virtual void calculateAverageFromChildren(); virtual bool collapseChildren(); + virtual bool findSpherePenetration(const glm::vec3& center, float radius, + glm::vec3& penetration, void** penetratedObject) const; + glBufferIndex getBufferIndex() const { return _glBufferIndex; } @@ -88,4 +91,5 @@ protected: nodeColor _currentColor; /// Client only, false color of this voxel, 4 bytes }; + #endif /* defined(__hifi__VoxelTreeElement__) */ \ No newline at end of file diff --git a/libraries/voxels/src/VoxelsScriptingInterface.h b/libraries/voxels/src/VoxelsScriptingInterface.h index 34b16d1496..5df814065e 100644 --- a/libraries/voxels/src/VoxelsScriptingInterface.h +++ b/libraries/voxels/src/VoxelsScriptingInterface.h @@ -56,4 +56,18 @@ private: void queueVoxelAdd(PACKET_TYPE addPacketType, VoxelDetail& addVoxelDetails); }; +class VoxelDetailScriptObject : public QObject { + Q_OBJECT +public: + VoxelDetailScriptObject(VoxelDetail* voxelDetail) { _voxelDetail = voxelDetail; } + +public slots: + glm::vec3 getPosition() const { return glm::vec3(_voxelDetail->x, _voxelDetail->y, _voxelDetail->z); } + xColor getColor() const { return { _voxelDetail->red, _voxelDetail->green, _voxelDetail->blue }; } + float getScale() const { return _voxelDetail->s; } + +private: + VoxelDetail* _voxelDetail; +}; + #endif /* defined(__hifi__VoxelsScriptingInterface__) */ From 8f9a99e1f44f8ad76d3c2c67338e5b9f9673b892 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 31 Dec 2013 12:13:06 -0800 Subject: [PATCH 14/14] add example scripts --- examples/collidingParticles.js | 149 +++++++++++++++++++++++++++++++++ examples/gun.js | 98 ++++++++++++++++++++++ 2 files changed, 247 insertions(+) create mode 100644 examples/collidingParticles.js create mode 100644 examples/gun.js diff --git a/examples/collidingParticles.js b/examples/collidingParticles.js new file mode 100644 index 0000000000..641dd1a4ec --- /dev/null +++ b/examples/collidingParticles.js @@ -0,0 +1,149 @@ +var currentIteration = 0; +var NUM_ITERATIONS_BEFORE_SEND = 15; // every 1/4th seconds send another + +var numberParticlesAdded = 0; +var MAX_PARTICLES = 1; + +var velocity = { + x: 1/TREE_SCALE, + y: 0/TREE_SCALE, + z: 1/TREE_SCALE }; + +var gravity = { + x: 0/TREE_SCALE, + y: 0/TREE_SCALE, + z: 0/TREE_SCALE }; + +var damping = 0.1; + +var scriptA = " " + + //" function update() { " + + //" print('update()\\n'); " + + //" var color = { red: 255, green: 127 + (Math.random() * 128), blue: 0 };" + + //" Particle.setColor(color); " + + //" } " + + " function collisionWithParticle(other) { " + + " print('collisionWithParticle(other.getID()=' + other.getID() + ')...'); " + + " print('myID=' + Particle.getID() + '\\n'); " + + " var colorBlack = { red: 0, green: 0, blue: 0 };" + + " var otherColor = other.getColor();" + + " print('otherColor=' + otherColor.red + ', ' + otherColor.green + ', ' + otherColor.blue + '\\n'); " + + " var myColor = Particle.getColor();" + + " print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " + + " Particle.setColor(otherColor); " + + " other.setColor(myColor); " + + " } " + + " function collisionWithVoxel(voxel) { " + + " print('collisionWithVoxel(voxel)... '); " + + " print('myID=' + Particle.getID() + '\\n'); " + + " var voxelColor = voxel.getColor();" + + " print('voxelColor=' + voxelColor.red + ', ' + voxelColor.green + ', ' + voxelColor.blue + '\\n'); " + + " var myColor = Particle.getColor();" + + " print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " + + " Particle.setColor(voxelColor); " + + " } " + + " Particle.collisionWithParticle.connect(collisionWithParticle); " + + " Particle.collisionWithVoxel.connect(collisionWithVoxel); " + + " "; + +var scriptB = " " + + " function collisionWithParticle(other) { " + + " print('collisionWithParticle(other.getID()=' + other.getID() + ')...'); " + + " print('myID=' + Particle.getID() + '\\n'); " + + " var myPosition = Particle.getPosition();" + + " var myRadius = Particle.getRadius();" + + " var myColor = Particle.getColor();" + + " Voxels.queueDestructiveVoxelAdd(myPosition.x, myPosition.y, myPosition.z, myRadius, myColor.red, myColor.green, myColor.blue); " + + " Particle.setScript('Particle.setShouldDie(true);'); " + + " } " + + " function collisionWithVoxel(voxel) { " + + " print('collisionWithVoxel(voxel)... '); " + + " print('myID=' + Particle.getID() + '\\n'); " + + " var voxelColor = voxel.getColor();" + + " print('voxelColor=' + voxelColor.red + ', ' + voxelColor.green + ', ' + voxelColor.blue + '\\n'); " + + " var myColor = Particle.getColor();" + + " print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " + + " Particle.setColor(voxelColor); " + + " } " + + " Particle.collisionWithParticle.connect(collisionWithParticle); " + + " Particle.collisionWithVoxel.connect(collisionWithVoxel); " + + " "; + +var color = { + red: 255, + green: 255, + blue: 0 }; + +function draw() { + print("hello... draw()... currentIteration=" + currentIteration + "\n"); + + // on the first iteration, setup a single particle that's slowly moving + if (currentIteration == 0) { + var colorGreen = { red: 0, green: 255, blue: 0 }; + var startPosition = { + x: 2/TREE_SCALE, + y: 0/TREE_SCALE, + z: 2/TREE_SCALE }; + var largeRadius = 0.5/TREE_SCALE; + var verySlow = { + x: 0.01/TREE_SCALE, + y: 0/TREE_SCALE, + z: 0.01/TREE_SCALE }; + + Particles.queueParticleAdd(startPosition, largeRadius, colorGreen, verySlow, gravity, damping, false, scriptA); + print("hello... added particle... script=\n"); + print(scriptA); + numberParticlesAdded++; + } + + if (currentIteration++ % NUM_ITERATIONS_BEFORE_SEND === 0) { + print("draw()... sending another... currentIteration=" +currentIteration + "\n"); + + var center = { + x: 0/TREE_SCALE, + y: 0/TREE_SCALE, + z: 0/TREE_SCALE }; + + var particleSize = 0.1 / TREE_SCALE; + + print("number of particles=" + numberParticlesAdded +"\n"); + + var velocityStep = 0.1/TREE_SCALE; + if (velocity.x > 0) { + velocity.x -= velocityStep; + velocity.z += velocityStep; + color.blue = 0; + color.green = 255; + } else { + velocity.x += velocityStep; + velocity.z -= velocityStep; + color.blue = 255; + color.green = 0; + } + + if (numberParticlesAdded <= MAX_PARTICLES) { + Particles.queueParticleAdd(center, particleSize, color, velocity, gravity, damping, false, scriptB); + print("hello... added particle... script=\n"); + print(scriptB); + numberParticlesAdded++; + } else { + Agent.stop(); + } + + print("Particles Stats: " + Particles.getLifetimeInSeconds() + " seconds," + + " Queued packets:" + Particles.getLifetimePacketsQueued() + "," + + " PPS:" + Particles.getLifetimePPSQueued() + "," + + " BPS:" + Particles.getLifetimeBPSQueued() + "," + + " Sent packets:" + Particles.getLifetimePacketsSent() + "," + + " PPS:" + Particles.getLifetimePPS() + "," + + " BPS:" + Particles.getLifetimeBPS() + + "\n"); + } +} + + +// register the call back so it fires before each data send +print("here...\n"); +Particles.setPacketsPerSecond(40000); +Agent.willSendVisualDataCallback.connect(draw); +print("and here...\n"); diff --git a/examples/gun.js b/examples/gun.js new file mode 100644 index 0000000000..f4e6e04ea9 --- /dev/null +++ b/examples/gun.js @@ -0,0 +1,98 @@ +// initialize our triggers +var triggerPulled = new Array(); +var numberOfTriggers = Controller.getNumberOfTriggers(); +for (t = 0; t < numberOfTriggers; t++) { + triggerPulled[t] = false; +} + +function checkController() { + var numberOfTriggers = Controller.getNumberOfTriggers(); + var numberOfSpatialControls = Controller.getNumberOfSpatialControls(); + var controllersPerTrigger = numberOfSpatialControls / numberOfTriggers; + //print("numberOfTriggers:" + numberOfTriggers + "\n"); + //print("numberOfSpatialControls:" + numberOfSpatialControls + "\n"); + //print("controllersPerTrigger:" + controllersPerTrigger + "\n"); + + // this is expected for hydras + if (numberOfTriggers == 2 && controllersPerTrigger == 2) { + for (var t = 0; t < numberOfTriggers; t++) { + var shootABullet = false; + var triggerValue = Controller.getTriggerValue(t); + + if (triggerPulled[t]) { + // must release to at least 0.1 + if (triggerValue < 0.1) { + triggerPulled[t] = false; // unpulled + } + } else { + // must pull to at least 0.9 + if (triggerValue > 0.9) { + triggerPulled[t] = true; // pulled + shootABullet = true; + } + } + + if (shootABullet) { + var palmController = t * controllersPerTrigger; + var palmPosition = Controller.getSpatialControlPosition(palmController); + + var fingerTipController = palmController + 1; + var fingerTipPosition = Controller.getSpatialControlPosition(fingerTipController); + + var bulletSize = 0.25/TREE_SCALE; + + var palmInParticleSpace = + { x: palmPosition.x/TREE_SCALE, + y: palmPosition.y/TREE_SCALE, + z: palmPosition.z/TREE_SCALE }; + + var tipInParticleSpace = + { x: fingerTipPosition.x/TREE_SCALE, + y: fingerTipPosition.y/TREE_SCALE, + z: fingerTipPosition.z/TREE_SCALE }; + + var palmToFingerTipVector = + { x: (tipInParticleSpace.x - palmInParticleSpace.x), + y: (tipInParticleSpace.y - palmInParticleSpace.y), + z: (tipInParticleSpace.z - palmInParticleSpace.z) }; + + // just off the front of the finger tip + var position = { x: tipInParticleSpace.x + palmToFingerTipVector.x/2, + y: tipInParticleSpace.y + palmToFingerTipVector.y/2, + z: tipInParticleSpace.z + palmToFingerTipVector.z/2}; + + var linearVelocity = 50; // 50 meters per second + + var velocity = { x: palmToFingerTipVector.x * linearVelocity, + y: palmToFingerTipVector.y * linearVelocity, + z: palmToFingerTipVector.z * linearVelocity }; + + var gravity = { x: 0, y: -0.1/TREE_SCALE, z: 0 }; // gravity has no effect on these bullets + var color = { red: 128, green: 128, blue: 128 }; + var damping = 0; // no damping + var inHand = false; + var script = + " function collisionWithVoxel(voxel) { " + + " print('collisionWithVoxel(voxel)... '); " + + " print('myID=' + Particle.getID() + '\\n'); " + + " var voxelColor = voxel.getColor();" + + " print('voxelColor=' + voxelColor.red + ', ' + voxelColor.green + ', ' + voxelColor.blue + '\\n'); " + + " var myColor = Particle.getColor();" + + " print('myColor=' + myColor.red + ', ' + myColor.green + ', ' + myColor.blue + '\\n'); " + + " Particle.setColor(voxelColor); " + + " var voxelAt = voxel.getPosition();" + + " var voxelScale = voxel.getScale();" + + " Voxels.queueVoxelDelete(voxelAt.x, voxelAt.y, voxelAt.z, voxelScale); " + + " print('Voxels.queueVoxelDelete(' + voxelAt.x + ', ' + voxelAt.y + ', ' + voxelAt.z + ', ' + voxelScale + ')... \\n'); " + + " } " + + " Particle.collisionWithVoxel.connect(collisionWithVoxel); "; + + Particles.queueParticleAdd(position, bulletSize, color, velocity, gravity, damping, inHand, script); + } + } + } +} + + +// register the call back so it fires before each data send +Agent.willSendVisualDataCallback.connect(checkController);