Compute the mesh extents for geometry and use them to set the spanner bounds.

This commit is contained in:
Andrzej Kapolka 2014-02-24 17:28:11 -08:00
parent 4dea4b586b
commit 718439014a
6 changed files with 118 additions and 10 deletions

View file

@ -9,6 +9,8 @@
#include <QMutexLocker>
#include <QtDebug>
#include <glm/gtx/transform.hpp>
#include <SharedUtil.h>
#include <MetavoxelUtil.h>
@ -274,6 +276,14 @@ void StaticModelRenderer::init(Spanner* spanner) {
}
void StaticModelRenderer::simulate(float deltaTime) {
// update the bounds
Box bounds;
if (_model->isActive()) {
const Extents& extents = _model->getGeometry()->getFBXGeometry().meshExtents;
bounds = Box(extents.minimum, extents.maximum);
}
static_cast<StaticModel*>(parent())->setBounds(glm::translate(_model->getTranslation()) *
glm::mat4_cast(_model->getRotation()) * glm::scale(_model->getScale()) * bounds);
_model->simulate(deltaTime);
}

View file

@ -1276,6 +1276,8 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
geometry.bindExtents.maximum = glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
geometry.staticExtents.minimum = glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX);
geometry.staticExtents.maximum = glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
geometry.meshExtents.minimum = glm::vec3(FLT_MAX, FLT_MAX, FLT_MAX);
geometry.meshExtents.maximum = glm::vec3(-FLT_MAX, -FLT_MAX, -FLT_MAX);
QVariantHash springs = mapping.value("spring").toHash();
QVariant defaultSpring = springs.value("default");
@ -1287,6 +1289,13 @@ FBXGeometry extractFBXGeometry(const FBXNode& node, const QVariantHash& mapping)
extracted.mesh.springiness = springs.value(models.value(modelID).name, defaultSpring).toFloat();
glm::mat4 modelTransform = getGlobalTransform(parentMap, models, modelID);
// compute the mesh extents from the transformed vertices
foreach (const glm::vec3& vertex, extracted.mesh.vertices) {
glm::vec3 transformedVertex = glm::vec3(modelTransform * glm::vec4(vertex, 1.0f));
geometry.meshExtents.minimum = glm::min(geometry.meshExtents.minimum, transformedVertex);
geometry.meshExtents.maximum = glm::max(geometry.meshExtents.maximum, transformedVertex);
}
// look for textures, material properties
int materialIndex = 0;
int textureIndex = 0;
@ -1704,5 +1713,7 @@ FBXGeometry readSVO(const QByteArray& model) {
geometry.meshes.append(mesh);
geometry.meshExtents.maximum = glm::vec3(1.0f, 1.0f, 1.0f);
return geometry;
}

View file

@ -163,6 +163,7 @@ public:
Extents bindExtents;
Extents staticExtents;
Extents meshExtents;
QVector<FBXAttachment> attachments;
};

View file

