ユーザーブロマガは2021年10月7日(予定)をもちましてサービスを終了します

頂点法線とオブジェクトスペースノーマルカラーを行き来するスプリクトを作りたい「Blender+Python」
閉じる
閉じる

新しい記事を投稿しました。シェアして読者に伝えましょう

×

頂点法線とオブジェクトスペースノーマルカラーを行き来するスプリクトを作りたい「Blender+Python」

2015-08-09 20:15

    一応これまでちょこちょこpythonさわってみてたのと
    Web上に転がってるサンプルをコピペ&改変してできたところまで貼っとく
    現在では頂点法線を頂点カラーでオブジェクトスペースノーマルマップのカラーにするほうはできたっぽいけど
    (このあとはベイクとかでテクスチャとして吐き出せるんじゃない?という見込み)
    その逆である頂点色から頂点法線方向への上書きが上手くいかないの状態
    なんか調べづかれたので一度現状スクリプト貼って置く


    注意:なんかコピペしたらインデントの高さなくなっちゃったのでその編集し直さないとうまく実行されない
    ----------------ここから-------------------
    import bpy


    class NormalColorImput(bpy.types.Operator):

    #ボタン押して呼び出すときの名前
    bl_idname = "object.normal_imput_operator"

    #ボタンに表示するときの名前
    bl_label = "Normal -> Color"

    def execute(self, context):

    #選択中オブジェクトを順番に処理するためのfor?
    for object in bpy.context.selected_objects:
    #選択オブジェクトがメッシュかどうか判定
    if object.type == 'MESH':
    #選択オブジェクト取得
    bpy.context.scene.objects.active = object

    #新規頂点カラーグループを追加
    bpy.ops.mesh.vertex_color_add()

    #作成したばかりのグループを現在の名称(Col)からNormalColorに変更
    bpy.context.object.data.vertex_colors["Col"].name = "NormalColor"

    #取得したオブジェクトのメッシュをさらに取得?
    #メッシュ取得しないと各種頂点情報取れない?
    mesh = object.data

    #頂点カラー取得して色をセットする準備
    VertexNormalColor = mesh.vertex_colors["NormalColor"]

    #ポリゴンを一つ一つ処理?
    for poly in mesh.polygons:

    #ポリゴンの頂点を一つ一つ処理?
    for id in range( poly.loop_start, poly.loop_start + poly.loop_total ):

    #blnederではXが左右、Yが前後、Zが上下なことに注意
    VertexNormalColor.data[id].color.r = 0.5 - (poly.normal[0] / 2)
    VertexNormalColor.data[id].color.b = 0.5 - (poly.normal[1] / 2)
    VertexNormalColor.data[id].color.g = 0.5 + (poly.normal[2] / 2)


    #頂点カラーがハードエッジ的につくのでスムース
    bpy.ops.object.mode_set(mode='VERTEX_PAINT')
    bpy.ops.paint.vertex_color_smooth()
    bpy.ops.object.mode_set(mode='OBJECT')






    return {'FINISHED'}




    class NormalColorOutput(bpy.types.Operator):
    bl_idname = "object.normal_output_operator"
    bl_label = "Color -> Normal"

    def execute(self, context):

    for object in bpy.context.selected_objects:
    if object.type == 'MESH':
    bpy.context.scene.objects.active = object
    mesh = object.data


    #頂点カラーグループがあるかどうか、ある場合はその格納
    vcolor_array= mesh.vertex_colors.active.data if len(mesh.vertex_colors) else None


    for poly in mesh.polygons:

    for id in range( poly.loop_start, poly.loop_start + poly.loop_total ):

    vcolor= vcolor_array[id].color

    VerR = ( vcolor[0] * -2 ) + 1
    VerG = ( vcolor[1] * 2 ) - 1
    VerB = ( vcolor[2] * -2 ) + 1
    print( 'vcolorR=', VerR )
    print( 'vcolorG=', VerG )
    print( 'vcolorB=', VerB )

    #mesh.vertex[id].normal[0] = VerR
    #mesh.vertex[id].normal[0] = VerB
    #mesh.vertex[id].normal[0] = VerG

    return {'FINISHED'}





    class HelloWorldPanel(bpy.types.Panel):
    """Creates a Panel in the Object properties window"""
    bl_label = "Normal_Color_Panell"
    bl_idname = "OBJECT_PT_hello"
    bl_space_type = "VIEW_3D"
    bl_region_type = "TOOLS"
    bl_category = "Tools"


    def draw(self, context):
    layout = self.layout

    row = layout.row()
    layout.operator("object.normal_imput_operator")

    row = layout.row()
    layout.operator("object.normal_output_operator")

    def register():
    bpy.utils.register_class(HelloWorldPanel)
    bpy.utils.register_class(NormalColorImput)
    bpy.utils.register_class(NormalColorOutput)

    def unregister():
    bpy.utils.unregister_class(HelloWorldPanel)
    bpy.utils.unregister_class(NormalColorImput)
    bpy.utils.unregister_class(NormalColorOutput)

    if __name__ == "__main__":
    register()

    ----------------ここまで-------------------


    #mesh.vertex[id].normal[0] = VerR
    #mesh.vertex[id].normal[0] = VerB
    #mesh.vertex[id].normal[0] = VerG
    とかやってコメントアウトしているところで取り出した色の値から頂点の法線方向ぶち込みたいんだけど
    いろいろググっても(英語のページが多いせいもあるけど)なんかそのための命令文?みたいのが一向にひっかからない感じでうーん

    一応今そこだけテストするべくもっとシンプルなのを別にやってテストしてるんでそっちも貼っとくけど

    ----------------ここから-------------------
    import bpy


    print("----------------------------------------------")
    v = bpy.context.object.data.vertices
    for i in range(0, len(v)):
    print("Vertex index",v[i].index, "Normal", v[i].normal)
    v[i].normal = [1,1,1]
    print("Vertex index",v[i].index, "Normal", v[i].normal)

    #追記
    #一度表示を行き来しないと法線方向がシェーディングに反映されないっぽいのでその切替
    #自動スムースも切っておかないと駄目っぽいのでそれもやる(どういうデータの持ち方になってるのかまだよくわかってない)

    bpy.ops.object.shade_flat()
    bpy.ops.object.shade_smooth()
    bpy.context.object.data.use_auto_smooth = False
    print("----------------------------------------------")
    ----------------ここまで-------------------


    こっちだと二回printしている情報をコンソールでみるに

    ちゃんと頂点には法線方向セット出来ているはずなんだけど
    表示の方はさっぱり変わらないし
    追記
    一度オブジェクトの表示をスムースとフラット行き来させると変更した法線の表示になってくれる模様なのでその分スプリクトに追記
    ただすぐ下に書いた編集モード入ると解除されちゃう問題はまだ解錠できてないのと
    これだとちゃんとした頂点数に試行されるけど
    上手く行ってる法線->色変換だと1頂点につきその頂点が使われているポリゴン数分だけ試行されるのでなんかデータ的にちがう感
    その上英語のページで「これだと編集モードに入ったら法線もとにもどっちゃうんですけお!!」ってあったんだけどそのとおりでデータ的にも元に戻っちゃうっぽい


    もうここだけ上手く行けば自分的には最低限の用を成してくれるんだけど
    どうにもここがどうしたらいいのかわからない


    もちろん今回作ってるモデルがblender上で完結する分にはオブジェクトスペースノーマルマップ作れれば大丈夫なんだけど
    今回最終目標が一度MMDに持って行きたいっていうのがあるわけで
    MMDのシェーダーとか調べてみたけどどうもオブジェクトスペースのノーマルマップに対応したシェーダーとかなさそうなのよなぁ……
    そうなるとどうしても最終的に頂点法線方向に落としこむ必要があるわけでうーん……

    とにかくIQ低いおじさんにはもうちょっと思考力限界なので
    いちど現状だけこっちに愚痴的に吐き出して後日またしらべることにする


    追記
    後なんか今頂点色への変換の方は上手く動いているっぽいけど
    頂点の法線方向じゃなくてポリゴンの法線方向を色変換してる気がいましてきた
    それでも今のところは最低限はできてるとは思うけども多分……

    setNormal()とかいうのがあるっぽくて其れが怪しいのであとでググる
    ちがったそのWebページで公開しているスクリプトのオリジナルのclassの何かだった

    さらに追記
    今ノーマルから頂点カラーは一見上手く言ってるけど
    よーく考えるとというた多分blenderはデータ的に普通の頂点法線とカスタム法線の二種類あるっぽくて
    今色つけるために取得してるのどっちの法線なのかわからんので其れも知らべないと駄目だ
    カスタム法線取得できてないと色々意味ない
    さらにさらに追記
    思った通り通常の法線取得して色つけててカスタム法線の取得ではなかった
    これじゃ単純な形状のオブジェクトの法線焼き付けて単純化したノーマルマップをとりだすことができないじゃんかよ
    なおカスタム法線へのアクセス方法を今必死にググっている模様


    http://www.blender.moe/2014/07/blender.html
    エディットモード入ると法線リセットされるのと
    カスタム法線のことについてnスクリプトあるっぽいのであとでみる


    広告
    コメントを書く
    コメントをするには、
    ログインして下さい。