9
$\begingroup$

I'm using blender 2.72b x64 on windows 7.

I need a quick way to render armature using f12 button. With shadows and everything. "render armature" means render geometry that is visible in viewports - boxes/octahedrons/sticks, depending on chosen visualization.

I only need to render still frames, no animation.

"OpenGL render image" is not an option, because OpenGL render does not produce raytraced shadows.

As I understand it, this can be done by either somehow turning armature into renderable geometry or generating mesh from it via script.

Is there a built-in way to do it or ready to use script somewhere?

$\endgroup$
3
  • $\begingroup$ Not a duplicate, because opengl render does not render shadows. $\endgroup$
    – SigTerm
    Nov 8, 2014 at 15:56
  • 2
    $\begingroup$ AFAIK there is no built in way to do it, but a script probably wouldn't be too hard. Not sure if one exists or not though.. $\endgroup$
    – gandalf3
    Nov 8, 2014 at 20:10
  • $\begingroup$ @gandalf3: Sigh... it's been 2 or 3 years since I wrote last blender exporter in python. Guess I'll get to writing the script if nobody has a snippet to share (I'll post it here if I finish it). I've been used armature+rigify as wooden manikins for 2d drawing reference and lighting/shadows for a rough idea which light goes where. Works perfectly with exception of armature being invisible in render window. $\endgroup$
    – SigTerm
    Nov 8, 2014 at 22:33

2 Answers 2

16
$\begingroup$

Blender doesn't support rendering armatures directly.

This is intentional and there is no plan to add support for this feature. ~ @ideasman42


However, I've come up with script to convert armature into mesh or skin.

Implemented as blender addon, only BBone armature style is supported (bezier bones, subdivided bones etc are untested).

Creates mesh if armature in "pose" mode. Creates SKIN if armature is in "skin" mode.

armature_to_mesh.py

bl_info = {"name": "Armature To Mesh", "category": "Object"}

import bpy
import mathutils

class ArmatureToMesh(bpy.types.Operator):
    """Armature to mesh/skin conversion script"""
    bl_idname = "object.armature_to_mesh_skin"
    bl_label = "Armature to Mesh/Skin"
    bl_options = {'REGISTER', 'UNDO'}

    def decomposeMatrix(self, matrix):
        return [x.to_3d() for x in matrix.transposed()]

    def processArmature(self, context, arm, genVertexGroups = True):
        print("processing armature {0}".format(arm.name))

        if genVertexGroups:
            #because setting pose_position ot 'REST' manually doesn't work for some reason.
            genVertexGroups = arm.data.pose_position == 'REST'

        meshName = arm.name + "_mesh"
        meshData = bpy.data.meshes.new(meshName + "Data")
        meshObj = bpy.data.objects.new(meshName, meshData)
        meshObj.location = arm.location

        scene = context.scene
        #scene.objects.link(meshObj)
        # update 
        scene.collection.objects.link(meshObj)

        armMatrix = arm.matrix_local.copy()

        verts = []
        edges = []
        faces = []
        vertexGroups = {}


        for bone in arm.pose.bones:
            poseBone = bone
            boneName = bone.name
            armBone = arm.data.bones[boneName]
            #print(poseBone.matrix)
            #print(armBone.matrix)
            #print(boneName)

            boneMatrix = poseBone.matrix
            boneStart = poseBone.head
            boneEnd = poseBone.tail

            decomposedMatrix = self.decomposeMatrix(boneMatrix)
            #print(decomposedMatrix)
            xSize = armBone.bbone_x
            zSize = armBone.bbone_z
            #print(xSize, zSize)
            xSizeAdd = bone.x_axis
            zSizeAdd = bone.z_axis
            xSizeAdd = decomposedMatrix[0]
            zSizeAdd = decomposedMatrix[2]
            ySizeAdd = decomposedMatrix[1]
            origin = mathutils.Vector((0.0, 0.0, 0.0)) @ boneMatrix
            xSizeAdd *= xSize
            zSizeAdd *= zSize
            ySizeAdd *= bone.length

            baseIndex = len(verts)

            verts.append((boneStart - xSizeAdd + zSizeAdd)@armMatrix)
            verts.append((boneStart + xSizeAdd + zSizeAdd)@armMatrix)
            verts.append((boneStart - xSizeAdd - zSizeAdd)@armMatrix)
            verts.append((boneStart + xSizeAdd - zSizeAdd)@armMatrix)
            verts.append((boneEnd - xSizeAdd + zSizeAdd)@armMatrix)
            verts.append((boneEnd + xSizeAdd + zSizeAdd)@armMatrix)
            verts.append((boneEnd - xSizeAdd - zSizeAdd)@armMatrix)
            verts.append((boneEnd + xSizeAdd - zSizeAdd)@armMatrix)

            base = baseIndex
            newFaces = [
                (base+0, base+1, base+3, base+2),
                (base+5, base+4, base+6, base+7),
                (base+1, base+0, base+4, base+5),
                (base+2, base+3, base+7, base+6),
                (base+3, base+1, base+5, base+7),
                (base+0, base+2, base+6, base+4)
                ]
            faces.extend(newFaces)

            if genVertexGroups:
                vertexGroups[boneName] = [(x, 1.0) for x in range(baseIndex, len(verts))]

        meshData.from_pydata(verts, edges, faces)

        if genVertexGroups:
            for name, vertexGroup in vertexGroups.items():
                groupObject = meshObj.vertex_groups.new(name)
                for (index, weight) in vertexGroup:
                    groupObject.add([index], weight, 'REPLACE')

            modifier = meshObj.modifiers.new('ArmatureMod', 'ARMATURE')
            modifier.object = arm
            modifier.use_bone_envelopes = False
            modifier.use_vertex_groups = True

        meshData.update()

        return meshObj

    def processObject(self, context, obj):
        if (obj == None):
            return False
        if (obj.type != "ARMATURE"):
            print ("invalid type {0} of object {1}: armature expected".format(obj.type, obj.name))
            return False
        self.processArmature(context, obj)
        return True

    def execute(self, context):
            scene = context.scene
            selected = context.selected_objects
            processedAnything = False
            if len(selected) > 0:
                print ("selected objects present, processing selection")
                for obj in selected:
                    processedAnything |= self.processObject(context, obj)
                pass
            else:
                print ("processing active object")
                obj = context.active_object
                processedAnything |= self.processObject(context, obj)

            if not processedAnything:
                print ("no objects processed")

            return {'FINISHED'}

def register():
    bpy.utils.register_class(ArmatureToMesh)

def unregister():
    bpy.utils.unregister_class(ArmatureToMesh)

if __name__ == "__main__": 
    register()

Armature-to-skin in action. Screenshot

$\endgroup$
7
  • $\begingroup$ sorry I am new to Blender...how can I use your Python script for rendering? $\endgroup$
    – user14004
    Apr 26, 2015 at 15:33
  • $\begingroup$ see this answer running-python-script-in-blender $\endgroup$
    – Chebhou
    Apr 26, 2015 at 15:47
  • $\begingroup$ Yeah, actually I meant...what the script really does? how can i launch it in order to obtain the armature meshes? $\endgroup$
    – user14004
    Apr 26, 2015 at 16:40
  • 1
    $\begingroup$ @Gennosuke: Armature does not have a mesh. So you can't "obtain" it. The script should be placed into "addons" folder (google how to install addons for blender). It creates new (renderable) object and attaches it to armature. You need to select armature, press "space", start typing "armature", select "Armature to Mesh/Skin" and that will create renderable object. If armature is in "pose" mode, it will be mesh that won't move with armature. If armature is in "skin" mode, it will be skinned mesh that'll be attached to armature. Only boxed representation of armature is supported. $\endgroup$
    – SigTerm
    Apr 28, 2015 at 14:07
  • $\begingroup$ Thanks for the add-on, found by searching for a way to render bones in Blender, but this is useful for more than just that. $\endgroup$
    – user16810
    Aug 31, 2015 at 6:00
5
$\begingroup$

Viewport Render.

In answer to put color to bvh and render , which was closed as a dupe of this question, it may be the case that a viewport render will suffice. Realize question here stipulates need for shadows etc, for which case this is not a viable option (See below re fudging it... may look into doing properly)

enter image description here

Result as demonstrated in bvh display multiple frames at the same time

  • After import of bvh enter pose mode, select all pose bones, create and assign to a group. Then assign a color to the group, choose from preseets or create your own. enter image description here

  • Go to view port overlays and turn everything you don't want to see off, like the grid,

  • In viewport shading for above have chosen flat, and world for background. Changed world bg to white.

  • To render press F3 type in, then select "viewport render" to render what you see in current 3D vies.

Shadows.

Possibly worth mentioning can emulate shadows by transforming a copy onto a shadow plane.

enter image description here

Very Dodgy Example, displayed as sticks, copy rotated to lie on ground plane and scaled to zero on Z.

$\endgroup$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .