Amazon Sumerian Tutorial 49:SumerianRunner Events

こんにちは、ナレコム前川です。

今回は、Amazon Sumerian の公式チュートリアルの

SumerianRunner Events を進めていきたいと思います。

ここで学ぶことは

・Event Listeners

・sumerianRunner Event Listeners

・Events

・Intersection marker

の4つです。

また、今回のイベントリスナーは通常の DOM イベントリスナーよりも重いようなので

必要最低限のアクションを起こすことがおすすめされています。

それでは、進めていきましょう。

1. シーンの作成

① ダッシュボードからDefault Lightingを選択。

① ダッシュボードからDefault Lightingを選択。

② シーン名を「SumerianRunner Events」に設定し、作成。

③ Create Entity から Box を追加。※ Entity は、Box に限らず好きなものを追加してください。

今回、私は Box を追加しました。

追加できたらシーンの設定は終わりです。

2. Entity に Event Listeners を追加する

ここからは、主に Script を編集する作業を行っていきたいと思います。

① Create Entity から Empty を追加。

① Create Entity から Empty を追加。

② 追加した Entity に Script Component を追加し、Custom を選択。

③ エディタを開き、以下のコードと置き換える。
1var setup = function(args, ctx) {2    ctx.runnerListeners = {3        click: function(evt) {4            console.log('Click event', evt);5        }6    };78    for (var l in ctx.runnerListeners) {9        ctx.world.sumerianRunner.addEventListener(l, ctx.runnerListeners[l]);10    }11};1213// Remember to clean up after ourselves14var cleanup = function(args, ctx) {15    for (var l in ctx.runnerListeners) {16        ctx.world.sumerianRunner.removeEventListener(l, ctx.runnerListeners[l]);17    }18};

シーンを公開し、Iframe のやり方と同様に動作確認を行っていきます。

シーン上でマウスをクリックするとコンソールにメッセージと座標などの情報が表示されます。

3. ちょっとした GUI の追加

ここからは、イベントの情報を表示する HTML Entity を作成していきます。

① Create Entity から HTML</> を追加。

② Move with Transform のチェックを外す。

② Move with Transform のチェックを外す。

③ HTML エディタを開いて、以下のコードに置き換える。
1Screen coords: (?, ?)23    Entity: ?45    Point: ?67    Depth: ?

置き換えると、シーンの左上に intersection-info 内で定義して文字が表示されると思います。

④ Entity を選択し、Script に以下の関数を追加。
1var displayIntersectionInfo = function(screenCoords, entity, point, depth) {2    var coordsDiv = document.getElementById('intersection-screen');3    var entityDiv = document.getElementById('intersection-entity');4    var pointDiv = document.getElementById('intersection-point');5    var depthDiv = document.getElementById('intersection-depth');6    coordsDiv.innerHTML = '(' + screenCoords[0] + ', ' + screenCoords[1] + ')';7    entityDiv.innerHTML = entity;8    pointDiv.innerHTML = '(' + point[0].toFixed(2) + ', ' +9            point[1].toFixed(2) + ', ' + point[2].toFixed(2) + ')';10    depthDiv.innerHTML = depth.toFixed(2);11};
⑤ 以下のコードを Script の setup 関数内の runnerListeners と置き換える。
1ctx.runnerListeners = {2    click: function(evt) {3        console.log('Click event', evt);4        var name, point, depth;5        if (evt.entity && evt.intersection) {6            name = evt.entity.name;7            point = evt.intersection ? evt.intersection.toArray() : [0, 0, 0];8            depth = evt.depth;9        } else {10            name = 'None';11            depth = 0;12            point = [0, 0, 0];13        }14        displayIntersectionInfo([evt.x, evt.y], name, point, depth);15    }16};

シーンを実行して、値がどのように変化するか確認してください。

以下のようになると思います。

4. Intersection Marker

ここからは、Sphere を使ってシンプルな Intersection Marker を追加していきたいと思います。

① Create Entity から Sphere を追加。

