[PYTHON] Suivez la structure de données de Blender et extrayez les coordonnées des sommets de fbx

En utilisant Blender, j'ai créé un script qui extrait uniquement les coordonnées des sommets des données FBX et les arrange, je vais donc l'introduire après explication.

Structure de données de Blender

Tout d'abord, à propos de cette figure familière (état initial).

image.png

À propos, la vue 3D de Blender est gérée de la manière suivante.

image.png

Dans le script Python

bpy.context.scene.collection

C'est là que ça correspond.

image.png

Ceci est l'interface graphique.

Il y a une scène → collection à l'origine, et il y a des objets dans la collection. Je ne comprends pas vraiment la différence entre une scène et une collection. Cependant, les objets (dits cubes, caméras, etc.) qui existent sous forme de données sont appelés dans la collection en les liant. Cela signifie que seuls les objets liés apparaîtront dans la vue, et les ** objets invisibles mais existant en tant que données **. En faisant cela, il semble que les mêmes données soient utilisées. C'est compliqué pour ceux qui l'exploitent.

Et comme les objets, les maillages et les matériaux qui les accompagnent ont également une liste de données que vous pouvez lier pour utiliser autant que vous en avez besoin.

Par exemple, ici

bpy.data.objects.new("hoge", bpy.data.meshes.new("fuga"))

Ne change rien à la scène apparente,

for i in bpy.data.objects:
    print(i)

alors,

Output


<bpy_struct, Object("Camera")>
<bpy_struct, Object("Cube")>
<bpy_struct, Object("hoge")>
<bpy_struct, Object("Light")>

Est retourné, donc vous pouvez voir qu'un objet mystérieux appelé hoge a été ajouté. Aussi,

bpy.data.objects['hoge'].to_mesh()

alors,

Output


bpy.data.meshes['fuga']

Vous pouvez voir que cet objet est lié à un maillage appelé fuga. Bien sûr, il ne s'agit que de données vides nommées, donc si vous liez hoge à la collection maintenant, il n'appellera rien avec un nom qui n'a pas de sommets.

Regardez de plus près le maillage. Les informations sur les sommets du maillage sont gérées sous la forme suivante.

image.png

L'objet lie le maillage.

image.png

Ceci est l'interface graphique.

Les données de maillage stockent également les données de sommet, donc si vous voulez les informations de sommet, vous y accéderez. Ciblons maintenant les cubes qui ont une forme appropriée.

bpy.data.objects['Cube'].to_mesh().vertices

C'est presque le même que l'image ci-dessus.

Output


bpy.data.meshes['Cube'].vertices

En regardant ce contenu,

for i in bpy.data.meshes['Cube'].vertices:
    print(i)

Output


<bpy_struct, MeshVertex at 0x0000024A9FA28038>
<bpy_struct, MeshVertex at 0x0000024A9FA2804C>
<bpy_struct, MeshVertex at 0x0000024A9FA28060>
<bpy_struct, MeshVertex at 0x0000024A9FA28074>
<bpy_struct, MeshVertex at 0x0000024A9FA28088>
<bpy_struct, MeshVertex at 0x0000024A9FA2809C>
<bpy_struct, MeshVertex at 0x0000024A9FA280B0>
<bpy_struct, MeshVertex at 0x0000024A9FA280C4>

Les données binaires sont renvoyées sérieusement. Puisqu'il y en a 8 correctement, il semble qu'il n'y ait pas d'erreur dans le cube, mais j'aimerais que vous retourniez la valeur numérique si possible. Si vous regardez la Référence, vous pouvez voir que la valeur peut être obtenue avec l'attribut co.

for i in bpy.data.meshes['Cube'].vertices:
    print(i.co)

Output


