Switched from storing Euler angles to using quaternions along with a

quaternion editor.  Also, use a default step of 0.01 for floats/doubles.
This commit is contained in:
Andrzej Kapolka 2014-04-07 15:41:42 -07:00
parent 404b804b2f
commit 15e9d45dc3
9 changed files with 136 additions and 38 deletions

View file

@ -395,7 +395,7 @@ void SphereRenderer::renderUnclipped(float alpha, Mode mode) {
glPushMatrix();
const glm::vec3& translation = sphere->getTranslation();
glTranslatef(translation.x, translation.y, translation.z);
glm::quat rotation = glm::quat(glm::radians(sphere->getRotation()));
glm::quat rotation = sphere->getRotation();
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
@ -418,7 +418,7 @@ void StaticModelRenderer::init(Spanner* spanner) {
applyURL(staticModel->getURL());
connect(spanner, SIGNAL(translationChanged(const glm::vec3&)), SLOT(applyTranslation(const glm::vec3&)));
connect(spanner, SIGNAL(rotationChanged(const glm::vec3&)), SLOT(applyRotation(const glm::vec3&)));
connect(spanner, SIGNAL(rotationChanged(const glm::quat&)), SLOT(applyRotation(const glm::quat&)));
connect(spanner, SIGNAL(scaleChanged(float)), SLOT(applyScale(float)));
connect(spanner, SIGNAL(urlChanged(const QUrl&)), SLOT(applyURL(const QUrl&)));
}
@ -461,8 +461,8 @@ void StaticModelRenderer::applyTranslation(const glm::vec3& translation) {
_model->setTranslation(translation);
}
void StaticModelRenderer::applyRotation(const glm::vec3& rotation) {
_model->setRotation(glm::quat(glm::radians(rotation)));
void StaticModelRenderer::applyRotation(const glm::quat& rotation) {
_model->setRotation(rotation);
}
void StaticModelRenderer::applyScale(float scale) {

View file

@ -189,7 +189,7 @@ protected:
private slots:
void applyTranslation(const glm::vec3& translation);
void applyRotation(const glm::vec3& eulerAngles); // eulerAngles are in degrees
void applyRotation(const glm::quat& rotation);
void applyScale(float scale);
void applyURL(const QUrl& url);

View file

@ -58,7 +58,10 @@ Model::SkinLocations Model::_skinShadowLocations;
void Model::setScale(const glm::vec3& scale) {
glm::vec3 deltaScale = _scale - scale;
if (glm::length2(deltaScale) > EPSILON) {
// decreased epsilon because this wasn't handling scale changes of 0.01
const float SMALLER_EPSILON = EPSILON * 0.0001f;
if (glm::length2(deltaScale) > SMALLER_EPSILON) {
_scale = scale;
rebuildShapes();
}

View file

@ -35,6 +35,7 @@ REGISTER_SIMPLE_TYPE_STREAMER(SharedObjectPointer)
// some types don't quite work with our macro
static int vec3Streamer = Bitstream::registerTypeStreamer(qMetaTypeId<glm::vec3>(), new SimpleTypeStreamer<glm::vec3>());
static int quatStreamer = Bitstream::registerTypeStreamer(qMetaTypeId<glm::quat>(), new SimpleTypeStreamer<glm::quat>());
static int metaObjectStreamer = Bitstream::registerTypeStreamer(qMetaTypeId<const QMetaObject*>(),
new SimpleTypeStreamer<const QMetaObject*>());
@ -352,6 +353,14 @@ Bitstream& Bitstream::operator>>(glm::vec3& value) {
return *this >> value.x >> value.y >> value.z;
}
Bitstream& Bitstream::operator<<(const glm::quat& value) {
return *this << value.w << value.x << value.y << value.z;
}
Bitstream& Bitstream::operator>>(glm::quat& value) {
return *this >> value.w >> value.x >> value.y >> value.z;
}
Bitstream& Bitstream::operator<<(const QByteArray& string) {
*this << string.size();
return write(string.constData(), string.size() * BITS_IN_BYTE);

View file

@ -312,6 +312,9 @@ public:
Bitstream& operator<<(const glm::vec3& value);
Bitstream& operator>>(glm::vec3& value);
Bitstream& operator<<(const glm::quat& value);
Bitstream& operator>>(glm::quat& value);
Bitstream& operator<<(const QByteArray& string);
Bitstream& operator>>(QByteArray& string);

View file

@ -1545,7 +1545,7 @@ void Transformable::setTranslation(const glm::vec3& translation) {
}
}
void Transformable::setRotation(const glm::vec3& rotation) {
void Transformable::setRotation(const glm::quat& rotation) {
if (_rotation != rotation) {
emit rotationChanged(_rotation = rotation);
}

View file

@ -533,7 +533,7 @@ public:
class Transformable : public Spanner {
Q_OBJECT
Q_PROPERTY(glm::vec3 translation MEMBER _translation WRITE setTranslation NOTIFY translationChanged)
Q_PROPERTY(glm::vec3 rotation MEMBER _rotation WRITE setRotation NOTIFY rotationChanged)
Q_PROPERTY(glm::quat rotation MEMBER _rotation WRITE setRotation NOTIFY rotationChanged)
Q_PROPERTY(float scale MEMBER _scale WRITE setScale NOTIFY scaleChanged)
public:
@ -543,8 +543,8 @@ public:
void setTranslation(const glm::vec3& translation);
const glm::vec3& getTranslation() const { return _translation; }
void setRotation(const glm::vec3& rotation);
const glm::vec3& getRotation() const { return _rotation; }
void setRotation(const glm::quat& rotation);
const glm::quat& getRotation() const { return _rotation; }
void setScale(float scale);
float getScale() const { return _scale; }
@ -552,13 +552,13 @@ public:
signals:
void translationChanged(const glm::vec3& translation);
void rotationChanged(const glm::vec3& rotation);
void rotationChanged(const glm::quat& rotation);
void scaleChanged(float scale);
private:
glm::vec3 _translation;
glm::vec3 _rotation; // Euler Angles in degrees
glm::quat _rotation;
float _scale;
};

View file

@ -52,6 +52,7 @@ public:
DoubleEditor::DoubleEditor(QWidget* parent) : QDoubleSpinBox(parent) {
setMinimum(-FLT_MAX);
setMaximum(FLT_MAX);
setSingleStep(0.01);
}
DelegatingItemEditorFactory::DelegatingItemEditorFactory() :
@ -127,6 +128,12 @@ static QItemEditorCreatorBase* createVec3EditorCreator() {
return creator;
}
static QItemEditorCreatorBase* createQuatEditorCreator() {
QItemEditorCreatorBase* creator = new LazyItemEditorCreator<QuatEditor>();
getItemEditorFactory()->registerEditor(qMetaTypeId<glm::quat>(), creator);
return creator;
}
static QItemEditorCreatorBase* createParameterizedURLEditorCreator() {
QItemEditorCreatorBase* creator = new LazyItemEditorCreator<ParameterizedURLEditor>();
getItemEditorFactory()->registerEditor(qMetaTypeId<ParameterizedURL>(), creator);
@ -138,6 +145,7 @@ static QItemEditorCreatorBase* qMetaObjectEditorCreator = createQMetaObjectEdito
static QItemEditorCreatorBase* qColorEditorCreator = createQColorEditorCreator();
static QItemEditorCreatorBase* qUrlEditorCreator = createQUrlEditorCreator();
static QItemEditorCreatorBase* vec3EditorCreator = createVec3EditorCreator();
static QItemEditorCreatorBase* quatEditorCreator = createQuatEditorCreator();
static QItemEditorCreatorBase* parameterizedURLEditorCreator = createParameterizedURLEditorCreator();
QByteArray signal(const char* signature) {
@ -380,7 +388,7 @@ void QUrlEditor::updateSettings() {
QSettings().setValue("editorURLs", urls);
}
Vec3Editor::Vec3Editor(QWidget* parent) : QWidget(parent) {
BaseVec3Editor::BaseVec3Editor(QWidget* parent) : QWidget(parent) {
QHBoxLayout* layout = new QHBoxLayout();
layout->setContentsMargins(QMargins());
setLayout(layout);
@ -390,26 +398,59 @@ Vec3Editor::Vec3Editor(QWidget* parent) : QWidget(parent) {
layout->addWidget(_z = createComponentBox());
}
void Vec3Editor::setVector(const glm::vec3& vector) {
_vector = vector;
_x->setValue(vector.x);
_y->setValue(vector.y);
_z->setValue(vector.z);
}
void Vec3Editor::updateVector() {
emit vectorChanged(_vector = glm::vec3(_x->value(), _y->value(), _z->value()));
}
QDoubleSpinBox* Vec3Editor::createComponentBox() {
QDoubleSpinBox* BaseVec3Editor::createComponentBox() {
QDoubleSpinBox* box = new QDoubleSpinBox();
box->setMinimum(-FLT_MAX);
box->setMaximum(FLT_MAX);
box->setMinimumWidth(50);
connect(box, SIGNAL(valueChanged(double)), SLOT(updateVector()));
connect(box, SIGNAL(valueChanged(double)), SLOT(updateValue()));
return box;
}
Vec3Editor::Vec3Editor(QWidget* parent) : BaseVec3Editor(parent) {
_x->setSingleStep(0.01);
_y->setSingleStep(0.01);
_z->setSingleStep(0.01);
}
static void setComponentValue(QDoubleSpinBox* box, double value) {
box->blockSignals(true);
box->setValue(value);
box->blockSignals(false);
}
void Vec3Editor::setValue(const glm::vec3& value) {
_value = value;
setComponentValue(_x, value.x);
setComponentValue(_y, value.y);
setComponentValue(_z, value.z);
}
void Vec3Editor::updateValue() {
emit valueChanged(_value = glm::vec3(_x->value(), _y->value(), _z->value()));
}
QuatEditor::QuatEditor(QWidget* parent) : BaseVec3Editor(parent) {
_x->setRange(-180.0, 180.0);
_y->setRange(-90.0, 90.0);
_z->setRange(-180.0, 180.0);
_x->setWrapping(true);
_y->setWrapping(true);
_z->setWrapping(true);
}
void QuatEditor::setValue(const glm::quat& value) {
glm::vec3 eulers = glm::degrees(safeEulerAngles(_value = value));
setComponentValue(_x, eulers.x);
setComponentValue(_y, eulers.y);
setComponentValue(_z, eulers.z);
}
void QuatEditor::updateValue() {
emit valueChanged(_value = glm::quat(glm::radians(glm::vec3(_x->value(), _y->value(), _z->value()))));
}
ParameterizedURL::ParameterizedURL(const QUrl& url, const ScriptHash& parameters) :
_url(url),
_parameters(parameters) {

View file

@ -142,10 +142,31 @@ private:
QUrl _url;
};
/// Editor for vector values.
class Vec3Editor : public QWidget {
/// Base class for Vec3Editor and QuatEditor.
class BaseVec3Editor : public QWidget {
Q_OBJECT
Q_PROPERTY(glm::vec3 vector MEMBER _vector WRITE setVector NOTIFY vectorChanged USER true)
public:
BaseVec3Editor(QWidget* parent);
protected slots:
virtual void updateValue() = 0;
protected:
QDoubleSpinBox* createComponentBox();
QDoubleSpinBox* _x;
QDoubleSpinBox* _y;
QDoubleSpinBox* _z;
};
/// Editor for vector values.
class Vec3Editor : public BaseVec3Editor {
Q_OBJECT
Q_PROPERTY(glm::vec3 value MEMBER _value WRITE setValue NOTIFY valueChanged USER true)
public:
@ -153,24 +174,45 @@ public:
signals:
void vectorChanged(const glm::vec3& vector);
void valueChanged(const glm::vec3& vector);
public slots:
void setVector(const glm::vec3& vector);
void setValue(const glm::vec3& vector);
private slots:
protected:
void updateVector();
virtual void updateValue();
private:
QDoubleSpinBox* createComponentBox();
glm::vec3 _value;
};
/// Editor for quaternion values.
class QuatEditor : public BaseVec3Editor {
Q_OBJECT
Q_PROPERTY(glm::quat value MEMBER _value WRITE setValue NOTIFY valueChanged USER true)
public:
QDoubleSpinBox* _x;
QDoubleSpinBox* _y;
QDoubleSpinBox* _z;
glm::vec3 _vector;
QuatEditor(QWidget* parent);
signals:
void valueChanged(const glm::quat& value);
public slots:
void setValue(const glm::quat& value);
protected:
virtual void updateValue();
private:
glm::quat _value;
};
typedef QHash<QScriptString, QVariant> ScriptHash;