2
$\begingroup$

My goal is to get a rendered image of an PLY mesh from command line. I wrote this script:

import os
import bpy
import sys
from math import pi

filename = 'web.ply'
in_dir = os.path.join('J:\\', 'aa')
item = os.path.join(in_dir, filename)
out_dir = os.path.join(in_dir, 'out')
os.makedirs(out_dir, exist_ok=True)     


bpy.ops.object.delete()
bpy.ops.import_mesh.ply(filepath=os.path.join(item))
bpy.ops.object.lamp_add(type='SUN', radius=100, view_align=False, location=(0, 0, 0), layers=(True, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False, False))
bpy.ops.object.select_all(action='DESELECT')
for ob in bpy.data.objects:
  print (ob.type, ob.name)
  if ob.type == 'MESH':
    bpy.context.scene.objects.active = ob
    ob.select = True
  elif ob.type == 'CAMERA':
    ob.data.clip_end = 1000000
    ob.data.clip_start = 0.01
    ob.select = False
  else:
    ob.select = False


bpy.ops.transform.rotate(value=pi/2, axis=(True, False, False))
bpy.context.scene.render.resolution_x = 692
bpy.context.scene.render.resolution_y = 900
bpy.context.scene.render.alpha_mode = 'TRANSPARENT'

bpy.ops.object.mode_set(mode='VERTEX_PAINT')

for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        ctx = bpy.context.copy()
        ctx['area'] = area
        ctx['region'] = area.regions[-1]
        bpy.ops.view3d.view_selected(ctx)
        bpy.ops.view3d.camera_to_view_selected(ctx)

bpy.context.scene.render.image_settings.file_format = 'PNG'
bpy.context.scene.render.image_settings.quality = 100
bpy.context.scene.render.filepath = os.path.join(out_dir, filename+'-preview.jpg')
bpy.ops.render.render(write_still=True)

It works, but not properly renders colors. The output image is in gray scale colors! I think that the issue is bpy.ops.object.mode_set(mode='VERTEX_PAINT') and the position inside the script. Something is wrong. Any tips? Here a PLY example file: http://156.54.99.175/3d/a.ply

$\endgroup$
  • $\begingroup$ which render engine would you prefer? Cycles or Blender Internal. $\endgroup$ – zeffii Sep 2 '15 at 10:16
  • $\begingroup$ Blender Internal, thankyou @zeffii your script works like a sharm! And great explanation, you are my guru. $\endgroup$ – sborfedor Sep 2 '15 at 13:13
  • $\begingroup$ Your script was very close already - hopefully this cleared up some details. $\endgroup$ – zeffii Sep 2 '15 at 13:32
2
$\begingroup$

If you used bpy.ops.screen.screenshot(ctx, filepath=destination, full=False) in the correct context it would save a screenshot of what you see in the viewport, but render.render() isn't the same as doing a screenshot.

I think you're getting something like this? enter image description here

You need to set up a material to pipe the Vertex Color Layer to the material diffuse colour. Right now you are rendering the object with the default material, which doesn't know anything about the Vertex Color layer. The .ply importer doesn't assign a material to your object.

Blender Internal materials.

enter image description here

# assuming there is a material assigned to the object.
obj.data.materials[0].use_vertex_color_paint = True

else it's something like

obj = bpy.data.objects['a']
mat = bpy.data.materials.new('material_1')
obj.active_material = mat
mat.use_vertex_color_paint = True

maybe stick some ambient occlusion on it:

enter image description here

bpy.data.worlds["World"].light_settings.use_ambient_occlusion = True

For cycles materials

via the UI it's pretty easy

enter image description here

Which makes a node setup like this:

enter image description here

If you wanted to script that, that's another matter.

Your script adjusted (expects Blender Internal)

import os
import bpy
import sys
from math import pi

# filename = 'web.ply'
# in_dir = os.path.join('J:\\', 'aa')
filename = 'a.ply'
in_dir = "/home/zeffii/Desktop"
item = os.path.join(in_dir, filename)
out_dir = os.path.join(in_dir, 'out')
os.makedirs(out_dir, exist_ok=True)


bpy.ops.object.delete()
bpy.ops.import_mesh.ply(filepath=item)
bpy.ops.object.lamp_add(
    type='SUN', radius=100,
    view_align=False, location=(0, 0, 0),
    layers=tuple(i == 0 for i in range(20))
)
bpy.ops.object.select_all(action='DESELECT')

for ob in bpy.data.objects:
    print(ob.type, ob.name)
    if ob.type == 'MESH':
        bpy.context.scene.objects.active = ob
        ob.select = True
        mat = bpy.data.materials.new('material_1')
        ob.active_material = mat
        mat.use_vertex_color_paint = True
    elif ob.type == 'CAMERA':
        ob.data.clip_end = 1000000
        ob.data.clip_start = 0.01
        ob.select = False
    else:
        ob.select = False

bpy.ops.transform.rotate(value=pi / 2, axis=(True, False, False))
scn = bpy.context.scene
scn.render.resolution_x = 692
scn.render.resolution_y = 900
scn.render.alpha_mode = 'TRANSPARENT'
bpy.data.worlds["World"].light_settings.use_ambient_occlusion = True


for area in bpy.context.screen.areas:
    if area.type == 'VIEW_3D':
        ctx = bpy.context.copy()
        ctx['area'] = area
        ctx['region'] = area.regions[-1]
        bpy.ops.view3d.view_selected(ctx)
        bpy.ops.view3d.camera_to_view_selected(ctx)

scn.render.image_settings.file_format = 'PNG'
scn.render.image_settings.quality = 100
scn.render.filepath = os.path.join(out_dir, filename + '-preview.jpg')
bpy.ops.render.render(write_still=True)

outputs this:

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.