Obtenez des informations sur l'alambic avec Python

SOP, DOP, Wrangle semble être recouvert de matériel: dancer_tone5: Je voudrais donc écrire du matériel Python. La version est à partir de Houdini 15.5. Étant donné que Houdini est un système basé sur des nœuds, en d'autres termes, il permet la programmation visuelle, je pense qu'il y a moins de possibilités de script avec Python qu'avec d'autres logiciels de CG 3D. Alors, où utilisez-vous Python! : punch_tone1: J'en parle, mais après tout, le développement du pipeline est l'essentiel. Par exemple, si HQueue, qui est un répartiteur Houdini standard, est utilisé en standard, le flux consistera à transmettre le travail de rendu à un autre client une fois la simulation de toutes les images terminée, mais si vous utilisez Python, ** 1 simulation d'image Lorsque vous avez terminé, vous pouvez dire ** lancer le travail de rendu à un autre client. De plus, comme vous pouvez spécifier un fichier de script Python avec l'option -P de la commande Mantra, vous pouvez remplacer les ** propriétés de rendu IFD ** (par exemple, les sous-pixels) que vous avez déjà exportés et rendus, donc les sous-pixels. Vous pouvez éviter de changer et de sortir à nouveau l'IFD. : clin d'œil: Vous pouvez également utiliser Python pour lire les informations de ** transformation d'objet ** dans le fichier Alembic lors de sa lecture. HQueue lui-même est gratuit, mais il vérifie les licences Houdini Indie ou supérieures (je n'obtiens pas la licence), et l'exportation IFD n'est possible qu'avec la version commerciale de Houdini / Engine, ce sont donc des informations utiles pour les utilisateurs Apprentice et Indie ** Python Je voudrais vous présenter comment obtenir des informations sur Alembic **. : détendu:

Le Python de Houdini fournit un module appelé ** _alembic_hom_extensions **. Normalement, lorsque vous contrôlez Houdini avec Python, vous commencez avec le module ** hou **, mais ce ** _alembic_hom_extensions ** est indépendant du module ** hou **. En d'autres termes, aucune licence n'est requise si vous utilisez simplement ce module. Mais cela n'a pas beaucoup de sens car la plupart du temps, je transmets les informations d'Alambic à Houdini et les traite: scream_cat: En utilisant ce module, vous pouvez principalement obtenir la hiérarchie d'objets, la transformation d'objet et la visibilité du fichier Almembic spécifié. Vous pouvez également obtenir la valeur de la propriété utilisateur de l'objet (dans le cas d'Alambic de Houdini, c'est-à-dire la résolution définie en plus pour l'objet caméra) et la plage de temps de l'animation de l'objet. Les fonctions de ce module sont: Lisez: zzz: Passons à l'explication suivante.


python


alembicArbGeometry(abcPath, objectPath, name, sampleTime) → (value, isConstant, scope)

Renvoie un taple de None ou (value, isConstant, scope). Le contenu de ce taple est la valeur de l'attribut, la valeur booléenne indiquant si l'attribut est constant sur l'axe du temps et la portée ('variant', 'vertex', 'facevarying', 'uniform', 'constant', 'unknown'. ')est. </ sup>

python


alembicClearArchiveCache()

Effacez le cache interne du fichier Alembic. </ sup>

python


alembicGetArchiveMaxCacheSize()

Renvoie la taille du cache du fichier Alembic. </ sup>

python


alembicGetCameraDict(abcPath, objectPath, sampleTime)

Renvoie un dictionnaire de paramètres de caméra pour l'objet spécifié. </ sup>

python


alembicGetCameraResolution(abcPath, objectPath, sampleTime)

Renvoie un taple contenant Aucun ou deux flottants. La première valeur est la résolution X de la caméra Houdini. La deuxième valeur est la résolution Y de la caméra Houdini. Certaines caméras (par exemple Maya Camera) n'ont pas de résolution, donc Aucune n'est renvoyée dans ce cas. </ sup>

