Qt Quick 3D - 커스텀 지오메트리 예제
C++ 및 QML에서 커스텀 버텍스 데이터를 제공하는 방법을 보여줍니다.
이 예제에서는 QQuick3DGeometry 및 the geometry property 모델을 사용하여 미리 구워진 에셋 대신 C++ 및 QML에서 지정된 버텍스, 노멀 및 텍스처 좌표로 메시를 렌더링합니다.
GridGeometry 또한 GridGeometry 은 그리드를 표시하는 데 적합한 선 프리미티브가 있는 메시를 제공하는 QQuick3DGeometry 구현이 내장되어 있습니다.
이 예제에서는 커스텀 지오메트리를 제공하는 코드에 초점을 맞추므로 먼저 ExampleTriangleGeometry
C++ 헤더 파일을 살펴보겠습니다:
class ExampleTriangleGeometry : public QQuick3DGeometry { Q_OBJECT QML_NAMED_ELEMENT(ExampleTriangleGeometry) Q_PROPERTY(bool normals READ normals WRITE setNormals NOTIFY normalsChanged) Q_PROPERTY(float normalXY READ normalXY WRITE setNormalXY NOTIFY normalXYChanged) Q_PROPERTY(bool uv READ uv WRITE setUV NOTIFY uvChanged) Q_PROPERTY(float uvAdjust READ uvAdjust WRITE setUVAdjust NOTIFY uvAdjustChanged) public: ExampleTriangleGeometry(); bool normals() const { return m_hasNormals; } void setNormals(bool enable); float normalXY() const { return m_normalXY; } void setNormalXY(float xy); bool uv() const { return m_hasUV; } void setUV(bool enable); float uvAdjust() const { return m_uvAdjust; } void setUVAdjust(float f); signals: void normalsChanged(); void normalXYChanged(); void uvChanged(); void uvAdjustChanged(); private: void updateData(); bool m_hasNormals = false; float m_normalXY = 0.0f; bool m_hasUV = false; float m_uvAdjust = 0.0f; };
가장 중요한 점은 ExampleTriangleGeometry
클래스가 QQuick3DGeometry 클래스를 상속하고 QML_NAMED_ELEMENT(ExampleTriangleGeometry)
매크로를 호출하여 QML에서 클래스에 액세스할 수 있도록 한다는 것입니다. 또한 Q_PROPERTY
매크로를 통해 정의된 몇 가지 프로퍼티가 QML 객체에 자동으로 노출됩니다. 이제 QML 모델을 살펴보겠습니다:
Model { id: triangleModel visible: false scale: Qt.vector3d(100, 100, 100) geometry: ExampleTriangleGeometry { normals: cbNorm.checked normalXY: sliderNorm.value uv: cbUV.checked uvAdjust: sliderUV.value } materials: [ DefaultMaterial { Texture { id: baseColorMap source: "qt_logo_rect.png" } cullMode: DefaultMaterial.NoCulling diffuseMap: cbTexture.checked ? baseColorMap : null specularAmount: 0.5 } ] }
ExampleTriangleGeometry
클래스를 사용하기 위해 geometry
프로퍼티를 지정하고 관련 프로퍼티를 지정한 것을 확인할 수 있습니다. 이것이 사용자 정의 지오메트리를 사용하기 위해 QML 측에서 필요한 전부입니다.
이제 C++ 코드의 또 다른 중요한 부분, 즉 updateData()
메서드를 살펴보겠습니다. 이 메서드는 ExampleTriangleGeometry
클래스가 생성되거나 해당 QML 프로퍼티가 업데이트될 때마다 커스텀 지오메트리에 대한 데이터를 생성하고 업로드합니다.
void ExampleTriangleGeometry::updateData() { clear(); int stride = 3 * sizeof(float); if (m_hasNormals) stride += 3 * sizeof(float); if (m_hasUV) stride += 2 * sizeof(float); QByteArray vertexData(3 * stride, Qt::Initialization::Uninitialized); float *p = reinterpret_cast<float *>(vertexData.data()); // a triangle, front face = counter-clockwise *p++ = -1.0f; *p++ = -1.0f; *p++ = 0.0f; if (m_hasNormals) { *p++ = m_normalXY; *p++ = m_normalXY; *p++ = 1.0f; } if (m_hasUV) { *p++ = 0.0f + m_uvAdjust; *p++ = 0.0f + m_uvAdjust; } *p++ = 1.0f; *p++ = -1.0f; *p++ = 0.0f; if (m_hasNormals) { *p++ = m_normalXY; *p++ = m_normalXY; *p++ = 1.0f; } if (m_hasUV) { *p++ = 1.0f - m_uvAdjust; *p++ = 0.0f + m_uvAdjust; } *p++ = 0.0f; *p++ = 1.0f; *p++ = 0.0f; if (m_hasNormals) { *p++ = m_normalXY; *p++ = m_normalXY; *p++ = 1.0f; } if (m_hasUV) { *p++ = 1.0f - m_uvAdjust; *p++ = 1.0f - m_uvAdjust; } setVertexData(vertexData); setStride(stride); setBounds(QVector3D(-1.0f, -1.0f, 0.0f), QVector3D(+1.0f, +1.0f, 0.0f)); setPrimitiveType(QQuick3DGeometry::PrimitiveType::Triangles); addAttribute(QQuick3DGeometry::Attribute::PositionSemantic, 0, QQuick3DGeometry::Attribute::F32Type); if (m_hasNormals) { addAttribute(QQuick3DGeometry::Attribute::NormalSemantic, 3 * sizeof(float), QQuick3DGeometry::Attribute::F32Type); } if (m_hasUV) { addAttribute(QQuick3DGeometry::Attribute::TexCoordSemantic, m_hasNormals ? 6 * sizeof(float) : 3 * sizeof(float), QQuick3DGeometry::Attribute::F32Type); } }
이 메서드는 clear()
을 호출하여 이전에 업로드된 모든 데이터를 지우는 것으로 시작합니다. 그런 다음 법선과 좌표의 존재를 고려하여 정점의 보폭을 계산합니다. 그런 다음 정점 버퍼를 보관할 바이트 배열을 생성한 다음 모서리가 (-1, -1, 0), (1, -1, 0) 및 (0, 1, 0)인 단일 삼각형의 정점으로 채웁니다.
그런 다음 정점 데이터를 업로드하고 setVertexData()
및 setStride()
을 호출하여 보폭을 설정합니다. 지오메트리의 바운드는 setBounds
을 호출하여 설정합니다. 이 예제에서는 사용되지 않았지만 그림자가 작동하려면 바운드 설정이 필요합니다. 그런 다음 setPrimitiveType()
를 호출하여 기본 유형을 설정합니다. 마지막으로 각 속성에 대해 addAttribute()
을 호출하여 이전에 업로드한 버퍼의 메모리에 위치, 노멀 및 자외선 좌표 속성이 어떻게 배치되는지 지정합니다.
© 2025 The Qt Company Ltd. Documentation contributions included herein are the copyrights of their respective owners. The documentation provided herein is licensed under the terms of the GNU Free Documentation License version 1.3 as published by the Free Software Foundation. Qt and respective logos are trademarks of The Qt Company Ltd. in Finland and/or other countries worldwide. All other trademarks are property of their respective owners.