Beispiel #1
0
    def testCropWindow(self):

        r = GafferScene.Private.IECoreScenePreview.Renderer.create(
            "IECoreArnold::Renderer", GafferScene.Private.IECoreScenePreview.
            Renderer.RenderType.SceneDescription,
            self.temporaryDirectory() + "/test.ass")

        r.camera(
            "testCamera",
            IECore.Camera(
                parameters={
                    "resolution": IECore.V2i(2000, 1000),
                    "cropWindow": IECore.Box2f(IECore.V2f(0),
                                               IECore.V2f(1, 0.75)),
                }))

        r.option("camera", IECore.StringData("testCamera"))

        r.render()
        del r

        with IECoreArnold.UniverseBlock():

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")
            options = arnold.AiUniverseGetOptions()

            self.assertEqual(arnold.AiNodeGetInt(options, "xres"), 2000)
            self.assertEqual(arnold.AiNodeGetInt(options, "yres"), 1000)

            self.assertEqual(arnold.AiNodeGetInt(options, "region_min_x"), 0)
            self.assertEqual(arnold.AiNodeGetInt(options, "region_min_y"), 0)
            self.assertEqual(arnold.AiNodeGetInt(options, "region_max_x"),
                             1999)
            self.assertEqual(arnold.AiNodeGetInt(options, "region_max_y"), 749)
Beispiel #2
0
    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")
Beispiel #3
0
	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.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 )
Beispiel #4
0
    def testSharedLightAttributes(self):

        r = GafferScene.Private.IECoreScenePreview.Renderer.create(
            "IECoreArnold::Renderer", GafferScene.Private.IECoreScenePreview.
            Renderer.RenderType.SceneDescription,
            self.temporaryDirectory() + "/test.ass")

        lightShader = IECore.ObjectVector([
            IECore.Shader("point_light", "ai:light"),
        ])
        lightAttributes = r.attributes(
            IECore.CompoundObject({"ai:light": lightShader}))

        o = r.light("testLight1", None)
        o.attributes(lightAttributes)

        o = r.light("testLight2", None)
        o.attributes(lightAttributes)

        del o, lightAttributes
        r.render()
        del r

        with IECoreArnold.UniverseBlock():

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")

            lights = self.__allNodes(type=arnold.AI_NODE_LIGHT)
            self.assertEqual(len(lights), 2)
            self.assertEqual(set([arnold.AiNodeGetName(l) for l in lights]),
                             {"testLight1", "testLight2"})
Beispiel #5
0
	def testFrameAndAASeed( self ) :

		options = GafferArnold.ArnoldOptions()

		render = GafferArnold.ArnoldRender()
		render["in"].setInput( options["out"] )
		render["mode"].setValue( render.Mode.SceneDescriptionMode )
		render["fileName"].setValue( self.temporaryDirectory() + "/test.ass" )

		for frame in ( 1, 2, 2.8, 3.2 ) :
			for seed in ( None, 3, 4 ) :
				with Gaffer.Context() as c :

					c.setFrame( frame )

					options["options"]["aaSeed"]["enabled"].setValue( seed is not None )
					options["options"]["aaSeed"]["value"].setValue( seed or 1 )

					render["task"].execute()

					with IECoreArnold.UniverseBlock( writable = True ) :

						arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )

						self.assertEqual(
							arnold.AiNodeGetInt( arnold.AiUniverseGetOptions(), "AA_seed" ),
							seed or round( frame )
						)
Beispiel #6
0
    def testShaderGarbageCollection(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))))
        # Replace the shader a few times.
        for shader in ("utility", "flat", "standard"):
            a = IECore.CompoundObject({
                "ai:surface":
                IECore.ObjectVector([IECore.Shader(shader)]),
            })
            o.attributes(r.attributes(a))

        del o, a
        r.render()
        del r

        with IECoreArnold.UniverseBlock():

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")
            # We only want one shader to have been saved, because only one was genuinely used.
            self.assertEqual(len(self.__allNodes(type=arnold.AI_NODE_SHADER)),
                             1)
