Help us understand the problem. What is going on with this article?

AutodeskのForge Viewerを利用してFBXファイルを表示する

More than 3 years have passed since last update.

Autodesk社のForge ViewerはWebGLベースのJavaScriptライブラリーであり、他のForge APIの機能と合わせて使うことで様々なツールで作成された2Dや3DデータをWebブラウザ上で表示することが出来ます。

本記事では、手元のFBXをクラウドにアップロードしてViwerを利用したWebページで表示するまでの一連の手順について説明します。

Autodesk Forgeとは何か

Autodesk Forge プラットフォームとは (引用元: Technology Perspective from Japan)
Autodesk Forge(http://forge.autodesk.com/) は、クラウドを利用して ‘接続された’ エコ システムを構築する サービス や ツール、製品のためのプラットフォームです。

オートデスクのクラウド サービスを構成するさまざまなテクノロジを Web サービス API や SDK として提供する開発プラットフォーム、Forge を利用するアイデアや開発を助成するファンド、コンファレンスやミートアップ、フォーラムを通して開発コミュニティをバックアップするデベロッパ プログラムで構成されています。

幅広い概念なのでちょっと難しいですが、Autodesk社独自のPaaS的なサービスと理解しています。(間違っていたらご指摘下さい)

事前準備

  • Autodeskアカウントの取得
  • Forge Developerページへのサインイン
  • 自前のWebサーバー。もしくはホスティングサービス(GitHub Pagesなど)のアカウント
  • cURL
  • Forge Deliverable APIによりSVF formatへの変換が可能なファイル。変換可能なファイルのリストはこちらを参照
  • テキストエディタ
  • (Windowsで以下に挙げたコマンドをそのまま利用する場合は、Bash on Ubuntu on WindowsやMinGWやCygwinなどが必要になるかもしれません。筆者はMacを使いました)

アップロードから表示までの手順

それでは本題である手元のFBXファイルをアップロードしてViwerを利用したWebページで表示するまでの一連の流れについて説明します。
image
手順はこのようなイメージです。

1. APIの登録

Forge Developerにログインした後、My Appsのページから"CREATE APP"を選択してアプリケーションを登録していきます。
本家のCreate an Appに書かれている内容と同等です。

1.1. My Appsページ

image

1.2. CREATE APPページ

image

ここではGitHub Pagesを利用したTestという名前のアプリケーションを作ってみます。
今回は3-legged authenticationは使用しませんが、空欄のままだとアプリケーションが作成できないので、仮のものを入れておきます。

1.3. Testアプリケーションのページ

image

次の2-Leggedトークンを取得する時に、ここの記載されているClient IDとClient Secretを使用します。

2. 2-Leggedトークンの取得

本家のGet a 2-Legged Tokenに書かれている内容とほぼ同等ですが、ここの例ではscope=data:readと書いてありますが、今回は後述するApp-Managed Bucketの作成とアップローを可能にするためにscope=bucket:create%20bucket:read%20data:write%20data:readを設定しています。

ここからは、ターミナルを開いてcurlコマンドを使っていきます。

curl -v 'https://developer.api.autodesk.com/authentication/v1/authenticate' \
-X 'POST' \
-H 'Content-Type: application/x-www-form-urlencoded' \
-d 'client_id=[CLIENT_ID]&client_secret=[CLIENT_SECRET]&grant_type=client_credentials&scope=bucket:create%20bucket:read%20data:write%20data:read'

[CLIENT_ID][CLIENT_SECRET]は、上述のアプリケーションを登録した時に発行されたClient IDとClient Secretに置き換えてください。

コマンドが成功すると、次のような結果が返ってきます。

{"access_token":"[ACCESS_TOKEN]","token_type":"Bearer","expires_in":86399}

なお、上記の[ACCESS_TOKEN]のところには数十〜数百文字の文字列が入ってきます。
この[ACCESS_TOKEN]の値は今後の作業で頻繁に使うので、次のようにして環境変数に登録しておきます。

export ACCESS_TOKEN="[ACCESS_TOKEN]"

上記の[ACCESS_TOKEN]の値は前述の通り適宜書き換えて下さい。

3. ファイルのアップロード

3.1. App-Managed Bucketの作成

本家のCreate an App-Managed Bucket and Upload a Fileに習って作業を進めていきます。
今後bucketKeyの値を何度も使うことになるので、環境変数に登録しておきます。

export BUCKET_KEY="[BUCKET_KEY]"

上記の[BUCKET_KEY]の値は適宜好みの値に書き換えて下さい。
なお、この値は他のユーザーが作成した値と重複しない値にする必要があるようです。
重複すると次のコマンドを実行した時にエラーメッセージが返ってきます。

curl -v 'https://developer.api.autodesk.com/oss/v2/buckets' \
-X 'POST' \
-H 'Content-Type: application/json' \
-H 'Authorization: Bearer '${ACCESS_TOKEN} \
-d '{"bucketKey":"'${BUCKET_KEY}'","policyKey":"persistent"}'

成功すると次のような結果が返ってきます。

{"bucketKey":"[BUCKET_KEY]","bucketOwner":"[BUCKET_OWNER]","createdDate":1489572965267,"permissions":[{"authId":"[AUTH_ID]","access":"full"}],"policyKey":"persistent"}%

なお上記の、[BUCKET_KEY][BUCKET_OWNER]そして[AUTH_ID]は、実際には固有の値が入っています。

3.2. App-Managed Bucketへのアップロード

作成したApp-Managed Bucketに、手元のファイルをアップロードしていきます。
今回利用するファイルは、カレントディレクトリにあることを想定しています。
例によって何度か利用することになるので、ファイル名を環境変数に登録しておきます。

export FILE_NAME="[FILE_NAME]"

ここで[FILE_NAME]は各自が用意したファイル名で置き換えて下さい。
なお、URL的にエスケープが必要な文字が含まれたファイル名は、試していませんが避けた方が良いと思います。

そして次のコマンドでアップロードします。

curl -v 'https://developer.api.autodesk.com/oss/v2/buckets/'${BUCKET_KEY}'/objects/'${FILE_NAME} \
-X 'PUT' \
-H 'Authorization: Bearer '${ACCESS_TOKEN} \
-H 'Content-Type: application/octet-stream'\
-H 'Content-Length: '`ls -l ${FILE_NAME} | awk '{print $5}'` \
-T ${FILE_NAME}

なお、途中に含まれているls -l ${FILE_NAME} | awk '{print $5}'では、ファイルサイズを取得しています。
アップロードが成功すると、次のような結果が返ってきます。

{
  "bucketKey" : "[BUCKET_KEY]",
  "objectId" : "urn:adsk.objects:os.object:[BUCKET_KEY]/[FILE_NAME]",
  "objectKey" : "[FILE_NAME]",
  "sha1" : "[SHA1]",
  "size" : [FILE_SIZE],
  "contentType" : "application/octet-stream-H",
  "location" : "https://developer.api.autodesk.com/oss/v2/buckets/[BUCKET_KEY]/objects/[FILE_NAME]"
* Connection #0 to host developer.api.autodesk.com left intact
}* Rebuilt URL to: Content-Length: [FILE_SIZE]/

ここで、実際には[BUCKET_KEY][FILE_NAME][SHA1]および[FILE_SIZE]は各自の値が入っています。

4. SVF formatへの変換

ここからは、本家のPrepare a File for the Viewerに習って、App-Managed BucketにアップロードしたファイルをViewerが扱うことの出来るSVF formatに変換していきます。

4.1. URNをURL-safe Base64 (no padding)に変換する

このオンラインツールを使ってURNをBase64エンコードします。

URNの値は上記の例では次のようになっていました。
urn:adsk.objects:os.object:[BUCKET_KEY]/[FILE_NAME]
この文字列をエンコードすると、末尾に===が含まれた文字列になることがあります。
その場合、末尾の===を取り除いた値が、URL-safe Base64 (no padding)になり、これを利用していきます。

URL-safe Base64 (no padding)の値は何度も利用するので環境変数に登録しておきます。

export URN="[URN]"

ここで[URN]は各自のURL-safe Base64 (no padding)の値です。

4.2. SVF formatへの変換

次のコマンドを使って、SVF formatへの変換を実行します。

curl -X 'POST' \
-H 'Authorization: Bearer '${ACCESS_TOKEN} \
-H 'Content-Type: application/json' \
-v 'https://developer.api.autodesk.com/modelderivative/v2/designdata/job' \
-d '{"input":{"urn":"'${URN}'"},"output":{"formats":[{"type":"svf","views":["2d","3d"]}]}}'

コマンドが成功すると、次のような結果が返ってきます。

{"result":"created","urn":"[URN]","acceptedJobs":{"output":{"formats":[{"type":"svf","views":["2d","3d"]}]}},"registerKeys":["[REGISTER_KEYS]"]}

ここで[URN][REGISTER_KEYS]は各自の値です。

5. ViewerのHTMLファイルを作成する

本家のBasic Viewerの説明に習って、HTMLファイルを作成し、Webサーバーに配置します。

<head>
    <meta name="viewport" content="width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no" />
    <meta charset="utf-8">

    <!-- The Viewer CSS -->
    <link rel="stylesheet" href="https://developer.api.autodesk.com/viewingservice/v1/viewers/style.min.css" type="text/css">

    <!-- Developer CSS -->
    <style>
        body {
            margin: 0;
        }
        #MyViewerDiv {
            width: 100%;
            height: 100%;
            margin: 0;
            background-color: #F0F8FF;
        }
    </style>
