« ガッデムPlot。 | トップページ | リージョンさん。 (XPOP普及委員会その15) »

2010年11月20日 (土)

取得 その6。

取得その3 で、Texture Projection(UV) の取得のしかたを教えてくれというコメントが付きましてね。 そのコメント内のやりとりで一応は解決した感じなのですが、改めてまとめてみようと思いましてね。



ってことで、Texture Projection の取得のしかた、およびどうやってその方法にたどり着くかの思考過程について書いてみようと思います。




まずはともあれ、取得しましょう。 現在ユーザが選んでいるオブジェクトが持つ Texture Projection を取得する、ということにしましょう。

for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);
    var oClusters = oObj.ActivePrimitive.Geometry.Clusters;
    Logmessage( oObj + " が持っている Cluster の数 -- " + oClusters.count );

    for ( var j=0; j<oClusters.count; j++ )
    {
        var oCluster = oClusters(j);
        Logmessage( "  (Cls " + (j+1) + ") " + oCluster + " : Type = " + oCluster.type );

        if ( oCluster.type == "sample" )
        {
            var oClusterProperties = oCluster.LocalProperties;
            Logmessage( "    " + oCluster + " が持っている ClusterProperty の数 -- " +  oClusterProperties.count );
            
            for ( var k=0; k<oClusterProperties.count; k++ )
            {
                var oClusterProperty = oClusterProperties(k);
                Logmessage( "      (ClsProp " + (k+1) + ") " + oClusterProperty + " : Type = " + oClusterProperty.type );
                if ( oClusterProperty.type == "uvspace" )
                {
                    Logmessage( "      #### ↑ これは Texture_Projection っス。####" );
                }
            }
        }
    }
    Logmessage( "---" );
}

冗長な Logmessage が入っているので見づらいコードですが、まあこういうことです。

Texture Projection を持つオブジェクト(複数可)を選んで実行すると、
Gettp_result
こうなります。 ログを見ると、Texture_Projection が取得できているのがわかります。 




では解説。

でもコードの解説の前に、そもそも Texture Projection とは、どういう形でシーンに存在するのだ? ということを知らなければいけない、という解説をします。これを知らないと取得しようにないからです。

Explorer または SDK Explorer で見てみます。
Tp_explorer1

 cone > Polygon Mesh > Clusters > Texture_Coordinates_AUTO > Texture_Projection


という階層構造で Texture Projection が存在しているのがわかります。 この階層を把握することが重要です。 これがわかれば、あとは逆にたどっていけば良いのです。 どういうことかと言うと、


1.最終目的地である Texture_ProjectionTexture_Coordinates_AUTO 以下にあるんだから、Texture_Projection を取得しようと思ったらまずその親である Texture_Coordinates_AUTO を取得することが必要だ

2.Texture_Coordinates_AUTO を取得するためには、その親である Clusters の取得が必要だ

3.Clusters を取得するためにはその親である Polygon Mesh(Primitive) の取得が必要だ

4.Primitive を取得するにはその親である cone の取得が必要だ

5.cone というのはユーザが選んでいるシーン内の3Dオブジェクトだから、これの取得は Selection を使えばいいじゃないか


という風に、目的地から逆をたどって取得の方法を探るのが一般的だと思います。階層をすっ飛ばしてイッキに取得できる便利な方法もあったりしますが、まあそれは別の話として、基本はこの階層構造を認識できているかどうかが、ひとつのポイントになると思います。 このためにも、スクリプトを書くときは常に Explorer を見ながら、自分は今、階層のどこを取得してるのかを意識しておくといいと思います。




さて、これで取得の 「 順番 」 は想像が付きました。 次に SDK Explorer で最終目的地である Texture_Projection の仔細を見てみます。
Tp_explorer2
すると、Texture_Projection は ClusterProperty というものだということがわかります。Type は uvspace となっています。 ここから、「 Texture_Projection は ClusterPropety と呼ばれるものであり、かつ、ClusterProperty の中でも uvspace というタイプに分類されるんだな」 と想像します。 

そして、上記の階層構造の解析により、Texture_Projection の親は Texture_Coordinates_AUTO だとわかっているんだから、「 親である Texture_Coordinates_AUTO が ClusterPropery を所有している。その中でも uvspace というタイプのものを選別すれば、それは Textrue_Projection である」 と想像します。

