2025年11月10日

しばらく更新をお休みします

しばらくブログを書く時間を他に回す事にしました。



take_z_ultima at 11:30|この記事のURLその他 

2025年10月27日

HDDのデータ飛ばしてしまった・・・orz

HDDを交換しようとして、まちがってデータの入っているHDDをフォーマットしてしまった。そこにバックアップするHDDのデータを書き込んでしまったのでもう復旧は不能だろうな。HDDは交換する時にそのまま取ってあるので1つ前の交換時のデータまでは残っているんだが、やれやれ。

これから出来る限りの復旧をしようと思う。



take_z_ultima at 11:30|この記事のURLその他 

2025年10月20日

ウェイトマップ値の決定方法について考えてみた その28

今回はペアレントされたオブジェクト上の点を1つの姿勢から他の姿勢に移す変換についてだ。

どんな姿勢でもその点が属しているオブジェクトのローカル座標値は変わらないので、まずもとになる姿勢の点のワールド座標値からローカル座標値に変換する変換を取得して、次にそのローカル座標値を姿勢変更後のワールド座標値に変換する変換を取得して、その2つの変換を順に合成すれば姿勢を変えた先の座標値に変換する変換になる。

例えば下のように2つのペアレントされたオブジェクトCube1とCube2があって、

fig 1

最初の姿勢の緒元は以下のようになっていて、

fig 2

これをこのように変えて姿勢を変えた場合、

fig 3

ワールド座標はこのように変わるはずだ。

fig 4

さっそくプログラムでやってみると、

import numpy as np
import math

def transform(tx,ty,tz,rx,ry,rz,scx,scy,scz):

    rad = math.pi / 180

    cx = math.cos(rx*rad)
    sx = math.sin(rx*rad)
    cy = math.cos(ry*rad)
    sy = math.sin(ry*rad)
    cz = math.cos(rz*rad)
    sz = math.sin(rz*rad)

    rotx = np.array([[1.0,0.0,0.0,0.0],
                     [0.0, cx,  sx,0.0],
                     [0.0, -sx, cx,0.0],
                     [0.0,0.0,0.0,1.0]]
                   )
    roty = np.array([[ cy,0.0,-sy,0.0],
                     [0.0,1.0,0.0,0.0],
                     [ sy,0.0, cy,0.0],
                     [0.0,0.0,0.0,1.0]]
                   )
    rotz = np.array([[ cz,sz,0.0,0.0],
                     [ -sz, cz,0.0,0.0],
                     [0.0,0.0,1.0,0.0],
                     [0.0,0.0,0.0,1.0]]
                   )
    trns = np.array([[1.0,0.0,0.0,0.0],
                     [0.0,1.0,0.0,0.0],
                     [0.0,0.0,1.0,0.0],
                     [ tx, ty, tz,1.0]]
                   )
    scl = np.array([[scx,0.0,0.0,0.0],
                     [0.0,scy,0.0,0.0],
                     [0.0,0.0,scz,0.0],
                     [0.0,0.0,0.0,1.0]]
                   )
    return scl @ rotz @ rotx @ roty @ trns

cube1_M0 = transform(0,0,0,0,60,-30,1,1,1)
cube2_M0 = transform(0,1.5,0,10,0,-10,1,1,1)
M0 = cube2_M0 @ cube1_M0

cube1_M1 = transform(0,0,0,45,30,0,1,1,1)
cube2_M1 = transform(0,1.5,0,-20,0,60,1,1,1)
M1 = cube2_M1 @ cube1_M1

M = np.linalg.inv(M0) @ M1

p0 = np.array([1.1773,2.5361,-1.0255])

p1 = np.append(p0,1.0) @ M

print('original:',p0)
print('transformed:',p1[:-1])

これが実行結果。変換出来ている事がわかる。

original: [ 1.1773 2.5361 -1.0255]
transformed: [-0.46398329 1.42950851 2.00973274]

続きはまた次回。



take_z_ultima at 11:30|この記事のURLCG 

2025年10月06日

ウェイトマップ値の決定方法について考えてみた その27

