mirror of
https://github.com/overte-org/overte.git
synced 2025-04-25 10:14:52 +02:00
commit
a4e4e86669
30 changed files with 362 additions and 93 deletions
|
@ -22,7 +22,8 @@ var zoneEntityA = Entities.addEntity({
|
|||
dimensions: { x: 10, y: 10, z: 10 },
|
||||
keyLightColor: { red: 255, green: 0, blue: 0 },
|
||||
stageSunModelEnabled: false,
|
||||
keyLightDirection: { x: 0, y: -1.0, z: 0 }
|
||||
keyLightDirection: { x: 0, y: -1.0, z: 0 },
|
||||
shapeType: "sphere"
|
||||
});
|
||||
|
||||
print("zoneEntityA:" + zoneEntityA);
|
||||
|
@ -51,7 +52,9 @@ var zoneEntityC = Entities.addEntity({
|
|||
keyLightColor: { red: 0, green: 0, blue: 255 },
|
||||
keyLightIntensity: 0.75,
|
||||
keyLightDirection: { x: 0, y: 0, z: -1 },
|
||||
stageSunModelEnabled: false
|
||||
stageSunModelEnabled: false,
|
||||
shapeType: "compound",
|
||||
compoundShapeURL: "http://headache.hungry.com/~seth/hifi/cube.fbx"
|
||||
});
|
||||
|
||||
print("zoneEntityC:" + zoneEntityC);
|
||||
|
|
|
@ -162,7 +162,7 @@
|
|||
|
||||
var elModelSections = document.querySelectorAll(".model-section");
|
||||
var elModelURL = document.getElementById("property-model-url");
|
||||
var elCollisionModelURL = document.getElementById("property-collision-model-url");
|
||||
var elCompoundShapeURL = document.getElementById("property-compound-shape-url");
|
||||
var elModelAnimationURL = document.getElementById("property-model-animation-url");
|
||||
var elModelAnimationPlaying = document.getElementById("property-model-animation-playing");
|
||||
var elModelAnimationFPS = document.getElementById("property-model-animation-fps");
|
||||
|
@ -323,7 +323,7 @@
|
|||
}
|
||||
|
||||
elModelURL.value = properties.modelURL;
|
||||
elCollisionModelURL.value = properties.collisionModelURL;
|
||||
elCompoundShapeURL.value = properties.compoundShapeURL;
|
||||
elModelAnimationURL.value = properties.animationURL;
|
||||
elModelAnimationPlaying.checked = properties.animationIsPlaying;
|
||||
elModelAnimationFPS.value = properties.animationFPS;
|
||||
|
@ -487,7 +487,7 @@
|
|||
elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff'));
|
||||
|
||||
elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL'));
|
||||
elCollisionModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('collisionModelURL'));
|
||||
elCompoundShapeURL.addEventListener('change', createEmitTextPropertyUpdateFunction('compoundShapeURL'));
|
||||
elModelAnimationURL.addEventListener('change', createEmitTextPropertyUpdateFunction('animationURL'));
|
||||
elModelAnimationPlaying.addEventListener('change', createEmitCheckedPropertyUpdateFunction('animationIsPlaying'));
|
||||
elModelAnimationFPS.addEventListener('change', createEmitNumberPropertyUpdateFunction('animationFPS'));
|
||||
|
@ -775,9 +775,9 @@
|
|||
</div>
|
||||
</div>
|
||||
<div class="model-section property">
|
||||
<div class="label">Collision Model URL</div>
|
||||
<div class="label">Compound Shape URL</div>
|
||||
<div class="value">
|
||||
<input type="text" id="property-collision-model-url" class="url"></input>
|
||||
<input type="text" id="property-compound-shape-url" class="url"></input>
|
||||
</div>
|
||||
</div>
|
||||
<div class="model-section property">
|
||||
|
|
|
@ -53,7 +53,7 @@ function Tooltip() {
|
|||
text += "ID: " + properties.id + "\n"
|
||||
if (properties.type == "Model") {
|
||||
text += "Model URL: " + properties.modelURL + "\n"
|
||||
text += "Collision Model URL: " + properties.collisionModelURL + "\n"
|
||||
text += "Compound Shape URL: " + properties.compoundShapeURL + "\n"
|
||||
text += "Animation URL: " + properties.animationURL + "\n"
|
||||
text += "Animation is playing: " + properties.animationIsPlaying + "\n"
|
||||
if (properties.sittingPoints && properties.sittingPoints.length > 0) {
|
||||
|
|
|
@ -52,7 +52,7 @@ EntityPropertyDialogBox = (function () {
|
|||
if (properties.type == "Model") {
|
||||
array.push({ label: "Model URL:", value: properties.modelURL });
|
||||
index++;
|
||||
array.push({ label: "Collision Model URL:", value: properties.collisionModelURL });
|
||||
array.push({ label: "Compound Shape URL:", value: properties.compoundShapeURL });
|
||||
index++;
|
||||
array.push({ label: "Animation URL:", value: properties.animationURL });
|
||||
index++;
|
||||
|
@ -284,7 +284,7 @@ EntityPropertyDialogBox = (function () {
|
|||
properties.locked = array[index++].value;
|
||||
if (properties.type == "Model") {
|
||||
properties.modelURL = array[index++].value;
|
||||
properties.collisionModelURL = array[index++].value;
|
||||
properties.compoundShapeURL = array[index++].value;
|
||||
properties.animationURL = array[index++].value;
|
||||
|
||||
var newAnimationIsPlaying = array[index++].value;
|
||||
|
|
|
@ -34,8 +34,8 @@
|
|||
#include "RenderableParticleEffectEntityItem.h"
|
||||
#include "RenderableSphereEntityItem.h"
|
||||
#include "RenderableTextEntityItem.h"
|
||||
#include "RenderableZoneEntityItem.h"
|
||||
#include "EntitiesRendererLogging.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
|
||||
EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterface* viewState,
|
||||
AbstractScriptingServicesInterface* scriptingServices) :
|
||||
|
@ -57,6 +57,7 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
|||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Text, RenderableTextEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(ParticleEffect, RenderableParticleEffectEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Zone, RenderableZoneEntityItem::factory)
|
||||
|
||||
_currentHoverOverEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID
|
||||
_currentClickingOnEntityID = EntityItemID::createInvalidEntityID(); // makes it the unknown ID
|
||||
|
@ -496,7 +497,7 @@ const FBXGeometry* EntityTreeRenderer::getCollisionGeometryForEntity(const Entit
|
|||
|
||||
if (entityItem->getType() == EntityTypes::Model) {
|
||||
const RenderableModelEntityItem* constModelEntityItem = dynamic_cast<const RenderableModelEntityItem*>(entityItem);
|
||||
if (constModelEntityItem->hasCollisionModel()) {
|
||||
if (constModelEntityItem->hasCompoundShapeURL()) {
|
||||
RenderableModelEntityItem* modelEntityItem = const_cast<RenderableModelEntityItem*>(constModelEntityItem);
|
||||
Model* model = modelEntityItem->getModel(this);
|
||||
if (model) {
|
||||
|
|
|
@ -224,10 +224,10 @@ Model* RenderableModelEntityItem::getModel(EntityTreeRenderer* renderer) {
|
|||
// if we have a previously allocated model, but its URL doesn't match
|
||||
// then we need to let our renderer update our model for us.
|
||||
if (_model && QUrl(getModelURL()) != _model->getURL()) {
|
||||
result = _model = _myRenderer->updateModel(_model, getModelURL(), getCollisionModelURL());
|
||||
result = _model = _myRenderer->updateModel(_model, getModelURL(), getCompoundShapeURL());
|
||||
_needsInitialSimulation = true;
|
||||
} else if (!_model) { // if we don't yet have a model, then we want our renderer to allocate one
|
||||
result = _model = _myRenderer->allocateModel(getModelURL(), getCollisionModelURL());
|
||||
result = _model = _myRenderer->allocateModel(getModelURL(), getCompoundShapeURL());
|
||||
_needsInitialSimulation = true;
|
||||
} else { // we already have the model we want...
|
||||
result = _model;
|
||||
|
@ -267,8 +267,8 @@ bool RenderableModelEntityItem::findDetailedRayIntersection(const glm::vec3& ori
|
|||
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, extraInfo, precisionPicking);
|
||||
}
|
||||
|
||||
void RenderableModelEntityItem::setCollisionModelURL(const QString& url) {
|
||||
ModelEntityItem::setCollisionModelURL(url);
|
||||
void RenderableModelEntityItem::setCompoundShapeURL(const QString& url) {
|
||||
ModelEntityItem::setCompoundShapeURL(url);
|
||||
if (_model) {
|
||||
_model->setCollisionModelURL(QUrl(url));
|
||||
}
|
||||
|
@ -410,8 +410,17 @@ void RenderableModelEntityItem::computeShapeInfo(ShapeInfo& info) {
|
|||
}
|
||||
|
||||
glm::vec3 collisionModelDimensions = box.getDimensions();
|
||||
info.setParams(type, collisionModelDimensions, _collisionModelURL);
|
||||
info.setParams(type, collisionModelDimensions, _compoundShapeURL);
|
||||
info.setConvexHulls(_points);
|
||||
}
|
||||
}
|
||||
|
||||
bool RenderableModelEntityItem::contains(const glm::vec3& point) const {
|
||||
if (EntityItem::contains(point) && _model && _model->getCollisionGeometry()) {
|
||||
const QSharedPointer<NetworkGeometry> collisionNetworkGeometry = _model->getCollisionGeometry();
|
||||
const FBXGeometry& collisionGeometry = collisionNetworkGeometry->getFBXGeometry();
|
||||
return collisionGeometry.convexHullContains(worldToEntity(point));
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -52,10 +52,12 @@ public:
|
|||
|
||||
bool needsToCallUpdate() const;
|
||||
|
||||
virtual void setCollisionModelURL(const QString& url);
|
||||
virtual void setCompoundShapeURL(const QString& url);
|
||||
|
||||
bool isReadyToComputeShape();
|
||||
void computeShapeInfo(ShapeInfo& info);
|
||||
|
||||
virtual bool contains(const glm::vec3& point) const;
|
||||
|
||||
private:
|
||||
void remapTextures();
|
||||
|
|
57
libraries/entities-renderer/src/RenderableZoneEntityItem.cpp
Normal file
57
libraries/entities-renderer/src/RenderableZoneEntityItem.cpp
Normal file
|
@ -0,0 +1,57 @@
|
|||
//
|
||||
// RenderableZoneEntityItem.cpp
|
||||
//
|
||||
//
|
||||
// Created by Clement on 4/22/15.
|
||||
// Copyright 2015 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
|
||||
//
|
||||
|
||||
#include "RenderableZoneEntityItem.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
|
||||
EntityItem* RenderableZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return new RenderableZoneEntityItem(entityID, properties);
|
||||
}
|
||||
|
||||
bool RenderableZoneEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
QString oldShapeURL = getCompoundShapeURL();
|
||||
bool somethingChanged = ZoneEntityItem::setProperties(properties);
|
||||
if (somethingChanged && oldShapeURL != getCompoundShapeURL()) {
|
||||
_compoundShapeModel = DependencyManager::get<GeometryCache>()->getGeometry(getCompoundShapeURL(), QUrl(), true);
|
||||
}
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
int RenderableZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData) {
|
||||
QString oldShapeURL = getCompoundShapeURL();
|
||||
int bytesRead = ZoneEntityItem::readEntitySubclassDataFromBuffer(data, bytesLeftToRead,
|
||||
args, propertyFlags, overwriteLocalData);
|
||||
if (oldShapeURL != getCompoundShapeURL()) {
|
||||
_compoundShapeModel = DependencyManager::get<GeometryCache>()->getGeometry(getCompoundShapeURL(), QUrl(), true);
|
||||
}
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
bool RenderableZoneEntityItem::contains(const glm::vec3& point) const {
|
||||
if (getShapeType() != SHAPE_TYPE_COMPOUND) {
|
||||
return EntityItem::contains(point);
|
||||
}
|
||||
if (!_compoundShapeModel && hasCompoundShapeURL()) {
|
||||
const_cast<RenderableZoneEntityItem*>(this)->_compoundShapeModel = DependencyManager::get<GeometryCache>()->getGeometry(getCompoundShapeURL(), QUrl(), true);
|
||||
}
|
||||
|
||||
if (EntityItem::contains(point) && _compoundShapeModel && _compoundShapeModel->isLoaded()) {
|
||||
const FBXGeometry& geometry = _compoundShapeModel->getFBXGeometry();
|
||||
glm::vec3 meshDimensions = geometry.getUnscaledMeshExtents().maximum - geometry.getUnscaledMeshExtents().minimum;
|
||||
return geometry.convexHullContains(worldToEntity(point) * meshDimensions);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
39
libraries/entities-renderer/src/RenderableZoneEntityItem.h
Normal file
39
libraries/entities-renderer/src/RenderableZoneEntityItem.h
Normal file
|
@ -0,0 +1,39 @@
|
|||
//
|
||||
// RenderableZoneEntityItem.h
|
||||
//
|
||||
//
|
||||
// Created by Clement on 4/22/15.
|
||||
// Copyright 2015 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
|
||||
//
|
||||
|
||||
#ifndef hifi_RenderableZoneEntityItem_h
|
||||
#define hifi_RenderableZoneEntityItem_h
|
||||
|
||||
#include <ZoneEntityItem.h>
|
||||
|
||||
class NetworkGeometry;
|
||||
|
||||
class RenderableZoneEntityItem : public ZoneEntityItem {
|
||||
public:
|
||||
static EntityItem* factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
RenderableZoneEntityItem(const EntityItemID& entityItemID, const EntityItemProperties& properties) :
|
||||
ZoneEntityItem(entityItemID, properties)
|
||||
{ }
|
||||
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData);
|
||||
|
||||
virtual bool contains(const glm::vec3& point) const;
|
||||
|
||||
private:
|
||||
|
||||
QSharedPointer<NetworkGeometry> _compoundShapeModel;
|
||||
};
|
||||
|
||||
#endif // hifi_RenderableZoneEntityItem_h
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include <QtCore/QObject>
|
||||
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
#include <GLMHelpers.h>
|
||||
#include <Octree.h>
|
||||
|
@ -843,7 +845,27 @@ bool EntityItem::isMoving() const {
|
|||
return hasVelocity() || hasAngularVelocity();
|
||||
}
|
||||
|
||||
bool EntityItem::lifetimeHasExpired() const {
|
||||
glm::mat4 EntityItem::getEntityToWorldMatrix() const {
|
||||
glm::mat4 translation = glm::translate(getPosition());
|
||||
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
||||
glm::mat4 scale = glm::scale(getDimensions());
|
||||
glm::mat4 registration = glm::translate(ENTITY_ITEM_DEFAULT_REGISTRATION_POINT - getRegistrationPoint());
|
||||
return translation * rotation * scale * registration;
|
||||
}
|
||||
|
||||
glm::mat4 EntityItem::getWorldToEntityMatrix() const {
|
||||
return glm::inverse(getEntityToWorldMatrix());
|
||||
}
|
||||
|
||||
glm::vec3 EntityItem::entityToWorld(const glm::vec3 point) const {
|
||||
return glm::vec3(getEntityToWorldMatrix() * glm::vec4(point, 1.0f));
|
||||
}
|
||||
|
||||
glm::vec3 EntityItem::worldToEntity(const glm::vec3 point) const {
|
||||
return glm::vec3(getWorldToEntityMatrix() * glm::vec4(point, 1.0f));
|
||||
}
|
||||
|
||||
bool EntityItem::lifetimeHasExpired() const {
|
||||
return isMortal() && (getAge() > getLifetime());
|
||||
}
|
||||
|
||||
|
@ -1033,12 +1055,6 @@ AABox EntityItem::getAABox() const {
|
|||
return AABox(rotatedExtentsRelativeToRegistrationPoint);
|
||||
}
|
||||
|
||||
AABox EntityItem::getAABoxInDomainUnits() const {
|
||||
AABox box = getAABox();
|
||||
box.scale(1.0f / (float)TREE_SCALE);
|
||||
return box;
|
||||
}
|
||||
|
||||
// NOTE: This should only be used in cases of old bitstreams which only contain radius data
|
||||
// 0,0,0 --> maxDimension,maxDimension,maxDimension
|
||||
// ... has a corner to corner distance of glm::length(maxDimension,maxDimension,maxDimension)
|
||||
|
@ -1066,6 +1082,16 @@ float EntityItem::getRadius() const {
|
|||
return 0.5f * glm::length(_dimensions);
|
||||
}
|
||||
|
||||
bool EntityItem::contains(const glm::vec3& point) const {
|
||||
if (getShapeType() == SHAPE_TYPE_COMPOUND) {
|
||||
return getAABox().contains(point);
|
||||
} else {
|
||||
ShapeInfo info;
|
||||
info.setParams(getShapeType(), glm::vec3(0.5f));
|
||||
return info.contains(worldToEntity(point));
|
||||
}
|
||||
}
|
||||
|
||||
void EntityItem::computeShapeInfo(ShapeInfo& info) {
|
||||
info.setParams(getShapeType(), 0.5f * getDimensions());
|
||||
}
|
||||
|
|
|
@ -145,25 +145,16 @@ public:
|
|||
|
||||
// attributes applicable to all entity types
|
||||
EntityTypes::EntityType getType() const { return _type; }
|
||||
glm::vec3 getPositionInDomainUnits() const { return _position / (float)TREE_SCALE; } /// get position in domain scale units (0.0 - 1.0)
|
||||
const glm::vec3& getPosition() const { return _position; } /// get position in meters
|
||||
|
||||
/// set position in domain scale units (0.0 - 1.0)
|
||||
void setPositionInDomainUnits(const glm::vec3& value)
|
||||
{ setPosition(glm::clamp(value, 0.0f, 1.0f) * (float)TREE_SCALE); }
|
||||
void setPosition(const glm::vec3& value) {
|
||||
_position = value;
|
||||
}
|
||||
|
||||
glm::vec3 getCenterInDomainUnits() const { return getCenter() / (float) TREE_SCALE; }
|
||||
glm::vec3 getCenter() const;
|
||||
|
||||
glm::vec3 getDimensionsInDomainUnits() const { return _dimensions / (float)TREE_SCALE; } /// get dimensions in domain scale units (0.0 - 1.0)
|
||||
const glm::vec3& getDimensions() const { return _dimensions; } /// get dimensions in meters
|
||||
|
||||
/// set dimensions in domain scale units (0.0 - 1.0)
|
||||
virtual void setDimensionsInDomainUnits(const glm::vec3& value) { _dimensions = glm::abs(value) * (float)TREE_SCALE; }
|
||||
|
||||
/// set dimensions in meter units (0.0 - TREE_SCALE)
|
||||
virtual void setDimensions(const glm::vec3& value) { _dimensions = glm::abs(value); }
|
||||
|
||||
|
@ -182,15 +173,11 @@ public:
|
|||
|
||||
float getDensity() const { return _density; }
|
||||
|
||||
glm::vec3 getVelocityInDomainUnits() const { return _velocity / (float)TREE_SCALE; } /// velocity in domain scale units (0.0-1.0) per second
|
||||
const glm::vec3 getVelocity() const { return _velocity; } /// get velocity in meters
|
||||
void setVelocityInDomainUnits(const glm::vec3& value) { _velocity = value * (float)TREE_SCALE; } /// velocity in domain scale units (0.0-1.0) per second
|
||||
void setVelocity(const glm::vec3& value) { _velocity = value; } /// velocity in meters
|
||||
bool hasVelocity() const { return _velocity != ENTITY_ITEM_ZERO_VEC3; }
|
||||
|
||||
glm::vec3 getGravityInDomainUnits() const { return _gravity / (float)TREE_SCALE; } /// gravity in domain scale units (0.0-1.0) per second squared
|
||||
const glm::vec3& getGravity() const { return _gravity; } /// get gravity in meters
|
||||
void setGravityInDomainUnits(const glm::vec3& value) { _gravity = value * (float)TREE_SCALE; } /// gravity in domain scale units (0.0-1.0) per second squared
|
||||
void setGravity(const glm::vec3& value) { _gravity = value; } /// gravity in meters
|
||||
bool hasGravity() const { return _gravity != ENTITY_ITEM_ZERO_VEC3; }
|
||||
|
||||
|
@ -220,7 +207,6 @@ public:
|
|||
AACube getMaximumAACube() const;
|
||||
AACube getMinimumAACube() const;
|
||||
AABox getAABox() const; /// axis aligned bounding box in world-frame (meters)
|
||||
AABox getAABoxInDomainUnits() const; /// axis aligned bounding box in domain scale units (0.0 - 1.0)
|
||||
|
||||
const QString& getScript() const { return _script; }
|
||||
void setScript(const QString& value) { _script = value; }
|
||||
|
@ -267,8 +253,7 @@ public:
|
|||
// TODO: get rid of users of getRadius()...
|
||||
float getRadius() const;
|
||||
|
||||
virtual bool contains(const glm::vec3& point) const { return getAABox().contains(point); }
|
||||
virtual bool containsInDomainUnits(const glm::vec3& point) const { return getAABoxInDomainUnits().contains(point); }
|
||||
virtual bool contains(const glm::vec3& point) const;
|
||||
|
||||
virtual bool isReadyToComputeShape() { return true; }
|
||||
virtual void computeShapeInfo(ShapeInfo& info);
|
||||
|
@ -312,6 +297,11 @@ public:
|
|||
static void setSendPhysicsUpdates(bool value) { _sendPhysicsUpdates = value; }
|
||||
static bool getSendPhysicsUpdates() { return _sendPhysicsUpdates; }
|
||||
|
||||
glm::mat4 getEntityToWorldMatrix() const;
|
||||
glm::mat4 getWorldToEntityMatrix() const;
|
||||
glm::vec3 worldToEntity(const glm::vec3 point) const;
|
||||
glm::vec3 entityToWorld(const glm::vec3 point) const;
|
||||
|
||||
protected:
|
||||
|
||||
static bool _sendPhysicsUpdates;
|
||||
|
|
|
@ -44,7 +44,7 @@ EntityItemProperties::EntityItemProperties() :
|
|||
CONSTRUCT_PROPERTY(script, ENTITY_ITEM_DEFAULT_SCRIPT),
|
||||
CONSTRUCT_PROPERTY(color, ),
|
||||
CONSTRUCT_PROPERTY(modelURL, ""),
|
||||
CONSTRUCT_PROPERTY(collisionModelURL, ""),
|
||||
CONSTRUCT_PROPERTY(compoundShapeURL, ""),
|
||||
CONSTRUCT_PROPERTY(animationURL, ""),
|
||||
CONSTRUCT_PROPERTY(animationFPS, ModelEntityItem::DEFAULT_ANIMATION_FPS),
|
||||
CONSTRUCT_PROPERTY(animationFrameIndex, ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX),
|
||||
|
@ -175,7 +175,7 @@ void EntityItemProperties::debugDump() const {
|
|||
qCDebug(entities) << " _position=" << _position.x << "," << _position.y << "," << _position.z;
|
||||
qCDebug(entities) << " _dimensions=" << getDimensions();
|
||||
qCDebug(entities) << " _modelURL=" << _modelURL;
|
||||
qCDebug(entities) << " _collisionModelURL=" << _collisionModelURL;
|
||||
qCDebug(entities) << " _compoundShapeURL=" << _compoundShapeURL;
|
||||
qCDebug(entities) << " changed properties...";
|
||||
EntityPropertyFlags props = getChangedProperties();
|
||||
props.debugDumpBits();
|
||||
|
@ -245,7 +245,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_SCRIPT, script);
|
||||
CHECK_PROPERTY_CHANGE(PROP_COLOR, color);
|
||||
CHECK_PROPERTY_CHANGE(PROP_MODEL_URL, modelURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_COLLISION_MODEL_URL, collisionModelURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_COMPOUND_SHAPE_URL, compoundShapeURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_URL, animationURL);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_PLAYING, animationIsPlaying);
|
||||
CHECK_PROPERTY_CHANGE(PROP_ANIMATION_FRAME_INDEX, animationFrameIndex);
|
||||
|
@ -322,7 +322,7 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine) cons
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(visible);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_COLOR(color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(modelURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(collisionModelURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(compoundShapeURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationURL);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationIsPlaying);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(animationFPS);
|
||||
|
@ -417,7 +417,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object) {
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(visible, setVisible);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_COLOR(color, setColor);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(modelURL, setModelURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(collisionModelURL, setCollisionModelURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(compoundShapeURL, setCompoundShapeURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_STRING(animationURL, setAnimationURL);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_BOOL(animationIsPlaying, setAnimationIsPlaying);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE_FLOAT(animationFPS, setAnimationFPS);
|
||||
|
@ -618,7 +618,7 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, properties.getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_MODEL_URL, appendValue, properties.getCollisionModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, properties.getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, properties.getAnimationURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, properties.getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, properties.getAnimationFrameIndex());
|
||||
|
@ -657,6 +657,9 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, properties.getStageAltitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, properties.getStageDay());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, properties.getStageHour());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)properties.getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, properties.getCompoundShapeURL());
|
||||
}
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, appendValue, properties.getMarketplaceID());
|
||||
|
@ -864,7 +867,7 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
|
||||
if (properties.getType() == EntityTypes::Model) {
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MODEL_URL, setModelURL);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COLLISION_MODEL_URL, setCollisionModelURL);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_ANIMATION_URL, setAnimationURL);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FPS, float, setAnimationFPS);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_ANIMATION_FRAME_INDEX, float, setAnimationFrameIndex);
|
||||
|
@ -903,6 +906,8 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_ALTITUDE, float, setStageAltitude);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_DAY, quint16, setStageDay);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STAGE_HOUR, float, setStageHour);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE_TYPE, ShapeType, setShapeType);
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_STRING_TO_PROPERTIES(PROP_MARKETPLACE_ID, setMarketplaceID);
|
||||
|
@ -958,7 +963,7 @@ void EntityItemProperties::markAllChanged() {
|
|||
_visibleChanged = true;
|
||||
_colorChanged = true;
|
||||
_modelURLChanged = true;
|
||||
_collisionModelURLChanged = true;
|
||||
_compoundShapeURLChanged = true;
|
||||
_animationURLChanged = true;
|
||||
_animationIsPlayingChanged = true;
|
||||
_animationFrameIndexChanged = true;
|
||||
|
|
|
@ -93,7 +93,7 @@ enum EntityPropertyList {
|
|||
PROP_LOCAL_GRAVITY,
|
||||
PROP_PARTICLE_RADIUS,
|
||||
|
||||
PROP_COLLISION_MODEL_URL,
|
||||
PROP_COMPOUND_SHAPE_URL,
|
||||
PROP_MARKETPLACE_ID,
|
||||
PROP_ACCELERATION,
|
||||
PROP_SIMULATOR_ID,
|
||||
|
@ -197,7 +197,7 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_SCRIPT, Script, script, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_COLOR, Color, color, xColor);
|
||||
DEFINE_PROPERTY_REF(PROP_MODEL_URL, ModelURL, modelURL, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_COLLISION_MODEL_URL, CollisionModelURL, collisionModelURL, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_COMPOUND_SHAPE_URL, CompoundShapeURL, compoundShapeURL, QString);
|
||||
DEFINE_PROPERTY_REF(PROP_ANIMATION_URL, AnimationURL, animationURL, QString);
|
||||
DEFINE_PROPERTY(PROP_ANIMATION_FPS, AnimationFPS, animationFPS, float);
|
||||
DEFINE_PROPERTY(PROP_ANIMATION_FRAME_INDEX, AnimationFrameIndex, animationFrameIndex, float);
|
||||
|
@ -340,7 +340,7 @@ inline QDebug operator<<(QDebug debug, const EntityItemProperties& properties) {
|
|||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Script, script, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, Color, color, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, ModelURL, modelURL, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CollisionModelURL, collisionModelURL, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, CompoundShapeURL, compoundShapeURL, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationURL, animationURL, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFPS, animationFPS, "");
|
||||
DEBUG_PROPERTY_IF_CHANGED(debug, properties, AnimationFrameIndex, animationFrameIndex, "");
|
||||
|
|
|
@ -21,7 +21,7 @@
|
|||
#include "ModelEntityItem.h"
|
||||
|
||||
const QString ModelEntityItem::DEFAULT_MODEL_URL = QString("");
|
||||
const QString ModelEntityItem::DEFAULT_COLLISION_MODEL_URL = QString("");
|
||||
const QString ModelEntityItem::DEFAULT_COMPOUND_SHAPE_URL = QString("");
|
||||
const QString ModelEntityItem::DEFAULT_ANIMATION_URL = QString("");
|
||||
const float ModelEntityItem::DEFAULT_ANIMATION_FRAME_INDEX = 0.0f;
|
||||
const bool ModelEntityItem::DEFAULT_ANIMATION_IS_PLAYING = false;
|
||||
|
@ -47,7 +47,7 @@ EntityItemProperties ModelEntityItem::getProperties() const {
|
|||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getXColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(modelURL, getModelURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(collisionModelURL, getCollisionModelURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationURL, getAnimationURL);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationIsPlaying, getAnimationIsPlaying);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(animationFrameIndex, getAnimationFrameIndex);
|
||||
|
@ -65,7 +65,7 @@ bool ModelEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(modelURL, setModelURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(collisionModelURL, setCollisionModelURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationURL, setAnimationURL);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationIsPlaying, setAnimationIsPlaying);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(animationFrameIndex, setAnimationFrameIndex);
|
||||
|
@ -98,11 +98,11 @@ int ModelEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
READ_ENTITY_PROPERTY_COLOR(PROP_COLOR, _color);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_MODEL_URL, setModelURL);
|
||||
if (args.bitstreamVersion < VERSION_ENTITIES_HAS_COLLISION_MODEL) {
|
||||
setCollisionModelURL("");
|
||||
setCompoundShapeURL("");
|
||||
} else if (args.bitstreamVersion == VERSION_ENTITIES_HAS_COLLISION_MODEL) {
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_COLLISION_MODEL_URL_OLD_VERSION, setCollisionModelURL);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
|
||||
} else {
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_COLLISION_MODEL_URL, setCollisionModelURL);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
|
||||
}
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_ANIMATION_URL, setAnimationURL);
|
||||
|
||||
|
@ -140,7 +140,7 @@ EntityPropertyFlags ModelEntityItem::getEntityProperties(EncodeBitstreamParams&
|
|||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
|
||||
requestedProperties += PROP_MODEL_URL;
|
||||
requestedProperties += PROP_COLLISION_MODEL_URL;
|
||||
requestedProperties += PROP_COMPOUND_SHAPE_URL;
|
||||
requestedProperties += PROP_ANIMATION_URL;
|
||||
requestedProperties += PROP_ANIMATION_FPS;
|
||||
requestedProperties += PROP_ANIMATION_FRAME_INDEX;
|
||||
|
@ -164,7 +164,7 @@ void ModelEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBit
|
|||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, appendColor, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_MODEL_URL, appendValue, getModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_MODEL_URL, appendValue, getCollisionModelURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCompoundShapeURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_URL, appendValue, getAnimationURL());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FPS, appendValue, getAnimationFPS());
|
||||
APPEND_ENTITY_PROPERTY(PROP_ANIMATION_FRAME_INDEX, appendValue, getAnimationFrameIndex());
|
||||
|
@ -272,7 +272,7 @@ void ModelEntityItem::debugDump() const {
|
|||
qCDebug(entities) << " position:" << getPosition();
|
||||
qCDebug(entities) << " dimensions:" << getDimensions();
|
||||
qCDebug(entities) << " model URL:" << getModelURL();
|
||||
qCDebug(entities) << " collision model URL:" << getCollisionModelURL();
|
||||
qCDebug(entities) << " compound shape URL:" << getCompoundShapeURL();
|
||||
}
|
||||
|
||||
void ModelEntityItem::updateShapeType(ShapeType type) {
|
||||
|
@ -280,8 +280,8 @@ void ModelEntityItem::updateShapeType(ShapeType type) {
|
|||
// we have allowed inconsistent ShapeType's to be stored in SVO files in the past (this was a bug)
|
||||
// but we are now enforcing the entity properties to be consistent. To make the possible we're
|
||||
// introducing a temporary workaround: we will ignore ShapeType updates that conflict with the
|
||||
// _collisionModelURL.
|
||||
if (hasCollisionModel()) {
|
||||
// _compoundShapeURL.
|
||||
if (hasCompoundShapeURL()) {
|
||||
type = SHAPE_TYPE_COMPOUND;
|
||||
}
|
||||
// END_TEMPORARY_WORKAROUND
|
||||
|
@ -295,17 +295,17 @@ void ModelEntityItem::updateShapeType(ShapeType type) {
|
|||
// virtual
|
||||
ShapeType ModelEntityItem::getShapeType() const {
|
||||
if (_shapeType == SHAPE_TYPE_COMPOUND) {
|
||||
return hasCollisionModel() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE;
|
||||
return hasCompoundShapeURL() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE;
|
||||
} else {
|
||||
return _shapeType;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelEntityItem::setCollisionModelURL(const QString& url) {
|
||||
if (_collisionModelURL != url) {
|
||||
_collisionModelURL = url;
|
||||
void ModelEntityItem::setCompoundShapeURL(const QString& url) {
|
||||
if (_compoundShapeURL != url) {
|
||||
_compoundShapeURL = url;
|
||||
_dirtyFlags |= EntityItem::DIRTY_SHAPE | EntityItem::DIRTY_MASS;
|
||||
_shapeType = _collisionModelURL.isEmpty() ? SHAPE_TYPE_NONE : SHAPE_TYPE_COMPOUND;
|
||||
_shapeType = _compoundShapeURL.isEmpty() ? SHAPE_TYPE_NONE : SHAPE_TYPE_COMPOUND;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -57,13 +57,13 @@ public:
|
|||
const rgbColor& getColor() const { return _color; }
|
||||
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
||||
bool hasModel() const { return !_modelURL.isEmpty(); }
|
||||
virtual bool hasCollisionModel() const { return !_collisionModelURL.isEmpty(); }
|
||||
virtual bool hasCompoundShapeURL() const { return !_compoundShapeURL.isEmpty(); }
|
||||
|
||||
static const QString DEFAULT_MODEL_URL;
|
||||
const QString& getModelURL() const { return _modelURL; }
|
||||
|
||||
static const QString DEFAULT_COLLISION_MODEL_URL;
|
||||
const QString& getCollisionModelURL() const { return _collisionModelURL; }
|
||||
static const QString DEFAULT_COMPOUND_SHAPE_URL;
|
||||
const QString& getCompoundShapeURL() const { return _compoundShapeURL; }
|
||||
|
||||
bool hasAnimation() const { return !_animationURL.isEmpty(); }
|
||||
static const QString DEFAULT_ANIMATION_URL;
|
||||
|
@ -78,7 +78,7 @@ public:
|
|||
|
||||
// model related properties
|
||||
void setModelURL(const QString& url) { _modelURL = url; }
|
||||
virtual void setCollisionModelURL(const QString& url);
|
||||
virtual void setCompoundShapeURL(const QString& url);
|
||||
void setAnimationURL(const QString& url);
|
||||
static const float DEFAULT_ANIMATION_FRAME_INDEX;
|
||||
void setAnimationFrameIndex(float value);
|
||||
|
@ -126,7 +126,7 @@ protected:
|
|||
|
||||
rgbColor _color;
|
||||
QString _modelURL;
|
||||
QString _collisionModelURL;
|
||||
QString _compoundShapeURL;
|
||||
|
||||
quint64 _lastAnimated;
|
||||
QString _animationURL;
|
||||
|
|
|
@ -96,11 +96,7 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons
|
|||
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||
void** intersectedObject, bool precisionPicking) const {
|
||||
// determine the ray in the frame of the entity transformed from a unit sphere
|
||||
glm::mat4 translation = glm::translate(getPosition());
|
||||
glm::mat4 rotation = glm::mat4_cast(getRotation());
|
||||
glm::mat4 scale = glm::scale(getDimensions());
|
||||
glm::mat4 registration = glm::translate(glm::vec3(0.5f, 0.5f, 0.5f) - getRegistrationPoint());
|
||||
glm::mat4 entityToWorldMatrix = translation * rotation * scale * registration;
|
||||
glm::mat4 entityToWorldMatrix = getEntityToWorldMatrix();
|
||||
glm::mat4 worldToEntityMatrix = glm::inverse(entityToWorldMatrix);
|
||||
glm::vec3 entityFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f));
|
||||
glm::vec3 entityFrameDirection = glm::normalize(glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f)));
|
||||
|
@ -112,7 +108,7 @@ bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, cons
|
|||
glm::vec3 entityFrameHitAt = entityFrameOrigin + (entityFrameDirection * localDistance);
|
||||
// then translate back to work coordinates
|
||||
glm::vec3 hitAt = glm::vec3(entityToWorldMatrix * glm::vec4(entityFrameHitAt, 1.0f));
|
||||
distance = glm::distance(origin,hitAt);
|
||||
distance = glm::distance(origin, hitAt);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
|
|
@ -50,9 +50,6 @@ public:
|
|||
_color[BLUE_INDEX] = value.blue;
|
||||
}
|
||||
|
||||
// TODO: implement proper contains for 3D ellipsoid
|
||||
//virtual bool contains(const glm::vec3& point) const;
|
||||
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_SPHERE; }
|
||||
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
|
|
|
@ -48,11 +48,6 @@ void TextEntityItem::setDimensions(const glm::vec3& value) {
|
|||
_dimensions = glm::vec3(value.x, value.y, TEXT_ENTITY_ITEM_FIXED_DEPTH);
|
||||
}
|
||||
|
||||
void TextEntityItem::setDimensionsInDomainUnits(const glm::vec3& value) {
|
||||
// NOTE: Text Entities always have a "depth" of 1cm.
|
||||
_dimensions = glm::vec3(value.x * (float)TREE_SCALE, value.y * (float)TREE_SCALE, TEXT_ENTITY_ITEM_FIXED_DEPTH);
|
||||
}
|
||||
|
||||
EntityItemProperties TextEntityItem::getProperties() const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(); // get the properties from our base class
|
||||
|
||||
|
|
|
@ -24,7 +24,6 @@ public:
|
|||
|
||||
/// set dimensions in domain scale units (0.0 - 1.0) this will also reset radius appropriately
|
||||
virtual void setDimensions(const glm::vec3& value);
|
||||
virtual void setDimensionsInDomainUnits(const glm::vec3& value);
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
|
|
|
@ -31,6 +31,8 @@ const float ZoneEntityItem::DEFAULT_STAGE_LONGITUDE = 122.407f;
|
|||
const float ZoneEntityItem::DEFAULT_STAGE_ALTITUDE = 0.03f;
|
||||
const quint16 ZoneEntityItem::DEFAULT_STAGE_DAY = 60;
|
||||
const float ZoneEntityItem::DEFAULT_STAGE_HOUR = 12.0f;
|
||||
const ShapeType ZoneEntityItem::DEFAULT_SHAPE_TYPE = SHAPE_TYPE_BOX;
|
||||
const QString ZoneEntityItem::DEFAULT_COMPOUND_SHAPE_URL = "";
|
||||
|
||||
EntityItem* ZoneEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItem* result = new ZoneEntityItem(entityID, properties);
|
||||
|
@ -56,6 +58,8 @@ ZoneEntityItem::ZoneEntityItem(const EntityItemID& entityItemID, const EntityIte
|
|||
_stageAltitude = DEFAULT_STAGE_ALTITUDE;
|
||||
_stageDay = DEFAULT_STAGE_DAY;
|
||||
_stageHour = DEFAULT_STAGE_HOUR;
|
||||
_shapeType = DEFAULT_SHAPE_TYPE;
|
||||
_compoundShapeURL = DEFAULT_COMPOUND_SHAPE_URL;
|
||||
|
||||
setProperties(properties);
|
||||
}
|
||||
|
@ -73,6 +77,8 @@ EntityItemProperties ZoneEntityItem::getProperties() const {
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageAltitude, getStageAltitude);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageDay, getStageDay);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(stageHour, getStageHour);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(shapeType, getShapeType);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(compoundShapeURL, getCompoundShapeURL);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
@ -91,6 +97,8 @@ bool ZoneEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageAltitude, setStageAltitude);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageDay, setStageDay);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(stageHour, setStageHour);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shapeType, updateShapeType);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(compoundShapeURL, setCompoundShapeURL);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -122,6 +130,8 @@ int ZoneEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data,
|
|||
READ_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, float, _stageAltitude);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_DAY, quint16, _stageDay);
|
||||
READ_ENTITY_PROPERTY(PROP_STAGE_HOUR, float, _stageHour);
|
||||
READ_ENTITY_PROPERTY_SETTER(PROP_SHAPE_TYPE, ShapeType, updateShapeType);
|
||||
READ_ENTITY_PROPERTY_STRING(PROP_COMPOUND_SHAPE_URL, setCompoundShapeURL);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -141,6 +151,8 @@ EntityPropertyFlags ZoneEntityItem::getEntityProperties(EncodeBitstreamParams& p
|
|||
requestedProperties += PROP_STAGE_ALTITUDE;
|
||||
requestedProperties += PROP_STAGE_DAY;
|
||||
requestedProperties += PROP_STAGE_HOUR;
|
||||
requestedProperties += PROP_SHAPE_TYPE;
|
||||
requestedProperties += PROP_COMPOUND_SHAPE_URL;
|
||||
|
||||
return requestedProperties;
|
||||
}
|
||||
|
@ -165,6 +177,8 @@ void ZoneEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBits
|
|||
APPEND_ENTITY_PROPERTY(PROP_STAGE_ALTITUDE, appendValue, getStageAltitude());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_DAY, appendValue, getStageDay());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STAGE_HOUR, appendValue, getStageHour());
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE_TYPE, appendValue, (uint32_t)getShapeType());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COMPOUND_SHAPE_URL, appendValue, getCompoundShapeURL());
|
||||
}
|
||||
|
||||
void ZoneEntityItem::debugDump() const {
|
||||
|
@ -185,6 +199,23 @@ void ZoneEntityItem::debugDump() const {
|
|||
qCDebug(entities) << " _stageHour:" << _stageHour;
|
||||
}
|
||||
|
||||
ShapeType ZoneEntityItem::getShapeType() const {
|
||||
if (_shapeType == SHAPE_TYPE_COMPOUND) {
|
||||
return hasCompoundShapeURL() ? SHAPE_TYPE_COMPOUND : SHAPE_TYPE_NONE;
|
||||
} else {
|
||||
return _shapeType;
|
||||
}
|
||||
}
|
||||
|
||||
void ZoneEntityItem::setCompoundShapeURL(const QString& url) {
|
||||
_compoundShapeURL = url;
|
||||
if (!_compoundShapeURL.isEmpty()) {
|
||||
updateShapeType(SHAPE_TYPE_COMPOUND);
|
||||
} else if (_shapeType == SHAPE_TYPE_COMPOUND) {
|
||||
_shapeType = DEFAULT_SHAPE_TYPE;
|
||||
}
|
||||
}
|
||||
|
||||
bool ZoneEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElement*& element, float& distance, BoxFace& face,
|
||||
void** intersectedObject, bool precisionPicking) const {
|
||||
|
|
|
@ -91,6 +91,14 @@ public:
|
|||
|
||||
static bool getZonesArePickable() { return _zonesArePickable; }
|
||||
static void setZonesArePickable(bool value) { _zonesArePickable = value; }
|
||||
|
||||
virtual bool isReadyToComputeShape() { return false; }
|
||||
void updateShapeType(ShapeType type) { _shapeType = type; }
|
||||
virtual ShapeType getShapeType() const;
|
||||
|
||||
virtual bool hasCompoundShapeURL() const { return !_compoundShapeURL.isEmpty(); }
|
||||
const QString getCompoundShapeURL() const { return _compoundShapeURL; }
|
||||
virtual void setCompoundShapeURL(const QString& url);
|
||||
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
|
@ -109,6 +117,8 @@ public:
|
|||
static const float DEFAULT_STAGE_ALTITUDE;
|
||||
static const quint16 DEFAULT_STAGE_DAY;
|
||||
static const float DEFAULT_STAGE_HOUR;
|
||||
static const ShapeType DEFAULT_SHAPE_TYPE;
|
||||
static const QString DEFAULT_COMPOUND_SHAPE_URL;
|
||||
|
||||
protected:
|
||||
// properties of the "sun" in the zone
|
||||
|
@ -122,6 +132,9 @@ protected:
|
|||
float _stageAltitude;
|
||||
uint16_t _stageDay;
|
||||
float _stageHour;
|
||||
|
||||
ShapeType _shapeType = SHAPE_TYPE_NONE;
|
||||
QString _compoundShapeURL;
|
||||
|
||||
static bool _zonesArePickable;
|
||||
};
|
||||
|
|
|
@ -125,6 +125,51 @@ Extents FBXGeometry::getUnscaledMeshExtents() const {
|
|||
return scaledExtents;
|
||||
}
|
||||
|
||||
// TODO: Move to model::Mesh when Sam's ready
|
||||
bool FBXGeometry::convexHullContains(const glm::vec3& point) const {
|
||||
if (!getUnscaledMeshExtents().containsPoint(point)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto checkEachPrimitive = [=](FBXMesh& mesh, QVector<int> indices, int primitiveSize) -> bool {
|
||||
// Check whether the point is "behind" all the primitives.
|
||||
for (unsigned int j = 0; j < indices.size(); j += primitiveSize) {
|
||||
if (!isPointBehindTrianglesPlane(point,
|
||||
mesh.vertices[indices[j]],
|
||||
mesh.vertices[indices[j + 1]],
|
||||
mesh.vertices[indices[j + 2]])) {
|
||||
// it's not behind at least one so we bail
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
};
|
||||
|
||||
// Check that the point is contained in at least one convex mesh.
|
||||
for (auto mesh : meshes) {
|
||||
bool insideMesh = true;
|
||||
|
||||
// To be considered inside a convex mesh,
|
||||
// the point needs to be "behind" all the primitives respective planes.
|
||||
for (auto part : mesh.parts) {
|
||||
// run through all the triangles and quads
|
||||
if (!checkEachPrimitive(mesh, part.triangleIndices, 3) ||
|
||||
!checkEachPrimitive(mesh, part.quadIndices, 4)) {
|
||||
// If not, the point is outside, bail for this mesh
|
||||
insideMesh = false;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (insideMesh) {
|
||||
// It's inside this mesh, return true.
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
// It wasn't in any mesh, return false.
|
||||
return false;
|
||||
}
|
||||
|
||||
QString FBXGeometry::getModelNameOfMesh(int meshIndex) const {
|
||||
if (meshIndicesToModelNames.contains(meshIndex)) {
|
||||
return meshIndicesToModelNames.value(meshIndex);
|
||||
|
@ -132,8 +177,6 @@ QString FBXGeometry::getModelNameOfMesh(int meshIndex) const {
|
|||
return QString();
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int fbxGeometryMetaTypeId = qRegisterMetaType<FBXGeometry>();
|
||||
static int fbxAnimationFrameMetaTypeId = qRegisterMetaType<FBXAnimationFrame>();
|
||||
static int fbxAnimationFrameVectorMetaTypeId = qRegisterMetaType<QVector<FBXAnimationFrame> >();
|
||||
|
|
|
@ -252,6 +252,7 @@ public:
|
|||
/// Returns the unscaled extents of the model's mesh
|
||||
Extents getUnscaledMeshExtents() const;
|
||||
|
||||
bool convexHullContains(const glm::vec3& point) const;
|
||||
|
||||
QHash<int, QString> meshIndicesToModelNames;
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ PacketVersion versionForPacketType(PacketType type) {
|
|||
return 1;
|
||||
case PacketTypeEntityAddOrEdit:
|
||||
case PacketTypeEntityData:
|
||||
return VERSION_ENTITIES_ZONE_ENTITIES_EXIST;
|
||||
return VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE;
|
||||
case PacketTypeEntityErase:
|
||||
return 2;
|
||||
case PacketTypeAudioStreamStats:
|
||||
|
|
|
@ -138,5 +138,6 @@ const PacketVersion VERSION_ENTITIES_HAS_MARKETPLACE_ID = 14;
|
|||
const PacketVersion VERSION_ENTITIES_HAVE_ACCELERATION = 15;
|
||||
const PacketVersion VERSION_ENTITIES_HAVE_UUIDS = 16;
|
||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_EXIST = 17;
|
||||
const PacketVersion VERSION_ENTITIES_ZONE_ENTITIES_HAVE_DYNAMIC_SHAPE = 18;
|
||||
|
||||
#endif // hifi_PacketHeaders_h
|
||||
|
|
|
@ -203,6 +203,13 @@ glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2) {
|
|||
return glm::angleAxis(angle, axis);
|
||||
}
|
||||
|
||||
bool isPointBehindTrianglesPlane(glm::vec3 point, glm::vec3 p0, glm::vec3 p1, glm::vec3 p2) {
|
||||
glm::vec3 v1 = p0 - p1, v2 = p2 - p1; // Non-collinear vectors contained in the plane
|
||||
glm::vec3 n = glm::cross(v1, v2); // Plane's normal vector, pointing out of the triangle
|
||||
float d = -glm::dot(n, p0); // Compute plane's equation constant
|
||||
return (glm::dot(n, point) + d) >= 0;
|
||||
}
|
||||
|
||||
glm::vec3 extractTranslation(const glm::mat4& matrix) {
|
||||
return glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]);
|
||||
}
|
||||
|
|
|
@ -82,6 +82,8 @@ float angleBetween(const glm::vec3& v1, const glm::vec3& v2);
|
|||
|
||||
glm::quat rotationBetween(const glm::vec3& v1, const glm::vec3& v2);
|
||||
|
||||
bool isPointBehindTrianglesPlane(glm::vec3 point, glm::vec3 p0, glm::vec3 p1, glm::vec3 p2);
|
||||
|
||||
glm::vec3 extractTranslation(const glm::mat4& matrix);
|
||||
|
||||
void setTranslation(glm::mat4& matrix, const glm::vec3& translation);
|
||||
|
|
|
@ -114,7 +114,7 @@ float ShapeInfo::computeVolume() const {
|
|||
}
|
||||
case SHAPE_TYPE_CAPSULE_Y: {
|
||||
float radius = _halfExtents.x;
|
||||
volume = PI * radius * radius * (2.0f * _halfExtents.y + 4.0f * radius / 3.0f);
|
||||
volume = PI * radius * radius * (2.0f * (_halfExtents.y - _halfExtents.x) + 4.0f * radius / 3.0f);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
|
@ -124,6 +124,54 @@ float ShapeInfo::computeVolume() const {
|
|||
return volume;
|
||||
}
|
||||
|
||||
bool ShapeInfo::contains(const glm::vec3& point) const {
|
||||
switch(_type) {
|
||||
case SHAPE_TYPE_SPHERE:
|
||||
return glm::length(point) <= _halfExtents.x;
|
||||
case SHAPE_TYPE_ELLIPSOID: {
|
||||
glm::vec3 scaledPoint = glm::abs(point) / _halfExtents;
|
||||
return glm::length(scaledPoint) <= 1.0f;
|
||||
}
|
||||
case SHAPE_TYPE_CYLINDER_X:
|
||||
return glm::length(glm::vec2(point.y, point.z)) <= _halfExtents.z;
|
||||
case SHAPE_TYPE_CYLINDER_Y:
|
||||
return glm::length(glm::vec2(point.x, point.z)) <= _halfExtents.x;
|
||||
case SHAPE_TYPE_CYLINDER_Z:
|
||||
return glm::length(glm::vec2(point.x, point.y)) <= _halfExtents.y;
|
||||
case SHAPE_TYPE_CAPSULE_X: {
|
||||
if (glm::abs(point.x) <= _halfExtents.x) {
|
||||
return glm::length(glm::vec2(point.y, point.z)) <= _halfExtents.z;
|
||||
} else {
|
||||
glm::vec3 absPoint = glm::abs(point) - _halfExtents.x;
|
||||
return glm::length(absPoint) <= _halfExtents.z;
|
||||
}
|
||||
}
|
||||
case SHAPE_TYPE_CAPSULE_Y: {
|
||||
if (glm::abs(point.y) <= _halfExtents.y) {
|
||||
return glm::length(glm::vec2(point.x, point.z)) <= _halfExtents.x;
|
||||
} else {
|
||||
glm::vec3 absPoint = glm::abs(point) - _halfExtents.y;
|
||||
return glm::length(absPoint) <= _halfExtents.x;
|
||||
}
|
||||
}
|
||||
case SHAPE_TYPE_CAPSULE_Z: {
|
||||
if (glm::abs(point.z) <= _halfExtents.z) {
|
||||
return glm::length(glm::vec2(point.x, point.y)) <= _halfExtents.y;
|
||||
} else {
|
||||
glm::vec3 absPoint = glm::abs(point) - _halfExtents.z;
|
||||
return glm::length(absPoint) <= _halfExtents.y;
|
||||
}
|
||||
}
|
||||
case SHAPE_TYPE_BOX:
|
||||
default: {
|
||||
glm::vec3 absPoint = glm::abs(point);
|
||||
return absPoint.x <= _halfExtents.x
|
||||
&& absPoint.y <= _halfExtents.y
|
||||
&& absPoint.z <= _halfExtents.z;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const DoubleHashKey& ShapeInfo::getHash() const {
|
||||
// NOTE: we cache the key so we only ever need to compute it once for any valid ShapeInfo instance.
|
||||
if (_doubleHashKey.isNull() && _type != SHAPE_TYPE_NONE) {
|
||||
|
|
|
@ -57,6 +57,10 @@ public:
|
|||
void appendToPoints (const QVector<glm::vec3>& newPoints) { _points << newPoints; }
|
||||
|
||||
float computeVolume() const;
|
||||
|
||||
/// Returns whether point is inside the shape
|
||||
/// For compound shapes it will only return whether it is inside the bounding box
|
||||
bool contains(const glm::vec3& point) const;
|
||||
|
||||
const DoubleHashKey& getHash() const;
|
||||
|
||||
|
|
|
@ -74,7 +74,7 @@ void OctreeTests::propertyFlagsTests(bool verbose) {
|
|||
props.setHasProperty(PROP_POSITION);
|
||||
props.setHasProperty(PROP_RADIUS);
|
||||
props.setHasProperty(PROP_MODEL_URL);
|
||||
props.setHasProperty(PROP_COLLISION_MODEL_URL);
|
||||
props.setHasProperty(PROP_COMPOUND_SHAPE_URL);
|
||||
props.setHasProperty(PROP_ROTATION);
|
||||
|
||||
QByteArray encoded = props.encode();
|
||||
|
|
Loading…
Reference in a new issue