Beispiel #7
0
    def testShaderReuse(self):

        r = GafferScene.Private.IECoreScenePreview.Renderer.create(
            "IECoreArnold::Renderer", GafferScene.Private.IECoreScenePreview.
            Renderer.RenderType.SceneDescription,
            self.temporaryDirectory() + "/test.ass")

        for i in range(0, 10):

            a = IECore.CompoundObject({
                "ai:surface":
                IECore.ObjectVector([IECore.Shader("flat")]),
            })

            o = r.object(
                "testPlane",
                IECore.MeshPrimitive.createPlane(
                    IECore.Box2f(IECore.V2f(-1), IECore.V2f(1))))
            # We keep specifying the same shader, but we'd like the renderer
            # to be frugal and reuse a single arnold shader on the other side.
            o.attributes(r.attributes(a))
            del o

        r.render()
        del r

        with IECoreArnold.UniverseBlock():

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")
            self.assertEqual(len(self.__allNodes(type=arnold.AI_NODE_SHADER)),
                             1)
Beispiel #8
0
    def testResolution(self):

        s = Gaffer.ScriptNode()

        s["camera"] = GafferScene.Camera()

        s["options"] = GafferScene.StandardOptions()
        s["options"]["in"].setInput(s["camera"]["out"])
        s["options"]["options"]["renderResolution"]["enabled"].setValue(True)
        s["options"]["options"]["renderResolution"]["value"].setValue(
            imath.V2i(200, 100))
        s["options"]["options"]["resolutionMultiplier"]["enabled"].setValue(
            True)
        s["options"]["options"]["resolutionMultiplier"]["value"].setValue(2)

        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")

        # Default camera should have the right resolution.

        s["render"]["task"].execute()

        with IECoreArnold.UniverseBlock(writable=True):

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")
            options = arnold.AiUniverseGetOptions()
            self.assertEqual(arnold.AiNodeGetInt(options, "xres"), 400)
            self.assertEqual(arnold.AiNodeGetInt(options, "yres"), 200)

        # As should a camera picked from the scene.

        s["options"]["options"]["renderCamera"]["enabled"].setValue(True)
        s["options"]["options"]["renderCamera"]["value"].setValue("/camera")
        s["render"]["task"].execute()

        with IECoreArnold.UniverseBlock(writable=True):

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")
            options = arnold.AiUniverseGetOptions()
            self.assertEqual(arnold.AiNodeGetInt(options, "xres"), 400)
            self.assertEqual(arnold.AiNodeGetInt(options, "yres"), 200)
Beispiel #9
0
    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 render_ass(ass, remove_ass=False):
    imagefilename = None
    ai.AiBegin()
    ai.AiLoadPlugins(os.environ['ARNOLD_PLUGIN_PATH'])
    ai.AiASSLoad (ass, ai.AI_NODE_ALL)
    ai.AiRender()
    ai.AiEnd()
    # read out file
    ai.AiBegin()
    ai.AiMsgSetConsoleFlags(ai.AI_LOG_ALL)
    ai.AiASSLoad(ass, ai.AI_NODE_ALL)
    iter = ai.AiUniverseGetNodeIterator(ai.AI_NODE_ALL)
    while not ai.AiNodeIteratorFinished(iter):
        node = ai.AiNodeIteratorGetNext(iter)
        if ai.AiNodeIs( node, "driver_jpeg" ):
            imagefilename = ai.AiNodeGetStr( node, "filename" )
    ai.AiNodeIteratorDestroy(iter)
    ai.AiEnd()
    if remove_ass:
        os.remove(ass)
    return imagefilename
Beispiel #11
0
    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"})
Beispiel #12
0
    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"))
Beispiel #13
0
	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 )
Beispiel #14
0
    def testShaderNames(self):

        r = GafferScene.Private.IECoreScenePreview.Renderer.create(
            "IECoreArnold::Renderer", GafferScene.Private.IECoreScenePreview.
            Renderer.RenderType.SceneDescription,
            self.temporaryDirectory() + "/test.ass")

        shader1 = IECore.ObjectVector([
            IECore.Shader("noise", parameters={"__handle": "myHandle"}),
            IECore.Shader("flat", parameters={"color": "link:myHandle"}),
        ])

        o1 = r.object(
            "testPlane",
            IECore.MeshPrimitive.createPlane(
                IECore.Box2f(IECore.V2f(-1), IECore.V2f(1))))
        o1.attributes(
            r.attributes(IECore.CompoundObject({"ai:surface": shader1})))

        shader2 = IECore.ObjectVector([
            IECore.Shader("noise", parameters={"__handle": "myHandle"}),
            IECore.Shader("standard", parameters={"Kd_color":
                                                  "link:myHandle"}),
        ])

        o2 = r.object(
            "testPlane",
            IECore.MeshPrimitive.createPlane(
                IECore.Box2f(IECore.V2f(-1), IECore.V2f(1))))
        o2.attributes(
            r.attributes(IECore.CompoundObject({"ai:surface": shader2})))

        del o1, o2
        r.render()
        del r

        with IECoreArnold.UniverseBlock():

            arnold.AiASSLoad(self.temporaryDirectory() + "/test.ass")

            shaders = self.__allNodes(type=arnold.AI_NODE_SHADER)
            self.assertEqual(len(shaders), 4)
            self.assertEqual(
                len(set([arnold.AiNodeGetName(s) for s in shaders])), 4)