前回のプログラムでradの定義が抜けていたので追加しておいた。

さて、今までやって来た座標変換はとあるアイテム上にある点の座標をそのアイテムのローカル座標系からアイテムが存在するワールド座標系の座標値に変換するものだ。

ローカル座標系(アイテムの内部で見れば)であればアイテムがどう移動・回転・縮尺されようとその位置に変化は無いが、ワールド座標系(アイテムの外から見れば)ではアイテムの動きや変形によってその中にある点の位置は変化して見える。

逆にある点を特定のアイテムのローカル座標系に変換するにはどうすればいいかと言えば、答えは簡単。今までやった変換の逆をやればいいだけだ。X軸に90度回転しているならば逆に−90度回転させれば元に戻るわけで、変換に使ったパラメータすべてを打ち消す値に置き換えて、スケール→回転→移動の順に変換していたので逆に移動→回転→スケールの順に変換してやればワールド座標からアイテムのローカル座標に変換できる。

そしてこの変換については行列にはそれを逆変換する逆行列が存在していてnumpyでは

numpy.linalg.inv(M)

で簡単に求められる。前回ワールド座標に変換した座標値を逆変換すると当たり前だけど元のローカル座標に戻ることが確認できる。

import numpy as np
import math

tx = -0.5
ty = 0.5
tz = 1.0
rx = -30.0
ry = 50.0
rz = -60.0
scx = 0.8
scy = 1.2
scz = 0.5

rad = math.pi / 180

cx = math.cos(rx*rad)
sx = math.sin(rx*rad)
cy = math.cos(ry*rad)
sy = math.sin(ry*rad)
cz = math.cos(rz*rad)
sz = math.sin(rz*rad)