@ -269,6 +269,12 @@ const float GRID_BRIGHTNESS = 0.5f;
void MetavoxelEditor::render() {
glDisable(GL_LIGHTING);
MetavoxelTool* tool = getActiveTool();
if (tool) {
tool->render();
}
glDepthMask(GL_FALSE);
glPushMatrix();
@ -277,11 +283,6 @@ void MetavoxelEditor::render() {
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
MetavoxelTool* tool = getActiveTool();
if (tool) {
tool->render();
}
glLineWidth(1.0f);
// center the grid around the camera position on the plane
@ -375,7 +376,14 @@ void BoxSetTool::render() {
resetState();
return;
}
glDepthMask(GL_FALSE);
glPushMatrix();
glm::quat rotation = _editor->getGridRotation();
glm::vec3 axis = glm::axis(rotation);
glRotatef(glm::angle(rotation), axis.x, axis.y, axis.z);
glm::quat inverseRotation = glm::inverse(rotation);
glm::vec3 rayOrigin = inverseRotation * Application::getInstance()->getMouseRayOrigin();
glm::vec3 rayDirection = inverseRotation * Application::getInstance()->getMouseRayDirection();
@ -439,6 +447,8 @@ void BoxSetTool::render() {
glPopMatrix();
}
glPopMatrix();
}
bool BoxSetTool::eventFilter(QObject* watched, QEvent* event) {
@ -524,11 +534,6 @@ InsertSpannerTool::InsertSpannerTool(MetavoxelEditor* editor) :
}
void InsertSpannerTool::simulate(float deltaTime) {
SharedObjectPointer spanner = _editor->getValue().value<SharedObjectPointer>();
static_cast<Spanner*>(spanner.data())->getRenderer()->simulate(deltaTime);
}
void InsertSpannerTool::render() {
_editor->detachValue();
Spanner* spanner = static_cast<Spanner*>(_editor->getValue().value<SharedObjectPointer>().data());
Transformable* transformable = qobject_cast<Transformable*>(spanner);
@ -543,6 +548,11 @@ void InsertSpannerTool::render() {
transformable->setTranslation(rotation * glm::vec3(glm::vec2(rayOrigin + rayDirection * distance), position));
}
spanner->getRenderer()->simulate(deltaTime);
}
void InsertSpannerTool::render() {
Spanner* spanner = static_cast<Spanner*>(_editor->getValue().value<SharedObjectPointer>().data());
const float SPANNER_ALPHA = 0.25f;
spanner->getRenderer()->render(SPANNER_ALPHA);
}

View file

@ -162,6 +162,80 @@ bool Box::intersects(const Box& other) const {
other.maximum.z >= minimum.z && other.minimum.z <= maximum.z;
}
Box operator*(const glm::mat4& matrix, const Box& box) {
// start with the constant component
Box newBox(glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]), glm::vec3(matrix[3][0], matrix[3][1], matrix[3][2]));
// for each element, we choose the minimum or maximum based on the matrix sign
if (matrix[0][0] >= 0.0f) {
newBox.minimum.x += matrix[0][0] * box.minimum.x;
newBox.maximum.x += matrix[0][0] * box.maximum.x;
} else {
newBox.minimum.x += matrix[0][0] * box.maximum.x;
newBox.maximum.x += matrix[0][0] * box.minimum.x;
}
if (matrix[1][0] >= 0.0f) {
newBox.minimum.x += matrix[1][0] * box.minimum.y;
newBox.maximum.x += matrix[1][0] * box.maximum.y;
} else {
newBox.minimum.x += matrix[1][0] * box.maximum.y;
newBox.maximum.x += matrix[1][0] * box.minimum.y;
}
if (matrix[2][0] >= 0.0f) {
newBox.minimum.x += matrix[2][0] * box.minimum.z;
newBox.maximum.x += matrix[2][0] * box.maximum.z;
} else {
newBox.minimum.x += matrix[2][0] * box.maximum.z;
newBox.maximum.x += matrix[2][0] * box.minimum.z;
}
if (matrix[0][1] >= 0.0f) {
newBox.minimum.y += matrix[0][1] * box.minimum.x;
newBox.maximum.y += matrix[0][1] * box.maximum.x;
} else {
newBox.minimum.y += matrix[0][1] * box.maximum.x;
newBox.maximum.y += matrix[0][1] * box.minimum.x;
}
if (matrix[1][1] >= 0.0f) {
newBox.minimum.y += matrix[1][1] * box.minimum.y;
newBox.maximum.y += matrix[1][1] * box.maximum.y;
} else {
newBox.minimum.y += matrix[1][1] * box.maximum.y;
newBox.maximum.y += matrix[1][1] * box.minimum.y;
}
if (matrix[2][1] >= 0.0f) {
newBox.minimum.y += matrix[2][1] * box.minimum.z;
newBox.maximum.y += matrix[2][1] * box.maximum.z;
} else {
newBox.minimum.y += matrix[2][1] * box.maximum.z;
newBox.maximum.y += matrix[2][1] * box.minimum.z;
}
if (matrix[0][2] >= 0.0f) {
newBox.minimum.z += matrix[0][2] * box.minimum.x;
newBox.maximum.z += matrix[0][2] * box.maximum.x;
} else {
newBox.minimum.z += matrix[0][2] * box.maximum.x;
newBox.maximum.z += matrix[0][2] * box.minimum.x;
}
if (matrix[1][2] >= 0.0f) {
newBox.minimum.z += matrix[1][2] * box.minimum.y;
newBox.maximum.z += matrix[1][2] * box.maximum.y;
} else {
newBox.minimum.z += matrix[1][2] * box.maximum.y;
newBox.maximum.z += matrix[1][2] * box.minimum.y;
}
if (matrix[2][2] >= 0.0f) {
newBox.minimum.z += matrix[2][2] * box.minimum.z;
newBox.maximum.z += matrix[2][2] * box.maximum.z;
} else {
newBox.minimum.z += matrix[2][2] * box.maximum.z;
newBox.maximum.z += matrix[2][2] * box.minimum.z;
}
return newBox;
}
QMetaObjectEditor::QMetaObjectEditor(QWidget* parent) : QWidget(parent) {
QVBoxLayout* layout = new QVBoxLayout();
layout->setContentsMargins(QMargins());

View file

@ -48,6 +48,8 @@ public:
DECLARE_STREAMABLE_METATYPE(Box)
Box operator*(const glm::mat4& matrix, const Box& box);
/// Editor for meta-object values.
class QMetaObjectEditor : public QWidget {
Q_OBJECT