mirror of
https://github.com/overte-org/overte.git
synced 2025-08-06 06:35:05 +02:00
add back line entities, undo polyline changes temporarily
This commit is contained in:
parent
5dd00bed1d
commit
6094a2f0a0
24 changed files with 1061 additions and 433 deletions
|
@ -15,6 +15,7 @@
|
|||
#include <ObjectMotionState.h>
|
||||
|
||||
#include "RenderableLightEntityItem.h"
|
||||
#include "RenderableLineEntityItem.h"
|
||||
#include "RenderableModelEntityItem.h"
|
||||
#include "RenderableParticleEffectEntityItem.h"
|
||||
#include "RenderablePolyVoxEntityItem.h"
|
||||
|
@ -247,6 +248,10 @@ EntityRenderer::Pointer EntityRenderer::addToScene(EntityTreeRenderer& renderer,
|
|||
result = make_renderer<ParticleEffectEntityRenderer>(entity);
|
||||
break;
|
||||
|
||||
case Type::Line:
|
||||
result = make_renderer<LineEntityRenderer>(entity);
|
||||
break;
|
||||
|
||||
case Type::PolyLine:
|
||||
result = make_renderer<PolyLineEntityRenderer>(entity);
|
||||
break;
|
||||
|
|
61
libraries/entities-renderer/src/RenderableLineEntityItem.cpp
Normal file
61
libraries/entities-renderer/src/RenderableLineEntityItem.cpp
Normal file
|
@ -0,0 +1,61 @@
|
|||
//
|
||||
// RenderableLineEntityItem.cpp
|
||||
// libraries/entities-renderer/src/
|
||||
//
|
||||
// Created by Seth Alves on 5/11/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 "RenderableLineEntityItem.h"
|
||||
|
||||
#include <gpu/Batch.h>
|
||||
#include <PerfStat.h>
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
void LineEntityRenderer::onRemoveFromSceneTyped(const TypedEntityPointer& entity) {
|
||||
if (_lineVerticesID != GeometryCache::UNKNOWN_ID) {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
geometryCache->releaseID(_lineVerticesID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool LineEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
return entity->pointsChanged();
|
||||
}
|
||||
|
||||
void LineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
entity->resetPointsChanged();
|
||||
_linePoints = entity->getLinePoints();
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
_lineVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
glm::vec4 lineColor(toGlm(entity->getColor()), 1.0f);
|
||||
geometryCache->updateVertices(_lineVerticesID, _linePoints, lineColor);
|
||||
}
|
||||
|
||||
void LineEntityRenderer::doRender(RenderArgs* args) {
|
||||
if (_lineVerticesID == GeometryCache::UNKNOWN_ID) {
|
||||
return;
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("RenderableLineEntityItem::render");
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
const auto& modelTransform = getModelTransform();
|
||||
Transform transform = Transform();
|
||||
transform.setTranslation(modelTransform.getTranslation());
|
||||
transform.setRotation(modelTransform.getRotation());
|
||||
batch.setModelTransform(transform);
|
||||
if (_linePoints.size() > 1) {
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch);
|
||||
DependencyManager::get<GeometryCache>()->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
|
||||
}
|
||||
}
|
42
libraries/entities-renderer/src/RenderableLineEntityItem.h
Normal file
42
libraries/entities-renderer/src/RenderableLineEntityItem.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
//
|
||||
// RenderableLineEntityItem.h
|
||||
// libraries/entities-renderer/src/
|
||||
//
|
||||
// Created by Seth Alves on 5/11/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_RenderableLineEntityItem_h
|
||||
#define hifi_RenderableLineEntityItem_h
|
||||
|
||||
#include "RenderableEntityItem.h"
|
||||
#include <LineEntityItem.h>
|
||||
#include <GeometryCache.h>
|
||||
|
||||
|
||||
namespace render { namespace entities {
|
||||
|
||||
class LineEntityRenderer : public TypedEntityRenderer<LineEntityItem> {
|
||||
using Parent = TypedEntityRenderer<LineEntityItem>;
|
||||
friend class EntityRenderer;
|
||||
|
||||
public:
|
||||
LineEntityRenderer(const EntityItemPointer& entity) : Parent(entity) { }
|
||||
|
||||
protected:
|
||||
virtual void onRemoveFromSceneTyped(const TypedEntityPointer& entity) override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
private:
|
||||
int _lineVerticesID { GeometryCache::UNKNOWN_ID };
|
||||
QVector<glm::vec3> _linePoints;
|
||||
};
|
||||
|
||||
} } // namespace
|
||||
|
||||
#endif // hifi_RenderableLineEntityItem_h
|
|
@ -19,35 +19,66 @@
|
|||
#include <PerfStat.h>
|
||||
#include <shaders/Shaders.h>
|
||||
|
||||
#include "paintStroke_shared.slh"
|
||||
//#define POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
# include <FadeEffect.h>
|
||||
#endif
|
||||
|
||||
using namespace render;
|
||||
using namespace render::entities;
|
||||
|
||||
gpu::PipelinePointer PolyLineEntityRenderer::_pipeline = nullptr;
|
||||
static uint8_t CUSTOM_PIPELINE_NUMBER { 0 };
|
||||
static const int32_t PAINTSTROKE_TEXTURE_SLOT { 0 };
|
||||
static gpu::Stream::FormatPointer polylineFormat;
|
||||
static gpu::PipelinePointer polylinePipeline;
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
static gpu::PipelinePointer polylineFadePipeline;
|
||||
#endif
|
||||
|
||||
static const QUrl DEFAULT_POLYLINE_TEXTURE = QUrl(PathUtils::resourcesPath() + "images/paintStroke.png");
|
||||
static render::ShapePipelinePointer shapePipelineFactory(const render::ShapePlumber& plumber, const render::ShapeKey& key, gpu::Batch& batch) {
|
||||
if (!polylinePipeline) {
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
auto fadeVS = gpu::Shader::createVertex(std::string(paintStroke_fade_vert));
|
||||
auto fadePS = gpu::Shader::createPixel(std::string(paintStroke_fade_frag));
|
||||
gpu::ShaderPointer fadeProgram = gpu::Shader::createProgram(fadeVS, fadePS);
|
||||
#endif
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true,
|
||||
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);
|
||||
polylinePipeline = gpu::Pipeline::create(program, state);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
_fadePipeline = gpu::Pipeline::create(fadeProgram, state);
|
||||
#endif
|
||||
}
|
||||
|
||||
PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(DEFAULT_POLYLINE_TEXTURE);
|
||||
|
||||
_polylineGeometryBuffer = std::make_shared<gpu::Buffer>();
|
||||
|
||||
_polylineDataBuffer = std::make_shared<gpu::Buffer>();
|
||||
_polylineDataBuffer->resize(sizeof(PolylineData));
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
if (key.isFaded()) {
|
||||
auto fadeEffect = DependencyManager::get<FadeEffect>();
|
||||
return std::make_shared<render::ShapePipeline>(_fadePipeline, nullptr, fadeEffect->getBatchSetter(), fadeEffect->getItemUniformSetter());
|
||||
} else {
|
||||
#endif
|
||||
return std::make_shared<render::ShapePipeline>(polylinePipeline, nullptr, nullptr, nullptr);
|
||||
#ifdef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::buildPipeline() {
|
||||
// FIXME: opaque pipeline
|
||||
gpu::ShaderPointer program = gpu::Shader::createProgram(shader::entities_renderer::program::paintStroke);
|
||||
gpu::StatePointer state = gpu::StatePointer(new gpu::State());
|
||||
state->setCullMode(gpu::State::CullMode::CULL_NONE);
|
||||
state->setDepthTest(true, true, gpu::LESS_EQUAL);
|
||||
PrepareStencil::testMask(*state);
|
||||
state->setBlendFunction(true,
|
||||
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);
|
||||
_pipeline = gpu::Pipeline::create(program, state);
|
||||
PolyLineEntityRenderer::PolyLineEntityRenderer(const EntityItemPointer& entity) : Parent(entity) {
|
||||
static std::once_flag once;
|
||||
std::call_once(once, [&] {
|
||||
CUSTOM_PIPELINE_NUMBER = render::ShapePipeline::registerCustomShapePipelineFactory(shapePipelineFactory);
|
||||
polylineFormat.reset(new gpu::Stream::Format());
|
||||
polylineFormat->setAttribute(gpu::Stream::POSITION, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), offsetof(Vertex, position));
|
||||
polylineFormat->setAttribute(gpu::Stream::NORMAL, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::XYZ), offsetof(Vertex, normal));
|
||||
polylineFormat->setAttribute(gpu::Stream::TEXCOORD, 0, gpu::Element(gpu::VEC2, gpu::FLOAT, gpu::UV), offsetof(Vertex, uv));
|
||||
polylineFormat->setAttribute(gpu::Stream::COLOR, 0, gpu::Element(gpu::VEC3, gpu::FLOAT, gpu::RGB), offsetof(Vertex, color));
|
||||
});
|
||||
|
||||
_verticesBuffer = std::make_shared<gpu::Buffer>();
|
||||
}
|
||||
|
||||
ItemKey PolyLineEntityRenderer::getKey() {
|
||||
|
@ -55,165 +86,152 @@ ItemKey PolyLineEntityRenderer::getKey() {
|
|||
}
|
||||
|
||||
ShapeKey PolyLineEntityRenderer::getShapeKey() {
|
||||
return ShapeKey::Builder().withOwnPipeline().withTranslucent().withoutCullFace();
|
||||
}
|
||||
|
||||
bool PolyLineEntityRenderer::needsRenderUpdate() const {
|
||||
bool textureLoadedChanged = resultWithReadLock<bool>([&] {
|
||||
return (!_textureLoaded && _texture && _texture->isLoaded());
|
||||
});
|
||||
|
||||
if (textureLoadedChanged) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return Parent::needsRenderUpdate();
|
||||
return ShapeKey::Builder().withCustom(CUSTOM_PIPELINE_NUMBER).build();
|
||||
}
|
||||
|
||||
bool PolyLineEntityRenderer::needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const {
|
||||
return (
|
||||
entity->pointsChanged() ||
|
||||
entity->widthsChanged() ||
|
||||
entity->strokeWidthsChanged() ||
|
||||
entity->normalsChanged() ||
|
||||
entity->texturesChanged() ||
|
||||
entity->colorsChanged() ||
|
||||
_isUVModeStretch != entity->getIsUVModeStretch() ||
|
||||
_glow != entity->getGlow() ||
|
||||
_faceCamera != entity->getFaceCamera()
|
||||
entity->strokeColorsChanged()
|
||||
);
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
auto pointsChanged = entity->pointsChanged();
|
||||
auto widthsChanged = entity->widthsChanged();
|
||||
auto normalsChanged = entity->normalsChanged();
|
||||
auto colorsChanged = entity->colorsChanged();
|
||||
|
||||
bool isUVModeStretch = entity->getIsUVModeStretch();
|
||||
bool glow = entity->getGlow();
|
||||
bool faceCamera = entity->getFaceCamera();
|
||||
|
||||
entity->resetPolyLineChanged();
|
||||
|
||||
// Transform
|
||||
_renderTransform = Transform();
|
||||
_renderTransform.setTranslation(entity->getWorldPosition() - entity->getPolylineCenter());
|
||||
_renderTransform.setRotation(entity->getWorldOrientation());
|
||||
|
||||
// Textures
|
||||
void PolyLineEntityRenderer::doRenderUpdateSynchronousTyped(const ScenePointer& scene, Transaction& transaction, const TypedEntityPointer& entity) {
|
||||
static const QUrl DEFAULT_POLYLINE_TEXTURE = QUrl(PathUtils::resourcesPath() + "images/paintStroke.png");
|
||||
QUrl entityTextures = DEFAULT_POLYLINE_TEXTURE;
|
||||
if (entity->texturesChanged()) {
|
||||
entity->resetTexturesChanged();
|
||||
QUrl entityTextures = DEFAULT_POLYLINE_TEXTURE;
|
||||
auto textures = entity->getTextures();
|
||||
if (!textures.isEmpty()) {
|
||||
entityTextures = QUrl(textures);
|
||||
}
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(entityTextures);
|
||||
_textureAspectRatio = 1.0f;
|
||||
_textureLoaded = false;
|
||||
}
|
||||
|
||||
bool textureChanged = false;
|
||||
if (!_textureLoaded && _texture && _texture->isLoaded()) {
|
||||
textureChanged = true;
|
||||
_textureAspectRatio = (float)_texture->getOriginalHeight() / (float)_texture->getOriginalWidth();
|
||||
_textureLoaded = true;
|
||||
}
|
||||
|
||||
// Geometry
|
||||
if (pointsChanged) {
|
||||
_points = entity->getLinePoints();
|
||||
}
|
||||
if (widthsChanged) {
|
||||
_widths = entity->getStrokeWidths();
|
||||
}
|
||||
if (normalsChanged) {
|
||||
_normals = entity->getNormals();
|
||||
}
|
||||
if (colorsChanged) {
|
||||
_colors = entity->getStrokeColors();
|
||||
_color = toGlm(entity->getColor());
|
||||
}
|
||||
if (_isUVModeStretch != isUVModeStretch || pointsChanged || widthsChanged || normalsChanged || colorsChanged || textureChanged) {
|
||||
_isUVModeStretch = isUVModeStretch;
|
||||
updateGeometry();
|
||||
}
|
||||
|
||||
// Data
|
||||
if (faceCamera != _faceCamera || glow != _glow) {
|
||||
_faceCamera = faceCamera;
|
||||
_glow = glow;
|
||||
updateData();
|
||||
|
||||
|
||||
if (!_texture) {
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(entityTextures);
|
||||
}
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::updateGeometry() {
|
||||
int maxNumVertices = std::min(_points.length(), _normals.length());
|
||||
void PolyLineEntityRenderer::doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) {
|
||||
auto pointsChanged = entity->pointsChanged();
|
||||
auto strokeWidthsChanged = entity->strokeWidthsChanged();
|
||||
auto normalsChanged = entity->normalsChanged();
|
||||
auto strokeColorsChanged = entity->strokeColorsChanged();
|
||||
|
||||
|
||||
bool isUVModeStretch = entity->getIsUVModeStretch();
|
||||
entity->resetPolyLineChanged();
|
||||
|
||||
_polylineTransform = Transform();
|
||||
_polylineTransform.setTranslation(entity->getWorldPosition());
|
||||
_polylineTransform.setRotation(entity->getWorldOrientation());
|
||||
|
||||
if (pointsChanged) {
|
||||
_lastPoints = entity->getLinePoints();
|
||||
}
|
||||
if (strokeWidthsChanged) {
|
||||
_lastStrokeWidths = entity->getStrokeWidths();
|
||||
}
|
||||
if (normalsChanged) {
|
||||
_lastNormals = entity->getNormals();
|
||||
}
|
||||
if (strokeColorsChanged) {
|
||||
_lastStrokeColors = entity->getStrokeColors();
|
||||
_lastStrokeColors = _lastNormals.size() == _lastStrokeColors.size() ? _lastStrokeColors : QVector<glm::vec3>({ toGlm(entity->getColor()) });
|
||||
}
|
||||
if (pointsChanged || strokeWidthsChanged || normalsChanged || strokeColorsChanged) {
|
||||
_empty = std::min(_lastPoints.size(), std::min(_lastNormals.size(), _lastStrokeWidths.size())) < 2;
|
||||
if (!_empty) {
|
||||
updateGeometry(updateVertices(_lastPoints, _lastNormals, _lastStrokeWidths, _lastStrokeColors, isUVModeStretch, _textureAspectRatio));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::updateGeometry(const std::vector<Vertex>& vertices) {
|
||||
_numVertices = (uint32_t)vertices.size();
|
||||
auto bufferSize = _numVertices * sizeof(Vertex);
|
||||
if (bufferSize > _verticesBuffer->getSize()) {
|
||||
_verticesBuffer->resize(bufferSize);
|
||||
}
|
||||
_verticesBuffer->setSubData(0, vertices);
|
||||
}
|
||||
|
||||
std::vector<PolyLineEntityRenderer::Vertex> PolyLineEntityRenderer::updateVertices(const QVector<glm::vec3>& points,
|
||||
const QVector<glm::vec3>& normals,
|
||||
const QVector<float>& strokeWidths,
|
||||
const QVector<glm::vec3>& strokeColors,
|
||||
const bool isUVModeStretch,
|
||||
const float textureAspectRatio) {
|
||||
// Calculate the minimum vector size out of normals, points, and stroke widths
|
||||
int size = std::min(points.size(), std::min(normals.size(), strokeWidths.size()));
|
||||
|
||||
std::vector<Vertex> vertices;
|
||||
|
||||
// Guard against an empty polyline
|
||||
if (size <= 0) {
|
||||
return vertices;
|
||||
}
|
||||
|
||||
float uCoordInc = 1.0f / size;
|
||||
float uCoord = 0.0f;
|
||||
int finalIndex = size - 1;
|
||||
glm::vec3 binormal;
|
||||
float accumulatedDistance = 0.0f;
|
||||
float distanceToLastPoint = 0.0f;
|
||||
float accumulatedStrokeWidth = 0.0f;
|
||||
float strokeWidth = 0.0f;
|
||||
bool doesStrokeWidthVary = false;
|
||||
if (_widths.size() >= 0) {
|
||||
for (int i = 1; i < maxNumVertices; i++) {
|
||||
float width = PolyLineEntityItem::DEFAULT_LINE_WIDTH;
|
||||
if (i < _widths.length()) {
|
||||
width = _widths[i];
|
||||
}
|
||||
if (width != _widths[i - 1]) {
|
||||
doesStrokeWidthVary = true;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
for (int i = 1; i < strokeWidths.size(); i++) {
|
||||
if (strokeWidths[i] != strokeWidths[i - 1]) {
|
||||
doesStrokeWidthVary = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
float uCoordInc = 1.0f / maxNumVertices;
|
||||
float uCoord = 0.0f;
|
||||
float accumulatedDistance = 0.0f;
|
||||
float accumulatedStrokeWidth = 0.0f;
|
||||
glm::vec3 binormal;
|
||||
for (int i = 0; i <= finalIndex; i++) {
|
||||
const float& width = strokeWidths.at(i);
|
||||
const auto& point = points.at(i);
|
||||
const auto& normal = normals.at(i);
|
||||
const auto& color = strokeColors.size() == normals.size() ? strokeColors.at(i) : strokeColors.at(0);
|
||||
int vertexIndex = i * 2;
|
||||
|
||||
|
||||
std::vector<PolylineVertex> vertices;
|
||||
vertices.reserve(maxNumVertices);
|
||||
for (int i = 0; i < maxNumVertices; i++) {
|
||||
// Position
|
||||
glm::vec3 point = _points[i];
|
||||
if (!isUVModeStretch && i >= 1) {
|
||||
distanceToLastPoint = glm::distance(points.at(i), points.at(i - 1));
|
||||
accumulatedDistance += distanceToLastPoint;
|
||||
strokeWidth = 2 * strokeWidths[i];
|
||||
|
||||
// uCoord
|
||||
float width = i < _widths.size() ? _widths[i] : PolyLineEntityItem::DEFAULT_LINE_WIDTH;
|
||||
if (i > 0) { // First uCoord is 0.0f
|
||||
if (!_isUVModeStretch) {
|
||||
accumulatedDistance += glm::distance(point, _points[i - 1]);
|
||||
|
||||
if (doesStrokeWidthVary) {
|
||||
//If the stroke varies along the line the texture will stretch more or less depending on the speed
|
||||
//because it looks better than using the same method as below
|
||||
accumulatedStrokeWidth += width;
|
||||
float increaseValue = 1;
|
||||
if (accumulatedStrokeWidth != 0) {
|
||||
float newUcoord = glm::ceil((_textureAspectRatio * accumulatedDistance) / (accumulatedStrokeWidth / i));
|
||||
increaseValue = newUcoord - uCoord;
|
||||
}
|
||||
|
||||
increaseValue = increaseValue > 0 ? increaseValue : 1;
|
||||
uCoord += increaseValue;
|
||||
} else {
|
||||
// If the stroke width is constant then the textures should keep the aspect ratio along the line
|
||||
uCoord = (_textureAspectRatio * accumulatedDistance) / width;
|
||||
if (doesStrokeWidthVary) {
|
||||
//If the stroke varies along the line the texture will stretch more or less depending on the speed
|
||||
//because it looks better than using the same method as below
|
||||
accumulatedStrokeWidth += strokeWidth;
|
||||
float increaseValue = 1;
|
||||
if (accumulatedStrokeWidth != 0) {
|
||||
float newUcoord = glm::ceil(((1.0f / textureAspectRatio) * accumulatedDistance) / (accumulatedStrokeWidth / i));
|
||||
increaseValue = newUcoord - uCoord;
|
||||
}
|
||||
|
||||
increaseValue = increaseValue > 0 ? increaseValue : 1;
|
||||
uCoord += increaseValue;
|
||||
} else {
|
||||
uCoord += uCoordInc;
|
||||
//If the stroke width is constant then the textures should keep the aspect ratio along the line
|
||||
uCoord = ((1.0f / textureAspectRatio) * accumulatedDistance) / strokeWidth;
|
||||
}
|
||||
} else if (vertexIndex >= 2) {
|
||||
uCoord += uCoordInc;
|
||||
}
|
||||
|
||||
// Color
|
||||
glm::vec3 color = i < _colors.length() ? _colors[i] : _color;
|
||||
|
||||
// Normal
|
||||
glm::vec3 normal = _normals[i];
|
||||
|
||||
// Binormal
|
||||
// For last point we can assume binormals are the same since it represents the last two vertices of quad
|
||||
if (i < maxNumVertices - 1) {
|
||||
glm::vec3 tangent = _points[i + 1] - point;
|
||||
binormal = glm::normalize(glm::cross(tangent, normal));
|
||||
if (i < finalIndex) {
|
||||
const auto tangent = points.at(i + 1) - point;
|
||||
binormal = glm::normalize(glm::cross(tangent, normal)) * width;
|
||||
|
||||
// Check to make sure binormal is not a NAN. If it is, don't add to vertices vector
|
||||
if (binormal.x != binormal.x) {
|
||||
|
@ -221,36 +239,54 @@ void PolyLineEntityRenderer::updateGeometry() {
|
|||
}
|
||||
}
|
||||
|
||||
PolylineVertex vertex = { glm::vec4(point, uCoord), glm::vec4(color, 1.0f), glm::vec4(normal, 0.0f), glm::vec4(binormal, 0.5f * width) };
|
||||
vertices.push_back(vertex);
|
||||
const auto v1 = points.at(i) + binormal;
|
||||
const auto v2 = points.at(i) - binormal;
|
||||
vertices.emplace_back(v1, normal, vec2(uCoord, 0.0f), color);
|
||||
vertices.emplace_back(v2, normal, vec2(uCoord, 1.0f), color);
|
||||
}
|
||||
|
||||
_numVertices = vertices.size();
|
||||
_polylineGeometryBuffer->setData(vertices.size() * sizeof(PolylineVertex), (const gpu::Byte*) vertices.data());
|
||||
return vertices;
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::updateData() {
|
||||
PolylineData data { glm::vec2(_faceCamera, _glow), glm::vec2(0.0f) };
|
||||
_polylineDataBuffer->setSubData(0, data);
|
||||
scriptable::ScriptableModelBase PolyLineEntityRenderer::getScriptableModel() {
|
||||
// TODO: adapt polyline into a triangles mesh...
|
||||
return EntityRenderer::getScriptableModel();
|
||||
}
|
||||
|
||||
void PolyLineEntityRenderer::doRender(RenderArgs* args) {
|
||||
if (_numVertices < 2) {
|
||||
if (_empty) {
|
||||
return;
|
||||
}
|
||||
|
||||
PerformanceTimer perfTimer("RenderablePolyLineEntityItem::render");
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
|
||||
if (!_pipeline) {
|
||||
buildPipeline();
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
batch.setModelTransform(_polylineTransform);
|
||||
|
||||
if (_texture && _texture->isLoaded()) {
|
||||
batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, _texture->getGPUTexture());
|
||||
} else {
|
||||
batch.setResourceTexture(PAINTSTROKE_TEXTURE_SLOT, DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
}
|
||||
|
||||
batch.setPipeline(_pipeline);
|
||||
batch.setModelTransform(_renderTransform);
|
||||
batch.setResourceTexture(0, _textureLoaded ? _texture->getGPUTexture() : DependencyManager::get<TextureCache>()->getWhiteTexture());
|
||||
batch.setResourceBuffer(0, _polylineGeometryBuffer);
|
||||
batch.setUniformBuffer(0, _polylineDataBuffer);
|
||||
batch.draw(gpu::TRIANGLE_STRIP, 2 * _numVertices, 0);
|
||||
float textureWidth = (float)_texture->getOriginalWidth();
|
||||
float textureHeight = (float)_texture->getOriginalHeight();
|
||||
if (textureWidth != 0 && textureHeight != 0) {
|
||||
_textureAspectRatio = textureWidth / textureHeight;
|
||||
}
|
||||
|
||||
batch.setInputFormat(polylineFormat);
|
||||
batch.setInputBuffer(0, _verticesBuffer, 0, sizeof(Vertex));
|
||||
|
||||
#ifndef POLYLINE_ENTITY_USE_FADE_EFFECT
|
||||
// glColor4f must be called after setInputFormat if it must be taken into account
|
||||
if (_isFading) {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, Interpolate::calculateFadeRatio(_fadeStartTime));
|
||||
} else {
|
||||
batch._glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
|
||||
}
|
||||
#endif
|
||||
|
||||
batch.draw(gpu::TRIANGLE_STRIP, _numVertices, 0);
|
||||
}
|
||||
|
|
|
@ -25,40 +25,52 @@ class PolyLineEntityRenderer : public TypedEntityRenderer<PolyLineEntityItem> {
|
|||
public:
|
||||
PolyLineEntityRenderer(const EntityItemPointer& entity);
|
||||
|
||||
// FIXME: shouldn't always be transparent: take into account texture and glow
|
||||
virtual bool isTransparent() const override { return true; }
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
protected:
|
||||
virtual bool needsRenderUpdate() const override;
|
||||
virtual bool needsRenderUpdateFromTypedEntity(const TypedEntityPointer& entity) const override;
|
||||
virtual void doRenderUpdateSynchronousTyped(const ScenePointer& scene,
|
||||
Transaction& transaction,
|
||||
const TypedEntityPointer& entity) override;
|
||||
virtual void doRenderUpdateAsynchronousTyped(const TypedEntityPointer& entity) override;
|
||||
|
||||
virtual ItemKey getKey() override;
|
||||
virtual ShapeKey getShapeKey() override;
|
||||
virtual void doRender(RenderArgs* args) override;
|
||||
|
||||
void buildPipeline();
|
||||
void updateGeometry();
|
||||
void updateData();
|
||||
virtual bool isTransparent() const override { return true; }
|
||||
|
||||
QVector<glm::vec3> _points;
|
||||
QVector<glm::vec3> _normals;
|
||||
QVector<glm::vec3> _colors;
|
||||
glm::vec3 _color;
|
||||
QVector<float> _widths;
|
||||
struct Vertex {
|
||||
Vertex() {}
|
||||
Vertex(const vec3& position, const vec3& normal, const vec2& uv, const vec3& color) : position(position),
|
||||
normal(normal),
|
||||
uv(uv),
|
||||
color(color) {}
|
||||
vec3 position;
|
||||
vec3 normal;
|
||||
vec2 uv;
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
void updateGeometry(const std::vector<Vertex>& vertices);
|
||||
static std::vector<Vertex> updateVertices(const QVector<glm::vec3>& points,
|
||||
const QVector<glm::vec3>& normals,
|
||||
const QVector<float>& strokeWidths,
|
||||
const QVector<glm::vec3>& strokeColors,
|
||||
const bool isUVModeStretch,
|
||||
const float textureAspectRatio);
|
||||
|
||||
Transform _polylineTransform;
|
||||
QVector<glm::vec3> _lastPoints;
|
||||
QVector<glm::vec3> _lastNormals;
|
||||
QVector<glm::vec3> _lastStrokeColors;
|
||||
QVector<float> _lastStrokeWidths;
|
||||
gpu::BufferPointer _verticesBuffer;
|
||||
|
||||
uint32_t _numVertices { 0 };
|
||||
bool _empty{ true };
|
||||
NetworkTexturePointer _texture;
|
||||
float _textureAspectRatio { 1.0f };
|
||||
bool _textureLoaded { false };
|
||||
|
||||
bool _isUVModeStretch;
|
||||
bool _faceCamera;
|
||||
bool _glow;
|
||||
|
||||
int _numVertices;
|
||||
gpu::BufferPointer _polylineDataBuffer;
|
||||
gpu::BufferPointer _polylineGeometryBuffer;
|
||||
static gpu::PipelinePointer _pipeline;
|
||||
};
|
||||
|
||||
} } // namespace
|
||||
|
|
|
@ -14,27 +14,21 @@
|
|||
|
||||
<@include DeferredBufferWrite.slh@>
|
||||
|
||||
<@include paintStroke.slh@>
|
||||
<$declarePolyLineBuffers()$>
|
||||
// the albedo texture
|
||||
LAYOUT(binding=0) uniform sampler2D originalTexture;
|
||||
|
||||
LAYOUT(binding=0) uniform sampler2D _texture;
|
||||
|
||||
layout(location=0) in vec3 _normalWS;
|
||||
layout(location=1) in vec2 _texCoord;
|
||||
layout(location=2) in vec4 _color;
|
||||
layout(location=3) in float _distanceFromCenter;
|
||||
// the interpolated normal
|
||||
layout(location=0) in vec3 interpolatedNormal;
|
||||
layout(location=1) in vec2 varTexcoord;
|
||||
layout(location=2) in vec4 varColor;
|
||||
|
||||
void main(void) {
|
||||
vec4 texel = texture(_texture, _texCoord);
|
||||
int frontCondition = 1 - 2 * int(gl_FrontFacing);
|
||||
vec3 color = _color.rgb * texel.rgb;
|
||||
float alpha = texel.a * _color.a;
|
||||
|
||||
alpha *= mix(1.0, pow(1.0 - abs(_distanceFromCenter), 10.0), _polylineData.faceCameraGlow.y);
|
||||
|
||||
vec4 texel = texture(originalTexture, varTexcoord);
|
||||
int frontCondition = 1 -int(gl_FrontFacing) * 2;
|
||||
vec3 color = varColor.rgb;
|
||||
packDeferredFragmentTranslucent(
|
||||
float(frontCondition) * _normalWS,
|
||||
alpha,
|
||||
color,
|
||||
DEFAULT_ROUGHNESS);
|
||||
float(frontCondition) * interpolatedNormal,
|
||||
texel.a * varColor.a,
|
||||
color * texel.rgb,
|
||||
10.0);
|
||||
}
|
||||
|
|
|
@ -1,48 +0,0 @@
|
|||
<!
|
||||
// paintStroke.slh
|
||||
//
|
||||
// Created by Sam Gondelman on 12/13/2018
|
||||
// Copyright 2018 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
|
||||
!>
|
||||
|
||||
<@if not PAINTSTROKE_SLH@>
|
||||
<@def PAINTSTROKE_SLH@>
|
||||
|
||||
<@include paintStroke_Shared.slh@>
|
||||
<@include gpu/ShaderConstants.h@>
|
||||
|
||||
<@func declarePolyLineBuffers() @>
|
||||
|
||||
// Hack comment to absorb the extra '//' scribe prepends
|
||||
|
||||
#if !defined(GPU_SSBO_TRANSFORM_OBJECT)
|
||||
LAYOUT(binding=GPU_RESOURCE_BUFFER_SLOT0_TEXTURE) uniform samplerBuffer polylineVerticesBuffer;
|
||||
PolylineVertex getPolylineVertex(int i) {
|
||||
int offset = 4 * i;
|
||||
PolylineVertex vertex;
|
||||
vertex.positionAndUCoord = texelFetch(polylineVerticesBuffer, offset);
|
||||
vertex.color = texelFetch(polylineVerticesBuffer, offset + 1);
|
||||
vertex.normal = texelFetch(polylineVerticesBuffer, offset + 2);
|
||||
vertex.binormalAndHalfWidth = texelFetch(polylineVerticesBuffer, offset + 3);
|
||||
return vertex;
|
||||
}
|
||||
#else
|
||||
LAYOUT_STD140(binding=GPU_RESOURCE_BUFFER_SLOT0_STORAGE) buffer polylineVerticesBuffer {
|
||||
PolylineVertex _vertices[];
|
||||
};
|
||||
PolylineVertex getPolylineVertex(int i) {
|
||||
PolylineVertex vertex = _vertices[i];
|
||||
return vertex;
|
||||
}
|
||||
#endif
|
||||
|
||||
LAYOUT_STD140(binding=0) uniform polylineDataBuffer {
|
||||
PolylineData _polylineData;
|
||||
};
|
||||
|
||||
<@endfunc@>
|
||||
|
||||
<@endif@>
|
|
@ -17,45 +17,23 @@
|
|||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
<@include paintStroke.slh@>
|
||||
<$declarePolyLineBuffers()$>
|
||||
// the interpolated normal
|
||||
layout(location=0) out vec3 interpolatedNormal;
|
||||
|
||||
layout(location=0) out vec3 _normalWS;
|
||||
layout(location=1) out vec2 _texCoord;
|
||||
layout(location=2) out vec4 _color;
|
||||
layout(location=3) out float _distanceFromCenter;
|
||||
//the diffuse texture
|
||||
layout(location=1) out vec2 varTexcoord;
|
||||
|
||||
layout(location=2) out vec4 varColor;
|
||||
|
||||
void main(void) {
|
||||
PolylineVertex vertex = getPolylineVertex(gl_VertexID / 2);
|
||||
float evenVertex = float(gl_VertexID % 2 == 0);
|
||||
varTexcoord = inTexCoord0.st;
|
||||
|
||||
_texCoord = vec2(vertex.positionAndUCoord.w, mix(1.0, 0.0, evenVertex));
|
||||
_color = color_sRGBAToLinear(vertex.color);
|
||||
// pass along the diffuse color
|
||||
varColor = color_sRGBAToLinear(inColor);
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
_distanceFromCenter = -1.0 + 2.0 * evenVertex;
|
||||
vec4 position = vec4(vertex.positionAndUCoord.xyz, 1.0);
|
||||
vec3 normal = vertex.normal.xyz;
|
||||
vec3 binormal = vertex.binormalAndHalfWidth.xyz;
|
||||
if (_polylineData.faceCameraGlow.x != 0.0) {
|
||||
vec4 posEye;
|
||||
vec3 normalEye;
|
||||
vec3 binormalEye;
|
||||
<$transformModelToEyePos(cam, obj, position, posEye)$>
|
||||
<$transformModelToEyeDir(cam, obj, normal, normalEye)$>
|
||||
<$transformModelToEyeDir(cam, obj, binormal, binormalEye)$>
|
||||
|
||||
vec3 tangentEye = cross(binormalEye, normalEye);
|
||||
// new normal faces the camera
|
||||
normalEye = normalize(posEye.xyz);
|
||||
binormalEye = normalize(cross(normalEye, tangentEye));
|
||||
posEye.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormalEye;
|
||||
<$transformEyeToClipPos(cam, posEye, gl_Position)$>
|
||||
<$transformEyeToWorldDir(cam, normalEye, _normalWS)$>
|
||||
} else {
|
||||
position.xyz += _distanceFromCenter * vertex.binormalAndHalfWidth.w * binormal;
|
||||
<$transformModelToClipPos(cam, obj, position, gl_Position)$>
|
||||
<$transformModelToWorldDir(cam, obj, normal, _normalWS)$>
|
||||
}
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, interpolatedNormal)$>
|
||||
}
|
|
@ -1,25 +0,0 @@
|
|||
// glsl / C++ compatible source as interface for FadeEffect
|
||||
#ifdef __cplusplus
|
||||
# define _VEC4 glm::vec4
|
||||
# define _VEC2 glm::vec2
|
||||
#else
|
||||
# define _VEC4 vec4
|
||||
# define _VEC2 vec2
|
||||
#endif
|
||||
|
||||
struct PolylineVertex {
|
||||
_VEC4 positionAndUCoord;
|
||||
_VEC4 color;
|
||||
_VEC4 normal;
|
||||
_VEC4 binormalAndHalfWidth;
|
||||
};
|
||||
|
||||
struct PolylineData {
|
||||
_VEC2 faceCameraGlow;
|
||||
_VEC2 spare;
|
||||
};
|
||||
|
||||
// <@if 1@>
|
||||
// Trigger Scribe include
|
||||
// <@endif@> <!def that !>
|
||||
//
|
52
libraries/entities-renderer/src/paintStroke_fade.slf
Normal file
52
libraries/entities-renderer/src/paintStroke_fade.slf
Normal file
|
@ -0,0 +1,52 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// paintStroke_fade.frag
|
||||
// fragment shader
|
||||
//
|
||||
// Created by Olivier Prat on 19/07/17.
|
||||
// Copyright 2017 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 DeferredBufferWrite.slh@>
|
||||
|
||||
<@include Fade.slh@>
|
||||
<$declareFadeFragment()$>
|
||||
|
||||
// the albedo texture
|
||||
LAYOUT(binding=0) uniform sampler2D originalTexture;
|
||||
|
||||
// the interpolated normal
|
||||
layout(location=0) in vec3 interpolatedNormal;
|
||||
layout(location=1) in vec2 varTexcoord;
|
||||
layout(location=2) in vec4 varColor;
|
||||
layout(location=3) in vec4 _worldPosition;
|
||||
|
||||
struct PolyLineUniforms {
|
||||
vec3 color;
|
||||
};
|
||||
|
||||
LAYOUT(binding=0) uniform polyLineBuffer {
|
||||
PolyLineUniforms polyline;
|
||||
};
|
||||
|
||||
void main(void) {
|
||||
vec3 fadeEmissive;
|
||||
FadeObjectParams fadeParams;
|
||||
|
||||
<$fetchFadeObjectParams(fadeParams)$>
|
||||
applyFade(fadeParams, _worldPosition.xyz, fadeEmissive);
|
||||
|
||||
vec4 texel = texture(originalTexture, varTexcoord);
|
||||
int frontCondition = 1 -int(gl_FrontFacing) * 2;
|
||||
vec3 color = varColor.rgb;
|
||||
packDeferredFragmentTranslucent(
|
||||
interpolatedNormal * float(frontCondition),
|
||||
texel.a * varColor.a,
|
||||
polyline.color * texel.rgb + fadeEmissive,
|
||||
10.0);
|
||||
}
|
43
libraries/entities-renderer/src/paintStroke_fade.slv
Normal file
43
libraries/entities-renderer/src/paintStroke_fade.slv
Normal file
|
@ -0,0 +1,43 @@
|
|||
<@include gpu/Config.slh@>
|
||||
<$VERSION_HEADER$>
|
||||
// Generated on <$_SCRIBE_DATE$>
|
||||
//
|
||||
// paintStroke_fade.vert
|
||||
// vertex shader
|
||||
//
|
||||
// Created by Olivier Prat on 19/07/17.
|
||||
// Copyright 2017 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 gpu/Inputs.slh@>
|
||||
<@include gpu/Color.slh@>
|
||||
<@include gpu/Transform.slh@>
|
||||
<$declareStandardTransform()$>
|
||||
|
||||
// the interpolated normal
|
||||
layout(location=0) out vec3 interpolatedNormal;
|
||||
|
||||
//the diffuse texture
|
||||
layout(location=1) out vec2 varTexcoord;
|
||||
|
||||
layout(location=2) out vec4 varColor;
|
||||
layout(location=3) out vec4 _worldPosition;
|
||||
|
||||
void main(void) {
|
||||
|
||||
varTexcoord = inTexCoord0.st;
|
||||
|
||||
// pass along the diffuse color
|
||||
varColor = color_sRGBAToLinear(inColor);
|
||||
|
||||
|
||||
// standard transform
|
||||
TransformCamera cam = getTransformCamera();
|
||||
TransformObject obj = getTransformObject();
|
||||
<$transformModelToClipPos(cam, obj, inPosition, gl_Position)$>
|
||||
<$transformModelToEyeDir(cam, obj, inNormal.xyz, interpolatedNormal)$>
|
||||
<$transformModelToWorldPos(obj, inPosition, _worldPosition)$>
|
||||
}
|
|
@ -527,8 +527,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
CHECK_PROPERTY_CHANGE(PROP_STROKE_NORMALS, normals);
|
||||
CHECK_PROPERTY_CHANGE(PROP_STROKE_COLORS, strokeColors);
|
||||
CHECK_PROPERTY_CHANGE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch);
|
||||
CHECK_PROPERTY_CHANGE(PROP_LINE_GLOW, glow);
|
||||
CHECK_PROPERTY_CHANGE(PROP_LINE_FACE_CAMERA, faceCamera);
|
||||
|
||||
// Shape
|
||||
CHECK_PROPERTY_CHANGE(PROP_SHAPE, shape);
|
||||
|
@ -741,6 +739,7 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* @see {@link Entities.EntityProperties-Image|EntityProperties-Image}
|
||||
* @see {@link Entities.EntityProperties-Web|EntityProperties-Web}
|
||||
* @see {@link Entities.EntityProperties-ParticleEffect|EntityProperties-ParticleEffect}
|
||||
* @see {@link Entities.EntityProperties-Line|EntityProperties-Line}
|
||||
* @see {@link Entities.EntityProperties-PolyLine|EntityProperties-PolyLine}
|
||||
* @see {@link Entities.EntityProperties-PolyVox|EntityProperties-PolyVox}
|
||||
* @see {@link Entities.EntityProperties-Grid|EntityProperties-Grid}
|
||||
|
@ -786,6 +785,33 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* });
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Line"</code> {@link Entities.EntityType|EntityType} draws thin, straight lines between a sequence of two or more
|
||||
* points. Deprecated: Use PolyLines instead.
|
||||
* It has properties in addition to the common {@link Entities.EntityProperties|EntityProperties}.
|
||||
* @typedef {object} Entities.EntityProperties-Line
|
||||
* @property {Vec3} dimensions=0.1,0.1,0.1 - The dimensions of the entity. Must be sufficient to contain all the
|
||||
* <code>linePoints</code>.
|
||||
* @property {Vec3[]} linePoints=[]] - The sequence of points to draw lines between. The values are relative to the entity's
|
||||
* position. A maximum of 70 points can be specified. The property's value is set only if all the <code>linePoints</code>
|
||||
* lie within the entity's <code>dimensions</code>.
|
||||
* @property {Color} color=255,255,255 - The color of the line.
|
||||
* @example <caption>Draw lines in a "V".</caption>
|
||||
* var entity = Entities.addEntity({
|
||||
* type: "Line",
|
||||
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -5 })),
|
||||
* rotation: MyAvatar.orientation,
|
||||
* dimensions: { x: 2, y: 2, z: 1 },
|
||||
* linePoints: [
|
||||
* { x: -1, y: 1, z: 0 },
|
||||
* { x: 0, y: -1, z: 0 },
|
||||
* { x: 1, y: 1, z: 0 },
|
||||
* ],
|
||||
* color: { red: 255, green: 0, blue: 0 },
|
||||
* lifetime: 300 // Delete after 5 minutes.
|
||||
* });
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Material"</code> {@link Entities.EntityType|EntityType} modifies the existing materials on
|
||||
* {@link Entities.EntityType|Model} entities, {@link Entities.EntityType|Shape} entities (albedo only),
|
||||
|
@ -1025,8 +1051,6 @@ EntityPropertyFlags EntityItemProperties::getChangedProperties() const {
|
|||
* format.
|
||||
* @property {boolean} isUVModeStretch=true - If <code>true</code>, the texture is stretched to fill the whole line, otherwise
|
||||
* the texture repeats along the line.
|
||||
* @property {bool} glow=false - If <code>true</code>, the alpha of the strokes will drop off farther from the center.
|
||||
* @property {bool} faceCamera=false - If <code>true</code>, each line segment will rotate to face the camera.
|
||||
* @example <caption>Draw a textured "V".</caption>
|
||||
* var entity = Entities.addEntity({
|
||||
* type: "PolyLine",
|
||||
|
@ -1593,6 +1617,13 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_Z_P_NEIGHBOR_ID, zPNeighborID);
|
||||
}
|
||||
|
||||
// Lines
|
||||
if (_type == EntityTypes::Line) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_POINTS, linePoints);
|
||||
}
|
||||
|
||||
// Polylines
|
||||
if (_type == EntityTypes::PolyLine) {
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_COLOR, color, u8vec3Color);
|
||||
|
@ -1603,8 +1634,6 @@ QScriptValue EntityItemProperties::copyToScriptValue(QScriptEngine* engine, bool
|
|||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_STROKE_NORMALS, normals);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE_TYPED(PROP_STROKE_COLORS, strokeColors, qVectorVec3Color);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_IS_UV_MODE_STRETCH, isUVModeStretch);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_GLOW, glow);
|
||||
COPY_PROPERTY_TO_QSCRIPTVALUE(PROP_LINE_FACE_CAMERA, faceCamera);
|
||||
}
|
||||
|
||||
// Materials
|
||||
|
@ -1927,8 +1956,6 @@ void EntityItemProperties::copyFromScriptValue(const QScriptValue& object, bool
|
|||
COPY_PROPERTY_FROM_QSCRIPTVALUE(normals, qVectorVec3, setNormals);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(strokeColors, qVectorVec3, setStrokeColors);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(isUVModeStretch, bool, setIsUVModeStretch);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(glow, bool, setGlow);
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(faceCamera, bool, setFaceCamera);
|
||||
|
||||
// Shape
|
||||
COPY_PROPERTY_FROM_QSCRIPTVALUE(shape, QString, setShape);
|
||||
|
@ -2181,8 +2208,6 @@ void EntityItemProperties::merge(const EntityItemProperties& other) {
|
|||
COPY_PROPERTY_IF_CHANGED(normals);
|
||||
COPY_PROPERTY_IF_CHANGED(strokeColors);
|
||||
COPY_PROPERTY_IF_CHANGED(isUVModeStretch);
|
||||
COPY_PROPERTY_IF_CHANGED(glow);
|
||||
COPY_PROPERTY_IF_CHANGED(faceCamera);
|
||||
|
||||
// Shape
|
||||
COPY_PROPERTY_IF_CHANGED(shape);
|
||||
|
@ -2498,8 +2523,6 @@ void EntityItemProperties::entityPropertyFlagsFromScriptValue(const QScriptValue
|
|||
ADD_PROPERTY_TO_MAP(PROP_STROKE_NORMALS, Normals, normals, QVector<vec3>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector<vec3>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_IS_UV_MODE_STRETCH, IsUVModeStretch, isUVModeStretch, QVector<float>);
|
||||
ADD_PROPERTY_TO_MAP(PROP_LINE_GLOW, Glow, glow);
|
||||
ADD_PROPERTY_TO_MAP(PROP_LINE_FACE_CAMERA, FaceCamera, faceCamera, bool);
|
||||
|
||||
// Shape
|
||||
ADD_PROPERTY_TO_MAP(PROP_SHAPE, Shape, shape, QString);
|
||||
|
@ -2849,6 +2872,12 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
|
|||
APPEND_ENTITY_PROPERTY(PROP_DPI, properties.getDPI());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Line) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, properties.getLinePoints());
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::PolyLine) {
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, properties.getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_TEXTURES, properties.getTextures());
|
||||
|
@ -2858,8 +2887,6 @@ OctreeElement::AppendState EntityItemProperties::encodeEntityEditPacket(PacketTy
|
|||
APPEND_ENTITY_PROPERTY(PROP_STROKE_NORMALS, properties.getPackedNormals());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, properties.getPackedStrokeColors());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, properties.getIsUVModeStretch());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_GLOW, properties.getGlow());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_FACE_CAMERA, properties.getFaceCamera());
|
||||
}
|
||||
|
||||
// NOTE: Spheres and Boxes are just special cases of Shape, and they need to include their PROP_SHAPE
|
||||
|
@ -3278,6 +3305,12 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_DPI, uint16_t, setDPI);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::Line) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor);
|
||||
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_POINTS, QVector<vec3>, setLinePoints);
|
||||
}
|
||||
|
||||
if (properties.getType() == EntityTypes::PolyLine) {
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_COLOR, u8vec3Color, setColor);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_TEXTURES, QString, setTextures);
|
||||
|
@ -3287,8 +3320,6 @@ bool EntityItemProperties::decodeEntityEditPacket(const unsigned char* data, int
|
|||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STROKE_NORMALS, QByteArray, setPackedNormals);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_STROKE_COLORS, QByteArray, setPackedStrokeColors);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_IS_UV_MODE_STRETCH, bool, setIsUVModeStretch);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_GLOW, bool, setGlow);
|
||||
READ_ENTITY_PROPERTY_TO_PROPERTIES(PROP_LINE_FACE_CAMERA, bool, setFaceCamera);
|
||||
}
|
||||
|
||||
// NOTE: Spheres and Boxes are just special cases of Shape, and they need to include their PROP_SHAPE
|
||||
|
@ -3634,8 +3665,6 @@ void EntityItemProperties::markAllChanged() {
|
|||
_normalsChanged = true;
|
||||
_strokeColorsChanged = true;
|
||||
_isUVModeStretchChanged = true;
|
||||
_glowChanged = true;
|
||||
_faceCameraChanged = true;
|
||||
|
||||
// Shape
|
||||
_shapeChanged = true;
|
||||
|
@ -4234,12 +4263,6 @@ QList<QString> EntityItemProperties::listChangedProperties() {
|
|||
if (isUVModeStretchChanged()) {
|
||||
out += "isUVModeStretch";
|
||||
}
|
||||
if (glowChanged()) {
|
||||
out += "glow";
|
||||
}
|
||||
if (faceCameraChanged()) {
|
||||
out += "faceCamera";
|
||||
}
|
||||
|
||||
// Shape
|
||||
if (shapeChanged()) {
|
||||
|
|
|
@ -37,6 +37,7 @@
|
|||
#include "EntityPropertyFlags.h"
|
||||
#include "EntityPsuedoPropertyFlags.h"
|
||||
#include "LightEntityItem.h"
|
||||
#include "LineEntityItem.h"
|
||||
#include "ParticleEffectEntityItem.h"
|
||||
#include "PolyVoxEntityItem.h"
|
||||
#include "SimulationOwner.h"
|
||||
|
@ -77,6 +78,7 @@ class EntityItemProperties {
|
|||
friend class ImageEntityItem;
|
||||
friend class WebEntityItem;
|
||||
friend class ParticleEffectEntityItem;
|
||||
friend class LineEntityItem;
|
||||
friend class PolyLineEntityItem;
|
||||
friend class PolyVoxEntityItem;
|
||||
friend class GridEntityItem;
|
||||
|
@ -307,8 +309,6 @@ public:
|
|||
DEFINE_PROPERTY(PROP_STROKE_NORMALS, Normals, normals, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_STROKE_COLORS, StrokeColors, strokeColors, QVector<glm::vec3>, ENTITY_ITEM_DEFAULT_EMPTY_VEC3_QVEC);
|
||||
DEFINE_PROPERTY(PROP_IS_UV_MODE_STRETCH, IsUVModeStretch, isUVModeStretch, bool, true);
|
||||
DEFINE_PROPERTY(PROP_LINE_GLOW, Glow, glow, bool, false);
|
||||
DEFINE_PROPERTY(PROP_LINE_FACE_CAMERA, FaceCamera, faceCamera, bool, false);
|
||||
|
||||
// Shape
|
||||
DEFINE_PROPERTY_REF(PROP_SHAPE, Shape, shape, QString, "Sphere");
|
||||
|
|
|
@ -290,8 +290,6 @@ enum EntityPropertyList {
|
|||
PROP_STROKE_NORMALS = PROP_DERIVED_2,
|
||||
PROP_STROKE_COLORS = PROP_DERIVED_3,
|
||||
PROP_IS_UV_MODE_STRETCH = PROP_DERIVED_4,
|
||||
PROP_LINE_GLOW = PROP_DERIVED_5,
|
||||
PROP_LINE_FACE_CAMERA = PROP_DERIVED_6,
|
||||
|
||||
// Shape
|
||||
PROP_SHAPE = PROP_DERIVED_0,
|
||||
|
|
|
@ -1519,6 +1519,46 @@ bool EntityScriptingInterface::polyVoxWorker(QUuid entityID, std::function<bool(
|
|||
return result;
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::setPoints(QUuid entityID, std::function<bool(LineEntityItem&)> actor) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
if (!_entityTree) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
|
||||
}
|
||||
|
||||
EntityTypes::EntityType entityType = entity->getType();
|
||||
|
||||
if (entityType != EntityTypes::Line) {
|
||||
return false;
|
||||
}
|
||||
|
||||
auto now = usecTimestampNow();
|
||||
|
||||
auto lineEntity = std::static_pointer_cast<LineEntityItem>(entity);
|
||||
bool success;
|
||||
_entityTree->withWriteLock([&] {
|
||||
success = actor(*lineEntity);
|
||||
entity->setLastEdited(now);
|
||||
entity->setLastBroadcast(now);
|
||||
});
|
||||
|
||||
EntityItemProperties properties;
|
||||
_entityTree->withReadLock([&] {
|
||||
properties = entity->getProperties();
|
||||
});
|
||||
|
||||
properties.setLinePointsDirty();
|
||||
properties.setLastEdited(now);
|
||||
|
||||
queueEntityMessage(PacketType::EntityEdit, entityID, properties);
|
||||
return success;
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::setVoxelSphere(QUuid entityID, const glm::vec3& center, float radius, int value) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
return polyVoxWorker(entityID, [center, radius, value](PolyVoxEntityItem& polyVoxEntity) {
|
||||
|
@ -1561,6 +1601,49 @@ bool EntityScriptingInterface::setVoxelsInCuboid(QUuid entityID, const glm::vec3
|
|||
});
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::setAllPoints(QUuid entityID, const QVector<glm::vec3>& points) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
|
||||
}
|
||||
|
||||
EntityTypes::EntityType entityType = entity->getType();
|
||||
|
||||
if (entityType == EntityTypes::Line) {
|
||||
return setPoints(entityID, [points](LineEntityItem& lineEntity) -> bool
|
||||
{
|
||||
return (LineEntityItem*)lineEntity.setLinePoints(points);
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool EntityScriptingInterface::appendPoint(QUuid entityID, const glm::vec3& point) {
|
||||
PROFILE_RANGE(script_entities, __FUNCTION__);
|
||||
|
||||
EntityItemPointer entity = static_cast<EntityItemPointer>(_entityTree->findEntityByEntityItemID(entityID));
|
||||
if (!entity) {
|
||||
qCDebug(entities) << "EntityScriptingInterface::setPoints no entity with ID" << entityID;
|
||||
// There is no entity
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityTypes::EntityType entityType = entity->getType();
|
||||
|
||||
if (entityType == EntityTypes::Line) {
|
||||
return setPoints(entityID, [point](LineEntityItem& lineEntity) -> bool
|
||||
{
|
||||
return (LineEntityItem*)lineEntity.appendPoint(point);
|
||||
});
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool EntityScriptingInterface::actionWorker(const QUuid& entityID,
|
||||
std::function<bool(EntitySimulationPointer, EntityItemPointer)> actor) {
|
||||
if (!_entityTree) {
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include <PointerEvent.h>
|
||||
|
||||
#include "PolyVoxEntityItem.h"
|
||||
#include "LineEntityItem.h"
|
||||
#include "PolyLineEntityItem.h"
|
||||
#include "EntityTree.h"
|
||||
|
||||
|
@ -860,12 +861,75 @@ public slots:
|
|||
// FIXME move to a renderable entity interface
|
||||
Q_INVOKABLE glm::vec3 localCoordsToVoxelCoords(const QUuid& entityID, glm::vec3 localCoords);
|
||||
|
||||
/**jsdoc
|
||||
* Set the <code>linePoints</code> property of a {@link Entities.EntityType|Line} entity.
|
||||
* @function Entities.setAllPoints
|
||||
* @param {Uuid} entityID - The ID of the {@link Entities.EntityType|Line} entity.
|
||||
* @param {Vec3[]} points - The array of points to set the entity's <code>linePoints</code> property to.
|
||||
* @returns {boolean} <code>true</code> if the entity's property was updated, otherwise <code>false</code>. The property
|
||||
* may fail to be updated if the entity does not exist, the entity is not a {@link Entities.EntityType|Line} entity,
|
||||
* one of the points is outside the entity's dimensions, or the number of points is greater than the maximum allowed.
|
||||
* @example <caption>Change the shape of a Line entity.</caption>
|
||||
* // Draw a horizontal line between two points.
|
||||
* var entity = Entities.addEntity({
|
||||
* type: "Line",
|
||||
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -5 })),
|
||||
* rotation: MyAvatar.orientation,
|
||||
* dimensions: { x: 2, y: 2, z: 1 },
|
||||
* linePoints: [
|
||||
* { x: -1, y: 0, z: 0 },
|
||||
* { x:1, y: -0, z: 0 }
|
||||
* ],
|
||||
* color: { red: 255, green: 0, blue: 0 },
|
||||
* lifetime: 300 // Delete after 5 minutes.
|
||||
* });
|
||||
*
|
||||
* // Change the line to be a "V".
|
||||
* Script.setTimeout(function () {
|
||||
* Entities.setAllPoints(entity, [
|
||||
* { x: -1, y: 1, z: 0 },
|
||||
* { x: 0, y: -1, z: 0 },
|
||||
* { x: 1, y: 1, z: 0 },
|
||||
* ]);
|
||||
* }, 2000);
|
||||
*/
|
||||
Q_INVOKABLE bool setAllPoints(QUuid entityID, const QVector<glm::vec3>& points);
|
||||
|
||||
/**jsdoc
|
||||
* Append a point to a {@link Entities.EntityType|Line} entity.
|
||||
* @function Entities.appendPoint
|
||||
* @param {Uuid} entityID - The ID of the {@link Entities.EntityType|Line} entity.
|
||||
* @param {Vec3} point - The point to add to the line. The coordinates are relative to the entity's position.
|
||||
* @returns {boolean} <code>true</code> if the point was added to the line, otherwise <code>false</code>. The point may
|
||||
* fail to be added if the entity does not exist, the entity is not a {@link Entities.EntityType|Line} entity, the
|
||||
* point is outside the entity's dimensions, or the maximum number of points has been reached.
|
||||
* @example <caption>Append a point to a Line entity.</caption>
|
||||
* // Draw a line between two points.
|
||||
* var entity = Entities.addEntity({
|
||||
* type: "Line",
|
||||
* position: Vec3.sum(MyAvatar.position, Vec3.multiplyQbyV(MyAvatar.orientation, { x: 0, y: 0.75, z: -5 })),
|
||||
* rotation: MyAvatar.orientation,
|
||||
* dimensions: { x: 2, y: 2, z: 1 },
|
||||
* linePoints: [
|
||||
* { x: -1, y: 1, z: 0 },
|
||||
* { x: 0, y: -1, z: 0 }
|
||||
* ],
|
||||
* color: { red: 255, green: 0, blue: 0 },
|
||||
* lifetime: 300 // Delete after 5 minutes.
|
||||
* });
|
||||
*
|
||||
* // Add a third point to create a "V".
|
||||
* Entities.appendPoint(entity, { x: 1, y: 1, z: 0 });
|
||||
*/
|
||||
Q_INVOKABLE bool appendPoint(QUuid entityID, const glm::vec3& point);
|
||||
|
||||
/**jsdoc
|
||||
* Dumps debug information about all entities in Interface's local in-memory tree of entities it knows about to the program log.
|
||||
* @function Entities.dumpTree
|
||||
*/
|
||||
Q_INVOKABLE void dumpTree() const;
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* Add an action to an entity. An action is registered with the physics engine and is applied every physics simulation
|
||||
* step. Any entity may have more than one action associated with it, but only as many as will fit in an entity's
|
||||
|
@ -1914,6 +1978,7 @@ private slots:
|
|||
private:
|
||||
bool actionWorker(const QUuid& entityID, std::function<bool(EntitySimulationPointer, EntityItemPointer)> actor);
|
||||
bool polyVoxWorker(QUuid entityID, std::function<bool(PolyVoxEntityItem&)> actor);
|
||||
bool setPoints(QUuid entityID, std::function<bool(LineEntityItem&)> actor);
|
||||
void queueEntityMessage(PacketType packetType, EntityItemID entityID, const EntityItemProperties& properties);
|
||||
bool addLocalEntityCopy(EntityItemProperties& propertiesWithSimID, EntityItemID& id, bool isClone = false);
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "TextEntityItem.h"
|
||||
#include "ImageEntityItem.h"
|
||||
#include "WebEntityItem.h"
|
||||
#include "LineEntityItem.h"
|
||||
#include "PolyLineEntityItem.h"
|
||||
#include "PolyVoxEntityItem.h"
|
||||
#include "GridEntityItem.h"
|
||||
|
@ -49,6 +50,7 @@ REGISTER_ENTITY_TYPE(Text)
|
|||
REGISTER_ENTITY_TYPE(Image)
|
||||
REGISTER_ENTITY_TYPE(Web)
|
||||
REGISTER_ENTITY_TYPE(ParticleEffect)
|
||||
REGISTER_ENTITY_TYPE(Line)
|
||||
REGISTER_ENTITY_TYPE(PolyLine)
|
||||
REGISTER_ENTITY_TYPE(PolyVox)
|
||||
REGISTER_ENTITY_TYPE(Grid)
|
||||
|
|
|
@ -70,6 +70,8 @@ public:
|
|||
* <tr><td><code>"ParticleEffect"</code></td><td>A particle system that can be used to simulate things such as fire,
|
||||
* smoke, snow, magic spells, etc.</td>
|
||||
* <td>{@link Entities.EntityProperties-ParticleEffect|EntityProperties-ParticleEffect}</td></tr>
|
||||
* <tr><td><code>"Line"</code></td><td>A sequence of one or more simple straight lines.</td>
|
||||
* <td>{@link Entities.EntityProperties-Line|EntityProperties-Line}</td></tr>
|
||||
* <tr><td><code>"PolyLine"</code></td><td>A sequence of one or more textured straight lines.</td>
|
||||
* <td>{@link Entities.EntityProperties-PolyLine|EntityProperties-PolyLine}</td></tr>
|
||||
* <tr><td><code>"PolyVox"</code></td><td>A set of textured voxels.</td>
|
||||
|
@ -97,6 +99,7 @@ public:
|
|||
Image,
|
||||
Web,
|
||||
ParticleEffect,
|
||||
Line,
|
||||
PolyLine,
|
||||
PolyVox,
|
||||
Grid,
|
||||
|
|
175
libraries/entities/src/LineEntityItem.cpp
Normal file
175
libraries/entities/src/LineEntityItem.cpp
Normal file
|
@ -0,0 +1,175 @@
|
|||
//
|
||||
// LineEntityItem.cpp
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 5/11/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 "LineEntityItem.h"
|
||||
|
||||
#include <QDebug>
|
||||
|
||||
#include <ByteCountCoding.h>
|
||||
|
||||
#include "EntitiesLogging.h"
|
||||
#include "EntityItemProperties.h"
|
||||
#include "EntityTree.h"
|
||||
#include "EntityTreeElement.h"
|
||||
#include "OctreeConstants.h"
|
||||
|
||||
const int LineEntityItem::MAX_POINTS_PER_LINE = 70;
|
||||
|
||||
|
||||
EntityItemPointer LineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity(new LineEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
return entity;
|
||||
}
|
||||
|
||||
LineEntityItem::LineEntityItem(const EntityItemID& entityItemID) :
|
||||
EntityItem(entityItemID)
|
||||
{
|
||||
_type = EntityTypes::Line;
|
||||
}
|
||||
|
||||
EntityItemProperties LineEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
|
||||
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(linePoints, getLinePoints);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool LineEntityItem::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);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(linePoints, setLinePoints);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
if (wantDebug) {
|
||||
uint64_t now = usecTimestampNow();
|
||||
int elapsed = now - getLastEdited();
|
||||
qCDebug(entities) << "LineEntityItem::setProperties() AFTER update... edited AGO=" << elapsed <<
|
||||
"now=" << now << " getLastEdited()=" << getLastEdited();
|
||||
}
|
||||
setLastEdited(properties._lastEdited);
|
||||
}
|
||||
return somethingChanged;
|
||||
}
|
||||
|
||||
bool LineEntityItem::appendPoint(const glm::vec3& point) {
|
||||
if (_points.size() > MAX_POINTS_PER_LINE - 1) {
|
||||
qCDebug(entities) << "MAX POINTS REACHED!";
|
||||
return false;
|
||||
}
|
||||
glm::vec3 halfBox = getScaledDimensions() * 0.5f;
|
||||
if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) {
|
||||
qCDebug(entities) << "Point is outside entity's bounding box";
|
||||
return false;
|
||||
}
|
||||
withWriteLock([&] {
|
||||
_points << point;
|
||||
_pointsChanged = true;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
bool LineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
|
||||
if (points.size() > MAX_POINTS_PER_LINE) {
|
||||
return false;
|
||||
}
|
||||
glm::vec3 halfBox = getScaledDimensions() * 0.5f;
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
glm::vec3 point = points.at(i);
|
||||
if ( (point.x < - halfBox.x || point.x > halfBox.x) || (point.y < -halfBox.y || point.y > halfBox.y) || (point.z < - halfBox.z || point.z > halfBox.z) ) {
|
||||
qCDebug(entities) << "Point is outside entity's bounding box";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
withWriteLock([&] {
|
||||
_points = points;
|
||||
_pointsChanged = true;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
int LineEntityItem::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, glm::u8vec3, setColor);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_POINTS, QVector<glm::vec3>, setLinePoints);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
||||
|
||||
EntityPropertyFlags LineEntityItem::getEntityProperties(EncodeBitstreamParams& params) const {
|
||||
EntityPropertyFlags requestedProperties = EntityItem::getEntityProperties(params);
|
||||
requestedProperties += PROP_COLOR;
|
||||
requestedProperties += PROP_LINE_POINTS;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
void LineEntityItem::appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_POINTS, getLinePoints());
|
||||
}
|
||||
|
||||
void LineEntityItem::debugDump() const {
|
||||
quint64 now = usecTimestampNow();
|
||||
qCDebug(entities) << " LINE EntityItem id:" << getEntityItemID() << "---------------------------------------------";
|
||||
qCDebug(entities) << " color:" << _color;
|
||||
qCDebug(entities) << " position:" << debugTreeVector(getWorldPosition());
|
||||
qCDebug(entities) << " dimensions:" << debugTreeVector(getScaledDimensions());
|
||||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
||||
glm::u8vec3 LineEntityItem::getColor() const {
|
||||
return resultWithReadLock<glm::u8vec3>([&] {
|
||||
return _color;
|
||||
});
|
||||
}
|
||||
|
||||
void LineEntityItem::setColor(const glm::u8vec3& value) {
|
||||
withWriteLock([&] {
|
||||
_color = value;
|
||||
});
|
||||
}
|
||||
|
||||
QVector<glm::vec3> LineEntityItem::getLinePoints() const {
|
||||
QVector<glm::vec3> result;
|
||||
withReadLock([&] {
|
||||
result = _points;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void LineEntityItem::resetPointsChanged() {
|
||||
withWriteLock([&] {
|
||||
_pointsChanged = false;
|
||||
});
|
||||
}
|
77
libraries/entities/src/LineEntityItem.h
Normal file
77
libraries/entities/src/LineEntityItem.h
Normal file
|
@ -0,0 +1,77 @@
|
|||
//
|
||||
// LineEntityItem.h
|
||||
// libraries/entities/src
|
||||
//
|
||||
// Created by Seth Alves on 5/11/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_LineEntityItem_h
|
||||
#define hifi_LineEntityItem_h
|
||||
|
||||
#include "EntityItem.h"
|
||||
|
||||
class LineEntityItem : public EntityItem {
|
||||
public:
|
||||
static EntityItemPointer factory(const EntityItemID& entityID, const EntityItemProperties& properties);
|
||||
|
||||
LineEntityItem(const EntityItemID& entityItemID);
|
||||
|
||||
ALLOW_INSTANTIATION // This class can be instantiated
|
||||
|
||||
// methods for getting/setting all properties of an entity
|
||||
virtual EntityItemProperties getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const override;
|
||||
virtual bool setProperties(const EntityItemProperties& properties) override;
|
||||
|
||||
virtual EntityPropertyFlags getEntityProperties(EncodeBitstreamParams& params) const override;
|
||||
|
||||
virtual void appendSubclassData(OctreePacketData* packetData, EncodeBitstreamParams& params,
|
||||
EntityTreeElementExtraEncodeDataPointer modelTreeElementExtraEncodeData,
|
||||
EntityPropertyFlags& requestedProperties,
|
||||
EntityPropertyFlags& propertyFlags,
|
||||
EntityPropertyFlags& propertiesDidntFit,
|
||||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const override;
|
||||
|
||||
virtual int readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged) override;
|
||||
|
||||
glm::u8vec3 getColor() const;
|
||||
void setColor(const glm::u8vec3& value);
|
||||
|
||||
bool setLinePoints(const QVector<glm::vec3>& points);
|
||||
bool appendPoint(const glm::vec3& point);
|
||||
|
||||
QVector<glm::vec3> getLinePoints() const;
|
||||
|
||||
virtual ShapeType getShapeType() const override { return SHAPE_TYPE_NONE; }
|
||||
|
||||
// never have a ray intersection pick a LineEntityItem.
|
||||
virtual bool supportsDetailedIntersection() const override { return true; }
|
||||
virtual bool findDetailedRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
OctreeElementPointer& element, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo,
|
||||
bool precisionPicking) const override { return false; }
|
||||
virtual bool findDetailedParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity,
|
||||
const glm::vec3& acceleration, OctreeElementPointer& element, float& parabolicDistance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo,
|
||||
bool precisionPicking) const override { return false; }
|
||||
bool pointsChanged() const { return _pointsChanged; }
|
||||
void resetPointsChanged();
|
||||
virtual void debugDump() const override;
|
||||
static const int MAX_POINTS_PER_LINE;
|
||||
|
||||
private:
|
||||
glm::u8vec3 _color;
|
||||
QVector<glm::vec3> _points;
|
||||
bool _pointsChanged { true };
|
||||
};
|
||||
|
||||
#endif // hifi_LineEntityItem_h
|
|
@ -24,6 +24,7 @@
|
|||
const float PolyLineEntityItem::DEFAULT_LINE_WIDTH = 0.1f;
|
||||
const int PolyLineEntityItem::MAX_POINTS_PER_LINE = 60;
|
||||
|
||||
|
||||
EntityItemPointer PolyLineEntityItem::factory(const EntityItemID& entityID, const EntityItemProperties& properties) {
|
||||
EntityItemPointer entity(new PolyLineEntityItem(entityID), [](EntityItem* ptr) { ptr->deleteLater(); });
|
||||
entity->setProperties(properties);
|
||||
|
@ -36,6 +37,7 @@ PolyLineEntityItem::PolyLineEntityItem(const EntityItemID& entityItemID) : Entit
|
|||
}
|
||||
|
||||
EntityItemProperties PolyLineEntityItem::getProperties(const EntityPropertyFlags& desiredProperties, bool allowEmptyDesiredProperties) const {
|
||||
QWriteLocker lock(&_quadReadWriteLock);
|
||||
EntityItemProperties properties = EntityItem::getProperties(desiredProperties, allowEmptyDesiredProperties); // get the properties from our base class
|
||||
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(color, getColor);
|
||||
|
@ -46,13 +48,11 @@ EntityItemProperties PolyLineEntityItem::getProperties(const EntityPropertyFlags
|
|||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(normals, getNormals);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(strokeColors, getStrokeColors);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(isUVModeStretch, getIsUVModeStretch);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(glow, getGlow);
|
||||
COPY_ENTITY_PROPERTY_TO_PROPERTIES(faceCamera, getFaceCamera);
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
|
||||
QWriteLocker lock(&_quadReadWriteLock);
|
||||
bool somethingChanged = false;
|
||||
somethingChanged = EntityItem::setProperties(properties); // set the properties in our base class
|
||||
|
||||
|
@ -64,8 +64,6 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(normals, setNormals);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(strokeColors, setStrokeColors);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(isUVModeStretch, setIsUVModeStretch);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(glow, setGlow);
|
||||
SET_ENTITY_PROPERTY_FROM_PROPERTIES(faceCamera, setFaceCamera);
|
||||
|
||||
if (somethingChanged) {
|
||||
bool wantDebug = false;
|
||||
|
@ -80,73 +78,125 @@ bool PolyLineEntityItem::setProperties(const EntityItemProperties& properties) {
|
|||
return somethingChanged;
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
|
||||
withWriteLock([&] {
|
||||
_points = points;
|
||||
_pointsChanged = true;
|
||||
});
|
||||
computeAndUpdateDimensionsAndPosition();
|
||||
|
||||
bool PolyLineEntityItem::appendPoint(const glm::vec3& point) {
|
||||
if (_points.size() > MAX_POINTS_PER_LINE - 1) {
|
||||
qCDebug(entities) << "MAX POINTS REACHED!";
|
||||
return false;
|
||||
}
|
||||
|
||||
_points << point;
|
||||
_pointsChanged = true;
|
||||
|
||||
calculateScaleAndRegistrationPoint();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
|
||||
|
||||
bool PolyLineEntityItem::setStrokeWidths(const QVector<float>& strokeWidths) {
|
||||
withWriteLock([&] {
|
||||
_widths = strokeWidths;
|
||||
_widthsChanged = true;
|
||||
_strokeWidths = strokeWidths;
|
||||
_strokeWidthsChanged = true;
|
||||
});
|
||||
computeAndUpdateDimensionsAndPosition();
|
||||
return true;
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setNormals(const QVector<glm::vec3>& normals) {
|
||||
bool PolyLineEntityItem::setNormals(const QVector<glm::vec3>& normals) {
|
||||
withWriteLock([&] {
|
||||
_normals = normals;
|
||||
_normalsChanged = true;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setStrokeColors(const QVector<glm::vec3>& strokeColors) {
|
||||
bool PolyLineEntityItem::setStrokeColors(const QVector<glm::vec3>& strokeColors) {
|
||||
withWriteLock([&] {
|
||||
_colors = strokeColors;
|
||||
_colorsChanged = true;
|
||||
_strokeColors = strokeColors;
|
||||
_strokeColorsChanged = true;
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::computeAndUpdateDimensionsAndPosition() {
|
||||
QVector<glm::vec3> points;
|
||||
QVector<float> widths;
|
||||
|
||||
withReadLock([&] {
|
||||
points = _points;
|
||||
widths = _widths;
|
||||
bool PolyLineEntityItem::setLinePoints(const QVector<glm::vec3>& points) {
|
||||
if (points.size() > MAX_POINTS_PER_LINE) {
|
||||
return false;
|
||||
}
|
||||
bool result = false;
|
||||
withWriteLock([&] {
|
||||
//Check to see if points actually changed. If they haven't, return before doing anything else
|
||||
if (points.size() != _points.size()) {
|
||||
_pointsChanged = true;
|
||||
} else if (points.size() == _points.size()) {
|
||||
//same number of points, so now compare every point
|
||||
for (int i = 0; i < points.size(); i++) {
|
||||
if (points.at(i) != _points.at(i)) {
|
||||
_pointsChanged = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!_pointsChanged) {
|
||||
return;
|
||||
}
|
||||
|
||||
_points = points;
|
||||
|
||||
result = true;
|
||||
});
|
||||
|
||||
AABox container;
|
||||
float maxWidth = 0.0f;
|
||||
if (_points.length() > 0) {
|
||||
container = AABox(_points[0] - 0.5f * ENTITY_ITEM_DEFAULT_DIMENSIONS, ENTITY_ITEM_DEFAULT_WIDTH);
|
||||
for (int i = 0; i < points.length(); i++) {
|
||||
container += points[i];
|
||||
maxWidth = glm::max(maxWidth, i < widths.length() ? widths[i] : DEFAULT_LINE_WIDTH);
|
||||
}
|
||||
} else {
|
||||
container = AABox(-0.5f * ENTITY_ITEM_DEFAULT_DIMENSIONS, ENTITY_ITEM_DEFAULT_WIDTH);
|
||||
if (result) {
|
||||
calculateScaleAndRegistrationPoint();
|
||||
}
|
||||
|
||||
// Adjust the box to account for the line width, assuming the worst case
|
||||
container.setScaleStayCentered(container.getScale() + 2.0f * maxWidth);
|
||||
return result;
|
||||
}
|
||||
|
||||
bool success;
|
||||
glm::vec3 center = container.calcCenter();
|
||||
setWorldPosition(center + getCenterPosition(success));
|
||||
setScaledDimensions(container.getScale());
|
||||
withWriteLock([&] {
|
||||
_polylineCenter = center;
|
||||
void PolyLineEntityItem::calculateScaleAndRegistrationPoint() {
|
||||
glm::vec3 high(0.0f, 0.0f, 0.0f);
|
||||
glm::vec3 low(0.0f, 0.0f, 0.0f);
|
||||
int pointCount = 0;
|
||||
glm::vec3 firstPoint;
|
||||
withReadLock([&] {
|
||||
pointCount = _points.size();
|
||||
if (pointCount > 0) {
|
||||
firstPoint = _points.at(0);
|
||||
}
|
||||
for (int i = 0; i < pointCount; i++) {
|
||||
const glm::vec3& point = _points.at(i);
|
||||
high = glm::max(point, high);
|
||||
low = glm::min(point, low);
|
||||
}
|
||||
});
|
||||
|
||||
float magnitudeSquared = glm::length2(low - high);
|
||||
vec3 newScale { 1 };
|
||||
vec3 newRegistrationPoint { 0.5f };
|
||||
|
||||
const float EPSILON = 0.0001f;
|
||||
const float EPSILON_SQUARED = EPSILON * EPSILON;
|
||||
const float HALF_LINE_WIDTH = 0.075f; // sadly _strokeWidths() don't seem to correspond to reality, so just use a flat assumption of the stroke width
|
||||
const vec3 QUARTER_LINE_WIDTH { HALF_LINE_WIDTH * 0.5f };
|
||||
if (pointCount > 1 && magnitudeSquared > EPSILON_SQUARED) {
|
||||
newScale = glm::abs(high) + glm::abs(low) + vec3(HALF_LINE_WIDTH);
|
||||
// Center the poly line in the bounding box
|
||||
glm::vec3 startPointInScaleSpace = firstPoint - low;
|
||||
startPointInScaleSpace += QUARTER_LINE_WIDTH;
|
||||
newRegistrationPoint = startPointInScaleSpace / newScale;
|
||||
}
|
||||
|
||||
// if Polyline has only one or fewer points, use default dimension settings
|
||||
setScaledDimensions(newScale);
|
||||
EntityItem::setRegistrationPoint(newRegistrationPoint);
|
||||
}
|
||||
|
||||
int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* data, int bytesLeftToRead,
|
||||
ReadBitstreamToTreeParams& args,
|
||||
EntityPropertyFlags& propertyFlags, bool overwriteLocalData,
|
||||
bool& somethingChanged) {
|
||||
|
||||
QWriteLocker lock(&_quadReadWriteLock);
|
||||
int bytesRead = 0;
|
||||
const unsigned char* dataAt = data;
|
||||
|
||||
|
@ -158,8 +208,6 @@ int PolyLineEntityItem::readEntitySubclassDataFromBuffer(const unsigned char* da
|
|||
READ_ENTITY_PROPERTY(PROP_STROKE_NORMALS, QVector<glm::vec3>, setNormals);
|
||||
READ_ENTITY_PROPERTY(PROP_STROKE_COLORS, QVector<glm::vec3>, setStrokeColors);
|
||||
READ_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, bool, setIsUVModeStretch);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_GLOW, bool, setGlow);
|
||||
READ_ENTITY_PROPERTY(PROP_LINE_FACE_CAMERA, bool, setFaceCamera);
|
||||
|
||||
return bytesRead;
|
||||
}
|
||||
|
@ -174,8 +222,6 @@ EntityPropertyFlags PolyLineEntityItem::getEntityProperties(EncodeBitstreamParam
|
|||
requestedProperties += PROP_STROKE_NORMALS;
|
||||
requestedProperties += PROP_STROKE_COLORS;
|
||||
requestedProperties += PROP_IS_UV_MODE_STRETCH;
|
||||
requestedProperties += PROP_LINE_GLOW;
|
||||
requestedProperties += PROP_LINE_FACE_CAMERA;
|
||||
return requestedProperties;
|
||||
}
|
||||
|
||||
|
@ -187,6 +233,7 @@ void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, Encode
|
|||
int& propertyCount,
|
||||
OctreeElement::AppendState& appendState) const {
|
||||
|
||||
QWriteLocker lock(&_quadReadWriteLock);
|
||||
bool successPropertyFits = true;
|
||||
|
||||
APPEND_ENTITY_PROPERTY(PROP_COLOR, getColor());
|
||||
|
@ -197,8 +244,6 @@ void PolyLineEntityItem::appendSubclassData(OctreePacketData* packetData, Encode
|
|||
APPEND_ENTITY_PROPERTY(PROP_STROKE_NORMALS, getNormals());
|
||||
APPEND_ENTITY_PROPERTY(PROP_STROKE_COLORS, getStrokeColors());
|
||||
APPEND_ENTITY_PROPERTY(PROP_IS_UV_MODE_STRETCH, getIsUVModeStretch());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_GLOW, getGlow());
|
||||
APPEND_ENTITY_PROPERTY(PROP_LINE_FACE_CAMERA, getFaceCamera());
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::debugDump() const {
|
||||
|
@ -210,49 +255,61 @@ void PolyLineEntityItem::debugDump() const {
|
|||
qCDebug(entities) << " getLastEdited:" << debugTime(getLastEdited(), now);
|
||||
}
|
||||
|
||||
|
||||
|
||||
QVector<glm::vec3> PolyLineEntityItem::getLinePoints() const {
|
||||
return resultWithReadLock<QVector<glm::vec3>>([&] {
|
||||
return _points;
|
||||
QVector<glm::vec3> result;
|
||||
withReadLock([&] {
|
||||
result = _points;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<glm::vec3> PolyLineEntityItem::getNormals() const {
|
||||
return resultWithReadLock<QVector<glm::vec3>>([&] {
|
||||
return _normals;
|
||||
QVector<glm::vec3> result;
|
||||
withReadLock([&] {
|
||||
result = _normals;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<glm::vec3> PolyLineEntityItem::getStrokeColors() const {
|
||||
return resultWithReadLock<QVector<glm::vec3>>([&] {
|
||||
return _colors;
|
||||
QVector<glm::vec3> result;
|
||||
withReadLock([&] {
|
||||
result = _strokeColors;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
QVector<float> PolyLineEntityItem::getStrokeWidths() const {
|
||||
return resultWithReadLock<QVector<float>>([&] {
|
||||
return _widths;
|
||||
QVector<float> result;
|
||||
withReadLock([&] {
|
||||
result = _strokeWidths;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
QString PolyLineEntityItem::getTextures() const {
|
||||
return resultWithReadLock<QString>([&] {
|
||||
return _textures;
|
||||
QString result;
|
||||
withReadLock([&] {
|
||||
result = _textures;
|
||||
});
|
||||
return result;
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setTextures(const QString& textures) {
|
||||
withWriteLock([&] {
|
||||
if (_textures != textures) {
|
||||
_textures = textures;
|
||||
_texturesChanged = true;
|
||||
_texturesChangedFlag = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void PolyLineEntityItem::setColor(const glm::u8vec3& value) {
|
||||
withWriteLock([&] {
|
||||
_strokeColorsChanged = true;
|
||||
_color = value;
|
||||
_colorsChanged = true;
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -44,42 +44,35 @@ class PolyLineEntityItem : public EntityItem {
|
|||
glm::u8vec3 getColor() const;
|
||||
void setColor(const glm::u8vec3& value);
|
||||
|
||||
static const int MAX_POINTS_PER_LINE;
|
||||
void setLinePoints(const QVector<glm::vec3>& points);
|
||||
bool setLinePoints(const QVector<glm::vec3>& points);
|
||||
bool appendPoint(const glm::vec3& point);
|
||||
QVector<glm::vec3> getLinePoints() const;
|
||||
|
||||
glm::vec3 getPolylineCenter() const { return _polylineCenter; }
|
||||
|
||||
static const float DEFAULT_LINE_WIDTH;
|
||||
void setStrokeWidths(const QVector<float>& strokeWidths);
|
||||
QVector<float> getStrokeWidths() const;
|
||||
|
||||
void setNormals(const QVector<glm::vec3>& normals);
|
||||
bool setNormals(const QVector<glm::vec3>& normals);
|
||||
QVector<glm::vec3> getNormals() const;
|
||||
|
||||
void setStrokeColors(const QVector<glm::vec3>& strokeColors);
|
||||
bool setStrokeColors(const QVector<glm::vec3>& strokeColors);
|
||||
QVector<glm::vec3> getStrokeColors() const;
|
||||
|
||||
bool setStrokeWidths(const QVector<float>& strokeWidths);
|
||||
QVector<float> getStrokeWidths() const;
|
||||
|
||||
void setIsUVModeStretch(bool isUVModeStretch){ _isUVModeStretch = isUVModeStretch; }
|
||||
bool getIsUVModeStretch() const{ return _isUVModeStretch; }
|
||||
|
||||
QString getTextures() const;
|
||||
void setTextures(const QString& textures);
|
||||
|
||||
void setGlow(bool glow) { _glow = glow; }
|
||||
bool getGlow() const { return _glow; }
|
||||
|
||||
void setFaceCamera(bool faceCamera) { _faceCamera = faceCamera; }
|
||||
bool getFaceCamera() const { return _faceCamera; }
|
||||
virtual ShapeType getShapeType() const override { return SHAPE_TYPE_NONE; }
|
||||
|
||||
bool pointsChanged() const { return _pointsChanged; }
|
||||
bool normalsChanged() const { return _normalsChanged; }
|
||||
bool colorsChanged() const { return _colorsChanged; }
|
||||
bool widthsChanged() const { return _widthsChanged; }
|
||||
bool texturesChanged() const { return _texturesChanged; }
|
||||
bool strokeColorsChanged() const { return _strokeColorsChanged; }
|
||||
bool strokeWidthsChanged() const { return _strokeWidthsChanged; }
|
||||
bool texturesChanged() const { return _texturesChangedFlag; }
|
||||
void resetTexturesChanged() { _texturesChangedFlag = false; }
|
||||
void resetPolyLineChanged() { _strokeColorsChanged = _strokeWidthsChanged = _normalsChanged = _pointsChanged = false; }
|
||||
|
||||
void resetTexturesChanged() { _texturesChanged = false; }
|
||||
void resetPolyLineChanged() { _colorsChanged = _widthsChanged = _normalsChanged = _pointsChanged = false; }
|
||||
|
||||
// never have a ray intersection pick a PolyLineEntityItem.
|
||||
virtual bool supportsDetailedIntersection() const override { return true; }
|
||||
|
@ -92,27 +85,29 @@ class PolyLineEntityItem : public EntityItem {
|
|||
BoxFace& face, glm::vec3& surfaceNormal,
|
||||
QVariantMap& extraInfo, bool precisionPicking) const override { return false; }
|
||||
|
||||
// disable these external interfaces as PolyLineEntities caculate their own dimensions based on the points they contain
|
||||
virtual void setRegistrationPoint(const glm::vec3& value) override {}; // FIXME: this is suspicious!
|
||||
|
||||
virtual void debugDump() const override;
|
||||
static const float DEFAULT_LINE_WIDTH;
|
||||
static const int MAX_POINTS_PER_LINE;
|
||||
private:
|
||||
void computeAndUpdateDimensionsAndPosition();
|
||||
void calculateScaleAndRegistrationPoint();
|
||||
|
||||
protected:
|
||||
glm::u8vec3 _color;
|
||||
bool _pointsChanged { true };
|
||||
bool _normalsChanged { true };
|
||||
bool _strokeColorsChanged { true };
|
||||
bool _strokeWidthsChanged { true };
|
||||
QVector<glm::vec3> _points;
|
||||
glm::vec3 _polylineCenter;
|
||||
QVector<glm::vec3> _normals;
|
||||
QVector<glm::vec3> _colors;
|
||||
QVector<float> _widths;
|
||||
QVector<glm::vec3> _strokeColors;
|
||||
QVector<float> _strokeWidths;
|
||||
QString _textures;
|
||||
bool _isUVModeStretch;
|
||||
bool _glow;
|
||||
bool _faceCamera;
|
||||
|
||||
bool _pointsChanged { false };
|
||||
bool _normalsChanged { false };
|
||||
bool _colorsChanged { false };
|
||||
bool _widthsChanged { false };
|
||||
bool _texturesChanged { false };
|
||||
bool _texturesChangedFlag { false };
|
||||
mutable QReadWriteLock _quadReadWriteLock;
|
||||
};
|
||||
|
||||
#endif // hifi_PolyLineEntityItem_h
|
||||
|
|
|
@ -33,7 +33,7 @@ PacketVersion versionForPacketType(PacketType packetType) {
|
|||
case PacketType::EntityEdit:
|
||||
case PacketType::EntityData:
|
||||
case PacketType::EntityPhysics:
|
||||
return static_cast<PacketVersion>(EntityVersion::MissingLineProperties);
|
||||
return static_cast<PacketVersion>(EntityVersion::MorePropertiesCleanup);
|
||||
case PacketType::EntityQuery:
|
||||
return static_cast<PacketVersion>(EntityQueryPacketVersion::ConicalFrustums);
|
||||
case PacketType::AvatarIdentity:
|
||||
|
|
|
@ -251,7 +251,7 @@ enum class EntityVersion : PacketVersion {
|
|||
ImageEntities,
|
||||
GridEntities,
|
||||
MissingTextProperties,
|
||||
MissingLineProperties
|
||||
MorePropertiesCleanup
|
||||
};
|
||||
|
||||
enum class EntityScriptCallMethodVersion : PacketVersion {
|
||||
|
|
Loading…
Reference in a new issue