python


alembicGetObjectPathListForMenu(abcPath)

Renvoie un tuple de chaînes au format requis pour les rappels de menu. </ sup>

python


alembicGetSceneHierarchy(abcPath, objectPath) → (object_name, object_type, (children))

Renvoie 3 taples. Chaque taple a la structure suivante: (object_name, object_type, (children)) (children) est un taple contenant des nœuds enfants. object_type contient l'un des éléments suivants (peut inclure d'autres types): --cxform nœud de transformation constante

python


alembicHasUserProperties(abcPath, objectPath)

Renvoie None si l'objet n'a pas de propriétés utilisateur. Si tel est le cas, renvoie si la propriété utilisateur est constante dans le temps. </ sup>

python


alembicSetArchiveMaxCacheSize(size)

Définit le nombre maximum de fichiers Alembic qui seront mis en cache à la fois. </ sup>

python


alembicTimeRange(abcPath, [objectPath=None]) → (start_time, end_time)

Renvoie un taple de None ou (start_time, end_time). Ce taple contient l'heure globale de début / fin de l'archive selon les informations FPS dans l'archive Alembic. Si vous spécifiez objectPath, l'heure de début / fin de cet objet est calculée. Renvoie None si l'archive est constante. </ sup>

python


alembicUserProperty(abcPath, objectPath, name, sampleTime) → (value, isConstant)

Renvoie un taple de None ou (value, isConstant). Ce taple contient la valeur de l'attribut et une valeur booléenne qui indique si l'attribut est constant dans le temps. </ sup>

python


alembicUserPropertyMetadata(abcPath, objectPath, sampleTime)

Renvoie Aucun ou dictionnaire JSON. Ce dictionnaire JSON contient une carte de nom de propriété utilisateur -> métadonnées de propriété utilisateur. </ sup>

python


alembicUserPropertyDictionary(abcPath, objectPath, sampleTime)

Renvoie Aucun ou dictionnaire JSON. Ce dictionnaire JSON contient une carte des noms de propriétés utilisateur-> valeurs des propriétés utilisateur. </ sup>

python


alembicUserPropertyValuesAndMetadata(abcPath, objectPath, sampleTime)

Renvoie None ou Taple. Ce taple contient deux dictionnaires JSON. Le premier dictionnaire contient une carte des propriétés et des valeurs utilisateur. Le deuxième dictionnaire contient une carte des propriétés de l'utilisateur et les métadonnées utilisées pour interpréter le premier dictionnaire. </ sup>

python


alembicVisibility(abcPath, objectPath, sampleTime, [check_ancestor=False]) → (value, isConstant)

Renvoie un taple de None ou (value, isConstant). Ce taple contient la visibilité de l'objet et une valeur booléenne qui indique si la visibilité est constante dans le temps. La valeur de retour de visibilité de 0 signifie masqué, 1 signifie visible et -1 signifie différer (en fonction de la visibilité parentale). </ sup>

python


getLocalXform(abcPath, objectPath, sampleTime) → (xform, isConstant, inherit)

Renvoie un tapple de (xform, isConstant, inherits). Ce tapple est une transformation locale, une valeur booléenne qui indique si la transformation est constante dans le temps et une valeur booléenne qui indique si le nœud hérite (ou est connecté à) la transformation parent. Comprend. </ sup>

python


getWorldXform(abcPath, objectPath, sampleTime) → (xform, isConstant, inherit)

Renvoie un tuple de (xform, isConstant, inherits). Ce tapple est une transformation mondiale, une valeur booléenne qui indique si la transformation est constante dans le temps et une valeur booléenne qui indique si le nœud hérite (ou est connecté à) la transformation parent. Comprend. </ sup>


Je n'utilise pas vraiment toutes les fonctions ci-dessus, donc j'aimerais me concentrer uniquement sur celles qui m'intéressent.