② Entity を選択し、Script エディタを開く。③ setup 関数に以下のコードを追加。
1var setup = function(args, ctx) {2    console.clear();34    ctx.markerMeshData = new sumerian.Sphere(16, 16, 0.14);5    ctx.markerMaterial = new sumerian.Material(sumerian.ShaderLib.uber);6    ctx.markerMaterial.uniforms.materialDiffuse = [1, 0, 0, 1];7    ctx.markerMaterial.uniforms.materialEmissive = [0.7, 0, 0, 1];8    ctx.markerMaterial.uniforms.materialSpecular = [0, 0, 0, 1];910//...

④ 以下の関数を追加。

1var showMarker = function(ctx, pos) {2    if (!ctx.markerEntity) {3        ctx.markerEntity = ctx.world.createEntity(4            ctx.markerMeshData,5            ctx.markerMaterial,6            'Intersection Marker');7    }8    ctx.markerEntity.addToWorld();9    ctx.markerEntity.setTranslation(pos);10};1112var hideMarker = function(ctx) {13    if (ctx.markerEntity) ctx.markerEntity.removeFromWorld();14};

⑤ 最後に setup 関数の runnerListeners を以下に変更。

1ctx.runnerListeners = {2        click: function(evt) {3            console.log('Click event', evt);4            var name, point, depth;5            if (evt.entity && evt.intersection) {6                showMarker(ctx, evt.intersection);   // <----- here7                name = evt.entity.name;8                point = evt.intersection ? evt.intersection.toArray() : [0, 0, 0];9                depth = evt.depth;10            } else {11                hideMarker(ctx);                     // <----- and here12                name = 'None';13                depth = 0;14                point = [0, 0, 0];15            }16            displayIntersectionInfo([evt.x, evt.y], name, point, depth);17        }18};

Script を保存して、シーンを実行してみてください。

以下のように動作するはずです。

5. 完成版Script

うまく動作しなかった場合には、以下のコードと置き換えるか見比べてみてください。

以下のコードは、完成したコードになっています。

1var setup = function(args, ctx) {2    console.clear();34    ctx.markerMeshData = new sumerian.Sphere(16, 16, 0.14);5    ctx.markerMaterial = new sumerian.Material(sumerian.ShaderLib.uber);6    ctx.markerMaterial.uniforms.materialDiffuse = [1, 0, 0, 1];7    ctx.markerMaterial.uniforms.materialEmissive = [0.7, 0, 0, 1];8    ctx.markerMaterial.uniforms.materialSpecular = [0, 0, 0, 1];910    ctx.runnerListeners = {11        click: function(evt) {12            console.log('Click event', evt);13            var name, point, depth;14            if (evt.entity && evt.intersection) {15                console.log(evt);16                showMarker(ctx, evt.intersection);17                name = evt.entity.name;18                point = evt.intersection ? evt.intersection.toArray() : [0, 0, 0];19                depth = evt.depth;20            } else {21                hideMarker(ctx);22                name = 'None';23                depth = 0;24                point = [0, 0, 0];25            }26            displayIntersectionInfo(27                [evt.x, evt.y], name, point, depth);28        }29    };3031    for (var l in ctx.runnerListeners) {32        ctx.world.sumerianRunner.addEventListener(l, ctx.runnerListeners[l]);33    }34};3536var cleanup = function(args, ctx) {37    for (var l in ctx.runnerListeners) {38        ctx.world.sumerianRunner.removeEventListener(l, ctx.runnerListeners[l]);39    }40    if (ctx.markerEntity) ctx.markerEntity.removeFromWorld();41};4243var showMarker = function(ctx, pos) {44    if (!ctx.markerEntity) {45        ctx.markerEntity = ctx.world.createEntity(46            ctx.markerMeshData,47            ctx.markerMaterial,48            'Intersection Marker');49    }50    ctx.markerEntity.addToWorld();51    ctx.markerEntity.setTranslation(pos);52};5354var hideMarker = function(ctx) {55    if (ctx.markerEntity) ctx.markerEntity.removeFromWorld();56};5758var displayIntersectionInfo = function(screenCoords, entity, point, depth) {59    var coordsDiv = document.getElementById('intersection-screen');60    var entityDiv = document.getElementById('intersection-entity');61    var pointDiv = document.getElementById('intersection-point');62    var depthDiv = document.getElementById('intersection-depth');63    coordsDiv.innerHTML = '(' + screenCoords[0] + ', ' + screenCoords[1] + ')';64    entityDiv.innerHTML = entity;65    pointDiv.innerHTML = '(' + point[0].toFixed(2) + ', ' +66        point[1].toFixed(2) + ', ' + point[2].toFixed(2) + ')';67    depthDiv.innerHTML = depth.toFixed(2);68};

今回のチュートリアルは以上です。

お疲れ様でした。

この記事を書いた人

aws-recipe-user