考え方として重要なのは、SDK Explorer で調べた「Texture_Projection は ClusterProperty である」 という事実を、「自分自身が ClusterProperty だということは、親が所有する ClusterProperty の中に自分が含まれるんだ」 という風にとらえることですかね。

このとらえ方をベタにコードにしてみると、Texture_Coordinates_AUTO.ClusterProperty と書けば ClusterProperty を取得できることになります。 でも実際のコードはこの書き方になりません。 実際の書き方については後述します。




ともかくも、親オブジェクトが持つ ClusterProperty という認識がここでできました。では、次に親オブジェクトである Texture_Coordinates_AUTO とはいったい何なのか? を考えます。 同様に SDK Explorer で見てみると、
Tcood_explorer
はい、Cluster であることが分かります。Type は sample です。 
ってことは、親が所有する Cluster を取得して、その中の sample というタイプのものだけを取り出せばいいんだ」 と想像します。


このように、自分自身が○○である、とわかったら、親が持つ○○の中から自分を探せば良い、という認識を育てると良いような気がしていますが、どうですか。どうですかって言われても困りますよね。 でも、どうですか。 円熟スクリプターのあなた、どうですか。





ってことでもうめんどくさくなったので思考過程の説明は終わりにして、コードを順に解説します。


for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);

     .................
}


まあこれはもういいですよね。 Selection の for ループで i 番目の人を取得しています。ユーザが選んでいる(複数かも知れない)オブジェクトの中の1つを取り出したということです。 これで基点になる3Dオブジェクトを、オブジェクトとして取得できました。



次に Primitive を取得しますが、ここはひとつずつ取得するとめんどくさいので、その次に取得するべき Clusters までイッキに取得します。

 var oClusters = oObj.ActivePrimitive.Geometry.Clusters;

これはこういうもんだとカンニングで覚えちゃってもいいかとは思いますがね。
ちなみに、もしイッキに取得せずひとつずつ行くなら、

 var oPrimitive = oObj.ActivePrimitive;
 var oGeometry = oPrimitive.Geometry;
 var oClusters = oGeometry.Clusters;


と3行に分けて書いても結果は同じです。上の書き方では、長くなるのを嫌ってドットでつないでイッキに Clusters までたどり着いているというだけで、目的によってはこのように分けて書いた方が便利な場合もあるでしょう。

で、Explorer 上ではPolygon Mesh となっていますが、その横に P のアイコンがありますよね。 これを Primitive オブジェクトといいます。 3Dオブジェクトのカタチを決めているオブジェクトです。 例えばヌルにも Primitive があり、同様に P のアイコンがあり、ヌルのカタチを決めています。 X3DObject には全部 Primitive があります(たぶん)。 

そして Primitive オブジェクトを取得するには xxx.ActivePrimitive という書き方になります。 oObj.Primitive.Geometry.Clusters と書かずに oObj.ActivePrimitive.Geometry.Clusters と書いているのはそういった理由からです。 これはもう文法なので、覚えるしかない。

そしてその下に Geometry オブジェクトがあります。 この Geometry は、上記の階層の中には含まれていませんね。これについての説明は上手くできません。俺もよく分かってないからです。ともかく、Cluster は Primitive オブジェクトの直下に存在するのではなく、Primitive 直下に存在する Geometry のさらに下に存在するんです。これは丸暗記で勘弁してください。クラスタというものはこういう階層構造で存在するのだと覚えちまいましょう。  

少し正確に言うと、ここでは ActivePrimitive プロパティを使って取得できたPrimitive オブジェクトの Geometry プロパティを使っています。Primitive.Geometry という書き方をすると Geometry オブジェクトが返ってくるので、返って来た Geometry オブジェクトの Clusters プロパティを使って ClusterCollection にアクセスしているのです。

余談ながら、なんで Primitive にアクセスするためには ActivePrimitive と書かなければいけないのに、Geometry にアクセスするときは ActiveGeometry ではなくただの Geometry になるのか、その理由がよく分かりません。 何かロジカルな理由があるんでしょうか?

さらに余談ですが、例えばヌルは1点の情報しか持っていませんのでジオメトリは存在しないということになり、この Geometry オブジェクトも存在しません。Geometry オブジェクトが無いということは、ヌルにはクラスタが作れないということになります。 その一方、例えば Curve ですが、レンダリングできるジオメトリが無いという意味ではヌルと同じですが、3D空間上には1点ではない実体が厳然としてあります。だから Curve.Primitive の下にはヌルと違って Geometry が存在し、その下に Clusters も存在できます。





