FC2ブログ
*admin*entry*file*plugin| 文字サイズ  

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。



以前に公開したアドオンをちょっと改良したのでその紹介です
動作は「選択領域」を基に「一つ飛ばし」で頂点を選択する
というもので、基本的に領域拡大しか出来ませんでした。
あと、ボタンを何度も押す必要があるのでそこの改良です。

データはこちらのページに置いてあります
ここをクリック

改良後の全ソースがこちら


bl_info = {
"name": "Skip Select(Loop)",
"author": "Mithril",
"version": (0, 0, 2),
"blender": (2, 7, 9),
"location": "3DView > Tools > Skip Select > Edit Mode ",
"description": "Loop selection for one skip",
"tracker_url": "http://mithrilproject.blog66.fc2.com/",
"warning": "",
"category": "Tools"}

import bpy
import bmesh
from bpy.props import *

def SkipSelectMore(verts_back):
#Only Edit Mode
if bpy.context.object.mode != "EDIT":return {'FINISHED'}

obj = bpy.context.active_object
bpy.ops.object.mode_set(mode='EDIT')
#Vertex Mord
bpy.context.tool_settings.mesh_select_mode = (True, False, False)
mesh = bmesh.from_edit_mesh(obj.data)

#Get Select Vertex(s)
if ( verts_back == []) :
verts = []
i = 0
for vert in mesh.verts:
if vert.select == True:
verts.append(vert.index)
i = i+1
else :
m = 0
for vert in verts_back:
m += 1

verts = []
i = 0
for vert in mesh.verts:
if (vert.index == verts_back[i]) :
vert.select = True
verts.append(vert.index)
i += 1
if ( i == m ) : break

#Select More
bpy.ops.mesh.select_more()
#Select Inverse
bpy.ops.mesh.select_all(action='INVERT')

#Reselect
k = 0
for v in mesh.verts:
if k == i : break
if v.index == verts[k]:
v.select = True
k = k+1
if k == i : break

#Select Inverse
bpy.ops.mesh.select_all(action='INVERT')

verts_back.clear()

for vert in mesh.verts:
if vert.select == True:
verts_back.append(vert.index)

return verts_back


def SkipSelectLess(verts_back):
#Only Edit Mode
if bpy.context.object.mode != "EDIT":return {'FINISHED'}

obj = bpy.context.active_object
bpy.ops.object.mode_set(mode='EDIT')
#Vertex Mord
bpy.context.tool_settings.mesh_select_mode = (True, False, False)
mesh = bmesh.from_edit_mesh(obj.data)

#Get Select Vertex(s)
if ( verts_back == []) :
verts = []
i = 0
for vert in mesh.verts:
if vert.select == True:
verts.append(vert.index)
i = i+1
else :
m = 0
for vert in verts_back:
m += 1

verts = []
i = 0
for vert in mesh.verts:
if (vert.index == verts_back[i]) :
vert.select = True
verts.append(vert.index)
i += 1
if ( i == m ) : break

#Select More
bpy.ops.mesh.select_more()
#Select Less
bpy.ops.mesh.select_less()

#Reselect
k = 0
for v in mesh.verts:
if k == i : break
if v.index == verts[k]:
v.select = False
k = k+1
if k == i : break

#Select Inverse
bpy.ops.mesh.select_all(action='INVERT')
bpy.ops.mesh.select_all(action='INVERT')

verts_back.clear()

for vert in mesh.verts:
if vert.select == True:
verts_back.append(vert.index)

return verts_back

class UI(bpy.types.Panel):
bl_label = "Skip Select"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = 'Tools'

@classmethod
def poll(self, context):
obj = context.active_object
if obj and obj.type == 'MESH':
return{'FINISHED'}

def draw(self, context):
row = self.layout.row(align=True)
row.operator('skip.select', icon='LATTICE_DATA')
row.enabled = len([o for o in context.selected_objects if o.mode == 'EDIT'])

class Skip_Select(bpy.types.Operator):
bl_idname = "skip.select"
bl_label = "Select (More)"
bl_options = {'REGISTER', 'UNDO'}

repeat_c = IntProperty(name='Repeat',
description='Repeat Count',
min=0,
max=100,
default=0)
count = 0
verts_back = []

## EXECUTE #######
def execute(self, context):

obj = bpy.context.active_object
more = self.repeat_c- self.count
#print(self.count)
#print(self.repeat_c)
#print(more)
#print(obj.data.total_vert_sel)

if ( self.count == 0 ) :
self.repeat_c = 1
more = 1
self.verts_back = []

verts_back = self.verts_back

if ( more == 1 ) :
SkipSelectMore(verts_back)
elif ( more == -1 ) :
SkipSelectLess(verts_back)
elif ( more > 1 ) :
for i in range(more) :
SkipSelectMore(verts_back)
elif ( more < 1 ) :
for i in range(more * -1 ) :
SkipSelectLess(verts_back)

self.verts_back = verts_back
self.count += more
if ( self.verts_back == [] and self.count == 0) :
self.repeat_c = 0
return {'FINISHED'}

### REGISTER ######

def register():
bpy.utils.register_module(__name__)

def unregister():
bpy.utils.unregister_module(__name__)

if __name__ == '__main__':
register()



まず最初に「追加のプロパティ」を設定します。


class Skip_Select(bpy.types.Operator):
bl_idname = "skip.select"
bl_label = "Select (More)"
bl_options = {'REGISTER', 'UNDO'}

repeat_c = IntProperty(name='Repeat',
description='Repeat Count',
min=0,
max=100,
default=0)
count = 0
verts_back = []

とりあえずこれで追加だけならできるみたいです。
数値変更は出来ますが特に何も動作はしません。
追加の変数も2つほど入れてます

「count」は「ツールのボタンを押した」時の動作で
「初期化」させるようにしています。

「verts_back」は頂点の一時保管場所として定義


そして、メインの処理がこちら


#Get Select Vertex(s)
if ( verts_back == []) :
verts = []
i = 0
for vert in mesh.verts:
if vert.select == True:
verts.append(vert.index)
i = i+1
else :
m = 0
for vert in verts_back:
m += 1

verts = []
i = 0
for vert in mesh.verts:
if (vert.index == verts_back[i]) :
vert.select = True
verts.append(vert.index)
i += 1
if ( i == m ) : break


結果的に特に大した処理をしているわけではないのですが、
どうも、ボタンを押すのとプロパティを操作するのでは
挙動が異なるらしく同じような処理が出来ませんでした。

「プロパティ」が更新されても「頂点情報が更新されない」
という罠にひかかりまして、それで一時保管場所を作りました
「領域縮小」はただ単に逆の動作になっているだけです。

使うと解かりますが、メッシュの頂点数の上限までやっちゃうと
プロパティの動作では戻らなくなっちゃいます。
このときは一度プロパティを「0」にすると初期化されます

処理速度について
最初に改良していたのはこんな感じで


verts = []
i = 0
for vert in mesh.verts:
for m in verts_back :
if vert.select == True and vert.index == m :
verts.append(vert.index)
i += 1
elif (vert.index == m) :
vert.select = True
verts.append(vert.index)
i += 1


これでも、動作するのですが使ってみるとめっちゃ重いです。
理由は簡単で「全ての頂点情報ひとつひとつ」に対して
「保管されている頂点」全てを照合させているから、
そりゃぁ重くなるよ。で、処理を軽くするために
今のソースになってます。一応「サブディビジョンサーフェス」
「10」の後に更に「2」をかけたぐらいの密度なら
ストレス無く動作します、多分

やりすぎるとBlenderが落ちるので程々に
使う使わないは別にして、アドオン作成のお勉強にはなったかな?


スポンサーサイト


また、久しぶりの更新ですが
今回アップしたアドオンについての説明です。
何をするものかというと・・・

これを簡略化できないかなぁ・・・

こういう選択を簡単に行うためのものです。
「何に使うねん」っていうと「ポリゴン削減」が
主な目的ですかね・・・

すでにあるかもしれませんが見つけられ
なかったので作ってみました。
最初に選択されている頂点が基準になります
これにより縦向きか、横向きかを決めます。
アドオンの作り方の勉強にもなるし良いかなぁって
実行すると・・・

これが
これを簡略化できないかなぁ・・・

こうなります
これを簡略化できないかなぁ・・・
ボタンを押すほど選択範囲が広がります。

物自体はココに置いてあるのでお好きにどうぞ
ここをクリック

ソースコードはこんな感じです


#アドオンの情報
bl_info = {
"name": "Skip Select(Loop)",
"author": "Mithril",
"version": (0, 0, 1),
"blender": (2, 7, 9),
"location": "3DView > Tools > Skip Select > Edit Mode ",
"description": "Loop selection for one skip",
"tracker_url": "http://mithrilproject.blog66.fc2.com/",
"warning": "",
"category": "Tools"}

#必要なインポート
import bpy
import bmesh

#メインの処理
def SkipSelect():
#エディットモードじゃなければ終了
if bpy.context.object.mode != "EDIT":return {'FINISHED'}

obj = bpy.context.active_object
#エディットモードに変更(別に要らないけど)
bpy.ops.object.mode_set(mode='EDIT')
#頂点モードに変更
bpy.context.tool_settings.mesh_select_mode = (True, False, False)
mesh = bmesh.from_edit_mesh(obj.data)

#選択頂点取得
verts = []
i = 0
for vert in mesh.verts:
if vert.select == True:
verts.append(vert.index)
i = i+1

#選択範囲拡張
bpy.ops.mesh.select_more()
#インバース選択
bpy.ops.mesh.select_all(action='INVERT')

#選択頂点を再選択
k = 0
for v in mesh.verts:
if k == i : break
if v.index == verts[k]:
v.select = True
k = k+1
if k == i : break

#インバース選択
bpy.ops.mesh.select_all(action='INVERT')

class UI(bpy.types.Panel):
#UI情報
bl_label = "Skip Select"
bl_space_type = "VIEW_3D"
bl_region_type = "TOOLS"
bl_category = 'Tools'

#オブジェクトが「メッシュ」以外だと非表示
@classmethod
def poll(self, context):
obj = context.active_object
if obj and obj.type == 'MESH':
return{'FINISHED'}

#ボタン配置
#エディットモード以外だとグレーアウト
def draw(self, context):
row = self.layout.row(align=True)
row.operator('skip.select', icon='LATTICE_DATA')
row.enabled = len([o for o in context.selected_objects if o.mode == 'EDIT'])

#ボタン押したら実行するやつ、たぶん
class Skip_Select(bpy.types.Operator):
bl_idname = "skip.select"
bl_label = "Select (More)"

### EXECUTE #######
def execute(self, context):
SkipSelect()
return {'FINISHED'}

#インストールとアンインストールの処理
def register():
bpy.utils.register_module(__name__)

def unregister():
bpy.utils.unregister_module(__name__)

if __name__ == '__main__':
register()


まず最初のところはアドオンの情報ですね
インストール時にこのあたりに表示されたり。

アドオンの情報

その次は必要なインポートで「bpy」「bmesh」の
2つ入れてます、「bpy」はほぼ確実に必要なものですね。

で、次の「SkipSelect()」が今回作ったメインの部分
手動でやるところをコードに起こしただけですが、

①選択された頂点を取得
②選択範囲拡張
③インバース選択
④①を再選択
⑤インバース選択

これをやってるだけ

本当は
①選択された頂点を取得
②選択範囲拡張
③①を非選択

これでもいけるはずなんだけど、何故かうまくいかなくて
ちょっと回りくどいやり方になってます。
その他の具体的なコードの説明は冒頭のソースコードの
コメントにしてるのでそれを参照していただければ。

「Run Script」で行うだけなら「SkipSelect()」の
中身だけで事足りますが、アドオンにするときはインストール
やらボタンやらレジストリやらなんやかんやついてきて
まぁ、面倒ですね。

「SkipSelect()」の部分を外に出しているのはそのほうが都合が
良さそうだからで、「Class」の中でやるとどうも「print」が
使えないんですよね、これ使えないとデバックできないじゃん
ってことで外に出しました。

Blenderはマウスオーバーのときにソースコピーきますし、
「Python Console」使えば「Ctrl」+「スペース」でリスト出ますし
アドオン作る上では色々便利になってますね。

また何かあれば記事にするかも



「顔Rigでリップシンクを」
ということで、まずはこの話題です

私が作ったリップシンクのアドオンはシェイプキーが
ターゲットになっています。しかし、シェイプキー自体が
実はあまり使い勝手がよろしくない場合が出てきたりします。

なので、顔Rigを作って尚且つVSQからインポート可能な
状態を作りたいと思います。結論は出たのですが
結構回りくどいやりかたで、

手順は以下のとおりです

①リップシンクインポート用メッシュを別オブジェクトとして追加

②リップシンク用メッシュに各キーを登録する

③顔Rigを追加・編集しリップシンク用のメッシュに合わせる。

④コントローラー用メッシュを作成し適当に配置

⑤「CopyLocation」「CopyRotation」等を使いリップシンク用
メッシュに顔Rigを連動させる。

⑥必要キーの数だけ同じことを繰り返す。

⑧インポートテストをして動作確認

ってな感じですね。⑤の設定を切れば普通のRigとして扱えますし、
リップシンクのときだけ有効にして活用すればいいかも。

先日Twitterに上げたリップシンクの動画とほぼ同じ動作を
させることができます、モデル自身にはシェイプキーを使用して
いませんので多少融通が聞くようになったような気がします。



顔Rig動作確認



これと同じことができる、と思う。

ただ、セットアップがいささか面倒臭いです。
メッシュに合わせてボーンを配置して、「Stretch To」「Copy Location」
とか設定して、インポート用のメッシュ用意して等シェイプキー
に比べてやることが多いですね。

しかし、今回のモデルに実装しようかと思ったのですが、途中でバグに
遭遇してしまったので保留として普通にシェイプキーが入ってます。



下絵から始まりモデリングからリギングまで
一通りできたような気がします。

で、データ配布場所についてですが「uploader.jp」
に、とりあえず置くことにしました。

配布物は「ローソン鹿島さん」と「VSQインポーター」
の2点に今のところなっています。


ローソン制服
ローソン制服

ねこランジェリー
ねこランジェリー

セットアップは「Rigify + α」です。
踊らせても基本破綻しない・・・・はず。
衣類とかは物理演算前提にしています。


「VSQインポーター」についてですが、
ちょっと前にTwitterで紹介してから更に修正しています。
Versionが1.0.3になってるはずです。

Ver.1.0.3

基データ作ったの7年ぐらい前らしく、何やってるのか思い出すのに
ちょと時間がかかってしまいました。 修正したのはタイミング
のところですね。実は結構適当な数字が入っていた模様。
なので、ちゃんとタイミングの計算させてマッチさせました。



肝心のデータ配布場所リンクは

ここをクリック

パスワードは特に設定していません
そしたら削除・編集できなくなっちゃったよ(´・ω・`)
編集用のパスワードは設けないといけないみたいで・・・

良識の範囲内で使ってくださいね。
今日の記事はこのぐらいにしておきましょうか、ではでは。



さて、粗方モデリングができたのでセットアップを
順次進めていて、標準の「rigify」を使います。
使い方としては

①基礎となるボーンを「Shift+ A」 から挿入
使うのは「Human(Meta-Rig)」です

②モデルに合わせて各関節をスナップさせる

③ジェネレートさせる

④「29」レイヤーにウェイト用のボーンがあるので、
このボーンに対してウェイトをかける。
(自動設定でそれなりに設定してくれる)


⑤「IK」「FK」等の設定をしつつウェイトを
確認して必要があれば調節する。

⑥足りないボーン「髪」「目」「胸」「つま先」等を追加設定


⑦顔Rigはよくわからないからとりあえずシェイプキー

今はこんな状態になってます

セットアップ中

で、動かしてみたんですが印象が変わりますね。
歩行テストと胸を揺らしてみるテストをしています。




ウェイトがまだほぼ無調整なので可能な限り破綻しないよう
調節する必要があるのですが、メッシュの重なり等でどうしても
破綻してしまうようなところは動かすときは下のメッシュを
削除して使うようにする必要がありそうです。





DropboxにHP置いてたんですが、どうやら表示できない
ようになってしまっているようですね。
仕様変更されて「レンダリングできません」だって。
さて、どうしたものか、ここ(FC2)のHPはデータ置くと速攻で
削除されてしまったのでDropboxにしたんですが。
Dropboxのリンクだけ貼る形になるかもしれない・・・

で、作ってるモデルは「ローソン鹿島」さん

ローソン鹿島さん

ローソン鹿島さん

下着がねこランジェリーなのはただの趣味です。
服の縞模様どうしようかと思いましたが、Blenderで
縞模様作って編集・UV展開して貼っつけてます。
縞模様の作り方はこんな感じで

テクスチャノード

テクスチャノードで「Wood」を追加しますが、
デフォルトだと境界がぼやけててしかも傾いています。
それを「ColorLamp」と「Rotation」で修正します
(「Scale」は縞模様の間隔調節用)

しかし、どうもテクスチャノードは「Renderモード」
じゃないと見えないらしく「テクスチャモード」で見られる
ようテクスチャとして出力して画像を取り込んで反映
させるようにします。

適当に「UV/Image Editor」で画像を追加して「Bake」
あとはUV展開したところに貼り付けるわけですが、
私の場合マテリアルが全てノードベースにしているので
ちょっと普通とは違った?設定方法です。

テクスチャノード

UV展開を反映させるために最初に「UV」を引っ張ってきて
テクスチャを反映させて基のマテリアルに付け加えます。
これで普通のテクスチャ貼り付けと同じ結果が得られる
わけですが、この方法だと「Texture Paint」が使えないらしい。
やろうとしてもエラー吐きます、ちょっと不便かも。

「Texture Paint」を使うときはノード設定の前にしないと
ダメみたいで、仮設定しておけば良いのかな?


Mithril

Author:Mithril


趣味は主に雑学です。
どうでもいいこと書いてます。

Blenderやプログラムに
ついても書いたりするかも。
私のPC環境はこちら

メールはこちらから↓
mithrilp★yahoo.co.jp
(★を@に変えて下さい)

11 | 2018/12 | 01
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 - - - - -

QRコード
上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。