コンテンツにスキップ

C++でUSDのコードを書こう(準備編)

C++はやらなきゃと思いながらもよくわからん!!と放置してきたところがあるのですが
そもそも始めることすら出来なくて放置してました。
が、、、せっかくUSDをはじめたので、PythonだけではなくC++でもコードが書けるように
色々とビルドできるようにするまでの環境を、調べながらつくってみました。

コードを書く

とりあえずこんなコードを動くようにしてみます。

#define NOMINMAX

#include "pxr/usd/usd/stage.h"
#include "pxr/usd/sdf/path.h"
#include "pxr/usd/usdGeom/sphere.h"

void main()
{
  auto stage = pxr::UsdStage::CreateInMemory();
  auto sphere = pxr::UsdGeomSphere::Define(stage, pxr::SdfPath("/TestSphere"));
  stage->GetRootLayer()->Export("D:/test_sphere.usda");
}

同じコードをPythonで書くと、こうなります。

from pxr import UsdGeom,Usd

stage = Usd.Stage.CreateInMemory()
sphere = UsdGeom.Sphere(stage,"/TestSphere")
stage.GetRootLayer().Export("D:/test_sphere.usda")

Pythonの場合は、書いたらそのまま実行すればOKなのですが
C++だとそう簡単ではなく、ビルドをする必要があります。
なので、このコードをビルドするためのcmakeを書いていきます。

cmakeを書く

https://cmake.org/

まずは、cmakeをダウンロードしてインストールします。

cmake_minimum_required(VERSION 3.1)
project(testProj)

set(CMAKE_CXX_STANDARD 14)
set(CMAKE_CXX_STANDARD_REQUIRED ON)

set(USD_INSTALL_ROOT D:/python_lib/usd_py27)
set(PYTHON_ROOT_DIR C:/Python27)

set(USD_LIBRARY_DIRECTORY ${USD_INSTALL_ROOT}/lib)
set(USD_INCLUDE_DIRECTORY ${USD_INSTALL_ROOT}/include)
set(BOOST_INCLUDE_DIRECTORY ${USD_INSTALL_ROOT}/include/boost-1_65_1)

# ライブラリのPath取得
find_library(USD_SDF sdf HINTS ${USD_LIBRARY_DIRECTORY})
find_library(USD_TF tf HINTS ${USD_LIBRARY_DIRECTORY})
find_library(USD_USD usd HINTS ${USD_LIBRARY_DIRECTORY})
find_library(USD_GEOM usdGeom HINTS ${USD_LIBRARY_DIRECTORY})
find_library(TBB_LIB tbb HINTS ${USD_LIBRARY_DIRECTORY})
find_package(PythonLibs 2.7)

add_executable(main_app main.cpp)
target_compile_options(main_app PRIVATE /DWIN32_LEAN_AND_MEAN)
target_include_directories(
    main_app
    PUBLIC
    ${PYTHON_INCLUDE_PATH}
    ${USD_INCLUDE_DIRECTORY}
    ${BOOST_INCLUDE_DIRECTORY}
    ${PYTHON_ROOT_DIR}/include
)
target_link_libraries(
    main_app
    ${USD_LIBRARY_DIRECTORY}/boost_python-vc141-mt-1_65_1.lib
    ${PYTHON_LIBRARY}
    ${TBB_LIB}
    ${USD_SDF}
    ${USD_TF}
    ${USD_USD}
    ${USD_GEOM}
)

cppと同じフォルダに、 CMakeLists.txt を作り
中身を↑のようにします。

まずは、cppをビルドするためのプロジェクトを作ります。
いわゆるVisualStudioの slnファイル(ソリューション)がこれにあたります。

そしてその中に追加するプロジェクトを add_executable で追加します。
この第一引数が、プロジェクト名になり、

こんな感じで追加されます。
さらに、そのプロジェクトに対して、使用するライブラリとIncludeフォルダを指定します。
このlinkライブラリのパスは、find_libraryで検索することができますが
boost_pythonはみつけたサンプルのとおりにやるとエラーになったので
自分のビルドしたUSDフォルダにあるboost_pythonのlibを書いてあります。

もう1つトラップだったのが、
サンプルだとPythonLibも find_library で書かれていたのですが、
find_package(PythonLibs REQUIRED)
コレで書くと、python3.7のライブラリが引っかかってしまったので
とりあえずフルパスで追加するようにしました。

...とおもったら色々勘違いしていただけで、REQUIREDではなく指定のバージョンにすれば
そのバージョンのpythonlibをみつけてくれるので、2.7にしておきました。(※追記)

find_package自体は、.cmakeで検索コードを書いたりも出来るみたいなので
色々やってみたいです。

で。
サンプルに必要な Sdf UsdGeom Stage のlibを追加して準備完了。

おなじフォルダに build フォルダを作り、コマンドラインで buildフォルダに移動します。

cmake -G "Visual Studio 15 2017 Win64" -DCMAKE_BUILD_TYPE=Release --build ..

そしてコマンド実行。
今回はVisualStudio 2017 Win64でビルドしたいので、 -G でバージョンを指定します。
さらに、Debug版だと tbb で盛大にビルドエラーになるので今回はReleaseにします。

実行すると、buildフォルダ下にソリューションファイルができあがるので、
VisualStudioで開き、あとは ソリューションエクスプローラーから main_app を右クリック
そしてビルドすれば完了です。

はまりポイント

C++初心者な自分が盛大にはまったポイントがいくつかあります。

window.h マクロ定義問題

https://yohhoy.hatenadiary.jp/entry/20120115/p1

まず1つめが、window.hの定義マクロ問題。
window.hが「min/max」という超被りそうな名前のマクロを定義してしまうため
盛大にエラーを吐いてビルド出来ませんでした。
というわけで、回避策として #define NOMINMAX を定義。

DWIN32_LEAN_AND_MEAN

もう1つ、window.h が「small」という名のマクロを定義してしまうことで発生する
ビルドエラーを回避するために、DWIN32_LEAN_AND_MEAN を追加。

Debugモードでのエラー

最後にDebugモード時に、tbb周りのマクロ定義で盛大にエラーになってしまう問題。
なので、cmake コマンドでソリューションを作る時に -DCMAKE_BUILD_TYPE=Release
フラグを追加して回避しました。

lib入れ忘れ

これも超基本ですが、途中でSphereを作るUsdGeomSphereを追加した場合、 sphere.h を
インクルードしたらエラーになってしまいはじめはかなり困りました。
が、よく考えてみると target_link_libraries で usdGeom.libをリンクしないと
だめじゃん!ってことに気がついて追加したらいけました。

というわけで...

とりあえず色々と分からないことがあるものの、書き始められるだけの環境はできました。
なんだかんだで理解するだけで1ヶ月以上かかりました。。。C++難しい。

ビルドが通るようになって以降は、ドキュメント自体はC++で書かれていることもあって
(一応文法もわかるので)Pythonで書いたサンプルをC++に移植するとかは出来るようになりました。
一番難しいのはビルドだったのではないかと思います。

とにもかくにも動くようにはなったので、
しばらくはC++の基本を勉強しつつC++でUSDのデータを作って見るのを試してみようと思います。

参考


最終更新日: 2020-08-01 15:45:28