2017年06月26日

modo11.0v3のスクリプトについて調べてみた その98

引き続き「TD SDK」の「Vector3」クラスについて調べてみたい。

「angle()」メソッドは2つのベクトルの為す角度を求める。下がそのプログラムで、2つのベクトルの単位ベクトルを「normal()」メソッドで得て、それらを「dot()」メソッドで内積計算をして、得られた値を「acos()」メソッドで角度(ラジアン)に変換している。

 def angle(self, other):
     """Returns the angle between this and another vector"""
     return math.acos(self.normal().dot(other.normal()))

これは2つのベクトルの内積が下の式である事から

V1・V2 = |V1||V2|cosθ

ベクトルを単位ベクトルにすれば |V1||V2|=1になって、cosθになるのを利用したものだ。「acos()」はcos関数の逆関数だ。

fig01

「rotate()」は実装されていないようだ。

 def rotate(self, other):
     # by matrix, quaternion, euler etc.
     raise NotImplementedError

そのかわりクォータニオンや回転軸と角度を指定した回転メソッドが実装されている。

「rotateByQuat()」はクォータニオンでベクトルを回転するメソッドだ。下がそのプログラム。回転させたい「Vector3」を「Matrix4」の移動ベクトルにして、クォータニオンも「toMatrix4()」で「Matrix4」に変換して、掛け合わせる事で「Matrx4」の移動ベクトルを回転変換している。そしてその結果の「matrix4」から移動ベクトル部分を抽出して「Vector3」に戻している。「mulByMatrixAsPoint()」を使っても良かったね。

 def rotateByQuat(self, other):
     """Rotate this vector by a quaternion"""
     matrix = Matrix4(position=self.values)
     matrix = matrix * other.toMatrix4()
     for i in range(3):
         self.values[i] = matrix[3][i]

「rotateByAxisAngle()」は回転軸ベクトル「axis」とその軸回りの回転角度「angle」を指定してベクトルを回転させるメソッドだ。下がそのプログラムで、回転軸と回転角度からクォータニオンを作って、あとは「rotateByQuat()」と同様の処理をしている。

 def rotateByAxisAngle(self, axis, angle):
     """Rotates this vector by a given axis and angle

     :param Vector3 axis: This axis to rotate about
     :param float angle: The angle in radians to rotate by
     """
     quat = Quaternion()
     quat.setAxisAngle(axis, angle)
     result = Matrix4(position=self.values) * quat.toMatrix4()
     self.values = list(result.position)

fig02

下のプログラムは「Cylinder」アイテムのY軸を中心に「Mesh」アイテムの選択された頂点を30度回転させるプログラムだ。「rotateByAxisAngle()」の回転は原点中心にしか出来ないので、回転させたい頂点の座標値から回転中心の座標値を一旦引いて回転させ、回転後に足して戻している。

import math
from modo import *
cylinder = Mesh('Cylinder')
mesh = Mesh('Mesh')
cylinder_m4 = Matrix4(cylinder.channel('worldMatrix').get())
cylinder_y = cylinder_m4[1]
selected_vertex = mesh.geometry.vertices.selected

for v in selected_vertex:
	tmp = Vector3(v.position) - cylinder_m4.position
	tmp.rotateByAxisAngle(cylinder_y,math.radians(30))
	tmp = tmp + cylinder_m4.position
	v.position = tmp.values
mesh.geometry.setMeshEdits()

こんなシーンを作って、

fig03

「Cylinder」のローカル座標は下のようになっている。

fig04

下が「Mesh」の上の面の頂点を選択して実行した結果。「Cylinder」を軸に30度回転したのがわかる。

fig05

続きはまた次回。

modo10-11ブログ目次



take_z_ultima at 11:30│Comments(0)TrackBack(0)modo | CG

トラックバックURL

この記事にコメントする

名前:
URL:
  情報を記憶: 評価: 顔   
 
 
 

Archives