Qt3D: QGeometryData::detach() does not function as expected



  • StackOverflow is failing me, so I wondered if anyone here would be able to explain some Qt3D to me:

    I'm trying to get my head around how the QGeometryData class works in the Qt3D library. I understand that it encapsulates shared data, but even after calling detach() (whose description is "Force this geometry to ensure it has its own unshared internal data block, making a copy in the case that it is currently shared"), modifications to my original object are reflected in the QGeometryData object when they shouldn't be, as far as I can see.

    My process is as follows:

    • A RenderBox object (my class) is set up to reside at the origin of the world.
    • toGeomData() is called in order to convert the object's data (origin, min/max points) into actual geometry data:

    @QGeometryData RenderBox::toGeomData() const
    {
    // Calculate the min and max co-ordinates in world space.
    QVector3D min = m_vecPosition + minimum();
    QVector3D max = m_vecPosition + maximum();
    QColor colMin = colorMin();
    QColor colMax = colorMax();
    float colMinR = colMin.redF();
    float colMinG = colMin.greenF();
    float colMinB = colMin.blueF();
    float colMaxR = colMax.redF();
    float colMaxG = colMax.greenF();
    float colMaxB = colMax.blueF();
    QGeometryData geom;

    // Order of vertices:
    // 0. Minimum
    // 1. Minimum with modified X co-ord
    // 2. Minimum with modified X and Z co-ords
    // 3. Minimum with modified Z co-ord
    // 4. Maximum with modified Z co-ord
    // 5. Maximum with modified Z and X co-ords
    // 6. Maximum with modified X co-ord
    // 7. Maximum
    // This gives us an easy counter-clockwise winding for the top and bottom faces.
    
    const QVector3D verts[8] =               // Taking Z as "north" and looking down on the box (Y pointing at us), we have:
    {
        min,                                    // Lower SE 0
        QVector3D(max.x(), min.y(), min.z()),   // Lower SW 1
        QVector3D(max.x(), min.y(), max.z()),   // Lower NW 2
        QVector3D(min.x(), min.y(), max.z()),   // Lower NE 3
        QVector3D(max.x(), max.y(), min.z()),   // Upper SW 4
        QVector3D(min.x(), max.y(), min.z()),   // Upper SE 5
        QVector3D(min.x(), max.y(), max.z()),   // Upper NE 6
        max                                     // Upper NW 7
    };
    
    QColor cols[8] = 
    {
        QColor(0.0, 0.0, 0.0),
        QColor(0.0, 0.0, 0.0),
        QColor(0.0, 0.0, 0.0),
        QColor(0.0, 0.0, 0.0),
        QColor(0.0, 0.0, 0.0),
        QColor(0.0, 0.0, 0.0),
        QColor(0.0, 0.0, 0.0),
        QColor(0.0, 0.0, 0.0)
    };
    
    QVector3D dir = (max - min).normalized();
    
    // Set each vertex's colour appropriately.
    for ( int i = 0; i < 8; i++ )
    {
        float extent = scalarProjection((verts[i]-min).normalized(), dir);
        //qDebug() << "Extent for" << verts[i] << "=" << extent;
        cols[i].setRedF(colMinR + (extent * (colMaxR-colMinR)));
        cols[i].setGreenF(colMinG + (extent * (colMaxG-colMinG)));
        cols[i].setBlueF(colMinB + (extent * (colMaxB-colMinB)));
    }
    
    // Normals for faces
    const QVector3D nTop(0, 1, 0);      // Up    = +Y
    const QVector3D nBottom(0, -1, 0);  // Down  = -Y
    const QVector3D nNorth(0, 0, 1);    // North = +Z
    const QVector3D nSouth(0, 0, -1);   // South = -Z
    const QVector3D nEast(-1, 0, 0);    // East  = -X
    const QVector3D nWest(1, 0, 0);     // West  = +X
    
    int n = 0;
    // Top face
    geom.appendVertex(verts[4], verts[5], verts[6], verts[7]);
    geom.appendNormal(nTop, nTop, nTop, nTop);
    geom.appendColor(cols[4], cols[5], cols[6], cols[7]);
    geom.appendIndex(n);geom.appendIndex(n+1);geom.appendIndex(n+2);
    geom.appendIndex(n+2);geom.appendIndex(n+3);geom.appendIndex(n);
    
    n += 4;
    // Bottom face
    geom.appendVertex(verts[0], verts[1], verts[2], verts[3]);
    geom.appendNormal(nBottom, nBottom, nBottom, nBottom);
    geom.appendColor(cols[0], cols[1], cols[2], cols[3]);
    geom.appendIndex(n);geom.appendIndex(n+1);geom.appendIndex(n+2);
    geom.appendIndex(n+2);geom.appendIndex(n+3);geom.appendIndex(n);
    
    // ...and so on.
    
    // Return the GeomData.
    return geom;
    

    }@

    • A copy of the QGeometryData is returned.
    • detach() is called on the returned copy.
    • The RenderBox then has its origin changed from 0, 0, 0 to 2, 2, 2.
    • The original QGeometryData, exported before the change, is given to the scene builder; the RenderBox is not.
    • When the scene renders, the geometry is present at 2, 2, 2 and not 0, 0, 0 as expected.

    Am I interpreting this wrong? Is there a way to export an object (which contains only minimal data, ie. origin and min/max vectors) to geometry data (ie. vertices and normals) and have the geometry data then become completely independent of the object?

    Thanks.


  • Lifetime Qt Champion

    Hi,

    Since Qt3D is not yet released, I would recommend asking this question on the "interest":http://lists.qt-project.org/mailman/listinfo/interest mailing list. You'll find there Qt's developers/maintainers (this forum is more user oriented)



  • Thanks, I'll try that.

    Just for info: I realised I'd made a mistake in my rendering code. I'm still getting a problem with only one set of geometry being rendered, but it seems to be related to QGLBuilder rather than QGeometryData.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.