Houdini: CopyToPoints -> C4D: Cloner
HoudiniでCopyToPointsとして作った配置をC4DのClonerで再現する
Houdini
https://scrapbox.io/files/67c2e60138a6c9d8bcac4b57.png
以下2つをAlembicとしてそれぞれ書き出す
A 配置元オブジェクト (パーツ群)
パーツ単位でPacked Primitive等にまとめて1つのAlembicに
variantのindexと対応させておく
B 配置先オブジェクト (点)
Point Attributeに入れる (→C4D上で頂点タグになる)
v@N, v@up : 姿勢
i@variant : パーツ種別
点群やPolylineだとC4Dが点のアトリビュートを読めないので、何かしらメッシュを張る
Triangulate 2D → Restore Original Point Positions とかで
↓
Cinema 4D
クローナー
https://scrapbox.io/files/67c2e2533da22bc50cc84e86.png
Mode: Object
Distribution: Vertex
Object: 配置先オブジェクトを指定
読み込んだAlembicをMake Editableしておく
Align Cloneは使わない
向きをNormalタグとして設定しても無視されてしまうため、下のPython Effectorで処理する
子階層にパーツ群をバラして入れておく (variantの数と一致させる)
Pythonエフェクタ
タグのポイントアトリビュート値を読んで、N/up/variantを適用する
Mode: Full Control にて以下Pythonをコピペ
配置先オブジェクトに合計7個の頂点タグが、左から以下の順番で並んでいる想定
normal_x/normal_y/normal_z/up_x/up_y/up_z/variant
https://scrapbox.io/files/67c2e1e6433e2ef87732bee3.png
vectorタグはあるのに、なぜかfloatに分解されてしまう模様
code:python
from typing import List
import c4d
op: c4d.BaseObject #このPythonエフェクタ
gen: c4d.BaseObject #クローナーオブジェクト
# ポイントアトリビュート格納用
v_norm: Listc4d.Vector = []
v_up: Listc4d.Vector = []
variants: Listfloat = []
def main() -> bool:
src_obj: c4d.PolygonObject = genc4d.MG_OBJECT_LINK
global v_norm, v_up, variants
# global化して0Fの時だけ読む
if len(v_norm) == 0:
tags = src_obj.GetTags()
# normal vector
n_x: Listfloat = tags0.GetAllHighlevelData()
n_y: Listfloat = tags1.GetAllHighlevelData()
n_z: Listfloat = tags2.GetAllHighlevelData()
# up vector
up_x: Listfloat = tags3.GetAllHighlevelData()
up_y: Listfloat = tags4.GetAllHighlevelData()
up_z: Listfloat = tags5.GetAllHighlevelData()
# floatに分解されてしまったベクトルを再構成する
for i in range(tags0.GetDataCount()):
v_norm.append(c4d.Vector(n_xi, n_yi, -n_zi)) #zは反転
v_up.append(c4d.Vector(up_xi, up_yi, -up_zi)) #zは反転
variants = tags6.GetAllHighlevelData()
print('initialized vectors')
# MoGraphデータ
data: c4d.modules.mograph.MoData = c4d.modules.mograph.GeGetMoData(op)
if data is None:
return 1.0
# 姿勢マトリックスとクローン情報(何番目を使うか)を取得
matrices: listc4d.Matrix = data.GetArray(c4d.MODATA_MATRIX)
clones: Listfloat = data.GetArray(c4d.MODATA_CLONE)
for i in range(data.GetCount()):
# N, upからMatrixを作る
norm = v_normi
up = v_upi
x_axis = up.Cross(norm).GetNormalized()
matricesi = c4d.Matrix(v1=x_axis, v2=up, v3=norm, off=matricesi.off)
# クローンはvariantを正規化するのみ
clonesi = variantsi / len(gen.GetChildren()) + 1E-4
data.SetArray(c4d.MODATA_MATRIX, matrices, opc4d.FIELDS.HasContent())
data.SetArray(c4d.MODATA_CLONE, clones, opc4d.FIELDS.HasContent())
return True
#Cinema4D #Houdini