Qt3D Geometry

Geometry data inspection.

This examples shows GammaRay's capabilities for inspecting Qt 3D vertex and index attribute data.

Problem

The example shows a three dimensional cylinder using Qt 3D. It's implemented as a custom Qt3DRender::QGeometry sub-class and computes the cylinder geometry, surface normals and vertex indexes.

Looking at the rendered result we notice that one side of the cylinder is not rendered correctly, and on closer look we also see that the phong shading doesn't match the expected light reflections on a cylinder

Investigation

GammaRay provides several features supporting the analysis of issues regarding vertex data provided via Qt3DRender::QAttribute and Qt3DRender::QBuffer. They are all available by opening the Qt3D Inspector view, selecting a geometry entity in the entity tree view on the left side and then opening the Qt3D Geometry Inspector tab on the right side.

Backface culling

A common problem for seemingly "missing" parts of the geometry is a wrong vertex order. The Qt3D Geometry Inspector in GammaRay allows you to disable the normally active backface culling to easily spot such cases. You find the action for that in the toolbar above the geometry view.

Back faces of triangles are rendered in red with culling disabled. Rotating the cylinder in our example using the middle mouse button so you can see the bottom disc will show that the triangles are indeed the wrong way around, and thus aren't rendred.

// const auto yNormal = (yPosition < 0.0f) ? -1.0f : 1.0f;
for (auto slice = 0; slice < m_slices; ++slice) {
    const auto nextSlice = slice + 1;
    *indicesPtr++ = discCenterIndex;
    *indicesPtr++ = (discCenterIndex + 1 + nextSlice);
    *indicesPtr++ = (discCenterIndex + 1 + slice);

    // if (yNormal < 0.0f)
    //     qSwap(*(indicesPtr -1), *(indicesPtr - 2));
}
Normal vector visualization

With the geometry fixed, we can look into the shading issues. Light reflection in the phong model largely depends on surface normal vectors, which are also provided via a Qt3DRender::QAttribute in our example. Normals can be visualized with the Qt3D Geometry Inspector by choosing the corresponding action in the toolbar above the geometry view. The resulting blue lines show the vertex normals, the yellow lines the corresponding face normals.

In our case we can easily see that the normals for the side faces are bent towards the center line of the cylinder, that is their y value isn't 0 for all vertices as it is supposed to be.

const float dY = m_length / static_cast<float>(m_rings - 1);
const float dTheta = (M_PI * 2) / static_cast<float>(m_slices);

for (int ring = 0; ring < m_rings; ++ring) {
    const float y = -m_length / 2.0f + static_cast<float>(ring) * dY;
    for (int slice = 0; slice <= m_slices; ++slice) {
        const float theta = static_cast<float>(slice) * dTheta;
        *verticesPtr++ = m_radius * qCos(theta);
        ;
        *verticesPtr++ = y;
        *verticesPtr++ = m_radius * qSin(theta);

        QVector3D n(qCos(theta), -y * 0.5f, qSin(theta));
        n.normalize();
        *verticesPtr++ = n.x();
        *verticesPtr++ = n.y();
        *verticesPtr++ = n.z();
    }
}

Files: