2012年2月29日水曜日

blender - 2.6 - pythonで面の面積(2)

前回で面積が出せました。

面積が分かると色々できますね!

とりあえず小さい順にソートして、小さいほうから選択してみると何か分かるかもしれませんね。

試しにミクさんの顔の面を、面積を小さいほうから150個くらい選択してみましょう


import bpy

context = bpy.context
context.tool_settings.mesh_select_mode = [True, False, False]

N = 150

if (context.active_object != None):
object = bpy.context.active_object

bpy.ops.object.mode_set(mode='OBJECT')

area_dict = {}

if (object.type == "MESH"):
faces = object.data.faces
vertices = object.data.vertices
for f in faces:
area_dict[f] = f.area

count = 0
for f, area in sorted(area_dict.items(), key=lambda x:x[1]):
if count < N:
for vi in f.vertices:
vertices[vi].select = True
count += 1

bpy.ops.object.mode_set(mode='EDIT')


途中、見かけないlambdaというやつがありますが、ぶっちゃけよく分かりません。
ソートするにはでググって出てきたのをそのまま使った程度です。

そして結果!


おお!おおおおお!これは何か分かりそうですね!(続く)

blender - 2.6 - pythonで面の面積

前回のを改造して面の面積を求めて見ます。

三角形の面積というと、
2Dでは、底辺x高さ÷2
3Dでは、外積の大きさ÷2
です。

BlenderはOpenGLで面の頂点番号もOpenGLと同じく、反時計回りです。

0
|
|
1---2

といった感じで三角形になっています。
よって、選択した三角形の面積を表示するなら次のようになります。


import bpy

context = bpy.context

if (context.active_object != None):
object = bpy.context.active_object

if (object.type == "MESH"):
faces = object.data.faces
vertices = object.data.vertices
for f in faces:
if (f.select):
vi = f.vertices
a = vertices[vi[2]].co - vertices[vi[1]].co
b = vertices[vi[0]].co - vertices[vi[1]].co
c = a.cross(b)
print(c.length / 2)



で、これをもっと簡単にして、さらに四角形にも対応させると、次のようになります。


import bpy

context = bpy.context

if (context.active_object != None):
object = bpy.context.active_object

if (object.type == "MESH"):
faces = object.data.faces
vertices = object.data.vertices
for f in faces:
if (f.select):
print(f.area)


さすがBlender、計算するまでもないですね!
(続く)

2012年2月26日日曜日

blender - pixivで開催されたUnityのためのCGとか勉強会に行ってきました

pixivで開催されたUnityのためのCGとか勉強会(第4回)に行ってきました。

実はこの勉強会、第1回にも参加させていただいたのですが、そのときは会場は大久保のルノアールでした。
いつのまにか会場がpixivになっていて、ずっと参加したいなーと思っていたのですが、ついに参加できました。

さて、pixivは、色々と凄いところでした。
入り口、うわさには聞いていたピクシブたんチャリ!




そして大量の壁絵。



中も撮りわすれたのですが、色々と凄いです!色々と凄いです。
pixivさん最高です!


遅れて到着したため、みんなもくもくと作業をしていたので、ちょっと外れたところの人が少なめの席に行っ
たら、なんということでしょう、ピクシブさんの中の人な席でした。

とりあえずBlender2.62の新機能を試したりしていたのですが、やはりネットブックだと厳しい。
そして皆やはりMac率が高いっ!MBA!MBA!
色々PC環境の準備が足りてなくて駄目な感じだったので、途中から参加者とか中の人と話をする方向でうろうろしていました。twitterなどで気になっていた方にも無事会え、前会った方にも会え、有意義な時間を過ごせました。

がっ、全く成果が出なかったため帰宅後に1人反省会を兼ねてBlender。
2.6になってなかなか付いていけてないですが、shapeがマシになったとか、booleanが良くなったとか、remeshが付いたとか、cyclesとか凄いことになってるんで、そろそろ本気出さないとヤバイですね!
というわけで、本日の成果。
2.6になってpythonのapi覚えなおさないといけなくてめんどかったです。

shapekeyで参照元の頂点と位置が違う部分を選択するスクリプト



import bpy

context = bpy.context

if (context != None):
if (context.active_object != None):
object = bpy.context.active_object

bpy.ops.object.mode_set(mode='OBJECT')

verts = []

if (object.type == "MESH"):
vertices = object.data.vertices
for v in vertices:
v.select = False
verts.append(v)

if (object.active_shape_key != None):
shape_key = object.active_shape_key
base = shape_key.relative_key
for i, v in enumerate(shape_key.data):
if (v.co != base.data[i].co):
verts[i].select = True

bpy.ops.object.mode_set(mode='EDIT')


これは何かというと、↓シェイプキーを選択して実行すると、こんな感じにシェイプの参照元と位置が違う頂点を選択してくれます。


これはBlender2.49で作った駄目なシェイプキーなので、口のシェイプのつもりだったのですが、
このように要らないところが動いてしまっています。
さらにその後にベースのメッシュをいじってしまったので、もう大変です。

しかし、最近のBlenderには、wキーを押したときに、"Blend from shape"という機能が付きました。

ちょっと動いてしまったところに、これを適用すると…



このように、口の周り以外の余計に動いてしまった部分を元に戻せます。


昔DirectXに持っていくときに、この辺でなかなか死んだ記憶があります。
たしか、目と口をシェイプでつけていて、重くならないように動く頂点だけ抽出しようとしたのですが、動く部分だけ切り出したときに頂点が点在すると面にならないので、vertexgroupオプションでshapekeyの範囲を絞って頂点を切り出すのですが、vertexgroup範囲外の微妙に動いている頂点をなんとかしようとpropagateしたらもうグチャグチャです。まぁこの場合、切り出すのが一番難しかったんですが…