From 48b2d7d3fa7b3830331503777cb5a4dddae8aa54 Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 31 Dec 2013 11:33:43 -0800 Subject: [PATCH] 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__) */