mirror of
https://github.com/JulianGro/overte.git
synced 2025-04-08 06:22:14 +02:00
Add a generic shape primitive
This commit is contained in:
parent
e07674134f
commit
cd1e910844
25 changed files with 819 additions and 791 deletions
|
@ -29,17 +29,16 @@
|
|||
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
#include "RenderableBoxEntityItem.h"
|
||||
#include "RenderableLightEntityItem.h"
|
||||
#include "RenderableModelEntityItem.h"
|
||||
#include "RenderableParticleEffectEntityItem.h"
|
||||
#include "RenderableSphereEntityItem.h"
|
||||
#include "RenderableTextEntityItem.h"
|
||||
#include "RenderableWebEntityItem.h"
|
||||
#include "RenderableZoneEntityItem.h"
|
||||
#include "RenderableLineEntityItem.h"
|
||||
#include "RenderablePolyVoxEntityItem.h"
|
||||
#include "RenderablePolyLineEntityItem.h"
|
||||
#include "RenderableShapeEntityItem.h"
|
||||
#include "EntitiesRendererLogging.h"
|
||||
#include "AddressManager.h"
|
||||
#include <Rig.h>
|
||||
|
@ -56,8 +55,6 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
|||
_dontDoPrecisionPicking(false)
|
||||
{
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Model, RenderableModelEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, RenderableBoxEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableSphereEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Light, RenderableLightEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Text, RenderableTextEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Web, RenderableWebEntityItem::factory)
|
||||
|
@ -66,7 +63,10 @@ EntityTreeRenderer::EntityTreeRenderer(bool wantScripts, AbstractViewStateInterf
|
|||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Line, RenderableLineEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(PolyVox, RenderablePolyVoxEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(PolyLine, RenderablePolyLineEntityItem::factory)
|
||||
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Shape, RenderableShapeEntityItem::factory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, RenderableShapeEntityItem::boxFactory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, RenderableShapeEntityItem::sphereFactory)
|
||||
|
||||
_currentHoverOverEntityID = UNKNOWN_ENTITY_ID;
|
||||
_currentClickingOnEntityID = UNKNOWN_ENTITY_ID;
|
||||
}
|
||||
|
|
|
@ -1,76 +0,0 @@
|
|||
//
|
||||
// RenderableBoxEntityItem.cpp
|
||||
// libraries/entities-renderer/src/
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/6/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
|
||||
//
|
||||
|
||||
#include "RenderableBoxEntityItem.h"
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
|
||||
#include <GeometryCache.h>
|
||||
#include <ObjectMotionState.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include <render-utils/simple_vert.h>
|
||||
#include <render-utils/simple_frag.h>
|
||||
|
||||
EntityItemPointer RenderableBoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity{ new RenderableBoxEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
void RenderableBoxEntityItem::setUserData(const QString& value) {
|
||||
if (value != getUserData()) {
|
||||
BoxEntityItem::setUserData(value);
|
||||
if (_procedural) {
|
||||
_procedural->parse(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableBoxEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableBoxEntityItem::render");
|
||||
Q_ASSERT(getType() == EntityTypes::Box);
|
||||
Q_ASSERT(args->_batch);
|
||||
|
||||
if (!_procedural) {
|
||||
_procedural.reset(new Procedural(this->getUserData()));
|
||||
_procedural->_vertexSource = simple_vert;
|
||||
_procedural->_fragmentSource = simple_frag;
|
||||
_procedural->_state->setCullMode(gpu::State::CULL_NONE);
|
||||
_procedural->_state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
_procedural->_state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
}
|
||||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
glm::vec4 cubeColor(toGlm(getXColor()), getLocalRenderAlpha());
|
||||
|
||||
bool success;
|
||||
auto transToCenter = getTransformToCenter(success);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
|
||||
batch.setModelTransform(transToCenter); // we want to include the scale as well
|
||||
if (_procedural->ready()) {
|
||||
_procedural->prepare(batch, getPosition(), getDimensions());
|
||||
auto color = _procedural->getColor(cubeColor);
|
||||
batch._glColor4f(color.r, color.g, color.b, color.a);
|
||||
DependencyManager::get<GeometryCache>()->renderCube(batch);
|
||||
} else {
|
||||
DependencyManager::get<GeometryCache>()->renderSolidCubeInstance(batch, cubeColor);
|
||||
}
|
||||
static const auto triCount = DependencyManager::get<GeometryCache>()->getCubeTriangleCount();
|
||||
args->_details._trianglesRendered += (int)triCount;
|
||||
}
|
|
@ -1,34 +0,0 @@
|
|||
//
|
||||
// RenderableBoxEntityItem.h
|
||||
// libraries/entities-renderer/src/
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/6/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
|
||||
//
|
||||
|
||||
#ifndef hifi_RenderableBoxEntityItem_h
|
||||
#define hifi_RenderableBoxEntityItem_h
|
||||
|
||||
#include <BoxEntityItem.h>
|
||||
#include <procedural/Procedural.h>
|
||||
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
class RenderableBoxEntityItem : public BoxEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
RenderableBoxEntityItem(const EntityItemID& entityItemID) : BoxEntityItem(entityItemID) { }
|
||||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual void setUserData(const QString& value) override;
|
||||
|
||||
SIMPLE_RENDERABLE()
|
||||
private:
|
||||
QSharedPointer<Procedural> _procedural;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_RenderableBoxEntityItem_h
|
113
libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
Normal file
113
libraries/entities-renderer/src/RenderableShapeEntityItem.cpp
Normal file
|
@ -0,0 +1,113 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/05/09
|
||||
// Copyright 2013 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 "RenderableShapeEntityItem.h"
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include <render-utils/simple_vert.h>
|
||||
#include <render-utils/simple_frag.h>
|
||||
|
||||
// Sphere entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1
|
||||
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
||||
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
||||
|
||||
static GeometryCache::Shape MAPPING[entity::NUM_SHAPES] = {
|
||||
GeometryCache::Triangle,
|
||||
GeometryCache::Quad,
|
||||
GeometryCache::Circle,
|
||||
GeometryCache::Cube,
|
||||
GeometryCache::Sphere,
|
||||
GeometryCache::Tetrahedron,
|
||||
GeometryCache::Octahetron,
|
||||
GeometryCache::Dodecahedron,
|
||||
GeometryCache::Icosahedron,
|
||||
GeometryCache::Torus,
|
||||
GeometryCache::Cone,
|
||||
GeometryCache::Cylinder,
|
||||
};
|
||||
|
||||
|
||||
RenderableShapeEntityItem::Pointer RenderableShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
Pointer entity = std::make_shared<RenderableShapeEntityItem>(entityID);
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
EntityItemPointer RenderableShapeEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return baseFactory(entityID, properties);
|
||||
}
|
||||
|
||||
EntityItemPointer RenderableShapeEntityItem::boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
auto result = baseFactory(entityID, properties);
|
||||
result->setShape(entity::Cube);
|
||||
return result;
|
||||
}
|
||||
|
||||
EntityItemPointer RenderableShapeEntityItem::sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
auto result = baseFactory(entityID, properties);
|
||||
result->setShape(entity::Sphere);
|
||||
return result;
|
||||
}
|
||||
|
||||
void RenderableShapeEntityItem::setUserData(const QString& value) {
|
||||
if (value != getUserData()) {
|
||||
ShapeEntityItem::setUserData(value);
|
||||
if (_procedural) {
|
||||
_procedural->parse(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableShapeEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableShapeEntityItem::render");
|
||||
//Q_ASSERT(getType() == EntityTypes::Shape);
|
||||
Q_ASSERT(args->_batch);
|
||||
|
||||
if (!_procedural) {
|
||||
_procedural.reset(new Procedural(getUserData()));
|
||||
_procedural->_vertexSource = simple_vert;
|
||||
_procedural->_fragmentSource = simple_frag;
|
||||
_procedural->_state->setCullMode(gpu::State::CULL_NONE);
|
||||
_procedural->_state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
_procedural->_state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
}
|
||||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
glm::vec4 color(toGlm(getXColor()), getLocalRenderAlpha());
|
||||
bool success;
|
||||
Transform modelTransform = getTransformToCenter(success);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
if (_shape != entity::Cube) {
|
||||
modelTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
}
|
||||
batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation
|
||||
if (_procedural->ready()) {
|
||||
_procedural->prepare(batch, getPosition(), getDimensions());
|
||||
auto outColor = _procedural->getColor(color);
|
||||
batch._glColor4f(outColor.r, outColor.g, outColor.b, outColor.a);
|
||||
DependencyManager::get<GeometryCache>()->renderShape(batch, MAPPING[_shape]);
|
||||
} else {
|
||||
// FIXME, support instanced multi-shape rendering using multidraw indirect
|
||||
DependencyManager::get<GeometryCache>()->renderSolidShapeInstance(batch, MAPPING[_shape], color);
|
||||
}
|
||||
|
||||
|
||||
static const auto triCount = DependencyManager::get<GeometryCache>()->getShapeTriangleCount(MAPPING[_shape]);
|
||||
args->_details._trianglesRendered += (int)triCount;
|
||||
}
|
36
libraries/entities-renderer/src/RenderableShapeEntityItem.h
Normal file
36
libraries/entities-renderer/src/RenderableShapeEntityItem.h
Normal file
|
@ -0,0 +1,36 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/05/09
|
||||
// Copyright 2013 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_RenderableShapeEntityItem_h
|
||||
#define hifi_RenderableShapeEntityItem_h
|
||||
|
||||
#include <ShapeEntityItem.h>
|
||||
#include <procedural/Procedural.h>
|
||||
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
class RenderableShapeEntityItem : public ShapeEntityItem {
|
||||
using Pointer = std::shared_ptr<RenderableShapeEntityItem>;
|
||||
static Pointer baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
RenderableShapeEntityItem(const EntityItemID& entityItemID) : ShapeEntityItem(entityItemID) {}
|
||||
|
||||
void render(RenderArgs* args) override;
|
||||
void setUserData(const QString& value) override;
|
||||
|
||||
SIMPLE_RENDERABLE();
|
||||
|
||||
private:
|
||||
QSharedPointer<Procedural> _procedural;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_RenderableShapeEntityItem_h
|
|
@ -1,80 +0,0 @@
|
|||
//
|
||||
// RenderableSphereEntityItem.cpp
|
||||
// interface/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/6/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
|
||||
//
|
||||
|
||||
#include "RenderableSphereEntityItem.h"
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
#include <render-utils/simple_vert.h>
|
||||
#include <render-utils/simple_frag.h>
|
||||
|
||||
// Sphere entities should fit inside a cube entity of the same size, so a sphere that has dimensions 1x1x1
|
||||
// is a half unit sphere. However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
||||
static const float SPHERE_ENTITY_SCALE = 0.5f;
|
||||
|
||||
|
||||
EntityItemPointer RenderableSphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity{ new RenderableSphereEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
void RenderableSphereEntityItem::setUserData(const QString& value) {
|
||||
if (value != getUserData()) {
|
||||
SphereEntityItem::setUserData(value);
|
||||
if (_procedural) {
|
||||
_procedural->parse(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RenderableSphereEntityItem::render(RenderArgs* args) {
|
||||
PerformanceTimer perfTimer("RenderableSphereEntityItem::render");
|
||||
Q_ASSERT(getType() == EntityTypes::Sphere);
|
||||
Q_ASSERT(args->_batch);
|
||||
|
||||
if (!_procedural) {
|
||||
_procedural.reset(new Procedural(getUserData()));
|
||||
_procedural->_vertexSource = simple_vert;
|
||||
_procedural->_fragmentSource = simple_frag;
|
||||
_procedural->_state->setCullMode(gpu::State::CULL_NONE);
|
||||
_procedural->_state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
_procedural->_state->setBlendFunction(false,
|
||||
gpu::State::SRC_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::INV_SRC_ALPHA,
|
||||
gpu::State::FACTOR_ALPHA, gpu::State::BLEND_OP_ADD, gpu::State::ONE);
|
||||
}
|
||||
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
glm::vec4 sphereColor(toGlm(getXColor()), getLocalRenderAlpha());
|
||||
bool success;
|
||||
Transform modelTransform = getTransformToCenter(success);
|
||||
if (!success) {
|
||||
return;
|
||||
}
|
||||
modelTransform.postScale(SPHERE_ENTITY_SCALE);
|
||||
batch.setModelTransform(modelTransform); // use a transform with scale, rotation, registration point and translation
|
||||
if (_procedural->ready()) {
|
||||
_procedural->prepare(batch, getPosition(), getDimensions());
|
||||
auto color = _procedural->getColor(sphereColor);
|
||||
batch._glColor4f(color.r, color.g, color.b, color.a);
|
||||
DependencyManager::get<GeometryCache>()->renderSphere(batch);
|
||||
} else {
|
||||
DependencyManager::get<GeometryCache>()->renderSolidSphereInstance(batch, sphereColor);
|
||||
}
|
||||
static const auto triCount = DependencyManager::get<GeometryCache>()->getSphereTriangleCount();
|
||||
args->_details._trianglesRendered += (int)triCount;
|
||||
}
|
|
@ -1,35 +0,0 @@
|
|||
//
|
||||
// RenderableSphereEntityItem.h
|
||||
// interface/src/entities
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 8/6/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
|
||||
//
|
||||
|
||||
#ifndef hifi_RenderableSphereEntityItem_h
|
||||
#define hifi_RenderableSphereEntityItem_h
|
||||
|
||||
#include <SphereEntityItem.h>
|
||||
#include <procedural/Procedural.h>
|
||||
|
||||
#include "RenderableEntityItem.h"
|
||||
|
||||
class RenderableSphereEntityItem : public SphereEntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
RenderableSphereEntityItem(const EntityItemID& entityItemID) : SphereEntityItem(entityItemID) { }
|
||||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual void setUserData(const QString& value) override;
|
||||
|
||||
SIMPLE_RENDERABLE();
|
||||
|
||||
private:
|
||||
QSharedPointer<Procedural> _procedural;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_RenderableSphereEntityItem_h
|
|
@ -1,103 +0,0 @@
|
|||
//
|
||||
// BoxEntityItem.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/4/13.
|
||||
// Copyright 2013 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 <QDebug>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
|
||||
#include "BoxEntityItem.h"
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityItemProperties.h"
|
||||
#include "EntityTree.h"
|
||||
#include "EntityTreeElement.h"
|
||||
|
||||
EntityItemPointer BoxEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new BoxEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
BoxEntityItem::BoxEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Box;
|
||||
}
|
||||
|
||||
EntityItemProperties BoxEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
|
||||
properties._color = getXColor();
|
||||
properties._colorChanged = false;
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool BoxEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = false;
|
||||
somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - getLastEdited();
|
||||
qCDebug(entities) << "BoxEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties._lastEdited);
|
||||
}
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
int BoxEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged) {
|
||||
|
||||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
EntityPropertyFlags BoxEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_COLOR;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
void BoxEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
}
|
||||
|
||||
void BoxEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qCDebug(entities) << " BOX EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2];
|
||||
qCDebug(entities) << " position:" << debugTreeVector(getPosition());
|
||||
qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions());
|
||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
|
@ -1,64 +0,0 @@
|
|||
//
|
||||
// BoxEntityItem.h
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/4/13.
|
||||
// Copyright 2013 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_BoxEntityItem_h
|
||||
#define hifi_BoxEntityItem_h
|
||||
|
||||
#include "EntityItem.h"
|
||||
|
||||
class BoxEntityItem : public EntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
BoxEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||
|
||||
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const;
|
||||
|
||||
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged);
|
||||
|
||||
const rgbColor& getColor() const { return _color; }
|
||||
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_BOX; }
|
||||
virtual bool shouldBePhysical() const { return !isDead(); }
|
||||
|
||||
virtual void debugDump() const;
|
||||
|
||||
protected:
|
||||
rgbColor _color;
|
||||
};
|
||||
|
||||
#endif // hifi_BoxEntityItem_h
|
|
@ -689,6 +689,7 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(jointRotations, qVectorQuat, setJointRotations);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(jointTranslationsSet, qVectorBool, setJointTranslationsSet);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(jointTranslations, qVectorVec3, setJointTranslations);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(shape, QString, setShape);
|
||||
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(flyingAllowed, bool, setFlyingAllowed);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(ghostingAllowed, bool, setGhostingAllowed);
|
||||
|
@ -846,6 +847,8 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS_SET, JointTranslationsSet, jointTranslationsSet, QVector<bool>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_JOINT_TRANSLATIONS, JointTranslations, jointTranslations, QVector<glm::vec3>);
|
||||
|
||||
ADD_PROPERTY_TO_MAP(PROP_SHAPE, Shape, shape, QString);
|
||||
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_URL, Animation, animation, URL, url);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FPS, Animation, animation, FPS, fps);
|
||||
ADD_GROUP_PROPERTY_TO_MAP(PROP_ANIMATION_FRAME_INDEX, Animation, animation, CurrentFrame, currentFrame);
|
||||
|
@ -1141,7 +1144,9 @@ bool EntityItemProperties::encodeEntityEditPacket(PacketType command, EntityItem
|
|||
APPEND_ENTITY_PROPERTY(PROP_STROKE_WIDTHS, properties.getStrokeWidths());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Shape) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE, properties.getShape());
|
||||
}
|
||||
APPEND_ENTITY_PROPERTY(PROP_MARKETPLACE_ID, properties.getMarketplaceID());
|
||||
APPEND_ENTITY_PROPERTY(PROP_NAME, properties.getName());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLLISION_SOUND_URL, properties.getCollisionSoundURL());
|
||||
|
@ -1429,6 +1434,9 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STROKE_WIDTHS, QVector<float>, setStrokeWidths);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
|
||||
}
|
||||
if (properties.getType() == EntityTypes::Shape) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_SHAPE, QString, setShape);
|
||||
}
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_MARKETPLACE_ID, QString, setMarketplaceID);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_NAME, QString, setName);
|
||||
|
@ -1915,6 +1923,7 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
if (queryAACubeChanged()) {
|
||||
out += "queryAACube";
|
||||
}
|
||||
|
||||
if (clientOnlyChanged()) {
|
||||
out += "clientOnly";
|
||||
}
|
||||
|
@ -1929,6 +1938,10 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
out += "ghostingAllowed";
|
||||
}
|
||||
|
||||
if (shapeChanged()) {
|
||||
out += "shape";
|
||||
}
|
||||
|
||||
getAnimation().listChangedProperties(out);
|
||||
getKeyLight().listChangedProperties(out);
|
||||
getSkybox().listChangedProperties(out);
|
||||
|
|
|
@ -50,7 +50,7 @@ const quint64 UNKNOWN_CREATED_TIME = 0;
|
|||
/// A collection of properties of an entity item used in the scripting API. Translates between the actual properties of an
|
||||
/// entity and a JavaScript style hash/QScriptValue storing a set of properties. Used in scripting to set/get the complete
|
||||
/// set of entity item properties via JavaScript hashes/QScriptValues
|
||||
/// all units for position, dimensions, etc are in meter units
|
||||
/// all units for SI units (meter, second, radian, etc)
|
||||
class EntityItemProperties {
|
||||
friend class EntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class ModelEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
|
@ -64,6 +64,7 @@ class EntityItemProperties {
|
|||
friend class LineEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class PolyVoxEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class PolyLineEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
friend class ShapeEntityItem; // TODO: consider removing this friend relationship and use public methods
|
||||
public:
|
||||
EntityItemProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags());
|
||||
virtual ~EntityItemProperties() = default;
|
||||
|
@ -195,6 +196,7 @@ public:
|
|||
DEFINE_PROPERTY_REF(PROP_PARENT_ID, ParentID, parentID, QUuid, UNKNOWN_ENTITY_ID);
|
||||
DEFINE_PROPERTY_REF(PROP_PARENT_JOINT_INDEX, ParentJointIndex, parentJointIndex, quint16, -1);
|
||||
DEFINE_PROPERTY_REF(PROP_QUERY_AA_CUBE, QueryAACube, queryAACube, AACube, AACube());
|
||||
DEFINE_PROPERTY_REF(PROP_SHAPE, Shape, shape, QString, "Sphere");
|
||||
|
||||
// these are used when bouncing location data into and out of scripts
|
||||
DEFINE_PROPERTY_REF(PROP_LOCAL_POSITION, LocalPosition, localPosition, glmVec3, ENTITY_ITEM_ZERO_VEC3);
|
||||
|
|
|
@ -175,6 +175,8 @@ enum EntityPropertyList {
|
|||
PROP_CLIENT_ONLY, // doesn't go over wire
|
||||
PROP_OWNING_AVATAR_ID, // doesn't go over wire
|
||||
|
||||
PROP_SHAPE,
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// ATTENTION: add new properties to end of list just ABOVE this line
|
||||
PROP_AFTER_LAST_ITEM,
|
||||
|
|
|
@ -18,17 +18,16 @@
|
|||
#include "EntityItemProperties.h"
|
||||
#include "EntityTypes.h"
|
||||
|
||||
#include "BoxEntityItem.h"
|
||||
#include "LightEntityItem.h"
|
||||
#include "ModelEntityItem.h"
|
||||
#include "ParticleEffectEntityItem.h"
|
||||
#include "SphereEntityItem.h"
|
||||
#include "TextEntityItem.h"
|
||||
#include "WebEntityItem.h"
|
||||
#include "ZoneEntityItem.h"
|
||||
#include "LineEntityItem.h"
|
||||
#include "PolyVoxEntityItem.h"
|
||||
#include "PolyLineEntityItem.h"
|
||||
#include "ShapeEntityItem.h"
|
||||
|
||||
QMap<EntityTypes::EntityType, QString> EntityTypes::_typeToNameMap;
|
||||
QMap<QString, EntityTypes::EntityType> EntityTypes::_nameToTypeMap;
|
||||
|
@ -39,16 +38,17 @@ const QString ENTITY_TYPE_NAME_UNKNOWN = "Unknown";
|
|||
|
||||
// Register Entity the default implementations of entity types here...
|
||||
REGISTER_ENTITY_TYPE(Model)
|
||||
REGISTER_ENTITY_TYPE(Box)
|
||||
REGISTER_ENTITY_TYPE(Web)
|
||||
REGISTER_ENTITY_TYPE(Sphere)
|
||||
REGISTER_ENTITY_TYPE(Light)
|
||||
REGISTER_ENTITY_TYPE(Text)
|
||||
REGISTER_ENTITY_TYPE(ParticleEffect)
|
||||
REGISTER_ENTITY_TYPE(Zone)
|
||||
REGISTER_ENTITY_TYPE(Line)
|
||||
REGISTER_ENTITY_TYPE(PolyVox)
|
||||
REGISTER_ENTITY_TYPE(PolyLine);
|
||||
REGISTER_ENTITY_TYPE(PolyLine)
|
||||
REGISTER_ENTITY_TYPE(Shape)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Box, ShapeEntityItem::boxFactory)
|
||||
REGISTER_ENTITY_TYPE_WITH_FACTORY(Sphere, ShapeEntityItem::sphereFactory)
|
||||
|
||||
const QString& EntityTypes::getEntityTypeName(EntityType entityType) {
|
||||
QMap<EntityType, QString>::iterator matchedTypeName = _typeToNameMap.find(entityType);
|
||||
|
|
|
@ -48,7 +48,8 @@ public:
|
|||
Line,
|
||||
PolyVox,
|
||||
PolyLine,
|
||||
LAST = PolyLine
|
||||
Shape,
|
||||
LAST = Shape
|
||||
} EntityType;
|
||||
|
||||
static const QString& getEntityTypeName(EntityType entityType);
|
||||
|
@ -72,6 +73,15 @@ private:
|
|||
#define REGISTER_ENTITY_TYPE(x) static bool x##Registration = \
|
||||
EntityTypes::registerEntityType(EntityTypes::x, #x, x##EntityItem::factory);
|
||||
|
||||
|
||||
struct EntityRegistrationChecker {
|
||||
EntityRegistrationChecker(bool result, const char* debugMessage) {
|
||||
if (!result) {
|
||||
qDebug() << debugMessage;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// Macro for registering entity types with an overloaded factory. Like using the REGISTER_ENTITY_TYPE macro: Make sure to add
|
||||
/// an element to the EntityType enum with your name. But unlike REGISTER_ENTITY_TYPE, your class can be named anything
|
||||
/// so long as you provide a static method passed to the macro, that takes an EnityItemID, and EntityItemProperties and
|
||||
|
@ -79,9 +89,9 @@ private:
|
|||
// static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
#define REGISTER_ENTITY_TYPE_WITH_FACTORY(x,y) static bool x##Registration = \
|
||||
EntityTypes::registerEntityType(EntityTypes::x, #x, y); \
|
||||
if (!x##Registration) { \
|
||||
qDebug() << "UNEXPECTED: REGISTER_ENTITY_TYPE_WITH_FACTORY(" #x "," #y ") FAILED.!"; \
|
||||
}
|
||||
EntityRegistrationChecker x##RegistrationChecker( \
|
||||
x##Registration, \
|
||||
"UNEXPECTED: REGISTER_ENTITY_TYPE_WITH_FACTORY(" #x "," #y ") FAILED.!");
|
||||
|
||||
|
||||
#endif // hifi_EntityTypes_h
|
||||
|
|
230
libraries/entities/src/ShapeEntityItem.cpp
Normal file
230
libraries/entities/src/ShapeEntityItem.cpp
Normal file
|
@ -0,0 +1,230 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/05/09
|
||||
// Copyright 2013 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 <glm/gtx/transform.hpp>
|
||||
|
||||
#include <QtCore/QDebug>
|
||||
|
||||
#include <GeometryUtil.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityItemProperties.h"
|
||||
#include "EntityTree.h"
|
||||
#include "EntityTreeElement.h"
|
||||
#include "ShapeEntityItem.h"
|
||||
|
||||
namespace entity {
|
||||
static const std::vector<QString> shapeStrings { {
|
||||
"Triangle",
|
||||
"Quad",
|
||||
"Circle",
|
||||
"Cube",
|
||||
"Sphere",
|
||||
"Tetrahedron",
|
||||
"Octahetron",
|
||||
"Dodecahedron",
|
||||
"Icosahedron",
|
||||
"Torus",
|
||||
"Cone",
|
||||
"Cylinder"
|
||||
} };
|
||||
|
||||
Shape shapeFromString(const ::QString& shapeString) {
|
||||
for (size_t i = 0; i < shapeStrings.size(); ++i) {
|
||||
if (shapeString.toLower() == shapeStrings[i].toLower()) {
|
||||
return static_cast<Shape>(i);
|
||||
}
|
||||
}
|
||||
return Shape::Sphere;
|
||||
}
|
||||
|
||||
::QString stringFromShape(Shape shape) {
|
||||
return shapeStrings[shape];
|
||||
}
|
||||
}
|
||||
|
||||
ShapeEntityItem::Pointer ShapeEntityItem::baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
Pointer entity { new ShapeEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
EntityItemPointer ShapeEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
return baseFactory(entityID, properties);
|
||||
}
|
||||
|
||||
EntityItemPointer ShapeEntityItem::boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
auto result = baseFactory(entityID, properties);
|
||||
result->setShape(entity::Shape::Cube);
|
||||
return result;
|
||||
}
|
||||
|
||||
EntityItemPointer ShapeEntityItem::sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
auto result = baseFactory(entityID, properties);
|
||||
result->setShape(entity::Shape::Sphere);
|
||||
return result;
|
||||
}
|
||||
|
||||
// our non-pure virtual subclass for now...
|
||||
ShapeEntityItem::ShapeEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Shape;
|
||||
_volumeMultiplier *= PI / 6.0f;
|
||||
}
|
||||
|
||||
EntityItemProperties ShapeEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
properties.setColor(getXColor());
|
||||
properties.setShape(entity::stringFromShape(getShape()));
|
||||
return properties;
|
||||
}
|
||||
|
||||
void ShapeEntityItem::setShape(const entity::Shape& shape) {
|
||||
_shape = shape;
|
||||
switch (_shape) {
|
||||
case entity::Shape::Cube:
|
||||
_type = EntityTypes::Box;
|
||||
break;
|
||||
case entity::Shape::Sphere:
|
||||
_type = EntityTypes::Sphere;
|
||||
break;
|
||||
default:
|
||||
_type = EntityTypes::Shape;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool ShapeEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(alpha, setAlpha);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(shape, setShape);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - getLastEdited();
|
||||
qCDebug(entities) << "ShapeEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties.getLastEdited());
|
||||
}
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
int ShapeEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged) {
|
||||
|
||||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_SHAPE, QString, setShape);
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_ALPHA, float, setAlpha);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
EntityPropertyFlags ShapeEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_SHAPE;
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_ALPHA;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
void ShapeEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_SHAPE, entity::stringFromShape(getShape()));
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getAlpha());
|
||||
}
|
||||
|
||||
// This value specifes how the shape should be treated by physics calculations.
|
||||
// For now, all polys will act as spheres
|
||||
ShapeType ShapeEntityItem::getShapeType() const {
|
||||
return SHAPE_TYPE_ELLIPSOID;
|
||||
}
|
||||
|
||||
void ShapeEntityItem::setColor(const rgbColor& value) {
|
||||
memcpy(_color, value, sizeof(rgbColor));
|
||||
}
|
||||
|
||||
xColor ShapeEntityItem::getXColor() const {
|
||||
return xColor { _color[0], _color[1], _color[2] };
|
||||
}
|
||||
|
||||
void ShapeEntityItem::setColor(const xColor& value) {
|
||||
setColor(rgbColor { value.red, value.green, value.blue });
|
||||
}
|
||||
|
||||
QColor ShapeEntityItem::getQColor() const {
|
||||
auto& color = getColor();
|
||||
return QColor(color[0], color[1], color[2], (int)(getAlpha() * 255));
|
||||
}
|
||||
|
||||
void ShapeEntityItem::setColor(const QColor& value) {
|
||||
setColor(rgbColor { (uint8_t)value.red(), (uint8_t)value.green(), (uint8_t)value.blue() });
|
||||
setAlpha(value.alpha());
|
||||
}
|
||||
|
||||
bool ShapeEntityItem::supportsDetailedRayIntersection() const {
|
||||
return _shape == entity::Sphere;
|
||||
}
|
||||
|
||||
bool ShapeEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& element,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||
void** intersectedObject, bool precisionPicking) const {
|
||||
// determine the ray in the frame of the entity transformed from a unit sphere
|
||||
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)));
|
||||
|
||||
float localDistance;
|
||||
// NOTE: unit sphere has center of 0,0,0 and radius of 0.5
|
||||
if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, localDistance)) {
|
||||
// determine where on the unit sphere the hit point occured
|
||||
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);
|
||||
bool success;
|
||||
surfaceNormal = glm::normalize(hitAt - getCenterPosition(success));
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void ShapeEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qCDebug(entities) << "SHAPE EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qCDebug(entities) << " shape:" << stringFromShape(_shape);
|
||||
qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2];
|
||||
qCDebug(entities) << " position:" << debugTreeVector(getPosition());
|
||||
qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions());
|
||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
103
libraries/entities/src/ShapeEntityItem.h
Normal file
103
libraries/entities/src/ShapeEntityItem.h
Normal file
|
@ -0,0 +1,103 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2016/05/09
|
||||
// Copyright 2013 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_ShapeEntityItem_h
|
||||
#define hifi_ShapeEntityItem_h
|
||||
|
||||
#include "EntityItem.h"
|
||||
|
||||
namespace entity {
|
||||
enum Shape {
|
||||
Triangle,
|
||||
Quad,
|
||||
Circle,
|
||||
Cube,
|
||||
Sphere,
|
||||
Tetrahedron,
|
||||
Octahetron,
|
||||
Dodecahedron,
|
||||
Icosahedron,
|
||||
Torus,
|
||||
Cone,
|
||||
Cylinder,
|
||||
NUM_SHAPES,
|
||||
};
|
||||
|
||||
Shape shapeFromString(const ::QString& shapeString);
|
||||
::QString stringFromShape(Shape shape);
|
||||
}
|
||||
|
||||
|
||||
class ShapeEntityItem : public EntityItem {
|
||||
using Pointer = std::shared_ptr<ShapeEntityItem>;
|
||||
static Pointer baseFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
static EntityItemPointer sphereFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
static EntityItemPointer boxFactory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
ShapeEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
void pureVirtualFunctionPlaceHolder() override { };
|
||||
// Triggers warnings on OSX
|
||||
//ALLOW_INSTANTIATION
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const override;
|
||||
bool setProperties(const EntityItemProperties& properties) override;
|
||||
|
||||
EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
|
||||
|
||||
void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const override;
|
||||
|
||||
int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged) override;
|
||||
|
||||
entity::Shape getShape() const { return _shape; }
|
||||
void setShape(const entity::Shape& shape);
|
||||
void setShape(const QString& shape) { setShape(entity::shapeFromString(shape)); }
|
||||
|
||||
float getAlpha() const { return _alpha; };
|
||||
void setAlpha(float alpha) { _alpha = alpha; }
|
||||
|
||||
const rgbColor& getColor() const { return _color; }
|
||||
void setColor(const rgbColor& value);
|
||||
|
||||
xColor getXColor() const;
|
||||
void setColor(const xColor& value);
|
||||
|
||||
QColor getQColor() const;
|
||||
void setColor(const QColor& value);
|
||||
|
||||
ShapeType getShapeType() const override;
|
||||
bool shouldBePhysical() const override { return !isDead(); }
|
||||
|
||||
bool supportsDetailedRayIntersection() const override;
|
||||
bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
void** intersectedObject, bool precisionPicking) const override;
|
||||
|
||||
void debugDump() const override;
|
||||
|
||||
protected:
|
||||
|
||||
float _alpha { 1 };
|
||||
rgbColor _color;
|
||||
entity::Shape _shape { entity::Shape::Sphere };
|
||||
};
|
||||
|
||||
#endif // hifi_ShapeEntityItem_h
|
|
@ -1,132 +0,0 @@
|
|||
//
|
||||
// SphereEntityItem.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/4/13.
|
||||
// Copyright 2013 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 <glm/gtx/transform.hpp>
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
#include <GeometryUtil.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityItemProperties.h"
|
||||
#include "EntityTree.h"
|
||||
#include "EntityTreeElement.h"
|
||||
#include "SphereEntityItem.h"
|
||||
|
||||
EntityItemPointer SphereEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity { new SphereEntityItem(entityID) };
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
// our non-pure virtual subclass for now...
|
||||
SphereEntityItem::SphereEntityItem(const EntityItemID& entityItemID) : EntityItem(entityItemID) {
|
||||
_type = EntityTypes::Sphere;
|
||||
_volumeMultiplier *= PI / 6.0f;
|
||||
}
|
||||
|
||||
EntityItemProperties SphereEntityItem::getProperties(EntityPropertyFlags desiredProperties) const {
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties); // get the properties from our base class
|
||||
properties.setColor(getXColor());
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool SphereEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
bool somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(color, setColor);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - getLastEdited();
|
||||
qCDebug(entities) << "SphereEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties.getLastEdited());
|
||||
}
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
int SphereEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged) {
|
||||
|
||||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
READ_ENTITY_PROPERTY(PROP_COLOR, rgbColor, setColor);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
// TODO: eventually only include properties changed since the params.lastViewFrustumSent time
|
||||
EntityPropertyFlags SphereEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_COLOR;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
void SphereEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
}
|
||||
|
||||
bool SphereEntityItem::findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& element,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal,
|
||||
void** intersectedObject, bool precisionPicking) const {
|
||||
// determine the ray in the frame of the entity transformed from a unit sphere
|
||||
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)));
|
||||
|
||||
float localDistance;
|
||||
// NOTE: unit sphere has center of 0,0,0 and radius of 0.5
|
||||
if (findRaySphereIntersection(entityFrameOrigin, entityFrameDirection, glm::vec3(0.0f), 0.5f, localDistance)) {
|
||||
// determine where on the unit sphere the hit point occured
|
||||
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);
|
||||
bool success;
|
||||
surfaceNormal = glm::normalize(hitAt - getCenterPosition(success));
|
||||
if (!success) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void SphereEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qCDebug(entities) << "SHPERE EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qCDebug(entities) << " color:" << _color[0] << "," << _color[1] << "," << _color[2];
|
||||
qCDebug(entities) << " position:" << debugTreeVector(getPosition());
|
||||
qCDebug(entities) << " dimensions:" << debugTreeVector(getDimensions());
|
||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
|
@ -1,70 +0,0 @@
|
|||
//
|
||||
// SphereEntityItem.h
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Brad Hefta-Gaub on 12/4/13.
|
||||
// Copyright 2013 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_SphereEntityItem_h
|
||||
#define hifi_SphereEntityItem_h
|
||||
|
||||
#include "EntityItem.h"
|
||||
|
||||
class SphereEntityItem : public EntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
SphereEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties(EntityPropertyFlags desiredProperties = EntityPropertyFlags()) const;
|
||||
virtual bool setProperties(const EntityItemProperties& properties);
|
||||
|
||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const;
|
||||
|
||||
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeData* modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const;
|
||||
|
||||
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged);
|
||||
|
||||
const rgbColor& getColor() const { return _color; }
|
||||
xColor getXColor() const { xColor color = { _color[RED_INDEX], _color[GREEN_INDEX], _color[BLUE_INDEX] }; return color; }
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
virtual ShapeType getShapeType() const { return SHAPE_TYPE_SPHERE; }
|
||||
virtual bool shouldBePhysical() const { return !isDead(); }
|
||||
|
||||
virtual bool supportsDetailedRayIntersection() const { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
bool& keepSearching, OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
void** intersectedObject, bool precisionPicking) const;
|
||||
|
||||
virtual void debugDump() const;
|
||||
|
||||
protected:
|
||||
|
||||
rgbColor _color;
|
||||
};
|
||||
|
||||
#endif // hifi_SphereEntityItem_h
|
|
@ -112,10 +112,12 @@ void GeometryCache::ShapeData::drawWireInstances(gpu::Batch& batch, size_t count
|
|||
}
|
||||
}
|
||||
|
||||
// The golden ratio
|
||||
static const float PHI = 1.61803398874f;
|
||||
|
||||
const VertexVector& icosahedronVertices() {
|
||||
static const float phi = (1.0f + sqrtf(5.0f)) / 2.0f;
|
||||
static const float a = 0.5f;
|
||||
static const float b = 1.0f / (2.0f * phi);
|
||||
static const float a = 1;
|
||||
static const float b = PHI / 2.0f;
|
||||
|
||||
static const VertexVector vertices{ //
|
||||
vec3(0, b, -a), vec3(-b, a, 0), vec3(b, a, 0), //
|
||||
|
@ -143,11 +145,10 @@ const VertexVector& icosahedronVertices() {
|
|||
}
|
||||
|
||||
const VertexVector& tetrahedronVertices() {
|
||||
static const float a = 1.0f / sqrtf(2.0f);
|
||||
static const auto A = vec3(0, 1, a);
|
||||
static const auto B = vec3(0, -1, a);
|
||||
static const auto C = vec3(1, 0, -a);
|
||||
static const auto D = vec3(-1, 0, -a);
|
||||
static const auto A = vec3(1, 1, 1);
|
||||
static const auto B = vec3(1, -1, -1);
|
||||
static const auto C = vec3(-1, 1, -1);
|
||||
static const auto D = vec3(-1, -1, 1);
|
||||
static const VertexVector vertices{
|
||||
A, B, C,
|
||||
D, B, A,
|
||||
|
@ -356,7 +357,7 @@ void GeometryCache::buildShapes() {
|
|||
for (size_t j = 0; j < VERTICES_PER_TRIANGLE; ++j) {
|
||||
auto triangleVertexIndex = j;
|
||||
auto vertexIndex = triangleStartIndex + triangleVertexIndex;
|
||||
vertices.push_back(glm::normalize(originalVertices[vertexIndex]));
|
||||
vertices.push_back(originalVertices[vertexIndex]);
|
||||
vertices.push_back(faceNormal);
|
||||
}
|
||||
}
|
||||
|
@ -437,7 +438,7 @@ void GeometryCache::buildShapes() {
|
|||
for (int j = 0; j < VERTICES_PER_TRIANGLE; ++j) {
|
||||
auto triangleVertexIndex = j;
|
||||
auto vertexIndex = triangleStartIndex + triangleVertexIndex;
|
||||
vertices.push_back(glm::normalize(originalVertices[vertexIndex]));
|
||||
vertices.push_back(originalVertices[vertexIndex]);
|
||||
vertices.push_back(faceNormal);
|
||||
indices.push_back((uint16_t)(vertexIndex + startingIndex));
|
||||
}
|
||||
|
@ -1801,10 +1802,10 @@ uint32_t toCompactColor(const glm::vec4& color) {
|
|||
|
||||
static const size_t INSTANCE_COLOR_BUFFER = 0;
|
||||
|
||||
void renderInstances(const std::string& name, gpu::Batch& batch, const glm::vec4& color, bool isWire,
|
||||
void renderInstances(gpu::Batch& batch, const glm::vec4& color, bool isWire,
|
||||
const render::ShapePipelinePointer& pipeline, GeometryCache::Shape shape) {
|
||||
// Add pipeline to name
|
||||
std::string instanceName = name + std::to_string(std::hash<render::ShapePipelinePointer>()(pipeline));
|
||||
std::string instanceName = (isWire ? "wire_shapes_" : "solid_shapes_") + std::to_string(shape) + "_" + std::to_string(std::hash<render::ShapePipelinePointer>()(pipeline));
|
||||
|
||||
// Add color to named buffer
|
||||
{
|
||||
|
@ -1826,14 +1827,16 @@ void renderInstances(const std::string& name, gpu::Batch& batch, const glm::vec4
|
|||
});
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidShapeInstance(gpu::Batch& batch, GeometryCache::Shape shape, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
renderInstances(batch, color, false, pipeline, shape);
|
||||
}
|
||||
|
||||
void GeometryCache::renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||
renderInstances(INSTANCE_NAME, batch, color, false, pipeline, GeometryCache::Sphere);
|
||||
renderInstances(batch, color, false, pipeline, GeometryCache::Sphere);
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||
renderInstances(INSTANCE_NAME, batch, color, true, pipeline, GeometryCache::Sphere);
|
||||
renderInstances(batch, color, true, pipeline, GeometryCache::Sphere);
|
||||
}
|
||||
|
||||
// Enable this in a debug build to cause 'box' entities to iterate through all the
|
||||
|
@ -1841,8 +1844,6 @@ void GeometryCache::renderWireSphereInstance(gpu::Batch& batch, const glm::vec4&
|
|||
//#define DEBUG_SHAPES
|
||||
|
||||
void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||
|
||||
#ifdef DEBUG_SHAPES
|
||||
static auto startTime = usecTimestampNow();
|
||||
renderInstances(INSTANCE_NAME, batch, color, pipeline, [](gpu::Batch& batch, gpu::Batch::NamedBatchData& data) {
|
||||
|
@ -1876,11 +1877,11 @@ void GeometryCache::renderSolidCubeInstance(gpu::Batch& batch, const glm::vec4&
|
|||
}
|
||||
});
|
||||
#else
|
||||
renderInstances(INSTANCE_NAME, batch, color, false, pipeline, GeometryCache::Cube);
|
||||
renderInstances(batch, color, false, pipeline, GeometryCache::Cube);
|
||||
#endif
|
||||
}
|
||||
|
||||
void GeometryCache::renderWireCubeInstance(gpu::Batch& batch, const glm::vec4& color, const render::ShapePipelinePointer& pipeline) {
|
||||
static const std::string INSTANCE_NAME = __FUNCTION__;
|
||||
renderInstances(INSTANCE_NAME, batch, color, true, pipeline, GeometryCache::Cube);
|
||||
renderInstances(batch, color, true, pipeline, GeometryCache::Cube);
|
||||
}
|
||||
|
|
|
@ -163,6 +163,13 @@ public:
|
|||
void renderShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||
void renderWireShapeInstances(gpu::Batch& batch, Shape shape, size_t count, gpu::BufferPointer& colorBuffer);
|
||||
|
||||
void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec4& color = glm::vec4(1),
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
void renderSolidShapeInstance(gpu::Batch& batch, Shape shape, const glm::vec3& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline) {
|
||||
renderSolidShapeInstance(batch, shape, glm::vec4(color, 1.0f), pipeline);
|
||||
}
|
||||
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec4& color,
|
||||
const render::ShapePipelinePointer& pipeline = _simplePipeline);
|
||||
void renderSolidSphereInstance(gpu::Batch& batch, const glm::vec3& color,
|
||||
|
|
|
@ -15,161 +15,11 @@
|
|||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
var NUM_ENTITIES = 20000; // number of entities to spawn
|
||||
var ENTITY_SPAWN_LIMIT = 1000;
|
||||
var ENTITY_SPAWN_INTERVAL = 0.1;
|
||||
Script.include("./entitySpawnTool.js");
|
||||
|
||||
var UPDATE_INTERVAL = 0.05; // Re-randomize the entity's position every x seconds / ms
|
||||
var ENTITY_LIFETIME = 30; // Entity timeout (when/if we crash, we need the entities to delete themselves)
|
||||
var KEEPALIVE_INTERVAL = 5; // Refreshes the timeout every X seconds
|
||||
|
||||
var RADIUS = 5.0; // Spawn within this radius (square)
|
||||
var Y_OFFSET = 1.5; // Spawn at an offset below the avatar
|
||||
var TEST_ENTITY_NAME = "EntitySpawnTest";
|
||||
|
||||
(function () {
|
||||
this.makeEntity = function (properties) {
|
||||
var entity = Entities.addEntity(properties);
|
||||
// print("spawning entity: " + JSON.stringify(properties));
|
||||
|
||||
return {
|
||||
update: function (properties) {
|
||||
Entities.editEntity(entity, properties);
|
||||
},
|
||||
destroy: function () {
|
||||
Entities.deleteEntity(entity)
|
||||
},
|
||||
getAge: function () {
|
||||
return Entities.getEntityProperties(entity).age;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
this.randomPositionXZ = function (center, radius) {
|
||||
return {
|
||||
x: center.x + (Math.random() * radius * 2.0) - radius,
|
||||
y: center.y,
|
||||
z: center.z + (Math.random() * radius * 2.0) - radius
|
||||
};
|
||||
}
|
||||
this.randomColor = function () {
|
||||
var shade = Math.floor(Math.random() * 255);
|
||||
var hue = Math.floor(Math.random() * (255 - shade));
|
||||
|
||||
return {
|
||||
red: shade + hue,
|
||||
green: shade,
|
||||
blue: shade
|
||||
};
|
||||
}
|
||||
this.randomDimensions = function () {
|
||||
return {
|
||||
x: 0.1 + Math.random() * 0.5,
|
||||
y: 0.1 + Math.random() * 0.1,
|
||||
z: 0.1 + Math.random() * 0.5
|
||||
};
|
||||
}
|
||||
})();
|
||||
|
||||
(function () {
|
||||
var entities = [];
|
||||
var entitiesToCreate = 0;
|
||||
var entitiesSpawned = 0;
|
||||
|
||||
|
||||
function clear () {
|
||||
var ids = Entities.findEntities(MyAvatar.position, 50);
|
||||
var that = this;
|
||||
ids.forEach(function(id) {
|
||||
var properties = Entities.getEntityProperties(id);
|
||||
if (properties.name == TEST_ENTITY_NAME) {
|
||||
Entities.deleteEntity(id);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
function createEntities () {
|
||||
print("Creating " + NUM_ENTITIES + " entities (UPDATE_INTERVAL = " + UPDATE_INTERVAL + ", KEEPALIVE_INTERVAL = " + KEEPALIVE_INTERVAL + ")");
|
||||
entitiesToCreate = NUM_ENTITIES;
|
||||
Script.update.connect(spawnEntities);
|
||||
}
|
||||
|
||||
var spawnTimer = 0.0;
|
||||
function spawnEntities (dt) {
|
||||
if (entitiesToCreate <= 0) {
|
||||
Script.update.disconnect(spawnEntities);
|
||||
print("Finished spawning entities");
|
||||
}
|
||||
else if ((spawnTimer -= dt) < 0.0){
|
||||
spawnTimer = ENTITY_SPAWN_INTERVAL;
|
||||
|
||||
var n = Math.min(entitiesToCreate, ENTITY_SPAWN_LIMIT);
|
||||
print("Spawning " + n + " entities (" + (entitiesSpawned += n) + ")");
|
||||
|
||||
entitiesToCreate -= n;
|
||||
|
||||
var center = MyAvatar.position;
|
||||
center.y -= Y_OFFSET;
|
||||
|
||||
for (; n > 0; --n) {
|
||||
entities.push(makeEntity({
|
||||
type: "Box",
|
||||
name: TEST_ENTITY_NAME,
|
||||
position: randomPositionXZ(center, RADIUS),
|
||||
color: randomColor(),
|
||||
dimensions: randomDimensions(),
|
||||
lifetime: ENTITY_LIFETIME
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function despawnEntities () {
|
||||
print("despawning entities");
|
||||
entities.forEach(function (entity) {
|
||||
entity.destroy();
|
||||
});
|
||||
entities = [];
|
||||
}
|
||||
|
||||
var keepAliveTimer = 0.0;
|
||||
var updateTimer = 0.0;
|
||||
|
||||
// Runs the following entity updates:
|
||||
// a) refreshes the timeout interval every KEEPALIVE_INTERVAL seconds, and
|
||||
// b) re-randomizes its position every UPDATE_INTERVAL seconds.
|
||||
// This should be sufficient to crash the client until the entity tree bug is fixed (and thereafter if it shows up again).
|
||||
function updateEntities (dt) {
|
||||
var updateLifetime = ((keepAliveTimer -= dt) < 0.0) ? ((keepAliveTimer = KEEPALIVE_INTERVAL), true) : false;
|
||||
var updateProperties = ((updateTimer -= dt) < 0.0) ? ((updateTimer = UPDATE_INTERVAL), true) : false;
|
||||
|
||||
if (updateLifetime || updateProperties) {
|
||||
var center = MyAvatar.position;
|
||||
center.y -= Y_OFFSET;
|
||||
|
||||
entities.forEach((updateLifetime && updateProperties && function (entity) {
|
||||
entity.update({
|
||||
lifetime: entity.getAge() + ENTITY_LIFETIME,
|
||||
position: randomPositionXZ(center, RADIUS)
|
||||
});
|
||||
}) || (updateLifetime && function (entity) {
|
||||
entity.update({
|
||||
lifetime: entity.getAge() + ENTITY_LIFETIME
|
||||
});
|
||||
}) || (updateProperties && function (entity) {
|
||||
entity.update({
|
||||
position: randomPositionXZ(center, RADIUS)
|
||||
});
|
||||
}) || null, this);
|
||||
}
|
||||
}
|
||||
|
||||
function init () {
|
||||
Script.update.disconnect(init);
|
||||
clear();
|
||||
createEntities();
|
||||
Script.update.connect(updateEntities);
|
||||
Script.scriptEnding.connect(despawnEntities);
|
||||
}
|
||||
Script.update.connect(init);
|
||||
})();
|
||||
ENTITY_SPAWNER({
|
||||
count: 20000,
|
||||
spawnLimit: 1000,
|
||||
spawnInterval: 0.1,
|
||||
updateInterval: 0.05
|
||||
});
|
||||
|
|
184
scripts/developer/tests/entitySpawnTool.js
Normal file
184
scripts/developer/tests/entitySpawnTool.js
Normal file
|
@ -0,0 +1,184 @@
|
|||
// entityEditStressTest.js
|
||||
//
|
||||
// Created by Seiji Emery on 8/31/15
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Stress tests the client + server-side entity trees by spawning huge numbers of entities in
|
||||
// close proximity to your avatar and updating them continuously (ie. applying position edits),
|
||||
// with the intent of discovering crashes and other bugs related to the entity, scripting,
|
||||
// rendering, networking, and/or physics subsystems.
|
||||
//
|
||||
// This script was originally created to find + diagnose an a clientside crash caused by improper
|
||||
// locking of the entity tree, but can be reused for other purposes.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
ENTITY_SPAWNER = function (properties) {
|
||||
properties = properties || {};
|
||||
var RADIUS = properties.radius || 5.0; // Spawn within this radius (square)
|
||||
var Y_OFFSET = properties.yOffset || 1.5; // Spawn at an offset below the avatar
|
||||
var TEST_ENTITY_NAME = properties.entityName || "EntitySpawnTest";
|
||||
|
||||
var NUM_ENTITIES = properties.count || 1000; // number of entities to spawn
|
||||
var ENTITY_SPAWN_LIMIT = properties.spawnLimit || 100;
|
||||
var ENTITY_SPAWN_INTERVAL = properties.spawnInterval || properties.interval || 1.0;
|
||||
|
||||
var UPDATE_INTERVAL = properties.updateInterval || properties.interval || 0.1; // Re-randomize the entity's position every x seconds / ms
|
||||
var ENTITY_LIFETIME = properties.lifetime || 30; // Entity timeout (when/if we crash, we need the entities to delete themselves)
|
||||
var KEEPALIVE_INTERVAL = properties.keepAlive || 5; // Refreshes the timeout every X seconds
|
||||
var UPDATES = properties.updates || false
|
||||
var SHAPES = properties.shapes || ["Icosahedron", "Tetrahedron", "Cube", "Sphere" ];
|
||||
|
||||
function makeEntity(properties) {
|
||||
var entity = Entities.addEntity(properties);
|
||||
// print("spawning entity: " + JSON.stringify(properties));
|
||||
|
||||
return {
|
||||
update: function (properties) {
|
||||
Entities.editEntity(entity, properties);
|
||||
},
|
||||
destroy: function () {
|
||||
Entities.deleteEntity(entity)
|
||||
},
|
||||
getAge: function () {
|
||||
return Entities.getEntityProperties(entity).age;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
function randomPositionXZ(center, radius) {
|
||||
return {
|
||||
x: center.x + (Math.random() * radius * 2.0) - radius,
|
||||
y: center.y,
|
||||
z: center.z + (Math.random() * radius * 2.0) - radius
|
||||
};
|
||||
}
|
||||
|
||||
function randomPosition(center, radius) {
|
||||
return {
|
||||
x: center.x + (Math.random() * radius * 2.0) - radius,
|
||||
y: center.y + (Math.random() * radius * 2.0) - radius,
|
||||
z: center.z + (Math.random() * radius * 2.0) - radius
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
function randomColor() {
|
||||
return {
|
||||
red: Math.floor(Math.random() * 255),
|
||||
green: Math.floor(Math.random() * 255),
|
||||
blue: Math.floor(Math.random() * 255),
|
||||
};
|
||||
}
|
||||
|
||||
function randomDimensions() {
|
||||
return {
|
||||
x: 0.1 + Math.random() * 0.5,
|
||||
y: 0.1 + Math.random() * 0.1,
|
||||
z: 0.1 + Math.random() * 0.5
|
||||
};
|
||||
}
|
||||
|
||||
var entities = [];
|
||||
var entitiesToCreate = 0;
|
||||
var entitiesSpawned = 0;
|
||||
var spawnTimer = 0.0;
|
||||
var keepAliveTimer = 0.0;
|
||||
var updateTimer = 0.0;
|
||||
|
||||
function clear () {
|
||||
var ids = Entities.findEntities(MyAvatar.position, 50);
|
||||
var that = this;
|
||||
ids.forEach(function(id) {
|
||||
var properties = Entities.getEntityProperties(id);
|
||||
if (properties.name == TEST_ENTITY_NAME) {
|
||||
Entities.deleteEntity(id);
|
||||
}
|
||||
}, this);
|
||||
}
|
||||
|
||||
function createEntities () {
|
||||
print("Creating " + NUM_ENTITIES + " entities (UPDATE_INTERVAL = " + UPDATE_INTERVAL + ", KEEPALIVE_INTERVAL = " + KEEPALIVE_INTERVAL + ")");
|
||||
entitiesToCreate = NUM_ENTITIES;
|
||||
Script.update.connect(spawnEntities);
|
||||
}
|
||||
|
||||
function spawnEntities (dt) {
|
||||
if (entitiesToCreate <= 0) {
|
||||
Script.update.disconnect(spawnEntities);
|
||||
print("Finished spawning entities");
|
||||
}
|
||||
else if ((spawnTimer -= dt) < 0.0){
|
||||
spawnTimer = ENTITY_SPAWN_INTERVAL;
|
||||
|
||||
var n = Math.min(entitiesToCreate, ENTITY_SPAWN_LIMIT);
|
||||
print("Spawning " + n + " entities (" + (entitiesSpawned += n) + ")");
|
||||
|
||||
entitiesToCreate -= n;
|
||||
|
||||
var center = MyAvatar.position;
|
||||
center.y -= Y_OFFSET;
|
||||
|
||||
for (; n > 0; --n) {
|
||||
entities.push(makeEntity({
|
||||
type: "Shape",
|
||||
shape: SHAPES[n % SHAPES.length],
|
||||
name: TEST_ENTITY_NAME,
|
||||
position: randomPosition(center, RADIUS),
|
||||
color: randomColor(),
|
||||
dimensions: randomDimensions(),
|
||||
lifetime: ENTITY_LIFETIME
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function despawnEntities () {
|
||||
print("despawning entities");
|
||||
entities.forEach(function (entity) {
|
||||
entity.destroy();
|
||||
});
|
||||
entities = [];
|
||||
}
|
||||
|
||||
// Runs the following entity updates:
|
||||
// a) refreshes the timeout interval every KEEPALIVE_INTERVAL seconds, and
|
||||
// b) re-randomizes its position every UPDATE_INTERVAL seconds.
|
||||
// This should be sufficient to crash the client until the entity tree bug is fixed (and thereafter if it shows up again).
|
||||
function updateEntities (dt) {
|
||||
var updateLifetime = ((keepAliveTimer -= dt) < 0.0) ? ((keepAliveTimer = KEEPALIVE_INTERVAL), true) : false;
|
||||
var updateProperties = ((updateTimer -= dt) < 0.0) ? ((updateTimer = UPDATE_INTERVAL), true) : false;
|
||||
|
||||
if (updateLifetime || updateProperties) {
|
||||
var center = MyAvatar.position;
|
||||
center.y -= Y_OFFSET;
|
||||
|
||||
entities.forEach((updateLifetime && updateProperties && function (entity) {
|
||||
entity.update({
|
||||
lifetime: entity.getAge() + ENTITY_LIFETIME,
|
||||
position: randomPosition(center, RADIUS)
|
||||
});
|
||||
}) || (updateLifetime && function (entity) {
|
||||
entity.update({
|
||||
lifetime: entity.getAge() + ENTITY_LIFETIME
|
||||
});
|
||||
}) || (updateProperties && function (entity) {
|
||||
entity.update({
|
||||
position: randomPosition(center, RADIUS)
|
||||
});
|
||||
}) || null, this);
|
||||
}
|
||||
}
|
||||
|
||||
function init () {
|
||||
Script.update.disconnect(init);
|
||||
clear();
|
||||
createEntities();
|
||||
Script.update.connect(updateEntities);
|
||||
Script.scriptEnding.connect(despawnEntities);
|
||||
}
|
||||
|
||||
Script.update.connect(init);
|
||||
};
|
24
scripts/developer/tests/primitivesTest.js
Normal file
24
scripts/developer/tests/primitivesTest.js
Normal file
|
@ -0,0 +1,24 @@
|
|||
// entityEditStressTest.js
|
||||
//
|
||||
// Created by Seiji Emery on 8/31/15
|
||||
// Copyright 2015 High Fidelity, Inc.
|
||||
//
|
||||
// Stress tests the client + server-side entity trees by spawning huge numbers of entities in
|
||||
// close proximity to your avatar and updating them continuously (ie. applying position edits),
|
||||
// with the intent of discovering crashes and other bugs related to the entity, scripting,
|
||||
// rendering, networking, and/or physics subsystems.
|
||||
//
|
||||
// This script was originally created to find + diagnose an a clientside crash caused by improper
|
||||
// locking of the entity tree, but can be reused for other purposes.
|
||||
//
|
||||
// Distributed under the Apache License, Version 2.0.
|
||||
// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html
|
||||
//
|
||||
|
||||
Script.include("./entitySpawnTool.js");
|
||||
|
||||
|
||||
ENTITY_SPAWNER({
|
||||
updateInterval: 2.0
|
||||
})
|
||||
|
|
@ -25,6 +25,7 @@
|
|||
var ICON_FOR_TYPE = {
|
||||
Box: "V",
|
||||
Sphere: "n",
|
||||
Shape: "n",
|
||||
ParticleEffect: "",
|
||||
Model: "",
|
||||
Web: "q",
|
||||
|
@ -403,6 +404,10 @@
|
|||
var elColorGreen = document.getElementById("property-color-green");
|
||||
var elColorBlue = document.getElementById("property-color-blue");
|
||||
|
||||
var elShapeSections = document.querySelectorAll(".shape-section");
|
||||
allSections.push(elShapeSections);
|
||||
var elShape = document.getElementById("property-shape");
|
||||
|
||||
var elLightSections = document.querySelectorAll(".light-section");
|
||||
allSections.push(elLightSections);
|
||||
var elLightSpotLight = document.getElementById("property-light-spot-light");
|
||||
|
@ -666,7 +671,18 @@
|
|||
elHyperlinkSections[i].style.display = 'table';
|
||||
}
|
||||
|
||||
if (properties.type == "Box" || properties.type == "Sphere" || properties.type == "ParticleEffect") {
|
||||
if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere") {
|
||||
for (var i = 0; i < elShapeSections.length; i++) {
|
||||
elShapeSections[i].style.display = 'table';
|
||||
}
|
||||
} else {
|
||||
for (var i = 0; i < elShapeSections.length; i++) {
|
||||
console.log("Hiding shape section " + elShapeSections[i])
|
||||
elShapeSections[i].style.display = 'none';
|
||||
}
|
||||
}
|
||||
|
||||
if (properties.type == "Shape" || properties.type == "Box" || properties.type == "Sphere" || properties.type == "ParticleEffect") {
|
||||
for (var i = 0; i < elColorSections.length; i++) {
|
||||
elColorSections[i].style.display = 'table';
|
||||
}
|
||||
|
@ -958,6 +974,8 @@
|
|||
elLightExponent.addEventListener('change', createEmitNumberPropertyUpdateFunction('exponent', 2));
|
||||
elLightCutoff.addEventListener('change', createEmitNumberPropertyUpdateFunction('cutoff', 2));
|
||||
|
||||
elShape.addEventListener('change', createEmitTextPropertyUpdateFunction('shape'));
|
||||
|
||||
elWebSourceURL.addEventListener('change', createEmitTextPropertyUpdateFunction('sourceUrl'));
|
||||
|
||||
elModelURL.addEventListener('change', createEmitTextPropertyUpdateFunction('modelURL'));
|
||||
|
@ -1344,6 +1362,36 @@
|
|||
<span id="property-id" class="selectable"></span>
|
||||
</div>
|
||||
|
||||
<div class="section-header shape-group shape-section">
|
||||
<label>Shape</label><span>M</span>
|
||||
</div>
|
||||
<div class="shape-group shape-section property dropdown">
|
||||
<label for="property-shape">Shape</label>
|
||||
<select name="SelectShape" id="property-shape">
|
||||
<option value="Cube">Cube</option>
|
||||
<option value="Sphere">Sphere</option>
|
||||
<option value="Icosahedron">Icosahedron</option>
|
||||
<option value="Tetrahedron">Tetrahedron</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="shape-group shape-section property text">
|
||||
<label>Temp</label>
|
||||
<input type="text" id="property-temp-1">
|
||||
</div>
|
||||
<div class="shape-group shape-section property text">
|
||||
<label>Temp</label>
|
||||
<input type="text" id="property-temp-2">
|
||||
</div>
|
||||
<!--
|
||||
<div class="shape-group shape-section property text">
|
||||
<label>Temp</label>
|
||||
<input type="text" id="property-temp-3">
|
||||
</div>
|
||||
<div class="shape-group shape-section property text">
|
||||
<label>Temp</label>
|
||||
<input type="text" id="property-temp-4">
|
||||
</div>
|
||||
-->
|
||||
|
||||
<div class="section-header hyperlink-group hyperlink-section">
|
||||
<label>Hyperlink</label><span>M</span>
|
||||
|
@ -1678,7 +1726,6 @@
|
|||
<textarea id="property-model-original-textures" readonly></textarea>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="section-header text-group text-section">
|
||||
<label>Text</label><span>M</span>
|
||||
</div>
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#include <QDir>
|
||||
#include <ByteCountCoding.h>
|
||||
|
||||
#include <BoxEntityItem.h>
|
||||
#include <ShapeEntityItem.h>
|
||||
#include <EntityItemProperties.h>
|
||||
#include <Octree.h>
|
||||
#include <PathUtils.h>
|
||||
|
@ -155,7 +155,7 @@ int main(int argc, char** argv) {
|
|||
QFile file(getTestResourceDir() + "packet.bin");
|
||||
if (!file.open(QIODevice::ReadOnly)) return -1;
|
||||
QByteArray packet = file.readAll();
|
||||
EntityItemPointer item = BoxEntityItem::factory(EntityItemID(), EntityItemProperties());
|
||||
EntityItemPointer item = ShapeEntityItem::boxFactory(EntityItemID(), EntityItemProperties());
|
||||
ReadBitstreamToTreeParams params;
|
||||
params.bitstreamVersion = 33;
|
||||
|
||||
|
|
Loading…
Reference in a new issue