# Changing active camera will yield an incorrect rendering (camera view not reflected)

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.numCams = len(camPosList)
for i, coords in enumerate(camPosList):
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()

self.activeObj = self.scene.objects.active
self.activeObj.name = 'interiorIlluminator'
self.activeObj.data.name = 'interiorIlluminator'
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
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


And finally a .Blende file:

• I notice that the “activateCamera(self, camNo)” function assigns self.scene.camera twice - firstly to self.scene.objects['camera.0' + str(camNo)] and secondly to self.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. May 8, 2018 at 13:25
• @RichSedman Sorry that was a mistake. I don't use self.activeObj for that at all. Updated my post
– Amir
May 8, 2018 at 13:26
• Does the guy who solves your issue get a credit in the paper? May 8, 2018 at 15:03
• @brockmann Yes; he/she will be acknowledged :)
– Amir
May 8, 2018 at 20:53
• @RichSedman I resolved the issue in a hacky way. But do you think any part of my original code could be culprit for this problem?
– Amir
May 9, 2018 at 0:04