新卒研修報告#4 球体の整列生成

こんにちは、開発の杉原です。

 

冷静に振り返ると、最近忙しいアピールしかしていないですね。我ながらドン引きです。

というわけで、もっとまともなお話をしますと、先日新卒の歓迎会を開きました。

いまさらと思われるかもしれませんが、部に配属されたのは1か月前なので、こんなもんです。……って1か月!? もうそんなに経ったの!? 

 

 ということで、どんどん旬が過ぎていくこの報告、さすがにラストにしたいと思います。

最後は「球体の整列生成」についての報告をお送りします。

今回作成するモデルの概要については第一回で説明しているので、お手数ですがそちらをご覧ください。

このモデルの目的は、RackConfiguratorのようなコントローラの実装です。こうした部分はまだこのブログでは紹介できていないので、いつか別途ご説明できたらなと思います。

 

さて早速ですがまずはチームCのスクリプトからご紹介します。

 

function Box1_OnReset( sender : Demo3D.Visuals.BoxVisual )
{
        
}

function Box1_OnInitialize( sender : Demo3D.Visuals.BoxVisual )
{
    var X = 0;
    var Y = 0;
    var Z = 0;

    var sphere : Visual = doc.CreateVisual("SphereVisual");

    for(var i : int = 0; i < 4; ++i) 
    {   
        for(var j : int  = 0; j < 3; ++j)
        {                                       
            for(var k : int = 0; k < 2; ++k)
            {
                var X = sphere.WorldLocation.X + i;
                var Y = sphere.WorldLocation.Y + j;
                var Z = sphere.WorldLocation.Z + k;
                var sphere : Visual = doc.CreateVisual("SphereVisual");
                sphere.WorldLocation = new Vector3(X,Y,Z);
            }
        }
    }
}
// JScriptによる演習のため省略

 

このチームはこの課題に取り組んだのがちょっと遅かったような覚えがあります。そのためか、まずはハードコーディングで個数を指定しています。

処理としてはスタンダードに、列、段、連の数ごとにループして、座標を少しずつずらしながら球体を生成しています。

球体の生成方法は質問されたのでdoc.CreateVisualで生成できると私が回答し、その方法となっています。

 

次はチームB。

function Box1_OnReset( sender : Demo3D.Visuals.BoxVisual )
{
    sender.deleter.RemoveNulls();
    for(del in sender.deleter){
        doc.DestroyVisual(del);
    }
    sender.deleter.RemoveNulls();
}

function Box1_OnInitialize( sender : Demo3D.Visuals.BoxVisual )
{
    var i :int;
    var j :int;
    var k :int;
        
    var Deep : Visual = sender.deep;
    var High : Visual = sender.high;
    var Wide : Visual = sender.wide;
        
    var LocX : Vector3 = sender.WorldLocationX + 2;
    var LocY : Vector3 = sender.WorldLocationY;
    var LocZ : Vector3 = sender.WorldLocationZ + 2;
    for(i = 0; i < Deep; ++i){
        for(j = 0; j < High; ++j){
            for(k = 0; k < Wide; ++k){
                var sphere :Visual = doc.CreateVisual("SphereVisual");
                sphere.WorldLocationX = LocX + k;
                sphere.WorldLocationZ = LocZ + i;
                sphere.WorldLocationY = LocY + j;
                sender.deleter.Add(sphere);
            }
        }
    }
}
// JScriptによる演習のため省略

 

こちらは完成形ですね。リセット時に球体を削除していますし、プロパティから列・連・段の数を指定することもできます。

ここで注目したいのは球体の削除方法。doc.DestroyVisualを使用するというのもそうなのですが、その削除対象を得るためにVisualList型のプロパティdeleterを追加しています。

そのリストの中身を1つずつ削除していくのですが、リストの中身を削除しても、リストにはnull参照のオブジェクトが残り続けます。そこで、RemoveNullsメソッドを使ってnull参照の要素をリストから除外しています。

 

さて最後はチームA。

function Box1_OnReset( sender : Demo3D.Visuals.BoxVisual )
{
    var visible : BoxVisual = sender.FindChild("Sphere1");
    visible.Visible = false;
    var child : IEnumerable = sender.Children;
    for(e in child){
        if(e.Name == "Sphere1"){
            e.Visible = false;
        }else if(e.Name == "Box1"){
                
        }else{
            e.Delete();
        }
    }
}