で、Clusters までたどり着いたわけですが、Logmessage で取得したものを表示させています。

    Logmessage( oObj + " が持っている Cluster の数 -- " + oClusters.count );

デバッグです。ちゃんと取得できているかどうかを確認するために、いちいち Logmessage を入れるクセを付けた方がいいと思います。

ここで重要なのは Clusters で取得できたものは ClusterCollection であり、Cluster そのものではないということです。Geometry オブジェクトのヘルプページに行き、Clusters プロパティのリンクをたどってみて下さい。Clusters プロパティのページに飛ぶわけですが、
Sdkg_clustersproperty
ClusterCollection が戻り値だよと明確に書かれています。 そもそもコレクションだからこそ count というプロパティが存在するわけです。  count は集合体(コレクション)の中に含まれるオブジェクトの 「数」 です。コレクションではない単体オブジェクトは数が最初から1だとわかっているので、count なんていう意味のないプロパティはありません。 だから、count を表示させようとして「そんなメソッドやプロパティはサポートされてねえぜゴルァ」とエラーが出たら、コレクションを取得しようとしているのに、どうやらコレクションではないもの(例えば単体オブジェクト)を取得しちまってるらしい、と気づくことができます。 これがデバッグです。 なんでも Logmessage でデバッグしましょう。


それにしてもこの日本語 SDK ガイド、「 Cluster を含む ClusterCollection 」 って紛らわしい翻訳ですね。なんとなく、Cluster 以外のものも含まれているんじゃないかという誤解を与えかねません。 ClusterCollection には Cluster オブジェクト以外含まれていないんだから、「 Cluster を含む ClusterCollection 」なんて書かないで「Cluster が入ったClusterCollection 」とか「Cluster が格納されている ClusterCollection 」 と言うべきなんじゃないの。わかってますか、ローカライズしたあなた。そうあなたです。




ってことで、このコレクションをループして Cluster ひとつひとつを取り出します。それが次。↓

 for ( var j=0; j<oClusters.count; j++ )

はい、これで ClusterCollection に入ったブツの数だけ繰り返すループが発生しました。ちなみにクラスタを持たないオブジェクトが処理対象になっていた場合、count はゼロになるので、ゼロ回のループが発生します=つまりループは発生しません。 なので、クラスタがないオブジェクトは無視されるだけで、特にエラーで止まったりはしません。



次に、

        var oCluster = oClusters(j);
        Logmessage( "  (Cls " + (j+1) + ") " + oCluster + " : Type = " + oCluster.type );


oCluster の中に oClusters の中の j 番目の人を格納しています。 oCluster への代入は必須ではありませんが、代入しないと以降の行で常に oClusters(j) と書かねばならずコードが見にくいですし、今はコレクションの中から単一のものを取り出せているぞと意識するためにも、ひとまず代入することにしています。

2行目の Logmessage は、またもやデバッグのために結果を表示しているだけです。単一のクラスタについて、名前と、クラスタのタイプを表示しています。 もしそのオブジェクトが、例えばエンベロープを持っていたら、pnt(ポイント)というタイプのクラスタもログされるはずですし、マテリアルのためのポリゴンクラスタがあったりすると、poly(ポリゴン)というタイプのクラスタもログされるはずです。 後で sample というタイプだけ抜き出すので、色んなタイプのクラスタの中からちゃんと目的の物が抜き出せているかチェックするために Logmessage しているということです。




さ、ではそのクラスタが、目的のタイプである sample かどうかを調べましょう。

    if ( oCluster.type == "sample" )

そのまんまです。 oCluster の Type プロパティが sample であるかどうかをチェックしています。 sample でない場合、つまり上記の pnt や poly というタイプのクラスタだった場合は、以下の { } の中は実行されず、スルーしてループが進みます。 

はい、これで sample クラスタだけを選別することができました。上記の SDK Explorer で調べた結果 Texture_Coodinates_AUTO の正体は sample クラスタだとわかっているんですから、ここで初めて Texture_Coodinates_AUTO を取得できたことになります。 イエイ。




今度は、取得できた Texture_Coodinates_AUTO の子供のうち、Texture_Projection の正体である ClusterProperty を探します。

        var oClusterProperties = oCluster.LocalProperties;
        Logmessage( "    " + oCluster + " が持っている ClusterProperty の数 -- " +  oClusterProperties.count );