rotx = np.array([[1.0,0.0,0.0,0.0],
                 [0.0, cx,  sx,0.0],
                 [0.0, -sx, cx,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
roty = np.array([[ cy,0.0,-sy,0.0],
                 [0.0,1.0,0.0,0.0],
                 [ sy,0.0, cy,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
rotz = np.array([[ cz,sz,0.0,0.0],
                 [ -sz, cz,0.0,0.0],
                 [0.0,0.0,1.0,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
trns = np.array([[1.0,0.0,0.0,0.0],
                 [0.0,1.0,0.0,0.0],
                 [0.0,0.0,1.0,0.0],
                 [ tx, ty, tz,1.0]]
               )
scl = np.array([[scx,0.0,0.0,0.0],
                 [0.0,scy,0.0,0.0],
                 [0.0,0.0,scz,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
m1 = scl @ rotz @ rotx @ roty @ trns

tx = 0.0
ty = 1.6
tz = 0.0
rx = 45.0
ry = 30.0
rz = 60.0
scx = 1.0
scy = 1.5
scz = 1.0
rad = math.pi / 180.0
cx = math.cos(rx*rad)
sx = math.sin(rx*rad)
cy = math.cos(ry*rad)
sy = math.sin(ry*rad)
cz = math.cos(rz*rad)
sz = math.sin(rz*rad)

rotx = np.array([[1.0,0.0,0.0,0.0],
                 [0.0, cx,  sx,0.0],
                 [0.0, -sx, cx,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
roty = np.array([[ cy,0.0,-sy,0.0],
                 [0.0,1.0,0.0,0.0],
                 [ sy,0.0, cy,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
rotz = np.array([[ cz,sz,0.0,0.0],
                 [ -sz, cz,0.0,0.0],
                 [0.0,0.0,1.0,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
trns = np.array([[1.0,0.0,0.0,0.0],
                 [0.0,1.0,0.0,0.0],
                 [0.0,0.0,1.0,0.0],
                 [ tx, ty, tz,1.0]]
               )
scl = np.array([[scx,0.0,0.0,0.0],
                 [0.0,scy,0.0,0.0],
                 [0.0,0.0,scz,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
m2 = scl @ rotz @ rotx @ roty @ trns

p = np.array([0.5,1.5,-0.5])

M =  m2 @ m1

invM = np.linalg.inv(M)

p1 = np.append(p,1.0) @ M
p2 = p1 @ invM

print('original:',p)
print('world:',p1[:-1])
print('local',p2[:-1])
original: [ 0.5  1.5 -0.5]
world: [ 0.76227616  3.11999844 -1.51283819]
local: [ 0.5  1.5 -0.5]

続きはまた次回。



take_z_ultima at 11:30|この記事のURLCG 

2025年09月29日

ウェイトマップ値の決定方法について考えてみた その26

前回はアイテム1つの変換マトリクスを求めてみた。今回はさらにアイテムをペアレントした場合について見て行きたい。

結論から言えばペアレントされたアイテムの変換は親アイテムの変換がさらにかかるだけなので、変換マトリクスは親子2つのマトリクスの子→親の順の掛け算になる。

fig1

例えば上の図でCube1の緒元はこれで

fig4

Cube2はこのような設定だとして、

名称未設定 5

Cube2上の点Pがどのように変換されるかやってみると、

fig2

このようになって、

import numpy as np
import math

tx = -0.5
ty = 0.5
tz = 1.0
rx = -30.0
ry = 50.0
rz = -60.0
scx = 0.8
scy = 1.2
scz = 0.5

rad = math.pi / 180

cx = math.cos(rx*rad)
sx = math.sin(rx*rad)
cy = math.cos(ry*rad)
sy = math.sin(ry*rad)
cz = math.cos(rz*rad)
sz = math.sin(rz*rad)

rotx = np.array([[1.0,0.0,0.0,0.0],
                 [0.0, cx,  sx,0.0],
                 [0.0, -sx, cx,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
roty = np.array([[ cy,0.0,-sy,0.0],
                 [0.0,1.0,0.0,0.0],
                 [ sy,0.0, cy,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
rotz = np.array([[ cz,sz,0.0,0.0],
                 [ -sz, cz,0.0,0.0],
                 [0.0,0.0,1.0,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
trns = np.array([[1.0,0.0,0.0,0.0],
                 [0.0,1.0,0.0,0.0],
                 [0.0,0.0,1.0,0.0],
                 [ tx, ty, tz,1.0]]
               )
scl = np.array([[scx,0.0,0.0,0.0],
                 [0.0,scy,0.0,0.0],
                 [0.0,0.0,scz,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
m1 = scl @ rotz @ rotx @ roty @ trns

tx = 0.0
ty = 1.6
tz = 0.0
rx = 45.0
ry = 30.0
rz = 60.0
scx = 1.0
scy = 1.5
scz = 1.0
rad = math.pi / 180.0
cx = math.cos(rx*rad)
sx = math.sin(rx*rad)
cy = math.cos(ry*rad)
sy = math.sin(ry*rad)
cz = math.cos(rz*rad)
sz = math.sin(rz*rad)

rotx = np.array([[1.0,0.0,0.0,0.0],
                 [0.0, cx,  sx,0.0],
                 [0.0, -sx, cx,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
roty = np.array([[ cy,0.0,-sy,0.0],
                 [0.0,1.0,0.0,0.0],
                 [ sy,0.0, cy,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
rotz = np.array([[ cz,sz,0.0,0.0],
                 [ -sz, cz,0.0,0.0],
                 [0.0,0.0,1.0,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
trns = np.array([[1.0,0.0,0.0,0.0],
                 [0.0,1.0,0.0,0.0],
                 [0.0,0.0,1.0,0.0],
                 [ tx, ty, tz,1.0]]
               )
scl = np.array([[scx,0.0,0.0,0.0],
                 [0.0,scy,0.0,0.0],
                 [0.0,0.0,scz,0.0],
                 [0.0,0.0,0.0,1.0]]
               )
m2 = scl @ rotz @ rotx @ roty @ trns

p = np.array([0.5,1.5,-0.5])

pd = np.append(p,1.0) @ m2 @ m1

print(pd[:-1])

計算結果は実際のものと一致する。

fig3

続きはまた次回。



take_z_ultima at 11:30|この記事のURLCG 
Archives