python


alembicGetSceneHierarchy(abcPath, objectPath)

python


alembicTimeRange(abcPath, [objectPath=None])

python


getWorldXform(abcPath, objectPath, sampleTime)

Il a considérablement diminué. Voyons ce que nous pouvons faire avec ces trois fonctions. Scene.gif NetworkEditor.png J'ai créé cam1, Toy, Subnet (Pig, ShaderBall dans ce cas). Autre que ShaderBall, l'animation au niveau de l'objet est définie. Sortez toute cette scène sur Alembic et chargez-la dans une nouvelle scène. NetworkEditorAlembic.png Les données sont capturées dans la même hiérarchie d'objets que Houdini et également animées. Mais lorsque je sélectionne l'objet cam1 à animer, l'éditeur d'animation n'affiche aucune courbe d'animation. Si vous connaissez CHOP, vous pouvez utiliser Object CHOP pour afficher la courbe d'animation échantillonnée dans Motion FX View, n'est-ce pas? Je pense que tu peux penser. Si les données d'animation Alembic d'origine sont cuites et interpolées linéairement, c'est très bien, mais si ce n'est pas le cas, vous voudrez également obtenir les valeurs d'image en virgule flottante. Vous voulez donc obtenir la courbe d'animation, non? C'est là que le module ** _alembic_hom_extensions ** entre en jeu. Comme un flux brutal,

Vous pouvez développer divers pipelines avec.

Comment obtenir la hiérarchie des objets et le type d'animation d'Alembic

Le code est ci-dessous.

python


import _alembic_hom_extensions as abc

abcPath = "C:/data/alembicFile.abc"

def expandChild(root,child,objectHierarchy,objectType):
    objectHierarchy.append(root+child[0])
    objectType.append(child[1])
    if len(child[2])==0:
        return
    else:
        return expandChild(root+child[0]+"/",child[2][0],objectHierarchy,objectType)

objectHierarchy=[]
objectType=[]    
childNodes = abc.alembicGetSceneHierarchy(abcPath, "/")[2]
for eachChildNode in childNodes:
    expandChild("/",eachChildNode,objectHierarchy,objectType)
print objectHierarchy
print objectType

python


#Résultat de sortie
['/Toy', '/Toy/testgeometry_rubbertoy1', '/cam1', '/cam1/cameraProperties', '/Subnet', '/Subnet/Pig', '/Subnet/Pig/testgeometry_pighead1', '/Subnet/Pig/testgeometry_pighead1/PigFace']
['xform', 'polymesh', 'xform', 'camera', 'cxform', 'xform', 'polymesh', 'faceset']

Vous pouvez voir que xform a des informations d'animation pour cet objet et cxform n'a aucune information d'animation.

Comment obtenir la plage d'animation

Examinons maintenant la plage d'animation de cam1.

python


import _alembic_hom_extensions as abc

abcPath = "C:/data/alembicFile.abc"
objectPath = "/cam1"
print abc.alembicTimeRange(abcPath, objectPath)

python


#Résultat de sortie
(0.041666666666666664, 2.0)

L'unité de la plage d'animation produite par cette fonction est la seconde. Étant donné que cette caméra capture une plage d'animation de 1 image à 48 images avec FPS = 24 Le résultat de (1.0 / 24.0, 48.0 / 24.0) s'affiche.

Comment obtenir les valeurs de mouvement, de rotation et d'échelle de la caméra dans l'image actuelle

Examinons maintenant la transformation de l'objet.

python


import _alembic_hom_extensions as abc

abcPath = "C:/data/alembicFile.abc"

objectPath = "/cam1"

sampleTime = hou.frame()/hou.fps()