はい、またコレクションとして取得しました。 取得できた結果 oClusterProperties に入ったのは、ClusterPropertyCollection です。 この取得のために、Cluster オブジェクトに使えるプロパティのひとつ、LocalProperties プロパティを使いました。

LocalProperties はどうやって調べたかと言うと、まず上記の SDK Explorer での調査でTexture_Projection は ClusterProperty だということがわかったんだから、素直に SDK ガイドで ClusterProperty のページを見ます。

Sdkg_clsprop
はい、赤線の部分のような記述がありました。 

む。 まずいなこの表記は。 ここの「クラスタプロパティ」はカタカナではなく ClusterProperty と書くべき所だ。こら、ローカライズしたあなた、わかってますか。 あなたです。 ま、俺も厳密に使い分けられてないですけどね。

ともかく、ClusterProperty を取得するには、親オブジェクトの LocalProperties プロパティを使えとマニュアルに書いてあるわけです。 ただし、実はこの記述を見つけられなかったとしても簡単に取得の方法がわかる場合があります。これは後述します。



はい、ともかく ClusterPropertyCollection が取得できました。Logmessage で確認もしました。


次に、例によってコレクションなのでループして1つ1つ取り出します。

        for ( var k=0; k<oClusterProperties.count; k++ )
        {
     ............
        }


はい、ただのループです。取得できた ClusterPropertyCollection の中身の数だけ繰り返します。 ではループの中身行きます。

    var oClusterProperty = oClusterProperties(k);
    Logmessage( "      (ClsProp " + (k+1) + ") " + oClusterProperty + " : Type = " + oClusterProperty.type );

はい、また例によって、必須ではないけれど ClusterPropertyCollection の中から個別の ClusterProperty を取り出して代入しただけです。 そしてしつこく Logmessage をしています。 取得できた個別の ClusterProperty のタイプを表示しています。



そしてようやく、

        if ( oClusterProperty.type == "uvspace" )
        {
            Logmessage( "      #### ↑ これは Texture_Projection っス。####" );
        }


そのタイプが uvspace であるかどうかの判別をしています。 uvspace だった場合は、それはもう Texture_Projection です。 なので、 if のあとの最初の角カッコ { } の中が、Texture_Projection を取得できた場合です。 この例では これは Texture_Projection っス と Logmessage しているだけですが、実際に自分がやりたい処理をここに書けばいいでしょう。 oClusterProperty の中身に入っているんだから、あとはこいつを煮るなり焼くなり揚げるなり自由です。 完成。 イエイ。




以上。 うはー なげえ。 解説が長すぎてかえってわけがわからなくなっているという、典型的なダメパターンですか? やかましいノルァ



でもほんとに長くてわかりにくいと思うので、Logmessage などを廃してコメントを付けた省略バージョンを載せときます。

for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);    //    ユーザが選んでいるものを取得
    var oClusters = oObj.ActivePrimitive.Geometry.Clusters;// そこから、ClusterCollection を取得

    for ( var j=0; j<oClusters.count; j++ )
    {
        var oCluster = oClusters(j);    //    ClusterCollection の中から、1つの Cluster を取得
        if ( oCluster.type == "sample" )    //    そいつが sample という Type だったら以下を実行
        {
            var oClusterProperties = oCluster.LocalProperties;    // LocalProperties を使って ClusterPropertyCollection を取得   

            for ( var k=0; k<oClusterProperties.count; k++ )
            {
                var oClusterProperty = oClusterProperties(k);    //    ClusterPropertyCollection の中から1つの Cluster Property を取得
                if ( oClusterProperty.type == "uvspace" )    //    Type が uvspace だったら、そいつはめでたく Texture_Projection(゚∀゚)
                {
                    Logmessage( "      #### ↑ これは Texture_Projection っス。####" );    //    ここにやりたい処理を書く
                }
            }
        }
    }
}


こんなんでどうですかね。 一度解説をナナメ読みした後では、こっちの方がわかりやすい気がします。




さて、まだ続きます。 省略した書き方です。



上の例では、Cluster の Type が sample かどうかを調べるのに if を使いました。 ClusterProperty の Type が uvspace かどうかを調べるためにも if を使いました。 構造としてはわかりやすいと思うんですが、コードが長くなりがちです。構造を一度わかってしまえば、もっと簡単に書きたくなるものです。 そして簡単に書く方法はあります。 以下のように書けます。

