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
# ポイントアトリビュート格納用
def main() -> bool:
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を作る
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