From 7a828794be9b3e5b483de9932e7041c99555d4bf Mon Sep 17 00:00:00 2001 From: ZappoMan Date: Tue, 10 Dec 2013 11:27:18 -0800 Subject: [PATCH] more work with particles added javascript support to particle update --- interface/src/ParticleTreeRenderer.cpp | 15 +-- .../octree-server/src/OctreePersistThread.cpp | 6 +- libraries/octree/src/Octree.h | 3 + libraries/octree/src/OctreeRenderer.cpp | 5 +- libraries/particles/src/Particle.cpp | 109 ++++++++++++++++++ libraries/particles/src/Particle.h | 40 +++++++ libraries/particles/src/ParticleTree.cpp | 15 ++- libraries/particles/src/ParticleTree.h | 2 +- .../particles/src/ParticleTreeElement.cpp | 3 + libraries/shared/src/SharedUtil.h | 7 ++ 10 files changed, 191 insertions(+), 14 deletions(-) diff --git a/interface/src/ParticleTreeRenderer.cpp b/interface/src/ParticleTreeRenderer.cpp index 2c24fb77bc..12b75d8a0b 100644 --- a/interface/src/ParticleTreeRenderer.cpp +++ b/interface/src/ParticleTreeRenderer.cpp @@ -21,7 +21,9 @@ ParticleTreeRenderer::~ParticleTreeRenderer() { void ParticleTreeRenderer::update() { if (_tree) { ParticleTree* tree = (ParticleTree*)_tree; + _tree->lockForWrite(); tree->update(); + _tree->unlock(); } } @@ -36,11 +38,6 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element) { bool drawAsSphere = true; - if (!drawAsSphere) { - glPointSize(20.0f); - glBegin(GL_POINTS); - } - for (uint16_t i = 0; i < numberOfParticles; i++) { const Particle& particle = particles[i]; // render particle aspoints @@ -49,18 +46,18 @@ void ParticleTreeRenderer::renderElement(OctreeElement* element) { glColor3ub(particle.getColor()[RED_INDEX],particle.getColor()[GREEN_INDEX],particle.getColor()[BLUE_INDEX]); //printf("particle at... (%f, %f, %f)\n", position.x, position.y, position.z); + float sphereRadius = particle.getRadius() * (float)TREE_SCALE; if (drawAsSphere) { - float sphereRadius = particle.getRadius() * (float)TREE_SCALE; glPushMatrix(); glTranslatef(position.x, position.y, position.z); glutSolidSphere(sphereRadius, 15, 15); glPopMatrix(); } else { + glPointSize(sphereRadius); + glBegin(GL_POINTS); glVertex3f(position.x, position.y, position.z); + glEnd(); } } - if (!drawAsSphere) { - glEnd(); - } } diff --git a/libraries/octree-server/src/OctreePersistThread.cpp b/libraries/octree-server/src/OctreePersistThread.cpp index a3a2663342..aba683e110 100644 --- a/libraries/octree-server/src/OctreePersistThread.cpp +++ b/libraries/octree-server/src/OctreePersistThread.cpp @@ -64,8 +64,12 @@ bool OctreePersistThread::process() { if (isStillRunning()) { uint64_t MSECS_TO_USECS = 1000; - uint64_t USECS_TO_SLEEP = 100 * MSECS_TO_USECS; // every 100ms + uint64_t USECS_TO_SLEEP = 10 * MSECS_TO_USECS; // every 10ms usleep(USECS_TO_SLEEP); + + // do our updates then check to save... + _tree->update(); + uint64_t now = usecTimestampNow(); uint64_t sinceLastSave = now - _lastCheck; uint64_t intervalToCheck = _persistInterval * MSECS_TO_USECS; diff --git a/libraries/octree/src/Octree.h b/libraries/octree/src/Octree.h index aed3ad334d..920fe04be7 100644 --- a/libraries/octree/src/Octree.h +++ b/libraries/octree/src/Octree.h @@ -187,6 +187,9 @@ public: virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength, unsigned char* editData, int maxLength) { return 0; } + + virtual void update() { }; // nothing to do by default + OctreeElement* getRoot() { return _rootNode; } void eraseAllOctreeElements(); diff --git a/libraries/octree/src/OctreeRenderer.cpp b/libraries/octree/src/OctreeRenderer.cpp index b0a3bf581a..de1e980a0a 100644 --- a/libraries/octree/src/OctreeRenderer.cpp +++ b/libraries/octree/src/OctreeRenderer.cpp @@ -126,7 +126,8 @@ public: bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) { RenderArgs* args = static_cast(extraData); - if (true || element->isInView(*args->_viewFrustum)) { + //if (true || element->isInView(*args->_viewFrustum)) { + if (element) { if (element->hasContent()) { args->_renderer->renderElement(element); } @@ -139,6 +140,8 @@ bool OctreeRenderer::renderOperation(OctreeElement* element, void* extraData) { void OctreeRenderer::render() { RenderArgs args = { this, _viewFrustum }; if (_tree) { + _tree->lockForRead(); _tree->recurseTreeWithOperation(renderOperation, &args); + _tree->unlock(); } } diff --git a/libraries/particles/src/Particle.cpp b/libraries/particles/src/Particle.cpp index f5957c564f..520a92908d 100644 --- a/libraries/particles/src/Particle.cpp +++ b/libraries/particles/src/Particle.cpp @@ -7,6 +7,9 @@ // // +#include +#include + #include // usecTimestampNow() #include "Particle.h" @@ -211,9 +214,115 @@ void Particle::update() { //printf("velocity=%f, %f, %f\n", getVelocity().x, getVelocity().y, getVelocity().z); _position += _velocity * timeElapsed; + + float gravity = -9.8f / TREE_SCALE; + + glm::vec3 velocity = getVelocity() * (float)TREE_SCALE; + //printf("OLD velocity=%f, %f, %f\n", velocity.x, velocity.y, velocity.z); + + // handle bounces off the ground... + if (_position.y <= 0) { + _velocity = _velocity * glm::vec3(1,-1,1); + + velocity = getVelocity() * (float)TREE_SCALE; + //printf("NEW from ground BOUNCE velocity=%f, %f, %f\n", velocity.x, velocity.y, velocity.z); + + _position.y = 0; + } + + // handle gravity.... + _velocity += glm::vec3(0,gravity,0) * timeElapsed; + velocity = getVelocity() * (float)TREE_SCALE; + //printf("NEW from gravity.... velocity=%f, %f, %f\n", velocity.x, velocity.y, velocity.z); + + // handle air resistance.... + glm::vec3 airResistance = _velocity * glm::vec3(-0.25,-0.25,-0.25); + _velocity += airResistance * timeElapsed; + + velocity = getVelocity() * (float)TREE_SCALE; + //printf("NEW from air resistance.... velocity=%f, %f, %f\n", velocity.x, velocity.y, velocity.z); position = getPosition() * (float)TREE_SCALE; //printf("NEW position=%f, %f, %f\n", position.x, position.y, position.z); + + runScript(); // test this... + + position = getPosition() * (float)TREE_SCALE; + //printf("AFTER SCRIPT NEW position=%f, %f, %f\n", position.x, position.y, position.z); + _lastUpdated = now; } +Q_DECLARE_METATYPE(glm::vec3); +Q_DECLARE_METATYPE(xColor); + +QScriptValue Particle::vec3toScriptValue(QScriptEngine *engine, const glm::vec3 &vec3) { + QScriptValue obj = engine->newObject(); + obj.setProperty("x", vec3.x); + obj.setProperty("y", vec3.y); + obj.setProperty("z", vec3.z); + return obj; +} + +void Particle::vec3FromScriptValue(const QScriptValue &object, glm::vec3 &vec3) { + vec3.x = object.property("x").toVariant().toFloat(); + vec3.y = object.property("y").toVariant().toFloat(); + vec3.z = object.property("z").toVariant().toFloat(); +} + +QScriptValue Particle::xColorToScriptValue(QScriptEngine *engine, const xColor& color) { + QScriptValue obj = engine->newObject(); + obj.setProperty("red", color.red); + obj.setProperty("green", color.green); + obj.setProperty("blue", color.blue); + return obj; +} + +void Particle::xColorFromScriptValue(const QScriptValue &object, xColor& color) { + color.red = object.property("red").toVariant().toInt(); + color.green = object.property("green").toVariant().toInt(); + color.blue = object.property("blue").toVariant().toInt(); +} + +void Particle::runScript() { + QString scriptContents("" + //"print(\"hello world\\n\");\n" + //"var position = Particle.getPosition();\n" + //"print(\"position.x=\" + position.x + \"\\n\");\n" + //"position.x = position.x * 0.9;\n" + //"Particle.setPosition(position);\n" + //"print(\"position.x=\" + position.x + \"\\n\");\n" + //"var color = Particle.getColor();\n" + //"color.red = color.red - 1;\n" + //"if (color.red < 10) { color.red = 255; }\n" + //"Particle.setColor(color);\n" + //"print(\"position=\" + position.x + \",\" + position.y + \",\" + position.z + \"\\n\");\n" + ); + QScriptEngine engine; + + // register meta-type for glm::vec3 and rgbColor conversions + qScriptRegisterMetaType(&engine, vec3toScriptValue, vec3FromScriptValue); + qScriptRegisterMetaType(&engine, xColorToScriptValue, xColorFromScriptValue); + + ParticleScriptObject particleScriptable(this); + QScriptValue particleValue = engine.newQObject(&particleScriptable); + engine.globalObject().setProperty("Particle", particleValue); + + //QScriptValue voxelScripterValue = engine.newQObject(&_voxelScriptingInterface); + //engine.globalObject().setProperty("Voxels", voxelScripterValue); + + //QScriptValue particleScripterValue = engine.newQObject(&_particleScriptingInterface); + //engine.globalObject().setProperty("Particles", particleScripterValue); + + QScriptValue treeScaleValue = engine.newVariant(QVariant(TREE_SCALE)); + engine.globalObject().setProperty("TREE_SCALE", TREE_SCALE); + + //qDebug() << "Downloaded script:" << scriptContents << "\n"; + QScriptValue result = engine.evaluate(scriptContents); + //qDebug() << "Evaluated script.\n"; + + 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 84d512b5fd..bc95b37758 100644 --- a/libraries/particles/src/Particle.h +++ b/libraries/particles/src/Particle.h @@ -13,6 +13,9 @@ #include #include +#include +#include + #include #include @@ -24,7 +27,9 @@ public: glm::vec3 velocity; }; + class Particle { + public: Particle(); Particle(glm::vec3 position, float radius, rgbColor color, glm::vec3 velocity); @@ -37,11 +42,22 @@ public: const glm::vec3& getPosition() const { return _position; } const rgbColor& getColor() const { return _color; } + xColor getColor() { return { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; } + float getRadius() const { return _radius; } const glm::vec3& getVelocity() const { return _velocity; } uint64_t getLastUpdated() const { return _lastUpdated; } uint32_t getID() const { return _id; } + void setPosition(const glm::vec3& value) { _position = value; } + void setVelocity(const glm::vec3& value) { _velocity = value; } + void setColor(const rgbColor& value) { memcpy(_color, value, sizeof(_color)); } + void setColor(const xColor& value) { + _color[RED_INDEX] = value.red; + _color[GREEN_INDEX] = value.green; + _color[BLUE_INDEX] = value.blue; + } + bool appendParticleData(OctreePacketData* packetData) const; int readParticleDataFromBuffer(const unsigned char* data, int bytesLeftToRead, ReadBitstreamToTreeParams& args); static int expectedBytes(); @@ -50,6 +66,12 @@ public: unsigned char* bufferOut, int sizeIn, int& sizeOut); void update(); + void runScript(); + + 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); + static void xColorFromScriptValue(const QScriptValue &object, xColor& color); protected: glm::vec3 _position; @@ -61,4 +83,22 @@ protected: static uint32_t _nextID; }; +class ParticleScriptObject : public QObject { + Q_OBJECT +public: + ParticleScriptObject(Particle* particle) { _particle = particle; } + +public slots: + glm::vec3 getPosition() const { return _particle->getPosition(); } + glm::vec3 getVelocity() const { return _particle->getVelocity(); } + xColor getColor() const { return _particle->getColor(); } + + void setPosition(glm::vec3 value) { return _particle->setPosition(value); } + void setVelocity(glm::vec3 value) { return _particle->setVelocity(value); } + void setColor(xColor value) { return _particle->setColor(value); } + +private: + Particle* _particle; +}; + #endif /* defined(__hifi__Particle__) */ \ No newline at end of file diff --git a/libraries/particles/src/ParticleTree.cpp b/libraries/particles/src/ParticleTree.cpp index 52b8b60354..9bb08b4004 100644 --- a/libraries/particles/src/ParticleTree.cpp +++ b/libraries/particles/src/ParticleTree.cpp @@ -74,14 +74,25 @@ bool ParticleTree::updateOperation(OctreeElement* element, void* extraData) { } void ParticleTree::update() { + _isDirty = true; + ParticleTreeUpdateArgs args = { }; recurseTreeWithOperation(updateOperation, &args); // now add back any of the particles that moved elements.... int movingParticles = args._movingParticles.size(); for (int i = 0; i < movingParticles; i++) { - printf("re-storing moved particle...\n"); - storeParticle(args._movingParticles[i]); + // if the particle is still inside our total bounds, then re-add it + AABox treeBounds = getRoot()->getAABox(); + float velocityScalar = glm::length(args._movingParticles[i].getVelocity()); + const float STILL_MOVING = 0.0001; + + if (velocityScalar > STILL_MOVING && treeBounds.contains(args._movingParticles[i].getPosition())) { + printf("re-storing moved particle...\n"); + storeParticle(args._movingParticles[i]); + } else { + printf("out of bounds or !velocityScalar=[%f], not re-storing moved particle...\n",velocityScalar); + } } } diff --git a/libraries/particles/src/ParticleTree.h b/libraries/particles/src/ParticleTree.h index 359a1572ac..4581a2d276 100644 --- a/libraries/particles/src/ParticleTree.h +++ b/libraries/particles/src/ParticleTree.h @@ -37,7 +37,7 @@ public: virtual int processEditPacketData(PACKET_TYPE packetType, unsigned char* packetData, int packetLength, unsigned char* editData, int maxLength); - void update(); + virtual void update(); private: void storeParticle(const Particle& particle); diff --git a/libraries/particles/src/ParticleTreeElement.cpp b/libraries/particles/src/ParticleTreeElement.cpp index 515e1b2453..5eb140b681 100644 --- a/libraries/particles/src/ParticleTreeElement.cpp +++ b/libraries/particles/src/ParticleTreeElement.cpp @@ -60,10 +60,13 @@ bool ParticleTreeElement::appendElementData(OctreePacketData* packetData) const } void ParticleTreeElement::update(ParticleTreeUpdateArgs& args) { + markWithChangedTime(); + // update our contained particles uint16_t numberOfParticles = _particles.size(); for (uint16_t i = 0; i < numberOfParticles; i++) { _particles[i].update(); + // what if this update moves the particle to a new element?? if (!_box.contains(_particles[i].getPosition())) { diff --git a/libraries/shared/src/SharedUtil.h b/libraries/shared/src/SharedUtil.h index 7d73e93fcc..8124822b46 100644 --- a/libraries/shared/src/SharedUtil.h +++ b/libraries/shared/src/SharedUtil.h @@ -31,6 +31,13 @@ typedef unsigned char colorPart; typedef unsigned char nodeColor[BYTES_PER_COLOR + BYTES_PER_FLAGS]; typedef unsigned char rgbColor[BYTES_PER_COLOR]; +struct xColor { + unsigned char red; + unsigned char green; + unsigned char blue; +}; + + static const float ZERO = 0.0f; static const float ONE = 1.0f; static const float ONE_HALF = 0.5f;