6
7

Qtでポイントクラウド

Posted at

はじめに

Qtは組み込みシステムからOSSと様々なシーンで採用されています。それでも3DCGを扱えることを知る人は、Qtでプログラミングしてみた人以外はあまり知られていないと思います。

以前、Qtで3次元データのポイントクラウド(点群)を表示する方法を調べ、実装例をGitHubに公開していました。

下記の4つの環境で、それぞれ実装例を作ってます。

  • Qt Quick 3D 6.6
  • Qt Quick 3D 5.15.2
  • Qt 3D 5.15.2
  • Qt Quick 5.15.2 + OpenGL

この記事でまとめて紹介していきます。情報が少なく苦労したものもあります。誰かの役に立てば幸いです。

なお普段使っているmacOS環境ベースで書いています。Windows 11で動作しましたが確認したのは1年くらい前です。2023年11月時点での最新版の動作確認はしていません。

Qt Quick 3D 6.6 環境のポイントクラウド

Qt 6のQt Quick 3Dを使って、ポイントサイズを変更するサンプルアプリです。

pc_qtquick3d6.png

Features

あとに記載するQt5では、QMLだけでポイントクラウドのポイントサイズを変えられませんでした。Qt6からQuick 3DのDefaultMaterialのプロパティpointSizeを変更するだけで、ポイントの大きさを表示が変えられるようになりました。 ポイントの形状は正方形になります。

Model {
    id: cube
    geometry: PointCloudCubeGeometry {
        pointCount: 10000
    }
    materials: [
        DefaultMaterial {
            lighting: DefaultMaterial.NoLighting
            pointSize: Screen.devicePixelRatio * 5
            vertexColorsEnabled: true
        }
    ]
}

Screen.devicePixelRatio をかけることで、普通のディスプレイと高画素密度のディスプレイの双方同じ見え方になります。

Requirement

  • Qt Creator
  • CMake
  • Qt 6.6.0

Qt Quick 3D 5.15.2 環境のポイントクラウド

Qt 5.15.2のQt Quick 3Dを使って、ポイントサイズを擬似的に変更するサンプルアプリです。

pc_qtquick3d5.png

Features

Qt5のQt Quick 3Dでは、PrimitiveTypeがポイントに設定した時のサイズを簡単に変更することができません。 Qt Quick 3Dのソースコードを調べてみると、シェーダーコンパイラにわたす前にglPointSizeを削除しているようでした。そこでポイントの代わりにビルボードを作成し、Shaderでポイントサイズが可変したかのように見せています。やっていることはパーティクルと同じかと思います。

C++のコードでは、トライアングル2枚を生成しています。座標はすべて同じにしていて、Vertex shaderでポイントサイズにあわせて座標を変更しています。Fragment shaderで円を描画しています。お好みの形やテクスチャを貼るように書き換えてもいいと思います。

    for (int i = 0; i < m_fPointCount; ++i) {
        float x = randomFloat(-5.0f, +5.0f);
        float y = randomFloat(-5.0f, +5.0f);
        float z = randomFloat(-5.0f, +5.0f);

        // vertex
        for (int j = 0; j < 4; ++j) {
            *p++ = x;
            *p++ = y;
            *p++ = z;
            *p++ = float(((j+1) >> 1) & 1); // Texture u
            *p++ = float(( j    >> 1) & 1); // Texture v
        }

        // index
        *idx++ = i * 4;
        *idx++ = i * 4 + 1;
        *idx++ = i * 4 + 2;

        *idx++ = i * 4;
        *idx++ = i * 4 + 2;
        *idx++ = i * 4 + 3;
    }
ChangePoints.vert
in vec3 attr_pos;
in vec2 attr_uv0;
uniform mat4 modelViewProjection;
out vec3 pos;
out vec2 uv0;

