mirror of
https://github.com/overte-org/overte.git
synced 2025-07-10 19:58:48 +02:00
Merge pull request #3924 from ZappoMan/entityCollisions
make collision callbacks work as entity methods
This commit is contained in:
commit
db751ca0c4
12 changed files with 88 additions and 29 deletions
|
@ -22,11 +22,6 @@ var velocity = {
|
||||||
y: 0,
|
y: 0,
|
||||||
z: 1 };
|
z: 1 };
|
||||||
|
|
||||||
var gravity = {
|
|
||||||
x: 0,
|
|
||||||
y: 0,
|
|
||||||
z: 0 };
|
|
||||||
|
|
||||||
var damping = 0.1;
|
var damping = 0.1;
|
||||||
|
|
||||||
var color = {
|
var color = {
|
||||||
|
@ -42,22 +37,17 @@ function draw(deltaTime) {
|
||||||
var colorGreen = { red: 0, green: 255, blue: 0 };
|
var colorGreen = { red: 0, green: 255, blue: 0 };
|
||||||
var startPosition = {
|
var startPosition = {
|
||||||
x: 2,
|
x: 2,
|
||||||
y: 0,
|
y: 1,
|
||||||
z: 2 };
|
z: 2 };
|
||||||
var largeRadius = 0.5;
|
var largeRadius = 0.5;
|
||||||
var verySlow = {
|
|
||||||
x: 0.01,
|
|
||||||
y: 0,
|
|
||||||
z: 0.01 };
|
|
||||||
|
|
||||||
var properties = {
|
var properties = {
|
||||||
type: "Sphere",
|
type: "Sphere",
|
||||||
collisionsWillMove: true,
|
collisionsWillMove: true,
|
||||||
position: startPosition,
|
position: startPosition,
|
||||||
dimensions: {x: largeRadius, y: largeRadius, z: largeRadius},
|
dimensions: {x: largeRadius, y: largeRadius, z: largeRadius},
|
||||||
|
registrationPoint: { x: 0.5, y: 0.5, z: 0.5 },
|
||||||
color: colorGreen,
|
color: colorGreen,
|
||||||
velocity: verySlow,
|
|
||||||
gravity: gravity,
|
|
||||||
damping: damping,
|
damping: damping,
|
||||||
lifetime: 20
|
lifetime: 20
|
||||||
};
|
};
|
||||||
|
@ -71,7 +61,7 @@ function draw(deltaTime) {
|
||||||
|
|
||||||
var center = {
|
var center = {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: 0,
|
y: 1,
|
||||||
z: 0 };
|
z: 0 };
|
||||||
|
|
||||||
var entitySize = 0.1;
|
var entitySize = 0.1;
|
||||||
|
@ -97,9 +87,9 @@ function draw(deltaTime) {
|
||||||
collisionsWillMove: true,
|
collisionsWillMove: true,
|
||||||
position: center,
|
position: center,
|
||||||
dimensions: {x: entitySize, y: entitySize, z: entitySize},
|
dimensions: {x: entitySize, y: entitySize, z: entitySize},
|
||||||
|
registrationPoint: { x: 0.5, y: 0.5, z: 0.5 },
|
||||||
color: color,
|
color: color,
|
||||||
velocity: velocity,
|
velocity: velocity,
|
||||||
gravity: gravity,
|
|
||||||
damping: damping,
|
damping: damping,
|
||||||
lifetime: 20
|
lifetime: 20
|
||||||
};
|
};
|
||||||
|
|
20
examples/entityScripts/changeColorOnCollision.js
Normal file
20
examples/entityScripts/changeColorOnCollision.js
Normal 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)} });
|
||||||
|
};
|
||||||
|
})
|
|
@ -41,6 +41,8 @@ EntityPropertyDialogBox = (function () {
|
||||||
|
|
||||||
array.push({ label: "Entity Type:" + properties.type, type: "header" });
|
array.push({ label: "Entity Type:" + properties.type, type: "header" });
|
||||||
index++;
|
index++;
|
||||||
|
array.push({ label: "ID:", value: properties.id });
|
||||||
|
index++;
|
||||||
array.push({ label: "Locked:", type: "checkbox", value: properties.locked });
|
array.push({ label: "Locked:", type: "checkbox", value: properties.locked });
|
||||||
index++;
|
index++;
|
||||||
|
|
||||||
|
@ -265,6 +267,7 @@ EntityPropertyDialogBox = (function () {
|
||||||
var properties = propertiesForEditedEntity;
|
var properties = propertiesForEditedEntity;
|
||||||
var index = 0;
|
var index = 0;
|
||||||
index++; // skip type header
|
index++; // skip type header
|
||||||
|
index++; // skip id item
|
||||||
properties.locked = array[index++].value;
|
properties.locked = array[index++].value;
|
||||||
if (properties.type == "Model") {
|
if (properties.type == "Model") {
|
||||||
properties.modelURL = array[index++].value;
|
properties.modelURL = array[index++].value;
|
||||||
|
|
|
@ -2019,6 +2019,13 @@ void Application::init() {
|
||||||
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity,
|
connect(&_entityCollisionSystem, &EntityCollisionSystem::entityCollisionWithEntity,
|
||||||
ScriptEngine::getEntityScriptingInterface(), &EntityScriptingInterface::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
|
// connect the _entities (EntityTreeRenderer) to our script engine's EntityScriptingInterface for firing
|
||||||
// of events related clicking, hovering over, and entering entities
|
// of events related clicking, hovering over, and entering entities
|
||||||
_entities.connectSignalsToSlots(ScriptEngine::getEntityScriptingInterface());
|
_entities.connectSignalsToSlots(ScriptEngine::getEntityScriptingInterface());
|
||||||
|
|
|
@ -233,7 +233,7 @@ void EntityTreeRenderer::update() {
|
||||||
|
|
||||||
void EntityTreeRenderer::checkEnterLeaveEntities() {
|
void EntityTreeRenderer::checkEnterLeaveEntities() {
|
||||||
if (_tree) {
|
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;
|
glm::vec3 avatarPosition = Application::getInstance()->getAvatar()->getPosition() / (float) TREE_SCALE;
|
||||||
|
|
||||||
if (avatarPosition != _lastAvatarPosition) {
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -106,6 +106,9 @@ public slots:
|
||||||
void deletingEntity(const EntityItemID& entityID);
|
void deletingEntity(const EntityItemID& entityID);
|
||||||
void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID);
|
void changingEntityID(const EntityItemID& oldEntityID, const EntityItemID& newEntityID);
|
||||||
void entitySciptChanging(const EntityItemID& entityID);
|
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:
|
protected:
|
||||||
virtual Octree* createTree() { return new EntityTree(true); }
|
virtual Octree* createTree() { return new EntityTree(true); }
|
||||||
|
|
|
@ -54,7 +54,7 @@ void EntityCollisionSystem::updateCollisions() {
|
||||||
PerformanceTimer perfTimer("collisions");
|
PerformanceTimer perfTimer("collisions");
|
||||||
assert(_entityTree);
|
assert(_entityTree);
|
||||||
// update all Entities
|
// update all Entities
|
||||||
if (_entityTree->tryLockForRead()) {
|
if (_entityTree->tryLockForWrite()) {
|
||||||
foreach (EntityItem* entity, _movingEntities) {
|
foreach (EntityItem* entity, _movingEntities) {
|
||||||
checkEntity(entity);
|
checkEntity(entity);
|
||||||
}
|
}
|
||||||
|
@ -70,13 +70,13 @@ void EntityCollisionSystem::checkEntity(EntityItem* entity) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityCollisionSystem::emitGlobalEntityCollisionWithVoxel(EntityItem* entity,
|
void EntityCollisionSystem::emitGlobalEntityCollisionWithVoxel(EntityItem* entity,
|
||||||
VoxelDetail* voxelDetails, const CollisionInfo& collision) {
|
VoxelDetail* voxelDetails, const Collision& collision) {
|
||||||
EntityItemID entityItemID = entity->getEntityItemID();
|
EntityItemID entityItemID = entity->getEntityItemID();
|
||||||
emit entityCollisionWithVoxel(entityItemID, *voxelDetails, collision);
|
emit entityCollisionWithVoxel(entityItemID, *voxelDetails, collision);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* entityA,
|
void EntityCollisionSystem::emitGlobalEntityCollisionWithEntity(EntityItem* entityA,
|
||||||
EntityItem* entityB, const CollisionInfo& collision) {
|
EntityItem* entityB, const Collision& collision) {
|
||||||
|
|
||||||
EntityItemID idA = entityA->getEntityItemID();
|
EntityItemID idA = entityA->getEntityItemID();
|
||||||
EntityItemID idB = entityB->getEntityItemID();
|
EntityItemID idB = entityB->getEntityItemID();
|
||||||
|
@ -104,7 +104,8 @@ void EntityCollisionSystem::updateCollisionWithVoxels(EntityItem* entity) {
|
||||||
// the results to systems outside of this octree reference frame.
|
// the results to systems outside of this octree reference frame.
|
||||||
collisionInfo._contactPoint = (float)TREE_SCALE * (entity->getPosition() + entity->getRadius() * glm::normalize(collisionInfo._penetration));
|
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
|
// 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
|
// we must scale back down to the octree reference frame before updating the Entity properties
|
||||||
collisionInfo._penetration /= (float)(TREE_SCALE);
|
collisionInfo._penetration /= (float)(TREE_SCALE);
|
||||||
|
@ -169,10 +170,10 @@ void EntityCollisionSystem::updateCollisionWithEntities(EntityItem* entityA) {
|
||||||
|
|
||||||
quint64 now = usecTimestampNow();
|
quint64 now = usecTimestampNow();
|
||||||
|
|
||||||
CollisionInfo collision;
|
Collision collision;
|
||||||
collision._penetration = penetration;
|
collision.penetration = penetration;
|
||||||
// for now the contactPoint is the average between the the two paricle centers
|
// 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);
|
emitGlobalEntityCollisionWithEntity(entityA, entityB, collision);
|
||||||
|
|
||||||
glm::vec3 axis = glm::normalize(penetration);
|
glm::vec3 axis = glm::normalize(penetration);
|
||||||
|
|
|
@ -53,15 +53,15 @@ public:
|
||||||
void updateCollisionSound(EntityItem* Entity, const glm::vec3 &penetration, float frequency);
|
void updateCollisionSound(EntityItem* Entity, const glm::vec3 &penetration, float frequency);
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void entityCollisionWithVoxel(const EntityItemID& entityItemID, const VoxelDetail& voxel, const CollisionInfo& penetration);
|
void entityCollisionWithVoxel(const EntityItemID& entityItemID, const VoxelDetail& voxel, const Collision& collision);
|
||||||
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& penetration);
|
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void applyHardCollision(EntityItem* entity, const CollisionInfo& collisionInfo);
|
void applyHardCollision(EntityItem* entity, const CollisionInfo& collisionInfo);
|
||||||
|
|
||||||
static bool updateOperation(OctreeElement* element, void* extraData);
|
static bool updateOperation(OctreeElement* element, void* extraData);
|
||||||
void emitGlobalEntityCollisionWithVoxel(EntityItem* Entity, VoxelDetail* voxelDetails, const CollisionInfo& penetration);
|
void emitGlobalEntityCollisionWithVoxel(EntityItem* Entity, VoxelDetail* voxelDetails, const Collision& penetration);
|
||||||
void emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const CollisionInfo& penetration);
|
void emitGlobalEntityCollisionWithEntity(EntityItem* entityA, EntityItem* entityB, const Collision& penetration);
|
||||||
|
|
||||||
EntityEditPacketSender* _packetSender;
|
EntityEditPacketSender* _packetSender;
|
||||||
VoxelTree* _voxels;
|
VoxelTree* _voxels;
|
||||||
|
|
|
@ -102,8 +102,8 @@ public slots:
|
||||||
Q_INVOKABLE void dumpTree() const;
|
Q_INVOKABLE void dumpTree() const;
|
||||||
|
|
||||||
signals:
|
signals:
|
||||||
void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const CollisionInfo& collision);
|
void entityCollisionWithVoxel(const EntityItemID& entityID, const VoxelDetail& voxel, const Collision& collision);
|
||||||
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const CollisionInfo& collision);
|
void entityCollisionWithEntity(const EntityItemID& idA, const EntityItemID& idB, const Collision& collision);
|
||||||
|
|
||||||
void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
void mousePressOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||||
void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
void mouseMoveOnEntity(const EntityItemID& entityItemID, const MouseEvent& event);
|
||||||
|
|
|
@ -46,7 +46,7 @@ Octree::Octree(bool shouldReaverage) :
|
||||||
_isDirty(true),
|
_isDirty(true),
|
||||||
_shouldReaverage(shouldReaverage),
|
_shouldReaverage(shouldReaverage),
|
||||||
_stopImport(false),
|
_stopImport(false),
|
||||||
_lock(),
|
_lock(QReadWriteLock::Recursive),
|
||||||
_isViewing(false),
|
_isViewing(false),
|
||||||
_isServer(false)
|
_isServer(false)
|
||||||
{
|
{
|
||||||
|
|
|
@ -26,6 +26,7 @@ static int xColorMetaTypeId = qRegisterMetaType<xColor>();
|
||||||
static int pickRayMetaTypeId = qRegisterMetaType<PickRay>();
|
static int pickRayMetaTypeId = qRegisterMetaType<PickRay>();
|
||||||
static int collisionMetaTypeId = qRegisterMetaType<Collision>();
|
static int collisionMetaTypeId = qRegisterMetaType<Collision>();
|
||||||
|
|
||||||
|
|
||||||
void registerMetaTypes(QScriptEngine* engine) {
|
void registerMetaTypes(QScriptEngine* engine) {
|
||||||
qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue);
|
qScriptRegisterMetaType(engine, vec4toScriptValue, vec4FromScriptValue);
|
||||||
qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue);
|
qScriptRegisterMetaType(engine, vec3toScriptValue, vec3FromScriptValue);
|
||||||
|
|
|
@ -68,6 +68,8 @@ void pickRayFromScriptValue(const QScriptValue& object, PickRay& pickRay);
|
||||||
class Collision {
|
class Collision {
|
||||||
public:
|
public:
|
||||||
Collision() : contactPoint(0.0f), penetration(0.0f) { }
|
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 contactPoint;
|
||||||
glm::vec3 penetration;
|
glm::vec3 penetration;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue