====== 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")