I have defined a Blender class to help me abstract out details for rendering, object manipulation etc. I setup my scene using this class and put 12 cameras in it. Then I start rendering objects by switching between each of these cameras. A very strange thing that I noticed was no matter what the camera coordinates are, the last camera ALWAYS renders a black image as I had mentioned before, although my objects are all located at (0, 0, 0). I did some trial and error and found out that adding a "fake" camera would resolve the issue. However, what I then noticed was the rendering results of camera00 and camera04 are ALWAYS the same although the location of both cameras are completely different. This happens even if I change all of the camera coordinates. Another other strange fact is that all other cameras render the right images. Initially I was thinking the camera coordinates are the same but when I loaded the .blend file on my laptop I noticed that is not the case. I can render the objects correctly if I manually load the blend file and render with camera04. However I cannot do my rendering like that as I have many objects. The way I am currently doing my renderings is by compiling Blender as a Python module and loading it on my machine's Python.
This is a very strange issue. Does anyone know whether I am doing something wrong or how I can resolve it? Am I activating the cameras properly?
Below you can see the class I have defined and how I do the rendering:
#blenderClass.py
import importlib
class Blender(object):
def __init__(self):
self.bpy = importlib.import_module("bpy")
self.scene = self.bpy.context.scene
def setupScene(self, camPosList):
self.cleanScene()
self.addSun()
self.numCams = len(camPosList)
for i, coords in enumerate(camPosList):
self.bpy.ops.object.camera_add(location=tuple(coords))
self.activeObj = self.scene.objects.active
self.activeObj.name = 'camera.0' + str(i)
self.activeObj.data.name = 'camera.0' + str(i)
self.pointObjTo(self.activeObj, (0.0, 0.0, 0.0))
# Add a fake camera but never activate it
self.bpy.ops.object.camera_add(location=tuple(coords)) # Use the last coords
self.activeObj = self.scene.objects.active
self.activeObj.name = 'camera.0' + str(i+1) # Use the last i from the for loop
self.activeObj.data.name = 'camera.0' + str(i+1)
self.pointObjTo(self.activeObj, (0.0, 0.0, 0.0))
def render(self, objPath, renderPath):
self.bpy.ops.import_scene.obj(filepath=objPath, split_mode="OFF")
for i in range(self.numCams):
self.scene.render.filepath = renderPath + str(i) + '.png'
self.activateCamera(i)
self.bpy.ops.render.render(write_still=True)
def pointObjTo(self, obj, xyzTarget):
direction = Vector(xyzTarget) - obj.location
obj.rotation_euler = direction.to_track_quat('-Z', 'Y').to_euler()
def activateCamera(self, camNo):
self.scene.camera = self.scene.objects['camera.0' + str(camNo)]
self.scene.update()
def addSun(self, location=(0.0, 0.0, 1)):
self.bpy.ops.object.lamp_add(type='SUN', location=location)
self.activeObj = self.scene.objects.active
self.activeObj.name = 'interiorIlluminator'
self.activeObj.data.name = 'interiorIlluminator'
self.activeObj.data.shadow_method = 'NOSHADOW'
self.activeObj.data.energy = 0.8
def cleanScene(self):
self.removeLamps()
self.removeMeshes(0)
self.removeCameras()
def removeMeshes(self, layer = -1):
for obj in self.scene.objects:
if obj.type == 'MESH' and obj.layers[layer != -1 and layer]:
obj.select = True
else:
obj.select = False
self.bpy.ops.object.delete()
def removeCameras(self):
for obj in self.scene.objects:
if obj.type == 'CAMERA':
obj.select = True
else:
obj.select = False
self.bpy.ops.object.delete()
def removeLamps(self):
for obj in self.scene.objects:
if obj.type == 'LAMP':
obj.select = True
else:
obj.select = False
self.bpy.ops.object.delete()
And here's how I do my renderings:
#main.py
import blenderClass import Blender
import numpy as np
camPosList = np.loadtxt('camPosList.txt')
blender = Blender()
blender.setupScene()
objPaths = ['obj1.obj', 'obj2.obj', 'obj3.obj', 'obj4.obj']
for objPath in objPaths:
blender.render(objPath, 'somePath')
And here are the coordinates in camPosList::
1.106609463691711426e+00 -1.284419745206832886e-01 -4.973111748695373535e-01
2.114785015583038330e-01 -1.041638731956481934e+00 -5.988617539405822754e-01
6.345187127590179443e-02 7.305476069450378418e-02 -1.216143369674682617e+00
5.116637349128723145e-01 1.007419824600219727e+00 -4.601101875305175781e-01
9.366978406906127930e-01 4.701653420925140381e-01 6.244274377822875977e-01
7.511696219444274902e-01 -7.962130308151245117e-01 5.386640429496765137e-01
-9.366978406906127930e-01 -4.701653420925140381e-01 -6.244274377822875977e-01
-7.511696219444274902e-01 7.962130308151245117e-01 -5.386640429496765137e-01
-2.114785015583038330e-01 1.041638731956481934e+00 5.988617539405822754e-01
-6.345187127590179443e-02 -7.305476069450378418e-02 1.216143369674682617e+00
-5.116637349128723145e-01 -1.007419824600219727e+00 4.601101875305175781e-01
-1.106609463691711426e+00 1.284419745206832886e-01 4.973111748695373535e-01
You can download a set of rendering results from here: https://drive.google.com/open?id=1vqX_lLCFY7W3gll5CJ2hoaNzmhK8BLxp
And finally a .Blende file:
self.scene.objects['camera.0' + str(camNo)]
and secondly toself.activeObj
. Why is that? Without understanding more about this assignment I can’t say if this would be a problem but it certainly looks suspicious. $\endgroup$