頭と尻尾はくれてやる!

パソコンおやじのiPhoneアプリ・サイト作成・運営日記


SceneKitでシェーダを適用すると不具合発生?

Blenderで二つのオブジェクト+1つのarmatureを持つオブジェクトを作成し、daeファイルとして出力。それをSceneKitで使おうとしたらすごくはまった、というか全然できない!というお話。
なお、オブジェクト1つ+1つのarmatureなら何も問題ない。

Blenderでオブジェクト作成

↑Blenderで円柱と直方体のオブジェクトを作成、1つのarmatureと親子関係を設定してる。

Blenderでテクスチャを表示

↑円柱、直方体それぞれテクスチャを割り当ててる(けど本筋には関係ない)。
これらをdaeファイルとして出力。

Scene Editorでオブジェクト構成確認

↑そのdaeファイルおよび2枚のテクスチャ画像をXcodeに持ってきた。
Armature,Cylinder,Cubeの3つが同列にある。

これをSceneKit使って表示させる。
{
    SCNScene *daeScene = [SCNScene sceneNamed:@"parts.scnassets/testObject.dae"];
    [mainScene.rootNode addChildNode:daeScene.rootNode];
}
SceneKitで表示したオブジェクト

↑意図通り表示されてる。
armatureがある場合は一番トップにある、つまり一番の”親”のボーンを動かせば全体の位置や姿勢をコントロールできる。ここでは3番めの画像にあるように’PBone’という名前を付けてる。
それに対応するSCNNodeオブジェクトをpBoneNodeとすると、
{
    pBoneNode.position = _position;
    pBoneNode.orientation = _orientation;
}
ってな感じで全体を動かせる。

ボーンの位置と姿勢をセットしたオブジェクト

↑pBoneNodeの位置を(1,0,0)にして、z軸周りに+45°回転させた。ここまでは完全に意図通り動いてくれてる。


ところが、や。


このオブジェクトにシェーダを使おうとしたんよ。
-(void)applyShaderForNode:(SCNNode *)node
{
    SCNMaterial *material = node.geometry.firstMaterial;
    
    SCNProgram *program = [SCNProgram program];
    program.vertexFunctionName = @"myVertex";
    program.fragmentFunctionName = @"myFragment";
    material.program = program;
    
    SCNMaterialProperty *imageProperty = [SCNMaterialProperty materialPropertyWithContents:@"paper5.jpg"];
    [material setValue:imageProperty forKey:@"mainTexture"];
}
↑こんな感じで特別なことはやってない。よくあるサンプルコードのままだろう。

画面をクリックしたらシェーダを適用するように実装したんだが、、、

シェーダを適用したオブジェクト

シェーダ適用後、円柱は意図通り表示されているのだが、直方体の位置、姿勢がおかしい。デフォルト値というか未設定の場合の値になってるような。
そもそもオブジェクト(ここでは直方体と円柱)の位置、姿勢を設定する必要はなく、armatureの各ボーンの位置、姿勢を設定すればいい。
その関係がシェーダ(SCNProgram)を使うとはずれちゃってるってことなんだろうか???
何かの設定不足、もしくはSceneKitの不具合なのか、、、?

何かご存知の方、お教えください〜 m(._.)m



ここからはおまけ。
正しい位置、姿勢で表示されてないってことはいわゆるmodel view matrix(*1)がおかしいのか?ってことでシェーダに各マトリックスを送って表示させてみた。さっきのシェーダ適用の部分にこんなのを追加した。
{
    SCNMatrix4 mvMatrix = pBoneNode.transform;
    NSValue *mvBuffer = [NSValue valueWithSCNMatrix4:mvMatrix];
    [material setValue:mvBuffer forKey:@"mvMatrix"];


    SCNMatrix4 cameraMatrix = [self cameraMatrix];
    NSValue *cameraBuffer = [NSValue valueWithSCNMatrix4:cameraMatrix];
    [material setValue:cameraBuffer forKey:@"cameraMatrix"];


    SCNView *scnView = (SCNView *)self.view;
    SCNMatrix4 projectionMatrix = scnView.pointOfView.camera.projectionTransform;
    NSValue *projectionBuffer = [NSValue valueWithSCNMatrix4:projectionMatrix];
    [material setValue:projectionBuffer forKey:@"projectionMatrix"];
}
これを頂点シェーダで受ける。
vertex SimpleVertex myVertex(MyVertexInput in [[stage_in]],
                             constant MyNodeBuffer &scn_node [[buffer(0)]] ,
                             constant float4x4 &mvMatrix[[buffer(1)]] ,
                             constant float4x4 &cameraMatrix[[buffer(2)]] ,
                             constant float4x4 &projectionMatrix[[buffer(3)]]
                             )
{
    SimpleVertex vert;
    vert.position = projectionMatrix * cameraMatrix * mvMatrix * float4(in.position, 1.0);

}
これなら正しく表示されるだろうと思ったら、、、

各マトリックスを適用したオブジェクト

↑なっ、なんでやねん?!なんで今度は円柱がおかしいのん?しかも原点でも元の姿勢でもないし。意味不明、、、orz

(*1)文献等により表現は違うようですが、つまるところ各頂点データにたいして、位置や姿勢を考慮したマトリックスの意味(カメラは除く)


Blender 2.79
macOS High Sierra 10.13.4


追記:この件、バグレポート出しました



<< MPSCNNConvolutionのイニシャライズができない  TopPage  SCNFloorの床にオブジェクトが映らない >>

コメント


管理者にだけ表示を許可する
 

トラックバック

トラックバックURL
http://ringsbell.blog117.fc2.com/tb.php/1136-17e0e480




Copyright ©頭と尻尾はくれてやる!. Powered by FC2 Blog. Template by eriraha.

FC2Ad