9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Autodesk ForgeにおけるViewerことはじめ

Last updated at Posted at 2018-07-07

Autodesk Forgeは基本的にはA360などのサーバ上にアップされたBIMデータをウェブAPIを通じて操作できるようにしたもので、疎結合なアーキテクチャとなっています。つまりはビューワは独立に制作することができます。描画のライブラリはAutodeskから提供されており、ライブラリはthreeJSを拡張したものになっているそうです。BIMデータをアップしたときに取得する、Access TokenやデータのURNが既知であれば、HTMLファイルだけで3次元形状をブラウザ上に表示することができます。サーバ側の仕組みとしては、先に述べたAccess Tokenなどを保持したり、データベースと連携したりといったアイデアがあるはずで、それによってアプリケーションの拡張が可能と考えます。

それでは、今回はNodeJS+Expressでクライアントを試作してみます。

準備

BIMデータの準備

まずは、ForgeアプリとBIMのデータの登録を行います。以前のエントリにやり方があるので、参考にしてください。
Access Tokenのみならず、BIMデータの場所を示すURNも必要になります。ここに変換の仕方があるので参考にしてください。これらがきちんと取得していないとまったく動きません。

NodeJS+Express環境の準備

別にクライアントだけでも良いのですが、今後の拡張も鑑みてNodeJS+Expessで作ってみます。ExpressというのはNodeJSで有名なMVCフレームワークです。セットアップについては、ここら辺を参考にしてください。私はVisual Studioのテンプレートを使って作りました。package.jsonとエントリポイントであるapp.jsは以下です。これをnpm startなどとすると、localhost:3000あたりで、アプリが立ち上がります。ちなみに、./routes/index.js内に書かれたルーティングルールでルーティングされます。今回は./views以下のindex.pugにルーティングするようにしています。テンプレートエンジンはPUGです。この辺りはEXPRESSのほぼテンプレなので、説明は割愛します。

package.json
{
  "name": "forge-express",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node app"
  },
  "description": "Forge sample using NodeJS + Express",
  "dependencies": {
    "body-parser": "^1.15.0",
    "cookie-parser": "^1.4.0",
    "debug": "^2.2.0",
    "express": "^4.14.0",
    "morgan": "^1.7.0",
    "pug": "^2.0.0-beta6",
    "serve-favicon": "^2.3.0"
  }
}
app.js
'use strict';
var debug = require('debug');
var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'pug');

app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', routes);
app.use('/users', users);

// catch 404 and forward to error handler
app.use(function (req, res, next) {
    var err = new Error('Not Found');
    err.status = 404;
    next(err);
});

if (app.get('env') === 'development') {
    app.use(function (err, req, res, next) {
        res.status(err.status || 500);
        res.render('error', {
            message: err.message,
            error: err
        });
    });
}

app.use(function (err, req, res, next) {
    res.status(err.status || 500);
    res.render('error', {
        message: err.message,
        error: {}
    });
});

app.set('port', process.env.PORT || 3000);

var server = app.listen(app.get('port'), function () {
    debug('Express server listening on port ' + server.address().port);
});

基本的なForge Viewerの制作

HTMLのもととなるPUGファイルは、views以下に配置しています。ルート(/)が参照されたら、まずはlayout.pugの内容が出力されるようになってます。ここでは、まずForgeに関係するCSS、JSライブラリを読み込んでいます。最後に読み込んでいるviewer.jsが今回の肝となる部分です。

layout.pug
doctype html
html
  head
    title= title
    meta(name='viewport', content='width=device-width, minimum-scale=1.0, initial-scale=1, user-scalable=no')
    link(rel='stylesheet', href='/stylesheets/main.css')
    link(rel='stylesheet', href='https://developer.api.autodesk.com/modelderivative/v2/viewers/style.min.css', type='text/css')
    
  body
    block content
    script(src='https://developer.api.autodesk.com/modelderivative/v2/viewers/viewer3D.min.js')
    script(src='javascripts/viewer.js')

続いて、上記で参照しているblock contentの部分です。ここは簡単にMyViewerDivというタグがあるだけ。このDIV要素にForgeのビューワが読み込まれます。ついでにCSSも設定しておきます。画面いっぱいに表示できるように変えておきます。

index.pug
extends layout

block content
  div#MyViewerDiv
main.css
body {
    margin: 0;
}

#MyViewerDiv {
    width: 100%;
    height: 100%;
    margin: 0;
    background-color: #F0F8FF;
}

データ表示用のJavascript

先のviewer.jsにBIMデータの読み込み、表示の処理を書き込んでいきます。ここで、準備の項で述べたアクセストークンとURNが必要になります。

viewer.js
var viewerApp;
var options = {
    env: 'AutodeskProduction',
    getAccessToken: function (onGetAccessToken) {
        var accessToken = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';
        var expireTimeSeconds = 60 * 30;
        onGetAccessToken(accessToken, expireTimeSeconds);
    }
};
var documentId = 'urn:XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX';

Autodesk.Viewing.Initializer(options, function onInitialized() {
    // 読み込みが終わった後に呼ばれるハンドラ。MyViewerDiv内にビューワをロードする。
    viewerApp = new Autodesk.Viewing.ViewingApplication('MyViewerDiv');
    viewerApp.registerViewer(viewerApp.k3D, Autodesk.Viewing.Private.GuiViewer3D);
    // コンテンツのロードを始める。
    viewerApp.loadDocument(documentId, onDocumentLoadSuccess, onDocumentLoadFailure);
});

function onDocumentLoadSuccess(doc) {
    // A document contains references to 3D and 2D viewables.
    var viewables = viewerApp.bubble.search({ 'type': 'geometry' });
    if (viewables.length === 0) {
        console.error('Document contains no viewables.');
        return;
    }
    viewerApp.selectItem(viewables[0].data, onItemLoadSuccess, onItemLoadFail)
}

function onDocumentLoadFailure(viewerErrorCode) {
    console.error('onDocumentLoadFailure() - errorCode:' + viewerErrorCode);
}

function onItemLoadSuccess(viewer, item) {
    console.log('onItemLoadSuccess()!');
    console.log(viewer);
    console.log(item);
    console.log('Viewers are equal: ' + (viewer === viewerApp.getCurrentViewer()));
}

function onItemLoadFail(errorCode) {
    console.error('onItemLoadFail() - errorCode: ' + errorCode);
}

まず、optionsというオブジェクトをInitializerの引数としています。optionsにはenvとgetAccessTokenという関数がパラメータとしてあるが、後者は自動的にExpireされる前にアクセストークンを更新するような処理となるようです(隠蔽されていてわからない)。実際は、getAccessTokenという関数の代わりに、AccessTokenというパラメータとしても問題はありません。

初期化の処理が終わると、ViewingApplicationがnewされます。その際にビューワをロードするDIV要素を指定しています。
そのあとはviewerApp.k3DやAutodesk.Viewing.Private.GuiViewer3DなどのExtentionを読み込んでから、コンテンツ(BIMデータなど)のロードを始めています。それぞれに失敗した時と、成功した時のハンドラとなる関数を用意しています。
viewer.selectItemを呼び出して成功したら(onItemLoadSuccessが呼ばれたら)、画面に表示されます。

viewer.png

とりあえず、この記事ではここまで。
次回はビューワの柔軟な操作が可能なExtensionsやEvent処理についても説明します。

9
5
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
9
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?