for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);
    var oSampleClusters = oObj.ActivePrimitive.Geometry.Clusters.Filter( "sample" );//最初から sample という Type の Cluster しか取得しない

    for ( var j=0; j<oSampleClusters.count; j++ )
    {
        var oSampleCluster = oSampleClusters(j);
        var oUVs = oSampleCluster.LocalProperties.Filter( "uvspace" );//    最初から uvspace という type の ClusterProperty しか取得しない
        for ( var k=0; k<oUVs.count; k++ )
        {
            var oUV = oUVs(k);
            Logmessage( oUV + " は Texture_Projection ですので、煮るなり焼くなり揚げるなり蒸すなり、ご自由にどうぞ。" );
            //    ここにやりたい処理を書く。 Filter によって、Texture_Projection 以外は取得してないので、安心してどうぞ。
        }
    }
}


さっきのスクリプトを改造しました。結果は全く同様、Texture_Projection が取得できます。 ここで使っているのは Filter メソッドです。


 var oSampleClusters = oObj.ActivePrimitive.Geometry.Clusters.Filter( "sample" );

青字の部分までは、さっきのスクリプトと全く同じです(変数の名前は oSampleClusters に変えていますが)。 つまり、青字部分だけで ClusterCollection が取得できることはわかりますよね。

で、取得できた ClusterCollection に対して、Filter メソッドを使います。赤字部分です。 カッコの中は Type です。 

マニュアルで見ましょう。 該当ページへのたどり着き方は何度も書いているように、親である Geometry オブジェクトの Clusters プロパティをクリックすると、当然 Clustersプロパティのページに着き、Clusters は ClusterCollection を返すぜという記述があり、その ClusterCollection のリンクをクリックすると、当然 ClusterCollection のページに着き、そのページで ClusterCollection で使えるメソッドのひとつ Filter があるのでクリックする、という芋づるをたどります。

Sdkg_filter 細かいことはおいといて、カッコの中に書く最初の引数が Type だと書いてありますね。 先の SDK Explorer による調査で sample という Type が欲しいとわかっているので、そのまんま "sample" と書けばいいわけです。

すると、oSampleClusters には最初から Filter の条件に一致したオブジェクトしか格納されません。 さっきまでは、ともかく Cluster を全部取得して、その後で中身を1個1個調べて sample かどうかを if 分で判別していたわけですが、めんどくさいので最初から sample という type 以外は無視しろやゴルァ と書いているのです。 仮に sample というタイプのものが無かった場合は、oSampleClusters には何も入らないので、null かどうか、あるいは count がゼロかどうか、などで調べられるでしょう。 この例の場合は、もしゼロだったらそもそも次のループが発生しないので、スルーされるだけです。 楽ちんです。

で、取得できた oSampleCluster の中から(この中には sample タイプの Cluster しか入っていない)、ひとつずつループし、ClusterPropertyCollection を得るために LocalProperties を使っているんですが、同様に Filter で uvspace を指定しているので、oUVs の中には最初から uvspace 以外のものは入りません。 つまり Texture_Projection 以外のものは入りません。

   var oUVs = oSampleCluster.LocalProperties.Filter( "uvspace" );

楽ちんですね。



このように、コレクションに対しては Filter メソッドが効く場合が多いので、特定のものを判別したいときによく使います。 ま、でも、実際は Filter の存在を忘れて if とか書き出しちゃう場合も多いんですがね。







まだ続いてしまいます。





上で、「ClusterProperty を取得するには LocalPropertis を使え」という表記が見つけられなかったとしても大丈夫だ、という意味のことを書きました。 それについての説明です。


結論から書くと、以下の書き方でも挙動は同じです。

for ( var i=0; i<Selection.count; i++ )
{
    var oObj = Selection(i);
    var oSampleClusters = oObj.ActivePrimitive.Geometry.Clusters.Filter( "sample" );

    for ( var j=0; j<oSampleClusters.count; j++ )
    {
        var oSampleCluster = oSampleClusters(j);
        var oUVs = oSampleCluster.Properties.Filter( "uvspace" );//Properties でOKよ
        for ( var k=0; k<oUVs.count; k++ )
        {
            var oUV = oUVs(k);
            Logmessage( oUV + " は Texture_Projection ですので、煮るなり焼くなり揚げるなり蒸すなり、ご自由にどうぞ。" );
        }
    }
}




LocalPropertiesProperties に変えただけです。

