mirror of
https://github.com/HifiExperiments/overte.git
synced 2025-08-14 17:39:30 +02:00
DELETE IT ALL
This commit is contained in:
parent
a2083d949e
commit
becc9f4f8d
44 changed files with 600 additions and 5963 deletions
|
@ -1,392 +0,0 @@
|
|||
//
|
||||
// Base3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 "Base3DOverlay.h"
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <SharedUtil.h>
|
||||
#include "Application.h"
|
||||
|
||||
|
||||
const bool DEFAULT_IS_SOLID = false;
|
||||
const bool DEFAULT_IS_DASHED_LINE = false;
|
||||
|
||||
Base3DOverlay::Base3DOverlay() :
|
||||
SpatiallyNestable(NestableType::Overlay, QUuid::createUuid()),
|
||||
_isSolid(DEFAULT_IS_SOLID),
|
||||
_isDashedLine(DEFAULT_IS_DASHED_LINE),
|
||||
_ignorePickIntersection(false),
|
||||
_drawInFront(false),
|
||||
_drawHUDLayer(false)
|
||||
{
|
||||
// HACK: queryAACube stuff not actually relevant for 3DOverlays, and by setting _queryAACubeSet true here
|
||||
// we can avoid incorrect evaluation for sending updates for entities with 3DOverlays children.
|
||||
_queryAACubeSet = true;
|
||||
}
|
||||
|
||||
Base3DOverlay::Base3DOverlay(const Base3DOverlay* base3DOverlay) :
|
||||
Overlay(base3DOverlay),
|
||||
SpatiallyNestable(NestableType::Overlay, QUuid::createUuid()),
|
||||
_isSolid(base3DOverlay->_isSolid),
|
||||
_isDashedLine(base3DOverlay->_isDashedLine),
|
||||
_ignorePickIntersection(base3DOverlay->_ignorePickIntersection),
|
||||
_drawInFront(base3DOverlay->_drawInFront),
|
||||
_drawHUDLayer(base3DOverlay->_drawHUDLayer),
|
||||
_isGrabbable(base3DOverlay->_isGrabbable),
|
||||
_isVisibleInSecondaryCamera(base3DOverlay->_isVisibleInSecondaryCamera)
|
||||
{
|
||||
setTransform(base3DOverlay->getTransform());
|
||||
// HACK: queryAACube stuff not actually relevant for 3DOverlays, and by setting _queryAACubeSet true here
|
||||
// we can avoid incorrect evaluation for sending updates for entities with 3DOverlays children.
|
||||
_queryAACubeSet = true;
|
||||
}
|
||||
|
||||
QVariantMap convertOverlayLocationFromScriptSemantics(const QVariantMap& properties, bool scalesWithParent) {
|
||||
// the position and rotation in _transform are relative to the parent (aka local). The versions coming from
|
||||
// scripts are in world-frame, unless localPosition or localRotation are used. Patch up the properties
|
||||
// so that "position" and "rotation" are relative-to-parent values.
|
||||
QVariantMap result = properties;
|
||||
QUuid parentID = result["parentID"].isValid() ? QUuid(result["parentID"].toString()) : QUuid();
|
||||
int parentJointIndex = result["parentJointIndex"].isValid() ? result["parentJointIndex"].toInt() : -1;
|
||||
bool success;
|
||||
|
||||
// make "position" and "orientation" be relative-to-parent
|
||||
if (result["localPosition"].isValid()) {
|
||||
result["position"] = result["localPosition"];
|
||||
} else if (result["position"].isValid()) {
|
||||
glm::vec3 localPosition = SpatiallyNestable::worldToLocal(vec3FromVariant(result["position"]),
|
||||
parentID, parentJointIndex, scalesWithParent, success);
|
||||
if (success) {
|
||||
result["position"] = vec3toVariant(localPosition);
|
||||
}
|
||||
}
|
||||
|
||||
if (result["localOrientation"].isValid()) {
|
||||
result["orientation"] = result["localOrientation"];
|
||||
} else if (result["orientation"].isValid()) {
|
||||
glm::quat localOrientation = SpatiallyNestable::worldToLocal(quatFromVariant(result["orientation"]),
|
||||
parentID, parentJointIndex, scalesWithParent, success);
|
||||
if (success) {
|
||||
result["orientation"] = quatToVariant(localOrientation);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void Base3DOverlay::setProperties(const QVariantMap& originalProperties) {
|
||||
QVariantMap properties = originalProperties;
|
||||
|
||||
if (properties["name"].isValid()) {
|
||||
setName(properties["name"].toString());
|
||||
}
|
||||
|
||||
// carry over some legacy keys
|
||||
if (!properties["position"].isValid() && !properties["localPosition"].isValid()) {
|
||||
if (properties["p1"].isValid()) {
|
||||
properties["position"] = properties["p1"];
|
||||
} else if (properties["point"].isValid()) {
|
||||
properties["position"] = properties["point"];
|
||||
} else if (properties["start"].isValid()) {
|
||||
properties["position"] = properties["start"];
|
||||
}
|
||||
}
|
||||
if (!properties["orientation"].isValid() && properties["rotation"].isValid()) {
|
||||
properties["orientation"] = properties["rotation"];
|
||||
}
|
||||
if (!properties["localOrientation"].isValid() && properties["localRotation"].isValid()) {
|
||||
properties["localOrientation"] = properties["localRotation"];
|
||||
}
|
||||
|
||||
// All of parentID, parentJointIndex, position, orientation are needed to make sense of any of them.
|
||||
// If any of these changed, pull any missing properties from the overlay.
|
||||
if (properties["parentID"].isValid() || properties["parentJointIndex"].isValid() ||
|
||||
properties["position"].isValid() || properties["localPosition"].isValid() ||
|
||||
properties["orientation"].isValid() || properties["localOrientation"].isValid()) {
|
||||
if (!properties["parentID"].isValid()) {
|
||||
properties["parentID"] = getParentID();
|
||||
}
|
||||
if (!properties["parentJointIndex"].isValid()) {
|
||||
properties["parentJointIndex"] = getParentJointIndex();
|
||||
}
|
||||
if (!properties["position"].isValid() && !properties["localPosition"].isValid()) {
|
||||
properties["position"] = vec3toVariant(getWorldPosition());
|
||||
}
|
||||
if (!properties["orientation"].isValid() && !properties["localOrientation"].isValid()) {
|
||||
properties["orientation"] = quatToVariant(getWorldOrientation());
|
||||
}
|
||||
}
|
||||
|
||||
properties = convertOverlayLocationFromScriptSemantics(properties, getScalesWithParent());
|
||||
Overlay::setProperties(properties);
|
||||
|
||||
bool needRenderItemUpdate = false;
|
||||
|
||||
auto drawInFront = properties["drawInFront"];
|
||||
if (drawInFront.isValid()) {
|
||||
bool value = drawInFront.toBool();
|
||||
setDrawInFront(value);
|
||||
needRenderItemUpdate = true;
|
||||
}
|
||||
|
||||
auto drawHUDLayer = properties["drawHUDLayer"];
|
||||
if (drawHUDLayer.isValid()) {
|
||||
bool value = drawHUDLayer.toBool();
|
||||
setDrawHUDLayer(value);
|
||||
needRenderItemUpdate = true;
|
||||
}
|
||||
|
||||
auto isGrabbable = properties["grabbable"];
|
||||
if (isGrabbable.isValid()) {
|
||||
setIsGrabbable(isGrabbable.toBool());
|
||||
}
|
||||
|
||||
auto isVisibleInSecondaryCamera = properties["isVisibleInSecondaryCamera"];
|
||||
if (isVisibleInSecondaryCamera.isValid()) {
|
||||
bool value = isVisibleInSecondaryCamera.toBool();
|
||||
setIsVisibleInSecondaryCamera(value);
|
||||
needRenderItemUpdate = true;
|
||||
}
|
||||
|
||||
if (properties["position"].isValid()) {
|
||||
setLocalPosition(vec3FromVariant(properties["position"]));
|
||||
needRenderItemUpdate = true;
|
||||
}
|
||||
if (properties["orientation"].isValid()) {
|
||||
setLocalOrientation(quatFromVariant(properties["orientation"]));
|
||||
needRenderItemUpdate = true;
|
||||
}
|
||||
if (properties["isSolid"].isValid()) {
|
||||
setIsSolid(properties["isSolid"].toBool());
|
||||
}
|
||||
if (properties["isFilled"].isValid()) {
|
||||
setIsSolid(properties["isSolid"].toBool());
|
||||
}
|
||||
if (properties["isWire"].isValid()) {
|
||||
setIsSolid(!properties["isWire"].toBool());
|
||||
}
|
||||
if (properties["solid"].isValid()) {
|
||||
setIsSolid(properties["solid"].toBool());
|
||||
}
|
||||
if (properties["filled"].isValid()) {
|
||||
setIsSolid(properties["filled"].toBool());
|
||||
}
|
||||
if (properties["wire"].isValid()) {
|
||||
setIsSolid(!properties["wire"].toBool());
|
||||
}
|
||||
|
||||
if (properties["isDashedLine"].isValid()) {
|
||||
qDebug() << "isDashed is deprecated and will be removed in RC79!";
|
||||
setIsDashedLine(properties["isDashedLine"].toBool());
|
||||
}
|
||||
if (properties["dashed"].isValid()) {
|
||||
qDebug() << "dashed is deprecated and will be removed in RC79!";
|
||||
setIsDashedLine(properties["dashed"].toBool());
|
||||
}
|
||||
if (properties["ignorePickIntersection"].isValid()) {
|
||||
setIgnorePickIntersection(properties["ignorePickIntersection"].toBool());
|
||||
} else if (properties["ignoreRayIntersection"].isValid()) {
|
||||
setIgnorePickIntersection(properties["ignoreRayIntersection"].toBool());
|
||||
}
|
||||
|
||||
if (properties["parentID"].isValid()) {
|
||||
setParentID(QUuid(properties["parentID"].toString()));
|
||||
needRenderItemUpdate = true;
|
||||
}
|
||||
if (properties["parentJointIndex"].isValid()) {
|
||||
setParentJointIndex(properties["parentJointIndex"].toInt());
|
||||
needRenderItemUpdate = true;
|
||||
}
|
||||
|
||||
// Communicate changes to the renderItem if needed
|
||||
if (needRenderItemUpdate) {
|
||||
auto itemID = getRenderItemID();
|
||||
if (render::Item::isValidID(itemID)) {
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
transaction.updateItem(itemID);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
_queryAACubeSet = true; // HACK: just in case some SpatiallyNestable code accidentally set it false
|
||||
}
|
||||
}
|
||||
|
||||
// JSDoc for copying to @typedefs of overlay types that inherit Base3DOverlay.
|
||||
/**jsdoc
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {boolean} isVisibleInSecondaryCamera=false - If <code>true</code>, the overlay is rendered in secondary
|
||||
* camera views.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*/
|
||||
QVariant Base3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "name") {
|
||||
return _nameLock.resultWithReadLock<QString>([&] {
|
||||
return _name;
|
||||
});
|
||||
}
|
||||
if (property == "position" || property == "start" || property == "p1" || property == "point") {
|
||||
return vec3toVariant(getWorldPosition());
|
||||
}
|
||||
if (property == "localPosition") {
|
||||
return vec3toVariant(getLocalPosition());
|
||||
}
|
||||
if (property == "rotation" || property == "orientation") {
|
||||
return quatToVariant(getWorldOrientation());
|
||||
}
|
||||
if (property == "localRotation" || property == "localOrientation") {
|
||||
return quatToVariant(getLocalOrientation());
|
||||
}
|
||||
if (property == "isSolid" || property == "isFilled" || property == "solid" || property == "filled") {
|
||||
return _isSolid;
|
||||
}
|
||||
if (property == "isWire" || property == "wire") {
|
||||
return !_isSolid;
|
||||
}
|
||||
if (property == "isDashedLine" || property == "dashed") {
|
||||
qDebug() << "isDashedLine/dashed are deprecated and will be removed in RC79!";
|
||||
return _isDashedLine;
|
||||
}
|
||||
if (property == "ignorePickIntersection" || property == "ignoreRayIntersection") {
|
||||
return _ignorePickIntersection;
|
||||
}
|
||||
if (property == "drawInFront") {
|
||||
return _drawInFront;
|
||||
}
|
||||
if (property == "grabbable") {
|
||||
return _isGrabbable;
|
||||
}
|
||||
if (property == "isVisibleInSecondaryCamera") {
|
||||
return _isVisibleInSecondaryCamera;
|
||||
}
|
||||
if (property == "parentID") {
|
||||
return getParentID();
|
||||
}
|
||||
if (property == "parentJointIndex") {
|
||||
return getParentJointIndex();
|
||||
}
|
||||
|
||||
return Overlay::getProperty(property);
|
||||
}
|
||||
|
||||
void Base3DOverlay::locationChanged(bool tellPhysics) {
|
||||
SpatiallyNestable::locationChanged(tellPhysics);
|
||||
|
||||
// Force the actual update of the render transform through the notify call
|
||||
notifyRenderVariableChange();
|
||||
}
|
||||
|
||||
// FIXME: Overlays shouldn't be deleted when their parents are
|
||||
void Base3DOverlay::parentDeleted() {
|
||||
qApp->getOverlays().deleteOverlay(Overlay::getID());
|
||||
}
|
||||
|
||||
void Base3DOverlay::update(float duration) {
|
||||
// In Base3DOverlay, if its location or bound changed, the renderTrasnformDirty flag is true.
|
||||
// then the correct transform used for rendering is computed in the update transaction and assigned.
|
||||
if (_renderVariableDirty) {
|
||||
auto itemID = getRenderItemID();
|
||||
if (render::Item::isValidID(itemID)) {
|
||||
// Capture the render transform value in game loop before
|
||||
auto latestTransform = evalRenderTransform();
|
||||
bool latestVisible = getVisible();
|
||||
_renderVariableDirty = false;
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
transaction.updateItem<Overlay>(itemID, [latestTransform, latestVisible](Overlay& data) {
|
||||
auto overlay3D = dynamic_cast<Base3DOverlay*>(&data);
|
||||
if (overlay3D) {
|
||||
// TODO: overlays need to communicate all relavent render properties through transactions
|
||||
overlay3D->setRenderTransform(latestTransform);
|
||||
overlay3D->setRenderVisible(latestVisible);
|
||||
}
|
||||
});
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Base3DOverlay::notifyRenderVariableChange() const {
|
||||
_renderVariableDirty = true;
|
||||
}
|
||||
|
||||
Transform Base3DOverlay::evalRenderTransform() {
|
||||
return getTransform();
|
||||
}
|
||||
|
||||
void Base3DOverlay::setRenderTransform(const Transform& transform) {
|
||||
_renderTransform = transform;
|
||||
}
|
||||
|
||||
void Base3DOverlay::setRenderVisible(bool visible) {
|
||||
_renderVisible = visible;
|
||||
}
|
||||
|
||||
SpatialParentTree* Base3DOverlay::getParentTree() const {
|
||||
auto entityTreeRenderer = qApp->getEntities();
|
||||
EntityTreePointer entityTree = entityTreeRenderer ? entityTreeRenderer->getTree() : nullptr;
|
||||
return entityTree.get();
|
||||
}
|
||||
|
||||
void Base3DOverlay::setVisible(bool visible) {
|
||||
Parent::setVisible(visible);
|
||||
notifyRenderVariableChange();
|
||||
}
|
||||
|
||||
QString Base3DOverlay::getName() const {
|
||||
return _nameLock.resultWithReadLock<QString>([&] {
|
||||
return QString("Overlay:") + _name;
|
||||
});
|
||||
}
|
||||
|
||||
void Base3DOverlay::setName(QString name) {
|
||||
_nameLock.withWriteLock([&] {
|
||||
_name = name;
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
render::ItemKey Base3DOverlay::getKey() {
|
||||
auto builder = render::ItemKey::Builder(Overlay::getKey());
|
||||
|
||||
if (getDrawInFront()) {
|
||||
builder.withLayer(render::hifi::LAYER_3D_FRONT);
|
||||
} else if (getDrawHUDLayer()) {
|
||||
builder.withLayer(render::hifi::LAYER_3D_HUD);
|
||||
} else {
|
||||
builder.withoutLayer();
|
||||
}
|
||||
|
||||
builder.withoutViewSpace();
|
||||
|
||||
if (isTransparent()) {
|
||||
builder.withTransparent();
|
||||
}
|
||||
|
||||
return builder.build();
|
||||
}
|
|
@ -1,106 +0,0 @@
|
|||
//
|
||||
// Base3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Base3DOverlay_h
|
||||
#define hifi_Base3DOverlay_h
|
||||
|
||||
#include <Transform.h>
|
||||
#include <SpatiallyNestable.h>
|
||||
#include <graphics-scripting/Forward.h>
|
||||
#include "Overlay.h"
|
||||
|
||||
class Base3DOverlay : public Overlay, public SpatiallyNestable, public scriptable::ModelProvider {
|
||||
Q_OBJECT
|
||||
using Parent = Overlay;
|
||||
|
||||
public:
|
||||
Base3DOverlay();
|
||||
Base3DOverlay(const Base3DOverlay* base3DOverlay);
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
bool queryAACubeNeedsUpdate() const override { return false; } // HACK: queryAACube not relevant for Overlays
|
||||
|
||||
virtual QString getName() const override;
|
||||
void setName(QString name);
|
||||
|
||||
virtual render::ItemKey getKey() override;
|
||||
virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return (uint32_t) subItems.size(); }
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override { return scriptable::ScriptableModelBase(); }
|
||||
|
||||
// TODO: consider implementing registration points in this class
|
||||
glm::vec3 getCenter() const { return getWorldPosition(); }
|
||||
|
||||
bool getIsSolid() const { return _isSolid; }
|
||||
bool getIsDashedLine() const { return _isDashedLine; }
|
||||
bool getIsSolidLine() const { return !_isDashedLine; }
|
||||
bool getIgnorePickIntersection() const { return _ignorePickIntersection; }
|
||||
bool getDrawInFront() const { return _drawInFront; }
|
||||
bool getDrawHUDLayer() const { return _drawHUDLayer; }
|
||||
bool getIsGrabbable() const { return _isGrabbable; }
|
||||
virtual bool getIsVisibleInSecondaryCamera() const override { return _isVisibleInSecondaryCamera; }
|
||||
|
||||
void setIsSolid(bool isSolid) { _isSolid = isSolid; }
|
||||
void setIsDashedLine(bool isDashedLine) { _isDashedLine = isDashedLine; }
|
||||
void setIgnorePickIntersection(bool value) { _ignorePickIntersection = value; }
|
||||
virtual void setDrawInFront(bool value) { _drawInFront = value; }
|
||||
virtual void setDrawHUDLayer(bool value) { _drawHUDLayer = value; }
|
||||
void setIsGrabbable(bool value) { _isGrabbable = value; }
|
||||
virtual void setIsVisibleInSecondaryCamera(bool value) { _isVisibleInSecondaryCamera = value; }
|
||||
|
||||
void update(float deltatime) override;
|
||||
|
||||
void notifyRenderVariableChange() const;
|
||||
|
||||
virtual void setProperties(const QVariantMap& properties) override;
|
||||
virtual QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) { return false; }
|
||||
|
||||
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) {
|
||||
return findRayIntersection(origin, direction, distance, face, surfaceNormal, precisionPicking);
|
||||
}
|
||||
|
||||
virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) { return false; }
|
||||
|
||||
virtual bool findParabolaIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) {
|
||||
return findParabolaIntersection(origin, velocity, acceleration, parabolicDistance, face, surfaceNormal, precisionPicking);
|
||||
}
|
||||
|
||||
virtual SpatialParentTree* getParentTree() const override;
|
||||
|
||||
protected:
|
||||
virtual void locationChanged(bool tellPhysics = true) override;
|
||||
virtual void parentDeleted() override;
|
||||
|
||||
mutable Transform _renderTransform;
|
||||
mutable bool _renderVisible;
|
||||
virtual Transform evalRenderTransform();
|
||||
virtual void setRenderTransform(const Transform& transform);
|
||||
void setRenderVisible(bool visible);
|
||||
const Transform& getRenderTransform() const { return _renderTransform; }
|
||||
|
||||
bool _isSolid;
|
||||
bool _isDashedLine;
|
||||
bool _ignorePickIntersection;
|
||||
bool _drawInFront;
|
||||
bool _drawHUDLayer;
|
||||
bool _isGrabbable { false };
|
||||
bool _isVisibleInSecondaryCamera { false };
|
||||
mutable bool _renderVariableDirty { true };
|
||||
|
||||
QString _name;
|
||||
mutable ReadWriteLockable _nameLock;
|
||||
};
|
||||
|
||||
#endif // hifi_Base3DOverlay_h
|
|
@ -1,65 +0,0 @@
|
|||
//
|
||||
// Billboard3DOverlay.cpp
|
||||
// hifi/interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 8/4/15.
|
||||
// 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 "Billboard3DOverlay.h"
|
||||
|
||||
Billboard3DOverlay::Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay) :
|
||||
Planar3DOverlay(billboard3DOverlay),
|
||||
PanelAttachable(*billboard3DOverlay),
|
||||
Billboardable(*billboard3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
void Billboard3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
PanelAttachable::setProperties(properties);
|
||||
Billboardable::setProperties(properties);
|
||||
}
|
||||
|
||||
QVariant Billboard3DOverlay::getProperty(const QString &property) {
|
||||
QVariant value;
|
||||
value = Billboardable::getProperty(property);
|
||||
if (value.isValid()) {
|
||||
return value;
|
||||
}
|
||||
value = PanelAttachable::getProperty(property);
|
||||
if (value.isValid()) {
|
||||
return value;
|
||||
}
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) {
|
||||
bool transformChanged = false;
|
||||
if (force || usecTimestampNow() > _transformExpiry) {
|
||||
transformChanged = PanelAttachable::applyTransformTo(transform, true);
|
||||
transformChanged |= pointTransformAtCamera(transform, getOffsetRotation());
|
||||
}
|
||||
return transformChanged;
|
||||
}
|
||||
|
||||
void Billboard3DOverlay::update(float duration) {
|
||||
if (isFacingAvatar()) {
|
||||
_renderVariableDirty = true;
|
||||
}
|
||||
Parent::update(duration);
|
||||
}
|
||||
|
||||
Transform Billboard3DOverlay::evalRenderTransform() {
|
||||
Transform transform = getTransform();
|
||||
bool transformChanged = applyTransformTo(transform, true);
|
||||
// If the transform is not modified, setting the transform to
|
||||
// itself will cause drift over time due to floating point errors.
|
||||
if (transformChanged) {
|
||||
setTransform(transform);
|
||||
}
|
||||
return transform;
|
||||
}
|
|
@ -1,38 +0,0 @@
|
|||
//
|
||||
// Billboard3DOverlay.h
|
||||
// hifi/interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 8/4/15.
|
||||
// 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_Billboard3DOverlay_h
|
||||
#define hifi_Billboard3DOverlay_h
|
||||
|
||||
#include "Planar3DOverlay.h"
|
||||
#include "PanelAttachable.h"
|
||||
#include "Billboardable.h"
|
||||
|
||||
class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable, public Billboardable {
|
||||
Q_OBJECT
|
||||
using Parent = Planar3DOverlay;
|
||||
|
||||
public:
|
||||
Billboard3DOverlay() {}
|
||||
Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay);
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
void update(float duration) override;
|
||||
|
||||
protected:
|
||||
virtual bool applyTransformTo(Transform& transform, bool force = false) override;
|
||||
|
||||
Transform evalRenderTransform() override;
|
||||
};
|
||||
|
||||
#endif // hifi_Billboard3DOverlay_h
|
|
@ -1,56 +0,0 @@
|
|||
//
|
||||
// Billboardable.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 8/7/15.
|
||||
// Modified by Daniela Fontes on 24/10/17.
|
||||
// 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 "Billboardable.h"
|
||||
|
||||
#include <Application.h>
|
||||
#include <Transform.h>
|
||||
#include "avatar/AvatarManager.h"
|
||||
|
||||
void Billboardable::setProperties(const QVariantMap& properties) {
|
||||
auto isFacingAvatar = properties["isFacingAvatar"];
|
||||
if (isFacingAvatar.isValid()) {
|
||||
setIsFacingAvatar(isFacingAvatar.toBool());
|
||||
}
|
||||
}
|
||||
|
||||
// JSDoc for copying to @typedefs of overlay types that inherit Billboardable.
|
||||
/**jsdoc
|
||||
* @property {boolean} isFacingAvatar - If <code>true</code>, the overlay is rotated to face the user's camera about an axis
|
||||
* parallel to the user's avatar's "up" direction.
|
||||
*/
|
||||
QVariant Billboardable::getProperty(const QString &property) {
|
||||
if (property == "isFacingAvatar") {
|
||||
return isFacingAvatar();
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
bool Billboardable::pointTransformAtCamera(Transform& transform, glm::quat offsetRotation) {
|
||||
if (isFacingAvatar()) {
|
||||
glm::vec3 billboardPos = transform.getTranslation();
|
||||
glm::vec3 cameraPos = qApp->getCamera().getPosition();
|
||||
// use the referencial from the avatar, y isn't always up
|
||||
glm::vec3 avatarUP = DependencyManager::get<AvatarManager>()->getMyAvatar()->getWorldOrientation()*Vectors::UP;
|
||||
// check to see if glm::lookAt will work / using glm::lookAt variable name
|
||||
glm::highp_vec3 s(glm::cross(billboardPos - cameraPos, avatarUP));
|
||||
|
||||
// make sure s is not NaN for any component
|
||||
if(glm::length2(s) > 0.0f) {
|
||||
glm::quat rotation(conjugate(toQuat(glm::lookAt(cameraPos, billboardPos, avatarUP))));
|
||||
transform.setRotation(rotation);
|
||||
transform.postRotate(offsetRotation);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,36 +0,0 @@
|
|||
//
|
||||
// Billboardable.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 8/7/15.
|
||||
// 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_Billboardable_h
|
||||
#define hifi_Billboardable_h
|
||||
|
||||
#include <glm/gtc/quaternion.hpp>
|
||||
#include <QVariant>
|
||||
|
||||
class QString;
|
||||
class Transform;
|
||||
|
||||
class Billboardable {
|
||||
public:
|
||||
bool isFacingAvatar() const { return _isFacingAvatar; }
|
||||
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
|
||||
|
||||
protected:
|
||||
void setProperties(const QVariantMap& properties);
|
||||
QVariant getProperty(const QString& property);
|
||||
|
||||
bool pointTransformAtCamera(Transform& transform, glm::quat offsetRotation = {1, 0, 0, 0});
|
||||
|
||||
private:
|
||||
bool _isFacingAvatar = false;
|
||||
};
|
||||
|
||||
#endif // hifi_Billboardable_h
|
|
@ -1,589 +0,0 @@
|
|||
//
|
||||
// Circle3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 "Circle3DOverlay.h"
|
||||
|
||||
#include <GeometryUtil.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
QString const Circle3DOverlay::TYPE = "circle3d";
|
||||
|
||||
Circle3DOverlay::Circle3DOverlay() {}
|
||||
|
||||
Circle3DOverlay::Circle3DOverlay(const Circle3DOverlay* circle3DOverlay) :
|
||||
Planar3DOverlay(circle3DOverlay),
|
||||
_startAt(circle3DOverlay->_startAt),
|
||||
_endAt(circle3DOverlay->_endAt),
|
||||
_outerRadius(circle3DOverlay->_outerRadius),
|
||||
_innerRadius(circle3DOverlay->_innerRadius),
|
||||
_innerStartColor(circle3DOverlay->_innerStartColor),
|
||||
_innerEndColor(circle3DOverlay->_innerEndColor),
|
||||
_outerStartColor(circle3DOverlay->_outerStartColor),
|
||||
_outerEndColor(circle3DOverlay->_outerEndColor),
|
||||
_innerStartAlpha(circle3DOverlay->_innerStartAlpha),
|
||||
_innerEndAlpha(circle3DOverlay->_innerEndAlpha),
|
||||
_outerStartAlpha(circle3DOverlay->_outerStartAlpha),
|
||||
_outerEndAlpha(circle3DOverlay->_outerEndAlpha),
|
||||
_hasTickMarks(circle3DOverlay->_hasTickMarks),
|
||||
_majorTickMarksAngle(circle3DOverlay->_majorTickMarksAngle),
|
||||
_minorTickMarksAngle(circle3DOverlay->_minorTickMarksAngle),
|
||||
_majorTickMarksLength(circle3DOverlay->_majorTickMarksLength),
|
||||
_minorTickMarksLength(circle3DOverlay->_minorTickMarksLength),
|
||||
_majorTickMarksColor(circle3DOverlay->_majorTickMarksColor),
|
||||
_minorTickMarksColor(circle3DOverlay->_minorTickMarksColor)
|
||||
{
|
||||
}
|
||||
|
||||
Circle3DOverlay::~Circle3DOverlay() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
if (_quadVerticesID) {
|
||||
geometryCache->releaseID(_quadVerticesID);
|
||||
}
|
||||
if (_lineVerticesID) {
|
||||
geometryCache->releaseID(_lineVerticesID);
|
||||
}
|
||||
if (_majorTicksVerticesID) {
|
||||
geometryCache->releaseID(_majorTicksVerticesID);
|
||||
}
|
||||
if (_minorTicksVerticesID) {
|
||||
geometryCache->releaseID(_minorTicksVerticesID);
|
||||
}
|
||||
}
|
||||
}
|
||||
void Circle3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
float alpha = getAlpha();
|
||||
if (alpha == 0.0f) {
|
||||
return; // do nothing if our alpha is 0, we're not visible
|
||||
}
|
||||
|
||||
bool geometryChanged = _dirty;
|
||||
_dirty = false;
|
||||
|
||||
const float FULL_CIRCLE = 360.0f;
|
||||
const float SLICES = 180.0f; // The amount of segment to create the circle
|
||||
const float SLICE_ANGLE_RADIANS = glm::radians(FULL_CIRCLE / SLICES);
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
Q_ASSERT(args->_batch);
|
||||
auto& batch = *args->_batch;
|
||||
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, isTransparent(), false, !getIsSolid(), true);
|
||||
|
||||
batch.setModelTransform(getRenderTransform());
|
||||
|
||||
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
|
||||
// we just draw a line...
|
||||
if (getIsSolid()) {
|
||||
if (!_quadVerticesID) {
|
||||
_quadVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
|
||||
if (geometryChanged) {
|
||||
QVector<glm::vec2> points;
|
||||
QVector<glm::vec4> colors;
|
||||
|
||||
float pulseLevel = updatePulse();
|
||||
vec4 pulseModifier = vec4(1);
|
||||
if (_alphaPulse != 0.0f) {
|
||||
pulseModifier.a = (_alphaPulse >= 0.0f) ? pulseLevel : (1.0f - pulseLevel);
|
||||
}
|
||||
if (_colorPulse != 0.0f) {
|
||||
float pulseValue = (_colorPulse >= 0.0f) ? pulseLevel : (1.0f - pulseLevel);
|
||||
pulseModifier = vec4(vec3(pulseValue), pulseModifier.a);
|
||||
}
|
||||
vec4 innerStartColor = vec4(toGlm(_innerStartColor), _innerStartAlpha) * pulseModifier;
|
||||
vec4 outerStartColor = vec4(toGlm(_outerStartColor), _outerStartAlpha) * pulseModifier;
|
||||
vec4 innerEndColor = vec4(toGlm(_innerEndColor), _innerEndAlpha) * pulseModifier;
|
||||
vec4 outerEndColor = vec4(toGlm(_outerEndColor), _outerEndAlpha) * pulseModifier;
|
||||
|
||||
const auto startAtRadians = glm::radians(_startAt);
|
||||
const auto endAtRadians = glm::radians(_endAt);
|
||||
|
||||
const auto totalRange = _endAt - _startAt;
|
||||
if (_innerRadius <= 0) {
|
||||
_solidPrimitive = gpu::TRIANGLE_FAN;
|
||||
points << vec2();
|
||||
colors << innerStartColor;
|
||||
for (float angleRadians = startAtRadians; angleRadians < endAtRadians; angleRadians += SLICE_ANGLE_RADIANS) {
|
||||
float range = (angleRadians - startAtRadians) / totalRange;
|
||||
points << glm::vec2(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius);
|
||||
colors << glm::mix(outerStartColor, outerEndColor, range);
|
||||
}
|
||||
points << glm::vec2(cosf(endAtRadians) * _outerRadius, sinf(endAtRadians) * _outerRadius);
|
||||
colors << outerEndColor;
|
||||
|
||||
} else {
|
||||
_solidPrimitive = gpu::TRIANGLE_STRIP;
|
||||
for (float angleRadians = startAtRadians; angleRadians < endAtRadians; angleRadians += SLICE_ANGLE_RADIANS) {
|
||||
float range = (angleRadians - startAtRadians) / totalRange;
|
||||
|
||||
points << glm::vec2(cosf(angleRadians) * _innerRadius, sinf(angleRadians) * _innerRadius);
|
||||
colors << glm::mix(innerStartColor, innerEndColor, range);
|
||||
|
||||
points << glm::vec2(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius);
|
||||
colors << glm::mix(outerStartColor, outerEndColor, range);
|
||||
}
|
||||
points << glm::vec2(cosf(endAtRadians) * _innerRadius, sinf(endAtRadians) * _innerRadius);
|
||||
colors << innerEndColor;
|
||||
|
||||
points << glm::vec2(cosf(endAtRadians) * _outerRadius, sinf(endAtRadians) * _outerRadius);
|
||||
colors << outerEndColor;
|
||||
}
|
||||
geometryCache->updateVertices(_quadVerticesID, points, colors);
|
||||
}
|
||||
|
||||
geometryCache->renderVertices(batch, _solidPrimitive, _quadVerticesID);
|
||||
|
||||
} else {
|
||||
if (!_lineVerticesID) {
|
||||
_lineVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
|
||||
if (geometryChanged) {
|
||||
QVector<glm::vec2> points;
|
||||
|
||||
const auto startAtRadians = glm::radians(_startAt);
|
||||
const auto endAtRadians = glm::radians(_endAt);
|
||||
|
||||
float angleRadians = startAtRadians;
|
||||
glm::vec2 firstPoint(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius);
|
||||
points << firstPoint;
|
||||
|
||||
while (angleRadians < endAtRadians) {
|
||||
angleRadians += SLICE_ANGLE_RADIANS;
|
||||
glm::vec2 thisPoint(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius);
|
||||
points << thisPoint;
|
||||
|
||||
if (getIsDashedLine()) {
|
||||
angleRadians += SLICE_ANGLE_RADIANS / 2.0f; // short gap
|
||||
glm::vec2 dashStartPoint(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius);
|
||||
points << dashStartPoint;
|
||||
}
|
||||
}
|
||||
|
||||
// get the last slice portion....
|
||||
angleRadians = endAtRadians;
|
||||
glm::vec2 lastPoint(cosf(angleRadians) * _outerRadius, sinf(angleRadians) * _outerRadius);
|
||||
points << lastPoint;
|
||||
geometryCache->updateVertices(_lineVerticesID, points, vec4(toGlm(getColor()), getAlpha()));
|
||||
}
|
||||
|
||||
if (getIsDashedLine()) {
|
||||
geometryCache->renderVertices(batch, gpu::LINES, _lineVerticesID);
|
||||
} else {
|
||||
geometryCache->renderVertices(batch, gpu::LINE_STRIP, _lineVerticesID);
|
||||
}
|
||||
}
|
||||
|
||||
// draw our tick marks
|
||||
// for our overlay, is solid means we draw a ring between the inner and outer radius of the circle, otherwise
|
||||
// we just draw a line...
|
||||
if (getHasTickMarks()) {
|
||||
if (!_majorTicksVerticesID) {
|
||||
_majorTicksVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
if (!_minorTicksVerticesID) {
|
||||
_minorTicksVerticesID = geometryCache->allocateID();
|
||||
}
|
||||
|
||||
if (geometryChanged) {
|
||||
QVector<glm::vec2> majorPoints;
|
||||
QVector<glm::vec2> minorPoints;
|
||||
|
||||
// draw our major tick marks
|
||||
if (getMajorTickMarksAngle() > 0.0f && getMajorTickMarksLength() != 0.0f) {
|
||||
|
||||
float tickMarkAngle = getMajorTickMarksAngle();
|
||||
float angle = _startAt - fmodf(_startAt, tickMarkAngle) + tickMarkAngle;
|
||||
float tickMarkLength = getMajorTickMarksLength();
|
||||
float startRadius = (tickMarkLength > 0.0f) ? _innerRadius : _outerRadius;
|
||||
float endRadius = startRadius + tickMarkLength;
|
||||
|
||||
while (angle <= _endAt) {
|
||||
float angleInRadians = glm::radians(angle);
|
||||
|
||||
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
|
||||
glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
|
||||
|
||||
majorPoints << thisPointA << thisPointB;
|
||||
|
||||
angle += tickMarkAngle;
|
||||
}
|
||||
}
|
||||
|
||||
// draw our minor tick marks
|
||||
if (getMinorTickMarksAngle() > 0.0f && getMinorTickMarksLength() != 0.0f) {
|
||||
|
||||
float tickMarkAngle = getMinorTickMarksAngle();
|
||||
float angle = _startAt - fmodf(_startAt, tickMarkAngle) + tickMarkAngle;
|
||||
float tickMarkLength = getMinorTickMarksLength();
|
||||
float startRadius = (tickMarkLength > 0.0f) ? _innerRadius : _outerRadius;
|
||||
float endRadius = startRadius + tickMarkLength;
|
||||
|
||||
while (angle <= _endAt) {
|
||||
float angleInRadians = glm::radians(angle);
|
||||
|
||||
glm::vec2 thisPointA(cosf(angleInRadians) * startRadius, sinf(angleInRadians) * startRadius);
|
||||
glm::vec2 thisPointB(cosf(angleInRadians) * endRadius, sinf(angleInRadians) * endRadius);
|
||||
|
||||
minorPoints << thisPointA << thisPointB;
|
||||
|
||||
angle += tickMarkAngle;
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec4 majorColor(toGlm(getMajorTickMarksColor()), alpha);
|
||||
geometryCache->updateVertices(_majorTicksVerticesID, majorPoints, majorColor);
|
||||
glm::vec4 minorColor(toGlm(getMinorTickMarksColor()), alpha);
|
||||
geometryCache->updateVertices(_minorTicksVerticesID, minorPoints, minorColor);
|
||||
}
|
||||
|
||||
geometryCache->renderVertices(batch, gpu::LINES, _majorTicksVerticesID);
|
||||
|
||||
geometryCache->renderVertices(batch, gpu::LINES, _minorTicksVerticesID);
|
||||
}
|
||||
}
|
||||
|
||||
const render::ShapeKey Circle3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid()) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
template<typename T> T fromVariant(const QVariant& v, bool& valid) {
|
||||
valid = v.isValid();
|
||||
return qvariant_cast<T>(v);
|
||||
}
|
||||
|
||||
template<> glm::u8vec3 fromVariant(const QVariant& v, bool& valid) {
|
||||
return u8vec3FromVariant(v, valid);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
bool updateIfValid(const QVariantMap& properties, const char* key, T& output) {
|
||||
bool valid;
|
||||
T result = fromVariant<T>(properties[key], valid);
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't signal updates if the value was already set
|
||||
if (result == output) {
|
||||
return false;
|
||||
}
|
||||
|
||||
output = result;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Multicast, many outputs
|
||||
template<typename T>
|
||||
bool updateIfValid(const QVariantMap& properties, const char* key, std::initializer_list<std::reference_wrapper<T>> outputs) {
|
||||
bool valid;
|
||||
T value = fromVariant<T>(properties[key], valid);
|
||||
if (!valid) {
|
||||
return false;
|
||||
}
|
||||
bool updated = false;
|
||||
for (T& output : outputs) {
|
||||
if (output != value) {
|
||||
output = value;
|
||||
updated = true;
|
||||
}
|
||||
}
|
||||
return updated;
|
||||
}
|
||||
|
||||
// Multicast, multiple possible inputs, in order of preference
|
||||
template<typename T>
|
||||
bool updateIfValid(const QVariantMap& properties, const std::initializer_list<const char*> keys, T& output) {
|
||||
for (const char* key : keys) {
|
||||
if (updateIfValid<T>(properties, key, output)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void Circle3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
_dirty |= updateIfValid<float>(properties, "alpha", { _innerStartAlpha, _innerEndAlpha, _outerStartAlpha, _outerEndAlpha });
|
||||
_dirty |= updateIfValid<float>(properties, "Alpha", { _innerStartAlpha, _innerEndAlpha, _outerStartAlpha, _outerEndAlpha });
|
||||
_dirty |= updateIfValid<float>(properties, "startAlpha", { _innerStartAlpha, _outerStartAlpha });
|
||||
_dirty |= updateIfValid<float>(properties, "endAlpha", { _innerEndAlpha, _outerEndAlpha });
|
||||
_dirty |= updateIfValid<float>(properties, "innerAlpha", { _innerStartAlpha, _innerEndAlpha });
|
||||
_dirty |= updateIfValid<float>(properties, "outerAlpha", { _outerStartAlpha, _outerEndAlpha });
|
||||
_dirty |= updateIfValid(properties, "innerStartAlpha", _innerStartAlpha);
|
||||
_dirty |= updateIfValid(properties, "innerEndAlpha", _innerEndAlpha);
|
||||
_dirty |= updateIfValid(properties, "outerStartAlpha", _outerStartAlpha);
|
||||
_dirty |= updateIfValid(properties, "outerEndAlpha", _outerEndAlpha);
|
||||
|
||||
_dirty |= updateIfValid<glm::u8vec3>(properties, "color", { _innerStartColor, _innerEndColor, _outerStartColor, _outerEndColor });
|
||||
_dirty |= updateIfValid<glm::u8vec3>(properties, "startColor", { _innerStartColor, _outerStartColor } );
|
||||
_dirty |= updateIfValid<glm::u8vec3>(properties, "endColor", { _innerEndColor, _outerEndColor } );
|
||||
_dirty |= updateIfValid<glm::u8vec3>(properties, "innerColor", { _innerStartColor, _innerEndColor } );
|
||||
_dirty |= updateIfValid<glm::u8vec3>(properties, "outerColor", { _outerStartColor, _outerEndColor } );
|
||||
_dirty |= updateIfValid(properties, "innerStartColor", _innerStartColor);
|
||||
_dirty |= updateIfValid(properties, "innerEndColor", _innerEndColor);
|
||||
_dirty |= updateIfValid(properties, "outerStartColor", _outerStartColor);
|
||||
_dirty |= updateIfValid(properties, "outerEndColor", _outerEndColor);
|
||||
|
||||
_dirty |= updateIfValid(properties, "startAt", _startAt);
|
||||
_dirty |= updateIfValid(properties, "endAt", _endAt);
|
||||
|
||||
_dirty |= updateIfValid(properties, { "radius", "outerRadius" }, _outerRadius);
|
||||
_dirty |= updateIfValid(properties, "innerRadius", _innerRadius);
|
||||
_dirty |= updateIfValid(properties, "hasTickMarks", _hasTickMarks);
|
||||
_dirty |= updateIfValid(properties, "majorTickMarksAngle", _majorTickMarksAngle);
|
||||
_dirty |= updateIfValid(properties, "minorTickMarksAngle", _minorTickMarksAngle);
|
||||
_dirty |= updateIfValid(properties, "majorTickMarksLength", _majorTickMarksLength);
|
||||
_dirty |= updateIfValid(properties, "minorTickMarksLength", _minorTickMarksLength);
|
||||
_dirty |= updateIfValid(properties, "majorTickMarksColor", _majorTickMarksColor);
|
||||
_dirty |= updateIfValid(properties, "minorTickMarksColor", _minorTickMarksColor);
|
||||
|
||||
if (_innerStartAlpha < 1.0f || _innerEndAlpha < 1.0f || _outerStartAlpha < 1.0f || _outerEndAlpha < 1.0f) {
|
||||
// Force the alpha to 0.5, since we'll ignore it in the presence of these other values, but we need
|
||||
// it to be non-1 in order to get the right pipeline and non-0 in order to render at all.
|
||||
_alpha = 0.5f;
|
||||
}
|
||||
}
|
||||
|
||||
// Overlay's color and alpha properties are overridden. And the dimensions property is not used.
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>circle3d</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.Circle3DProperties
|
||||
*
|
||||
* @property {string} type=circle3d - Has the value <code>"circle3d"</code>. <em>Read-only.</em>
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* <em>Not used.</em>
|
||||
*
|
||||
* @property {number} startAt=0 - The counter-clockwise angle from the overlay's x-axis that drawing starts at, in degrees.
|
||||
* @property {number} endAt=360 - The counter-clockwise angle from the overlay's x-axis that drawing ends at, in degrees.
|
||||
* @property {number} outerRadius=1 - The outer radius of the overlay, in meters. Synonym: <code>radius</code>.
|
||||
* @property {number} innerRadius=0 - The inner radius of the overlay, in meters.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay. Setting this value also sets the values of
|
||||
* <code>innerStartColor</code>, <code>innerEndColor</code>, <code>outerStartColor</code>, and <code>outerEndColor</code>.
|
||||
* @property {Color} startColor - Sets the values of <code>innerStartColor</code> and <code>outerStartColor</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {Color} endColor - Sets the values of <code>innerEndColor</code> and <code>outerEndColor</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {Color} innerColor - Sets the values of <code>innerStartColor</code> and <code>innerEndColor</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {Color} outerColor - Sets the values of <code>outerStartColor</code> and <code>outerEndColor</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {Color} innerStartcolor - The color at the inner start point of the overlay.
|
||||
* @property {Color} innerEndColor - The color at the inner end point of the overlay.
|
||||
* @property {Color} outerStartColor - The color at the outer start point of the overlay.
|
||||
* @property {Color} outerEndColor - The color at the outer end point of the overlay.
|
||||
* @property {number} alpha=0.5 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>. Setting this value also sets
|
||||
* the values of <code>innerStartAlpha</code>, <code>innerEndAlpha</code>, <code>outerStartAlpha</code>, and
|
||||
* <code>outerEndAlpha</code>. Synonym: <code>Alpha</code>; <em>write-only</em>.
|
||||
* @property {number} startAlpha - Sets the values of <code>innerStartAlpha</code> and <code>outerStartAlpha</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} endAlpha - Sets the values of <code>innerEndAlpha</code> and <code>outerEndAlpha</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} innerAlpha - Sets the values of <code>innerStartAlpha</code> and <code>innerEndAlpha</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} outerAlpha - Sets the values of <code>outerStartAlpha</code> and <code>outerEndAlpha</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} innerStartAlpha=0 - The alpha at the inner start point of the overlay.
|
||||
* @property {number} innerEndAlpha=0 - The alpha at the inner end point of the overlay.
|
||||
* @property {number} outerStartAlpha=0 - The alpha at the outer start point of the overlay.
|
||||
* @property {number} outerEndAlpha=0 - The alpha at the outer end point of the overlay.
|
||||
|
||||
* @property {boolean} hasTickMarks=false - If <code>true</code>, tick marks are drawn.
|
||||
* @property {number} majorTickMarksAngle=0 - The angle between major tick marks, in degrees.
|
||||
* @property {number} minorTickMarksAngle=0 - The angle between minor tick marks, in degrees.
|
||||
* @property {number} majorTickMarksLength=0 - The length of the major tick marks, in meters. A positive value draws tick marks
|
||||
* outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
|
||||
* @property {number} minorTickMarksLength=0 - The length of the minor tick marks, in meters. A positive value draws tick marks
|
||||
* outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
|
||||
* @property {Color} majorTickMarksColor=0,0,0 - The color of the major tick marks.
|
||||
* @property {Color} minorTickMarksColor=0,0,0 - The color of the minor tick marks.
|
||||
*/
|
||||
QVariant Circle3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "startAt") {
|
||||
return _startAt;
|
||||
}
|
||||
if (property == "endAt") {
|
||||
return _endAt;
|
||||
}
|
||||
if (property == "radius") {
|
||||
return _outerRadius;
|
||||
}
|
||||
if (property == "outerRadius") {
|
||||
return _outerRadius;
|
||||
}
|
||||
if (property == "innerRadius") {
|
||||
return _innerRadius;
|
||||
}
|
||||
if (property == "innerStartColor") {
|
||||
return u8vec3ColortoVariant(_innerStartColor);
|
||||
}
|
||||
if (property == "innerEndColor") {
|
||||
return u8vec3ColortoVariant(_innerEndColor);
|
||||
}
|
||||
if (property == "outerStartColor") {
|
||||
return u8vec3ColortoVariant(_outerStartColor);
|
||||
}
|
||||
if (property == "outerEndColor") {
|
||||
return u8vec3ColortoVariant(_outerEndColor);
|
||||
}
|
||||
if (property == "innerStartAlpha") {
|
||||
return _innerStartAlpha;
|
||||
}
|
||||
if (property == "innerEndAlpha") {
|
||||
return _innerEndAlpha;
|
||||
}
|
||||
if (property == "outerStartAlpha") {
|
||||
return _outerStartAlpha;
|
||||
}
|
||||
if (property == "outerEndAlpha") {
|
||||
return _outerEndAlpha;
|
||||
}
|
||||
if (property == "hasTickMarks") {
|
||||
return _hasTickMarks;
|
||||
}
|
||||
if (property == "majorTickMarksAngle") {
|
||||
return _majorTickMarksAngle;
|
||||
}
|
||||
if (property == "minorTickMarksAngle") {
|
||||
return _minorTickMarksAngle;
|
||||
}
|
||||
if (property == "majorTickMarksLength") {
|
||||
return _majorTickMarksLength;
|
||||
}
|
||||
if (property == "minorTickMarksLength") {
|
||||
return _minorTickMarksLength;
|
||||
}
|
||||
if (property == "majorTickMarksColor") {
|
||||
return u8vec3ColortoVariant(_majorTickMarksColor);
|
||||
}
|
||||
if (property == "minorTickMarksColor") {
|
||||
return u8vec3ColortoVariant(_minorTickMarksColor);
|
||||
}
|
||||
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool Circle3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
// Scale the dimensions by the diameter
|
||||
glm::vec2 dimensions = getOuterRadius() * 2.0f * getDimensions();
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
|
||||
if (findRayRectangleIntersection(origin, direction, rotation, getWorldPosition(), dimensions, distance)) {
|
||||
glm::vec3 hitPosition = origin + (distance * direction);
|
||||
glm::vec3 localHitPosition = glm::inverse(getWorldOrientation()) * (hitPosition - getWorldPosition());
|
||||
localHitPosition.x /= getDimensions().x;
|
||||
localHitPosition.y /= getDimensions().y;
|
||||
float distanceToHit = glm::length(localHitPosition);
|
||||
|
||||
if (getInnerRadius() <= distanceToHit && distanceToHit <= getOuterRadius()) {
|
||||
glm::vec3 forward = rotation * Vectors::FRONT;
|
||||
if (glm::dot(forward, direction) > 0.0f) {
|
||||
face = MAX_Z_FACE;
|
||||
surfaceNormal = -forward;
|
||||
} else {
|
||||
face = MIN_Z_FACE;
|
||||
surfaceNormal = forward;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Circle3DOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
// Scale the dimensions by the diameter
|
||||
glm::vec2 xyDimensions = getOuterRadius() * 2.0f * getDimensions();
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
glm::vec3 position = getWorldPosition();
|
||||
|
||||
glm::quat inverseRot = glm::inverse(rotation);
|
||||
glm::vec3 localOrigin = inverseRot * (origin - position);
|
||||
glm::vec3 localVelocity = inverseRot * velocity;
|
||||
glm::vec3 localAcceleration = inverseRot * acceleration;
|
||||
|
||||
if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) {
|
||||
glm::vec3 localHitPosition = localOrigin + localVelocity * parabolicDistance + 0.5f * localAcceleration * parabolicDistance * parabolicDistance;
|
||||
localHitPosition.x /= getDimensions().x;
|
||||
localHitPosition.y /= getDimensions().y;
|
||||
float distanceToHit = glm::length(localHitPosition);
|
||||
|
||||
if (getInnerRadius() <= distanceToHit && distanceToHit <= getOuterRadius()) {
|
||||
float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance;
|
||||
glm::vec3 forward = rotation * Vectors::FRONT;
|
||||
if (localIntersectionVelocityZ > 0.0f) {
|
||||
face = MIN_Z_FACE;
|
||||
surfaceNormal = forward;
|
||||
} else {
|
||||
face = MAX_Z_FACE;
|
||||
surfaceNormal = -forward;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Circle3DOverlay* Circle3DOverlay::createClone() const {
|
||||
return new Circle3DOverlay(this);
|
||||
}
|
|
@ -1,96 +0,0 @@
|
|||
//
|
||||
// Circle3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Circle3DOverlay_h
|
||||
#define hifi_Circle3DOverlay_h
|
||||
|
||||
// include this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class Circle3DOverlay : public Planar3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Circle3DOverlay();
|
||||
Circle3DOverlay(const Circle3DOverlay* circle3DOverlay);
|
||||
~Circle3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
float getStartAt() const { return _startAt; }
|
||||
float getEndAt() const { return _endAt; }
|
||||
float getOuterRadius() const { return _outerRadius; }
|
||||
float getInnerRadius() const { return _innerRadius; }
|
||||
bool getHasTickMarks() const { return _hasTickMarks; }
|
||||
float getMajorTickMarksAngle() const { return _majorTickMarksAngle; }
|
||||
float getMinorTickMarksAngle() const { return _minorTickMarksAngle; }
|
||||
float getMajorTickMarksLength() const { return _majorTickMarksLength; }
|
||||
float getMinorTickMarksLength() const { return _minorTickMarksLength; }
|
||||
glm::u8vec3 getMajorTickMarksColor() const { return _majorTickMarksColor; }
|
||||
glm::u8vec3 getMinorTickMarksColor() const { return _minorTickMarksColor; }
|
||||
|
||||
void setStartAt(float value) { _startAt = value; }
|
||||
void setEndAt(float value) { _endAt = value; }
|
||||
void setOuterRadius(float value) { _outerRadius = value; }
|
||||
void setInnerRadius(float value) { _innerRadius = value; }
|
||||
void setHasTickMarks(bool value) { _hasTickMarks = value; }
|
||||
void setMajorTickMarksAngle(float value) { _majorTickMarksAngle = value; }
|
||||
void setMinorTickMarksAngle(float value) { _minorTickMarksAngle = value; }
|
||||
void setMajorTickMarksLength(float value) { _majorTickMarksLength = value; }
|
||||
void setMinorTickMarksLength(float value) { _minorTickMarksLength = value; }
|
||||
void setMajorTickMarksColor(const glm::u8vec3& value) { _majorTickMarksColor = value; }
|
||||
void setMinorTickMarksColor(const glm::u8vec3& value) { _minorTickMarksColor = value; }
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
|
||||
virtual Circle3DOverlay* createClone() const override;
|
||||
|
||||
protected:
|
||||
float _startAt { 0 };
|
||||
float _endAt { 360 };
|
||||
float _outerRadius { 1 };
|
||||
float _innerRadius { 0 };
|
||||
|
||||
glm::u8vec3 _innerStartColor { DEFAULT_OVERLAY_COLOR };
|
||||
glm::u8vec3 _innerEndColor { DEFAULT_OVERLAY_COLOR };
|
||||
glm::u8vec3 _outerStartColor { DEFAULT_OVERLAY_COLOR };
|
||||
glm::u8vec3 _outerEndColor { DEFAULT_OVERLAY_COLOR };
|
||||
float _innerStartAlpha { DEFAULT_ALPHA };
|
||||
float _innerEndAlpha { DEFAULT_ALPHA };
|
||||
float _outerStartAlpha { DEFAULT_ALPHA };
|
||||
float _outerEndAlpha { DEFAULT_ALPHA };
|
||||
|
||||
bool _hasTickMarks { false };
|
||||
float _majorTickMarksAngle { 0 };
|
||||
float _minorTickMarksAngle { 0 };
|
||||
float _majorTickMarksLength { 0 };
|
||||
float _minorTickMarksLength { 0 };
|
||||
glm::u8vec3 _majorTickMarksColor { DEFAULT_OVERLAY_COLOR };
|
||||
glm::u8vec3 _minorTickMarksColor { DEFAULT_OVERLAY_COLOR };
|
||||
gpu::Primitive _solidPrimitive { gpu::TRIANGLE_FAN };
|
||||
int _quadVerticesID { 0 };
|
||||
int _lineVerticesID { 0 };
|
||||
int _majorTicksVerticesID { 0 };
|
||||
int _minorTicksVerticesID { 0 };
|
||||
|
||||
bool _dirty { true };
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Circle3DOverlay_h
|
|
@ -1,196 +0,0 @@
|
|||
//
|
||||
// Cube3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "Cube3DOverlay.h"
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
QString const Cube3DOverlay::TYPE = "cube";
|
||||
|
||||
Cube3DOverlay::Cube3DOverlay() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
for (size_t i = 0; i < _geometryIds.size(); ++i) {
|
||||
_geometryIds[i] = geometryCache->allocateID();
|
||||
}
|
||||
}
|
||||
|
||||
Cube3DOverlay::Cube3DOverlay(const Cube3DOverlay* cube3DOverlay) :
|
||||
Volume3DOverlay(cube3DOverlay)
|
||||
{
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
for (size_t i = 0; i < _geometryIds.size(); ++i) {
|
||||
_geometryIds[i] = geometryCache->allocateID();
|
||||
}
|
||||
}
|
||||
|
||||
Cube3DOverlay::~Cube3DOverlay() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
for (size_t i = 0; i < _geometryIds.size(); ++i) {
|
||||
geometryCache->releaseID(_geometryIds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Cube3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
float alpha = getAlpha();
|
||||
glm::u8vec3 color = getColor();
|
||||
glm::vec4 cubeColor(toGlm(color), alpha);
|
||||
|
||||
auto batch = args->_batch;
|
||||
if (batch) {
|
||||
Transform transform = getRenderTransform();
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto shapePipeline = args->_shapePipeline;
|
||||
if (!shapePipeline) {
|
||||
shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
}
|
||||
|
||||
if (_isSolid) {
|
||||
batch->setModelTransform(transform);
|
||||
geometryCache->renderSolidCubeInstance(args, *batch, cubeColor, shapePipeline);
|
||||
} else {
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
|
||||
if (getIsDashedLine()) {
|
||||
auto dimensions = transform.getScale();
|
||||
transform.setScale(1.0f);
|
||||
batch->setModelTransform(transform);
|
||||
|
||||
glm::vec3 halfDimensions = dimensions / 2.0f;
|
||||
glm::vec3 bottomLeftNear(-halfDimensions.x, -halfDimensions.y, -halfDimensions.z);
|
||||
glm::vec3 bottomRightNear(halfDimensions.x, -halfDimensions.y, -halfDimensions.z);
|
||||
glm::vec3 topLeftNear(-halfDimensions.x, halfDimensions.y, -halfDimensions.z);
|
||||
glm::vec3 topRightNear(halfDimensions.x, halfDimensions.y, -halfDimensions.z);
|
||||
|
||||
glm::vec3 bottomLeftFar(-halfDimensions.x, -halfDimensions.y, halfDimensions.z);
|
||||
glm::vec3 bottomRightFar(halfDimensions.x, -halfDimensions.y, halfDimensions.z);
|
||||
glm::vec3 topLeftFar(-halfDimensions.x, halfDimensions.y, halfDimensions.z);
|
||||
glm::vec3 topRightFar(halfDimensions.x, halfDimensions.y, halfDimensions.z);
|
||||
|
||||
geometryCache->renderDashedLine(*batch, bottomLeftNear, bottomRightNear, cubeColor, _geometryIds[0]);
|
||||
geometryCache->renderDashedLine(*batch, bottomRightNear, bottomRightFar, cubeColor, _geometryIds[1]);
|
||||
geometryCache->renderDashedLine(*batch, bottomRightFar, bottomLeftFar, cubeColor, _geometryIds[2]);
|
||||
geometryCache->renderDashedLine(*batch, bottomLeftFar, bottomLeftNear, cubeColor, _geometryIds[3]);
|
||||
|
||||
geometryCache->renderDashedLine(*batch, topLeftNear, topRightNear, cubeColor, _geometryIds[4]);
|
||||
geometryCache->renderDashedLine(*batch, topRightNear, topRightFar, cubeColor, _geometryIds[5]);
|
||||
geometryCache->renderDashedLine(*batch, topRightFar, topLeftFar, cubeColor, _geometryIds[6]);
|
||||
geometryCache->renderDashedLine(*batch, topLeftFar, topLeftNear, cubeColor, _geometryIds[7]);
|
||||
|
||||
geometryCache->renderDashedLine(*batch, bottomLeftNear, topLeftNear, cubeColor, _geometryIds[8]);
|
||||
geometryCache->renderDashedLine(*batch, bottomRightNear, topRightNear, cubeColor, _geometryIds[9]);
|
||||
geometryCache->renderDashedLine(*batch, bottomLeftFar, topLeftFar, cubeColor, _geometryIds[10]);
|
||||
geometryCache->renderDashedLine(*batch, bottomRightFar, topRightFar, cubeColor, _geometryIds[11]);
|
||||
|
||||
} else {
|
||||
batch->setModelTransform(transform);
|
||||
geometryCache->renderWireCubeInstance(args, *batch, cubeColor, shapePipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const render::ShapeKey Cube3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid()) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
Cube3DOverlay* Cube3DOverlay::createClone() const {
|
||||
return new Cube3DOverlay(this);
|
||||
}
|
||||
|
||||
void Cube3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Volume3DOverlay::setProperties(properties);
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>cube</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.CubeProperties
|
||||
*
|
||||
* @property {string} type=cube - Has the value <code>"cube"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
*/
|
||||
QVariant Cube3DOverlay::getProperty(const QString& property) {
|
||||
return Volume3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Transform Cube3DOverlay::evalRenderTransform() {
|
||||
// TODO: handle registration point??
|
||||
glm::vec3 position = getWorldPosition();
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
|
||||
Transform transform;
|
||||
transform.setScale(dimensions);
|
||||
transform.setTranslation(position);
|
||||
transform.setRotation(rotation);
|
||||
return transform;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase Cube3DOverlay::getScriptableModel() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto vertexColor = ColorUtils::toVec3(_color);
|
||||
scriptable::ScriptableModelBase result;
|
||||
if (auto mesh = geometryCache->meshFromShape(GeometryCache::Cube, vertexColor)) {
|
||||
result.objectID = Overlay::getID();
|
||||
result.append(mesh);
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
//
|
||||
// Cube3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Cube3DOverlay_h
|
||||
#define hifi_Cube3DOverlay_h
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
class Cube3DOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Cube3DOverlay();
|
||||
Cube3DOverlay(const Cube3DOverlay* cube3DOverlay);
|
||||
~Cube3DOverlay();
|
||||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
|
||||
virtual Cube3DOverlay* createClone() const override;
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
private:
|
||||
// edges on a cube
|
||||
std::array<int, 12> _geometryIds;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Cube3DOverlay_h
|
|
@ -1,200 +0,0 @@
|
|||
//
|
||||
// Grid3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Ryan Huffman on 11/06/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 "Grid3DOverlay.h"
|
||||
|
||||
#include <OctreeConstants.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <PathUtils.h>
|
||||
#include <ViewFrustum.h>
|
||||
|
||||
|
||||
QString const Grid3DOverlay::TYPE = "grid";
|
||||
const float DEFAULT_SCALE = 100.0f;
|
||||
|
||||
Grid3DOverlay::Grid3DOverlay() {
|
||||
setDimensions(DEFAULT_SCALE);
|
||||
updateGrid();
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
|
||||
Grid3DOverlay::Grid3DOverlay(const Grid3DOverlay* grid3DOverlay) :
|
||||
Planar3DOverlay(grid3DOverlay),
|
||||
_majorGridEvery(grid3DOverlay->_majorGridEvery),
|
||||
_minorGridEvery(grid3DOverlay->_minorGridEvery)
|
||||
{
|
||||
updateGrid();
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
|
||||
Grid3DOverlay::~Grid3DOverlay() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
geometryCache->releaseID(_geometryId);
|
||||
}
|
||||
}
|
||||
|
||||
AABox Grid3DOverlay::getBounds() const {
|
||||
if (_followCamera) {
|
||||
// This is a UI element that should always be in view, lie to the octree to avoid culling
|
||||
const AABox DOMAIN_BOX = AABox(glm::vec3(-TREE_SCALE / 2), TREE_SCALE);
|
||||
return DOMAIN_BOX;
|
||||
}
|
||||
return Planar3DOverlay::getBounds();
|
||||
}
|
||||
|
||||
void Grid3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
float alpha = getAlpha();
|
||||
glm::u8vec3 color = getColor();
|
||||
glm::vec4 gridColor(toGlm(color), alpha);
|
||||
|
||||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
auto minCorner = glm::vec2(-0.5f, -0.5f);
|
||||
auto maxCorner = glm::vec2(0.5f, 0.5f);
|
||||
|
||||
auto position = getWorldPosition();
|
||||
if (_followCamera) {
|
||||
// Get the camera position rounded to the nearest major grid line
|
||||
// This grid is for UI and should lie on worldlines
|
||||
auto cameraPosition =
|
||||
(float)_majorGridEvery * glm::round(args->getViewFrustum().getPosition() / (float)_majorGridEvery);
|
||||
|
||||
position += glm::vec3(cameraPosition.x, 0.0f, cameraPosition.z);
|
||||
}
|
||||
|
||||
Transform transform = getRenderTransform();
|
||||
transform.setTranslation(position);
|
||||
batch->setModelTransform(transform);
|
||||
const float MINOR_GRID_EDGE = 0.0025f;
|
||||
const float MAJOR_GRID_EDGE = 0.005f;
|
||||
DependencyManager::get<GeometryCache>()->renderGrid(*batch, minCorner, maxCorner,
|
||||
_minorGridRowDivisions, _minorGridColDivisions, MINOR_GRID_EDGE,
|
||||
_majorGridRowDivisions, _majorGridColDivisions, MAJOR_GRID_EDGE,
|
||||
gridColor, _geometryId);
|
||||
}
|
||||
}
|
||||
|
||||
const render::ShapeKey Grid3DOverlay::getShapeKey() {
|
||||
return render::ShapeKey::Builder().withOwnPipeline().withUnlit().withDepthBias();
|
||||
}
|
||||
|
||||
void Grid3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
if (properties["followCamera"].isValid()) {
|
||||
_followCamera = properties["followCamera"].toBool();
|
||||
}
|
||||
|
||||
if (properties["majorGridEvery"].isValid()) {
|
||||
_majorGridEvery = properties["majorGridEvery"].toInt();
|
||||
}
|
||||
|
||||
if (properties["minorGridEvery"].isValid()) {
|
||||
_minorGridEvery = properties["minorGridEvery"].toFloat();
|
||||
}
|
||||
|
||||
updateGrid();
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>grid</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.GridProperties
|
||||
*
|
||||
* @property {string} type=grid - Has the value <code>"grid"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
*
|
||||
* @property {boolean} followCamera=true - If <code>true</code>, the grid is always visible even as the camera moves to another
|
||||
* position.
|
||||
* @property {number} majorGridEvery=5 - Integer number of <code>minorGridEvery</code> intervals at which to draw a thick grid
|
||||
* line. Minimum value = <code>1</code>.
|
||||
* @property {number} minorGridEvery=1 - Real number of meters at which to draw thin grid lines. Minimum value =
|
||||
* <code>0.001</code>.
|
||||
*/
|
||||
QVariant Grid3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "followCamera") {
|
||||
return _followCamera;
|
||||
}
|
||||
if (property == "majorGridEvery") {
|
||||
return _majorGridEvery;
|
||||
}
|
||||
if (property == "minorGridEvery") {
|
||||
return _minorGridEvery;
|
||||
}
|
||||
|
||||
return Planar3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Grid3DOverlay* Grid3DOverlay::createClone() const {
|
||||
return new Grid3DOverlay(this);
|
||||
}
|
||||
|
||||
void Grid3DOverlay::updateGrid() {
|
||||
const int MAJOR_GRID_EVERY_MIN = 1;
|
||||
const float MINOR_GRID_EVERY_MIN = 0.01f;
|
||||
|
||||
_majorGridEvery = std::max(_majorGridEvery, MAJOR_GRID_EVERY_MIN);
|
||||
_minorGridEvery = std::max(_minorGridEvery, MINOR_GRID_EVERY_MIN);
|
||||
|
||||
_majorGridRowDivisions = getDimensions().x / _majorGridEvery;
|
||||
_majorGridColDivisions = getDimensions().y / _majorGridEvery;
|
||||
|
||||
_minorGridRowDivisions = getDimensions().x / _minorGridEvery;
|
||||
_minorGridColDivisions = getDimensions().y / _minorGridEvery;
|
||||
}
|
||||
|
||||
Transform Grid3DOverlay::evalRenderTransform() {
|
||||
Transform transform;
|
||||
transform.setRotation(getWorldOrientation());
|
||||
transform.setScale(glm::vec3(getDimensions(), 1.0f));
|
||||
return transform;
|
||||
}
|
|
@ -1,61 +0,0 @@
|
|||
//
|
||||
// Grid3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Ryan Huffman on 11/06/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_Grid3DOverlay_h
|
||||
#define hifi_Grid3DOverlay_h
|
||||
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class Grid3DOverlay : public Planar3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Grid3DOverlay();
|
||||
Grid3DOverlay(const Grid3DOverlay* grid3DOverlay);
|
||||
~Grid3DOverlay();
|
||||
|
||||
virtual AABox getBounds() const override;
|
||||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual Grid3DOverlay* createClone() const override;
|
||||
|
||||
// Grids are UI tools, and may not be intersected (pickable)
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance, BoxFace& face,
|
||||
glm::vec3& surfaceNormal, bool precisionPicking = false) override { return false; }
|
||||
virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override { return false; }
|
||||
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
private:
|
||||
void updateGrid();
|
||||
|
||||
bool _followCamera { true };
|
||||
|
||||
int _majorGridEvery { 5 };
|
||||
float _majorGridRowDivisions;
|
||||
float _majorGridColDivisions;
|
||||
|
||||
float _minorGridEvery { 1.0f };
|
||||
float _minorGridRowDivisions;
|
||||
float _minorGridColDivisions;
|
||||
int _geometryId { 0 };
|
||||
};
|
||||
|
||||
#endif // hifi_Grid3DOverlay_h
|
|
@ -1,341 +0,0 @@
|
|||
//
|
||||
// Image3DOverlay.cpp
|
||||
//
|
||||
//
|
||||
// Created by Clement on 7/1/14.
|
||||
// Modified and renamed by Zander Otavka on 8/4/15
|
||||
// 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 "Image3DOverlay.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "GeometryUtil.h"
|
||||
|
||||
#include "AbstractViewStateInterface.h"
|
||||
|
||||
QString const Image3DOverlay::TYPE = "image3d";
|
||||
|
||||
Image3DOverlay::Image3DOverlay() {
|
||||
_isLoaded = false;
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
|
||||
Image3DOverlay::Image3DOverlay(const Image3DOverlay* image3DOverlay) :
|
||||
Billboard3DOverlay(image3DOverlay),
|
||||
_url(image3DOverlay->_url),
|
||||
_texture(image3DOverlay->_texture),
|
||||
_emissive(image3DOverlay->_emissive),
|
||||
_fromImage(image3DOverlay->_fromImage)
|
||||
{
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
|
||||
Image3DOverlay::~Image3DOverlay() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
geometryCache->releaseID(_geometryId);
|
||||
}
|
||||
}
|
||||
|
||||
void Image3DOverlay::update(float deltatime) {
|
||||
if (!_isLoaded) {
|
||||
_isLoaded = true;
|
||||
_texture = DependencyManager::get<TextureCache>()->getTexture(_url);
|
||||
_textureIsLoaded = false;
|
||||
}
|
||||
Parent::update(deltatime);
|
||||
}
|
||||
|
||||
void Image3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible || !getParentVisible() || !_texture || !_texture->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Once the texture has loaded, check if we need to update the render item because of transparency
|
||||
if (!_textureIsLoaded && _texture && _texture->getGPUTexture()) {
|
||||
_textureIsLoaded = true;
|
||||
bool prevAlphaTexture = _alphaTexture;
|
||||
_alphaTexture = _texture->getGPUTexture()->getUsage().isAlpha();
|
||||
if (_alphaTexture != prevAlphaTexture) {
|
||||
auto itemID = getRenderItemID();
|
||||
if (render::Item::isValidID(itemID)) {
|
||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
transaction.updateItem(itemID);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch* batch = args->_batch;
|
||||
|
||||
float imageWidth = _texture->getWidth();
|
||||
float imageHeight = _texture->getHeight();
|
||||
|
||||
QRect fromImage;
|
||||
if (_fromImage.width() <= 0) {
|
||||
fromImage.setX(0);
|
||||
fromImage.setWidth(imageWidth);
|
||||
} else {
|
||||
float scaleX = imageWidth / _texture->getOriginalWidth();
|
||||
fromImage.setX(scaleX * _fromImage.x());
|
||||
fromImage.setWidth(scaleX * _fromImage.width());
|
||||
}
|
||||
|
||||
if (_fromImage.height() <= 0) {
|
||||
fromImage.setY(0);
|
||||
fromImage.setHeight(imageHeight);
|
||||
} else {
|
||||
float scaleY = imageHeight / _texture->getOriginalHeight();
|
||||
fromImage.setY(scaleY * _fromImage.y());
|
||||
fromImage.setHeight(scaleY * _fromImage.height());
|
||||
}
|
||||
|
||||
float maxSize = glm::max(fromImage.width(), fromImage.height());
|
||||
float x = _keepAspectRatio ? fromImage.width() / (2.0f * maxSize) : 0.5f;
|
||||
float y = _keepAspectRatio ? -fromImage.height() / (2.0f * maxSize) : -0.5f;
|
||||
|
||||
glm::vec2 topLeft(-x, -y);
|
||||
glm::vec2 bottomRight(x, y);
|
||||
glm::vec2 texCoordTopLeft((fromImage.x() + 0.5f) / imageWidth, (fromImage.y() + 0.5f) / imageHeight);
|
||||
glm::vec2 texCoordBottomRight((fromImage.x() + fromImage.width() - 0.5f) / imageWidth,
|
||||
(fromImage.y() + fromImage.height() - 0.5f) / imageHeight);
|
||||
|
||||
float alpha = getAlpha();
|
||||
glm::u8vec3 color = getColor();
|
||||
glm::vec4 imageColor(toGlm(color), alpha);
|
||||
|
||||
batch->setModelTransform(getRenderTransform());
|
||||
batch->setResourceTexture(0, _texture->getGPUTexture());
|
||||
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(
|
||||
*batch, topLeft, bottomRight, texCoordTopLeft, texCoordBottomRight,
|
||||
imageColor, _geometryId
|
||||
);
|
||||
|
||||
batch->setResourceTexture(0, nullptr); // restore default white color after me
|
||||
}
|
||||
|
||||
const render::ShapeKey Image3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias();
|
||||
if (_emissive) {
|
||||
builder.withUnlit();
|
||||
}
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
void Image3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Billboard3DOverlay::setProperties(properties);
|
||||
|
||||
auto urlValue = properties["url"];
|
||||
if (urlValue.isValid()) {
|
||||
QString newURL = urlValue.toString();
|
||||
if (newURL != _url) {
|
||||
setURL(newURL);
|
||||
}
|
||||
}
|
||||
|
||||
auto subImageBoundsVar = properties["subImage"];
|
||||
if (subImageBoundsVar.isValid()) {
|
||||
if (subImageBoundsVar.isNull()) {
|
||||
_fromImage = QRect();
|
||||
} else {
|
||||
QRect oldSubImageRect = _fromImage;
|
||||
QRect subImageRect = _fromImage;
|
||||
auto subImageBounds = subImageBoundsVar.toMap();
|
||||
if (subImageBounds["x"].isValid()) {
|
||||
subImageRect.setX(subImageBounds["x"].toInt());
|
||||
} else {
|
||||
subImageRect.setX(oldSubImageRect.x());
|
||||
}
|
||||
if (subImageBounds["y"].isValid()) {
|
||||
subImageRect.setY(subImageBounds["y"].toInt());
|
||||
} else {
|
||||
subImageRect.setY(oldSubImageRect.y());
|
||||
}
|
||||
if (subImageBounds["width"].isValid()) {
|
||||
subImageRect.setWidth(subImageBounds["width"].toInt());
|
||||
} else {
|
||||
subImageRect.setWidth(oldSubImageRect.width());
|
||||
}
|
||||
if (subImageBounds["height"].isValid()) {
|
||||
subImageRect.setHeight(subImageBounds["height"].toInt());
|
||||
} else {
|
||||
subImageRect.setHeight(oldSubImageRect.height());
|
||||
}
|
||||
setClipFromSource(subImageRect);
|
||||
}
|
||||
}
|
||||
|
||||
auto keepAspectRatioValue = properties["keepAspectRatio"];
|
||||
if (keepAspectRatioValue.isValid()) {
|
||||
_keepAspectRatio = keepAspectRatioValue.toBool();
|
||||
}
|
||||
|
||||
auto emissiveValue = properties["emissive"];
|
||||
if (emissiveValue.isValid()) {
|
||||
_emissive = emissiveValue.toBool();
|
||||
}
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* These are the properties of an <code>image3d</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.Image3DProperties
|
||||
*
|
||||
* @property {string} type=image3d - Has the value <code>"image3d"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
*
|
||||
* @property {bool} keepAspectRatio=true - overlays will maintain the aspect ratio when the subImage is applied.
|
||||
*
|
||||
* @property {boolean} isFacingAvatar - If <code>true</code>, the overlay is rotated to face the user's camera about an axis
|
||||
* parallel to the user's avatar's "up" direction.
|
||||
*
|
||||
* @property {string} url - The URL of the PNG or JPG image to display.
|
||||
* @property {Rect} subImage - The portion of the image to display. Defaults to the full image.
|
||||
* @property {boolean} emissive - If <code>true</code>, the overlay is displayed at full brightness, otherwise it is rendered
|
||||
* with scene lighting.
|
||||
*/
|
||||
QVariant Image3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "url") {
|
||||
return _url;
|
||||
}
|
||||
if (property == "subImage") {
|
||||
return _fromImage;
|
||||
}
|
||||
if (property == "emissive") {
|
||||
return _emissive;
|
||||
}
|
||||
if (property == "keepAspectRatio") {
|
||||
return _keepAspectRatio;
|
||||
}
|
||||
|
||||
return Billboard3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
void Image3DOverlay::setURL(const QString& url) {
|
||||
_url = url;
|
||||
_isLoaded = false;
|
||||
}
|
||||
|
||||
bool Image3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
if (_texture && _texture->isLoaded()) {
|
||||
Transform transform = getTransform();
|
||||
|
||||
// Produce the dimensions of the overlay based on the image's aspect ratio and the overlay's scale.
|
||||
bool isNull = _fromImage.isNull();
|
||||
float width = isNull ? _texture->getWidth() : _fromImage.width();
|
||||
float height = isNull ? _texture->getHeight() : _fromImage.height();
|
||||
float maxSize = glm::max(width, height);
|
||||
glm::vec2 dimensions = _dimensions * glm::vec2(width / maxSize, height / maxSize);
|
||||
glm::quat rotation = transform.getRotation();
|
||||
|
||||
if (findRayRectangleIntersection(origin, direction, rotation, transform.getTranslation(), dimensions, distance)) {
|
||||
glm::vec3 forward = rotation * Vectors::FRONT;
|
||||
if (glm::dot(forward, direction) > 0.0f) {
|
||||
face = MAX_Z_FACE;
|
||||
surfaceNormal = -forward;
|
||||
} else {
|
||||
face = MIN_Z_FACE;
|
||||
surfaceNormal = forward;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Image3DOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
if (_texture && _texture->isLoaded()) {
|
||||
Transform transform = getTransform();
|
||||
|
||||
// Produce the dimensions of the overlay based on the image's aspect ratio and the overlay's scale.
|
||||
bool isNull = _fromImage.isNull();
|
||||
float width = isNull ? _texture->getWidth() : _fromImage.width();
|
||||
float height = isNull ? _texture->getHeight() : _fromImage.height();
|
||||
float maxSize = glm::max(width, height);
|
||||
glm::vec2 dimensions = _dimensions * glm::vec2(width / maxSize, height / maxSize);
|
||||
glm::quat rotation = transform.getRotation();
|
||||
glm::vec3 position = getWorldPosition();
|
||||
|
||||
glm::quat inverseRot = glm::inverse(rotation);
|
||||
glm::vec3 localOrigin = inverseRot * (origin - position);
|
||||
glm::vec3 localVelocity = inverseRot * velocity;
|
||||
glm::vec3 localAcceleration = inverseRot * acceleration;
|
||||
|
||||
if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, dimensions, parabolicDistance)) {
|
||||
float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance;
|
||||
glm::vec3 forward = rotation * Vectors::FRONT;
|
||||
if (localIntersectionVelocityZ > 0.0f) {
|
||||
face = MIN_Z_FACE;
|
||||
surfaceNormal = forward;
|
||||
} else {
|
||||
face = MAX_Z_FACE;
|
||||
surfaceNormal = -forward;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Image3DOverlay* Image3DOverlay::createClone() const {
|
||||
return new Image3DOverlay(this);
|
||||
}
|
||||
|
||||
Transform Image3DOverlay::evalRenderTransform() {
|
||||
auto transform = Parent::evalRenderTransform();
|
||||
transform.postScale(glm::vec3(getDimensions(), 1.0f));
|
||||
return transform;
|
||||
}
|
|
@ -1,67 +0,0 @@
|
|||
//
|
||||
// Image3DOverlay.h
|
||||
//
|
||||
//
|
||||
// Created by Clement on 7/1/14.
|
||||
// Modified and renamed by Zander Otavka on 8/4/15
|
||||
// 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_Image3DOverlay_h
|
||||
#define hifi_Image3DOverlay_h
|
||||
|
||||
#include <TextureCache.h>
|
||||
|
||||
#include "Billboard3DOverlay.h"
|
||||
|
||||
class Image3DOverlay : public Billboard3DOverlay {
|
||||
Q_OBJECT
|
||||
using Parent = Billboard3DOverlay;
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Image3DOverlay();
|
||||
Image3DOverlay(const Image3DOverlay* image3DOverlay);
|
||||
~Image3DOverlay();
|
||||
virtual void render(RenderArgs* args) override;
|
||||
|
||||
virtual void update(float deltatime) override;
|
||||
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
|
||||
// setters
|
||||
void setURL(const QString& url);
|
||||
void setClipFromSource(const QRect& bounds) { _fromImage = bounds; }
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
bool isTransparent() override { return Base3DOverlay::isTransparent() || _alphaTexture; }
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
|
||||
virtual Image3DOverlay* createClone() const override;
|
||||
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
private:
|
||||
QString _url;
|
||||
NetworkTexturePointer _texture;
|
||||
bool _textureIsLoaded { false };
|
||||
bool _alphaTexture { false };
|
||||
bool _emissive { false };
|
||||
bool _keepAspectRatio { true };
|
||||
|
||||
QRect _fromImage; // where from in the image to sample
|
||||
int _geometryId { 0 };
|
||||
};
|
||||
|
||||
#endif // hifi_Image3DOverlay_h
|
|
@ -19,29 +19,6 @@
|
|||
QString const ImageOverlay::TYPE = "image";
|
||||
QUrl const ImageOverlay::URL(QString("hifi/overlays/ImageOverlay.qml"));
|
||||
|
||||
// ImageOverlay's properties are defined in the QML file specified above.
|
||||
/**jsdoc
|
||||
* These are the properties of an <code>image</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.ImageProperties
|
||||
*
|
||||
* @property {Rect} bounds - The position and size of the image display area, in pixels. <em>Write-only.</em>
|
||||
* @property {number} x - Integer left, x-coordinate value of the image display area = <code>bounds.x</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} y - Integer top, y-coordinate value of the image display area = <code>bounds.y</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} width - Integer width of the image display area = <code>bounds.width</code>. <em>Write-only.</em>
|
||||
* @property {number} height - Integer height of the image display area = <code>bounds.height</code>. <em>Write-only.</em>
|
||||
* @property {string} imageURL - The URL of the image file to display. The image is scaled to fit to the <code>bounds</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {Vec2} subImage=0,0 - Integer coordinates of the top left pixel to start using image content from.
|
||||
* <em>Write-only.</em>
|
||||
* @property {Color} color=0,0,0 - The color to apply over the top of the image to colorize it. <em>Write-only.</em>
|
||||
* @property {number} alpha=0.0 - The opacity of the color applied over the top of the image, <code>0.0</code> -
|
||||
* <code>1.0</code>. <em>Write-only.</em>
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* <em>Write-only.</em>
|
||||
*/
|
||||
|
||||
ImageOverlay::ImageOverlay()
|
||||
: QmlOverlay(URL) { }
|
||||
|
||||
|
@ -50,5 +27,4 @@ ImageOverlay::ImageOverlay(const ImageOverlay* imageOverlay) :
|
|||
|
||||
ImageOverlay* ImageOverlay::createClone() const {
|
||||
return new ImageOverlay(this);
|
||||
}
|
||||
|
||||
}
|
|
@ -1,366 +0,0 @@
|
|||
//
|
||||
// Line3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 "Line3DOverlay.h"
|
||||
|
||||
#include <GeometryCache.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
#include "AbstractViewStateInterface.h"
|
||||
|
||||
QString const Line3DOverlay::TYPE = "line3d";
|
||||
|
||||
Line3DOverlay::Line3DOverlay() :
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
}
|
||||
|
||||
Line3DOverlay::Line3DOverlay(const Line3DOverlay* line3DOverlay) :
|
||||
Base3DOverlay(line3DOverlay),
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
setParentID(line3DOverlay->getParentID());
|
||||
setParentJointIndex(line3DOverlay->getParentJointIndex());
|
||||
setLocalTransform(line3DOverlay->getLocalTransform());
|
||||
_direction = line3DOverlay->getDirection();
|
||||
_length = line3DOverlay->getLength();
|
||||
_endParentID = line3DOverlay->getEndParentID();
|
||||
_endParentJointIndex = line3DOverlay->getEndJointIndex();
|
||||
_lineWidth = line3DOverlay->getLineWidth();
|
||||
_glow = line3DOverlay->getGlow();
|
||||
}
|
||||
|
||||
Line3DOverlay::~Line3DOverlay() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (_geometryCacheID && geometryCache) {
|
||||
geometryCache->releaseID(_geometryCacheID);
|
||||
}
|
||||
}
|
||||
|
||||
glm::vec3 Line3DOverlay::getStart() const {
|
||||
return getWorldPosition();
|
||||
}
|
||||
|
||||
glm::vec3 Line3DOverlay::getEnd() const {
|
||||
bool success;
|
||||
glm::vec3 localEnd;
|
||||
glm::vec3 worldEnd;
|
||||
|
||||
if (_endParentID != QUuid()) {
|
||||
glm::vec3 localOffset = _direction * _length;
|
||||
bool success;
|
||||
worldEnd = localToWorld(localOffset, _endParentID, _endParentJointIndex, getScalesWithParent(), success);
|
||||
return worldEnd;
|
||||
}
|
||||
|
||||
localEnd = getLocalEnd();
|
||||
worldEnd = localToWorld(localEnd, getParentID(), getParentJointIndex(), getScalesWithParent(), success);
|
||||
if (!success) {
|
||||
qDebug() << "Line3DOverlay::getEnd failed, parentID = " << getParentID();
|
||||
}
|
||||
return worldEnd;
|
||||
}
|
||||
|
||||
void Line3DOverlay::setStart(const glm::vec3& start) {
|
||||
setWorldPosition(start);
|
||||
}
|
||||
|
||||
void Line3DOverlay::setEnd(const glm::vec3& end) {
|
||||
bool success;
|
||||
glm::vec3 localStart;
|
||||
glm::vec3 localEnd;
|
||||
glm::vec3 offset;
|
||||
|
||||
if (_endParentID != QUuid()) {
|
||||
offset = worldToLocal(end, _endParentID, _endParentJointIndex, getScalesWithParent(), success);
|
||||
} else {
|
||||
localStart = getLocalStart();
|
||||
localEnd = worldToLocal(end, getParentID(), getParentJointIndex(), getScalesWithParent(), success);
|
||||
offset = localEnd - localStart;
|
||||
}
|
||||
if (!success) {
|
||||
qDebug() << "Line3DOverlay::setEnd failed";
|
||||
return;
|
||||
}
|
||||
|
||||
_length = glm::length(offset);
|
||||
if (_length > 0.0f) {
|
||||
_direction = glm::normalize(offset);
|
||||
} else {
|
||||
_direction = glm::vec3(0.0f);
|
||||
}
|
||||
notifyRenderVariableChange();
|
||||
}
|
||||
|
||||
void Line3DOverlay::setLocalEnd(const glm::vec3& localEnd) {
|
||||
glm::vec3 offset;
|
||||
if (_endParentID != QUuid()) {
|
||||
offset = localEnd;
|
||||
} else {
|
||||
glm::vec3 localStart = getLocalStart();
|
||||
offset = localEnd - localStart;
|
||||
}
|
||||
_length = glm::length(offset);
|
||||
if (_length > 0.0f) {
|
||||
_direction = glm::normalize(offset);
|
||||
} else {
|
||||
_direction = glm::vec3(0.0f);
|
||||
}
|
||||
}
|
||||
|
||||
AABox Line3DOverlay::getBounds() const {
|
||||
auto extents = Extents{};
|
||||
extents.addPoint(getStart());
|
||||
extents.addPoint(getEnd());
|
||||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Line3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
float alpha = getAlpha();
|
||||
glm::u8vec3 color = getColor();
|
||||
glm::vec4 colorv4(toGlm(color), alpha);
|
||||
auto batch = args->_batch;
|
||||
if (batch) {
|
||||
batch->setModelTransform(Transform());
|
||||
auto& renderTransform = getRenderTransform();
|
||||
glm::vec3 start = renderTransform.getTranslation();
|
||||
glm::vec3 end = renderTransform.transform(vec3(0.0, 0.0, -1.0));
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (getIsDashedLine()) {
|
||||
// TODO: add support for color to renderDashedLine()
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
|
||||
geometryCache->renderDashedLine(*batch, start, end, colorv4, _geometryCacheID);
|
||||
} else {
|
||||
// renderGlowLine handles both glow = 0 and glow > 0 cases
|
||||
geometryCache->renderGlowLine(*batch, start, end, colorv4, _glow, _lineWidth, _geometryCacheID);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const render::ShapeKey Line3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
void Line3DOverlay::setProperties(const QVariantMap& originalProperties) {
|
||||
QVariantMap properties = originalProperties;
|
||||
glm::vec3 newStart(0.0f);
|
||||
bool newStartSet { false };
|
||||
glm::vec3 newEnd(0.0f);
|
||||
bool newEndSet { false };
|
||||
|
||||
auto start = properties["start"];
|
||||
// If "start" property was not there, check to see if they included aliases: startPoint, p1
|
||||
if (!start.isValid()) {
|
||||
start = properties["startPoint"];
|
||||
}
|
||||
if (!start.isValid()) {
|
||||
start = properties["p1"];
|
||||
}
|
||||
if (start.isValid()) {
|
||||
newStart = vec3FromVariant(start);
|
||||
newStartSet = true;
|
||||
}
|
||||
properties.remove("start"); // so that Base3DOverlay doesn't respond to it
|
||||
properties.remove("startPoint");
|
||||
properties.remove("p1");
|
||||
|
||||
auto end = properties["end"];
|
||||
// If "end" property was not there, check to see if they included aliases: endPoint, p2
|
||||
if (!end.isValid()) {
|
||||
end = properties["endPoint"];
|
||||
}
|
||||
if (!end.isValid()) {
|
||||
end = properties["p2"];
|
||||
}
|
||||
if (end.isValid()) {
|
||||
newEnd = vec3FromVariant(end);
|
||||
newEndSet = true;
|
||||
}
|
||||
properties.remove("end"); // so that Base3DOverlay doesn't respond to it
|
||||
properties.remove("endPoint");
|
||||
properties.remove("p2");
|
||||
|
||||
auto length = properties["length"];
|
||||
if (length.isValid()) {
|
||||
_length = length.toFloat();
|
||||
}
|
||||
|
||||
Base3DOverlay::setProperties(properties);
|
||||
|
||||
auto endParentIDProp = properties["endParentID"];
|
||||
if (endParentIDProp.isValid()) {
|
||||
_endParentID = QUuid(endParentIDProp.toString());
|
||||
}
|
||||
auto endParentJointIndexProp = properties["endParentJointIndex"];
|
||||
if (endParentJointIndexProp.isValid()) {
|
||||
_endParentJointIndex = endParentJointIndexProp.toInt();
|
||||
}
|
||||
|
||||
auto localStart = properties["localStart"];
|
||||
if (localStart.isValid()) {
|
||||
glm::vec3 tmpLocalEnd = getLocalEnd();
|
||||
setLocalStart(vec3FromVariant(localStart));
|
||||
setLocalEnd(tmpLocalEnd);
|
||||
}
|
||||
|
||||
auto localEnd = properties["localEnd"];
|
||||
if (localEnd.isValid()) {
|
||||
setLocalEnd(vec3FromVariant(localEnd));
|
||||
}
|
||||
|
||||
// these are saved until after Base3DOverlay::setProperties so parenting infomation can be set, first
|
||||
if (newStartSet) {
|
||||
setStart(newStart);
|
||||
}
|
||||
if (newEndSet) {
|
||||
setEnd(newEnd);
|
||||
}
|
||||
|
||||
auto glow = properties["glow"];
|
||||
if (glow.isValid()) {
|
||||
float prevGlow = _glow;
|
||||
setGlow(glow.toFloat());
|
||||
// Update our payload key if necessary to handle transparency
|
||||
if ((prevGlow <= 0.0f && _glow > 0.0f) || (prevGlow > 0.0f && _glow <= 0.0f)) {
|
||||
auto itemID = getRenderItemID();
|
||||
if (render::Item::isValidID(itemID)) {
|
||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
transaction.updateItem(itemID);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto lineWidth = properties["lineWidth"];
|
||||
if (lineWidth.isValid()) {
|
||||
setLineWidth(lineWidth.toFloat());
|
||||
}
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>line3d</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.Line3DProperties
|
||||
*
|
||||
* @property {string} type=line3d - Has the value <code>"line3d"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Uuid} endParentID=null - The avatar, entity, or overlay that the end point of the line is parented to.
|
||||
* @property {number} endParentJointIndex=65535 - Integer value specifying the skeleton joint that the end point of the line is
|
||||
* attached to if <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
* @property {Vec3} start - The start point of the line. Synonyms: <code>startPoint</code>, <code>p1</code>, and
|
||||
* <code>position</code>.
|
||||
* @property {Vec3} end - The end point of the line. Synonyms: <code>endPoint</code> and <code>p2</code>.
|
||||
* @property {Vec3} localStart - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>start</code>. Synonym: <code>localPosition</code>.
|
||||
* @property {Vec3} localEnd - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>endParentID</code> set, otherwise the same value as <code>end</code>.
|
||||
* @property {number} length - The length of the line, in meters. This can be set after creating a line with start and end
|
||||
* points.
|
||||
* @property {number} glow=0 - If <code>glow > 0</code>, the line is rendered with a glow.
|
||||
* @property {number} lineWidth=0.02 - If <code>glow > 0</code>, this is the width of the glow, in meters.
|
||||
*/
|
||||
QVariant Line3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "start" || property == "startPoint" || property == "p1") {
|
||||
return vec3toVariant(getStart());
|
||||
}
|
||||
if (property == "end" || property == "endPoint" || property == "p2") {
|
||||
return vec3toVariant(getEnd());
|
||||
}
|
||||
if (property == "length") {
|
||||
return QVariant(getLength());
|
||||
}
|
||||
if (property == "endParentID") {
|
||||
return _endParentID;
|
||||
}
|
||||
if (property == "endParentJointIndex") {
|
||||
return _endParentJointIndex;
|
||||
}
|
||||
if (property == "localStart") {
|
||||
return vec3toVariant(getLocalStart());
|
||||
}
|
||||
if (property == "localEnd") {
|
||||
return vec3toVariant(getLocalEnd());
|
||||
}
|
||||
if (property == "glow") {
|
||||
return getGlow();
|
||||
}
|
||||
if (property == "lineWidth") {
|
||||
return _lineWidth;
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Line3DOverlay* Line3DOverlay::createClone() const {
|
||||
return new Line3DOverlay(this);
|
||||
}
|
||||
|
||||
Transform Line3DOverlay::evalRenderTransform() {
|
||||
// Capture start and endin the renderTransform:
|
||||
// start is the origin
|
||||
// end is at the tip of the front axis aka -Z
|
||||
Transform transform;
|
||||
transform.setTranslation( getStart());
|
||||
auto endPos = getEnd();
|
||||
|
||||
auto vec = endPos - transform.getTranslation();
|
||||
const float MIN_LINE_LENGTH = 0.0001f;
|
||||
auto scale = glm::max(glm::length(vec), MIN_LINE_LENGTH);
|
||||
auto dir = vec / scale;
|
||||
auto orientation = glm::rotation(glm::vec3(0.0f, 0.0f, -1.0f), dir);
|
||||
transform.setRotation(orientation);
|
||||
transform.setScale(scale);
|
||||
|
||||
return transform;
|
||||
}
|
|
@ -1,79 +0,0 @@
|
|||
//
|
||||
// Line3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Line3DOverlay_h
|
||||
#define hifi_Line3DOverlay_h
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
class Line3DOverlay : public Base3DOverlay {
|
||||
Q_OBJECT
|
||||
using Parent = Base3DOverlay;
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Line3DOverlay();
|
||||
Line3DOverlay(const Line3DOverlay* line3DOverlay);
|
||||
~Line3DOverlay();
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
virtual AABox getBounds() const override;
|
||||
|
||||
// getters
|
||||
glm::vec3 getStart() const;
|
||||
glm::vec3 getEnd() const;
|
||||
const float& getLineWidth() const { return _lineWidth; }
|
||||
const float& getGlow() const { return _glow; }
|
||||
|
||||
// setters
|
||||
void setStart(const glm::vec3& start);
|
||||
void setEnd(const glm::vec3& end);
|
||||
|
||||
void setLocalStart(const glm::vec3& localStart) { setLocalPosition(localStart); }
|
||||
void setLocalEnd(const glm::vec3& localEnd);
|
||||
|
||||
void setLineWidth(const float& lineWidth) { _lineWidth = lineWidth; }
|
||||
void setGlow(const float& glow) { _glow = glow; }
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
bool isTransparent() override { return Base3DOverlay::isTransparent() || _glow > 0.0f; }
|
||||
|
||||
virtual Line3DOverlay* createClone() const override;
|
||||
|
||||
glm::vec3 getDirection() const { return _direction; }
|
||||
float getLength() const { return _length; }
|
||||
glm::vec3 getLocalStart() const { return getLocalPosition(); }
|
||||
glm::vec3 getLocalEnd() const { return getLocalStart() + _direction * _length; }
|
||||
QUuid getEndParentID() const { return _endParentID; }
|
||||
quint16 getEndJointIndex() const { return _endParentJointIndex; }
|
||||
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
private:
|
||||
QUuid _endParentID;
|
||||
quint16 _endParentJointIndex { INVALID_JOINT_INDEX };
|
||||
|
||||
// _direction and _length are in the parent's frame. If _endParentID is set, they are
|
||||
// relative to that. Otherwise, they are relative to the local-start-position (which is the
|
||||
// same as localPosition)
|
||||
glm::vec3 _direction; // in parent frame
|
||||
float _length { 1.0 }; // in parent frame
|
||||
|
||||
const float DEFAULT_LINE_WIDTH = 0.02f;
|
||||
float _lineWidth { DEFAULT_LINE_WIDTH };
|
||||
float _glow { 0.0 };
|
||||
int _geometryCacheID;
|
||||
};
|
||||
|
||||
#endif // hifi_Line3DOverlay_h
|
|
@ -1,735 +0,0 @@
|
|||
//
|
||||
// ModelOverlay.cpp
|
||||
//
|
||||
//
|
||||
// Created by Clement on 6/30/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 "ModelOverlay.h"
|
||||
|
||||
#include <glm/gtx/quaternion.hpp>
|
||||
#include <glm/gtx/transform.hpp>
|
||||
|
||||
#include <Rig.h>
|
||||
|
||||
#include "Application.h"
|
||||
|
||||
|
||||
QString const ModelOverlay::TYPE = "model";
|
||||
|
||||
ModelOverlay::ModelOverlay()
|
||||
: _model(std::make_shared<Model>(nullptr, this)),
|
||||
_modelTextures(QVariantMap())
|
||||
{
|
||||
_model->setLoadingPriority(_loadPriority);
|
||||
_isLoaded = false;
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
_model->setVisibleInScene(false, scene);
|
||||
}
|
||||
|
||||
ModelOverlay::ModelOverlay(const ModelOverlay* modelOverlay) :
|
||||
Volume3DOverlay(modelOverlay),
|
||||
_model(std::make_shared<Model>(nullptr, this)),
|
||||
_modelTextures(QVariantMap()),
|
||||
_url(modelOverlay->_url),
|
||||
_updateModel(false),
|
||||
_scaleToFit(modelOverlay->_scaleToFit),
|
||||
_loadPriority(modelOverlay->_loadPriority),
|
||||
|
||||
_animationURL(modelOverlay->_animationURL),
|
||||
_animationFPS(modelOverlay->_animationFPS),
|
||||
_animationCurrentFrame(modelOverlay->_animationCurrentFrame),
|
||||
_animationRunning(modelOverlay->_animationRunning),
|
||||
_animationLoop(modelOverlay->_animationLoop),
|
||||
_animationFirstFrame(modelOverlay->_animationFirstFrame),
|
||||
_animationLastFrame(modelOverlay->_animationLastFrame),
|
||||
_animationHold(modelOverlay->_animationHold),
|
||||
_animationAllowTranslation(modelOverlay->_animationAllowTranslation)
|
||||
|
||||
// Joint translations and rotations aren't copied because the model needs to load before they can be applied.
|
||||
{
|
||||
_model->setLoadingPriority(_loadPriority);
|
||||
if (_url.isValid()) {
|
||||
_updateModel = true;
|
||||
_isLoaded = false;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::update(float deltatime) {
|
||||
Base3DOverlay::update(deltatime);
|
||||
|
||||
if (_updateModel) {
|
||||
_updateModel = false;
|
||||
_model->setSnapModelToCenter(true);
|
||||
Transform transform = evalRenderTransform();
|
||||
if (_scaleToFit) {
|
||||
_model->setScaleToFit(true, transform.getScale() * getDimensions());
|
||||
} else {
|
||||
_model->setScale(transform.getScale());
|
||||
}
|
||||
_model->setRotation(transform.getRotation());
|
||||
_model->setTranslation(transform.getTranslation());
|
||||
_model->setURL(_url);
|
||||
_model->simulate(deltatime, true);
|
||||
} else {
|
||||
_model->simulate(deltatime);
|
||||
}
|
||||
_isLoaded = _model->isActive();
|
||||
|
||||
if (isAnimatingSomething()) {
|
||||
if (!jointsMapped()) {
|
||||
mapAnimationJoints(_model->getJointNames());
|
||||
}
|
||||
animate();
|
||||
}
|
||||
|
||||
// check to see if when we added our model to the scene they were ready, if they were not ready, then
|
||||
// fix them up in the scene
|
||||
render::ScenePointer scene = qApp->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
if (_model->needsFixupInScene()) {
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(Overlay::getID(), NestableType::Overlay, _model);
|
||||
_model->removeFromScene(scene, transaction);
|
||||
_model->addToScene(scene, transaction);
|
||||
|
||||
auto newRenderItemIDs{ _model->fetchRenderItemIDs() };
|
||||
transaction.updateItem<Overlay>(getRenderItemID(), [newRenderItemIDs](Overlay& data) {
|
||||
auto modelOverlay = static_cast<ModelOverlay*>(&data);
|
||||
modelOverlay->setSubRenderItemIDs(newRenderItemIDs);
|
||||
});
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(Overlay::getID(), NestableType::Overlay, _model);
|
||||
}
|
||||
bool metaDirty = false;
|
||||
if (_visibleDirty && _texturesLoaded) {
|
||||
_visibleDirty = false;
|
||||
// don't show overlays in mirrors or spectator-cam unless _isVisibleInSecondaryCamera is true
|
||||
uint8_t modelRenderTagMask = (_isVisibleInSecondaryCamera ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW);
|
||||
|
||||
_model->setTagMask(modelRenderTagMask, scene);
|
||||
_model->setVisibleInScene(getVisible(), scene);
|
||||
metaDirty = true;
|
||||
}
|
||||
if (_renderLayerDirty) {
|
||||
_renderLayerDirty = false;
|
||||
_model->setHifiRenderLayer(_drawHUDLayer ? render::hifi::LAYER_3D_HUD : (_drawInFront ? render::hifi::LAYER_3D_FRONT : render::hifi::LAYER_3D), scene);
|
||||
metaDirty = true;
|
||||
}
|
||||
if (_groupCulledDirty) {
|
||||
_groupCulledDirty = false;
|
||||
_model->setGroupCulled(_isGroupCulled, scene);
|
||||
metaDirty = true;
|
||||
}
|
||||
if (metaDirty) {
|
||||
transaction.updateItem<Overlay>(getRenderItemID(), [](Overlay& data) {});
|
||||
}
|
||||
scene->enqueueTransaction(transaction);
|
||||
|
||||
if (_texturesDirty && !_modelTextures.isEmpty()) {
|
||||
_texturesDirty = false;
|
||||
_model->setTextures(_modelTextures);
|
||||
}
|
||||
|
||||
if (!_texturesLoaded && _model->getGeometry() && _model->getGeometry()->areTexturesLoaded()) {
|
||||
_texturesLoaded = true;
|
||||
|
||||
_model->setVisibleInScene(getVisible(), scene);
|
||||
_model->updateRenderItems();
|
||||
}
|
||||
}
|
||||
|
||||
bool ModelOverlay::addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
Volume3DOverlay::addToScene(overlay, scene, transaction);
|
||||
_model->addToScene(scene, transaction);
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelAddedToScene(Overlay::getID(), NestableType::Overlay, _model);
|
||||
return true;
|
||||
}
|
||||
|
||||
void ModelOverlay::removeFromScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
Volume3DOverlay::removeFromScene(overlay, scene, transaction);
|
||||
_model->removeFromScene(scene, transaction);
|
||||
emit DependencyManager::get<scriptable::ModelProviderFactory>()->modelRemovedFromScene(Overlay::getID(), NestableType::Overlay, _model);
|
||||
transaction.updateItem<Overlay>(getRenderItemID(), [](Overlay& data) {
|
||||
auto modelOverlay = static_cast<ModelOverlay*>(&data);
|
||||
modelOverlay->clearSubRenderItemIDs();
|
||||
});
|
||||
}
|
||||
|
||||
void ModelOverlay::setVisible(bool visible) {
|
||||
if (visible != getVisible()) {
|
||||
Overlay::setVisible(visible);
|
||||
_visibleDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::setDrawInFront(bool drawInFront) {
|
||||
if (drawInFront != getDrawInFront()) {
|
||||
Base3DOverlay::setDrawInFront(drawInFront);
|
||||
_renderLayerDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::setDrawHUDLayer(bool drawHUDLayer) {
|
||||
if (drawHUDLayer != getDrawHUDLayer()) {
|
||||
Base3DOverlay::setDrawHUDLayer(drawHUDLayer);
|
||||
_renderLayerDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::setGroupCulled(bool groupCulled) {
|
||||
if (groupCulled != _isGroupCulled) {
|
||||
_isGroupCulled = groupCulled;
|
||||
_groupCulledDirty = true;
|
||||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::setProperties(const QVariantMap& properties) {
|
||||
auto origPosition = getWorldPosition();
|
||||
auto origRotation = getWorldOrientation();
|
||||
auto origDimensions = getDimensions();
|
||||
auto origScale = getSNScale();
|
||||
|
||||
Base3DOverlay::setProperties(properties);
|
||||
|
||||
auto scale = properties["scale"];
|
||||
if (scale.isValid()) {
|
||||
setSNScale(vec3FromVariant(scale));
|
||||
}
|
||||
|
||||
auto dimensions = properties["dimensions"];
|
||||
if (!dimensions.isValid()) {
|
||||
dimensions = properties["size"];
|
||||
}
|
||||
if (dimensions.isValid()) {
|
||||
_scaleToFit = true;
|
||||
setDimensions(vec3FromVariant(dimensions));
|
||||
} else if (scale.isValid()) {
|
||||
// if "scale" property is set but "dimensions" is not.
|
||||
// do NOT scale to fit.
|
||||
_scaleToFit = false;
|
||||
}
|
||||
|
||||
if (origPosition != getWorldPosition() || origRotation != getWorldOrientation() || origDimensions != getDimensions() || origScale != getSNScale()) {
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
auto loadPriorityProperty = properties["loadPriority"];
|
||||
if (loadPriorityProperty.isValid()) {
|
||||
_loadPriority = loadPriorityProperty.toFloat();
|
||||
_model->setLoadingPriority(_loadPriority);
|
||||
}
|
||||
|
||||
auto urlValue = properties["url"];
|
||||
if (urlValue.isValid() && urlValue.canConvert<QString>()) {
|
||||
_url = urlValue.toString();
|
||||
_updateModel = true;
|
||||
_isLoaded = false;
|
||||
_texturesLoaded = false;
|
||||
}
|
||||
|
||||
auto texturesValue = properties["textures"];
|
||||
if (texturesValue.isValid() && texturesValue.canConvert(QVariant::Map)) {
|
||||
_texturesLoaded = false;
|
||||
QVariantMap textureMap = texturesValue.toMap();
|
||||
_modelTextures = textureMap;
|
||||
_texturesDirty = true;
|
||||
}
|
||||
|
||||
auto groupCulledValue = properties["isGroupCulled"];
|
||||
if (groupCulledValue.isValid() && groupCulledValue.canConvert(QVariant::Bool)) {
|
||||
setGroupCulled(groupCulledValue.toBool());
|
||||
}
|
||||
|
||||
// jointNames is read-only.
|
||||
// jointPositions is read-only.
|
||||
// jointOrientations is read-only.
|
||||
|
||||
// relative
|
||||
auto jointTranslationsValue = properties["jointTranslations"];
|
||||
if (jointTranslationsValue.canConvert(QVariant::List)) {
|
||||
const QVariantList& jointTranslations = jointTranslationsValue.toList();
|
||||
int translationCount = jointTranslations.size();
|
||||
int jointCount = _model->getJointStateCount();
|
||||
if (translationCount < jointCount) {
|
||||
jointCount = translationCount;
|
||||
}
|
||||
for (int i=0; i < jointCount; i++) {
|
||||
const auto& translationValue = jointTranslations[i];
|
||||
if (translationValue.isValid()) {
|
||||
_model->setJointTranslation(i, true, vec3FromVariant(translationValue), 1.0f);
|
||||
}
|
||||
}
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
// relative
|
||||
auto jointRotationsValue = properties["jointRotations"];
|
||||
if (jointRotationsValue.canConvert(QVariant::List)) {
|
||||
const QVariantList& jointRotations = jointRotationsValue.toList();
|
||||
int rotationCount = jointRotations.size();
|
||||
int jointCount = _model->getJointStateCount();
|
||||
if (rotationCount < jointCount) {
|
||||
jointCount = rotationCount;
|
||||
}
|
||||
for (int i=0; i < jointCount; i++) {
|
||||
const auto& rotationValue = jointRotations[i];
|
||||
if (rotationValue.isValid()) {
|
||||
_model->setJointRotation(i, true, quatFromVariant(rotationValue), 1.0f);
|
||||
}
|
||||
}
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
auto animationSettings = properties["animationSettings"];
|
||||
if (animationSettings.canConvert(QVariant::Map)) {
|
||||
QVariantMap animationSettingsMap = animationSettings.toMap();
|
||||
|
||||
auto animationURL = animationSettingsMap["url"];
|
||||
auto animationFPS = animationSettingsMap["fps"];
|
||||
auto animationCurrentFrame = animationSettingsMap["currentFrame"];
|
||||
auto animationFirstFrame = animationSettingsMap["firstFrame"];
|
||||
auto animationLastFrame = animationSettingsMap["lastFrame"];
|
||||
auto animationRunning = animationSettingsMap["running"];
|
||||
auto animationLoop = animationSettingsMap["loop"];
|
||||
auto animationHold = animationSettingsMap["hold"];
|
||||
auto animationAllowTranslation = animationSettingsMap["allowTranslation"];
|
||||
|
||||
if (animationURL.canConvert(QVariant::Url)) {
|
||||
_animationURL = animationURL.toUrl();
|
||||
}
|
||||
if (animationFPS.isValid()) {
|
||||
_animationFPS = animationFPS.toFloat();
|
||||
}
|
||||
if (animationCurrentFrame.isValid()) {
|
||||
_animationCurrentFrame = animationCurrentFrame.toFloat();
|
||||
}
|
||||
if (animationFirstFrame.isValid()) {
|
||||
_animationFirstFrame = animationFirstFrame.toFloat();
|
||||
}
|
||||
if (animationLastFrame.isValid()) {
|
||||
_animationLastFrame = animationLastFrame.toFloat();
|
||||
}
|
||||
|
||||
if (animationRunning.canConvert(QVariant::Bool)) {
|
||||
_animationRunning = animationRunning.toBool();
|
||||
}
|
||||
if (animationLoop.canConvert(QVariant::Bool)) {
|
||||
_animationLoop = animationLoop.toBool();
|
||||
}
|
||||
if (animationHold.canConvert(QVariant::Bool)) {
|
||||
_animationHold = animationHold.toBool();
|
||||
}
|
||||
if (animationAllowTranslation.canConvert(QVariant::Bool)) {
|
||||
_animationAllowTranslation = animationAllowTranslation.toBool();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
template <typename vectorType, typename itemType>
|
||||
vectorType ModelOverlay::mapJoints(mapFunction<itemType> function) const {
|
||||
vectorType result;
|
||||
if (_model && _model->isActive()) {
|
||||
const int jointCount = _model->getJointStateCount();
|
||||
result.reserve(jointCount);
|
||||
for (int i = 0; i < jointCount; i++) {
|
||||
result << function(i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// Note: ModelOverlay overrides Volume3DOverlay's "dimensions" and "scale" properties.
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>model</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.ModelProperties
|
||||
*
|
||||
* @property {string} type=sphere - Has the value <code>"model"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} isGroupCulled=false - If <code>true</code>, the mesh parts of the model are LOD culled as a group.
|
||||
* If <code>false</code>, separate mesh parts will be LOD culled individually.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {string} url - The URL of the FBX or OBJ model used for the overlay.
|
||||
* @property {number} loadPriority=0.0 - The priority for loading and displaying the overlay. Overlays with higher values load
|
||||
* first.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonym: <code>size</code>.
|
||||
* @property {Vec3} scale - The scale factor applied to the model's dimensions.
|
||||
* @property {object.<name, url>} textures - Maps the named textures in the model to the JPG or PNG images in the urls.
|
||||
* @property {Array.<string>} jointNames - The names of the joints - if any - in the model. <em>Read-only.</em>
|
||||
* @property {Array.<Quat>} jointRotations - The relative rotations of the model's joints. <em>Not copied if overlay is
|
||||
* cloned.</em>
|
||||
* @property {Array.<Vec3>} jointTranslations - The relative translations of the model's joints. <em>Not copied if overlay is
|
||||
* cloned.</em>
|
||||
* @property {Array.<Quat>} jointOrientations - The absolute orientations of the model's joints, in world coordinates.
|
||||
* <em>Read-only.</em>
|
||||
* @property {Array.<Vec3>} jointPositions - The absolute positions of the model's joints, in world coordinates.
|
||||
* <em>Read-only.</em>
|
||||
* @property {string} animationSettings.url="" - The URL of an FBX file containing an animation to play.
|
||||
* @property {number} animationSettings.fps=0 - The frame rate (frames/sec) to play the animation at.
|
||||
* @property {number} animationSettings.firstFrame=0 - The frame to start playing at.
|
||||
* @property {number} animationSettings.lastFrame=0 - The frame to finish playing at.
|
||||
* @property {number} animationSettings.currentFrame=0 - The current frame being played.
|
||||
* @property {boolean} animationSettings.running=false - Whether or not the animation is playing.
|
||||
* @property {boolean} animationSettings.loop=false - Whether or not the animation should repeat in a loop.
|
||||
* @property {boolean} animationSettings.hold=false - Whether or not when the animation finishes, the rotations and
|
||||
* translations of the last frame played should be maintained.
|
||||
* @property {boolean} animationSettings.allowTranslation=false - Whether or not translations contained in the animation should
|
||||
* be played.
|
||||
*/
|
||||
QVariant ModelOverlay::getProperty(const QString& property) {
|
||||
if (property == "url") {
|
||||
return _url.toString();
|
||||
}
|
||||
if (property == "dimensions" || property == "size") {
|
||||
return vec3toVariant(getDimensions());
|
||||
}
|
||||
if (property == "scale") {
|
||||
return vec3toVariant(getSNScale());
|
||||
}
|
||||
if (property == "textures") {
|
||||
if (_modelTextures.size() > 0) {
|
||||
QVariantMap textures;
|
||||
foreach(const QString& key, _modelTextures.keys()) {
|
||||
textures[key] = _modelTextures[key].toString();
|
||||
}
|
||||
return textures;
|
||||
} else {
|
||||
return QVariant();
|
||||
}
|
||||
}
|
||||
|
||||
if (property == "loadPriority") {
|
||||
return _loadPriority;
|
||||
}
|
||||
|
||||
if (property == "jointNames") {
|
||||
if (_model && _model->isActive()) {
|
||||
// note: going through Rig because Model::getJointNames() (which proxies to HFMModel) was always empty
|
||||
const Rig* rig = &(_model->getRig());
|
||||
return mapJoints<QStringList, QString>([rig](int jointIndex) -> QString {
|
||||
return rig->nameOfJoint(jointIndex);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// relative
|
||||
if (property == "jointRotations") {
|
||||
return mapJoints<QVariantList, QVariant>(
|
||||
[this](int jointIndex) -> QVariant {
|
||||
glm::quat rotation;
|
||||
_model->getJointRotation(jointIndex, rotation);
|
||||
return quatToVariant(rotation);
|
||||
});
|
||||
}
|
||||
|
||||
// relative
|
||||
if (property == "jointTranslations") {
|
||||
return mapJoints<QVariantList, QVariant>(
|
||||
[this](int jointIndex) -> QVariant {
|
||||
glm::vec3 translation;
|
||||
_model->getJointTranslation(jointIndex, translation);
|
||||
return vec3toVariant(translation);
|
||||
});
|
||||
}
|
||||
|
||||
// absolute
|
||||
if (property == "jointOrientations") {
|
||||
return mapJoints<QVariantList, QVariant>(
|
||||
[this](int jointIndex) -> QVariant {
|
||||
glm::quat orientation;
|
||||
_model->getJointRotationInWorldFrame(jointIndex, orientation);
|
||||
return quatToVariant(orientation);
|
||||
});
|
||||
}
|
||||
|
||||
// absolute
|
||||
if (property == "jointPositions") {
|
||||
return mapJoints<QVariantList, QVariant>(
|
||||
[this](int jointIndex) -> QVariant {
|
||||
glm::vec3 position;
|
||||
_model->getJointPositionInWorldFrame(jointIndex, position);
|
||||
return vec3toVariant(position);
|
||||
});
|
||||
}
|
||||
|
||||
// animation properties
|
||||
if (property == "animationSettings") {
|
||||
QVariantMap animationSettingsMap;
|
||||
|
||||
animationSettingsMap["url"] = _animationURL;
|
||||
animationSettingsMap["fps"] = _animationFPS;
|
||||
animationSettingsMap["currentFrame"] = _animationCurrentFrame;
|
||||
animationSettingsMap["firstFrame"] = _animationFirstFrame;
|
||||
animationSettingsMap["lastFrame"] = _animationLastFrame;
|
||||
animationSettingsMap["running"] = _animationRunning;
|
||||
animationSettingsMap["loop"] = _animationLoop;
|
||||
animationSettingsMap["hold"]= _animationHold;
|
||||
animationSettingsMap["allowTranslation"] = _animationAllowTranslation;
|
||||
|
||||
return animationSettingsMap;
|
||||
}
|
||||
|
||||
|
||||
return Volume3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool ModelOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
QVariantMap extraInfo;
|
||||
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo, precisionPicking);
|
||||
}
|
||||
|
||||
bool ModelOverlay::findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) {
|
||||
return _model->findRayIntersectionAgainstSubMeshes(origin, direction, distance, face, surfaceNormal, extraInfo, precisionPicking);
|
||||
}
|
||||
|
||||
bool ModelOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
QVariantMap extraInfo;
|
||||
return _model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, parabolicDistance, face, surfaceNormal, extraInfo, precisionPicking);
|
||||
}
|
||||
|
||||
bool ModelOverlay::findParabolaIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking) {
|
||||
return _model->findParabolaIntersectionAgainstSubMeshes(origin, velocity, acceleration, parabolicDistance, face, surfaceNormal, extraInfo, precisionPicking);
|
||||
}
|
||||
|
||||
ModelOverlay* ModelOverlay::createClone() const {
|
||||
return new ModelOverlay(this);
|
||||
}
|
||||
|
||||
Transform ModelOverlay::evalRenderTransform() {
|
||||
Transform transform = getTransform();
|
||||
transform.setScale(1.0f); // disable inherited scale
|
||||
return transform;
|
||||
}
|
||||
|
||||
void ModelOverlay::locationChanged(bool tellPhysics) {
|
||||
Base3DOverlay::locationChanged(tellPhysics);
|
||||
|
||||
// FIXME Start using the _renderTransform instead of calling for Transform and Dimensions from here, do the custom things needed in evalRenderTransform()
|
||||
if (_model && _model->isActive()) {
|
||||
_model->setRotation(getWorldOrientation());
|
||||
_model->setTranslation(getWorldPosition());
|
||||
_updateModel = true;
|
||||
}
|
||||
}
|
||||
|
||||
QString ModelOverlay::getName() const {
|
||||
if (_name != "") {
|
||||
return QString("Overlay:") + getType() + ":" + _name;
|
||||
}
|
||||
return QString("Overlay:") + getType() + ":" + _url.toString();
|
||||
}
|
||||
|
||||
|
||||
void ModelOverlay::animate() {
|
||||
|
||||
if (!_animation || !_animation->isLoaded() || !_model || !_model->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
QVector<JointData> jointsData;
|
||||
|
||||
const QVector<HFMAnimationFrame>& frames = _animation->getFramesReference(); // NOTE: getFrames() is too heavy
|
||||
int frameCount = frames.size();
|
||||
if (frameCount <= 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_lastAnimated) {
|
||||
_lastAnimated = usecTimestampNow();
|
||||
return;
|
||||
}
|
||||
|
||||
auto now = usecTimestampNow();
|
||||
auto interval = now - _lastAnimated;
|
||||
_lastAnimated = now;
|
||||
float deltaTime = (float)interval / (float)USECS_PER_SECOND;
|
||||
_animationCurrentFrame += (deltaTime * _animationFPS);
|
||||
|
||||
int animationCurrentFrame = (int)(glm::floor(_animationCurrentFrame)) % frameCount;
|
||||
if (animationCurrentFrame < 0 || animationCurrentFrame > frameCount) {
|
||||
animationCurrentFrame = 0;
|
||||
}
|
||||
|
||||
if (animationCurrentFrame == _lastKnownCurrentFrame) {
|
||||
return;
|
||||
}
|
||||
_lastKnownCurrentFrame = animationCurrentFrame;
|
||||
|
||||
if (_jointMapping.size() != _model->getJointStateCount()) {
|
||||
return;
|
||||
}
|
||||
|
||||
QStringList animationJointNames = _animation->getHFMModel().getJointNames();
|
||||
auto& hfmJoints = _animation->getHFMModel().joints;
|
||||
|
||||
auto& originalHFMJoints = _model->getHFMModel().joints;
|
||||
auto& originalHFMIndices = _model->getHFMModel().jointIndices;
|
||||
|
||||
const QVector<glm::quat>& rotations = frames[_lastKnownCurrentFrame].rotations;
|
||||
const QVector<glm::vec3>& translations = frames[_lastKnownCurrentFrame].translations;
|
||||
|
||||
jointsData.resize(_jointMapping.size());
|
||||
for (int j = 0; j < _jointMapping.size(); j++) {
|
||||
int index = _jointMapping[j];
|
||||
|
||||
if (index >= 0) {
|
||||
glm::mat4 translationMat;
|
||||
|
||||
if (_animationAllowTranslation) {
|
||||
if (index < translations.size()) {
|
||||
translationMat = glm::translate(translations[index]);
|
||||
}
|
||||
} else if (index < animationJointNames.size()) {
|
||||
QString jointName = hfmJoints[index].name;
|
||||
|
||||
if (originalHFMIndices.contains(jointName)) {
|
||||
// Making sure the joint names exist in the original model the animation is trying to apply onto. If they do, then remap and get its translation.
|
||||
int remappedIndex = originalHFMIndices[jointName] - 1; // JointIndeces seem to always start from 1 and the found index is always 1 higher than actual.
|
||||
translationMat = glm::translate(originalHFMJoints[remappedIndex].translation);
|
||||
}
|
||||
}
|
||||
glm::mat4 rotationMat;
|
||||
if (index < rotations.size()) {
|
||||
rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * rotations[index] * hfmJoints[index].postRotation);
|
||||
} else {
|
||||
rotationMat = glm::mat4_cast(hfmJoints[index].preRotation * hfmJoints[index].postRotation);
|
||||
}
|
||||
|
||||
glm::mat4 finalMat = (translationMat * hfmJoints[index].preTransform *
|
||||
rotationMat * hfmJoints[index].postTransform);
|
||||
auto& jointData = jointsData[j];
|
||||
jointData.translation = extractTranslation(finalMat);
|
||||
jointData.translationIsDefaultPose = false;
|
||||
jointData.rotation = glmExtractRotation(finalMat);
|
||||
jointData.rotationIsDefaultPose = false;
|
||||
}
|
||||
}
|
||||
// Set the data in the model
|
||||
copyAnimationJointDataToModel(jointsData);
|
||||
}
|
||||
|
||||
|
||||
void ModelOverlay::mapAnimationJoints(const QStringList& modelJointNames) {
|
||||
|
||||
// if we don't have animation, or we're already joint mapped then bail early
|
||||
if (!hasAnimation() || jointsMapped()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_animation || _animation->getURL() != _animationURL) {
|
||||
_animation = DependencyManager::get<AnimationCache>()->getAnimation(_animationURL);
|
||||
}
|
||||
|
||||
if (_animation && _animation->isLoaded()) {
|
||||
QStringList animationJointNames = _animation->getJointNames();
|
||||
|
||||
if (modelJointNames.size() > 0 && animationJointNames.size() > 0) {
|
||||
_jointMapping.resize(modelJointNames.size());
|
||||
for (int i = 0; i < modelJointNames.size(); i++) {
|
||||
_jointMapping[i] = animationJointNames.indexOf(modelJointNames[i]);
|
||||
}
|
||||
_jointMappingCompleted = true;
|
||||
_jointMappingURL = _animationURL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ModelOverlay::copyAnimationJointDataToModel(QVector<JointData> jointsData) {
|
||||
if (!_model || !_model->isLoaded()) {
|
||||
return;
|
||||
}
|
||||
|
||||
// relay any inbound joint changes from scripts/animation/network to the model/rig
|
||||
for (int index = 0; index < jointsData.size(); ++index) {
|
||||
auto& jointData = jointsData[index];
|
||||
_model->setJointRotation(index, true, jointData.rotation, 1.0f);
|
||||
_model->setJointTranslation(index, true, jointData.translation, 1.0f);
|
||||
}
|
||||
_updateModel = true;
|
||||
}
|
||||
|
||||
void ModelOverlay::clearSubRenderItemIDs() {
|
||||
_subRenderItemIDs.clear();
|
||||
}
|
||||
|
||||
void ModelOverlay::setSubRenderItemIDs(const render::ItemIDs& ids) {
|
||||
_subRenderItemIDs = ids;
|
||||
}
|
||||
|
||||
uint32_t ModelOverlay::fetchMetaSubItems(render::ItemIDs& subItems) const {
|
||||
if (_model) {
|
||||
auto metaSubItems = _subRenderItemIDs;
|
||||
subItems.insert(subItems.end(), metaSubItems.begin(), metaSubItems.end());
|
||||
return (uint32_t)metaSubItems.size();
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool ModelOverlay::canReplaceModelMeshPart(int meshIndex, int partIndex) {
|
||||
// TODO: bounds checking; for now just used to indicate provider generally supports mesh updates
|
||||
return _model && _model->isLoaded();
|
||||
}
|
||||
|
||||
bool ModelOverlay::replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer newModel, int meshIndex, int partIndex) {
|
||||
return canReplaceModelMeshPart(meshIndex, partIndex) &&
|
||||
_model->replaceScriptableModelMeshPart(newModel, meshIndex, partIndex);
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase ModelOverlay::getScriptableModel() {
|
||||
if (!_model || !_model->isLoaded()) {
|
||||
return Base3DOverlay::getScriptableModel();
|
||||
}
|
||||
auto result = _model->getScriptableModel();
|
||||
result.objectID = Overlay::getID();
|
||||
return result;
|
||||
}
|
||||
|
||||
render::ItemKey ModelOverlay::getKey() {
|
||||
auto builder = render::ItemKey::Builder(Base3DOverlay::getKey());
|
||||
if (_isGroupCulled) {
|
||||
builder.withMetaCullGroup();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
|
@ -1,132 +0,0 @@
|
|||
//
|
||||
// ModelOverlay.h
|
||||
//
|
||||
//
|
||||
// Created by Clement on 6/30/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_ModelOverlay_h
|
||||
#define hifi_ModelOverlay_h
|
||||
|
||||
#include <Model.h>
|
||||
#include <AnimationCache.h>
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
class ModelOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
virtual QString getName() const override;
|
||||
|
||||
ModelOverlay();
|
||||
ModelOverlay(const ModelOverlay* modelOverlay);
|
||||
|
||||
virtual void update(float deltatime) override;
|
||||
virtual void render(RenderArgs* args) override {};
|
||||
|
||||
virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override;
|
||||
|
||||
render::ItemKey getKey() override;
|
||||
void clearSubRenderItemIDs();
|
||||
void setSubRenderItemIDs(const render::ItemIDs& ids);
|
||||
|
||||
virtual void setIsVisibleInSecondaryCamera(bool value) override {
|
||||
Base3DOverlay::setIsVisibleInSecondaryCamera(value);
|
||||
_visibleDirty = true;
|
||||
}
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
virtual bool findRayIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) override;
|
||||
virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
virtual bool findParabolaIntersectionExtraInfo(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, QVariantMap& extraInfo, bool precisionPicking = false) override;
|
||||
|
||||
virtual ModelOverlay* createClone() const override;
|
||||
|
||||
virtual bool addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) override;
|
||||
virtual void removeFromScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) override;
|
||||
|
||||
void locationChanged(bool tellPhysics) override;
|
||||
|
||||
float getLoadPriority() const { return _loadPriority; }
|
||||
|
||||
bool hasAnimation() const { return !_animationURL.isEmpty(); }
|
||||
bool jointsMapped() const { return _jointMappingURL == _animationURL && _jointMappingCompleted; }
|
||||
|
||||
void setVisible(bool visible) override;
|
||||
void setDrawInFront(bool drawInFront) override;
|
||||
void setDrawHUDLayer(bool drawHUDLayer) override;
|
||||
void setGroupCulled(bool groupCulled);
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
virtual bool canReplaceModelMeshPart(int meshIndex, int partIndex) override;
|
||||
virtual bool replaceScriptableModelMeshPart(scriptable::ScriptableModelBasePointer model, int meshIndex, int partIndex) override;
|
||||
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
// helper to extract metadata from our Model's rigged joints
|
||||
template <typename itemType> using mapFunction = std::function<itemType(int jointIndex)>;
|
||||
template <typename vectorType, typename itemType>
|
||||
vectorType mapJoints(mapFunction<itemType> function) const;
|
||||
|
||||
void animate();
|
||||
void mapAnimationJoints(const QStringList& modelJointNames);
|
||||
bool isAnimatingSomething() const {
|
||||
return !_animationURL.isEmpty() && _animationRunning && _animationFPS != 0.0f;
|
||||
}
|
||||
void copyAnimationJointDataToModel(QVector<JointData> jointsData);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
ModelPointer _model;
|
||||
QVariantMap _modelTextures;
|
||||
bool _texturesLoaded { false };
|
||||
bool _texturesDirty { false };
|
||||
|
||||
render::ItemIDs _subRenderItemIDs;
|
||||
|
||||
QUrl _url;
|
||||
bool _updateModel { false };
|
||||
bool _scaleToFit { false };
|
||||
float _loadPriority { 0.0f };
|
||||
|
||||
AnimationPointer _animation;
|
||||
|
||||
QUrl _animationURL;
|
||||
float _animationFPS { 0.0f };
|
||||
float _animationCurrentFrame { 0.0f };
|
||||
bool _animationRunning { false };
|
||||
bool _animationLoop { false };
|
||||
float _animationFirstFrame { 0.0f };
|
||||
float _animationLastFrame { 0.0f };
|
||||
bool _animationHold { false };
|
||||
bool _animationAllowTranslation { false };
|
||||
uint64_t _lastAnimated { 0 };
|
||||
int _lastKnownCurrentFrame { -1 };
|
||||
|
||||
QUrl _jointMappingURL;
|
||||
bool _jointMappingCompleted { false };
|
||||
QVector<int> _jointMapping; // domain is index into model-joints, range is index into animation-joints
|
||||
|
||||
bool _visibleDirty { true };
|
||||
bool _renderLayerDirty { false };
|
||||
bool _isGroupCulled { false };
|
||||
bool _groupCulledDirty { false };
|
||||
|
||||
};
|
||||
|
||||
#endif // hifi_ModelOverlay_h
|
|
@ -15,126 +15,31 @@
|
|||
|
||||
#include "Application.h"
|
||||
|
||||
const glm::u8vec3 Overlay::DEFAULT_OVERLAY_COLOR = { 255, 255, 255 };
|
||||
const float Overlay::DEFAULT_ALPHA = 0.7f;
|
||||
|
||||
Overlay::Overlay() :
|
||||
_renderItemID(render::Item::INVALID_ITEM_ID),
|
||||
_isLoaded(true),
|
||||
_alpha(DEFAULT_ALPHA),
|
||||
_pulse(1.0f),
|
||||
_pulseMax(0.0f),
|
||||
_pulseMin(0.0f),
|
||||
_pulsePeriod(1.0f),
|
||||
_pulseDirection(1.0f),
|
||||
_lastPulseUpdate(usecTimestampNow()),
|
||||
_alphaPulse(0.0f),
|
||||
_colorPulse(0.0f),
|
||||
_color(DEFAULT_OVERLAY_COLOR),
|
||||
_visible(true)
|
||||
{
|
||||
}
|
||||
|
||||
Overlay::Overlay(const Overlay* overlay) :
|
||||
_renderItemID(render::Item::INVALID_ITEM_ID),
|
||||
_isLoaded(overlay->_isLoaded),
|
||||
_alpha(overlay->_alpha),
|
||||
_pulse(overlay->_pulse),
|
||||
_pulseMax(overlay->_pulseMax),
|
||||
_pulseMin(overlay->_pulseMin),
|
||||
_pulsePeriod(overlay->_pulsePeriod),
|
||||
_pulseDirection(overlay->_pulseDirection),
|
||||
_lastPulseUpdate(usecTimestampNow()),
|
||||
_alphaPulse(overlay->_alphaPulse),
|
||||
_colorPulse(overlay->_colorPulse),
|
||||
_color(overlay->_color),
|
||||
_visible(overlay->_visible)
|
||||
{
|
||||
}
|
||||
|
||||
Overlay::~Overlay() {
|
||||
}
|
||||
|
||||
void Overlay::setProperties(const QVariantMap& properties) {
|
||||
bool valid;
|
||||
auto color = u8vec3FromVariant(properties["color"], valid);
|
||||
if (valid) {
|
||||
_color = color;
|
||||
}
|
||||
|
||||
if (properties["alpha"].isValid()) {
|
||||
setAlpha(properties["alpha"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["pulseMax"].isValid()) {
|
||||
setPulseMax(properties["pulseMax"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["pulseMin"].isValid()) {
|
||||
setPulseMin(properties["pulseMin"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["pulsePeriod"].isValid()) {
|
||||
setPulsePeriod(properties["pulsePeriod"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["alphaPulse"].isValid()) {
|
||||
setAlphaPulse(properties["alphaPulse"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["colorPulse"].isValid()) {
|
||||
setColorPulse(properties["colorPulse"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["visible"].isValid()) {
|
||||
bool visible = properties["visible"].toBool();
|
||||
setVisible(visible);
|
||||
}
|
||||
}
|
||||
|
||||
// JSDoc for copying to @typedefs of overlay types that inherit Overlay.
|
||||
/**jsdoc
|
||||
* @property {string} type=TODO - Has the value <code>"TODO"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*/
|
||||
QVariant Overlay::getProperty(const QString& property) {
|
||||
if (property == "type") {
|
||||
return QVariant(getType());
|
||||
}
|
||||
if (property == "color") {
|
||||
return u8vec3ColortoVariant(_color);
|
||||
}
|
||||
if (property == "alpha") {
|
||||
return _alpha;
|
||||
}
|
||||
if (property == "pulseMax") {
|
||||
return _pulseMax;
|
||||
}
|
||||
if (property == "pulseMin") {
|
||||
return _pulseMin;
|
||||
}
|
||||
if (property == "pulsePeriod") {
|
||||
return _pulsePeriod;
|
||||
}
|
||||
if (property == "alphaPulse") {
|
||||
return _alphaPulse;
|
||||
}
|
||||
if (property == "colorPulse") {
|
||||
return _colorPulse;
|
||||
if (property == "id") {
|
||||
return getID();
|
||||
}
|
||||
if (property == "visible") {
|
||||
return _visible;
|
||||
|
@ -143,67 +48,6 @@ QVariant Overlay::getProperty(const QString& property) {
|
|||
return QVariant();
|
||||
}
|
||||
|
||||
glm::u8vec3 Overlay::getColor() {
|
||||
if (_colorPulse == 0.0f) {
|
||||
return _color;
|
||||
}
|
||||
|
||||
float pulseLevel = updatePulse();
|
||||
glm::u8vec3 result = _color;
|
||||
if (_colorPulse < 0.0f) {
|
||||
result.x *= (1.0f - pulseLevel);
|
||||
result.y *= (1.0f - pulseLevel);
|
||||
result.z *= (1.0f - pulseLevel);
|
||||
} else {
|
||||
result.x *= pulseLevel;
|
||||
result.y *= pulseLevel;
|
||||
result.z *= pulseLevel;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
float Overlay::getAlpha() {
|
||||
if (_alphaPulse == 0.0f) {
|
||||
return _alpha;
|
||||
}
|
||||
float pulseLevel = updatePulse();
|
||||
return (_alphaPulse >= 0.0f) ? _alpha * pulseLevel : _alpha * (1.0f - pulseLevel);
|
||||
}
|
||||
|
||||
// pulse travels from min to max, then max to min in one period.
|
||||
float Overlay::updatePulse() {
|
||||
if (_pulsePeriod <= 0.0f) {
|
||||
return _pulse;
|
||||
}
|
||||
quint64 now = usecTimestampNow();
|
||||
quint64 elapsedUSecs = (now - _lastPulseUpdate);
|
||||
float elapsedSeconds = (float)elapsedUSecs / (float)USECS_PER_SECOND;
|
||||
float elapsedPeriods = elapsedSeconds / _pulsePeriod;
|
||||
|
||||
// we can safely remove any "full" periods, since those just rotate us back
|
||||
// to our final pulse level
|
||||
elapsedPeriods = fmod(elapsedPeriods, 1.0f);
|
||||
_lastPulseUpdate = now;
|
||||
|
||||
float pulseDistance = (_pulseMax - _pulseMin);
|
||||
float pulseDistancePerPeriod = pulseDistance * 2.0f;
|
||||
|
||||
float pulseDelta = _pulseDirection * pulseDistancePerPeriod * elapsedPeriods;
|
||||
float newPulse = _pulse + pulseDelta;
|
||||
float limit = (_pulseDirection > 0.0f) ? _pulseMax : _pulseMin;
|
||||
float passedLimit = (_pulseDirection > 0.0f) ? (newPulse >= limit) : (newPulse <= limit);
|
||||
|
||||
if (passedLimit) {
|
||||
float pulseDeltaToLimit = newPulse - limit;
|
||||
float pulseDeltaFromLimitBack = pulseDelta - pulseDeltaToLimit;
|
||||
pulseDelta = -pulseDeltaFromLimitBack;
|
||||
_pulseDirection *= -1.0f;
|
||||
}
|
||||
_pulse += pulseDelta;
|
||||
|
||||
return _pulse;
|
||||
}
|
||||
|
||||
bool Overlay::addToScene(Overlay::Pointer overlay, const render::ScenePointer& scene, render::Transaction& transaction) {
|
||||
_renderItemID = scene->allocateID();
|
||||
transaction.resetItem(_renderItemID, std::make_shared<Overlay::Payload>(overlay));
|
||||
|
@ -225,8 +69,7 @@ render::ItemKey Overlay::getKey() {
|
|||
builder.withInvisible();
|
||||
}
|
||||
|
||||
// always visible in primary view. if isVisibleInSecondaryCamera, also draw in secondary view
|
||||
render::hifi::Tag viewTagBits = getIsVisibleInSecondaryCamera() ? render::hifi::TAG_ALL_VIEWS : render::hifi::TAG_MAIN_VIEW;
|
||||
render::hifi::Tag viewTagBits = render::hifi::TAG_ALL_VIEWS;
|
||||
builder.withTagBits(viewTagBits);
|
||||
|
||||
return builder.build();
|
||||
|
|
|
@ -23,12 +23,10 @@ public:
|
|||
|
||||
Overlay();
|
||||
Overlay(const Overlay* overlay);
|
||||
~Overlay();
|
||||
|
||||
virtual QUuid getID() const { return _id; }
|
||||
virtual void setID(const QUuid& id) { _id = id; }
|
||||
|
||||
virtual void update(float deltatime) {}
|
||||
virtual void render(RenderArgs* args) = 0;
|
||||
|
||||
virtual render::ItemKey getKey();
|
||||
|
@ -44,35 +42,13 @@ public:
|
|||
|
||||
// getters
|
||||
virtual QString getType() const = 0;
|
||||
bool isLoaded() { return _isLoaded; }
|
||||
bool isLoaded() { return true; }
|
||||
bool getVisible() const { return _visible; }
|
||||
virtual bool isTransparent() { return getAlphaPulse() != 0.0f || getAlpha() != 1.0f; };
|
||||
virtual bool getIsVisibleInSecondaryCamera() const { return false; }
|
||||
|
||||
glm::u8vec3 getColor();
|
||||
float getAlpha();
|
||||
|
||||
float getPulseMax() const { return _pulseMax; }
|
||||
float getPulseMin() const { return _pulseMin; }
|
||||
float getPulsePeriod() const { return _pulsePeriod; }
|
||||
float getPulseDirection() const { return _pulseDirection; }
|
||||
|
||||
float getColorPulse() const { return _colorPulse; }
|
||||
float getAlphaPulse() const { return _alphaPulse; }
|
||||
|
||||
// setters
|
||||
virtual void setVisible(bool visible) { _visible = visible; }
|
||||
void setDrawHUDLayer(bool drawHUDLayer);
|
||||
void setColor(const glm::u8vec3& color) { _color = color; }
|
||||
void setAlpha(float alpha) { _alpha = alpha; }
|
||||
|
||||
void setPulseMax(float value) { _pulseMax = value; }
|
||||
void setPulseMin(float value) { _pulseMin = value; }
|
||||
void setPulsePeriod(float value) { _pulsePeriod = value; }
|
||||
void setPulseDirection(float value) { _pulseDirection = value; }
|
||||
|
||||
void setColorPulse(float value) { _colorPulse = value; }
|
||||
void setAlphaPulse(float value) { _alphaPulse = value; }
|
||||
unsigned int getStackOrder() const { return _stackOrder; }
|
||||
void setStackOrder(unsigned int stackOrder) { _stackOrder = stackOrder; }
|
||||
|
||||
Q_INVOKABLE virtual void setProperties(const QVariantMap& properties);
|
||||
Q_INVOKABLE virtual Overlay* createClone() const = 0;
|
||||
|
@ -81,35 +57,12 @@ public:
|
|||
render::ItemID getRenderItemID() const { return _renderItemID; }
|
||||
void setRenderItemID(render::ItemID renderItemID) { _renderItemID = renderItemID; }
|
||||
|
||||
unsigned int getStackOrder() const { return _stackOrder; }
|
||||
void setStackOrder(unsigned int stackOrder) { _stackOrder = stackOrder; }
|
||||
|
||||
protected:
|
||||
float updatePulse();
|
||||
|
||||
render::ItemID _renderItemID{ render::Item::INVALID_ITEM_ID };
|
||||
|
||||
bool _isLoaded;
|
||||
float _alpha;
|
||||
|
||||
float _pulse;
|
||||
float _pulseMax;
|
||||
float _pulseMin;
|
||||
float _pulsePeriod;
|
||||
float _pulseDirection;
|
||||
quint64 _lastPulseUpdate;
|
||||
|
||||
float _alphaPulse; // ratio of the pulse to the alpha
|
||||
float _colorPulse; // ratio of the pulse to the color
|
||||
|
||||
glm::u8vec3 _color;
|
||||
bool _visible; // should the overlay be drawn at all
|
||||
render::ItemID _renderItemID { render::Item::INVALID_ITEM_ID };
|
||||
|
||||
bool _visible;
|
||||
unsigned int _stackOrder { 0 };
|
||||
|
||||
static const glm::u8vec3 DEFAULT_OVERLAY_COLOR;
|
||||
static const float DEFAULT_ALPHA;
|
||||
|
||||
private:
|
||||
QUuid _id;
|
||||
};
|
||||
|
|
|
@ -17,13 +17,12 @@
|
|||
|
||||
class Overlay2D : public Overlay {
|
||||
Q_OBJECT
|
||||
|
||||
|
||||
public:
|
||||
Overlay2D() {}
|
||||
Overlay2D(const Overlay2D* overlay2D);
|
||||
|
||||
virtual AABox getBounds() const override;
|
||||
|
||||
virtual AABox getBounds() const override;
|
||||
virtual uint32_t fetchMetaSubItems(render::ItemIDs& subItems) const override { subItems.push_back(getRenderItemID()); return 1; }
|
||||
|
||||
// getters
|
||||
|
@ -32,7 +31,7 @@ public:
|
|||
int getWidth() const { return _bounds.width(); }
|
||||
int getHeight() const { return _bounds.height(); }
|
||||
const QRect& getBoundingRect() const { return _bounds; }
|
||||
|
||||
|
||||
// setters
|
||||
void setX(int x) { _bounds.setX(x); }
|
||||
void setY(int y) { _bounds.setY(y); }
|
||||
|
|
|
@ -79,13 +79,6 @@ void Overlays::init() {
|
|||
}
|
||||
|
||||
void Overlays::update(float deltatime) {
|
||||
{
|
||||
QMutexLocker locker(&_mutex);
|
||||
foreach(const auto& thisOverlay, _overlays) {
|
||||
thisOverlay->update(deltatime);
|
||||
}
|
||||
}
|
||||
|
||||
cleanupOverlaysToDelete();
|
||||
}
|
||||
|
||||
|
@ -948,3 +941,589 @@ QVector<QUuid> Overlays::findOverlays(const glm::vec3& center, float radius) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* Different overlay types have different properties: some common to all overlays (listed below) and some specific to each
|
||||
* {@link Overlays.OverlayType|OverlayType} (linked to below). The properties are accessed as an object of property names and
|
||||
* values.
|
||||
*
|
||||
* @typedef {object} Overlays.OverlayProperties
|
||||
* @property {Uuid} id - The ID of the overlay. <em>Read-only.</em>
|
||||
* @property {string} type=TODO - Has the value <code>"TODO"</code>. <em>Read-only.</em>
|
||||
* @property {Overlays.OverlayType} type - The overlay type. <em>Read-only.</em>
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @see The different entity types have additional properties as follows:
|
||||
* @see {@link Overlays.OverlayProperties-Image|OverlayProperties-Image}
|
||||
* @see {@link Overlays.OverlayProperties-Text|OverlayProperties-Text}
|
||||
* @see {@link Overlays.OverlayProperties-Rectangle|OverlayProperties-Rectangle}
|
||||
* @see {@link Overlays.OverlayProperties-Cube|OverlayProperties-Cube}
|
||||
* @see {@link Overlays.OverlayProperties-Sphere|OverlayProperties-Sphere}
|
||||
* @see {@link Overlays.OverlayProperties-Shape|OverlayProperties-Shape}
|
||||
* @see {@link Overlays.OverlayProperties-Model|OverlayProperties-Model}
|
||||
* @see {@link Overlays.OverlayProperties-Text3D|OverlayProperties-Text3D}
|
||||
* @see {@link Overlays.OverlayProperties-Image3D|OverlayProperties-Image3D}
|
||||
* @see {@link Overlays.OverlayProperties-Web|OverlayProperties-Web}
|
||||
* @see {@link Overlays.OverlayProperties-Line|OverlayProperties-Line}
|
||||
* @see {@link Overlays.OverlayProperties-Grid|OverlayProperties-Grid}
|
||||
* @see {@link Overlays.OverlayProperties-Circle|OverlayProperties-Circle}
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Image"</code> {@link Overlays.OverlayType|OverlayType} is a 2D image.
|
||||
* @typedef {object} Overlays.OverlayProperties-Image
|
||||
* @property {Rect} bounds - The position and size of the image display area, in pixels. <em>Write-only.</em>
|
||||
* @property {number} x - Integer left, x-coordinate value of the image display area = <code>bounds.x</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} y - Integer top, y-coordinate value of the image display area = <code>bounds.y</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} width - Integer width of the image display area = <code>bounds.width</code>. <em>Write-only.</em>
|
||||
* @property {number} height - Integer height of the image display area = <code>bounds.height</code>. <em>Write-only.</em>
|
||||
* @property {string} imageURL - The URL of the image file to display. The image is scaled to fit to the <code>bounds</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {Vec2} subImage=0,0 - Integer coordinates of the top left pixel to start using image content from.
|
||||
* <em>Write-only.</em>
|
||||
* @property {Color} color=0,0,0 - The color to apply over the top of the image to colorize it. <em>Write-only.</em>
|
||||
* @property {number} alpha=0.0 - The opacity of the color applied over the top of the image, <code>0.0</code> -
|
||||
* <code>1.0</code>. <em>Write-only.</em>
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Text"</code> {@link Overlays.OverlayType|OverlayType} is for 2D text.
|
||||
* @typedef {object} Overlays.OverlayProperties-Text
|
||||
* @property {Rect} bounds - The position and size of the rectangle, in pixels. <em>Write-only.</em>
|
||||
* @property {number} x - Integer left, x-coordinate value = <code>bounds.x</code>. <em>Write-only.</em>
|
||||
* @property {number} y - Integer top, y-coordinate value = <code>bounds.y</code>. <em>Write-only.</em>
|
||||
* @property {number} width - Integer width of the rectangle = <code>bounds.width</code>. <em>Write-only.</em>
|
||||
* @property {number} height - Integer height of the rectangle = <code>bounds.height</code>. <em>Write-only.</em>
|
||||
*
|
||||
* @property {number} margin=0 - Sets the <code>leftMargin</code> and <code>topMargin</code> values, in pixels.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} leftMargin=0 - The left margin's size, in pixels. This value is also used for the right margin.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} topMargin=0 - The top margin's size, in pixels. This value is also used for the bottom margin.
|
||||
* <em>Write-only.</em>
|
||||
* @property {string} text="" - The text to display. Text does not automatically wrap; use <code>\n</code> for a line break. Text
|
||||
* is clipped to the <code>bounds</code>. <em>Write-only.</em>
|
||||
* @property {number} font.size=18 - The size of the text, in pixels. <em>Write-only.</em>
|
||||
* @property {number} lineHeight=18 - The height of a line of text, in pixels. <em>Write-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the text. Synonym: <code>textColor</code>. <em>Write-only.</em>
|
||||
* @property {number} alpha=1.0 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>. <em>Write-only.</em>
|
||||
* @property {Color} backgroundColor=0,0,0 - The color of the background rectangle. <em>Write-only.</em>
|
||||
* @property {number} backgroundAlpha=0.7 - The opacity of the background rectangle. <em>Write-only.</em>
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Text"</code> {@link Overlays.OverlayType|OverlayType} is for 2D rectangles.
|
||||
* @typedef {object} Overlays.OverlayProperties-Rectangle
|
||||
* @property {Rect} bounds - The position and size of the rectangle, in pixels. <em>Write-only.</em>
|
||||
* @property {number} x - Integer left, x-coordinate value = <code>bounds.x</code>. <em>Write-only.</em>
|
||||
* @property {number} y - Integer top, y-coordinate value = <code>bounds.y</code>. <em>Write-only.</em>
|
||||
* @property {number} width - Integer width of the rectangle = <code>bounds.width</code>. <em>Write-only.</em>
|
||||
* @property {number} height - Integer height of the rectangle = <code>bounds.height</code>. <em>Write-only.</em>
|
||||
*
|
||||
* @property {Color} color=0,0,0 - The color of the overlay. <em>Write-only.</em>
|
||||
* @property {number} alpha=1.0 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>. <em>Write-only.</em>
|
||||
* @property {number} borderWidth=1 - Integer width of the border, in pixels. The border is drawn within the rectangle's bounds.
|
||||
* It is not drawn unless either <code>borderColor</code> or <code>borderAlpha</code> are specified. <em>Write-only.</em>
|
||||
* @property {number} radius=0 - Integer corner radius, in pixels. <em>Write-only.</em>
|
||||
* @property {Color} borderColor=0,0,0 - The color of the border. <em>Write-only.</em>
|
||||
* @property {number} borderAlpha=1.0 - The opacity of the border, <code>0.0</code> - <code>1.0</code>.
|
||||
* <em>Write-only.</em>
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Cube"</code> {@link Overlays.OverlayType|OverlayType} is for 3D cubes.
|
||||
* @typedef {object} Overlays.OverlayProperties-Cube
|
||||
* @property {string} name - The name of the overlay.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Sphere"</code> {@link Overlays.OverlayType|OverlayType} is for 3D spheres.
|
||||
* @typedef {object} Overlays.OverlayProperties-Sphere
|
||||
* @property {string} name - The name of the overlay.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* <p>A <code>shape</code> {@link Overlays.OverlayType|OverlayType} may display as one of the following geometrical shapes:</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Dimensions</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"Circle"</code></td><td>2D</td><td>A circle oriented in 3D.</td></td></tr>
|
||||
* <tr><td><code>"Cone"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Cube"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Cylinder"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Dodecahedron"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Hexagon"</code></td><td>3D</td><td>A hexagonal prism.</td></tr>
|
||||
* <tr><td><code>"Icosahedron"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Line"</code></td><td>1D</td><td>A line oriented in 3D.</td></tr>
|
||||
* <tr><td><code>"Octagon"</code></td><td>3D</td><td>An octagonal prism.</td></tr>
|
||||
* <tr><td><code>"Octahedron"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Quad"</code></td><td>2D</td><td>A square oriented in 3D.</tr>
|
||||
* <tr><td><code>"Sphere"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Tetrahedron"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Torus"</code></td><td>3D</td><td><em>Not implemented.</em></td></tr>
|
||||
* <tr><td><code>"Triangle"</code></td><td>3D</td><td>A triangular prism.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Overlays.Shape
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Shape"</code> {@link Overlays.OverlayType|OverlayType} is for 3D shapes.
|
||||
* @typedef {object} Overlays.OverlayProperties-Shape
|
||||
* @property {string} name - The name of the overlay.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Overlays.Shape} shape=Hexagon - The geometrical shape of the overlay.
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Model"</code> {@link Overlays.OverlayType|OverlayType} is for 3D models.
|
||||
* @typedef {object} Overlays.OverlayProperties-Model
|
||||
* @property {string} name - The name of the overlay.
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {string} url - The URL of the FBX or OBJ model used for the overlay.
|
||||
* @property {number} loadPriority=0.0 - The priority for loading and displaying the overlay. Overlays with higher values load
|
||||
* first. <CURRENTLY NOT USED>
|
||||
* @property {object.<name, url>} textures - Maps the named textures in the model to the JPG or PNG images in the urls.
|
||||
* @property {string[]} jointNames - The names of the joints - if any - in the model. <em>Read-only.</em>
|
||||
* @property {Quat[]} jointRotations - The relative rotations of the model's joints.
|
||||
* @property {Vec3[]} jointTranslations - The relative translations of the model's joints.
|
||||
* @property {Quat[]} jointOrientations - The absolute orientations of the model's joints, in world coordinates. <em>Read-only.</em>
|
||||
* @property {Vec3[]} jointPositions - The absolute positions of the model's joints, in world coordinates. <em>Read-only.</em>
|
||||
* @property {string} animationSettings.url="" - The URL of an FBX file containing an animation to play.
|
||||
* @property {number} animationSettings.fps=0 - The frame rate (frames/sec) to play the animation at.
|
||||
* @property {number} animationSettings.firstFrame=0 - The frame to start playing at.
|
||||
* @property {number} animationSettings.lastFrame=0 - The frame to finish playing at.
|
||||
* @property {number} animationSettings.currentFrame=0 - The current frame being played.
|
||||
* @property {boolean} animationSettings.running=false - Whether or not the animation is playing.
|
||||
* @property {boolean} animationSettings.loop=false - Whether or not the animation should repeat in a loop.
|
||||
* @property {boolean} animationSettings.hold=false - Whether or not when the animation finishes, the rotations and
|
||||
* translations of the last frame played should be maintained.
|
||||
* @property {boolean} animationSettings.allowTranslation=false - Whether or not translations contained in the animation should
|
||||
* be played.
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Text3D"</code> {@link Overlays.OverlayType|OverlayType} is for 3D text.
|
||||
* @typedef {object} Overlays.OverlayProperties-Text3D
|
||||
* @property {string} name - The name of the overlay.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {boolean} isFacingAvatar - If <code>true< / code>, the overlay is rotated to face the user's camera about an axis
|
||||
* parallel to the user's avatar's "up" direction.
|
||||
* @property {string} text="" - The text to display.Text does not automatically wrap; use <code>\n< / code> for a line break.
|
||||
* @property {number} textAlpha=1 - The text alpha value.
|
||||
* @property {Color} backgroundColor=0,0,0 - The background color.
|
||||
* @property {number} backgroundAlpha=0.7 - The background alpha value.
|
||||
* @property {number} lineHeight=1 - The height of a line of text in meters.
|
||||
* @property {number} leftMargin=0.1 - The left margin, in meters.
|
||||
* @property {number} topMargin=0.1 - The top margin, in meters.
|
||||
* @property {number} rightMargin=0.1 - The right margin, in meters.
|
||||
* @property {number} bottomMargin=0.1 - The bottom margin, in meters.
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Image3D"</code> {@link Overlays.OverlayType|OverlayType} is for 3D images.
|
||||
* @typedef {object} Overlays.OverlayProperties-Image3D
|
||||
* @property {string} name - The name of the overlay.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {boolean} isFacingAvatar - If <code>true</code>, the overlay is rotated to face the user's camera about an axis
|
||||
* parallel to the user's avatar's "up" direction.
|
||||
* @property {string} url - The URL of the PNG or JPG image to display.
|
||||
* @property {Rect} subImage - The portion of the image to display. Defaults to the full image.
|
||||
* @property {boolean} emissive - If <code>true</code>, the overlay is displayed at full brightness, otherwise it is rendered
|
||||
* with scene lighting.
|
||||
* @property {bool} keepAspectRatio=true - overlays will maintain the aspect ratio when the subImage is applied.
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Web"</code> {@link Overlays.OverlayType|OverlayType} is for 3D web surfaces.
|
||||
* @typedef {object} Overlays.OverlayProperties-Web
|
||||
* @property {string} name - The name of the overlay.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {boolean} isFacingAvatar - If <code>true</code>, the overlay is rotated to face the user's camera about an axis
|
||||
* parallel to the user's avatar's "up" direction.
|
||||
* @property {string} url - The URL of the Web page to display.
|
||||
* @property {string} scriptURL="" - The URL of a JavaScript file to inject into the Web page.
|
||||
* @property {number} dpi=30 - The dots per inch to display the Web page at, on the overlay.
|
||||
* @property {number} maxFPS=10 - The maximum update rate for the Web overlay content, in frames/second.
|
||||
* @property {string} inputMode=Touch - The user input mode to use - either <code>"Touch"</code> or <code>"Mouse"</code>.
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Line"</code> {@link Overlays.OverlayType|OverlayType} is for 3D lines.
|
||||
* @typedef {object} Overlays.OverlayProperties-Line
|
||||
* @property {string} name - The name of the overlay.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Uuid} endParentID=null - The avatar, entity, or overlay that the end point of the line is parented to.
|
||||
* @property {number} endParentJointIndex=65535 - Integer value specifying the skeleton joint that the end point of the line is
|
||||
* attached to if <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint". <CURRENTLY BROKEN>
|
||||
* @property {Vec3} start - The start point of the line. Synonyms: <code>startPoint</code> and <code>p1</code>.
|
||||
* @property {Vec3} end - The end point of the line. Synonyms: <code>endPoint</code> and <code>p2</code>.
|
||||
* @property {Vec3} localStart - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>start</code>. Synonym: <code>localPosition</code>.
|
||||
* @property {Vec3} localEnd - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>endParentID</code> set, otherwise the same value as <code>end</code>. <CURRENTLY BROKEN>
|
||||
* @property {number} length - The length of the line, in meters. This can be set after creating a line with start and end
|
||||
* points. <CURRENTLY BROKEN>
|
||||
* @property {number} glow=0 - If <code>glow > 0</code>, the line is rendered with a glow.
|
||||
* @property {number} lineWidth=0.02 - Width of the line, in meters.
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Grid"</code> {@link Overlays.OverlayType|OverlayType} is for 3D grid.
|
||||
* @typedef {object} Overlays.OverlayProperties-Grid
|
||||
* @property {string} name - The name of the overlay.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {boolean} followCamera=true - If <code>true</code>, the grid is always visible even as the camera moves to another position.
|
||||
* @property {number} majorGridEvery=5 - Integer number of <code>minorGridEvery</code> intervals at which to draw a thick grid line. Minimum value = <code>1</code>.
|
||||
* @property {number} minorGridEvery=1 - Real number of meters at which to draw thin grid lines. Minimum value = <code>0.001</code>.
|
||||
*/
|
||||
|
||||
/**jsdoc
|
||||
* The <code>"Circle"</code> {@link Overlays.OverlayType|OverlayType} is for 3D circle.
|
||||
* @typedef {object} Overlays.OverlayProperties-Circle
|
||||
* @property {string} name - The name of the overlay.
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
*
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>. Synonym: <code>localOrientation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of objects in the world, but behind the HUD.
|
||||
* @property {boolean} drawHUDLayer=false - If <code>true</code>, the overlay is rendered in front of everything, including the HUD.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {number} startAt = 0 - The counter - clockwise angle from the overlay's x-axis that drawing starts at, in degrees.
|
||||
* @property {number} endAt = 360 - The counter - clockwise angle from the overlay's x-axis that drawing ends at, in degrees.
|
||||
* @property {number} outerRadius = 1 - The outer radius of the overlay, in meters.Synonym: <code>radius< / code>.
|
||||
* @property {number} innerRadius = 0 - The inner radius of the overlay, in meters.
|
||||
* @property {Color} color = 255, 255, 255 - The color of the overlay.Setting this value also sets the values of
|
||||
* <code>innerStartColor< / code>, <code>innerEndColor< / code>, <code>outerStartColor< / code>, and <code>outerEndColor< / code>.
|
||||
* @property {Color} startColor - Sets the values of <code>innerStartColor< / code> and <code>outerStartColor< / code>.
|
||||
* <em>Write - only.< / em>
|
||||
* @property {Color} endColor - Sets the values of <code>innerEndColor< / code> and <code>outerEndColor< / code>.
|
||||
* <em>Write - only.< / em>
|
||||
* @property {Color} innerColor - Sets the values of <code>innerStartColor< / code> and <code>innerEndColor< / code>.
|
||||
* <em>Write - only.< / em>
|
||||
* @property {Color} outerColor - Sets the values of <code>outerStartColor< / code> and <code>outerEndColor< / code>.
|
||||
* <em>Write - only.< / em>
|
||||
* @property {Color} innerStartcolor - The color at the inner start point of the overlay.
|
||||
* @property {Color} innerEndColor - The color at the inner end point of the overlay.
|
||||
* @property {Color} outerStartColor - The color at the outer start point of the overlay.
|
||||
* @property {Color} outerEndColor - The color at the outer end point of the overlay.
|
||||
* @property {number} alpha = 0.5 - The opacity of the overlay, <code>0.0< / code> -<code>1.0< / code>.Setting this value also sets
|
||||
* the values of <code>innerStartAlpha< / code>, <code>innerEndAlpha< / code>, <code>outerStartAlpha< / code>, and
|
||||
* <code>outerEndAlpha< / code>.Synonym: <code>Alpha< / code>; <em>write - only< / em>.
|
||||
* @property {number} startAlpha - Sets the values of <code>innerStartAlpha< / code> and <code>outerStartAlpha< / code>.
|
||||
* <em>Write - only.< / em>
|
||||
* @property {number} endAlpha - Sets the values of <code>innerEndAlpha< / code> and <code>outerEndAlpha< / code>.
|
||||
* <em>Write - only.< / em>
|
||||
* @property {number} innerAlpha - Sets the values of <code>innerStartAlpha< / code> and <code>innerEndAlpha< / code>.
|
||||
* <em>Write - only.< / em>
|
||||
* @property {number} outerAlpha - Sets the values of <code>outerStartAlpha< / code> and <code>outerEndAlpha< / code>.
|
||||
* <em>Write - only.< / em>
|
||||
* @property {number} innerStartAlpha = 0 - The alpha at the inner start point of the overlay.
|
||||
* @property {number} innerEndAlpha = 0 - The alpha at the inner end point of the overlay.
|
||||
* @property {number} outerStartAlpha = 0 - The alpha at the outer start point of the overlay.
|
||||
* @property {number} outerEndAlpha = 0 - The alpha at the outer end point of the overlay.
|
||||
*
|
||||
* @property {boolean} hasTickMarks = false - If <code>true< / code>, tick marks are drawn.
|
||||
* @property {number} majorTickMarksAngle = 0 - The angle between major tick marks, in degrees.
|
||||
* @property {number} minorTickMarksAngle = 0 - The angle between minor tick marks, in degrees.
|
||||
* @property {number} majorTickMarksLength = 0 - The length of the major tick marks, in meters.A positive value draws tick marks
|
||||
* outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
|
||||
* @property {number} minorTickMarksLength = 0 - The length of the minor tick marks, in meters.A positive value draws tick marks
|
||||
* outwards from the inner radius; a negative value draws tick marks inwards from the outer radius.
|
||||
* @property {Color} majorTickMarksColor = 0, 0, 0 - The color of the major tick marks.
|
||||
* @property {Color} minorTickMarksColor = 0, 0, 0 - The color of the minor tick marks.
|
||||
*/
|
|
@ -1,62 +0,0 @@
|
|||
//
|
||||
// PanelAttachable.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 7/15/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 "PanelAttachable.h"
|
||||
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
bool PanelAttachable::getParentVisible() const {
|
||||
return true;
|
||||
}
|
||||
|
||||
// JSDoc for copying to @typedefs of overlay types that inherit PanelAttachable.
|
||||
// No JSDoc because these properties are not actually used.
|
||||
QVariant PanelAttachable::getProperty(const QString& property) {
|
||||
if (property == "offsetPosition") {
|
||||
return vec3toVariant(getOffsetPosition());
|
||||
}
|
||||
if (property == "offsetRotation") {
|
||||
return quatToVariant(getOffsetRotation());
|
||||
}
|
||||
if (property == "offsetScale") {
|
||||
return vec3toVariant(getOffsetScale());
|
||||
}
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
void PanelAttachable::setProperties(const QVariantMap& properties) {
|
||||
auto offsetPosition = properties["offsetPosition"];
|
||||
bool valid;
|
||||
if (offsetPosition.isValid()) {
|
||||
glm::vec3 newPosition = vec3FromVariant(offsetPosition, valid);
|
||||
if (valid) {
|
||||
setOffsetPosition(newPosition);
|
||||
}
|
||||
}
|
||||
|
||||
auto offsetRotation = properties["offsetRotation"];
|
||||
if (offsetRotation.isValid()) {
|
||||
setOffsetRotation(quatFromVariant(offsetRotation));
|
||||
}
|
||||
|
||||
auto offsetScale = properties["offsetScale"];
|
||||
if (offsetScale.isValid()) {
|
||||
setOffsetScale(vec3FromVariant(offsetScale));
|
||||
}
|
||||
}
|
||||
|
||||
bool PanelAttachable::applyTransformTo(Transform& transform, bool force) {
|
||||
if (force || usecTimestampNow() > _transformExpiry) {
|
||||
const quint64 TRANSFORM_UPDATE_PERIOD = 100000; // frequency is 10 Hz
|
||||
_transformExpiry = usecTimestampNow() + TRANSFORM_UPDATE_PERIOD;
|
||||
}
|
||||
return false;
|
||||
}
|
|
@ -1,69 +0,0 @@
|
|||
//
|
||||
// PanelAttachable.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// Created by Zander Otavka on 7/1/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
|
||||
//
|
||||
// Base class for anything that can attach itself to an `OverlayPanel` as a child.
|
||||
// `PanelAttachable keeps an `std::shared_ptr` to it's parent panel, and sets its
|
||||
// transformations and visibility based on the parent.
|
||||
//
|
||||
// When subclassing `PanelAttachable`, make sure `applyTransformTo`, `getProperty`, and
|
||||
// `setProperties are all called in the appropriate places. Look through `Image3DOverlay` and
|
||||
// `Billboard3DOverlay` for examples. Pay special attention to `applyTransformTo`; it should
|
||||
// be called in three places for `Overlay`s: `render`, `update`, and `findRayIntersection`.
|
||||
//
|
||||
// When overriding `applyTransformTo`, make sure to wrap all of your code, including the call
|
||||
// to the superclass method, with the following `if` block. Then call the superclass method
|
||||
// with force = true.
|
||||
//
|
||||
// if (force || usecTimestampNow() > _transformExpiry) {
|
||||
// PanelAttachable::applyTransformTo(transform, true);
|
||||
// ...
|
||||
// }
|
||||
//
|
||||
|
||||
#ifndef hifi_PanelAttachable_h
|
||||
#define hifi_PanelAttachable_h
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include <glm/glm.hpp>
|
||||
#include <Transform.h>
|
||||
#include <QScriptValue>
|
||||
#include <QScriptEngine>
|
||||
#include <QUuid>
|
||||
|
||||
class OverlayPanel;
|
||||
class PanelAttachable {
|
||||
public:
|
||||
// getters
|
||||
glm::vec3 getOffsetPosition() const { return _offset.getTranslation(); }
|
||||
glm::quat getOffsetRotation() const { return _offset.getRotation(); }
|
||||
glm::vec3 getOffsetScale() const { return _offset.getScale(); }
|
||||
bool getParentVisible() const;
|
||||
|
||||
// setters
|
||||
void setOffsetPosition(const glm::vec3& position) { _offset.setTranslation(position); }
|
||||
void setOffsetRotation(const glm::quat& rotation) { _offset.setRotation(rotation); }
|
||||
void setOffsetScale(float scale) { _offset.setScale(scale); }
|
||||
void setOffsetScale(const glm::vec3& scale) { _offset.setScale(scale); }
|
||||
|
||||
protected:
|
||||
void setProperties(const QVariantMap& properties);
|
||||
QVariant getProperty(const QString& property);
|
||||
|
||||
/// set position, rotation and scale on transform based on offsets, and parent panel offsets
|
||||
/// if force is false, only apply transform if it hasn't been applied in the last .1 seconds
|
||||
virtual bool applyTransformTo(Transform& transform, bool force = false);
|
||||
quint64 _transformExpiry = 0;
|
||||
|
||||
private:
|
||||
Transform _offset;
|
||||
};
|
||||
|
||||
#endif // hifi_PanelAttachable_h
|
|
@ -1,126 +0,0 @@
|
|||
//
|
||||
// Planar3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 "Planar3DOverlay.h"
|
||||
|
||||
#include <Extents.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
Planar3DOverlay::Planar3DOverlay() :
|
||||
Base3DOverlay(),
|
||||
_dimensions{1.0f, 1.0f}
|
||||
{
|
||||
}
|
||||
|
||||
Planar3DOverlay::Planar3DOverlay(const Planar3DOverlay* planar3DOverlay) :
|
||||
Base3DOverlay(planar3DOverlay),
|
||||
_dimensions(planar3DOverlay->_dimensions)
|
||||
{
|
||||
}
|
||||
|
||||
AABox Planar3DOverlay::getBounds() const {
|
||||
auto halfDimensions = glm::vec3{_dimensions / 2.0f, 0.01f};
|
||||
|
||||
auto extents = Extents{-halfDimensions, halfDimensions};
|
||||
extents.transform(getTransform());
|
||||
|
||||
return AABox(extents);
|
||||
}
|
||||
|
||||
void Planar3DOverlay::setDimensions(const glm::vec2& value) {
|
||||
_dimensions = value;
|
||||
notifyRenderVariableChange();
|
||||
}
|
||||
|
||||
void Planar3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
|
||||
auto dimensions = properties["dimensions"];
|
||||
|
||||
// if "dimensions" property was not there, check to see if they included aliases: scale
|
||||
if (!dimensions.isValid()) {
|
||||
dimensions = properties["scale"];
|
||||
if (!dimensions.isValid()) {
|
||||
dimensions = properties["size"];
|
||||
}
|
||||
}
|
||||
|
||||
if (dimensions.isValid()) {
|
||||
setDimensions(vec2FromVariant(dimensions));
|
||||
}
|
||||
}
|
||||
|
||||
// JSDoc for copying to @typedefs of overlay types that inherit Planar3DOverlay.
|
||||
/**jsdoc
|
||||
* @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
*/
|
||||
QVariant Planar3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec2ToVariant(getDimensions());
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool Planar3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
glm::vec2 xyDimensions = getDimensions();
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
glm::vec3 position = getWorldPosition();
|
||||
|
||||
if (findRayRectangleIntersection(origin, direction, rotation, position, xyDimensions, distance)) {
|
||||
glm::vec3 forward = rotation * Vectors::FRONT;
|
||||
if (glm::dot(forward, direction) > 0.0f) {
|
||||
face = MAX_Z_FACE;
|
||||
surfaceNormal = -forward;
|
||||
} else {
|
||||
face = MIN_Z_FACE;
|
||||
surfaceNormal = forward;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Planar3DOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
glm::vec2 xyDimensions = getDimensions();
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
glm::vec3 position = getWorldPosition();
|
||||
|
||||
glm::quat inverseRot = glm::inverse(rotation);
|
||||
glm::vec3 localOrigin = inverseRot * (origin - position);
|
||||
glm::vec3 localVelocity = inverseRot * velocity;
|
||||
glm::vec3 localAcceleration = inverseRot * acceleration;
|
||||
|
||||
if (findParabolaRectangleIntersection(localOrigin, localVelocity, localAcceleration, xyDimensions, parabolicDistance)) {
|
||||
float localIntersectionVelocityZ = localVelocity.z + localAcceleration.z * parabolicDistance;
|
||||
glm::vec3 forward = rotation * Vectors::FRONT;
|
||||
if (localIntersectionVelocityZ > 0.0f) {
|
||||
face = MIN_Z_FACE;
|
||||
surfaceNormal = forward;
|
||||
} else {
|
||||
face = MAX_Z_FACE;
|
||||
surfaceNormal = -forward;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Transform Planar3DOverlay::evalRenderTransform() {
|
||||
auto transform = getTransform();
|
||||
transform.setScale(1.0f); // ignore inherited scale factor from parents
|
||||
if (glm::length2(getDimensions()) != 1.0f) {
|
||||
transform.postScale(vec3(getDimensions(), 1.0f));
|
||||
}
|
||||
return transform;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
//
|
||||
// Planar3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Planar3DOverlay_h
|
||||
#define hifi_Planar3DOverlay_h
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
class Planar3DOverlay : public Base3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Planar3DOverlay();
|
||||
Planar3DOverlay(const Planar3DOverlay* planar3DOverlay);
|
||||
|
||||
virtual AABox getBounds() const override;
|
||||
virtual glm::vec2 getSize() const { return _dimensions; };
|
||||
|
||||
glm::vec2 getDimensions() const { return _dimensions; }
|
||||
void setDimensions(float value) { setDimensions(glm::vec2(value)); }
|
||||
void setDimensions(const glm::vec2& value);
|
||||
|
||||
virtual void setProperties(const QVariantMap& properties) override;
|
||||
virtual QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
|
||||
protected:
|
||||
glm::vec2 _dimensions;
|
||||
|
||||
Transform evalRenderTransform() override;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Planar3DOverlay_h
|
|
@ -25,7 +25,6 @@ public:
|
|||
QmlOverlay(const QUrl& url, const QmlOverlay* textOverlay);
|
||||
~QmlOverlay();
|
||||
|
||||
// Cannot fetch properties from QML based overlays due to race conditions
|
||||
bool supportsGetProperty() const override { return false; }
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
|
|
|
@ -1,158 +0,0 @@
|
|||
//
|
||||
// Rectangle3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 "Rectangle3DOverlay.h"
|
||||
|
||||
#include <GeometryCache.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
|
||||
QString const Rectangle3DOverlay::TYPE = "rectangle3d";
|
||||
|
||||
Rectangle3DOverlay::Rectangle3DOverlay() :
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
for (size_t i = 0; i < _rectGeometryIds.size(); ++i) {
|
||||
_rectGeometryIds[i] = geometryCache->allocateID();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle3DOverlay::Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay) :
|
||||
Planar3DOverlay(rectangle3DOverlay),
|
||||
_geometryCacheID(DependencyManager::get<GeometryCache>()->allocateID())
|
||||
{
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
for (size_t i = 0; i < _rectGeometryIds.size(); ++i) {
|
||||
_rectGeometryIds[i] = geometryCache->allocateID();
|
||||
}
|
||||
}
|
||||
|
||||
Rectangle3DOverlay::~Rectangle3DOverlay() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
geometryCache->releaseID(_geometryCacheID);
|
||||
for (size_t i = 0; i < _rectGeometryIds.size(); ++i) {
|
||||
geometryCache->releaseID(_rectGeometryIds[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Rectangle3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
float alpha = getAlpha();
|
||||
glm::u8vec3 color = getColor();
|
||||
glm::vec4 rectangleColor(toGlm(color), alpha);
|
||||
|
||||
auto batch = args->_batch;
|
||||
if (batch) {
|
||||
Transform transform = getRenderTransform();
|
||||
glm::vec2 halfDimensions = transform.getScale() * 0.5f;
|
||||
transform.setScale(1.0f);
|
||||
|
||||
batch->setModelTransform(transform);
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
|
||||
if (getIsSolid()) {
|
||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, 0.0f);
|
||||
geometryCache->bindSimpleProgram(*batch);
|
||||
geometryCache->renderQuad(*batch, topLeft, bottomRight, rectangleColor, _geometryCacheID);
|
||||
} else {
|
||||
geometryCache->bindSimpleProgram(*batch, false, false, false, true, true);
|
||||
if (getIsDashedLine()) {
|
||||
glm::vec3 point1(-halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||
glm::vec3 point2(halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||
glm::vec3 point3(halfDimensions.x, halfDimensions.y, 0.0f);
|
||||
glm::vec3 point4(-halfDimensions.x, halfDimensions.y, 0.0f);
|
||||
|
||||
geometryCache->renderDashedLine(*batch, point1, point2, rectangleColor, _rectGeometryIds[0]);
|
||||
geometryCache->renderDashedLine(*batch, point2, point3, rectangleColor, _rectGeometryIds[1]);
|
||||
geometryCache->renderDashedLine(*batch, point3, point4, rectangleColor, _rectGeometryIds[2]);
|
||||
geometryCache->renderDashedLine(*batch, point4, point1, rectangleColor, _rectGeometryIds[3]);
|
||||
} else {
|
||||
if (halfDimensions != _previousHalfDimensions) {
|
||||
QVector<glm::vec3> border;
|
||||
border << glm::vec3(-halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||
border << glm::vec3(halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||
border << glm::vec3(halfDimensions.x, halfDimensions.y, 0.0f);
|
||||
border << glm::vec3(-halfDimensions.x, halfDimensions.y, 0.0f);
|
||||
border << glm::vec3(-halfDimensions.x, -halfDimensions.y, 0.0f);
|
||||
geometryCache->updateVertices(_geometryCacheID, border, rectangleColor);
|
||||
|
||||
_previousHalfDimensions = halfDimensions;
|
||||
}
|
||||
geometryCache->renderVertices(*batch, gpu::LINE_STRIP, _geometryCacheID);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const render::ShapeKey Rectangle3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withOwnPipeline();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>rectangle3d</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.Rectangle3DProperties
|
||||
*
|
||||
* @property {string} type=rectangle3d - Has the value <code>"rectangle3d"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
*/
|
||||
void Rectangle3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Planar3DOverlay::setProperties(properties);
|
||||
}
|
||||
|
||||
Rectangle3DOverlay* Rectangle3DOverlay::createClone() const {
|
||||
return new Rectangle3DOverlay(this);
|
||||
}
|
|
@ -1,39 +0,0 @@
|
|||
//
|
||||
// Rectangle3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Rectangle3DOverlay_h
|
||||
#define hifi_Rectangle3DOverlay_h
|
||||
|
||||
#include "Planar3DOverlay.h"
|
||||
|
||||
class Rectangle3DOverlay : public Planar3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Rectangle3DOverlay();
|
||||
Rectangle3DOverlay(const Rectangle3DOverlay* rectangle3DOverlay);
|
||||
~Rectangle3DOverlay();
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
|
||||
virtual Rectangle3DOverlay* createClone() const override;
|
||||
|
||||
private:
|
||||
int _geometryCacheID;
|
||||
std::array<int, 4> _rectGeometryIds;
|
||||
glm::vec2 _previousHalfDimensions;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Rectangle3DOverlay_h
|
|
@ -11,29 +11,6 @@
|
|||
QString const RectangleOverlay::TYPE = "rectangle";
|
||||
QUrl const RectangleOverlay::URL(QString("hifi/overlays/RectangleOverlay.qml"));
|
||||
|
||||
// RectangleOverlay's properties are defined in the QML file specified above.
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>rectangle</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.RectangleProperties
|
||||
*
|
||||
* @property {Rect} bounds - The position and size of the rectangle, in pixels. <em>Write-only.</em>
|
||||
* @property {number} x - Integer left, x-coordinate value = <code>bounds.x</code>. <em>Write-only.</em>
|
||||
* @property {number} y - Integer top, y-coordinate value = <code>bounds.y</code>. <em>Write-only.</em>
|
||||
* @property {number} width - Integer width of the rectangle = <code>bounds.width</code>. <em>Write-only.</em>
|
||||
* @property {number} height - Integer height of the rectangle = <code>bounds.height</code>. <em>Write-only.</em>
|
||||
*
|
||||
* @property {Color} color=0,0,0 - The color of the overlay. <em>Write-only.</em>
|
||||
* @property {number} alpha=1.0 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>. <em>Write-only.</em>
|
||||
* @property {number} borderWidth=1 - Integer width of the border, in pixels. The border is drawn within the rectangle's bounds.
|
||||
* It is not drawn unless either <code>borderColor</code> or <code>borderAlpha</code> are specified. <em>Write-only.</em>
|
||||
* @property {number} radius=0 - Integer corner radius, in pixels. <em>Write-only.</em>
|
||||
* @property {Color} borderColor=0,0,0 - The color of the border. <em>Write-only.</em>
|
||||
* @property {number} borderAlpha=1.0 - The opacity of the border, <code>0.0</code> - <code>1.0</code>.
|
||||
* <em>Write-only.</em>
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* <em>Write-only.</em>
|
||||
*/
|
||||
|
||||
RectangleOverlay::RectangleOverlay() : QmlOverlay(URL) {}
|
||||
|
||||
RectangleOverlay::RectangleOverlay(const RectangleOverlay* rectangleOverlay)
|
||||
|
|
|
@ -1,204 +0,0 @@
|
|||
//
|
||||
// Shape3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 this before QGLWidget, which includes an earlier version of OpenGL
|
||||
#include "Shape3DOverlay.h"
|
||||
|
||||
#include <SharedUtil.h>
|
||||
#include <StreamUtils.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <DependencyManager.h>
|
||||
|
||||
QString const Shape3DOverlay::TYPE = "shape";
|
||||
|
||||
Shape3DOverlay::Shape3DOverlay(const Shape3DOverlay* shape3DOverlay) :
|
||||
Volume3DOverlay(shape3DOverlay),
|
||||
_shape(shape3DOverlay->_shape)
|
||||
{
|
||||
}
|
||||
|
||||
void Shape3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
float alpha = getAlpha();
|
||||
glm::u8vec3 color = getColor();
|
||||
glm::vec4 shapeColor(toGlm(color), alpha);
|
||||
|
||||
auto batch = args->_batch;
|
||||
if (batch) {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto shapePipeline = args->_shapePipeline;
|
||||
if (!shapePipeline) {
|
||||
shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
}
|
||||
|
||||
batch->setModelTransform(getRenderTransform());
|
||||
if (_isSolid) {
|
||||
geometryCache->renderSolidShapeInstance(args, *batch, _shape, shapeColor, shapePipeline);
|
||||
} else {
|
||||
geometryCache->renderWireShapeInstance(args, *batch, _shape, shapeColor, shapePipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const render::ShapeKey Shape3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid()) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
Shape3DOverlay* Shape3DOverlay::createClone() const {
|
||||
return new Shape3DOverlay(this);
|
||||
}
|
||||
|
||||
|
||||
/**jsdoc
|
||||
* <p>A <code>shape</code> {@link Overlays.OverlayType|OverlayType} may display as one of the following geometrical shapes:</p>
|
||||
* <table>
|
||||
* <thead>
|
||||
* <tr><th>Value</th><th>Dimensions</th><th>Description</th></tr>
|
||||
* </thead>
|
||||
* <tbody>
|
||||
* <tr><td><code>"Circle"</code></td><td>2D</td><td>A circle oriented in 3D.</td></td></tr>
|
||||
* <tr><td><code>"Cone"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Cube"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Cylinder"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Dodecahedron"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Hexagon"</code></td><td>3D</td><td>A hexagonal prism.</td></tr>
|
||||
* <tr><td><code>"Icosahedron"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Line"</code></td><td>1D</td><td>A line oriented in 3D.</td></tr>
|
||||
* <tr><td><code>"Octagon"</code></td><td>3D</td><td>An octagonal prism.</td></tr>
|
||||
* <tr><td><code>"Octahedron"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Quad"</code></td><td>2D</td><td>A square oriented in 3D.</tr>
|
||||
* <tr><td><code>"Sphere"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Tetrahedron"</code></td><td>3D</td><td></td></tr>
|
||||
* <tr><td><code>"Torus"</code></td><td>3D</td><td><em>Not implemented.</em></td></tr>
|
||||
* <tr><td><code>"Triangle"</code></td><td>3D</td><td>A triangular prism.</td></tr>
|
||||
* </tbody>
|
||||
* </table>
|
||||
* @typedef {string} Overlays.Shape
|
||||
*/
|
||||
static const std::array<QString, GeometryCache::Shape::NUM_SHAPES> shapeStrings { {
|
||||
"Line",
|
||||
"Triangle",
|
||||
"Quad",
|
||||
"Hexagon",
|
||||
"Octagon",
|
||||
"Circle",
|
||||
"Cube",
|
||||
"Sphere",
|
||||
"Tetrahedron",
|
||||
"Octahedron",
|
||||
"Dodecahedron",
|
||||
"Icosahedron",
|
||||
"Torus", // Not implemented yet.
|
||||
"Cone",
|
||||
"Cylinder"
|
||||
} };
|
||||
|
||||
|
||||
void Shape3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Volume3DOverlay::setProperties(properties);
|
||||
|
||||
auto shape = properties["shape"];
|
||||
if (shape.isValid()) {
|
||||
const QString shapeStr = shape.toString();
|
||||
for (size_t i = 0; i < shapeStrings.size(); ++i) {
|
||||
if (shapeStr == shapeStrings[i]) {
|
||||
this->_shape = static_cast<GeometryCache::Shape>(i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>shape</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.ShapeProperties
|
||||
*
|
||||
* @property {string} type=shape - Has the value <code>"shape"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
*
|
||||
* @property {Overlays.Shape} shape=Hexagon - The geometrical shape of the overlay.
|
||||
*/
|
||||
QVariant Shape3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "shape") {
|
||||
return shapeStrings[_shape];
|
||||
}
|
||||
|
||||
return Volume3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Transform Shape3DOverlay::evalRenderTransform() {
|
||||
// TODO: handle registration point??
|
||||
glm::vec3 position = getWorldPosition();
|
||||
glm::vec3 dimensions = getDimensions();
|
||||
glm::quat rotation = getWorldOrientation();
|
||||
|
||||
Transform transform;
|
||||
transform.setScale(dimensions);
|
||||
transform.setTranslation(position);
|
||||
transform.setRotation(rotation);
|
||||
return transform;
|
||||
}
|
||||
|
||||
scriptable::ScriptableModelBase Shape3DOverlay::getScriptableModel() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto vertexColor = ColorUtils::toVec3(_color);
|
||||
scriptable::ScriptableModelBase result;
|
||||
result.objectID = Overlay::getID();
|
||||
if (auto mesh = geometryCache->meshFromShape(_shape, vertexColor)) {
|
||||
result.append(mesh);
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
//
|
||||
// Shape3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Shape3DOverlay_h
|
||||
#define hifi_Shape3DOverlay_h
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
#include <GeometryCache.h>
|
||||
|
||||
class Shape3DOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Shape3DOverlay() {}
|
||||
Shape3DOverlay(const Shape3DOverlay* shape3DOverlay);
|
||||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
|
||||
virtual Shape3DOverlay* createClone() const override;
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
private:
|
||||
GeometryCache::Shape _shape { GeometryCache::Hexagon };
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Shape3DOverlay_h
|
|
@ -1,135 +0,0 @@
|
|||
//
|
||||
// Sphere3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 "Sphere3DOverlay.h"
|
||||
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <SharedUtil.h>
|
||||
|
||||
QString const Sphere3DOverlay::TYPE = "sphere";
|
||||
|
||||
// Sphere overlays should fit inside a cube of the specified dimensions, hence it needs to be a half unit sphere.
|
||||
// However, the geometry cache renders a UNIT sphere, so we need to scale down.
|
||||
static const float SPHERE_OVERLAY_SCALE = 0.5f;
|
||||
|
||||
Sphere3DOverlay::Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay) :
|
||||
Volume3DOverlay(Sphere3DOverlay)
|
||||
{
|
||||
}
|
||||
|
||||
// If Sphere3DOverlay had a getProperty() method then it would go here; do JSDoc here.
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>sphere</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.SphereProperties
|
||||
*
|
||||
* @property {string} type=sphere - Has the value <code>"sphere"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
*/
|
||||
|
||||
void Sphere3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
float alpha = getAlpha();
|
||||
glm::u8vec3 color = getColor();
|
||||
glm::vec4 sphereColor(toGlm(color), alpha);
|
||||
|
||||
auto batch = args->_batch;
|
||||
|
||||
if (batch) {
|
||||
batch->setModelTransform(getRenderTransform());
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto shapePipeline = args->_shapePipeline;
|
||||
if (!shapePipeline) {
|
||||
shapePipeline = _isSolid ? geometryCache->getOpaqueShapePipeline() : geometryCache->getWireShapePipeline();
|
||||
}
|
||||
|
||||
if (_isSolid) {
|
||||
geometryCache->renderSolidSphereInstance(args, *batch, sphereColor, shapePipeline);
|
||||
} else {
|
||||
geometryCache->renderWireSphereInstance(args, *batch, sphereColor, shapePipeline);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const render::ShapeKey Sphere3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
if (!getIsSolid()) {
|
||||
builder.withUnlit().withDepthBias();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
Sphere3DOverlay* Sphere3DOverlay::createClone() const {
|
||||
return new Sphere3DOverlay(this);
|
||||
}
|
||||
|
||||
Transform Sphere3DOverlay::evalRenderTransform() {
|
||||
Transform transform = getTransform();
|
||||
transform.setScale(1.0f); // ignore inherited scale from SpatiallyNestable
|
||||
transform.postScale(getDimensions() * SPHERE_OVERLAY_SCALE);
|
||||
|
||||
return transform;
|
||||
}
|
||||
|
||||
|
||||
scriptable::ScriptableModelBase Sphere3DOverlay::getScriptableModel() {
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
auto vertexColor = ColorUtils::toVec3(_color);
|
||||
scriptable::ScriptableModelBase result;
|
||||
if (auto mesh = geometryCache->meshFromShape(GeometryCache::Sphere, vertexColor)) {
|
||||
result.objectID = Overlay::getID();
|
||||
result.append(mesh);
|
||||
}
|
||||
return result;
|
||||
}
|
|
@ -1,37 +0,0 @@
|
|||
//
|
||||
// Sphere3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Sphere3DOverlay_h
|
||||
#define hifi_Sphere3DOverlay_h
|
||||
|
||||
#include "Volume3DOverlay.h"
|
||||
|
||||
class Sphere3DOverlay : public Volume3DOverlay {
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Sphere3DOverlay() {}
|
||||
Sphere3DOverlay(const Sphere3DOverlay* Sphere3DOverlay);
|
||||
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
|
||||
virtual Sphere3DOverlay* createClone() const override;
|
||||
|
||||
virtual scriptable::ScriptableModelBase getScriptableModel() override;
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Sphere3DOverlay_h
|
|
@ -1,295 +0,0 @@
|
|||
//
|
||||
// Text3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 "Text3DOverlay.h"
|
||||
|
||||
#include <TextureCache.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <RenderDeferredTask.h>
|
||||
#include <TextRenderer3D.h>
|
||||
|
||||
#include <AbstractViewStateInterface.h>
|
||||
|
||||
const int FIXED_FONT_POINT_SIZE = 40;
|
||||
const int FIXED_FONT_SCALING_RATIO = FIXED_FONT_POINT_SIZE * 92.0f; // Determined through experimentation to fit font to line
|
||||
// height.
|
||||
const float LINE_SCALE_RATIO = 1.2f;
|
||||
|
||||
QString const Text3DOverlay::TYPE = "text3d";
|
||||
|
||||
Text3DOverlay::Text3DOverlay() {
|
||||
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
|
||||
Text3DOverlay::Text3DOverlay(const Text3DOverlay* text3DOverlay) :
|
||||
Billboard3DOverlay(text3DOverlay),
|
||||
_text(text3DOverlay->_text),
|
||||
_backgroundColor(text3DOverlay->_backgroundColor),
|
||||
_textAlpha(text3DOverlay->_textAlpha),
|
||||
_lineHeight(text3DOverlay->_lineHeight),
|
||||
_leftMargin(text3DOverlay->_leftMargin),
|
||||
_topMargin(text3DOverlay->_topMargin),
|
||||
_rightMargin(text3DOverlay->_rightMargin),
|
||||
_bottomMargin(text3DOverlay->_bottomMargin)
|
||||
{
|
||||
_textRenderer = TextRenderer3D::getInstance(SANS_FONT_FAMILY, FIXED_FONT_POINT_SIZE);
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
|
||||
Text3DOverlay::~Text3DOverlay() {
|
||||
delete _textRenderer;
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
geometryCache->releaseID(_geometryId);
|
||||
}
|
||||
}
|
||||
|
||||
const QString Text3DOverlay::getText() const {
|
||||
QMutexLocker lock(&_mutex);
|
||||
return _text;
|
||||
}
|
||||
|
||||
void Text3DOverlay::setText(const QString& text) {
|
||||
QMutexLocker lock(&_mutex);
|
||||
_text = text;
|
||||
}
|
||||
|
||||
glm::u8vec3 Text3DOverlay::getBackgroundColor() {
|
||||
if (_colorPulse == 0.0f) {
|
||||
return _backgroundColor;
|
||||
}
|
||||
|
||||
float pulseLevel = updatePulse();
|
||||
glm::u8vec3 result = _backgroundColor;
|
||||
if (_colorPulse < 0.0f) {
|
||||
result.x *= (1.0f - pulseLevel);
|
||||
result.y *= (1.0f - pulseLevel);
|
||||
result.z *= (1.0f - pulseLevel);
|
||||
} else {
|
||||
result.x *= pulseLevel;
|
||||
result.y *= pulseLevel;
|
||||
result.z *= pulseLevel;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
void Text3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible || !getParentVisible()) {
|
||||
return; // do nothing if we're not visible
|
||||
}
|
||||
|
||||
Q_ASSERT(args->_batch);
|
||||
auto& batch = *args->_batch;
|
||||
|
||||
auto transform = getRenderTransform();
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
glm::u8vec3 backgroundColor = getBackgroundColor();
|
||||
glm::vec4 quadColor(toGlm(backgroundColor), getBackgroundAlpha());
|
||||
|
||||
glm::vec2 dimensions = getDimensions();
|
||||
glm::vec2 halfDimensions = dimensions * 0.5f;
|
||||
|
||||
const float SLIGHTLY_BEHIND = -0.001f;
|
||||
|
||||
glm::vec3 topLeft(-halfDimensions.x, -halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
glm::vec3 bottomRight(halfDimensions.x, halfDimensions.y, SLIGHTLY_BEHIND);
|
||||
DependencyManager::get<GeometryCache>()->bindSimpleProgram(batch, false, quadColor.a < 1.0f, false, false, false);
|
||||
DependencyManager::get<GeometryCache>()->renderQuad(batch, topLeft, bottomRight, quadColor, _geometryId);
|
||||
|
||||
// Same font properties as textSize()
|
||||
float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
|
||||
|
||||
float scaleFactor = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||
|
||||
glm::vec2 clipDimensions((dimensions.x - (_leftMargin + _rightMargin)) / scaleFactor,
|
||||
(dimensions.y - (_topMargin + _bottomMargin)) / scaleFactor);
|
||||
|
||||
transform.postTranslate(glm::vec3(-(halfDimensions.x - _leftMargin),
|
||||
halfDimensions.y - _topMargin, 0.001f));
|
||||
transform.setScale(scaleFactor);
|
||||
batch.setModelTransform(transform);
|
||||
|
||||
glm::vec4 textColor = { toGlm(_color), getTextAlpha() };
|
||||
|
||||
// FIXME: Factor out textRenderer so that Text3DOverlay overlay parts can be grouped by pipeline for a gpu performance increase.
|
||||
_textRenderer->draw(batch, 0, 0, getText(), textColor, glm::vec2(-1.0f));
|
||||
}
|
||||
|
||||
const render::ShapeKey Text3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
void Text3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Billboard3DOverlay::setProperties(properties);
|
||||
|
||||
auto text = properties["text"];
|
||||
if (text.isValid()) {
|
||||
setText(text.toString());
|
||||
}
|
||||
|
||||
auto textAlpha = properties["textAlpha"];
|
||||
if (textAlpha.isValid()) {
|
||||
float prevTextAlpha = getTextAlpha();
|
||||
setTextAlpha(textAlpha.toFloat());
|
||||
// Update our payload key if necessary to handle transparency
|
||||
if ((prevTextAlpha < 1.0f && _textAlpha >= 1.0f) || (prevTextAlpha >= 1.0f && _textAlpha < 1.0f)) {
|
||||
auto itemID = getRenderItemID();
|
||||
if (render::Item::isValidID(itemID)) {
|
||||
render::ScenePointer scene = AbstractViewStateInterface::instance()->getMain3DScene();
|
||||
render::Transaction transaction;
|
||||
transaction.updateItem(itemID);
|
||||
scene->enqueueTransaction(transaction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool valid;
|
||||
auto backgroundColor = properties["backgroundColor"];
|
||||
if (backgroundColor.isValid()) {
|
||||
auto color = u8vec3FromVariant(backgroundColor, valid);
|
||||
if (valid) {
|
||||
_backgroundColor = color;
|
||||
}
|
||||
}
|
||||
|
||||
if (properties["backgroundAlpha"].isValid()) {
|
||||
setAlpha(properties["backgroundAlpha"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["lineHeight"].isValid()) {
|
||||
setLineHeight(properties["lineHeight"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["leftMargin"].isValid()) {
|
||||
setLeftMargin(properties["leftMargin"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["topMargin"].isValid()) {
|
||||
setTopMargin(properties["topMargin"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["rightMargin"].isValid()) {
|
||||
setRightMargin(properties["rightMargin"].toFloat());
|
||||
}
|
||||
|
||||
if (properties["bottomMargin"].isValid()) {
|
||||
setBottomMargin(properties["bottomMargin"].toFloat());
|
||||
}
|
||||
}
|
||||
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>text3d</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.Text3DProperties
|
||||
*
|
||||
* @property {string} type=text3d - Has the value <code>"text3d"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {Vec2} dimensions=1,1 - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
*
|
||||
* @property {boolean} isFacingAvatar - If <code>true</code>, the overlay is rotated to face the user's camera about an axis
|
||||
* parallel to the user's avatar's "up" direction.
|
||||
*
|
||||
* @property {string} text="" - The text to display. Text does not automatically wrap; use <code>\n</code> for a line break.
|
||||
* @property {number} textAlpha=1 - The text alpha value.
|
||||
* @property {Color} backgroundColor=0,0,0 - The background color.
|
||||
* @property {number} backgroundAlpha=0.7 - The background alpha value.
|
||||
* @property {number} lineHeight=1 - The height of a line of text in meters.
|
||||
* @property {number} leftMargin=0.1 - The left margin, in meters.
|
||||
* @property {number} topMargin=0.1 - The top margin, in meters.
|
||||
* @property {number} rightMargin=0.1 - The right margin, in meters.
|
||||
* @property {number} bottomMargin=0.1 - The bottom margin, in meters.
|
||||
*/
|
||||
|
||||
QVariant Text3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "text") {
|
||||
return getText();
|
||||
}
|
||||
if (property == "textAlpha") {
|
||||
return _textAlpha;
|
||||
}
|
||||
if (property == "backgroundColor") {
|
||||
return u8vec3ColortoVariant(_backgroundColor);
|
||||
}
|
||||
if (property == "backgroundAlpha") {
|
||||
return Billboard3DOverlay::getProperty("alpha");
|
||||
}
|
||||
if (property == "lineHeight") {
|
||||
return _lineHeight;
|
||||
}
|
||||
if (property == "leftMargin") {
|
||||
return _leftMargin;
|
||||
}
|
||||
if (property == "topMargin") {
|
||||
return _topMargin;
|
||||
}
|
||||
if (property == "rightMargin") {
|
||||
return _rightMargin;
|
||||
}
|
||||
if (property == "bottomMargin") {
|
||||
return _bottomMargin;
|
||||
}
|
||||
|
||||
return Billboard3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
Text3DOverlay* Text3DOverlay::createClone() const {
|
||||
return new Text3DOverlay(this);;
|
||||
}
|
||||
|
||||
QSizeF Text3DOverlay::textSize(const QString& text) const {
|
||||
auto extents = _textRenderer->computeExtent(text);
|
||||
|
||||
float maxHeight = (float)_textRenderer->computeExtent("Xy").y * LINE_SCALE_RATIO;
|
||||
float pointToWorldScale = (maxHeight / FIXED_FONT_SCALING_RATIO) * _lineHeight;
|
||||
|
||||
return QSizeF(extents.x, extents.y) * pointToWorldScale;
|
||||
}
|
|
@ -1,78 +0,0 @@
|
|||
//
|
||||
// Text3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Text3DOverlay_h
|
||||
#define hifi_Text3DOverlay_h
|
||||
|
||||
#include <QString>
|
||||
#include <QtCore/QMutex>
|
||||
#include "Billboard3DOverlay.h"
|
||||
|
||||
class TextRenderer3D;
|
||||
|
||||
class Text3DOverlay : public Billboard3DOverlay {
|
||||
Q_OBJECT
|
||||
using Parent = Billboard3DOverlay;
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Text3DOverlay();
|
||||
Text3DOverlay(const Text3DOverlay* text3DOverlay);
|
||||
~Text3DOverlay();
|
||||
virtual void render(RenderArgs* args) override;
|
||||
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
|
||||
// getters
|
||||
const QString getText() const;
|
||||
float getLineHeight() const { return _lineHeight; }
|
||||
float getLeftMargin() const { return _leftMargin; }
|
||||
float getTopMargin() const { return _topMargin; }
|
||||
float getRightMargin() const { return _rightMargin; }
|
||||
float getBottomMargin() const { return _bottomMargin; }
|
||||
glm::u8vec3 getBackgroundColor();
|
||||
float getTextAlpha() { return _textAlpha; }
|
||||
float getBackgroundAlpha() { return getAlpha(); }
|
||||
bool isTransparent() override { return Overlay::isTransparent() || _textAlpha < 1.0f; }
|
||||
|
||||
// setters
|
||||
void setText(const QString& text);
|
||||
void setTextAlpha(float alpha) { _textAlpha = alpha; }
|
||||
void setLineHeight(float value) { _lineHeight = value; }
|
||||
void setLeftMargin(float margin) { _leftMargin = margin; }
|
||||
void setTopMargin(float margin) { _topMargin = margin; }
|
||||
void setRightMargin(float margin) { _rightMargin = margin; }
|
||||
void setBottomMargin(float margin) { _bottomMargin = margin; }
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
QSizeF textSize(const QString& test) const; // Meters
|
||||
|
||||
virtual Text3DOverlay* createClone() const override;
|
||||
|
||||
private:
|
||||
TextRenderer3D* _textRenderer = nullptr;
|
||||
|
||||
QString _text;
|
||||
mutable QMutex _mutex; // used to make get/setText threadsafe, mutable so can be used in const functions
|
||||
glm::u8vec3 _backgroundColor { 0, 0, 0 };
|
||||
float _textAlpha { 1.0f };
|
||||
float _lineHeight { 1.0f };
|
||||
float _leftMargin { 0.1f };
|
||||
float _topMargin { 0.1f };
|
||||
float _rightMargin { 0.1f };
|
||||
float _bottomMargin { 0.1f };
|
||||
int _geometryId { 0 };
|
||||
};
|
||||
|
||||
#endif // hifi_Text3DOverlay_h
|
|
@ -27,43 +27,12 @@
|
|||
QString const TextOverlay::TYPE = "text";
|
||||
QUrl const TextOverlay::URL(QString("hifi/overlays/TextOverlay.qml"));
|
||||
|
||||
// TextOverlay's properties are defined in the QML file specified above.
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>text</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.TextProperties
|
||||
*
|
||||
* @property {Rect} bounds - The position and size of the rectangle, in pixels. <em>Write-only.</em>
|
||||
* @property {number} x - Integer left, x-coordinate value = <code>bounds.x</code>. <em>Write-only.</em>
|
||||
* @property {number} y - Integer top, y-coordinate value = <code>bounds.y</code>. <em>Write-only.</em>
|
||||
* @property {number} width - Integer width of the rectangle = <code>bounds.width</code>. <em>Write-only.</em>
|
||||
* @property {number} height - Integer height of the rectangle = <code>bounds.height</code>. <em>Write-only.</em>
|
||||
*
|
||||
* @property {number} margin=0 - Sets the <code>leftMargin</code> and <code>topMargin</code> values, in pixels.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} leftMargin=0 - The left margin's size, in pixels. This value is also used for the right margin.
|
||||
* <em>Write-only.</em>
|
||||
* @property {number} topMargin=0 - The top margin's size, in pixels. This value is also used for the bottom margin.
|
||||
* <em>Write-only.</em>
|
||||
* @property {string} text="" - The text to display. Text does not automatically wrap; use <code>\n</code> for a line break. Text
|
||||
* is clipped to the <code>bounds</code>. <em>Write-only.</em>
|
||||
* @property {number} font.size=18 - The size of the text, in pixels. <em>Write-only.</em>
|
||||
* @property {number} lineHeight=18 - The height of a line of text, in pixels. <em>Write-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the text. Synonym: <code>textColor</code>. <em>Write-only.</em>
|
||||
* @property {number} alpha=1.0 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>. <em>Write-only.</em>
|
||||
* @property {Color} backgroundColor=0,0,0 - The color of the background rectangle. <em>Write-only.</em>
|
||||
* @property {number} backgroundAlpha=0.7 - The opacity of the background rectangle. <em>Write-only.</em>
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
* <em>Write-only.</em>
|
||||
*/
|
||||
|
||||
TextOverlay::TextOverlay() : QmlOverlay(URL) { }
|
||||
|
||||
TextOverlay::TextOverlay(const TextOverlay* textOverlay)
|
||||
: QmlOverlay(URL, textOverlay) {
|
||||
}
|
||||
|
||||
TextOverlay::~TextOverlay() { }
|
||||
|
||||
TextOverlay* TextOverlay::createClone() const {
|
||||
return new TextOverlay(this);
|
||||
}
|
||||
|
@ -80,10 +49,4 @@ QSizeF TextOverlay::textSize(const QString& text) const {
|
|||
QFontMetrics fm(font);
|
||||
QSizeF result = QSizeF(fm.width(text), 18 * lines);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
void TextOverlay::setTopMargin(float margin) {}
|
||||
void TextOverlay::setLeftMargin(float margin) {}
|
||||
void TextOverlay::setFontSize(float size) {}
|
||||
void TextOverlay::setText(const QString& text) {}
|
||||
}
|
|
@ -19,16 +19,8 @@ public:
|
|||
QString getType() const override { return TYPE; }
|
||||
static QUrl const URL;
|
||||
|
||||
|
||||
TextOverlay();
|
||||
TextOverlay(const TextOverlay* textOverlay);
|
||||
~TextOverlay();
|
||||
|
||||
void setTopMargin(float margin);
|
||||
void setLeftMargin(float margin);
|
||||
void setFontSize(float size);
|
||||
void setText(const QString& text);
|
||||
|
||||
|
||||
TextOverlay* createClone() const override;
|
||||
QSizeF textSize(const QString& text) const; // Pixels
|
||||
|
|
|
@ -1,117 +0,0 @@
|
|||
//
|
||||
// Volume3DOverlay.cpp
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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 "Volume3DOverlay.h"
|
||||
|
||||
#include <Extents.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
|
||||
Volume3DOverlay::Volume3DOverlay(const Volume3DOverlay* volume3DOverlay) :
|
||||
Base3DOverlay(volume3DOverlay),
|
||||
_localBoundingBox(volume3DOverlay->_localBoundingBox)
|
||||
{
|
||||
}
|
||||
|
||||
AABox Volume3DOverlay::getBounds() const {
|
||||
AABox bounds = _localBoundingBox;
|
||||
bounds.transform(getTransform());
|
||||
return bounds;
|
||||
}
|
||||
|
||||
void Volume3DOverlay::setDimensions(const glm::vec3& value) {
|
||||
_localBoundingBox.setBox(-value / 2.0f, value);
|
||||
notifyRenderVariableChange();
|
||||
}
|
||||
|
||||
void Volume3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Base3DOverlay::setProperties(properties);
|
||||
|
||||
auto dimensions = properties["dimensions"];
|
||||
|
||||
// if "dimensions" property was not there, check to see if they included aliases: scale, size
|
||||
if (!dimensions.isValid()) {
|
||||
dimensions = properties["scale"];
|
||||
if (!dimensions.isValid()) {
|
||||
dimensions = properties["size"];
|
||||
}
|
||||
}
|
||||
|
||||
if (dimensions.isValid()) {
|
||||
glm::vec3 scale = vec3FromVariant(dimensions);
|
||||
// don't allow a zero or negative dimension component to reach the renderTransform
|
||||
const float MIN_DIMENSION = 0.0001f;
|
||||
scale = glm::max(scale, MIN_DIMENSION);
|
||||
setDimensions(scale);
|
||||
}
|
||||
}
|
||||
|
||||
// JSDoc for copying to @typedefs of overlay types that inherit Volume3DOverlay.
|
||||
/**jsdoc
|
||||
* @typedef
|
||||
* @property {Vec3} dimensions - The dimensions of the overlay. Synonyms: <code>scale</code>, <code>size</code>.
|
||||
*/
|
||||
QVariant Volume3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "dimensions" || property == "scale" || property == "size") {
|
||||
return vec3toVariant(getDimensions());
|
||||
}
|
||||
|
||||
return Base3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
bool Volume3DOverlay::findRayIntersection(const glm::vec3& origin, const glm::vec3& direction,
|
||||
float& distance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
// extents is the entity relative, scaled, centered extents of the entity
|
||||
glm::mat4 worldToEntityMatrix;
|
||||
Transform transform = getTransform();
|
||||
transform.setScale(1.0f); // ignore any inherited scale from SpatiallyNestable
|
||||
transform.getInverseMatrix(worldToEntityMatrix);
|
||||
|
||||
glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f));
|
||||
glm::vec3 overlayFrameDirection = glm::vec3(worldToEntityMatrix * glm::vec4(direction, 0.0f));
|
||||
|
||||
// we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame
|
||||
// and testing intersection there.
|
||||
bool hit = _localBoundingBox.findRayIntersection(overlayFrameOrigin, overlayFrameDirection, 1.0f / overlayFrameDirection, distance, face, surfaceNormal);
|
||||
|
||||
if (hit) {
|
||||
surfaceNormal = transform.getRotation() * surfaceNormal;
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
|
||||
bool Volume3DOverlay::findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration,
|
||||
float& parabolicDistance, BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking) {
|
||||
// extents is the entity relative, scaled, centered extents of the entity
|
||||
glm::mat4 worldToEntityMatrix;
|
||||
Transform transform = getTransform();
|
||||
transform.setScale(1.0f); // ignore any inherited scale from SpatiallyNestable
|
||||
transform.getInverseMatrix(worldToEntityMatrix);
|
||||
|
||||
glm::vec3 overlayFrameOrigin = glm::vec3(worldToEntityMatrix * glm::vec4(origin, 1.0f));
|
||||
glm::vec3 overlayFrameVelocity = glm::vec3(worldToEntityMatrix * glm::vec4(velocity, 0.0f));
|
||||
glm::vec3 overlayFrameAcceleration = glm::vec3(worldToEntityMatrix * glm::vec4(acceleration, 0.0f));
|
||||
|
||||
// we can use the AABox's ray intersection by mapping our origin and direction into the overlays frame
|
||||
// and testing intersection there.
|
||||
bool hit = _localBoundingBox.findParabolaIntersection(overlayFrameOrigin, overlayFrameVelocity, overlayFrameAcceleration, parabolicDistance, face, surfaceNormal);
|
||||
|
||||
if (hit) {
|
||||
surfaceNormal = transform.getRotation() * surfaceNormal;
|
||||
}
|
||||
return hit;
|
||||
}
|
||||
|
||||
Transform Volume3DOverlay::evalRenderTransform() {
|
||||
Transform transform = getTransform();
|
||||
#ifndef USE_SN_SCALE
|
||||
transform.setScale(1.0f); // ignore any inherited scale from SpatiallyNestable
|
||||
#endif
|
||||
return transform;
|
||||
}
|
|
@ -1,45 +0,0 @@
|
|||
//
|
||||
// Volume3DOverlay.h
|
||||
// interface/src/ui/overlays
|
||||
//
|
||||
// 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_Volume3DOverlay_h
|
||||
#define hifi_Volume3DOverlay_h
|
||||
|
||||
#include "Base3DOverlay.h"
|
||||
|
||||
class Volume3DOverlay : public Base3DOverlay {
|
||||
Q_OBJECT
|
||||
using Parent = Base3DOverlay;
|
||||
|
||||
public:
|
||||
Volume3DOverlay() {}
|
||||
Volume3DOverlay(const Volume3DOverlay* volume3DOverlay);
|
||||
|
||||
virtual AABox getBounds() const override;
|
||||
|
||||
const glm::vec3& getDimensions() const { return _localBoundingBox.getDimensions(); }
|
||||
void setDimensions(const glm::vec3& value);
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual bool findRayIntersection(const glm::vec3& origin, const glm::vec3& direction, float& distance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
virtual bool findParabolaIntersection(const glm::vec3& origin, const glm::vec3& velocity, const glm::vec3& acceleration, float& parabolicDistance,
|
||||
BoxFace& face, glm::vec3& surfaceNormal, bool precisionPicking = false) override;
|
||||
|
||||
protected:
|
||||
// Centered local bounding box
|
||||
AABox _localBoundingBox { vec3(-0.5), 1.0f };
|
||||
|
||||
Transform evalRenderTransform() override;
|
||||
};
|
||||
|
||||
|
||||
#endif // hifi_Volume3DOverlay_h
|
|
@ -1,490 +0,0 @@
|
|||
//
|
||||
// Web3DOverlay.cpp
|
||||
//
|
||||
// Created by Clement on 7/1/14.
|
||||
// Modified and renamed by Zander Otavka on 8/4/15
|
||||
// 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 "Web3DOverlay.h"
|
||||
|
||||
#include <Application.h>
|
||||
|
||||
#include <QQuickWindow>
|
||||
#include <QtGui/QOpenGLContext>
|
||||
#include <QtQuick/QQuickItem>
|
||||
#include <QtQml/QQmlContext>
|
||||
#include <QtQml/QQmlEngine>
|
||||
|
||||
#include <AbstractViewStateInterface.h>
|
||||
#include <gpu/Batch.h>
|
||||
#include <DependencyManager.h>
|
||||
#include <GeometryCache.h>
|
||||
#include <GeometryUtil.h>
|
||||
#include <gl/GLHelpers.h>
|
||||
#include <scripting/HMDScriptingInterface.h>
|
||||
#include <scripting/WindowScriptingInterface.h>
|
||||
#include <ui/OffscreenQmlSurface.h>
|
||||
#include <ui/OffscreenQmlSurfaceCache.h>
|
||||
#include <ui/TabletScriptingInterface.h>
|
||||
#include <PathUtils.h>
|
||||
#include <RegisteredMetaTypes.h>
|
||||
#include <TextureCache.h>
|
||||
#include <UsersScriptingInterface.h>
|
||||
#include <UserActivityLoggerScriptingInterface.h>
|
||||
#include <AbstractViewStateInterface.h>
|
||||
#include <AddressManager.h>
|
||||
#include "scripting/HMDScriptingInterface.h"
|
||||
#include "scripting/AssetMappingsScriptingInterface.h"
|
||||
#include "scripting/MenuScriptingInterface.h"
|
||||
#include "scripting/SettingsScriptingInterface.h"
|
||||
#include "scripting/KeyboardScriptingInterface.h"
|
||||
#include <Preferences.h>
|
||||
#include <AvatarBookmarks.h>
|
||||
#include <ScriptEngines.h>
|
||||
#include "FileDialogHelper.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "AudioClient.h"
|
||||
#include "LODManager.h"
|
||||
#include "ui/LoginDialog.h"
|
||||
#include "ui/OctreeStatsProvider.h"
|
||||
#include "ui/DomainConnectionModel.h"
|
||||
#include "ui/AvatarInputs.h"
|
||||
#include "avatar/AvatarManager.h"
|
||||
#include "scripting/AccountServicesScriptingInterface.h"
|
||||
#include "scripting/WalletScriptingInterface.h"
|
||||
#include <plugins/InputConfiguration.h>
|
||||
#include "ui/Snapshot.h"
|
||||
#include "SoundCacheScriptingInterface.h"
|
||||
#include "raypick/PointerScriptingInterface.h"
|
||||
#include <display-plugins/CompositorHelper.h>
|
||||
#include "AboutUtil.h"
|
||||
#include "ResourceRequestObserver.h"
|
||||
|
||||
#include <RenderableWebEntityItem.h>
|
||||
|
||||
static int MAX_WINDOW_SIZE = 4096;
|
||||
static const float METERS_TO_INCHES = 39.3701f;
|
||||
static const float OPAQUE_ALPHA_THRESHOLD = 0.99f;
|
||||
|
||||
const QString Web3DOverlay::TYPE = "web3d";
|
||||
|
||||
Web3DOverlay::Web3DOverlay() {
|
||||
_touchDevice.setCapabilities(QTouchDevice::Position);
|
||||
_touchDevice.setType(QTouchDevice::TouchScreen);
|
||||
_touchDevice.setName("Web3DOverlayTouchDevice");
|
||||
_touchDevice.setMaximumTouchPoints(4);
|
||||
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
connect(this, &Web3DOverlay::requestWebSurface, this, &Web3DOverlay::buildWebSurface);
|
||||
connect(this, &Web3DOverlay::resizeWebSurface, this, &Web3DOverlay::onResizeWebSurface);
|
||||
|
||||
buildWebSurface(true);
|
||||
}
|
||||
|
||||
Web3DOverlay::Web3DOverlay(const Web3DOverlay* Web3DOverlay) :
|
||||
Billboard3DOverlay(Web3DOverlay),
|
||||
_url(Web3DOverlay->_url),
|
||||
_scriptURL(Web3DOverlay->_scriptURL),
|
||||
_dpi(Web3DOverlay->_dpi)
|
||||
{
|
||||
_geometryId = DependencyManager::get<GeometryCache>()->allocateID();
|
||||
}
|
||||
|
||||
Web3DOverlay::~Web3DOverlay() {
|
||||
destroyWebSurface();
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (geometryCache) {
|
||||
geometryCache->releaseID(_geometryId);
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::rebuildWebSurface() {
|
||||
destroyWebSurface();
|
||||
buildWebSurface();
|
||||
}
|
||||
|
||||
void Web3DOverlay::destroyWebSurface() {
|
||||
if (_webSurface) {
|
||||
render::entities::WebEntityRenderer::releaseWebSurface(_webSurface, _cachedWebSurface, _connections);
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::buildWebSurface(bool overrideWeb) {
|
||||
if (_webSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
render::entities::WebEntityRenderer::acquireWebSurface(_url, overrideWeb || isWebContent(), _webSurface, _cachedWebSurface);
|
||||
onResizeWebSurface();
|
||||
_webSurface->resume();
|
||||
|
||||
_connections.push_back(QObject::connect(this, &Web3DOverlay::scriptEventReceived, _webSurface.data(), &OffscreenQmlSurface::emitScriptEvent));
|
||||
_connections.push_back(QObject::connect(_webSurface.data(), &OffscreenQmlSurface::webEventReceived, this, &Web3DOverlay::webEventReceived));
|
||||
}
|
||||
|
||||
void Web3DOverlay::update(float deltatime) {
|
||||
if (_webSurface) {
|
||||
// update globalPosition
|
||||
_webSurface->getSurfaceContext()->setContextProperty("globalPosition", vec3toVariant(getWorldPosition()));
|
||||
}
|
||||
Parent::update(deltatime);
|
||||
}
|
||||
|
||||
bool Web3DOverlay::isWebContent() const {
|
||||
QUrl sourceUrl(_url);
|
||||
if (sourceUrl.scheme() == "http" || sourceUrl.scheme() == "https" ||
|
||||
_url.toLower().endsWith(".htm") || _url.toLower().endsWith(".html")) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Web3DOverlay::setMaxFPS(uint8_t maxFPS) {
|
||||
// FIXME, the max FPS could be better managed by being dynamic (based on the number of current surfaces and the current rendering load)
|
||||
_desiredMaxFPS = maxFPS;
|
||||
if (_webSurface) {
|
||||
_webSurface->setMaxFps(_desiredMaxFPS);
|
||||
_currentMaxFPS = _desiredMaxFPS;
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::onResizeWebSurface() {
|
||||
glm::vec2 dims = glm::vec2(getDimensions());
|
||||
dims *= METERS_TO_INCHES * _dpi;
|
||||
|
||||
// ensure no side is never larger then MAX_WINDOW_SIZE
|
||||
float max = (dims.x > dims.y) ? dims.x : dims.y;
|
||||
if (max > MAX_WINDOW_SIZE) {
|
||||
dims *= MAX_WINDOW_SIZE / max;
|
||||
}
|
||||
|
||||
_webSurface->resize(QSize(dims.x, dims.y));
|
||||
}
|
||||
|
||||
void Web3DOverlay::render(RenderArgs* args) {
|
||||
if (!_renderVisible || !getParentVisible()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_webSurface) {
|
||||
emit requestWebSurface(false);
|
||||
return;
|
||||
}
|
||||
|
||||
if (_mayNeedResize) {
|
||||
emit resizeWebSurface();
|
||||
}
|
||||
|
||||
if (_currentMaxFPS != _desiredMaxFPS) {
|
||||
setMaxFPS(_desiredMaxFPS);
|
||||
}
|
||||
|
||||
vec4 color(toGlm(getColor()), getAlpha());
|
||||
|
||||
if (!_texture) {
|
||||
_texture = gpu::Texture::createExternal(OffscreenQmlSurface::getDiscardLambda());
|
||||
_texture->setSource(__FUNCTION__);
|
||||
}
|
||||
OffscreenQmlSurface::TextureAndFence newTextureAndFence;
|
||||
bool newTextureAvailable = _webSurface->fetchTexture(newTextureAndFence);
|
||||
if (newTextureAvailable) {
|
||||
_texture->setExternalTexture(newTextureAndFence.first, newTextureAndFence.second);
|
||||
}
|
||||
|
||||
Q_ASSERT(args->_batch);
|
||||
gpu::Batch& batch = *args->_batch;
|
||||
batch.setResourceTexture(0, _texture);
|
||||
|
||||
auto renderTransform = getRenderTransform();
|
||||
auto size = renderTransform.getScale();
|
||||
renderTransform.setScale(1.0f);
|
||||
batch.setModelTransform(renderTransform);
|
||||
|
||||
// Turn off jitter for these entities
|
||||
batch.pushProjectionJitter();
|
||||
|
||||
auto geometryCache = DependencyManager::get<GeometryCache>();
|
||||
if (color.a < OPAQUE_ALPHA_THRESHOLD) {
|
||||
geometryCache->bindWebBrowserProgram(batch, true);
|
||||
} else {
|
||||
geometryCache->bindWebBrowserProgram(batch);
|
||||
}
|
||||
vec2 halfSize = vec2(size.x, size.y) / 2.0f;
|
||||
geometryCache->renderQuad(batch, halfSize * -1.0f, halfSize, vec2(0), vec2(1), color, _geometryId);
|
||||
batch.popProjectionJitter(); // Restore jitter
|
||||
batch.setResourceTexture(0, nullptr); // restore default white color after me
|
||||
|
||||
}
|
||||
|
||||
Transform Web3DOverlay::evalRenderTransform() {
|
||||
Transform transform = Parent::evalRenderTransform();
|
||||
transform.setScale(1.0f);
|
||||
transform.postScale(glm::vec3(getDimensions(), 1.0f));
|
||||
return transform;
|
||||
}
|
||||
|
||||
const render::ShapeKey Web3DOverlay::getShapeKey() {
|
||||
auto builder = render::ShapeKey::Builder().withoutCullFace().withDepthBias().withOwnPipeline();
|
||||
if (isTransparent()) {
|
||||
builder.withTranslucent();
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
QObject* Web3DOverlay::getEventHandler() {
|
||||
if (!_webSurface) {
|
||||
return nullptr;
|
||||
}
|
||||
return _webSurface->getEventHandler();
|
||||
}
|
||||
|
||||
void Web3DOverlay::setProxyWindow(QWindow* proxyWindow) {
|
||||
if (!_webSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
_webSurface->setProxyWindow(proxyWindow);
|
||||
}
|
||||
|
||||
void Web3DOverlay::hoverEnterOverlay(const PointerEvent& event) {
|
||||
if (_inputMode == Mouse) {
|
||||
handlePointerEvent(event);
|
||||
} else if (_webSurface) {
|
||||
PointerEvent webEvent = event;
|
||||
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
|
||||
_webSurface->hoverBeginEvent(webEvent, _touchDevice);
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::hoverLeaveOverlay(const PointerEvent& event) {
|
||||
if (_inputMode == Mouse) {
|
||||
PointerEvent endEvent(PointerEvent::Release, event.getID(), event.getPos2D(), event.getPos3D(), event.getNormal(), event.getDirection(),
|
||||
event.getButton(), event.getButtons(), event.getKeyboardModifiers());
|
||||
handlePointerEvent(endEvent);
|
||||
// QML onReleased is only triggered if a click has happened first. We need to send this "fake" mouse move event to properly trigger an onExited.
|
||||
PointerEvent endMoveEvent(PointerEvent::Move, event.getID());
|
||||
handlePointerEvent(endMoveEvent);
|
||||
} else if (_webSurface) {
|
||||
PointerEvent webEvent = event;
|
||||
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
|
||||
_webSurface->hoverEndEvent(webEvent, _touchDevice);
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::handlePointerEvent(const PointerEvent& event) {
|
||||
if (_inputMode == Touch) {
|
||||
handlePointerEventAsTouch(event);
|
||||
} else {
|
||||
handlePointerEventAsMouse(event);
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::handlePointerEventAsTouch(const PointerEvent& event) {
|
||||
if (_webSurface) {
|
||||
PointerEvent webEvent = event;
|
||||
webEvent.setPos2D(event.getPos2D() * (METERS_TO_INCHES * _dpi));
|
||||
_webSurface->handlePointerEvent(webEvent, _touchDevice);
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::handlePointerEventAsMouse(const PointerEvent& event) {
|
||||
if (!_webSurface) {
|
||||
return;
|
||||
}
|
||||
|
||||
glm::vec2 windowPos = event.getPos2D() * (METERS_TO_INCHES * _dpi);
|
||||
QPointF windowPoint(windowPos.x, windowPos.y);
|
||||
|
||||
Qt::MouseButtons buttons = Qt::NoButton;
|
||||
if (event.getButtons() & PointerEvent::PrimaryButton) {
|
||||
buttons |= Qt::LeftButton;
|
||||
}
|
||||
|
||||
Qt::MouseButton button = Qt::NoButton;
|
||||
if (event.getButton() == PointerEvent::PrimaryButton) {
|
||||
button = Qt::LeftButton;
|
||||
}
|
||||
|
||||
QEvent::Type type;
|
||||
switch (event.getType()) {
|
||||
case PointerEvent::Press:
|
||||
type = QEvent::MouseButtonPress;
|
||||
break;
|
||||
case PointerEvent::Release:
|
||||
type = QEvent::MouseButtonRelease;
|
||||
break;
|
||||
case PointerEvent::Move:
|
||||
type = QEvent::MouseMove;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
QMouseEvent mouseEvent(type, windowPoint, windowPoint, windowPoint, button, buttons, event.getKeyboardModifiers());
|
||||
QCoreApplication::sendEvent(_webSurface->getWindow(), &mouseEvent);
|
||||
}
|
||||
|
||||
void Web3DOverlay::setProperties(const QVariantMap& properties) {
|
||||
Billboard3DOverlay::setProperties(properties);
|
||||
|
||||
auto urlValue = properties["url"];
|
||||
if (urlValue.isValid()) {
|
||||
QString newURL = urlValue.toString();
|
||||
if (newURL != _url) {
|
||||
setURL(newURL);
|
||||
}
|
||||
}
|
||||
|
||||
auto scriptURLValue = properties["scriptURL"];
|
||||
if (scriptURLValue.isValid()) {
|
||||
QString newScriptURL = scriptURLValue.toString();
|
||||
if (newScriptURL != _scriptURL) {
|
||||
setScriptURL(newScriptURL);
|
||||
}
|
||||
}
|
||||
|
||||
auto dpi = properties["dpi"];
|
||||
if (dpi.isValid()) {
|
||||
_dpi = dpi.toFloat();
|
||||
_mayNeedResize = true;
|
||||
}
|
||||
|
||||
auto maxFPS = properties["maxFPS"];
|
||||
if (maxFPS.isValid()) {
|
||||
_desiredMaxFPS = maxFPS.toInt();
|
||||
}
|
||||
|
||||
auto inputModeValue = properties["inputMode"];
|
||||
if (inputModeValue.isValid()) {
|
||||
QString inputModeStr = inputModeValue.toString();
|
||||
if (inputModeStr == "Mouse") {
|
||||
_inputMode = Mouse;
|
||||
} else {
|
||||
_inputMode = Touch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Web3DOverlay overrides the meaning of Planar3DOverlay's dimensions property.
|
||||
/**jsdoc
|
||||
* These are the properties of a <code>web3d</code> {@link Overlays.OverlayType|OverlayType}.
|
||||
* @typedef {object} Overlays.Web3DProperties
|
||||
*
|
||||
* @property {string} type=web3d - Has the value <code>"web3d"</code>. <em>Read-only.</em>
|
||||
* @property {Color} color=255,255,255 - The color of the overlay.
|
||||
* @property {number} alpha=0.7 - The opacity of the overlay, <code>0.0</code> - <code>1.0</code>.
|
||||
* @property {number} pulseMax=0 - The maximum value of the pulse multiplier.
|
||||
* @property {number} pulseMin=0 - The minimum value of the pulse multiplier.
|
||||
* @property {number} pulsePeriod=1 - The duration of the color and alpha pulse, in seconds. A pulse multiplier value goes from
|
||||
* <code>pulseMin</code> to <code>pulseMax</code>, then <code>pulseMax</code> to <code>pulseMin</code> in one period.
|
||||
* @property {number} alphaPulse=0 - If non-zero, the alpha of the overlay is pulsed: the alpha value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {number} colorPulse=0 - If non-zero, the color of the overlay is pulsed: the color value is multiplied by the
|
||||
* current pulse multiplier value each frame. If > 0 the pulse multiplier is applied in phase with the pulse period; if < 0
|
||||
* the pulse multiplier is applied out of phase with the pulse period. (The magnitude of the property isn't otherwise
|
||||
* used.)
|
||||
* @property {boolean} visible=true - If <code>true</code>, the overlay is rendered, otherwise it is not rendered.
|
||||
*
|
||||
* @property {string} name="" - A friendly name for the overlay.
|
||||
* @property {Vec3} position - The position of the overlay center. Synonyms: <code>p1</code>, <code>point</code>, and
|
||||
* <code>start</code>.
|
||||
* @property {Vec3} localPosition - The local position of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>position</code>.
|
||||
* @property {Quat} rotation - The orientation of the overlay. Synonym: <code>orientation</code>.
|
||||
* @property {Quat} localRotation - The orientation of the overlay relative to its parent if the overlay has a
|
||||
* <code>parentID</code> set, otherwise the same value as <code>rotation</code>.
|
||||
* @property {boolean} isSolid=false - Synonyms: <ode>solid</code>, <code>isFilled</code>, and <code>filled</code>.
|
||||
* Antonyms: <code>isWire</code> and <code>wire</code>.
|
||||
* @property {boolean} isDashedLine=false - If <code>true</code>, a dashed line is drawn on the overlay's edges. Synonym:
|
||||
* <code>dashed</code>. Deprecated.
|
||||
* @property {boolean} ignorePickIntersection=false - If <code>true</code>, picks ignore the overlay. <code>ignoreRayIntersection</code> is a synonym.
|
||||
* @property {boolean} drawInFront=false - If <code>true</code>, the overlay is rendered in front of other overlays that don't
|
||||
* have <code>drawInFront</code> set to <code>true</code>, and in front of entities.
|
||||
* @property {boolean} grabbable=false - Signal to grabbing scripts whether or not this overlay can be grabbed.
|
||||
* @property {Uuid} parentID=null - The avatar, entity, or overlay that the overlay is parented to.
|
||||
* @property {number} parentJointIndex=65535 - Integer value specifying the skeleton joint that the overlay is attached to if
|
||||
* <code>parentID</code> is an avatar skeleton. A value of <code>65535</code> means "no joint".
|
||||
*
|
||||
* @property {boolean} isFacingAvatar - If <code>true</code>, the overlay is rotated to face the user's camera about an axis
|
||||
* parallel to the user's avatar's "up" direction.
|
||||
*
|
||||
* @property {string} url - The URL of the Web page to display.
|
||||
* @property {string} scriptURL="" - The URL of a JavaScript file to inject into the Web page.
|
||||
* @property {number} dpi=30 - The dots per inch to display the Web page at, on the overlay.
|
||||
* @property {Vec2} dimensions=1,1 - The size of the overlay to display the Web page on, in meters. Synonyms:
|
||||
* <code>scale</code>, <code>size</code>.
|
||||
* @property {number} maxFPS=10 - The maximum update rate for the Web overlay content, in frames/second.
|
||||
* @property {string} inputMode=Touch - The user input mode to use - either <code>"Touch"</code> or <code>"Mouse"</code>.
|
||||
*/
|
||||
QVariant Web3DOverlay::getProperty(const QString& property) {
|
||||
if (property == "url") {
|
||||
return _url;
|
||||
}
|
||||
if (property == "scriptURL") {
|
||||
return _scriptURL;
|
||||
}
|
||||
if (property == "dpi") {
|
||||
return _dpi;
|
||||
}
|
||||
if (property == "maxFPS") {
|
||||
return _desiredMaxFPS;
|
||||
}
|
||||
|
||||
if (property == "inputMode") {
|
||||
if (_inputMode == Mouse) {
|
||||
return QVariant("Mouse");
|
||||
} else {
|
||||
return QVariant("Touch");
|
||||
}
|
||||
}
|
||||
return Billboard3DOverlay::getProperty(property);
|
||||
}
|
||||
|
||||
void Web3DOverlay::setURL(const QString& url) {
|
||||
if (url != _url) {
|
||||
bool wasWebContent = isWebContent();
|
||||
_url = url;
|
||||
if (_webSurface) {
|
||||
if (wasWebContent && isWebContent()) {
|
||||
// If we're just targeting a new web URL, then switch to that without messing around
|
||||
// with the underlying QML
|
||||
AbstractViewStateInterface::instance()->postLambdaEvent([this] {
|
||||
_webSurface->getRootItem()->setProperty(render::entities::WebEntityRenderer::URL_PROPERTY, _url);
|
||||
_webSurface->getRootItem()->setProperty("scriptURL", _scriptURL);
|
||||
});
|
||||
} else {
|
||||
// If we're switching to or from web content, or between different QML content
|
||||
// we need to destroy and rebuild the entire QML surface
|
||||
AbstractViewStateInterface::instance()->postLambdaEvent([this] {
|
||||
rebuildWebSurface();
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Web3DOverlay::setScriptURL(const QString& scriptURL) {
|
||||
_scriptURL = scriptURL;
|
||||
if (_webSurface) {
|
||||
AbstractViewStateInterface::instance()->postLambdaEvent([this, scriptURL] {
|
||||
if (!_webSurface) {
|
||||
return;
|
||||
}
|
||||
_webSurface->getRootItem()->setProperty("scriptURL", scriptURL);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Web3DOverlay* Web3DOverlay::createClone() const {
|
||||
return new Web3DOverlay(this);
|
||||
}
|
||||
|
||||
void Web3DOverlay::emitScriptEvent(const QVariant& message) {
|
||||
QMetaObject::invokeMethod(this, "scriptEventReceived", Q_ARG(QVariant, message));
|
||||
}
|
|
@ -1,99 +0,0 @@
|
|||
//
|
||||
// Created by Bradley Austin Davis on 2015/08/31
|
||||
// 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_Web3DOverlay_h
|
||||
#define hifi_Web3DOverlay_h
|
||||
|
||||
#include "Billboard3DOverlay.h"
|
||||
|
||||
#include <QTouchEvent>
|
||||
|
||||
#include <PointerEvent.h>
|
||||
|
||||
class OffscreenQmlSurface;
|
||||
|
||||
class Web3DOverlay : public Billboard3DOverlay {
|
||||
Q_OBJECT
|
||||
using Parent = Billboard3DOverlay;
|
||||
|
||||
public:
|
||||
static QString const TYPE;
|
||||
virtual QString getType() const override { return TYPE; }
|
||||
|
||||
Web3DOverlay();
|
||||
Web3DOverlay(const Web3DOverlay* Web3DOverlay);
|
||||
virtual ~Web3DOverlay();
|
||||
|
||||
void setMaxFPS(uint8_t maxFPS);
|
||||
virtual void render(RenderArgs* args) override;
|
||||
virtual const render::ShapeKey getShapeKey() override;
|
||||
|
||||
virtual void update(float deltatime) override;
|
||||
|
||||
QObject* getEventHandler();
|
||||
void setProxyWindow(QWindow* proxyWindow);
|
||||
Q_INVOKABLE void hoverEnterOverlay(const PointerEvent& event);
|
||||
Q_INVOKABLE void hoverLeaveOverlay(const PointerEvent& event);
|
||||
Q_INVOKABLE void handlePointerEvent(const PointerEvent& event);
|
||||
void handlePointerEventAsTouch(const PointerEvent& event);
|
||||
void handlePointerEventAsMouse(const PointerEvent& event);
|
||||
|
||||
// setters
|
||||
void setURL(const QString& url);
|
||||
void setScriptURL(const QString& script);
|
||||
|
||||
void setProperties(const QVariantMap& properties) override;
|
||||
QVariant getProperty(const QString& property) override;
|
||||
|
||||
virtual Web3DOverlay* createClone() const override;
|
||||
|
||||
enum InputMode {
|
||||
Touch,
|
||||
Mouse
|
||||
};
|
||||
|
||||
void buildWebSurface(bool overrideWeb = false);
|
||||
void destroyWebSurface();
|
||||
void onResizeWebSurface();
|
||||
|
||||
public slots:
|
||||
void emitScriptEvent(const QVariant& scriptMessage);
|
||||
|
||||
signals:
|
||||
void scriptEventReceived(const QVariant& message);
|
||||
void webEventReceived(const QVariant& message);
|
||||
void resizeWebSurface();
|
||||
void requestWebSurface(bool overrideWeb);
|
||||
|
||||
protected:
|
||||
Transform evalRenderTransform() override;
|
||||
|
||||
private:
|
||||
void rebuildWebSurface();
|
||||
bool isWebContent() const;
|
||||
|
||||
InputMode _inputMode { Touch };
|
||||
QSharedPointer<OffscreenQmlSurface> _webSurface;
|
||||
bool _cachedWebSurface { false };
|
||||
gpu::TexturePointer _texture;
|
||||
QString _url;
|
||||
QString _scriptURL;
|
||||
float _dpi { 30.0f };
|
||||
int _geometryId { 0 };
|
||||
|
||||
QTouchDevice _touchDevice;
|
||||
|
||||
uint8_t _desiredMaxFPS { 10 };
|
||||
uint8_t _currentMaxFPS { 0 };
|
||||
|
||||
bool _mayNeedResize { false };
|
||||
|
||||
std::vector<QMetaObject::Connection> _connections;
|
||||
};
|
||||
|
||||
#endif // hifi_Web3DOverlay_h
|
|
@ -61,7 +61,7 @@ void RenderForwardTask::build(JobModel& task, const render::Varying& input, rend
|
|||
|
||||
const auto& items = fetchedItems.get0();
|
||||
|
||||
// Extract opaques / transparents / lights / metas / overlays / background
|
||||
// Extract opaques / transparents / lights / metas / layered / background
|
||||
const auto& opaques = items[RenderFetchCullSortTask::OPAQUE_SHAPE];
|
||||
const auto& transparents = items[RenderFetchCullSortTask::TRANSPARENT_SHAPE];
|
||||
const auto& metas = items[RenderFetchCullSortTask::META];
|
||||
|
|
Loading…
Reference in a new issue