#Le premier élément du taple retourné par getWorldXform est 16 tapples float
xform = abc.getWorldXform(abcPath, objectPath, sampleTime)[0]
#Hou convertir au format matriciel.Utiliser Matrix4
xformMatrix = hou.Matrix4(xform)
#Extraire déplacer, faire pivoter, mettre à l'échelle
explodedDictionary = xformMatrix.explode()
print "translate:",explodedDictionary["translate"]
print "rotate",explodedDictionary["rotate"]
print "scale",explodedDictionary["scale"]

python


#Résultat de sortie
translate: [5.75595, 3.34021, 10.2852]
rotate [-11.6801, 28.4249, -1.25354e-06]
scale [1, 1, 1]
```

 Vous pouvez l'utiliser dans le script unique ci-dessus, mais ** les expressions Houdini peuvent utiliser Python ainsi que HScript **.
 Ensuite, ajoutons un paramètre utilisateur (appelé paramètre Spare dans Houdini) au nœud de caméra importé par Alembic comme suit.
 Ici, j'ai ajouté deux Float Vector3 et préparé le paramètre Translate et le paramètre Rotate.
 Puis changez le type d'expression en Python.
 ![UserParms.png](https://qiita-image-store.s3.amazonaws.com/0/154191/3c170758-182d-f349-6414-f89ccfb60957.png)
 Dans le nœud Alembic Xform, les paramètres de nom de fichier, chemin d'objet, cadre et cadre sont déjà préparés, je voudrais donc utiliser les valeurs de ces paramètres pour obtenir des informations sur le mouvement et la rotation de la caméra.
 Vous pouvez entrer plusieurs lignes de code Python à l'aide de la boîte de dialogue Modifier l'expression affichée en appuyant sur Alt + E sur les paramètres, mais il est difficile de saisir un par un le code fréquemment utilisé.
 Il est pratique d'enregistrer le code fréquemment utilisé en tant que fonction personnalisée.
 Une façon d'enregistrer une fonction personnalisée est de placer un fichier Python dans un répertoire spécifique et de le placer dans le chemin, mais cela entraînerait un fichier de scène dépendant de l'environnement.
 Je veux l'éviter!
 Définissons donc une fonction personnalisée dans le fichier de scène.

#### Comment enregistrer une fonction personnalisée dans un fichier de scène
 Les fonctions personnalisées peuvent être enregistrées avec l'éditeur de source Python dans le menu Windows.
 ![PythonSourceEditor.png](https://qiita-image-store.s3.amazonaws.com/0/154191/6022a0b5-fa4d-97ad-e550-6a4fe3141500.png)
 Entrez ensuite le code comme indiqué ci-dessous.
 ![PythonSourceEditorCode.png](https://qiita-image-store.s3.amazonaws.com/0/154191/6285343b-318f-656a-d176-36201529f123.png)
 Ce code est une fonction qui fonctionne avec des paramètres sur un nœud Alembic Xform et renvoie des informations de transformation pour ce nœud.


#### **`python`**
```python

#le mode est"translate"Puis les informations de localisation,"rotate"Puis les informations de rotation,"scale"Renvoie les informations d'échelle
#Si l'index est 0, c'est le composant X, s'il vaut 1, c'est le composant Y, et s'il vaut 2, c'est le composant Z.
def getAlembicTransform(mode="translate",index=0):
    import _alembic_hom_extensions as abc
    currentNode = hou.pwd()
    abcPath = currentNode.parm('fileName').eval()
    objectPath = currentNode.parm('objectPath').eval()
    sampleTime = currentNode.parm('frame').eval()/currentNode.parm('fps').eval()
    xform = abc.getWorldXform(abcPath, objectPath, sampleTime)[0]
    xformMatrix = hou.Matrix4(xform)
    explodedDictionary = xformMatrix.explode()

    return explodedDictionary[mode][index]
