summaryrefslogtreecommitdiffstats
path: root/src/datavisualization/engine/abstract3drenderer.cpp
diff options
context:
space:
mode:
authorMiikka Heikkinen <miikka.heikkinen@digia.com>2014-09-09 11:30:15 +0300
committerMiikka Heikkinen <miikka.heikkinen@digia.com>2014-09-10 12:30:54 +0300
commitddb9be979d93b7e17f1067dc6056de54d9828b29 (patch)
treedf612c56e4a804481297ae55b29f0ee379c5f8ab /src/datavisualization/engine/abstract3drenderer.cpp
parentbb30ea555c71604de9a2bc5096fa35c9532b26bd (diff)
Limit volume to axis ranges
The volume object that would go partially outside axis ranges is scale and repositioned so that it only renders the portion that is inside the axis ranges. Change-Id: I792494e437998ba6276f58fab645767276c1476d Reviewed-by: Mika Salmela <mika.salmela@digia.com>
Diffstat (limited to 'src/datavisualization/engine/abstract3drenderer.cpp')
-rw-r--r--src/datavisualization/engine/abstract3drenderer.cpp94
1 files changed, 70 insertions, 24 deletions
diff --git a/src/datavisualization/engine/abstract3drenderer.cpp b/src/datavisualization/engine/abstract3drenderer.cpp
index 18384872..305d3df0 100644
--- a/src/datavisualization/engine/abstract3drenderer.cpp
+++ b/src/datavisualization/engine/abstract3drenderer.cpp
@@ -960,7 +960,7 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
newItem->setRenderer(this);
newItem->setItemPointer(item); // Store pointer for render item updates
newItem->setMesh(item->meshFile());
- newItem->setPosition(item->position());
+ newItem->setOrigPosition(item->position());
newItem->setOrigScaling(item->scaling());
newItem->setScalingAbsolute(item->isScalingAbsolute());
newItem->setPositionAbsolute(item->isPositionAbsolute());
@@ -1013,7 +1013,7 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
newItem->setUseHighDefShader(volumeItem->useHighDefShader());
#endif
}
- recalculateCustomItemScaling(newItem);
+ recalculateCustomItemScalingAndPos(newItem);
newItem->setRotation(item->rotation());
#if !defined(QT_OPENGL_ES_2)
// In OpenGL ES we simply draw volumes as regular custom item placeholders.
@@ -1025,9 +1025,6 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
}
newItem->setTexture(texture);
item->d_ptr->clearTextureImage();
- QVector3D translation = convertPositionToTranslation(newItem->position(),
- newItem->isPositionAbsolute());
- newItem->setTranslation(translation);
newItem->setVisible(item->isVisible());
newItem->setShadowCasting(item->isShadowCasting());
newItem->setFacingCamera(facingCamera);
@@ -1035,25 +1032,71 @@ CustomRenderItem *Abstract3DRenderer::addCustomItem(QCustom3DItem *item)
return newItem;
}
-void Abstract3DRenderer::recalculateCustomItemScaling(CustomRenderItem *item)
+void Abstract3DRenderer::recalculateCustomItemScalingAndPos(CustomRenderItem *item)
{
if (!m_polarGraph && !item->isLabel() && !item->isScalingAbsolute()
&& !item->isPositionAbsolute()) {
QVector3D scale = item->origScaling() / 2.0f;
- QVector3D pos = item->position();
+ QVector3D pos = item->origPosition();
QVector3D minBounds(pos.x() - scale.x(),
pos.y() - scale.y(),
- pos.z() - scale.z());
+ pos.z() + scale.z());
QVector3D maxBounds(pos.x() + scale.x(),
pos.y() + scale.y(),
- pos.z() + scale.z());
- QVector3D min = convertPositionToTranslation(minBounds, false);
- QVector3D max = convertPositionToTranslation(maxBounds, false);
- item->setScaling(QVector3D(qAbs(max.x() - min.x()), qAbs(max.y() - min.y()),
- qAbs(max.z() - min.z())) / 2.0f);
+ pos.z() - scale.z());
+ QVector3D minCorner = convertPositionToTranslation(minBounds, false);
+ QVector3D maxCorner = convertPositionToTranslation(maxBounds, false);
+ scale = QVector3D(qAbs(maxCorner.x() - minCorner.x()),
+ qAbs(maxCorner.y() - minCorner.y()),
+ qAbs(maxCorner.z() - minCorner.z())) / 2.0f;
+ if (item->isVolume()) {
+ // Only volume items need to scale and reposition according to bounds
+ QVector3D minBoundsNormal = minCorner;
+ QVector3D maxBoundsNormal = maxCorner;
+ // getVisibleItemBounds returns bounds normalized for fragment shader [-1,1]
+ // Y and Z are also flipped.
+ getVisibleItemBounds(minBoundsNormal, maxBoundsNormal);
+ item->setMinBounds(minBoundsNormal);
+ item->setMaxBounds(maxBoundsNormal);
+ // For scaling calculations, we want [0,1] normalized values
+ minBoundsNormal = item->minBoundsNormal();
+ maxBoundsNormal = item->maxBoundsNormal();
+
+ // Rescale and reposition the item so that it doesn't go over the edges
+ QVector3D adjScaling =
+ QVector3D(scale.x() * (maxBoundsNormal.x() - minBoundsNormal.x()),
+ scale.y() * (maxBoundsNormal.y() - minBoundsNormal.y()),
+ scale.z() * (maxBoundsNormal.z() - minBoundsNormal.z()));
+
+ item->setScaling(adjScaling);
+
+ QVector3D adjPos = item->origPosition();
+ QVector3D dataExtents = QVector3D(maxBounds.x() - minBounds.x(),
+ maxBounds.y() - minBounds.y(),
+ maxBounds.z() - minBounds.z()) / 2.0f;
+ adjPos.setX(adjPos.x() + (dataExtents.x() * minBoundsNormal.x())
+ - (dataExtents.x() * (1.0f - maxBoundsNormal.x())));
+ adjPos.setY(adjPos.y() + (dataExtents.y() * minBoundsNormal.y())
+ - (dataExtents.y() * (1.0f - maxBoundsNormal.y())));
+ adjPos.setZ(adjPos.z() + (dataExtents.z() * minBoundsNormal.z())
+ - (dataExtents.z() * (1.0f - maxBoundsNormal.z())));
+ item->setPosition(adjPos);
+ } else {
+ // Only scale for non-volume items, and do not readjust position
+ item->setScaling(scale);
+ item->setPosition(item->origPosition());
+ }
} else {
item->setScaling(item->origScaling());
+ item->setPosition(item->origPosition());
+ if (item->isVolume()) {
+ item->setMinBounds(-1.0f * zeroVector);
+ item->setMaxBounds(oneVector);
+ }
}
+ QVector3D translation = convertPositionToTranslation(item->position(),
+ item->isPositionAbsolute());
+ item->setTranslation(translation);
}
void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
@@ -1064,11 +1107,10 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
item->d_ptr->m_dirtyBits.meshDirty = false;
}
if (item->d_ptr->m_dirtyBits.positionDirty) {
- renderItem->setPosition(item->position());
+ renderItem->setOrigPosition(item->position());
renderItem->setPositionAbsolute(item->isPositionAbsolute());
- QVector3D translation = convertPositionToTranslation(renderItem->position(),
- renderItem->isPositionAbsolute());
- renderItem->setTranslation(translation);
+ if (!item->d_ptr->m_dirtyBits.scalingDirty)
+ recalculateCustomItemScalingAndPos(renderItem);
item->d_ptr->m_dirtyBits.positionDirty = false;
}
if (item->d_ptr->m_dirtyBits.scalingDirty) {
@@ -1099,7 +1141,7 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
item->d_ptr->clearTextureImage();
renderItem->setOrigScaling(scaling);
}
- recalculateCustomItemScaling(renderItem);
+ recalculateCustomItemScalingAndPos(renderItem);
item->d_ptr->m_dirtyBits.scalingDirty = false;
}
if (item->d_ptr->m_dirtyBits.rotationDirty) {
@@ -1195,10 +1237,7 @@ void Abstract3DRenderer::updateCustomItem(CustomRenderItem *renderItem)
void Abstract3DRenderer::updateCustomItemPositions()
{
foreach (CustomRenderItem *renderItem, m_customRenderCache) {
- recalculateCustomItemScaling(renderItem);
- QVector3D translation = convertPositionToTranslation(renderItem->position(),
- renderItem->isPositionAbsolute());
- renderItem->setTranslation(translation);
+ recalculateCustomItemScalingAndPos(renderItem);
}
}
@@ -1243,7 +1282,7 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state,
continue;
}
- // Check if the render item is in data coordinates and not within axis ranges, and skip drawing if it is
+ // If the render item is in data coordinates and not within axis ranges, skip it
if (!item->isPositionAbsolute()
&& (item->position().x() < m_axisCacheX.min()
|| item->position().x() > m_axisCacheX.max()
@@ -1353,9 +1392,12 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state,
// Set shadowless shader bindings
#if !defined(QT_OPENGL_ES_2)
if (item->isVolume()) {
- // Volume shaders repurpose light position for camera position relative to item
QVector3D cameraPos = m_cachedScene->activeCamera()->position();
cameraPos = MVPMatrix.inverted().map(cameraPos);
+ // Adjust camera position according to min/max bounds
+ cameraPos = cameraPos
+ + ((oneVector - cameraPos) * item->minBoundsNormal())
+ - ((oneVector + cameraPos) * (oneVector - item->maxBoundsNormal()));
shader->setUniformValue(shader->cameraPositionRelativeToModel(), -cameraPos);
GLint color8Bit = (item->textureFormat() == QImage::Format_Indexed8) ? 1 : 0;
if (color8Bit) {
@@ -1366,6 +1408,10 @@ void Abstract3DRenderer::drawCustomItems(RenderingState state,
shader->setUniformValue(shader->alphaMultiplier(), item->alphaMultiplier());
shader->setUniformValue(shader->preserveOpacity(),
item->preserveOpacity() ? 1 : 0);
+
+ shader->setUniformValue(shader->minBounds(), item->minBounds());
+ shader->setUniformValue(shader->maxBounds(), item->maxBounds());
+
if (shader == m_volumeTextureSliceShader) {
QVector3D slices((float(item->sliceIndexX()) + 0.5f)
/ float(item->textureWidth()) * 2.0 - 1.0,