====== House of Cards Blender Project ======
Wanting to make a huge virtual house of cards and placing a large picture, tiling across certain panels of the cards. Need to UV map to portion of a big graphic with Python scripting.
Initial proof of concept jittered. Fixed by changing Scene->Rigid Body World -> Steps Per Second from 60 to 120.
* [[pythonoperators|Python Operators from Blender]]
* [[cardfaceinfo|Card Face Graphic Info]]
* [[blenderarraynumbering|Blender Array Numbering]]
* [[shufflecards|Shuffle Cards Routine in Python]]
* [[physicssettings|Physics Settings]]
* [[workingpython|Work Python Scripts (backup)]]
* [[playingcardspecifics|Playing Card Specifics]]
My example ''c:\Projects\HouseOfCards\panelTest.blend'' has one object "Panel" which has two material slots,
* Pink
* Card Face
In Python console, to look at the "Panel" dominoe:
dir (bpy.data.objects["Panel"]);
Returns lots of methods, values.
ob = bpy.data.objects["Panel"];
print (ob.active_material.name);
// -> Pink
>> type(ob.material_slots);
>>> len(ob.material_slots);
2
>>> list(ob.material_slots);
[bpy.data.objects['Panel'].material_slots[0],
bpy.data.objects['Panel'].material_slots[1]]
**Show name of material slot **(there are two in this example)
>> ob.material_slots[0].name
'Card Face'
**Show vertices**
ob = bpy.data.objects["Panel"];
mesh = ob.data;
for vertex in mesh.vertices:
print(vertex.co)
**Following need to be run in Object mode**
==== Printing UVs for Object ====
UVs are stored in a UV layer, but still need to know which uv_layer goes with which face:
ob = bpy.data.objects["Panel"];
for uv_layer in ob.data.uv_layers:
print("uv_layer: %s" % uv_layer.name)
for loop in ob.data.loops :
uv_coords = ob.data.uv_layers[0].data[loop.index].uv
print("Loop %d: %s" % (loop.index, uv_coords))
==== Get UVs per Face, Example from web ====
https://blenderartists.org/forum/showthread.php?254004-Accessing-UV-data-in-Python-script
import bpy
ob = bpy.data.objects["Panel"];
me = ob.data;
for f in me.polygons:
print("Polygon", f.index, "from loop index", f.loop_start, "and length", f.loop_total)
for i in f.loop_indices: # <-- python Range object with the proper indices already set
l = me.loops[i] # The loop entry this polygon point refers to
v = me.vertices[l.vertex_index] # The vertex data that loop entry refers to
print("\tLoop index", l.index, "points to vertex index", l.vertex_index, \
"at position", v.co)
for j,ul in enumerate(me.uv_layers):
print("\t\tUV Map", j, "has coordinates", ul.data[l.index].uv, \
"for this loop index")
Noticing that the polygon where the vertex index set (2, 3, 6, 7, in my case) equals the set in the Vertex Group I defined, **has the proper UV set.**
Their explanation:
The me.loops object is really a lookup list, and each entry is NOT a loop in and of itself. The "loops" are really polygons and are stored in the me.polygons structure. Using me.polygons, you can slice the me.loops list into chunks.
Running this on the default cube shows that me.polygons has six entries (the six faces of the cube). Each polygon refers to four loop indexes, making the me.loops list 24 entries long.
Every UV layer in me.uv_layers has a "data" attribute that is a list that is the same length as the me.loops list. Every me.loops entry relates to the same index entry in the me.uv_layers[n].data list.
==== Printing Vertices Per Mesh ====
**Vertices**
ob = bpy.data.objects["Panel"];
mesh = ob.data;
for vertex in mesh.vertices:
print(vertex.co)
Assigned vertices of card front and back to Vertex Groups:
^Card Front|Card Rank/Suit|
^Card Back|Card Back - Photo|
Let's find the vertex groups, to print out their UVs:
ob = bpy.data.objects["Panel"];
vgCardBack = ob.vertex_groups['Card Back'];
print('Card Back');
for vertex in vgCardBack.vertices:
print(vertex.co)
vgCardFront = ob.vertex_groups['Card Front'];
print('Card Front');
for vertex in vgCardFront.vertices:
print(vertex.co)
**Find vertices in Vertex Group**
Original, from http://blenderartists.org/forum/showthread.php?252350-Selecting-vertices-of-a-vertex-group
import bpy
# find the index of the target group
for obj in bpy.data.objects:
if type(obj.data) != bpy.types.Mesh:
continue
# This is an Object with a Mesh, see if it has the supported group name
groupIndex = -1
for i in range(0, len(obj.vertex_groups)):
group = obj.vertex_groups[i]
if group.name == "Test":
groupIndex = i
print("Checking %s for assigned vertices." % (obj.name))
# Now access the vertices that are assigned to this group
mesh = obj.data
for v in mesh.vertices:
for vertGroup in v.groups:
if vertGroup.group == groupIndex:
print("Vertex %d is part of group."%(v.index))
==== Non-BMesh, Working script ====
Modified to work with "Panel" example blend file:
import bpy
# find the index of the target group
ob = bpy.data.objects["Panel"];
# Print all vertices
print("\nPrinting all vertices.")
mesh = ob.data;
for vertex in mesh.vertices:
print(vertex.co)
# This is an Object with a Mesh, see if it has the supported group name
groupIndex = -1
groupName = "Card Back"
for i in range(0, len(ob.vertex_groups)):
group = ob.vertex_groups[i]
if group.name == groupName:
groupIndex = i
print("Checking %s for assigned vertices, groupIndex is %f" % (ob.name, groupIndex))
# Now access the vertices that are assigned to this group
mesh = ob.data
for v in mesh.vertices:
for vertGroup in v.groups:
if vertGroup.group == groupIndex:
print("Vertex %d is part of group %s."%(v.index, groupName))
# Find the UVs to go with these Vertices
===== Using BMesh =====
https://www.blender.org/api/blender_python_api_2_77_1/bmesh.html#module-bmesh
import bpy
import bmesh
ob = bpy.data.objects["Panel"];
# Get the active mesh
me = ob.data
# Get a BMesh representation
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
# Modify the BMesh, can do anything here...
for v in bm.verts:
v.co.x -= 1.0
# Finish up, write the bmesh back to the mesh
bm.to_mesh(me)
bm.free() # free and prevent further access
**Shows Vertexes and UVs**
Per face.
import bpy
import bmesh
ob = bpy.data.objects["Panel"];
# Get the active mesh
me = ob.data
# Get a BMesh representation
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
uv_lay = bm.loops.layers.uv.active
for face in bm.faces:
print("face index %d" % face.index);
for loop in face.loops:
uv = loop[uv_lay].uv
print("Loop UV: %f, %f" % uv[:])
vert = loop.vert
print("Loop Vertex: (%f,%f,%f)" % vert.co[:])
Let's try finding the face defined by the verts in the Vertex Group "Card Back".
import bpy
import bmesh
ob = bpy.data.objects["Panel"];
me = ob.data
# Get a BMesh representation
bm = bmesh.new() # create an empty BMesh
bm.from_mesh(me) # fill it in from a Mesh
uv_lay = bm.loops.layers.uv.active
# Find the vertex group vertices
groupIndex = -1
# This is an Object with a Mesh, see if it has the supported group name
for i in range(0, len(ob.vertex_groups)):
group = ob.vertex_groups[i]
if group.name == "Card Back":
groupIndex = i
# Now access the vertices that are assigned to this group
bmVertGroupMembers = []
for v in me.vertices:
for vertGroup in v.groups:
if vertGroup.group == groupIndex:
print("Vertex %d is part of group."%(v.index))
bmVertGroupMembers.new(v)
# Following doesn't work
groupFace = bm.faces.get(bmVertGroupMembers);
print ("groupFace len: %d" % len(groupFace))
Going back to non-BMESH method. In BMesh, it is difficult to assemble the correct types.
==== Get Face from Mesh defined by Vertex Group ====
import bpy
ob = bpy.data.objects["Panel"];
def getFaceFromObjectContainingVertexGroup(ob, vertexGroupName):
# First, get list of Vertexes in Vertex Group
groupIndex = -1
# This is an Object with a Mesh, see if it has the supported group name
for i in range(0, len(ob.vertex_groups)):
group = ob.vertex_groups[i]
if group.name == vertexGroupName:
groupIndex = i
# if we didn't find it, exit
if (groupIndex < 0):
return null
# Now access the vertices that are assigned to this group
bmVertGroupMembers = []
for v in ob.data.vertices:
for vertGroup in v.groups:
if vertGroup.group == groupIndex:
print("Vertex %d is part of group."%(v.index))
bmVertGroupMembers.append(v)
# at this point, we have a list of vertices in bmVertGroupMembers
# belonging to group vertexGroupName, with index groupIndex
for f in me.polygons:
print("Polygon", f.index, "from loop index", f.loop_start, "and length", f.loop_total)
for i in f.loop_indices: # <-- python Range object with the proper indices already set
l = me.loops[i] # The loop entry this polygon point refers to
v = me.vertices[l.vertex_index] # The vertex data that loop entry refers to
print("\tLoop index", l.index, "points to vertex index", l.vertex_index, \
"at position", v.co)
for j,ul in enumerate(me.uv_layers):
print("\t\tUV Map", j, "has coordinates", ul.data[l.index].uv, \
"for this loop index")