Wir werden zusammenfassen, wie Sie mit Blender Python auf Mesh-Daten zugreifen können. Es ist nicht so schwer herauszufinden, aber ich habe nicht viele Informationen, deshalb werde ich sie zusammenstellen, damit sie als Spickzettel aufgeführt werden können. Es gibt keine Garantie dafür, dass die hier beschriebenen Methoden hinsichtlich der Geschwindigkeit optimal sind. Bitte lassen Sie mich wissen, ob es einen anderen besseren Weg gibt.
Im Folgenden möchte ich den Beispielcode zusammenfassen, mit dem Würfel erstellt und mit UV, Scheitelpunktfarbe, Formschlüssel und Hautgewicht (Scheitelpunktgruppe) festgelegt werden. Es enthält auch den Code und das Protokoll zum Drucken des darin enthaltenen Datensatzes.
Nachtrag (03.04.2019): Die Version von Blender wurde 2.80, und die API wurde teilweise geändert und funktionierte nicht mehr, also habe ich sie behoben. Grundsätzlich die folgenden 4 Punkte.
Sie können ein Netz auch erstellen, indem Sie in den Bearbeitungsmodus wechseln und es als BMesh erstellen. Hier erfahren Sie jedoch, wie Sie es im Objektmodus erstellen.
create_mesh.py
import bpy
verts = [[-1.0, -1.0, 1.0], [1.0, -1.0, 1.0], [1.0, 1.0, 1.0], [-1.0, 1.0, 1.0],
[-1.0, -1.0, -1.0], [1.0, -1.0, -1.0], [1.0, 1.0, -1.0], [-1.0, 1.0, -1.0], ]
faces = [[0,1,2,3], [0,4,5,1], [1,5,6,2], [2,6,7,3], [0,3,7,4], [4,7,6,5]]
msh = bpy.data.meshes.new(name="cubemesh")
#msh = bpy.data.meshes.new("cubemesh")
msh.from_pydata(verts, [], faces)
msh.update()
obj = bpy.data.objects.new(name="cube", object_data=msh)
#obj = bpy.data.objects.new("cube", msh)
scene = bpy.context.scene
#scene.objects.link(obj)
scene.collection.objects.link(obj)
Als Fluss,
meshes.new
msh.update ()
. Es ist möglicherweise nicht erforderlich, wenn Sie from_pydata aufrufen.objects.new
, übergeben Sie jedoch die zuvor erstellten Netzdaten als Argument.scene.objects.link
erstellten Objekte mit der Szene zu verknüpfen.Der [] Teil des zentralen Arguments von from_pydata
legt die Kanteninformationen fest. Wenn nicht, wird es automatisch aus den Gesichtsinformationen berechnet. Wenn Sie also ein Netz erstellen möchten, das Gesichter generiert, gibt es kein Problem mit einem leeren Array. Blender kann auch ein Netz ohne Flächen erstellen. In diesem Fall können Sie die Kante angeben und die Flächenindexspezifikation leer lassen. Möglicherweise möchten Sie mit einem Skript ein Netz ohne Flächen erstellen, z. B. ein Netz für einen Rig-Controller.
--vertices Eigenschaft --index: Index der Eckpunkte --co: Koordinaten von Eckpunkten --normal: Scheitelpunkt normal
#Aufzählung der Scheitelpunktinformationen
print("num of vertices:", len(msh.vertices))
for vt in msh.vertices:
print("vertex index:{0:2} co:{1} normal:{2}".format(vt.index, vt.co, vt.normal))
Ausgabe
num of vertices: 8
vertex index: 0 co:<Vector (-1.0000, -1.0000, 1.0000)> normal:<Vector (-0.5773, -0.5773, 0.5773)>
vertex index: 1 co:<Vector (1.0000, -1.0000, 1.0000)> normal:<Vector (0.5773, -0.5773, 0.5773)>
vertex index: 2 co:<Vector (1.0000, 1.0000, 1.0000)> normal:<Vector (0.5773, 0.5773, 0.5773)>
vertex index: 3 co:<Vector (-1.0000, 1.0000, 1.0000)> normal:<Vector (-0.5773, 0.5773, 0.5773)>
vertex index: 4 co:<Vector (-1.0000, -1.0000, -1.0000)> normal:<Vector (-0.5773, -0.5773, -0.5773)>
vertex index: 5 co:<Vector (1.0000, -1.0000, -1.0000)> normal:<Vector (0.5773, -0.5773, -0.5773)>
vertex index: 6 co:<Vector (1.0000, 1.0000, -1.0000)> normal:<Vector (0.5773, 0.5773, -0.5773)>
vertex index: 7 co:<Vector (-1.0000, 1.0000, -1.0000)> normal:<Vector (-0.5773, 0.5773, -0.5773)>
print("num of edges:", len(msh.edges))
for ed in msh.edges:
print("edge index:{0: 2} v0:{0} v1:{1}".format(ed.index, ed.vertices[0], ed.vertices[1]))
Ausgabe
num of edges: 12
edge index: 0 v0: 4 v1: 5
edge index: 1 v0: 3 v1: 7
edge index: 2 v0: 6 v1: 7
edge index: 3 v0: 2 v1: 6
edge index: 4 v0: 5 v1: 6
edge index: 5 v0: 0 v1: 1
edge index: 6 v0: 4 v1: 7
edge index: 7 v0: 1 v1: 2
edge index: 8 v0: 1 v1: 5
edge index: 9 v0: 2 v1: 3
edge index:10 v0: 0 v1: 3
edge index:11 v0: 0 v1: 4
Die Eigenschaft ** Polygone **, nicht die Gesichter. Es gibt mehr Software mit dem Eigenschaftsnamen Gesichter, und ich versuche nur, mit Gesichtern darauf zuzugreifen? Ich betone es, weil es wird.
--polygons Eigenschaft --index: Index des Polygons --vertices: Index benachbarter Eckpunkte --loop_start: Index der Startschleifendaten zum Iterieren der Kanten und Scheitelpunkte dieses Polygons (Mesh hat eine Schleifeneigenschaft und einen Index) --loop_total: Anzahl der reellen Schleifen, Anzahl der Polygonscheitelpunkte --loop_indices: Liste der Schleifenindizes
Erhalten
print("num of polygons:", len(msh.polygons))
for pl in msh.polygons:
print("polygon index:{0:2} ".format(pl.index), end="")
print("vertices:", end="")
for vi in pl.vertices:
print("{0:2}, ".format(vi), end="")
print("")
for pl in msh.polygons:
print("polygon index:{0:2} ".format(pl.index))
print(" > loops:", end="")
print(" total:", pl.loop_total, end="")
print(" start:", pl.loop_start, end="")
print(" indices:", end="")
for lp in pl.loop_indices:
print("{0:2}, ".format(lp), end="")
print("")
Ausgabe
num of polygons: 6
polygon index: 0 vertices: 0, 1, 2, 3,
polygon index: 1 vertices: 0, 4, 5, 1,
polygon index: 2 vertices: 1, 5, 6, 2,
polygon index: 3 vertices: 2, 6, 7, 3,
polygon index: 4 vertices: 0, 3, 7, 4,
polygon index: 5 vertices: 4, 7, 6, 5,
polygon index: 0
> loops: total: 4 start: 0 indices: 0, 1, 2, 3,
polygon index: 1
> loops: total: 4 start: 4 indices: 4, 5, 6, 7,
polygon index: 2
> loops: total: 4 start: 8 indices: 8, 9, 10, 11,
polygon index: 3
> loops: total: 4 start: 12 indices:12, 13, 14, 15,
polygon index: 4
> loops: total: 4 start: 16 indices:16, 17, 18, 19,
polygon index: 5
> loops: total: 4 start: 20 indices:20, 21, 22, 23,
Daten, die den Index von Eckpunkten und Kanten verwalten. Es kann verwendet werden, wenn Sie den Kanten um das Polygon folgen möchten. Wenn Sie jedoch die Nachbarschaft von Scheitelpunkten, Kanten und Polygonen richtig verfolgen möchten, ist es besser, in den Bearbeitungsmodus zu wechseln und Bmesh zu verwenden. Ich denke, dass es eine solche Eigenschaft gibt.
print("num of loops:", len(msh.loops))
for lp in msh.loops:
print("loop index:{0:2} vertex index:{1:2} edge index:{2:2}".format(lp.index, lp.vertex_index, lp.edge_index))
Ausgabe
num of loops: 24
loop index: 0 vertex index: 0 edge index: 5
loop index: 1 vertex index: 1 edge index: 7
loop index: 2 vertex index: 2 edge index: 9
loop index: 3 vertex index: 3 edge index:10
loop index: 4 vertex index: 0 edge index:11
loop index: 5 vertex index: 4 edge index: 0
loop index: 6 vertex index: 5 edge index: 8
loop index: 7 vertex index: 1 edge index: 5
loop index: 8 vertex index: 1 edge index: 8
loop index: 9 vertex index: 5 edge index: 4
loop index:10 vertex index: 6 edge index: 3
loop index:11 vertex index: 2 edge index: 7
loop index:12 vertex index: 2 edge index: 3
loop index:13 vertex index: 6 edge index: 2
loop index:14 vertex index: 7 edge index: 1
loop index:15 vertex index: 3 edge index: 9
loop index:16 vertex index: 0 edge index:10
loop index:17 vertex index: 3 edge index: 1
loop index:18 vertex index: 7 edge index: 6
loop index:19 vertex index: 4 edge index:11
loop index:20 vertex index: 4 edge index: 6
loop index:21 vertex index: 7 edge index: 2
loop index:22 vertex index: 6 edge index: 4
loop index:23 vertex index: 5 edge index: 0
Das Einstellen und Abrufen von UV-Strahlen ist so einfach wie das Hinzufügen eines UV-Kanals und das Verwenden dieses Kanals als Schlüssel für den Zugriff auf das UV-Array. Beachten Sie, dass die in UV-Karten der GUI angezeigten Kanäle von der Eigenschaft uv_textures of Mesh verwaltet werden, die tatsächlichen UV-Koordinateninformationen jedoch von der Eigenschaft uv_layers gespeichert werden.
Es wird keine unterschiedliche Topologie für jeden UV-Kanal wie bei 3dsMax beibehalten. Daher ist die Anzahl der in jeder Schicht gehaltenen UV-Koordinaten immer die Summe der Anzahl der Eckpunkte aller Polygone. Blender scheint keine Konzepte wie Schweißen und Schweißen in den Daten zu haben.
>>> len(msh.uv_layers[channel_name].data.items())
24
#UV-Einstellung
tmp = [[0.0, 0.0], [0.5, 0.0], [0.5, 0.5], [0.0, 0.5]]
uvs = tmp * 6 #Initialisieren Sie die einzustellenden UV-Koordinaten
channel_name = "uv0" #UV-Kanalname
msh.uv_layers.new(name=channel_name) #UV-Kanal erstellen
#msh.uv_textures.new(channel_name) #UV-Kanal erstellen
for idx, dat in enumerate(msh.uv_layers[channel_name].data): #Iterieren Sie mit einer Reihe von UV-Schichten
dat.uv = uvs[idx]
Bestätigung der Daten
print("num of uv layers:", len(msh.uv_layers))
#print("num of uv layers:", len(msh.uv_textures))
for ly in msh.uv_layerss:
#for ly in msh.uv_textures:
print(ly.name)
for idx, dat in enumerate(msh.uv_layers[ly.name].data):
print(" {0}:{1}".format(idx, dat.uv))
print("")
Ausgabe
uv0
0:<Vector (0.0000, 0.0000)>
1:<Vector (0.5000, 0.0000)>
2:<Vector (0.5000, 0.5000)>
3:<Vector (0.0000, 0.5000)>
4:<Vector (0.0000, 0.0000)>
5:<Vector (0.5000, 0.0000)>
6:<Vector (0.5000, 0.5000)>
7:<Vector (0.0000, 0.5000)>
8:<Vector (0.0000, 0.0000)>
9:<Vector (0.5000, 0.0000)>
10:<Vector (0.5000, 0.5000)>
11:<Vector (0.0000, 0.5000)>
12:<Vector (0.0000, 0.0000)>
13:<Vector (0.5000, 0.0000)>
14:<Vector (0.5000, 0.5000)>
15:<Vector (0.0000, 0.5000)>
16:<Vector (0.0000, 0.0000)>
17:<Vector (0.5000, 0.0000)>
18:<Vector (0.5000, 0.5000)>
19:<Vector (0.0000, 0.5000)>
20:<Vector (0.0000, 0.0000)>
21:<Vector (0.5000, 0.0000)>
22:<Vector (0.5000, 0.5000)>
23:<Vector (0.0000, 0.5000)>
Vertex Color
Der Zugriff ist über die Eigenschaft vertex_colors leicht möglich.
Aufbau
#6 Seiten Rot, Green, Blue, Cyan, Magenta,Versuchen Sie, mit Gelb zu malen
#colormaps = [[1.0,0.0,0.0]]*4+[[0.0,1.0,0.0]]*4+[[0.0,0.0,1.0]]*4+[[0.0,1.0,1.0]]*4+[[1.0,0.0,1.0]]*4+[[1.0,1.0,0.0]]*4
colormaps = [[1.0,0.0,0.0,1.0]]*4+[[0.0,1.0,0.0,1.0]]*4+[[0.0,0.0,1.0,1.0]]*4+[[0.0,1.0,1.0,1.0]]*4+[[1.0,0.0,1.0,1.0]]*4+[[1.0,1.0,0.0,1.0]]*4
print("colormaps:", colormaps)
msh.vertex_colors.new(name='col')
# msh.vertex_colors.new('col')
for idx, vc in enumerate(msh.vertex_colors['col'].data):
vc.color = colormaps[idx]
Daten bekommen
#Anzeige der Scheitelpunktfarbe
print("num of vertex color layers:", len(msh.vertex_colors))
for ly in msh.vertex_colors:
print(ly.name)
for idx, vc in enumerate(msh.vertex_colors['col'].data):
print(" {0:2}:{1}".format(idx,vc.color))
Ausgabe
num of vertex color layers: 1
col
0:<Color (r=1.0000, g=0.0000, b=0.0000)>
1:<Color (r=1.0000, g=0.0000, b=0.0000)>
2:<Color (r=1.0000, g=0.0000, b=0.0000)>
3:<Color (r=1.0000, g=0.0000, b=0.0000)>
4:<Color (r=0.0000, g=1.0000, b=0.0000)>
5:<Color (r=0.0000, g=1.0000, b=0.0000)>
6:<Color (r=0.0000, g=1.0000, b=0.0000)>
7:<Color (r=0.0000, g=1.0000, b=0.0000)>
8:<Color (r=0.0000, g=0.0000, b=1.0000)>
9:<Color (r=0.0000, g=0.0000, b=1.0000)>
10:<Color (r=0.0000, g=0.0000, b=1.0000)>
11:<Color (r=0.0000, g=0.0000, b=1.0000)>
12:<Color (r=0.0000, g=1.0000, b=1.0000)>
13:<Color (r=0.0000, g=1.0000, b=1.0000)>
14:<Color (r=0.0000, g=1.0000, b=1.0000)>
15:<Color (r=0.0000, g=1.0000, b=1.0000)>
16:<Color (r=1.0000, g=0.0000, b=1.0000)>
17:<Color (r=1.0000, g=0.0000, b=1.0000)>
18:<Color (r=1.0000, g=0.0000, b=1.0000)>
19:<Color (r=1.0000, g=0.0000, b=1.0000)>
20:<Color (r=1.0000, g=1.0000, b=0.0000)>
21:<Color (r=1.0000, g=1.0000, b=0.0000)>
22:<Color (r=1.0000, g=1.0000, b=0.0000)>
23:<Color (r=1.0000, g=1.0000, b=0.0000)>
Shape Key
Es ist im Grunde das gleiche wie die UV-Einstellung. Im Gegensatz zu UV ist die Eigenschaft shape_keys des Netzes sowohl für die Verwaltung der Formschlüssel als auch für die Verwaltung der Scheitelpunktdaten verantwortlich. Es ist die key_blocks-Eigenschaft der shape_keys-Eigenschaft, die die Daten tatsächlich enthält.
Aufbau
#In der beim Erstellen des Cubes definierten verts-Variablen(0,0,1), (0,0,-1)MoveUp jeweils,Verwenden Sie die Taste Nach unten
shapemaps = {'MoveUp':[[v[0],v[1],v[2]+1.0] for v in verts],
'MoveDown':[[v[0],v[1],v[2]-1.0] for v in verts],}
#Erstellen Sie einen Basisschlüssel, wenn keine Form vorhanden ist
obj.shape_key_add()
msh.shape_keys.key_blocks[-1].name = "Basis"
for sname in shapemaps:
lst = shapemaps[sname]
obj.shape_key_add()
kb = msh.shape_keys.key_blocks[-1]
kb.name = sname
for idx, co in enumerate(lst):
kb.data[idx].co = co
Daten bekommen
#Formschlüssel abrufen
print("num of Shape Keys:", len(msh.shape_keys.key_blocks))
for kb in msh.shape_keys.key_blocks:
print(" Key Block:", kb.name)
for idx, dat in enumerate(kb.data):
print(" {0}:{1}".format(idx, dat.co))
Ausgabe
num of Shape Keys: 3
Key Block: Basis
0:<Vector (-1.0000, -1.0000, 1.0000)>
1:<Vector (1.0000, -1.0000, 1.0000)>
2:<Vector (1.0000, 1.0000, 1.0000)>
3:<Vector (-1.0000, 1.0000, 1.0000)>
4:<Vector (-1.0000, -1.0000, -1.0000)>
5:<Vector (1.0000, -1.0000, -1.0000)>
6:<Vector (1.0000, 1.0000, -1.0000)>
7:<Vector (-1.0000, 1.0000, -1.0000)>
Key Block: MoveDown
0:<Vector (-1.0000, -1.0000, 0.0000)>
1:<Vector (1.0000, -1.0000, 0.0000)>
2:<Vector (1.0000, 1.0000, 0.0000)>
3:<Vector (-1.0000, 1.0000, 0.0000)>
4:<Vector (-1.0000, -1.0000, -2.0000)>
5:<Vector (1.0000, -1.0000, -2.0000)>
6:<Vector (1.0000, 1.0000, -2.0000)>
7:<Vector (-1.0000, 1.0000, -2.0000)>
Key Block: MoveUp
0:<Vector (-1.0000, -1.0000, 2.0000)>
1:<Vector (1.0000, -1.0000, 2.0000)>
2:<Vector (1.0000, 1.0000, 2.0000)>
3:<Vector (-1.0000, 1.0000, 2.0000)>
4:<Vector (-1.0000, -1.0000, 0.0000)>
5:<Vector (1.0000, -1.0000, 0.0000)>
6:<Vector (1.0000, 1.0000, 0.0000)>
7:<Vector (-1.0000, 1.0000, 0.0000)>
Vertex Group
Ich denke, es sind die einfachsten Daten, aber es ist die problematischste Datenstruktur. Blender hält das Hautgewicht in dieser Vertex-Gruppe. Daher werden die Daten als assoziatives Array mit dem Index der Scheitelpunktgruppe als Schlüssel und dem Gewicht als Wert für jeden Scheitelpunkt gespeichert. Eine Funktion zum Festlegen des Vertex-Gewichts ist in der Struktur der Vertex-Gruppe enthalten, sodass sie so eingestellt werden kann, als wäre es UV. Ich denke nicht, dass die Verarbeitungsgeschwindigkeit schnell ist.
Aufbau
bone_list = ["bone1", "bone2"]
weight_map = {"bone1":[1.0]*4+[0.0]*4, # [1.0, 1.0, 1.0, 1.0, 0.0, 0.0, 0.0, 0.0],
"bone2":[0.0]*4+[1.0]*4,
}
vg_list = [] #Liste der VertexGroup
#Erstellen einer Scheitelpunktgruppe
for bname in bone_list:
obj.vertex_groups.new(name=bname)
#obj.vertex_groups.new(bname)
vg_list.append(obj.vertex_groups[-1])
#Einstellungen über Vertex Group
for vg in vg_list:
weights = weight_map[vg.name]
for vidx, w in enumerate(weights):
if w != 0.0:
vg.add([vidx], w, 'REPLACE')
Versuchen Sie, die Daten über die Eigenschaften der Eckpunkte abzurufen.
Daten bekommen
#Abrufen des Gewichts über die Gruppeneigenschaft von Vertex
msh = obj.data
for v in msh.vertices:
for vge in v.groups:
print("vindex:{0} group index:{1} weight:{2}".format(v.index, vge.group, vge.weight))
Ausgabe
vindex:0 group index:0 weight:1.0
vindex:1 group index:0 weight:1.0
vindex:2 group index:0 weight:1.0
vindex:3 group index:0 weight:1.0
vindex:4 group index:1 weight:1.0
vindex:5 group index:1 weight:1.0
vindex:6 group index:1 weight:1.0
vindex:7 group index:1 weight:1.0
Sammlungsdaten wie die Dateneigenschaft von uv_layer haben eine Funktion namens foreach_set, und Sie können den Wert in einem Schuss mit einem Array festlegen. Es wurde nicht überprüft, ob es schneller ist, als die Sequenzen normal zu iterieren und sie einzeln zuzuweisen. Beachten Sie, dass diese Methode ein gewöhnliches Array übergibt, das anstelle des Arrays des obigen Arrays abgeflacht ist.
python
tmp = [0.0, 0.0, 0.5, 0.0, 0.5, 0.5, 0.0, 0.5]
uvs = tmp * 6 #Initialisieren Sie die einzustellenden UV-Koordinaten
channel_name = "uv0"
msh.uv_textures.new(channel_name)
msh.uv_layers[channel_name].data.foreach_set("uv", uvlist)
python
shapemaps = {'MoveUp':[[v[0],v[1],v[2]+1.0] for v in verts],
'MoveDown':[[v[0],v[1],v[2]-1.0] for v in verts],}
for sname in shapemaps:
lst = shapemaps[sname]
lst2 = list(chain.from_iterable(lst)) #Dies scheint mit der Methode zum Reduzieren des Arrays von Arrays schneller zu sein
obj.shape_key_add()
sk = msh.shape_keys.key_blocks[-1]
sk.name = sname
sk.data.foreach_set("co", lst2)
Recommended Posts