</head>
<body>

    <!-- The Viewer will be instantiated here -->
    <div id="MyViewerDiv"></div>

    <!-- The Viewer JS -->
    <script src="https://developer.api.autodesk.com/viewingservice/v1/viewers/three.min.js"></script>
    <script src="https://developer.api.autodesk.com/viewingservice/v1/viewers/viewer3D.min.js"></script>

    <!-- Developer JS -->
    <script>
        var viewer;
        var options = {
            env: 'AutodeskProduction',
            accessToken: '<YOUR_APPLICATION_TOKEN>'
        };
        var documentId = 'urn:<YOUR_URN_ID>';
        Autodesk.Viewing.Initializer(options, function onInitialized(){
            Autodesk.Viewing.Document.load(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
        });

        /**
        * Autodesk.Viewing.Document.load() success callback.
        * Proceeds with model initialization.
        */
        function onDocumentLoadSuccess(doc) {

            // A document contains references to 3D and 2D viewables.
            var viewables = Autodesk.Viewing.Document.getSubItemsWithProperties(doc.getRootItem(), {'type':'geometry'}, true);
            if (viewables.length === 0) {
                console.error('Document contains no viewables.');
                return;
            }

            // Choose any of the avialble viewables
            var initialViewable = viewables[0];
            var svfUrl = doc.getViewablePath(initialViewable);
            var modelOptions = {
                sharedPropertyDbPath: doc.getPropertyDbPath()
            };

            var viewerDiv = document.getElementById('MyViewerDiv');
            viewer = new Autodesk.Viewing.Private.GuiViewer3D(viewerDiv);
            viewer.start(svfUrl, modelOptions, onLoadModelSuccess, onLoadModelError);
        }

        /**
         * Autodesk.Viewing.Document.load() failuire callback.
         */
        function onDocumentLoadFailure(viewerErrorCode) {
            console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode);
        }

        /**
         * viewer.loadModel() success callback.
         * Invoked after the model's SVF has been initially loaded.
         * It may trigger before any geometry has been downloaded and displayed on-screen.
         */
        function onLoadModelSuccess(model) {
            console.log('onLoadModelSuccess()!');
            console.log('Validate model loaded: ' + (viewer.model === model));
            console.log(model);
        }

        /**
         * viewer.loadModel() failure callback.
         * Invoked when there's an error fetching the SVF file.
         */
        function onLoadModelError(viewerErrorCode) {
            console.error('onLoadModelError() - errorCode:' + viewerErrorCode);
        }

    </script>
</body>
</html>

ここで<YOUR_APPLICATION_TOKEN>は前述の[ACCESS_TOKEN]の値に置き換え、<YOUR_URN_ID>は同様に前述の[URN](つまりURL-safe Base64 (no padding))に置き換えて下さい。
HTMLファイルが作成できたらWebサーバーに配置します。

6. Webブラウザで確認する

Webサーバーに配置したViewerのページをWebGLをサポートしているブラウザで開きます。
すると、少し間を置いてこのような画面を確認できると思います。
image
画面下部にあるボタンやマウスを使って、視点を制御したり、断面形状を見たり、寸法を測ったりすることが出来ますのでぜひやってみて下さい。
もしもACCESS_TOKENやURNの設定ミスによってエラーが発生した場合は空白の表示になりますので、デベロッパーツールなどで確認してみて下さい。

Forge APIの情報源

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした