Merge branch 'master' of https://github.com/highfidelity/hifi into metavoxels

This commit is contained in:
Andrzej Kapolka 2014-12-08 18:49:49 -08:00
commit 87c789ea76
17 changed files with 118 additions and 48 deletions

View file

@ -22,11 +22,6 @@ var velocity = {
y: 0,
z: 1 };
var gravity = {
x: 0,
y: 0,
z: 0 };
var damping = 0.1;
var color = {
@ -42,22 +37,17 @@ function draw(deltaTime) {
var colorGreen = { red: 0, green: 255, blue: 0 };
var startPosition = {
x: 2,
y: 0,
y: 1,
z: 2 };
var largeRadius = 0.5;
var verySlow = {
x: 0.01,
y: 0,
z: 0.01 };
var properties = {
type: "Sphere",
collisionsWillMove: true,
position: startPosition,
dimensions: {x: largeRadius, y: largeRadius, z: largeRadius},
registrationPoint: { x: 0.5, y: 0.5, z: 0.5 },
color: colorGreen,
velocity: verySlow,
gravity: gravity,
damping: damping,
lifetime: 20
};
@ -71,7 +61,7 @@ function draw(deltaTime) {
var center = {
x: 0,
y: 0,
y: 1,
z: 0 };
var entitySize = 0.1;
@ -97,9 +87,9 @@ function draw(deltaTime) {
collisionsWillMove: true,
position: center,
dimensions: {x: entitySize, y: entitySize, z: entitySize},
registrationPoint: { x: 0.5, y: 0.5, z: 0.5 },
color: color,
velocity: velocity,
gravity: gravity,
damping: damping,
lifetime: 20
};

View file

@ -0,0 +1,20 @@
//
// changeColorOnCollision.js
// examples/entityScripts
//
// Created by Brad Hefta-Gaub on 12/8/14.
// Copyright 2014 High Fidelity, Inc.
//
// Distributed under the Apache License, Version 2.0.
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
//
(function(){
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min + 1)) + min;
}
this.collisionWithEntity = function(myID, otherID, collisionInfo) {
Entities.editEntity(myID, { color: { red: getRandomInt(128,255), green: getRandomInt(128,255), blue: getRandomInt(128,255)} });
};
})

View file