では、LocalProperties じゃなくて Properties でも良いのだ、という情報をどうやって得るかというと、

 1.Explorer のアイコンを見て想像する
 2.SDK Explorer の ClassName から想像する
 3.SDK Explorer の Supported Object Model Interfaces から判断する


この3つかなあ。


まず1なんですが、Texture_Projection は、Explorer 上で白黒のグラデーションアイコンですよね。 このアイコンは、XSI の中でそいつは Property だ、ということを表します。
Propertyicon

例えば Kinematics や Visibility なども同じアイコンなので、 Property です。


今回の場合、

 Texture_Projection を取得したい → アイコンを調べたら白黒グラデだ →
 じゃあこいつは Property なんだな → だったら親オブジェクト.Properties が効くんじゃねえの


という思考回路を働かせればいいと思います。 

本来は、最初に SDK Explorer で調べたように Texture_Projection の正体は ClusterProperty なわけですが、おそらくは ClusterProperty は Property の一種類であるので、アイコンは同じものだし、Properties プロパティによって取得できる、ということなんだと思います。

このように Explorer でアイコンを見てブツの種類やそいつに使えるメソッド・プロパティを想像するというのは、けっこう有効な方法だと思います。 例えば Cluster の場合はあの青いアイコンですよね。 あれを見れば「あ、クラスタだ」 とわかります。 Texture_Projection は白黒グラデアイコンだからプロパティであり、しかも青いアイコンの下だからクラスタにぶら下がっているんだ、という理解があるだけで、マニュアルを調べるのもすんげえ楽になりますからね。 Clusters は白いフォルダのアイコンですが、これは何らかの Collection である場合が多いです。今回の場合は ClusterCollection ですね。

ちなみに、Properties プロパティを使って白黒アイコンのものを取得できるからと言って、Properties プロパティを使って取得できるものは白黒グラデアイコンのものだけだ、という話にはなりません。 例えば Material も Properties を使って取得できるもののひとつです。 



次に2と3ですが、SDK Explorer から端緒をつかみます。
Tp_explorer2

2に関しては、はい、ClassName が ClusterProperty なので、ああ、これって Property の一種なんじゃねえの? と想像してるだけです。 想像したら試しに使ってみて、結果がどんな場合でも変わらなく正しい場合は、うん、これは正しいのだろう、と想像にまかせたままスクリプトを書いてしまいます。 例外が出てきたらそのとき考えればいいんです。


3に関しては、SDK Explorer の中で明示されていると言ってもいいかと思います。 Supported Object Model Interfaces のところに、Property と書いてあります。つまり、この ClusterProperty というオブジェクトは、Property と同じメソッド・プロパティをサポートしてるよという意味だと思いますたぶん。 Property と同じなら、Properties プロパティを使って取得できないわけがないじゃないですか。 ってことで、自分自身の親になるオブジェクトに対して Properties の呪文を唱えてやると、自分自身が含まれたコレクションが返ってくるぞと想像できます。


このように俺はいつも、アイコンや SDK Explorer の記述から取得の仕方を想像しながら進めてますね。 あんまりロジカルにわかってなくても、想像さえつけばなんとか端緒がつかめるので、端っこさえつかんでしまえば後は芋づるです。 スクリプト書くのは芋掘りと同じなんです。


その6おわり。ふう。




うーむ、カンニングというよりは、取得方法がわからないときの思考過程の紹介に労力を費やしてしまっている気がするな。 でもまあ、載せたコードをそっくりコピペすれば Texture_Projection は取得できるわけだから、まあカンニングにもなってますわね。

もっとスマートなコードの書き方もあるでしょうねえ。でも俺は上記のような思考過程をたどっている感じなので、おのずと出てくるコードはこんな感じになるんですよ。 スマートかどうか、簡潔かどうかなどはひとまずおいといて、あるロジック(ある思考過程)に基づいて書けたかどうかで、満足度が違う気がします。 ロジックを無視するのがコピペ=カンニングですかね。 でも何度も言うように、ロジックはカンニングしてるうちにわかってくるものなので、やっぱりカンニングは必要なわけですよ。




.ふう。
またネタを見つけたら書くかも知れません。
ふう。



.

|

« ガッデムPlot。 | トップページ | リージョンさん。 (XPOP普及委員会その15) »

コメント

コメントを書く



(ウェブ上には掲載しません)




トラックバック


この記事へのトラックバック一覧です: 取得 その6。:

« ガッデムPlot。 | トップページ | リージョンさん。 (XPOP普及委員会その15) »