Refactor billboarding into Billboardable class.

This commit is contained in:
Zander Otavka 2015-08-07 02:34:56 -07:00
parent 3dcfa84a87
commit 3356bf31ac
8 changed files with 115 additions and 62 deletions

View File

@ -41,14 +41,20 @@
var overlays = {};
var panels = {};
var overlayTypes,
Overlay,
var overlayTypes;
// Abstract overlay types
var Overlay,
Overlay2D,
Base3DOverlay,
Planar3DOverlay,
Billboard3DOverlay,
Volume3DOverlay;
// Multiple inheritance mixins
var PanelAttachable,
Billboardable;
//
// Create a new JavaScript object for an overlay of given ID.
@ -232,10 +238,6 @@
return that;
}
// Supports multiple inheritance of properties. Just `concat` them onto the end of the
// properties list.
var PANEL_ATTACHABLE_FIELDS = ["offsetPosition", "offsetRotation", "offsetScale"];
Overlay = (function() {
var that = function(type, params) {
if (type && params) {
@ -286,6 +288,11 @@
]);
})();
// Supports multiple inheritance of properties. Just `concat` them onto the end of the
// properties list.
PanelAttachable = ["offsetPosition", "offsetRotation", "offsetScale"];
Billboardable = ["isFacingAvatar"];
Overlay2D = generateOverlayClass(Overlay, ABSTRACT, [
"bounds", "x", "y", "width", "height"
]);
@ -300,8 +307,7 @@
]);
Billboard3DOverlay = generateOverlayClass(Planar3DOverlay, ABSTRACT, [
"isFacingAvatar"
].concat(PANEL_ATTACHABLE_FIELDS));
].concat(PanelAttachable).concat(Billboardable));
Billboard3DOverlay.prototype.isPanelAttachable = function() { return true; };
Volume3DOverlay = generateOverlayClass(Base3DOverlay, ABSTRACT, [
@ -382,10 +388,11 @@
that.prototype.constructor = that;
[
"position", "positionBinding", "rotation", "rotationBinding", "scale",
"offsetPosition", "offsetRotation", "offsetScale", "visible", "isFacingAvatar"
].forEach(function(prop) {
var props = [
"position", "positionBinding", "rotation", "rotationBinding", "scale", "visible"
].concat(PanelAttachable).concat(Billboardable)
props.forEach(function(prop) {
Object.defineProperty(that.prototype, prop, {
get: function() {
return Overlays.getPanelProperty(this._id, prop);

View File

@ -15,26 +15,23 @@
Billboard3DOverlay::Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay) :
Planar3DOverlay(billboard3DOverlay),
PanelAttachable(*billboard3DOverlay),
_isFacingAvatar(billboard3DOverlay->_isFacingAvatar)
Billboardable(*billboard3DOverlay)
{
}
void Billboard3DOverlay::setProperties(const QScriptValue &properties) {
Planar3DOverlay::setProperties(properties);
PanelAttachable::setProperties(properties);
QScriptValue isFacingAvatarValue = properties.property("isFacingAvatar");
if (isFacingAvatarValue.isValid()) {
_isFacingAvatar = isFacingAvatarValue.toVariant().toBool();
}
Billboardable::setProperties(properties);
}
QScriptValue Billboard3DOverlay::getProperty(const QString &property) {
if (property == "isFacingAvatar") {
return _isFacingAvatar;
QScriptValue value;
value = Billboardable::getProperty(_scriptEngine, property);
if (value.isValid()) {
return value;
}
QScriptValue value = PanelAttachable::getProperty(_scriptEngine, property);
value = PanelAttachable::getProperty(_scriptEngine, property);
if (value.isValid()) {
return value;
}
@ -44,15 +41,7 @@ QScriptValue Billboard3DOverlay::getProperty(const QString &property) {
void Billboard3DOverlay::applyTransformTo(Transform& transform, bool force) {
if (force || usecTimestampNow() > _transformExpiry) {
PanelAttachable::applyTransformTo(transform, true);
if (_isFacingAvatar) {
glm::vec3 billboardPos = transform.getTranslation();
glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition();
glm::vec3 look = cameraPos - billboardPos;
float elevation = -asinf(look.y / glm::length(look));
float azimuth = atan2f(look.x, look.z);
glm::quat rotation(glm::vec3(elevation, azimuth, 0));
transform.setRotation(rotation);
transform.postRotate(getOffsetRotation());
}
transformLookAtCamera(transform);
transform.postRotate(getOffsetRotation());
}
}

View File

@ -14,25 +14,20 @@
#include "Planar3DOverlay.h"
#include "PanelAttachable.h"
#include "Billboardable.h"
class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable {
class Billboard3DOverlay : public Planar3DOverlay, public PanelAttachable, public Billboardable {
Q_OBJECT
public:
Billboard3DOverlay() {}
Billboard3DOverlay(const Billboard3DOverlay* billboard3DOverlay);
bool getIsFacingAvatar() const { return _isFacingAvatar; }
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
virtual void setProperties(const QScriptValue& properties);
virtual QScriptValue getProperty(const QString& property);
protected:
virtual void applyTransformTo(Transform& transform, bool force = false);
private:
bool _isFacingAvatar = false;
};
#endif // hifi_Billboard3DOverlay_h

View File

@ -0,0 +1,40 @@
//
// Billboardable.cpp
// 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
//
#include "Billboardable.h"
#include <Application.h>
void Billboardable::setProperties(const QScriptValue &properties) {
QScriptValue isFacingAvatar = properties.property("isFacingAvatar");
if (isFacingAvatar.isValid()) {
setIsFacingAvatar(isFacingAvatar.toVariant().toBool());
}
}
QScriptValue Billboardable::getProperty(QScriptEngine* scriptEngine, const QString &property) {
if (property == "isFacingAvatar") {
return isFacingAvatar();
}
return QScriptValue();
}
void Billboardable::transformLookAtCamera(Transform& transform) {
if (_isFacingAvatar) {
glm::vec3 billboardPos = transform.getTranslation();
glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition();
glm::vec3 look = cameraPos - billboardPos;
float elevation = -asinf(look.y / glm::length(look));
float azimuth = atan2f(look.x, look.z);
glm::quat rotation(glm::vec3(elevation, azimuth, 0));
transform.setRotation(rotation);
}
}

View File

@ -0,0 +1,35 @@
//
// 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 <QScriptValue>
#include <QScriptEngine>
#include <Transform.h>
class Billboardable {
public:
bool isFacingAvatar() const { return _isFacingAvatar; }
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
protected:
void setProperties(const QScriptValue& properties);
QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property);
void transformLookAtCamera(Transform& transform);
private:
bool _isFacingAvatar = false;
};
#endif // hifi_Billboardable_h

View File

@ -86,9 +86,6 @@ QScriptValue OverlayPanel::getProperty(const QString &property) {
if (property == "visible") {
return getVisible();
}
if (property == "isFacingAvatar") {
return getIsFacingAvatar();
}
if (property == "children") {
QScriptValue array = _scriptEngine->newArray(_children.length());
for (int i = 0; i < _children.length(); i++) {
@ -97,11 +94,16 @@ QScriptValue OverlayPanel::getProperty(const QString &property) {
return array;
}
QScriptValue value = Billboardable::getProperty(_scriptEngine, property);
if (value.isValid()) {
return value;
}
return PanelAttachable::getProperty(_scriptEngine, property);
}
void OverlayPanel::setProperties(const QScriptValue &properties) {
PanelAttachable::setProperties(properties);
Billboardable::setProperties(properties);
QScriptValue position = properties.property("position");
if (position.isValid() &&
@ -157,11 +159,6 @@ void OverlayPanel::setProperties(const QScriptValue &properties) {
if (visible.isValid()) {
setVisible(visible.toVariant().toBool());
}
QScriptValue isFacingAvatar = properties.property("isFacingAvatar");
if (isFacingAvatar.isValid()) {
setIsFacingAvatar(isFacingAvatar.toVariant().toBool());
}
}
void OverlayPanel::applyTransformTo(Transform& transform, bool force) {
@ -176,16 +173,8 @@ void OverlayPanel::applyTransformTo(Transform& transform, bool force) {
transform.postRotate(getOffsetRotation());
transform.postScale(getOffsetScale());
}
if (_isFacingAvatar) {
glm::vec3 billboardPos = transform.getTranslation();
glm::vec3 cameraPos = Application::getInstance()->getCamera()->getPosition();
glm::vec3 look = cameraPos - billboardPos;
float elevation = -asinf(look.y / glm::length(look));
float azimuth = atan2f(look.x, look.z);
glm::quat rotation(glm::vec3(elevation, azimuth, 0.0f));
transform.setRotation(rotation);
transform.postRotate(getOffsetRotation());
}
transformLookAtCamera(transform);
transform.postRotate(getOffsetRotation());
}
}

View File

@ -20,6 +20,7 @@
#include <QUuid>
#include "PanelAttachable.h"
#include "Billboardable.h"
class PropertyBinding {
public:
@ -33,7 +34,7 @@ QScriptValue propertyBindingToScriptValue(QScriptEngine* engine, const PropertyB
void propertyBindingFromScriptValue(const QScriptValue& object, PropertyBinding& value);
class OverlayPanel : public QObject, public PanelAttachable {
class OverlayPanel : public QObject, public PanelAttachable, public Billboardable {
Q_OBJECT
public:
@ -46,7 +47,6 @@ public:
glm::quat getRotation() const { return _transform.getRotation(); }
glm::vec3 getScale() const { return _transform.getScale(); }
bool getVisible() const { return _visible; }
bool getIsFacingAvatar() const { return _isFacingAvatar; }
// setters
void setPosition(const glm::vec3& position) { _transform.setTranslation(position); }
@ -54,7 +54,6 @@ public:
void setScale(float scale) { _transform.setScale(scale); }
void setScale(const glm::vec3& scale) { _transform.setScale(scale); }
void setVisible(bool visible) { _visible = visible; }
void setIsFacingAvatar(bool isFacingAvatar) { _isFacingAvatar = isFacingAvatar; }
const QList<unsigned int>& getChildren() { return _children; }
void addChild(unsigned int childId);
@ -78,7 +77,6 @@ private:
QUuid _rotationBindEntity;
bool _visible = true;
bool _isFacingAvatar = false;
QList<unsigned int> _children;
QScriptEngine* _scriptEngine;

View File

@ -38,10 +38,10 @@ public:
void setOffsetScale(float scale) { _offset.setScale(scale); }
void setOffsetScale(const glm::vec3& scale) { _offset.setScale(scale); }
protected:
QScriptValue getProperty(QScriptEngine* scriptEngine, const QString& property);
void setProperties(const QScriptValue& properties);
protected:
virtual void applyTransformTo(Transform& transform, bool force = false);
quint64 _transformExpiry = 0;