```
 Après avoir enregistré le code dans la fenêtre de l'éditeur de source Python
 Vous pourrez appeler la fonction personnalisée "getAlembicTransform" comme suit:
 ![ParameterExpression.png](https://qiita-image-store.s3.amazonaws.com/0/154191/380f944f-fa7b-6f00-98e3-c6ffd7d9344a.png)
 Cliquez avec le bouton gauche sur le nom du paramètre pour voir si la valeur est correcte.
 ![ParameterExpressionEval.png](https://qiita-image-store.s3.amazonaws.com/0/154191/c8e5cc41-04e2-4412-55ac-3d802a64680b.png)

 Vous pouvez maintenant voir la courbe d'animation de l'objet Alembic dans l'éditeur d'animation.
 ![AnimationCurve.png](https://qiita-image-store.s3.amazonaws.com/0/154191/e4697ace-c750-d3b1-7f2a-64ff75d139f7.png)


 Vous avez maintenant inclus les informations de transformation d'Alembic dans les valeurs des paramètres.

 C'est tout. : étreindre:


Recommended Posts

Obtenez des informations sur l'alambic avec Python
Obtenez des informations sur la propriété en grattant avec python
Obtenez date avec python
[Python] Obtenez des informations sur le package Python avec l'API PyPI
Obtenez des informations sur le processeur de Raspberry Pi avec Python
Script Python pour obtenir des informations de note avec REAPER
Obtenez le code du pays avec python
Obtenez la chronologie Twitter avec Python
Obtenez des données Youtube avec python
Obtenir des informations avec l'API Zabbix
Obtenir l'ID de thread avec python
Commencez avec Python! ~ ② Grammaire ~
Obtenir le répertoire personnel avec python
Obtenir un événement de clavier avec python
[Python] Obtenez des informations sur les utilisateurs et des articles sur l'API de Qiita
Obtenez des informations sur les fichiers vidéo avec ffmpeg-python
Commencez avec Python! ~ ① Construction de l'environnement ~
Obtenez des avis avec l'API googlemap de python
Obtenez la météo avec les requêtes Python
Obtenez une capture d'écran Web avec python
Obtenez la météo avec les requêtes Python 2
[Python] Obtenez des données économiques avec DataReader
Comment démarrer avec Python
[Petite histoire] Obtenez l'horodatage avec Python
Obtenez les tendances Qiita avec le scraping Python
[Python x Zapier] Obtenez des informations d'alerte et notifiez avec Slack
Essayez Juniper JUNOS PyEz (bibliothèque python) Note 2 ~ Obtenez des informations avec PyEz ~
Obtenez des données supplémentaires vers LDAP avec python
Obtenir le code HTML de l'élément avec du sélénium Python
[Note] Obtenir des données de PostgreSQL avec Python
Statistiques avec python
Python avec Go
[Python] Récupère le nom de la variable avec str
Twilio avec Python
Carte des informations de location sur une carte avec python
Intégrer avec Python
Jouez avec 2016-Python
AES256 avec python
Testé avec Python
python commence par ()
avec syntaxe (Python)
Commençons avec TopCoder en Python (version 2020)
Bingo avec python
Zundokokiyoshi avec python
Entendons-nous bien avec Python # 0 (Construction de l'environnement)
Obtenez des informations sur la monnaie virtuelle Coincheck avec l'API ♪
Excel avec Python
Micro-ordinateur avec Python
[Blender x Python] Commençons avec Blender Python !!
PhytoMine-I a essayé d'obtenir les informations génétiques de la plante avec Python
Cast avec python
[Yahoo! Weather Replacement Version] Comment obtenir des informations météo avec LINE Notify + Python
J'ai essayé d'obtenir les informations sur le film de l'API TMDb avec Python
Collecter des informations depuis Twitter avec Python (construction de l'environnement)
Jeu à la main en Python (commençons avec AtCoder?)
Obtenez les dernières informations AMI avec l'AWS CLI
Obtenez un billet pour un parc à thème avec python
J'ai essayé d'obtenir des données CloudWatch avec Python
Obtenez le nom de la branche git et le nom de la balise avec python