<Vector (1.0000, 1.0000, 1.0000)>
<Vector (1.0000, 1.0000, -1.0000)>
<Vector (1.0000, -1.0000, 1.0000)>
<Vector (1.0000, -1.0000, -1.0000)>
<Vector (-1.0000, 1.0000, 1.0000)>
<Vector (-1.0000, 1.0000, -1.0000)>
<Vector (-1.0000, -1.0000, 1.0000)>
<Vector (-1.0000, -1.0000, -1.0000)>

Maintenant, nous avons enfin un tableau de coordonnées de sommets.

S'applique à fbx

Faites de même pour le fbx importé.

image.png

En principe, vous devriez obtenir la même forme que ci-dessus en extrayant les sommets de toutes les données de maillage.

for i in bpy.data.meshes:
    print(i)

Output


<bpy_struct, Mesh("Cube")>
<bpy_struct, Mesh("Mesh")>
<bpy_struct, Mesh("Mesh.001")>
<bpy_struct, Mesh("Mesh.002")>
<bpy_struct, Mesh("Mesh.003")>
<bpy_struct, Mesh("Mesh.004")>
<bpy_struct, Mesh("Mesh.005")>
<bpy_struct, Mesh("Mesh.006")>
<bpy_struct, Mesh("Mesh.007")>

……. Il y a un mystérieux «Cube». Oui, ** le premier cube qui existe lorsque vous lancez Blender **. Même si vous le supprimez de la scène (dissocier pour être exact), les données à l'intérieur ne disparaîtront pas. Si rien n'est fait, il remontera en haut du cube. Faisons disparaître.

bpy.data.meshes.remove(bpy.data.meshes['Cube'])
for i in bpy.data.meshes:
    print(i)

Output


<bpy_struct, Mesh("Mesh")>
<bpy_struct, Mesh("Mesh.001")>
<bpy_struct, Mesh("Mesh.002")>
<bpy_struct, Mesh("Mesh.003")>
<bpy_struct, Mesh("Mesh.004")>
<bpy_struct, Mesh("Mesh.005")>
<bpy_struct, Mesh("Mesh.006")>
<bpy_struct, Mesh("Mesh.007")>

Il a disparu. Après cela, écrivez un script qui extrait les coordonnées des sommets de toutes ces données de maillage.

import bpy
import numpy as np

vts = []

for m in bpy.data.meshes:
    for v in m.vertices:
        vts.append(v.co)

vts = np.array(vts)

Puisque le nombre obtenu par «co» est de type «Vector», il est converti par «np.array» pour une facilité de manipulation.

Vérifiez que la séquence obtenue ici représente bien la forme d'origine. Si les sommets contiennent les informations tridimensionnelles avec précision, un diagramme de dispersion doit montrer la forme d'origine.

Le tableau vts obtenu plus tôt

np.savetxt(r'Chemin arbitraire\vts.txt', vts)

Exporter avec. Dessinez un diagramme de dispersion dans un fichier Python séparé (car le Python intégré de Blender n'a pas matplotlib ...).

import numpy as np
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D

data = np.loadtxt('vts.txt')

X = data[:,0]
Y = data[:,1]
Z = data[:,2]

fig = plt.figure()
ax = Axes3D(fig)
ax.set_xlabel("X")
ax.set_ylabel("Y")
ax.set_zlabel("Z")
ax.plot(X,Y,Z,marker="o",linestyle='None',ms=0.2)

plt.show()

image.png

Il s'avère que les sommets des données 3D d'origine peuvent être arrangés avec précision.

Recommended Posts

Suivez la structure de données de Blender et extrayez les coordonnées des sommets de fbx
Extraction de données depuis S3
Extraire les données csv et calculer
Extraire des données spécifiques d'un JSON complexe
Structure de données persistante créée à partir de zéro
Extraire les données et les compétences de Pokemon GO Pokemon
Extraire et tracer les dernières données démographiques à partir des données PDF fournies par la ville
Créez un arbre de décision à partir de 0 avec Python et comprenez-le (4. Structure des données)
Structure de données Python et implémentation interne ~ Liste ~
Structure et fonctionnement des données Python (mémo d'apprentissage Python ③)