From d493ae2fcef2ed63413b78e6afc16d13c82131ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomi=20Korpip=C3=A4=C3=A4?= Date: Wed, 6 Nov 2013 10:28:35 +0200 Subject: Added GL_POINTS for scatter Task-number: QTRD-2535 Change-Id: Icf2d4ab1d8a46ea38864d2b587411ed05c58de38 Change-Id: Icf2d4ab1d8a46ea38864d2b587411ed05c58de38 Reviewed-by: Miikka Heikkinen --- src/datavisualization/engine/drawer.cpp | 30 ++- src/datavisualization/engine/drawer_p.h | 2 + src/datavisualization/engine/q3dcamera.cpp | 6 +- src/datavisualization/engine/q3dcamera.h | 6 +- src/datavisualization/engine/q3dscatter.cpp | 4 +- .../engine/scatter3dcontroller.cpp | 16 +- .../engine/scatter3dcontroller_p.h | 2 - src/datavisualization/engine/scatter3drenderer.cpp | 204 +++++++++++++-------- src/datavisualization/engine/scatter3drenderer_p.h | 2 +- 9 files changed, 177 insertions(+), 95 deletions(-) (limited to 'src/datavisualization/engine') diff --git a/src/datavisualization/engine/drawer.cpp b/src/datavisualization/engine/drawer.cpp index 8643d6d9..93336e96 100644 --- a/src/datavisualization/engine/drawer.cpp +++ b/src/datavisualization/engine/drawer.cpp @@ -41,17 +41,22 @@ StaticLibInitializer staticLibInitializer; QT_DATAVISUALIZATION_BEGIN_NAMESPACE +// Vertex array buffer for point +const GLfloat point_data[] = {0.0f, 0.0f, 0.0f}; + Drawer::Drawer(const Theme &theme, const QFont &font, QDataVis::LabelStyle style) : m_theme(theme), m_font(font), m_style(style), - m_textureHelper(0) + m_textureHelper(0), + m_pointbuffer(0) { } Drawer::~Drawer() { delete m_textureHelper; + glDeleteBuffers(1, &m_pointbuffer); } void Drawer::initializeOpenGL() @@ -163,6 +168,29 @@ void Drawer::drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object) glDisableVertexAttribArray(shader->posAtt()); } +void Drawer::drawPoint(ShaderHelper *shader) +{ + // Generate vertex buffer for point if it does not exist + if (!m_pointbuffer) { + glGenBuffers(1, &m_pointbuffer); + glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer); + glBufferData(GL_ARRAY_BUFFER, sizeof(point_data), point_data, GL_STATIC_DRAW); + } + + // 1st attribute buffer : vertices + glEnableVertexAttribArray(shader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_pointbuffer); + glVertexAttribPointer(shader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void*)0); + + // Draw the point + glDrawArrays(GL_POINTS, 0, 1); + + // Free buffers + glBindBuffer(GL_ARRAY_BUFFER, 0); + + glDisableVertexAttribArray(shader->posAtt()); +} + void Drawer::drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem, const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix, const QVector3D &positionComp, const QVector3D &rotation, diff --git a/src/datavisualization/engine/drawer_p.h b/src/datavisualization/engine/drawer_p.h index 933b20c7..c4bc8d1b 100644 --- a/src/datavisualization/engine/drawer_p.h +++ b/src/datavisualization/engine/drawer_p.h @@ -77,6 +77,7 @@ public: void drawObject(ShaderHelper *shader, AbstractObjectHelper *object, GLuint textureId = 0, GLuint depthTextureId = 0); void drawSurfaceGrid(ShaderHelper *shader, SurfaceObject *object); + void drawPoint(ShaderHelper *shader); void drawLabel(const AbstractRenderItem &item, const LabelItem &labelItem, const QMatrix4x4 &viewmatrix, const QMatrix4x4 &projectionmatrix, const QVector3D &positionComp, const QVector3D &rotation, GLfloat itemHeight, @@ -96,6 +97,7 @@ private: QFont m_font; QDataVis::LabelStyle m_style; TextureHelper *m_textureHelper; + GLuint m_pointbuffer; }; QT_DATAVISUALIZATION_END_NAMESPACE diff --git a/src/datavisualization/engine/q3dcamera.cpp b/src/datavisualization/engine/q3dcamera.cpp index fe452739..d2bbe275 100644 --- a/src/datavisualization/engine/q3dcamera.cpp +++ b/src/datavisualization/engine/q3dcamera.cpp @@ -326,7 +326,7 @@ void Q3DCamera::setViewMatrix(const QMatrix4x4 &viewMatrix) * rotations. If set to false, no automatic recalculation is done and the view matrix can be set using the * Q3DMatrix::viewMatrix property. */ -bool Q3DCamera::isViewMatrixAutoUpdateEnabled() +bool Q3DCamera::isViewMatrixAutoUpdateEnabled() const { return d_ptr->m_isViewMatrixUpdateActive; } @@ -345,7 +345,7 @@ void Q3DCamera::setViewMatrixAutoUpdateEnabled(bool isEnabled) * \note The base camera orientation set by setBaseOrientation() will affect * the presets as all calculations are based on those values. */ -QDataVis::CameraPreset Q3DCamera::cameraPreset() +QDataVis::CameraPreset Q3DCamera::cameraPreset() const { return d_ptr->m_activePreset; } @@ -491,7 +491,7 @@ void Q3DCamera::setCameraPreset(QDataVis::CameraPreset preset) * This property contains the the camera zoom level in percentages. * 100% means there is no zoom in or out set in the camera. */ -int Q3DCamera::zoomLevel() +int Q3DCamera::zoomLevel() const { return d_ptr->m_zoomLevel; } diff --git a/src/datavisualization/engine/q3dcamera.h b/src/datavisualization/engine/q3dcamera.h index ee750cec..8e93ebb2 100644 --- a/src/datavisualization/engine/q3dcamera.h +++ b/src/datavisualization/engine/q3dcamera.h @@ -72,13 +72,13 @@ public: QMatrix4x4 viewMatrix() const; void setViewMatrix(const QMatrix4x4 &viewMatrix); - bool isViewMatrixAutoUpdateEnabled(); + bool isViewMatrixAutoUpdateEnabled() const; void setViewMatrixAutoUpdateEnabled(bool isEnabled); - QDataVis::CameraPreset cameraPreset(); + QDataVis::CameraPreset cameraPreset() const; void setCameraPreset(QDataVis::CameraPreset preset); - int zoomLevel(); + int zoomLevel() const; void setZoomLevel(int zoomLevel); void setBaseOrientation(const QVector3D &defaultPosition, diff --git a/src/datavisualization/engine/q3dscatter.cpp b/src/datavisualization/engine/q3dscatter.cpp index db78d5fb..b2b9c718 100644 --- a/src/datavisualization/engine/q3dscatter.cpp +++ b/src/datavisualization/engine/q3dscatter.cpp @@ -251,7 +251,9 @@ QColor Q3DScatter::objectColor() const * \property Q3DScatter::selectionMode * * Sets item selection \a mode to one of \c QDataVis::SelectionMode. It is preset to - * \c QDataVis::SelectionModeItem by default. + * \c QDataVis::SelectionItem by default. + * + * \note Only \c QDataVis::SelectionItem and \c QDataVis::SelectionNone are supported. */ void Q3DScatter::setSelectionMode(QDataVis::SelectionFlags mode) { diff --git a/src/datavisualization/engine/scatter3dcontroller.cpp b/src/datavisualization/engine/scatter3dcontroller.cpp index 1b865adc..065f1f02 100644 --- a/src/datavisualization/engine/scatter3dcontroller.cpp +++ b/src/datavisualization/engine/scatter3dcontroller.cpp @@ -73,11 +73,6 @@ void Scatter3DController::synchDataToRenderer() return; // Notify changes to renderer - if (m_changeTracker.slicingActiveChanged) { - // TODO: Add notification. - m_changeTracker.slicingActiveChanged = false; - } - if (m_changeTracker.selectedItemIndexChanged) { m_renderer->updateSelectedItemIndex(m_selectedItemIndex); m_changeTracker.selectedItemIndexChanged = false; @@ -89,7 +84,6 @@ void Scatter3DController::synchDataToRenderer() } } - void Scatter3DController::setActiveDataProxy(QAbstractDataProxy *proxy) { // Setting null proxy indicates default proxy @@ -202,20 +196,22 @@ void Scatter3DController::setObjectType(QDataVis::MeshStyle style, bool smooth) objFile = QStringLiteral(":/defaultMeshes/sphereSmooth"); else objFile = QStringLiteral(":/defaultMeshes/sphere"); - } else { + } else if (style == QDataVis::MeshStyleDots) { if (smooth) objFile = QStringLiteral(":/defaultMeshes/dotSmooth"); else objFile = QStringLiteral(":/defaultMeshes/dot"); + } else { + objFile = QString(); } Abstract3DController::setMeshFileName(objFile); } void Scatter3DController::setSelectionMode(QDataVis::SelectionFlags mode) { - // We only support single item selection mode - if (int(mode ^ QDataVis::SelectionItem) != 0) { - qWarning("Unsupported selection mode - only item selection mode is supported."); + // We only support single item selection mode and no selection mode + if (mode != QDataVis::SelectionItem && mode != QDataVis::SelectionNone) { + qWarning("Unsupported selection mode - only none and item selection modes are supported."); return; } Abstract3DController::setSelectionMode(mode); diff --git a/src/datavisualization/engine/scatter3dcontroller_p.h b/src/datavisualization/engine/scatter3dcontroller_p.h index 79be5119..d593d010 100644 --- a/src/datavisualization/engine/scatter3dcontroller_p.h +++ b/src/datavisualization/engine/scatter3dcontroller_p.h @@ -40,11 +40,9 @@ class Scatter3DRenderer; class QScatterDataProxy; struct Scatter3DChangeBitField { - bool slicingActiveChanged : 1; bool selectedItemIndexChanged : 1; Scatter3DChangeBitField() : - slicingActiveChanged(true), selectedItemIndexChanged(true) { } diff --git a/src/datavisualization/engine/scatter3drenderer.cpp b/src/datavisualization/engine/scatter3drenderer.cpp index e338b59f..70c7e107 100644 --- a/src/datavisualization/engine/scatter3drenderer.cpp +++ b/src/datavisualization/engine/scatter3drenderer.cpp @@ -79,7 +79,8 @@ Scatter3DRenderer::Scatter3DRenderer(Scatter3DController *controller) m_clickedColor(invalidColorVector), m_areaSize(QSizeF(0.0, 0.0)), m_dotSizeScale(1.0f), - m_hasHeightAdjustmentChanged(true) + m_hasHeightAdjustmentChanged(true), + m_drawingPoints(false) { initializeOpenGLFunctions(); initializeOpenGL(); @@ -255,7 +256,7 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) backgroundRotation = 0.0f; // Get light position from the scene - QVector3D lightPos = m_cachedScene->activeLight()->position(); + QVector3D lightPos = m_cachedScene->activeLight()->position(); // Map adjustment direction to model matrix scaling // TODO: Let's use these for testing the autoscaling of dots based on their number @@ -273,6 +274,12 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) QMatrix4x4 depthProjectionMatrix; QMatrix4x4 depthProjectionViewMatrix; + if (m_drawingPoints) { + glEnable(GL_POINT_SMOOTH); + glEnable(GL_PROGRAM_POINT_SIZE); + glPointSize(m_dotSizeScale * 100.0f); // Don't scale points based on zoom for shadows + } + #if !defined(QT_OPENGL_ES_2) if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { // Render scene into a depth texture for using with shadow mapping @@ -325,31 +332,37 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) QMatrix4x4 MVPMatrix; modelMatrix.translate(item.translation()); - modelMatrix.scale(modelScaler); - //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, - // heightMultiplier * item.size() + heightScaler, - // depthMultiplier * item.size() + depthScaler)); + if (!m_drawingPoints) { + modelMatrix.scale(modelScaler); + //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, + // heightMultiplier * item.size() + heightScaler, + // depthMultiplier * item.size() + depthScaler)); + } MVPMatrix = depthProjectionViewMatrix * modelMatrix; m_depthShader->setUniformValue(m_depthShader->MVP(), MVPMatrix); - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_depthShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf()); - glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + if (m_drawingPoints) { + m_drawer->drawPoint(m_depthShader); + } else { + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_depthShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf()); + glVertexAttribPointer(m_depthShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf()); + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf()); - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); - glDisableVertexAttribArray(m_depthShader->posAtt()); + glDisableVertexAttribArray(m_depthShader->posAtt()); + } } // Disable drawing to framebuffer (= enable drawing to screen) @@ -381,8 +394,10 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) } #endif + if (m_drawingPoints) + glPointSize(m_dotSizeScale * activeCamera->zoomLevel()); // Scale points based on zoom + // Skip selection mode drawing if we have no selection mode - // TODO: Can't call back to controller here! (QTRD-2216) if (m_cachedSelectionMode > QDataVis::SelectionNone && QDataVis::InputStateOnScene == m_inputState) { // Bind selection shader @@ -408,10 +423,12 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) QMatrix4x4 MVPMatrix; modelMatrix.translate(item.translation()); - modelMatrix.scale(modelScaler); - //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, - // heightMultiplier * item.size() + heightScaler, - // depthMultiplier * item.size() + depthScaler)); + if (!m_drawingPoints) { + modelMatrix.scale(modelScaler); + //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, + // heightMultiplier * item.size() + heightScaler, + // depthMultiplier * item.size() + depthScaler)); + } MVPMatrix = projectionViewMatrix * modelMatrix; @@ -421,22 +438,26 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) m_selectionShader->setUniformValue(m_selectionShader->MVP(), MVPMatrix); m_selectionShader->setUniformValue(m_selectionShader->color(), dotColor); - // 1st attribute buffer : vertices - glEnableVertexAttribArray(m_selectionShader->posAtt()); - glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf()); - glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); + if (m_drawingPoints) { + m_drawer->drawPoint(m_selectionShader); + } else { + // 1st attribute buffer : vertices + glEnableVertexAttribArray(m_selectionShader->posAtt()); + glBindBuffer(GL_ARRAY_BUFFER, m_dotObj->vertexBuf()); + glVertexAttribPointer(m_selectionShader->posAtt(), 3, GL_FLOAT, GL_FALSE, 0, (void *)0); - // Index buffer - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf()); + // Index buffer + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_dotObj->elementBuf()); - // Draw the triangles - glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); + // Draw the triangles + glDrawElements(GL_TRIANGLES, m_dotObj->indexCount(), GL_UNSIGNED_SHORT, (void *)0); - // Free buffers - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); - glBindBuffer(GL_ARRAY_BUFFER, 0); + // Free buffers + glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0); + glBindBuffer(GL_ARRAY_BUFFER, 0); - glDisableVertexAttribArray(m_selectionShader->posAtt()); + glDisableVertexAttribArray(m_selectionShader->posAtt()); + } } glEnable(GL_DITHER); @@ -470,15 +491,25 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) } // Bind dot shader - m_dotShader->bind(); + ShaderHelper *dotShader = 0; - // Set unchanging shader bindings - m_dotShader->setUniformValue(m_dotShader->lightP(), lightPos); - m_dotShader->setUniformValue(m_dotShader->view(), viewMatrix); - m_dotShader->setUniformValue(m_dotShader->ambientS(), m_cachedTheme.m_ambientStrength); + if (!m_drawingPoints) { + // Set default shader + dotShader = m_dotShader; + dotShader->bind(); - // Enable texture - glEnable(GL_TEXTURE_2D); + // Set unchanging shader bindings + dotShader->setUniformValue(dotShader->lightP(), lightPos); + dotShader->setUniformValue(dotShader->view(), viewMatrix); + dotShader->setUniformValue(dotShader->ambientS(), m_cachedTheme.m_ambientStrength); + + // Enable texture + glEnable(GL_TEXTURE_2D); + } else { + // We can use selection shader for points + dotShader = m_selectionShader; + dotShader->bind(); + } // Draw dots bool dotSelectionFound = false; @@ -496,15 +527,16 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) QMatrix4x4 itModelMatrix; modelMatrix.translate(item.translation()); - modelMatrix.scale(modelScaler); - //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, - // heightMultiplier * item.size() + heightScaler, - // depthMultiplier * item.size() + depthScaler)); - itModelMatrix.scale(modelScaler); - //itModelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, - // heightMultiplier * item.size() + heightScaler, - // depthMultiplier * item.size() + depthScaler)); - + if (!m_drawingPoints) { + modelMatrix.scale(modelScaler); + itModelMatrix.scale(modelScaler); + //modelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, + // heightMultiplier * item.size() + heightScaler, + // depthMultiplier * item.size() + depthScaler)); + //itModelMatrix.scale(QVector3D(widthMultiplier * item.size() + widthScaler, + // heightMultiplier * item.size() + heightScaler, + // depthMultiplier * item.size() + depthScaler)); + } #ifdef SHOW_DEPTH_TEXTURE_SCENE MVPMatrix = depthProjectionViewMatrix * modelMatrix; #else @@ -529,36 +561,54 @@ void Scatter3DRenderer::drawScene(const GLuint defaultFboHandle) dotSelectionFound = true; } - // Set shader bindings - m_dotShader->setUniformValue(m_dotShader->model(), modelMatrix); - m_dotShader->setUniformValue(m_dotShader->nModel(), - itModelMatrix.inverted().transposed()); - m_dotShader->setUniformValue(m_dotShader->MVP(), MVPMatrix); - m_dotShader->setUniformValue(m_dotShader->color(), dotColor); + if (!m_drawingPoints) { + // Set shader bindings + dotShader->setUniformValue(dotShader->model(), modelMatrix); + dotShader->setUniformValue(dotShader->nModel(), + itModelMatrix.inverted().transposed()); + } + dotShader->setUniformValue(dotShader->MVP(), MVPMatrix); + dotShader->setUniformValue(dotShader->color(), dotColor); #if !defined(QT_OPENGL_ES_2) if (m_cachedShadowQuality > QDataVis::ShadowQualityNone) { - // Set shadow shader bindings - QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; - m_dotShader->setUniformValue(m_dotShader->shadowQ(), m_shadowQualityToShader); - m_dotShader->setUniformValue(m_dotShader->depth(), depthMVPMatrix); - m_dotShader->setUniformValue(m_dotShader->lightS(), lightStrength / 10.0f); - - // Draw the object - m_drawer->drawObject(m_dotShader, m_dotObj, 0, m_depthTexture); + if (!m_drawingPoints) { + // Set shadow shader bindings + QMatrix4x4 depthMVPMatrix = depthProjectionViewMatrix * modelMatrix; + dotShader->setUniformValue(dotShader->shadowQ(), m_shadowQualityToShader); + dotShader->setUniformValue(dotShader->depth(), depthMVPMatrix); + dotShader->setUniformValue(dotShader->lightS(), lightStrength / 10.0f); + + // Draw the object + m_drawer->drawObject(dotShader, m_dotObj, 0, m_depthTexture); + } else { + // Draw the object + m_drawer->drawPoint(dotShader); + } } else #endif { - // Set shadowless shader bindings - m_dotShader->setUniformValue(m_dotShader->lightS(), lightStrength); - // Draw the object - m_drawer->drawObject(m_dotShader, m_dotObj); + if (!m_drawingPoints) { + // Set shadowless shader bindings + dotShader->setUniformValue(dotShader->lightS(), lightStrength); + // Draw the object + m_drawer->drawObject(dotShader, m_dotObj); + } else { + // Draw the object + m_drawer->drawPoint(dotShader); + } } } // Release dot shader - m_dotShader->release(); + dotShader->release(); + + if (m_drawingPoints) { + glDisable(GL_POINT_SMOOTH); + glDisable(GL_PROGRAM_POINT_SIZE); + glEnable(GL_TEXTURE_2D); // Enable texturing for background + } // Bind background shader m_backgroundShader->bind(); @@ -1376,11 +1426,17 @@ void Scatter3DRenderer::updateShadowQuality(QDataVis::ShadowQuality quality) void Scatter3DRenderer::loadMeshFile() { - QString objectFileName = m_cachedObjFile; - if (m_dotObj) + if (m_dotObj) { delete m_dotObj; - m_dotObj = new ObjectHelper(objectFileName); - m_dotObj->load(); + m_dotObj = 0; + } + if (m_cachedObjFile.isEmpty()) { + m_drawingPoints = true; + } else { + m_drawingPoints = false; + m_dotObj = new ObjectHelper(m_cachedObjFile); + m_dotObj->load(); + } } void Scatter3DRenderer::loadBackgroundMesh() diff --git a/src/datavisualization/engine/scatter3drenderer_p.h b/src/datavisualization/engine/scatter3drenderer_p.h index fc69094f..36492e80 100644 --- a/src/datavisualization/engine/scatter3drenderer_p.h +++ b/src/datavisualization/engine/scatter3drenderer_p.h @@ -83,8 +83,8 @@ private: QSizeF m_areaSize; GLfloat m_dotSizeScale; QVector3D m_translationOffset; - bool m_hasHeightAdjustmentChanged; + bool m_drawingPoints; ScatterRenderItem m_dummyRenderItem; ScatterRenderItemArray m_renderItemArray; -- cgit v1.2.3