Beispiel #15
0
    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"))
Beispiel #16
0
    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)
Beispiel #17
0
	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 )
Beispiel #18
0
	def testRenderRegion( self ) :

		s = Gaffer.ScriptNode()

		s["camera"] = GafferScene.Camera()

		s["options"] = GafferScene.StandardOptions()
		s["options"]["in"].setInput( s["camera"]["out"] )
		s["options"]["options"]["renderCamera"]["enabled"].setValue( True )
		s["options"]["options"]["renderCamera"]["value"].setValue( "/camera" )

		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" )

		# Default region
		s["render"]["task"].execute()

		with IECoreArnold.UniverseBlock( writable = True ) :

			arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )
			options = arnold.AiUniverseGetOptions()
			self.assertEqual( arnold.AiNodeGetInt( options, "xres" ), 640 )
			self.assertEqual( arnold.AiNodeGetInt( options, "yres" ), 480 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_x" ), 0 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_x" ), 639 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_y" ), 0 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_y" ), 479 )

		# Apply Crop Window
		s["options"]["options"]["renderCropWindow"]["enabled"].setValue( True )
		s["options"]["options"]["renderCropWindow"]["value"].setValue( imath.Box2f( imath.V2f( 0.25, 0.5 ), imath.V2f( 0.75, 1.0 ) ) )

		s["render"]["task"].execute()

		with IECoreArnold.UniverseBlock( writable = True ) :

			arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )
			options = arnold.AiUniverseGetOptions()
			self.assertEqual( arnold.AiNodeGetInt( options, "xres" ), 640 )
			self.assertEqual( arnold.AiNodeGetInt( options, "yres" ), 480 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_x" ), 160 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_x" ), 479 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_y" ), 240 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_y" ), 479 )

		# Test Empty Crop Window
		s["options"]["options"]["renderCropWindow"]["value"].setValue( imath.Box2f() )

		s["render"]["task"].execute()

		with IECoreArnold.UniverseBlock( writable = True ) :

			arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )
			options = arnold.AiUniverseGetOptions()
			self.assertEqual( arnold.AiNodeGetInt( options, "xres" ), 640 )
			self.assertEqual( arnold.AiNodeGetInt( options, "yres" ), 480 )

			# Since Arnold doesn't support empty regions, we default to one pixel in the corner
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_x" ), 0 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_x" ), 0 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_y" ), 479 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_y" ), 479 )

		# Apply Overscan
		s["options"]["options"]["renderCropWindow"]["enabled"].setValue( False )
		s["options"]["options"]["overscan"]["enabled"].setValue( True )
		s["options"]["options"]["overscan"]["value"].setValue( True )
		s["options"]["options"]["overscanTop"]["enabled"].setValue( True )
		s["options"]["options"]["overscanTop"]["value"].setValue( 0.1 )
		s["options"]["options"]["overscanBottom"]["enabled"].setValue( True )
		s["options"]["options"]["overscanBottom"]["value"].setValue( 0.2 )
		s["options"]["options"]["overscanLeft"]["enabled"].setValue( True )
		s["options"]["options"]["overscanLeft"]["value"].setValue( 0.3 )
		s["options"]["options"]["overscanRight"]["enabled"].setValue( True )
		s["options"]["options"]["overscanRight"]["value"].setValue( 0.4 )

		s["render"]["task"].execute()

		with IECoreArnold.UniverseBlock( writable = True ) :

			arnold.AiASSLoad( self.temporaryDirectory() + "/test.ass" )
			options = arnold.AiUniverseGetOptions()
			self.assertEqual( arnold.AiNodeGetInt( options, "xres" ), 640 )
			self.assertEqual( arnold.AiNodeGetInt( options, "yres" ), 480 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_x" ), -192 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_x" ), 640 + 255 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_min_y" ), -48 )
			self.assertEqual( arnold.AiNodeGetInt( options, "region_max_y" ), 480 + 95 )
Beispiel #19
0
	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 )
Beispiel #20
0
	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" )
Beispiel #21
0
	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 )
    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)