@ -41,6 +41,8 @@ EntityPropertyDialogBox = (function () {
array.push({ label: "Entity Type:" + properties.type, type: "header" });
index++;
array.push({ label: "ID:", value: properties.id });
index++;
array.push({ label: "Locked:", type: "checkbox", value: properties.locked });
index++;
@ -265,6 +267,7 @@ EntityPropertyDialogBox = (function () {
var properties = propertiesForEditedEntity;
var index = 0;
index++; // skip type header
index++; // skip id item
properties.locked = array[index++].value;
if (properties.type == "Model") {
properties.modelURL = array[index++].value;

View file

@ -2019,6 +2019,13 @@ void Application::init() {
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity,
ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::entityCollisionWithEntity);
// connect the _entityCollisionSystem to our EntityTreeRenderer since that's what handles running entity scripts
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithVoxel,
&_entities, &EntityTreeRenderer::entityCollisionWithVoxel);
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity,
&_entities, &EntityTreeRenderer::entityCollisionWithEntity);
// connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing
// of events related clicking, hovering over, and entering entities
_entities.connectSignalsToSlots(ScriptEngine::getEntityScriptingInterface());

View file

@ -233,7 +233,7 @@ void EntityTreeRenderer::update() {
void EntityTreeRenderer::checkEnterLeaveEntities() {
if (_tree) {
_tree->lockForRead();
_tree->lockForWrite(); // so that our scripts can do edits if they want
glm::vec3 avatarPosition = Application::getInstance()->getAvatar()->getPosition() / (float) TREE_SCALE;
if (avatarPosition != _lastAvatarPosition) {
@ -884,3 +884,35 @@ void EntityTreeRenderer::changingEntityID(const EntityItemID& oldEntityID, const
}
}
void EntityTreeRenderer::entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel,
const Collision& collision) {
QScriptValue entityScript = getPreviouslyLoadedEntityScript(entityID);
if (entityScript.property("collisionWithVoxel").isValid()) {
QScriptValueList args;
args << entityID.toScriptValue(_entitiesScriptEngine);
args << collisionToScriptValue(_entitiesScriptEngine, collision);
entityScript.property("collisionWithVoxel").call(entityScript, args);
}
}
void EntityTreeRenderer::entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB,
const Collision& collision) {
QScriptValue entityScriptA = loadEntityScript(idA);
if (entityScriptA.property("collisionWithEntity").isValid()) {
QScriptValueList args;
args << idA.toScriptValue(_entitiesScriptEngine);
args << idB.toScriptValue(_entitiesScriptEngine);
args << collisionToScriptValue(_entitiesScriptEngine, collision);
entityScriptA.property("collisionWithEntity").call(entityScriptA, args);
}
QScriptValue entityScriptB = loadEntityScript(idB);
if (entityScriptB.property("collisionWithEntity").isValid()) {
QScriptValueList args;
args << idB.toScriptValue(_entitiesScriptEngine);
args << idA.toScriptValue(_entitiesScriptEngine);
args << collisionToScriptValue(_entitiesScriptEngine, collision);
entityScriptB.property("collisionWithEntity").call(entityScriptA, args);
}
}

View file

@ -106,6 +106,9 @@ public slots:
void deletingEntity(const EntityItemID& entityID);
void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID);
void entitySciptChanging(const EntityItemID& entityID);
void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const Collision& collision);
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
protected:
virtual Octree* createTree() { return new EntityTree(true); }

View file

@ -54,7 +54,7 @@ void EntityCollisionSystem::updateCollisions() {
PerformanceTimer perfTimer("collisions");
assert(_entityTree);
// update all Entities
if (_entityTree->tryLockForRead()) {
if (_entityTree->tryLockForWrite()) {
foreach (EntityItem* entity, _movingEntities) {
checkEntity(entity);
}
@ -70,13 +70,13 @@ void EntityCollisionSystem::checkEntity(EntityItem* entity) {
}
void EntityCollisionSystem::emitGlobalEntityCollisionWithVoxel(EntityItem* entity,
VoxelDetail* voxelDetails, const CollisionInfo& collision) {
VoxelDetail* voxelDetails, const Collision& collision) {
EntityItemID entityItemID = entity->getEntityItemID();
emit entityCollisionWithVoxel(entityItemID, *voxelDetails, collision);
}
void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* entityA,
EntityItem* entityB, const CollisionInfo& collision) {
EntityItem* entityB, const Collision& collision) {
EntityItemID idA = entityA->getEntityItemID();
EntityItemID idB = entityB->getEntityItemID();
@ -104,7 +104,8 @@ void EntityCollisionSystem::updateCollisionWithVoxels(EntityItem* entity) {
// the results to systems outside of this octree reference frame.
collisionInfo._contactPoint = (float)TREE_SCALE * (entity->getPosition() + entity->getRadius() * glm::normalize(collisionInfo._penetration));
// let the global script run their collision scripts for Entities if they have them
emitGlobalEntityCollisionWithVoxel(entity, voxelDetails, collisionInfo);
Collision collision(collisionInfo._contactPoint, collisionInfo._penetration);
emitGlobalEntityCollisionWithVoxel(entity, voxelDetails, collision);
// we must scale back down to the octree reference frame before updating the Entity properties
collisionInfo._penetration /= (float)(TREE_SCALE);
@ -169,10 +170,10 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) {
quint64 now = usecTimestampNow();
CollisionInfo collision;
collision._penetration = penetration;
Collision collision;
collision.penetration = penetration;
// for now the contactPoint is the average between the the two paricle centers
collision._contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition());
collision.contactPoint = (0.5f * (float)TREE_SCALE) * (entityA->getPosition() + entityB->getPosition());
emitGlobalEntityCollisionWithEntity(entityA, entityB, collision);
glm::vec3 axis = glm::normalize(penetration);

View file

@ -53,15 +53,15 @@ public:
void updateCollisionSound(EntityItem* Entity, const glm::vec3 &penetration, float frequency);
signals:
void entityCollisionWithVoxel(const EntityItemID& entityItemID, const VoxelDetail& voxel, const CollisionInfo& penetration);
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& penetration);
void entityCollisionWithVoxel(const EntityItemID& entityItemID, const VoxelDetail& voxel, const Collision& collision);
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
private:
void applyHardCollision(EntityItem* entity, const CollisionInfo& collisionInfo);
static bool updateOperation(OctreeElement* element, void* extraData);
void emitGlobalEntityCollisionWithVoxel(EntityItem* Entity, VoxelDetail* voxelDetails, const CollisionInfo& penetration);
void emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const CollisionInfo& penetration);
void emitGlobalEntityCollisionWithVoxel(EntityItem* Entity, VoxelDetail* voxelDetails, const Collision& penetration);
void emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const Collision& penetration);
EntityEditPacketSender* _packetSender;
VoxelTree* _voxels;

View file

@ -49,6 +49,7 @@ public:
DIRTY_MOTION_TYPE = 0x0010,
DIRTY_SHAPE = 0x0020,
DIRTY_LIFETIME = 0x0040,
DIRTY_UPDATEABLE = 0x0080,
// add new simulation-relevant flags above
// all other flags below
DIRTY_SCRIPT = 0x8000
@ -130,7 +131,7 @@ public:
// perform linear extrapolation for SimpleEntitySimulation
void simulate(const quint64& now);
bool needsToCallUpdate() const { return false; }
virtual bool needsToCallUpdate() const { return false; }
virtual void debugDump() const;

View file

@ -102,8 +102,8 @@ public slots:
Q_INVOKABLE void dumpTree() const;
signals:
void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const CollisionInfo& collision);
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& collision);
void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const Collision& collision);
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);

View file

@ -397,6 +397,11 @@ void ModelEntityItem::debugDump() const {
qDebug() << " model URL:" << getModelURL();
}
void ModelEntityItem::setAnimationURL(const QString& url) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
_animationURL = url;
}
void ModelEntityItem::setAnimationSettings(const QString& value) {
// the animations setting is a JSON string that may contain various animation settings.
// if it includes fps, frameIndex, or running, those values will be parsed out and
@ -448,6 +453,17 @@ void ModelEntityItem::setAnimationSettings(const QString& value) {
}
_animationSettings = value;
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
}
void ModelEntityItem::setAnimationIsPlaying(bool value) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
_animationLoop.setRunning(value);
}
void ModelEntityItem::setAnimationFPS(float value) {
_dirtyFlags |= EntityItem::DIRTY_UPDATEABLE;
_animationLoop.setFPS(value);
}
QString ModelEntityItem::getAnimationSettings() const {

View file

@ -73,16 +73,16 @@ public:
// model related properties
void setModelURL(const QString& url) { _modelURL = url; }
void setAnimationURL(const QString& url) { _animationURL = url; }
void setAnimationURL(const QString& url);
static const float DEFAULT_ANIMATION_FRAME_INDEX;
void setAnimationFrameIndex(float value) { _animationLoop.setFrameIndex(value); }
void setAnimationSettings(const QString& value);
static const bool DEFAULT_ANIMATION_IS_PLAYING;
void setAnimationIsPlaying(bool value) { _animationLoop.setRunning(value); }
void setAnimationIsPlaying(bool value);
static const float DEFAULT_ANIMATION_FPS;
void setAnimationFPS(float value) { _animationLoop.setFPS(value); }
void setAnimationFPS(float value);
void setAnimationLoop(bool loop) { _animationLoop.setLoop(loop); }
bool getAnimationLoop() const { return _animationLoop.getLoop(); }

View file

@ -31,12 +31,10 @@ void SimpleEntitySimulation::updateEntitiesInternal(const quint64& now) {
}
void SimpleEntitySimulation::addEntityInternal(EntityItem* entity) {
if (entity->getCollisionsWillMove()) {
if (entity->isMoving()) {
_movingEntities.insert(entity);
} else {
_movableButStoppedEntities.insert(entity);
}
if (entity->isMoving()) {
_movingEntities.insert(entity);
} else if (entity->getCollisionsWillMove()) {
_movableButStoppedEntities.insert(entity);
}
}
@ -50,14 +48,10 @@ const int SIMPLE_SIMULATION_DIRTY_FLAGS = EntityItem::DIRTY_VELOCITY | EntityIte
void SimpleEntitySimulation::entityChangedInternal(EntityItem* entity) {
int dirtyFlags = entity->getDirtyFlags();
if (dirtyFlags & SIMPLE_SIMULATION_DIRTY_FLAGS) {
if (entity->getCollisionsWillMove()) {
if (entity->isMoving()) {
_movingEntities.insert(entity);
_movableButStoppedEntities.remove(entity);
} else {
_movingEntities.remove(entity);
_movableButStoppedEntities.insert(entity);
}
if (entity->isMoving()) {
_movingEntities.insert(entity);
} else if (entity->getCollisionsWillMove()) {
_movableButStoppedEntities.remove(entity);
} else {
_movingEntities.remove(entity);
_movableButStoppedEntities.remove(entity);

View file

@ -19,7 +19,7 @@
#include "MetavoxelMessages.h"
// in sequencer parlance, a "packet" may consist of multiple datagrams. clarify when we refer to actual datagrams
const int MAX_DATAGRAM_SIZE = MAX_PACKET_SIZE;
const int MAX_DATAGRAM_SIZE = 1450;
const int DEFAULT_MAX_PACKET_SIZE = 3000;

View file

@ -46,7 +46,7 @@ Octree::Octree(bool shouldReaverage) :
_isDirty(true),
_shouldReaverage(shouldReaverage),
_stopImport(false),
_lock(),
_lock(QReadWriteLock::Recursive),
_isViewing(false),
_isServer(false)
{

View file

@ -26,6 +26,7 @@ static int xColorMetaTypeId = qRegisterMetaType<xColor>();
static int pickRayMetaTypeId = qRegisterMetaType<PickRay>();
static int collisionMetaTypeId = qRegisterMetaType<Collision>();
void registerMetaTypes(QScriptEngine* engine) {
qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue);
qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue);

View file

@ -68,6 +68,8 @@ void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay);
class Collision {
public:
Collision() : contactPoint(0.0f), penetration(0.0f) { }
Collision(const glm::vec3& contactPoint, const glm::vec3& penetration) :
contactPoint(contactPoint), penetration(penetration) { }
glm::vec3 contactPoint;
glm::vec3 penetration;
};