def testTraceSets(self): sphere = GafferScene.Sphere() group = GafferScene.Group() group["in"][0].setInput(sphere["out"]) group["in"][1].setInput(sphere["out"]) set1 = GafferScene.Set() set1["name"].setValue("render:firstSphere") set1["paths"].setValue(IECore.StringVectorData(["/group/sphere"])) set1["in"].setInput(group["out"]) set2 = GafferScene.Set() set2["name"].setValue("render:secondSphere") set2["paths"].setValue(IECore.StringVectorData(["/group/sphere1"])) set2["in"].setInput(set1["out"]) set3 = GafferScene.Set() set3["name"].setValue("render:group") set3["paths"].setValue(IECore.StringVectorData(["/group"])) set3["in"].setInput(set2["out"]) set4 = GafferScene.Set() set4["name"].setValue("render:bothSpheres") set4["paths"].setValue( IECore.StringVectorData(["/group/sphere", "/group/sphere1"])) set4["in"].setInput(set3["out"]) render = GafferArnold.ArnoldRender() render["in"].setInput(set4["out"]) render["mode"].setValue(render.Mode.SceneDescriptionMode) render["fileName"].setValue(self.temporaryDirectory() + "/test.ass") render["task"].execute() with IECoreArnold.UniverseBlock(writable=True): arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass") firstSphere = arnold.AiNodeLookUpByName("/group/sphere") secondSphere = arnold.AiNodeLookUpByName("/group/sphere1") self.assertEqual( self.__arrayToSet( arnold.AiNodeGetArray(firstSphere, "trace_sets")), {"firstSphere", "group", "bothSpheres"}) self.assertEqual( self.__arrayToSet( arnold.AiNodeGetArray(secondSphere, "trace_sets")), {"secondSphere", "group", "bothSpheres"})
def get_node_by_name(self, name): ainode = arnold.AiNodeLookUpByName(name) node = ArnoldNode() node.set_data(ainode) return node
def testAdaptors( self ) : sphere = GafferScene.Sphere() def a() : result = GafferArnold.ArnoldAttributes() result["attributes"]["matte"]["enabled"].setValue( True ) result["attributes"]["matte"]["value"].setValue( True ) return result GafferScene.RendererAlgo.registerAdaptor( "Test", a ) sphere = GafferScene.Sphere() render = GafferArnold.ArnoldRender() render["in"].setInput( sphere["out"] ) render["mode"].setValue( render.Mode.SceneDescriptionMode ) render["fileName"].setValue( self.temporaryDirectory() + "/test.ass" ) render["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) node = arnold.AiNodeLookUpByName( "/sphere" ) self.assertEqual( arnold.AiNodeGetBool( node, "matte" ), True )
def testLightFilters(self): s = Gaffer.ScriptNode() s["lightFilter"] = GafferArnold.ArnoldLightFilter() s["lightFilter"].loadShader("light_blocker") s["attributes"] = GafferScene.StandardAttributes() s["attributes"]["in"].setInput(s["lightFilter"]["out"]) s["attributes"]["attributes"]["filteredLights"]["enabled"].setValue( True) s["attributes"]["attributes"]["filteredLights"]["value"].setValue( "defaultLights") s["light"] = GafferArnold.ArnoldLight() s["light"].loadShader("point_light") s["gobo"] = GafferArnold.ArnoldShader() s["gobo"].loadShader("gobo") s["assignment"] = GafferScene.ShaderAssignment() s["assignment"]["in"].setInput(s["light"]["out"]) s["assignment"]["shader"].setInput(s["gobo"]["out"]) s["group"] = GafferScene.Group() s["group"]["in"][0].setInput(s["attributes"]["out"]) s["group"]["in"][1].setInput(s["assignment"]["out"]) s["render"] = GafferArnold.ArnoldRender() s["render"]["in"].setInput(s["group"]["out"]) s["render"]["mode"].setValue(s["render"].Mode.SceneDescriptionMode) s["render"]["fileName"].setValue(self.temporaryDirectory() + "/test.ass") s["render"]["task"].execute() with IECoreArnold.UniverseBlock(writable=True): arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass") light = arnold.AiNodeLookUpByName("light:/group/light") linkedFilters = arnold.AiNodeGetArray(light, "filters") numFilters = arnold.AiArrayGetNumElements(linkedFilters.contents) self.assertEqual(numFilters, 2) linkedFilter = arnold.cast(arnold.AiArrayGetPtr(linkedFilters, 0), arnold.POINTER(arnold.AtNode)) linkedGobo = arnold.cast(arnold.AiArrayGetPtr(linkedFilters, 1), arnold.POINTER(arnold.AtNode)) self.assertEqual(arnold.AiNodeGetName(linkedFilter), "lightFilter:/group/lightFilter") self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry(linkedFilter)), "light_blocker") self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry(linkedGobo)), "gobo")
def testReadOnlyUniverseDoesntPreventWritableUniverseCleanup(self): with IECoreArnold.UniverseBlock(writable=False): with IECoreArnold.UniverseBlock(writable=True): node = arnold.AiNode("polymesh") arnold.AiNodeSetStr(node, "name", "test") self.assertEqual(arnold.AiNodeLookUpByName("test"), None)
def testLightFiltersMany(self): # \todo: this can easily be turned into a performance test s = Gaffer.ScriptNode() s["lightFilter"] = GafferArnold.ArnoldLightFilter() s["lightFilter"].loadShader("light_blocker") s["lightFilter"]["filteredLights"].setValue("defaultLights") s["planeFilters"] = GafferScene.Plane("Plane") s["planeFilters"]["divisions"].setValue(imath.V2i(9)) s["instancerFilters"] = GafferScene.Instancer("Instancer") s["instancerFilters"]["in"].setInput(s["planeFilters"]["out"]) s["instancerFilters"]["instances"].setInput(s["lightFilter"]["out"]) s["instancerFilters"]["parent"].setValue("/plane") s["light"] = GafferArnold.ArnoldLight() s["light"].loadShader("point_light") s["planeLights"] = GafferScene.Plane("Plane") s["planeLights"]["divisions"].setValue(imath.V2i(9)) s["instancerLights"] = GafferScene.Instancer("Instancer") s["instancerLights"]["in"].setInput(s["planeLights"]["out"]) s["instancerLights"]["instances"].setInput(s["light"]["out"]) s["instancerLights"]["parent"].setValue("/plane") s["group"] = GafferScene.Group("Group") s["group"]["in"][0].setInput(s["instancerFilters"]["out"]) s["group"]["in"][1].setInput(s["instancerLights"]["out"]) s["render"] = GafferArnold.ArnoldRender() s["render"]["in"].setInput(s["group"]["out"]) s["render"]["mode"].setValue(s["render"].Mode.SceneDescriptionMode) s["render"]["fileName"].setValue(self.temporaryDirectory() + "/testMany.ass") s["render"]["task"].execute() with IECoreArnold.UniverseBlock(writable=True): foo = self.temporaryDirectory() + "/testMany.ass" print foo arnold.AiASSLoad(foo) for i in range(100): light = arnold.AiNodeLookUpByName( "light:/group/plane1/instances/light/%s" % i) linkedFilters = arnold.AiNodeGetArray(light, "filters") numFilters = arnold.AiArrayGetNumElements( linkedFilters.contents) self.assertEqual(numFilters, 100)
def testNoLinkedLightsOnLights(self): sphere = GafferScene.Sphere() meshLightShader = GafferArnold.ArnoldShader() meshLightShader.loadShader("flat") meshLightFilter = GafferScene.PathFilter() meshLightFilter["paths"].setValue(IECore.StringVectorData(["/sphere"])) meshLight = GafferArnold.ArnoldMeshLight() meshLight["in"].setInput(sphere["out"]) meshLight["filter"].setInput(meshLightFilter["out"]) meshLight["parameters"]["color"].setInput(meshLightShader["out"]) light1 = GafferArnold.ArnoldLight() light1.loadShader("point_light") light2 = GafferArnold.ArnoldLight() light2.loadShader("point_light") # Trigger light linking by unlinking a light light2["defaultLight"].setValue(False) group = GafferScene.Group() group["in"][0].setInput(meshLight["out"]) group["in"][1].setInput(light1["out"]) group["in"][2].setInput(light2["out"]) render = GafferArnold.ArnoldRender() render["in"].setInput(group["out"]) render["mode"].setValue(render.Mode.SceneDescriptionMode) render["fileName"].setValue(self.temporaryDirectory() + "/test.ass") render["task"].execute() with IECoreArnold.UniverseBlock(writable=True): arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass") sphere = arnold.AiNodeLookUpByName("/group/sphere") self.assertIsNotNone(sphere) self.assertEqual( arnold.AiArrayGetNumElements( arnold.AiNodeGetArray(sphere, "light_group")), 0) self.assertFalse(arnold.AiNodeGetBool(sphere, "use_light_group"))
def Init(procName): proc = arnold.AiNodeLookUpByName(procName) if not proc: print("No such procedural: %s" % procName) return (0, None) attrs = {} it = arnold.AiNodeGetUserParamIterator(proc) while not arnold.AiUserParamIteratorFinished(it): param = arnold.AiUserParamIteratorGetNext(it) pname = arnold.AiUserParamGetName(param) pcat = arnold.AiUserParamGetCategory(param) if pcat == arnold.AI_USERDEF_CONSTANT: ptype = arnold.AiUserParamGetType(param) pval = None if ptype == arnold.AI_TYPE_BOOLEAN: pval = arnold.AiNodeGetBool(proc, pname) elif ptype == arnold.AI_TYPE_INT: pval = arnold.AiNodeGetInt(proc, pname) elif ptype == arnold.AI_TYPE_UINT: pval = arnold.AiNodeGetUInt(proc, pname) elif ptype == arnold.AI_TYPE_FLOAT: pval = arnold.AiNodeGetFlt(proc, pname) elif ptype == arnold.AI_TYPE_POINT: pval = arnold.AiNodeGetPnt(proc, pname) elif ptype == arnold.AI_TYPE_POINT2: pval = arnold.AiNodeGetPnt2(proc, pname) elif ptype == arnold.AI_TYPE_VECTOR: pval = arnold.AiNodeGetVec(proc, pname) elif ptype == arnold.AI_TYPE_RGB: pval = arnold.AiNodeGetRGB(proc, pname) elif ptype == arnold.AI_TYPE_RGBA: pval = arnold.AiNodeGetRGBA(proc, pname) elif ptype == arnold.AI_TYPE_STRING: pval = arnold.AiNodeGetStr(proc, pname) if pval != None: attrs[pname] = (ptype, pval) else: print("Unsupported type (%d) for parameter \"%s\"" % (ptype, pname)) else: print("Ignore non constant parameter \"%s\"" % pname) arnold.AiUserParamIteratorFinished(it) return (1, attrs)
def testRendererContextVariable( self ) : sphere = GafferScene.Sphere() sphere["name"].setValue( "sphere${scene:renderer}" ) render = GafferArnold.ArnoldRender() render["in"].setInput( sphere["out"] ) render["mode"].setValue( render.Mode.SceneDescriptionMode ) render["fileName"].setValue( self.temporaryDirectory() + "/test.ass" ) render["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) self.assertTrue( arnold.AiNodeLookUpByName( "/sphereArnold" ) is not None )
def testDefaultLightsMistakesDontForceLinking(self): light = GafferArnold.ArnoldLight() light.loadShader("point_light") sphere = GafferScene.Sphere() # It doesn't make sense to add a non-light to the "defaultLights" # set like this, but in the event of user error, we don't want to # emit light links unnecessarily. sphereSet = GafferScene.Set() sphereSet["in"].setInput(sphere["out"]) sphereSet["name"].setValue("defaultLights") sphereSet["paths"].setValue(IECore.StringVectorData(["/sphere"])) group = GafferScene.Group() group["in"][0].setInput(light["out"]) group["in"][1].setInput(sphereSet["out"]) render = GafferArnold.ArnoldRender() render["in"].setInput(group["out"]) render["mode"].setValue(render.Mode.SceneDescriptionMode) render["fileName"].setValue(self.temporaryDirectory() + "/test.ass") render["task"].execute() with IECoreArnold.UniverseBlock(writable=True): arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass") sphere = arnold.AiNodeLookUpByName("/group/sphere") self.assertIsNotNone(sphere) self.assertEqual( arnold.AiArrayGetNumElements( arnold.AiNodeGetArray(sphere, "light_group")), 0) self.assertFalse(arnold.AiNodeGetBool(sphere, "use_light_group"))
def testSceneDescription(self): r = GafferScene.Private.IECoreScenePreview.Renderer.create( "IECoreArnold::Renderer", GafferScene.Private.IECoreScenePreview. Renderer.RenderType.SceneDescription, self.temporaryDirectory() + "/test.ass") o = r.object( "testPlane", IECore.MeshPrimitive.createPlane( IECore.Box2f(IECore.V2f(-1), IECore.V2f(1)))) o.transform(IECore.M44f().translate(IECore.V3f(1, 2, 3))) r.render() del r with IECoreArnold.UniverseBlock(): arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass") n = arnold.AiNodeLookUpByName("testPlane") self.assertTrue( arnold.AiNodeEntryGetType(arnold.AiNodeGetNodeEntry(n)), arnold.AI_NODE_SHAPE)
def testLightAndShadowLinking( self ) : sphere1 = GafferScene.Sphere() sphere2 = GafferScene.Sphere() attributes = GafferScene.StandardAttributes() arnoldAttributes = GafferArnold.ArnoldAttributes() light1 = GafferArnold.ArnoldLight() light1.loadShader( "point_light" ) light2 = GafferArnold.ArnoldLight() light2.loadShader( "point_light" ) group = GafferScene.Group() render = GafferArnold.ArnoldRender() attributes["in"].setInput( sphere1["out"] ) arnoldAttributes["in"].setInput( attributes["out"] ) group["in"][0].setInput( arnoldAttributes["out"] ) group["in"][1].setInput( light1["out"] ) group["in"][2].setInput( light2["out"] ) group["in"][3].setInput( sphere2["out"] ) render["in"].setInput( group["out"] ) # Illumination attributes["attributes"]["linkedLights"]["enabled"].setValue( True ) attributes["attributes"]["linkedLights"]["value"].setValue( "/group/light" ) # Shadows arnoldAttributes["attributes"]["shadowGroup"]["enabled"].setValue( True ) arnoldAttributes["attributes"]["shadowGroup"]["value"].setValue( "/group/light1" ) render["mode"].setValue( render.Mode.SceneDescriptionMode ) render["fileName"].setValue( self.temporaryDirectory() + "/test.ass" ) render["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) # the first sphere had linked lights sphere = arnold.AiNodeLookUpByName( "/group/sphere" ) # check illumination self.assertTrue( arnold.AiNodeGetBool( sphere, "use_light_group" ) ) lights = arnold.AiNodeGetArray( sphere, "light_group" ) self.assertEqual( arnold.AiArrayGetNumElements( lights ), 1 ) self.assertEqual( arnold.AiNodeGetName( arnold.AiArrayGetPtr( lights, 0 ) ), "light:/group/light" ) # check shadows self.assertTrue( arnold.AiNodeGetBool( sphere, "use_shadow_group" ) ) shadows = arnold.AiNodeGetArray( sphere, "shadow_group" ) self.assertEqual( arnold.AiArrayGetNumElements( shadows ), 1 ) self.assertEqual( arnold.AiNodeGetName( arnold.AiArrayGetPtr( shadows, 0 ) ), "light:/group/light1" ) # the second sphere does not have any light linking enabled sphere1 = arnold.AiNodeLookUpByName( "/group/sphere1" ) # check illumination self.assertFalse( arnold.AiNodeGetBool( sphere1, "use_light_group" ) ) lights = arnold.AiNodeGetArray( sphere1, "light_group" ) self.assertEqual( arnold.AiArrayGetNumElements( lights ), 0 ) # check shadows self.assertFalse( arnold.AiNodeGetBool( sphere1, "use_shadow_group" ) ) shadows = arnold.AiNodeGetArray( sphere1, "shadow_group" ) self.assertEqual( arnold.AiArrayGetNumElements( shadows ), 0 )
def _worker(data, new_data, redraw_event, mmap_size, mmap_name, state): print("+++ _worker: started") import os import ctypes dir = os.path.dirname(__file__) if dir not in sys.path: sys.path.append(dir) import arnold nodes = {} lights = {} nptrs = [] # nodes linked by AiNodeSetPtr links = [] # nodes linked by AiNodeLink def _AiNodeSetArray(node, param, value): t, a = value _len = len(a) if t == arnold.AI_TYPE_VECTOR: _len //= 3 elif t == arnold.AI_TYPE_UINT: pass _a = arnold.AiArrayConvert(_len, 1, t, ctypes.c_void_p(a.ctypes.data)) arnold.AiNodeSetArray(node, param, _a) _AiNodeSet = { 'NodeSocketShader': lambda n, i, v: True, 'NodeSocketBool': lambda n, i, v: arnold.AiNodeSetBool(n, i, v), 'NodeSocketInt': lambda n, i, v: arnold.AiNodeSetInt(n, i, v), 'NodeSocketFloat': lambda n, i, v: arnold.AiNodeSetFlt(n, i, v), 'NodeSocketColor': lambda n, i, v: arnold.AiNodeSetRGBA(n, i, *v), 'NodeSocketVector': lambda n, i, v: arnold.AiNodeSetVec(n, i, *v), 'NodeSocketVectorXYZ': lambda n, i, v: arnold.AiNodeSetVector(n, i, *v), 'NodeSocketString': lambda n, i, v: arnold.AiNodeSetStr(n, i, v), 'ArnoldNodeSocketColor': lambda n, i, v: arnold.AiNodeSetRGB(n, i, *v), 'ArnoldNodeSocketByte': lambda n, i, v: arnold.AiNodeSetByte(n, i, v), 'ArnoldNodeSocketProperty': lambda n, i, v: True, 'BOOL': lambda n, p, v: arnold.AiNodeSetBool(n, p, v), 'BYTE': lambda n, p, v: arnold.AiNodeSetByte(n, p, v), 'INT': lambda n, p, v: arnold.AiNodeSetInt(n, p, v), 'FLOAT': lambda n, p, v: arnold.AiNodeSetFlt(n, p, v), 'VECTOR2': lambda n, p, v: arnold.AiNodeSetVec2(n, p, *v), 'RGB': lambda n, p, v: arnold.AiNodeSetRGB(n, p, *v), 'RGBA': lambda n, p, v: arnold.AiNodeSetRGBA(n, p, *v), 'VECTOR': lambda n, p, v: arnold.AiNodeSetVec(n, p, *v), 'STRING': lambda n, p, v: arnold.AiNodeSetStr(n, p, v), 'MATRIX': lambda n, p, v: arnold.AiNodeSetMatrix(n, p, arnold.AtMatrix(*v)), 'ARRAY': _AiNodeSetArray, 'LINK': lambda n, p, v: links.append((n, p, v)), 'NODE': lambda n, p, v: nptrs.append((n, p, v)), } arnold.AiBegin() try: # arnold.AiMsgSetConsoleFlags(arnold.AI_LOG_ALL) # arnold.AiMsgSetConsoleFlags(0x000E) # # from pprint import pprint as pp # pp(data) ## Nodes for node in data['nodes']: nt, np = node anode = arnold.AiNode(nt) for n, (t, v) in np.items(): _AiNodeSet[t](anode, n, v) nodes[id(node)] = anode for light in data['lights']: nt, np = light anode = arnold.AiNode(nt) for n, (t, v) in np.items(): _AiNodeSet[t](anode, n, v) lights[id(light)] = anode options = arnold.AiUniverseGetOptions() for n, (t, v) in data['options'].items(): _AiNodeSet[t](options, n, v) for n, p, v in nptrs: arnold.AiNodeSetPtr(n, p, nodes[id(v)]) for n, p, v in links: arnold.AiNodeLink(nodes[id(v)], p, n) ## Outputs filter = arnold.AiNode("gaussian_filter") arnold.AiNodeSetStr(filter, "name", "__filter") driver = arnold.AiNode("driver_display_callback") arnold.AiNodeSetStr(driver, "name", "__driver") #arnold.AiNodeSetBool(driver, "rgba_packing", False) outputs_aovs = (b"RGBA RGBA __filter __driver", ) outputs = arnold.AiArray(len(outputs_aovs), 1, arnold.AI_TYPE_STRING, *outputs_aovs) arnold.AiNodeSetArray(options, "outputs", outputs) sl = data['sl'] del nodes, nptrs, links, data if platform.system() == "Darwin" or "Linux": _rect = lambda w, h: numpy.frombuffer(mmap.mmap(-1, w * h * 4 * 4), dtype=numpy.float32).reshape( [h, w, 4]) rect = _rect(*mmap_size) if platform.system() == "Windows": _rect = lambda n, w, h: numpy.frombuffer( mmap.mmap(-1, w * h * 4 * 4, n), dtype=numpy.float32).reshape( [h, w, 4]) rect = _rect(mmap_name, *mmap_size) def _callback(x, y, width, height, buffer, data): #print("+++ _callback:", x, y, width, height, ctypes.cast(buffer, ctypes.c_void_p)) if buffer: try: if new_data.poll(): arnold.AiRenderInterrupt() else: #print("+++ _callback: tile", x, y, width, height) _buffer = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_uint16)) a = numpy.ctypeslib.as_array(_buffer, shape=(height, width, 4)) rect[y:y + height, x:x + width] = a redraw_event.set() return finally: arnold.AiFree(buffer) elif not new_data.poll(): return arnold.AiRenderAbort() print("+++ _callback: abort") cb = arnold.AtDisplayCallBack(_callback) arnold.AiNodeSetPtr(driver, "callback", cb) class _Dict(dict): def update(self, u): for k, v in u.items(): if isinstance(v, dict): self[k] = _Dict.update(self.get(k, {}), v) else: self[k] = u[k] return self while state.value != ABORT: for _sl in range(*sl): arnold.AiNodeSetInt(options, "AA_samples", _sl) res = arnold.AiRender(arnold.AI_RENDER_MODE_CAMERA) if res == arnold.AI_SUCCESS: break if state.value == ABORT: #print("+++ _worker: abort") break data = _Dict() _data = new_data.recv() print(_data) while _data is not None: # from pprint import pprint as pp # print("+++ _worker: data") # pp(_data) data.update(_data) if not new_data.poll(): _nodes = data.get('nodes') if _nodes is not None: for name, params in _nodes.items(): node = arnold.AiNodeLookUpByName(name) for n, (t, v) in params.items(): _AiNodeSet[t](node, n, v) opts = data.get('options') if opts is not None: for n, (t, v) in opts.items(): _AiNodeSet[t](options, n, v) size = data.get('mmap_size') if size is not None: rect = _rect(mmap_name, *size) break _data = new_data.recv() finally: arnold.AiEnd() print("+++ _worker: finished")
def testTransformMotion(self): s = Gaffer.ScriptNode() s["plane"] = GafferScene.Plane() s["sphere"] = GafferScene.Sphere() s["group"] = GafferScene.Group() s["group"]["in"][0].setInput(s["plane"]["out"]) s["group"]["in"][1].setInput(s["sphere"]["out"]) s["expression"] = Gaffer.Expression() s["expression"].setExpression( inspect.cleandoc(""" parent["plane"]["transform"]["translate"]["x"] = context.getFrame() parent["sphere"]["transform"]["translate"]["y"] = context.getFrame() * 2 parent["group"]["transform"]["translate"]["z"] = context.getFrame() - 1 """)) s["planeFilter"] = GafferScene.PathFilter() s["planeFilter"]["paths"].setValue( IECore.StringVectorData(["/group/plane"])) s["attributes"] = GafferScene.StandardAttributes() s["attributes"]["in"].setInput(s["group"]["out"]) s["attributes"]["filter"].setInput(s["planeFilter"]["out"]) s["attributes"]["attributes"]["transformBlur"]["enabled"].setValue( True) s["attributes"]["attributes"]["transformBlur"]["value"].setValue(False) s["options"] = GafferScene.StandardOptions() s["options"]["in"].setInput(s["attributes"]["out"]) s["options"]["options"]["transformBlur"]["enabled"].setValue(True) s["render"] = GafferArnold.ArnoldRender() s["render"]["in"].setInput(s["options"]["out"]) s["render"]["mode"].setValue(s["render"].Mode.SceneDescriptionMode) s["render"]["fileName"].setValue(self.temporaryDirectory() + "/test.ass") # No motion blur s["options"]["options"]["transformBlur"]["value"].setValue(False) s["render"]["task"].execute() with IECoreArnold.UniverseBlock(writable=True): arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass") sphere = arnold.AiNodeLookUpByName("/group/sphere") sphereTimes = arnold.AiNodeGetArray(sphere, "transform_time_samples") sphereMatrix = arnold.AtMatrix() arnold.AiNodeGetMatrix(sphere, "matrix", sphereMatrix) plane = arnold.AiNodeLookUpByName("/group/plane") planeTimes = arnold.AiNodeGetArray(plane, "transform_time_samples") planeMatrix = arnold.AtMatrix() arnold.AiNodeGetMatrix(plane, "matrix", planeMatrix) expectedSphereMatrix = arnold.AtMatrix() arnold.AiM4Translation(expectedSphereMatrix, arnold.AtVector(0, 2, 0)) expectedPlaneMatrix = arnold.AtMatrix() arnold.AiM4Translation(expectedPlaneMatrix, arnold.AtVector(1, 0, 0)) self.__assertStructsEqual(sphereMatrix, expectedSphereMatrix) self.__assertStructsEqual(planeMatrix, expectedPlaneMatrix) # Motion blur s["options"]["options"]["transformBlur"]["value"].setValue(True) s["render"]["task"].execute() with IECoreArnold.UniverseBlock(writable=True): arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass") sphere = arnold.AiNodeLookUpByName("/group/sphere") sphereTimes = arnold.AiNodeGetArray(sphere, "transform_time_samples") sphereMatrices = arnold.AiNodeGetArray(sphere, "matrix") plane = arnold.AiNodeLookUpByName("/group/plane") planeTimes = arnold.AiNodeGetArray(plane, "transform_time_samples") planeMatrices = arnold.AiNodeGetArray(plane, "matrix") self.assertEqual(sphereTimes.contents.nelements, 2) self.assertEqual(sphereTimes.contents.nkeys, 1) self.assertEqual(sphereMatrices.contents.nelements, 1) self.assertEqual(sphereMatrices.contents.nkeys, 2) self.assertEqual(planeTimes.contents.nelements, 2) self.assertEqual(planeTimes.contents.nkeys, 1) self.assertEqual(planeMatrices.contents.nelements, 1) self.assertEqual(planeMatrices.contents.nkeys, 2) for i in range(0, 2): frame = 0.75 + 0.5 * i self.assertEqual(arnold.AiArrayGetFlt(sphereTimes, i), frame) self.assertEqual(arnold.AiArrayGetFlt(planeTimes, i), frame) sphereMatrix = arnold.AtMatrix() arnold.AiArrayGetMtx(sphereMatrices, i, sphereMatrix) expectedSphereMatrix = arnold.AtMatrix() arnold.AiM4Translation( expectedSphereMatrix, arnold.AtVector(0, frame * 2, frame - 1)) planeMatrix = arnold.AtMatrix() arnold.AiArrayGetMtx(planeMatrices, i, planeMatrix) expectedPlaneMatrix = arnold.AtMatrix() arnold.AiM4Translation(expectedPlaneMatrix, arnold.AtVector(1, 0, frame - 1)) self.__assertStructsEqual(sphereMatrix, expectedSphereMatrix) self.__assertStructsEqual(planeMatrix, expectedPlaneMatrix)
def testUpdate(self): network = IECoreScene.ShaderNetwork(shaders={ "noiseHandle": IECoreScene.Shader("noise"), "flatHandle": IECoreScene.Shader("flat"), }, connections=[ (("noiseHandle", ""), ("flatHandle", "color")), ], output="flatHandle") with IECoreArnold.UniverseBlock(writable=True): # Convert nodes = IECoreArnoldPreview.ShaderNetworkAlgo.convert( network, "test") def assertNoiseAndFlatNodes(): self.assertEqual(len(nodes), 2) self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry(nodes[0])), "noise") self.assertEqual( arnold.AiNodeEntryGetName( arnold.AiNodeGetNodeEntry(nodes[1])), "flat") self.assertEqual(arnold.AiNodeGetName(nodes[0]), "test:noiseHandle") self.assertEqual(arnold.AiNodeGetName(nodes[1]), "test") self.assertEqual( ctypes.addressof( arnold.AiNodeGetLink(nodes[1], "color").contents), ctypes.addressof(nodes[0].contents)) assertNoiseAndFlatNodes() # Convert again with no changes at all. We want to see the same nodes reused. originalNodes = nodes[:] self.assertTrue( IECoreArnoldPreview.ShaderNetworkAlgo.update(nodes, network)) assertNoiseAndFlatNodes() self.assertEqual(ctypes.addressof(nodes[0].contents), ctypes.addressof(originalNodes[0].contents)) self.assertEqual(ctypes.addressof(nodes[1].contents), ctypes.addressof(originalNodes[1].contents)) # Convert again with a tweak to a noise parameter. We want to see the same nodes # reused, with the new parameter value taking hold. noise = network.getShader("noiseHandle") noise.parameters["octaves"] = IECore.IntData(3) network.setShader("noiseHandle", noise) originalNodes = nodes[:] self.assertTrue( IECoreArnoldPreview.ShaderNetworkAlgo.update(nodes, network)) assertNoiseAndFlatNodes() self.assertEqual(ctypes.addressof(nodes[0].contents), ctypes.addressof(originalNodes[0].contents)) self.assertEqual(ctypes.addressof(nodes[1].contents), ctypes.addressof(originalNodes[1].contents)) self.assertEqual(arnold.AiNodeGetInt(nodes[0], "octaves"), 3) # Remove the noise shader, and replace it with an image. Make sure the new network is as we expect, and # the old noise node has been destroyed. network.removeShader("noiseHandle") network.setShader("imageHandle", IECoreScene.Shader("image")) network.addConnection( (("imageHandle", ""), ("flatHandle", "color"))) originalNodes = nodes[:] self.assertTrue( IECoreArnoldPreview.ShaderNetworkAlgo.update(nodes, network)) self.assertEqual(ctypes.addressof(nodes[1].contents), ctypes.addressof(originalNodes[1].contents)) self.assertEqual( arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[0])), "image") self.assertEqual( arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[1])), "flat") self.assertEqual(arnold.AiNodeGetName(nodes[0]), "test:imageHandle") self.assertEqual(arnold.AiNodeGetName(nodes[1]), "test") self.assertEqual( ctypes.addressof( arnold.AiNodeGetLink(nodes[1], "color").contents), ctypes.addressof(nodes[0].contents)) self.assertIsNone(arnold.AiNodeLookUpByName("test:noiseHandle")) # Replace the output shader with something else. network.removeShader("flatHandle") network.setShader("lambertHandle", IECoreScene.Shader("lambert")) network.addConnection( (("imageHandle", ""), ("lambertHandle", "Kd_color"))) network.setOutput(("lambertHandle", "")) originalNodes = nodes[:] self.assertFalse( IECoreArnoldPreview.ShaderNetworkAlgo.update(nodes, network)) self.assertEqual(ctypes.addressof(nodes[0].contents), ctypes.addressof(originalNodes[0].contents)) self.assertEqual( arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[0])), "image") self.assertEqual( arnold.AiNodeEntryGetName(arnold.AiNodeGetNodeEntry(nodes[1])), "lambert") self.assertEqual(arnold.AiNodeGetName(nodes[0]), "test:imageHandle") self.assertEqual(arnold.AiNodeGetName(nodes[1]), "test") self.assertEqual( ctypes.addressof( arnold.AiNodeGetLink(nodes[1], "Kd_color").contents), ctypes.addressof(nodes[0].contents))
def testTransformMotion( self ) : s = Gaffer.ScriptNode() s["plane"] = GafferScene.Plane() s["sphere"] = GafferScene.Sphere() s["group"] = GafferScene.Group() s["group"]["in"][0].setInput( s["plane"]["out"] ) s["group"]["in"][1].setInput( s["sphere"]["out"] ) s["expression"] = Gaffer.Expression() s["expression"].setExpression( inspect.cleandoc( """ parent["plane"]["transform"]["translate"]["x"] = context.getFrame() parent["sphere"]["transform"]["translate"]["y"] = context.getFrame() * 2 parent["group"]["transform"]["translate"]["z"] = context.getFrame() - 1 """ ) ) s["planeFilter"] = GafferScene.PathFilter() s["planeFilter"]["paths"].setValue( IECore.StringVectorData( [ "/group/plane" ] ) ) s["attributes"] = GafferScene.StandardAttributes() s["attributes"]["in"].setInput( s["group"]["out"] ) s["attributes"]["filter"].setInput( s["planeFilter"]["out"] ) s["attributes"]["attributes"]["transformBlur"]["enabled"].setValue( True ) s["attributes"]["attributes"]["transformBlur"]["value"].setValue( False ) s["options"] = GafferScene.StandardOptions() s["options"]["in"].setInput( s["attributes"]["out"] ) s["options"]["options"]["shutter"]["enabled"].setValue( True ) s["options"]["options"]["transformBlur"]["enabled"].setValue( True ) s["render"] = GafferArnold.ArnoldRender() s["render"]["in"].setInput( s["options"]["out"] ) s["render"]["mode"].setValue( s["render"].Mode.SceneDescriptionMode ) s["render"]["fileName"].setValue( self.temporaryDirectory() + "/test.ass" ) # No motion blur s["options"]["options"]["transformBlur"]["value"].setValue( False ) s["render"]["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) camera = arnold.AiNodeLookUpByName( "gaffer:defaultCamera" ) sphere = arnold.AiNodeLookUpByName( "/group/sphere" ) sphereMotionStart = arnold.AiNodeGetFlt( sphere, "motion_start" ) sphereMotionEnd = arnold.AiNodeGetFlt( sphere, "motion_end" ) sphereMatrix = arnold.AiNodeGetMatrix( sphere, "matrix" ) plane = arnold.AiNodeLookUpByName( "/group/plane" ) planeMotionStart = arnold.AiNodeGetFlt( plane, "motion_start" ) planeMotionEnd = arnold.AiNodeGetFlt( plane, "motion_end" ) planeMatrix = arnold.AiNodeGetMatrix( plane, "matrix" ) # Motion parameters should be left at default self.assertEqual( sphereMotionStart, 0 ) self.assertEqual( sphereMotionEnd, 1 ) self.assertEqual( planeMotionStart, 0 ) self.assertEqual( planeMotionEnd, 1 ) expectedSphereMatrix = arnold.AiM4Translation( arnold.AtVector( 0, 2, 0 ) ) expectedPlaneMatrix = arnold.AiM4Translation( arnold.AtVector( 1, 0, 0 ) ) self.assertEqual( self.__m44f( sphereMatrix ), self.__m44f( expectedSphereMatrix ) ) self.assertEqual( self.__m44f( planeMatrix ), self.__m44f( expectedPlaneMatrix ) ) self.assertEqual( arnold.AiNodeGetFlt( camera, "shutter_start" ), 1 ) self.assertEqual( arnold.AiNodeGetFlt( camera, "shutter_end" ), 1 ) # Motion blur s["options"]["options"]["transformBlur"]["value"].setValue( True ) s["render"]["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) camera = arnold.AiNodeLookUpByName( "gaffer:defaultCamera" ) sphere = arnold.AiNodeLookUpByName( "/group/sphere" ) sphereMotionStart = arnold.AiNodeGetFlt( sphere, "motion_start" ) sphereMotionEnd = arnold.AiNodeGetFlt( sphere, "motion_end" ) sphereMatrices = arnold.AiNodeGetArray( sphere, "matrix" ) plane = arnold.AiNodeLookUpByName( "/group/plane" ) planeMotionStart = arnold.AiNodeGetFlt( plane, "motion_start" ) planeMotionEnd = arnold.AiNodeGetFlt( plane, "motion_end" ) planeMatrices = arnold.AiNodeGetArray( plane, "matrix" ) self.assertEqual( sphereMotionStart, 0.75 ) self.assertEqual( sphereMotionEnd, 1.25 ) self.assertEqual( arnold.AiArrayGetNumElements( sphereMatrices.contents ), 1 ) self.assertEqual( arnold.AiArrayGetNumKeys( sphereMatrices.contents ), 2 ) self.assertEqual( planeMotionStart, 0.75 ) self.assertEqual( planeMotionEnd, 1.25 ) self.assertEqual( arnold.AiArrayGetNumElements( planeMatrices.contents ), 1 ) self.assertEqual( arnold.AiArrayGetNumKeys( planeMatrices.contents ), 2 ) for i in range( 0, 2 ) : frame = 0.75 + 0.5 * i sphereMatrix = arnold.AiArrayGetMtx( sphereMatrices, i ) expectedSphereMatrix = arnold.AiM4Translation( arnold.AtVector( 0, frame * 2, frame - 1 ) ) planeMatrix = arnold.AiArrayGetMtx( planeMatrices, i ) expectedPlaneMatrix = arnold.AiM4Translation( arnold.AtVector( 1, 0, frame - 1 ) ) self.assertEqual( self.__m44f( sphereMatrix ), self.__m44f( expectedSphereMatrix ) ) self.assertEqual( self.__m44f( planeMatrix ), self.__m44f( expectedPlaneMatrix ) ) self.assertEqual( arnold.AiNodeGetFlt( camera, "shutter_start" ), 0.75 ) self.assertEqual( arnold.AiNodeGetFlt( camera, "shutter_end" ), 1.25 ) # Motion blur on, but sampleMotion off s["options"]["options"]["sampleMotion"]["enabled"].setValue( True ) s["options"]["options"]["sampleMotion"]["value"].setValue( False ) s["render"]["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) camera = arnold.AiNodeLookUpByName( "gaffer:defaultCamera" ) sphere = arnold.AiNodeLookUpByName( "/group/sphere" ) sphereMotionStart = arnold.AiNodeGetFlt( sphere, "motion_start" ) sphereMotionEnd = arnold.AiNodeGetFlt( sphere, "motion_end" ) sphereMatrices = arnold.AiNodeGetArray( sphere, "matrix" ) plane = arnold.AiNodeLookUpByName( "/group/plane" ) planeMotionStart = arnold.AiNodeGetFlt( plane, "motion_start" ) planeMotionEnd = arnold.AiNodeGetFlt( plane, "motion_end" ) planeMatrices = arnold.AiNodeGetArray( plane, "matrix" ) self.assertEqual( sphereMotionStart, 0.75 ) self.assertEqual( sphereMotionEnd, 1.25 ) self.assertEqual( arnold.AiArrayGetNumElements( sphereMatrices.contents ), 1 ) self.assertEqual( arnold.AiArrayGetNumKeys( sphereMatrices.contents ), 2 ) self.assertEqual( planeMotionStart, 0.75 ) self.assertEqual( planeMotionEnd, 1.25 ) self.assertEqual( arnold.AiArrayGetNumElements( planeMatrices.contents ), 1 ) self.assertEqual( arnold.AiArrayGetNumKeys( planeMatrices.contents ), 2 ) for i in range( 0, 2 ) : frame = 0.75 + 0.5 * i sphereMatrix = arnold.AiArrayGetMtx( sphereMatrices, i ) expectedSphereMatrix = arnold.AiM4Translation( arnold.AtVector( 0, frame * 2, frame - 1 ) ) planeMatrix = arnold.AiArrayGetMtx( planeMatrices, i ) expectedPlaneMatrix = arnold.AiM4Translation( arnold.AtVector( 1, 0, frame - 1 ) ) self.assertEqual( self.__m44f( sphereMatrix ), self.__m44f( expectedSphereMatrix ) ) self.assertEqual( self.__m44f( planeMatrix ), self.__m44f( expectedPlaneMatrix ) ) self.assertEqual( arnold.AiNodeGetFlt( camera, "shutter_start" ), 0.75 ) self.assertEqual( arnold.AiNodeGetFlt( camera, "shutter_end" ), 0.75 )
def testShaderSubstitutions( self ) : s = Gaffer.ScriptNode() s["plane"] = GafferScene.Plane() s["planeAttrs"] = GafferScene.CustomAttributes() s["planeAttrs"]["in"].setInput( s["plane"]["out"] ) s["planeAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "A", Gaffer.StringPlug( "value", defaultValue = 'bar' ) ) ) s["planeAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "B", Gaffer.StringPlug( "value", defaultValue = 'foo' ) ) ) s["cube"] = GafferScene.Cube() s["cubeAttrs"] = GafferScene.CustomAttributes() s["cubeAttrs"]["in"].setInput( s["cube"]["out"] ) s["cubeAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "B", Gaffer.StringPlug( "value", defaultValue = 'override' ) ) ) s["parent"] = GafferScene.Parent() s["parent"]["in"].setInput( s["planeAttrs"]["out"] ) s["parent"]["children"][0].setInput( s["cubeAttrs"]["out"] ) s["parent"]["parent"].setValue( "/plane" ) s["shader"] = GafferArnold.ArnoldShader() s["shader"].loadShader( "image" ) s["shader"]["parameters"]["filename"].setValue( "<attr:A>/path/<attr:B>.tx" ) s["filter"] = GafferScene.PathFilter() s["filter"]["paths"].setValue( IECore.StringVectorData( [ "/plane" ] ) ) s["shaderAssignment"] = GafferScene.ShaderAssignment() s["shaderAssignment"]["in"].setInput( s["parent"]["out"] ) s["shaderAssignment"]["filter"].setInput( s["filter"]["out"] ) s["shaderAssignment"]["shader"].setInput( s["shader"]["out"] ) s["light"] = GafferArnold.ArnoldLight() s["light"].loadShader( "photometric_light" ) s["light"]["parameters"]["filename"].setValue( "/path/<attr:A>.ies" ) s["goboTexture"] = GafferArnold.ArnoldShader() s["goboTexture"].loadShader( "image" ) s["goboTexture"]["parameters"]["filename"].setValue( "<attr:B>/gobo.tx" ) s["gobo"] = GafferArnold.ArnoldShader() s["gobo"].loadShader( "gobo" ) s["gobo"]["parameters"]["slidemap"].setInput( s["goboTexture"]["out"] ) s["goboAssign"] = GafferScene.ShaderAssignment() s["goboAssign"]["in"].setInput( s["light"]["out"] ) s["goboAssign"]["shader"].setInput( s["gobo"]["out"] ) s["lightBlocker"] = GafferArnold.ArnoldLightFilter() s["lightBlocker"].loadShader( "light_blocker" ) s["lightBlocker"]["parameters"]["geometry_type"].setValue( "<attr:geometryType>" ) s["lightGroup"] = GafferScene.Group() s["lightGroup"]["name"].setValue( "lightGroup" ) s["lightGroup"]["in"][0].setInput( s["goboAssign"]["out"] ) s["lightGroup"]["in"][1].setInput( s["lightBlocker"]["out"] ) s["parent2"] = GafferScene.Parent() s["parent2"]["in"].setInput( s["shaderAssignment"]["out"] ) s["parent2"]["children"][0].setInput( s["lightGroup"]["out"] ) s["parent2"]["parent"].setValue( "/" ) s["globalAttrs"] = GafferScene.CustomAttributes() s["globalAttrs"]["in"].setInput( s["parent2"]["out"] ) s["globalAttrs"]["global"].setValue( True ) s["globalAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "A", Gaffer.StringPlug( "value", defaultValue = 'default1' ) ) ) s["globalAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "B", Gaffer.StringPlug( "value", defaultValue = 'default2' ) ) ) s["globalAttrs"]["attributes"].addChild( Gaffer.NameValuePlug( "geometryType", Gaffer.StringPlug( "value", defaultValue = 'cylinder' ) ) ) s["render"] = GafferArnold.ArnoldRender() s["render"]["in"].setInput( s["globalAttrs"]["out"] ) s["render"]["mode"].setValue( s["render"].Mode.SceneDescriptionMode ) s["render"]["fileName"].setValue( self.temporaryDirectory() + "/test.ass" ) s["render"]["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) plane = arnold.AiNodeLookUpByName( "/plane" ) shader = arnold.AiNodeGetPtr( plane, "shader" ) self.assertEqual( arnold.AiNodeGetStr( shader, "filename" ), "bar/path/foo.tx" ) cube = arnold.AiNodeLookUpByName( "/plane/cube" ) shader2 = arnold.AiNodeGetPtr( cube, "shader" ) self.assertEqual( arnold.AiNodeGetStr( shader2, "filename" ), "bar/path/override.tx" ) light = arnold.AiNodeLookUpByName( "light:/lightGroup/light" ) self.assertEqual( arnold.AiNodeGetStr( light, "filename" ), "/path/default1.ies" ) gobo = arnold.AiNodeGetPtr( light, "filters" ) goboTex = arnold.AiNodeGetLink( gobo, "slidemap" ) self.assertEqual( arnold.AiNodeGetStr( goboTex, "filename" ), "default2/gobo.tx" ) lightFilter = arnold.AiNodeLookUpByName( "lightFilter:/lightGroup/lightFilter" ) self.assertEqual( arnold.AiNodeGetStr( lightFilter, "geometry_type" ), "cylinder" )
def testLightAndShadowLinking( self ) : sphere1 = GafferScene.Sphere() sphere2 = GafferScene.Sphere() attributes = GafferScene.StandardAttributes() arnoldAttributes = GafferArnold.ArnoldAttributes() light1 = GafferArnold.ArnoldLight() light1.loadShader( "point_light" ) light2 = GafferArnold.ArnoldLight() light2.loadShader( "point_light" ) group = GafferScene.Group() group["in"].addChild( GafferScene.ScenePlug( "in1" ) ) group["in"].addChild( GafferScene.ScenePlug( "in2" ) ) group["in"].addChild( GafferScene.ScenePlug( "in3" ) ) group["in"].addChild( GafferScene.ScenePlug( "in4" ) ) evaluate = GafferScene.EvaluateLightLinks() render = GafferArnold.ArnoldRender() attributes["in"].setInput( sphere1["out"] ) arnoldAttributes["in"].setInput( attributes["out"] ) group["in"]["in1"].setInput( arnoldAttributes["out"] ) group["in"]["in2"].setInput( light1["out"] ) group["in"]["in3"].setInput( light2["out"] ) group["in"]["in4"].setInput( sphere2["out"] ) evaluate["in"].setInput( group["out"] ) render["in"].setInput( evaluate["out"] ) # Illumination attributes["attributes"]["linkedLights"]["enabled"].setValue( True ) attributes["attributes"]["linkedLights"]["value"].setValue( "/group/light /group/light1" ) # Shadows arnoldAttributes["attributes"]["shadowGroup"]["enabled"].setValue( True ) arnoldAttributes["attributes"]["shadowGroup"]["value"].setValue( "/group/light /group/light1" ) # make sure we pass correct data into the renderer self.assertEqual( set( render["in"].attributes( "/group/sphere" )["linkedLights"] ), set( IECore.StringVectorData( ["/group/light", "/group/light1"] ) ) ) self.assertEqual( set( render["in"].attributes( "/group/sphere" )["ai:visibility:shadow_group"] ), set( IECore.StringVectorData( ["/group/light", "/group/light1"] ) ) ) render["mode"].setValue( render.Mode.SceneDescriptionMode ) render["fileName"].setValue( self.temporaryDirectory() + "/test.ass" ) render["task"].execute() with IECoreArnold.UniverseBlock( writable = True ) : arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" ) # the first sphere had linked lights sphere = arnold.AiNodeLookUpByName( "/group/sphere" ) # check illumination lights = arnold.AiNodeGetArray( sphere, "light_group" ) lightNames = [] for i in range( arnold.AiArrayGetNumElements( lights.contents ) ): light = arnold.cast(arnold.AiArrayGetPtr(lights, i), arnold.POINTER(arnold.AtNode)) lightNames.append( arnold.AiNodeGetName(light.contents) ) doLinking = arnold.AiNodeGetBool( sphere, "use_light_group" ) self.assertEqual( set( lightNames ), { "light:/group/light", "light:/group/light1" } ) self.assertEqual( doLinking, True ) # check shadows shadows = arnold.AiNodeGetArray( sphere, "shadow_group" ) lightNames = [] for i in range( arnold.AiArrayGetNumElements( shadows.contents ) ): light = arnold.cast(arnold.AiArrayGetPtr(shadows, i), arnold.POINTER(arnold.AtNode)) lightNames.append( arnold.AiNodeGetName(light.contents) ) doLinking = arnold.AiNodeGetBool( sphere, "use_shadow_group" ) self.assertEqual( set( lightNames ), { "light:/group/light", "light:/group/light1" } ) self.assertEqual( doLinking, True ) # the second sphere does not have any light linking enabled sphere1 = arnold.AiNodeLookUpByName( "/group/sphere1" ) # check illumination lights = arnold.AiNodeGetArray( sphere1, "light_group" ) lightNames = [] for i in range( arnold.AiArrayGetNumElements( lights.contents ) ): light = arnold.cast(arnold.AiArrayGetPtr(lights, i), arnold.POINTER(arnold.AtNode)) lightNames.append( arnold.AiNodeGetName(light.contents) ) doLinking = arnold.AiNodeGetBool( sphere1, "use_light_group" ) self.assertEqual( lightNames, [] ) self.assertEqual( doLinking, False ) # check shadows shadows = arnold.AiNodeGetArray( sphere1, "shadow_group" ) lightNames = [] for i in range( arnold.AiArrayGetNumElements( shadows.contents ) ): light = arnold.cast(arnold.AiArrayGetPtr(shadows, i), arnold.POINTER(arnold.AtNode)) lightNames.append( arnold.AiNodeGetName(light.contents) ) doLinking = arnold.AiNodeGetBool( sphere1, "use_shadow_group" ) self.assertEqual( lightNames, [] ) self.assertEqual( doLinking, False )