function Box1_OnInitialize( sender : Demo3D.Visuals.BoxVisual )
{
    var visible : BoxVisual = sender.FindChild("Sphere1");
    visible.Visible = true;
    var x : int = sender.X;
    var y : int = sender.Y;
    var z : int = sender.Z;

    for (var k=0; k < x; k++)
    {
        for (var j=0; j < y; j++)
        {
            for (var i=0; i < z; i++)
            {
                var proto = sender.FindChild("Sphere1");
                if (proto == null) return;
        
                var copy = proto.Clone();
                
                copy.Reparent( sender );
                copy.LocationZ = proto.LocationZ + i;
                copy.LocationY = proto.LocationY + j;
                copy.LocationX = proto.LocationX + k;
            }
        }
    }
}

// JScriptによる演習のため省略

 

このチームの面白いところは、doc.CreateVisualを使用していないところにあります。

ではこれを使わずにどうやって球体を生成しているのかというと、あらかじめ1つの球体を不可視にして持たせており、これを必要な個数分Cloneメソッドで増やしています。

この方法はRackConfigratorとほとんど同じ考え方で、今回の球体のように単純なVisualであればCreateVisualで作るだけでかまわないのですが、もっと複雑な形状のものを並べるのであれば、この手法での実装となるでしょう。

なおこの手法の場合、リセット時の削除で誤ってプロトタイプとなる球体を消してしまわないように配慮する必要があり、このスクリプトでもその処理が実装されています。

 

このように、この課題はチームによって違った解決が見られて面白かったと思います。

ちなみに私が事前に用意したスクリプトがこちら。

function Box1_OnReset( sender : Demo3D.Visuals.BoxVisual )
{
    var child : Visual = sender.FirstChild;
    while(child != null) {
        var next = child.NextSibling;
        doc.DestroyVisual(child);
        child = next;
    }
}

function Box1_OnInitialize( sender : Demo3D.Visuals.BoxVisual )
{
    var num = sender.Wide * sender.Deep * sender.High;
        
    for (var cnt = 0; cnt < num; cnt++) {
        var d : int = cnt % sender.Deep;
        var w : int = (int)(cnt / sender.Deep) % sender.Wide;
        var h : int = (int)(cnt / sender.Deep / sender.Wide) % sender.High;
                
        var vis : SphereVisual = doc.CreateVisual("SphereVisual");
                
        var size = vis.Radius * 2;
    
        var offset : Vector3 = new Vector3(0,0,0);
                
        offset.X = w * size;
        offset.Y = h * size;
        offset.Z = d * size;

        vis.WorldLocation = vis.WorldLocation + offset;
                
        vis.Parent = sender;
    }
}
// JScriptによる演習のため省略

ループの仕方が違いますね。1つのループだけを使って、列・連・段の位置はそのループカウンタから計算で求めています。

これは別に意図して面倒な方法をとったわけではなく、恥ずかしながらfor文を3つ使うことが浮かばなかっただけです。15分やそこらで急いで作ったというといいわけになるかもしれませんが、とにかく柔軟な考えができてないが故の結果かなと思います。

 

と、こんな感じの課題を新卒研修の最終日に行いました。

実のところ、新卒の全員がDemo3Dにかかわるわけではありません。弊社ではDemo3D以外のこともやっておりますので、そちらへ配属される方もいます。

ただ、この研修を通して、手探りで結果にたどり着くことや、いろいろな解決方法があるということなんかを知ってもらえたらなと思っています。

また、実際にDemo3Dを扱う部署に配属された方も当然います。配属から1か月、研修では教えられなかったようなこともそれぞれ徐々に覚えていき、なかなかいい感じに成長しているのではないでしょうか。

私自身も、お客様に満足いただけるもの・サービスを提供できるよう、彼らの教育に努めたいと思いますので、今後ともよろしくお願いいたします。

 

あ、あと新卒といえば、ちょうど昨日から新卒の方によるブログも始まったみたいですね。

これで平日は毎日ブログが更新される……予定です。担当者も増えたので、きっと毎日更新されるでしょう。

更新内容としては以下のように予定していますので、今後ともよろしくお願いいたします。

月:ロジアナ君関連、DEMO3D一般

火:マーケティング、VR関連

水:その他

木:スクリプト、技術関連

金:物流関連


 

次回からは【How to Demo3D Scripting】を再開します!

前回少し名前を出した「MessageListener」をご紹介できればと思っています。

更新は7/19(木)を予定しておりますので、お楽しみに。