void main() {
    float sx = sin(pitch);
    float cx = cos(pitch);
    mat3 mx = mat3(
        1.0, 0.0, 0.0,
        0.0,  cx, -sx,
        0.0,  sx,  cx);
    float sy = sin(yaw);
    float cy = cos(yaw);
    mat3 my = mat3(
         cy, 0.0,  sy,
        0.0, 1.0, 0.0,
        -sy, 0.0,  cy);

    pos = attr_pos;
    uv0 = attr_uv0;
    float x = (float((((gl_VertexID+1) / 2) % 2) * 2.0) - 1.0) * length;
    float y = (float((( gl_VertexID    / 2) % 2) * 2.0) - 1.0) * length;
    gl_Position = modelViewProjection * vec4(pos + mx * my * vec3(x, y, 0.0), 1.0);
}

Requirement

  • Qt Creator
  • CMake
  • Qt 5.15.2

Note

通常のポイントサイズは、Perspective/Orthographic(透視投影/平行投影)のいずれでも大きさは一定です。 このサンプルアプリは擬似的にサイズを変更しているため、透視射影ではカメラからの距離によってサイズが変わってしまいます。

Qt3D 5.15.2 環境のポイントクラウド

QtのQt3Dを使って、ポイントサイズを変更するサンプルアプリです。

pc_qt3d5.png

Features

Qt5のQt3Dを用いて、ポイントクラウドのポイントサイズを変更する方法を示しています。 Qt6.xでも多少の変更で可能と考えられます。Qt3DはQt Quick 3Dと比べてより低レベルのためちょっと難しいですが、ほとんどをqmlで記述できました。

PointSizeで大きさを設定しています。Screen.devicePixelRatio をかけることで、普通のディスプレイと高画素密度のディスプレイの双方同じ見え方になります。

stage.qml
...

    components: [
        RenderSettings {
            activeFrameGraph: RenderSurfaceSelector {
                ForwardRenderer {
                    clearColor: Qt.rgba(0.95, 1.0, 1.0, 1.0)
                    CameraSelector {
                        camera: root.perspective == true ? perspectiveCamera : orthographicCamera
                        RenderStateSet {
                            renderStates: [
                                PointSize {
                                    sizeMode: PointSize.Fixed
                                    // Common values are 1.0 on normal displays and 2.0 on Apple "retina" displays.
                                    value: root.pointSize * Screen.devicePixelRatio
                                },
                                DepthTest {
                                    depthFunction: DepthTest.Less
                                }
                            ]
                        }
                    }
                }
            }
        },
        InputSettings {}
    ]

...

Requirement

  • Qt Creator
  • CMake
  • Qt 5.15.2

Qt 5.15.2 GLSE 環境のポイントクラウド

Qt 5.15.2のOpenGLを使って、ポイントサイズを変更するサンプルアプリです。

pc_qtglsl.png

Features

Qt5のOpenGLのglPointSize()を使って変更しています。m_devicePixelRatioをかけることで、普通のディスプレイと高画素密度のディスプレイの双方同じ見え方になります。

  glPointSize(m_fPointSize * m_devicePixelRatio);

Requirement

  • Qt Creator
  • qmake
  • Qt 5.15.2

Note

  • /Library/Developer/CommandLineTools/SDKs/MacOSX13.3.sdk/System/Library/Frameworks/OpenGL.framework
    xcode-select --installでインストールしたSDKにはglPointSizeが定義されていました。

  • /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX13.1.sdk/System/Library/Frameworks/OpenGL.framework
    XcodeのからインストールするSDKにはglPointSizeがありませんでした。 環境設定、OSによってビルドに失敗するかもしれません。

  • /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX14.sdk/System/Library/Frameworks/OpenGL.framework
    まだ調べてません。

  • /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX15.sdk/System/Library/Frameworks/OpenGL.framework
    まだ調べてません。

Build Settings for M1 mac

M1 macではarm64とx86_64を明示的に指定する必要があります。 ビルド設定のCMake > CMAKE_OSX_ARCHITECTURESにx86_64と記述します。 Qt 5.15.4以降はarm64にサポート外ながら一応対応していてUniversal Binaryになります。Qt 6.xを使っているのであれば、何も気にする必要はありません。

qt5_cmake_build_settings.png

おわりに

時間をかけて調べ上げましたが、色々あって使い道を失ってしまいました。ここの記事にすることで供養したいと思います。

6
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
7