protected static CSGInnerNode head() { CSGInnerNode root = new CSGInnerNode( SetOperation.Union ); double[] skinColor = new double[] { 1, .8, .65 }; double[] whiteColor = new double[] { 1, 1, 1 }; double[] blackColor = new double[] { 0, 0, 0 }; double[] blueColor = new double[] { 0, 0, 1 }; double[] redColor = new double[] { 1, 0, 0 }; CSGInnerNode hlava = new CSGInnerNode( SetOperation.Difference ); root.InsertChild( hlava, Matrix4d.Identity ); Sphere s = new Sphere(); s.SetAttribute( PropertyName.COLOR, skinColor ); hlava.InsertChild( s, Matrix4d.Scale( 2.3 ) ); // klobouk CSGInnerNode klobouk = new CSGInnerNode( SetOperation.Union ); Cylinder klb = new Cylinder( -0.5, 0.5 ); klb.SetAttribute( PropertyName.COLOR, blackColor ); klobouk.InsertChild( klb, Matrix4d.Scale( 2, 2, 1.4 ) * Matrix4d.RotateX( Math.PI / 2 ) * Matrix4d.CreateTranslation( 0, 0.5, 0 ) ); Cylinder ksilt = new Cylinder( -0.5, 0.5 ); ksilt.SetAttribute( PropertyName.COLOR, blackColor ); klobouk.InsertChild( ksilt, Matrix4d.Scale( 3, 3, .1 ) * Matrix4d.RotateX( Math.PI / 2 ) ); root.InsertChild( klobouk, Matrix4d.CreateTranslation( 0, 1.25, 0 ) ); // levy ocni dulek s = new Sphere(); s.SetAttribute( PropertyName.COLOR, skinColor ); hlava.InsertChild( s, Matrix4d.Scale( 0.7 ) * Matrix4d.CreateTranslation( -0.7, .3, -1.8 ) ); // pravy ocni dulek s = new Sphere(); s.SetAttribute( PropertyName.COLOR, skinColor ); hlava.InsertChild( s, Matrix4d.Scale( 0.7 ) * Matrix4d.CreateTranslation( 0.7, .3, -1.8 ) ); // prave oko CSGInnerNode oko = new CSGInnerNode( SetOperation.Union ); root.InsertChild( oko, Matrix4d.CreateTranslation( 0.70, 0.3, -0.5 ) ); Sphere bulva = new Sphere(); bulva.SetAttribute( PropertyName.COLOR, whiteColor ); oko.InsertChild( bulva, Matrix4d.Scale( 1.3 ) ); Sphere cocka = new Sphere(); cocka.SetAttribute( PropertyName.COLOR, blueColor ); oko.InsertChild( cocka, Matrix4d.Scale( 0.3 ) * Matrix4d.CreateTranslation( 0, 0, -1.2 ) ); // leve oko oko = new CSGInnerNode( SetOperation.Union ); root.InsertChild( oko, Matrix4d.CreateTranslation( -0.70, 0.3, -0.5 ) ); bulva = new Sphere(); bulva.SetAttribute( PropertyName.COLOR, whiteColor ); oko.InsertChild( bulva, Matrix4d.Scale( 1.3 ) ); cocka = new Sphere(); cocka.SetAttribute( PropertyName.COLOR, blueColor ); oko.InsertChild( cocka, Matrix4d.Scale( 0.3 ) * Matrix4d.CreateTranslation( 0, 0, -1.2 ) ); // nos Cylinder nos = new Cylinder( -0.5, 0.5 ); nos.SetAttribute( PropertyName.COLOR, skinColor ); root.InsertChild( nos, Matrix4d.Scale( 0.2, 0.2, 0.6 ) * Matrix4d.CreateTranslation( 0, 0, -2.65 ) ); // usta CSGInnerNode usta = new CSGInnerNode( SetOperation.Xor ); Cylinder horniRet = new Cylinder( -0.5, 0.5 ); horniRet.SetAttribute( PropertyName.COLOR, redColor ); usta.InsertChild( horniRet, Matrix4d.CreateTranslation( 0, -0.3, 0 ) ); Cylinder dolniRet = new Cylinder( -0.5, 0.5 ); dolniRet.SetAttribute( PropertyName.COLOR, redColor ); usta.InsertChild( dolniRet, Matrix4d.CreateTranslation( 0, 0.3, 0 ) ); root.InsertChild( usta, Matrix4d.Scale( 0.7, 0.3, 1 ) * Matrix4d.CreateTranslation( 0, -0.7, -1.85 ) ); // vnitrek ust CSGInnerNode vnitrekUst = new CSGInnerNode( SetOperation.Intersection ); horniRet = new Cylinder( -0.5, 0.5 ); horniRet.SetAttribute( PropertyName.COLOR, blackColor ); vnitrekUst.InsertChild( horniRet, Matrix4d.CreateTranslation( 0, -0.3, 0 ) ); dolniRet = new Cylinder( -0.5, 0.5 ); dolniRet.SetAttribute( PropertyName.COLOR, blackColor ); vnitrekUst.InsertChild( dolniRet, Matrix4d.CreateTranslation( 0, 0.3, 0 ) ); usta.InsertChild( vnitrekUst, Matrix4d.CreateTranslation( 0, 0, 0.1 ) ); return root; }
/// <summary> /// Infinite plane with two spheres on it (one of them is transparent) /// </summary> public static void TwoSpheres( IRayScene sc ) { Debug.Assert( sc != null ); // CSG scene: CSGInnerNode root = new CSGInnerNode( SetOperation.Union ); root.SetAttribute( PropertyName.REFLECTANCE_MODEL, new PhongModel() ); root.SetAttribute( PropertyName.MATERIAL, new PhongMaterial( new double[] { 1.0, 0.8, 0.1 }, 0.1, 0.6, 0.4, 128 ) ); sc.Intersectable = root; // Background color: sc.BackgroundColor = new double[] { 0.0, 0.05, 0.07 }; // Camera: sc.Camera = new StaticCamera( new Vector3d( 0.7, 0.5, -5.0 ), new Vector3d( 0.0, -0.18, 1.0 ), 50.0 ); // Light sources: sc.Sources = new LinkedList<ILightSource>(); sc.Sources.Add( new AmbientLightSource( 0.8 ) ); sc.Sources.Add( new PointLightSource( new Vector3d( -5.0, 4.0, -3.0 ), 1.2 ) ); // --- NODE DEFINITIONS ---------------------------------------------------- // Transparent sphere: Sphere s; s = new Sphere(); PhongMaterial pm = new PhongMaterial( new double[] { 0.0, 0.2, 0.1 }, 0.05, 0.05, 0.1, 128 ); pm.n = 1.6; pm.Kt = 0.9; s.SetAttribute( PropertyName.MATERIAL, pm ); root.InsertChild( s, Matrix4d.Identity ); // Opaque sphere: s = new Sphere(); root.InsertChild( s, Matrix4d.Scale( 1.2 ) * Matrix4d.CreateTranslation( 1.5, 0.2, 2.4 ) ); // Infinite plane with checker: Plane pl = new Plane(); pl.SetAttribute( PropertyName.COLOR, new double[] { 0.3, 0.0, 0.0 } ); pl.SetAttribute( PropertyName.TEXTURE, new CheckerTexture( 0.6, 0.6, new double[] { 1.0, 1.0, 1.0 } ) ); root.InsertChild( pl, Matrix4d.RotateX( -MathHelper.PiOver2 ) * Matrix4d.CreateTranslation( 0.0, -1.0, 0.0 ) ); }
/// <summary> /// Test scene for Toruses by Jan Navratil, (c) 2012 /// </summary> public static void Toroids( IRayScene sc ) { Debug.Assert( sc != null ); // CSG scene: CSGInnerNode root = new CSGInnerNode( SetOperation.Union ); root.SetAttribute( PropertyName.REFLECTANCE_MODEL, new PhongModel() ); root.SetAttribute( PropertyName.MATERIAL, new PhongMaterial( new double[] { 0.5, 0.5, 0.5 }, 0.2, 0.7, 0.2, 16 ) ); sc.Intersectable = root; // Background color: sc.BackgroundColor = new double[] { 0.0, 0.15, 0.2 }; // Camera: sc.Camera = new StaticCamera( new Vector3d( 0.0, 0.0, -10.0 ), new Vector3d( 0.0, -0.04, 1.0 ), 60.0 ); // Light sources: sc.Sources = new LinkedList<ILightSource>(); sc.Sources.Add( new AmbientLightSource( 1.8 ) ); sc.Sources.Add( new PointLightSource( new Vector3d( -5.0, 3.0, -3.0 ), 2.0 ) ); // --- NODE DEFINITIONS ---------------------------------------------------- Sphere s; Torus t; t = new Torus( 2.0, 1.0 ); t.SetAttribute( PropertyName.COLOR, new double[] { 0, 0, 0.7 } ); t.SetAttribute( PropertyName.TEXTURE, new CheckerTexture( 50, 20, new double[] { 0.9, 0.9, 0 } ) ); root.InsertChild( t, Matrix4d.Scale( 0.8 ) * Matrix4d.CreateRotationX( 0.9 ) * Matrix4d.CreateTranslation( 2.7, 0.6, 0.0 ) ); t = new Torus( 1.0, 1.5 ); t.SetAttribute( PropertyName.COLOR, new double[] { 1, 0, 0 } ); t.SetAttribute( PropertyName.TEXTURE, new CheckerTexture( 40, 40, new double[] { 0.8, 1.0, 1.0 } ) ); CSGInnerNode donut = new CSGInnerNode( SetOperation.Difference ); donut.InsertChild( t, Matrix4d.Identity ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 0.5, 0.5, 0.5 } ); s.SetAttribute( PropertyName.TEXTURE, new CheckerTexture( 100, 100, new double[] { 1, 0.5, 0 } ) ); donut.InsertChild( s, Matrix4d.Scale( 3 ) * Matrix4d.CreateTranslation( 0, -3, 0 ) ); root.InsertChild( donut, Matrix4d.CreateRotationX( 0.8 ) * Matrix4d.CreateTranslation( -2.5, 0.0, 0.0 ) ); int number = 14; for ( int i = 0; i < number; i++ ) { t = new Torus( 0.2, 0.01 + 0.185 * i / number ); t.SetAttribute( PropertyName.COLOR, new double[] { 1, 1, 1 } ); root.InsertChild( t, Matrix4d.CreateRotationX( 0.5 * i ) * Matrix4d.CreateTranslation( 10.0 * (1.0 * i / number) - 4.7, -2.5, 0 ) ); } }
/// <summary> /// Six national flags (in artistic style) - by Jakub Vlcek, (c) 2012 /// </summary> public static void Flags( IRayScene sc ) { Debug.Assert( sc != null ); // CSG scene: CSGInnerNode flags = new CSGInnerNode( SetOperation.Union ); flags.SetAttribute( PropertyName.REFLECTANCE_MODEL, new PhongModel() ); flags.SetAttribute( PropertyName.MATERIAL, new PhongMaterial( new double[] { 0.5, 0.5, 0.5 }, 0.2, 0.7, 0.1, 16 ) ); sc.Intersectable = flags; Sphere s; Cube c; // Background color: sc.BackgroundColor = new double[] { 0.0, 0.05, 0.05 }; // Camera: sc.Camera = new StaticCamera( new Vector3d( 0.0, 0.0, -10.0 ), new Vector3d( 0.0, 0.0, 1.0 ), 60.0 ); // Light sources: sc.Sources = new LinkedList<ILightSource>(); sc.Sources.Add( new AmbientLightSource( 0.8 ) ); sc.Sources.Add( new PointLightSource( new Vector3d( -5.0, 3.0, -3.0 ), 1.0 ) ); sc.Sources.Add( new PointLightSource( new Vector3d( 5.0, 3.0, -3.0 ), 1.0 ) ); // --- NODE DEFINITIONS ---------------------------------------------------- // Latvian flag (intersection, difference and xor): CSGInnerNode latvia = new CSGInnerNode( SetOperation.Intersection ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 0.3, 0.0, 0.0 } ); latvia.InsertChild( c, Matrix4d.Scale( 4.0, 2.0, 0.4 ) * Matrix4d.CreateTranslation( -2.0, -1.0, 0.0 ) ); CSGInnerNode latviaFlag = new CSGInnerNode( SetOperation.Xor ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 0.3, 0.0, 0.0 } ); latviaFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 4.0, 2.0, 2.0 ) ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 1.0, 1.0 } ); latviaFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 4.2, 0.5, 0.5 ) ); latvia.InsertChild( latviaFlag, Matrix4d.Identity ); flags.InsertChild( latvia, Matrix4d.Scale( 0.7 ) * Matrix4d.CreateRotationX( Math.PI / 8 ) * Matrix4d.CreateTranslation( -3.5, 1.5, 0.0 ) ); // Czech flag (difference): CSGInnerNode czech = new CSGInnerNode( SetOperation.Difference ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 0.2, 0.2, 0.2 } ); czech.InsertChild( s, Matrix4d.Identity ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 1.0, 1.0 } ); czech.InsertChild( s, Matrix4d.CreateTranslation( 0.0, 0.8, -1.0 ) ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 0.0, 0.0 } ); czech.InsertChild( s, Matrix4d.CreateTranslation( 0.0, -0.8, -1.1 ) ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 0.0, 0.0, 1.0 } ); czech.InsertChild( s, Matrix4d.CreateTranslation( -1.0, 0.0, -0.8 ) ); flags.InsertChild( czech, Matrix4d.Scale( 1.6, 1.0, 1.0 ) * Matrix4d.CreateRotationY( Math.PI / 8 ) * Matrix4d.CreateTranslation( 4.0, -1.5, 0.0 ) ); // Croatian flag (union, intersection): CSGInnerNode croatianFlag = new CSGInnerNode( SetOperation.Union ); CSGInnerNode croatianSign = new CSGInnerNode( SetOperation.Intersection ); CSGInnerNode checkerBoard = new CSGInnerNode( SetOperation.Union ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 0.0, 0.0 } ); c.SetAttribute( PropertyName.TEXTURE, new CheckerTexture( 10.0, 10.0, new double[] { 1.0, 1.0, 1.0 } ) ); croatianSign.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 2.0, 2.0, 0.4 ) ); CSGInnerNode sign = new CSGInnerNode( SetOperation.Union ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 1.0, 1.0 } ); sign.InsertChild( s, Matrix4d.Identity ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 1.0, 1.0 } ); sign.InsertChild( c, Matrix4d.Scale( 1.8 ) * Matrix4d.CreateTranslation( -0.9, 0.1, -0.9 ) ); croatianSign.InsertChild( sign, Matrix4d.Scale( 0.5, 0.33, 0.5 ) * Matrix4d.CreateTranslation( 0.44, -0.5, 0.0 ) ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 0.0, 0.0 } ); croatianFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 4.0, 0.6, 0.6 ) * Matrix4d.RotateX( Math.PI / 4 ) * Matrix4d.CreateTranslation( 0.5, 1.0, 1.0 ) ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 1.0, 1.0 } ); croatianFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 4.0, 0.6, 0.6 ) * Matrix4d.RotateX( Math.PI / 4 ) * Matrix4d.CreateTranslation( 0.5, 0.3, 1.0 ) ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 0.0, 0.0, 1.0 } ); croatianFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 4.0, 0.6, 0.6 ) * Matrix4d.RotateX( Math.PI / 4 ) * Matrix4d.CreateTranslation( 0.5, -0.4, 1.0 ) ); croatianFlag.InsertChild( croatianSign, Matrix4d.Scale( 0.8 ) * Matrix4d.CreateTranslation( 0.4, 0.5, 0.0 ) ); flags.InsertChild( croatianFlag, Matrix4d.Scale( 0.8 ) * Matrix4d.CreateRotationY( Math.PI / 8 ) * Matrix4d.CreateTranslation( -0.4, 1.5, 1.0 ) ); // Brazilian flag (union): CSGInnerNode brazilianFlag = new CSGInnerNode( SetOperation.Union ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 0.0, 0.8, 0.0 } ); brazilianFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 4.0, 2.0, 0.2 ) ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 1.0, 0.0 } ); brazilianFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.CreateRotationZ( Math.PI / 4 ) * Matrix4d.Scale( 2.0, 1.0, 0.4 ) ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 0.0, 0.0, 1.0 } ); brazilianFlag.InsertChild( s, Matrix4d.Scale( 0.5 ) * Matrix4d.CreateTranslation( 0.0, 0.0, 0.0 ) ); flags.InsertChild( brazilianFlag, Matrix4d.Scale( 0.9 ) * Matrix4d.RotateY( -Math.PI / 8 ) * Matrix4d.CreateTranslation( 0.0, -1.8, 1.0 ) ); // Finnish flag (intersection and difference): CSGInnerNode finlandFlag = new CSGInnerNode( SetOperation.Difference ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 1.0, 1.0 } ); finlandFlag.InsertChild( s, Matrix4d.Scale( 2.0, 1.0, 0.5 ) * Matrix4d.CreateTranslation( 0.0, 0.0, 0.3 ) ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 0.0, 0.0, 1.0 } ); finlandFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 4.2, 0.5, 0.5 ) ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 0.0, 0.0, 1.0 } ); finlandFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 0.5, 4.2, 0.5 ) * Matrix4d.CreateTranslation( -0.5, 0.0, 0.0 ) ); flags.InsertChild( finlandFlag, Matrix4d.Scale( 0.7 ) * Matrix4d.CreateTranslation( 3.5, 1.5, 0.0 ) ); // Cuban flag (union and intersection): CSGInnerNode cubanFlag = new CSGInnerNode( SetOperation.Union ); for ( int i = 0; i < 5; i++ ) { c = new Cube(); if ( i % 2 == 0 ) c.SetAttribute( PropertyName.COLOR, new double[] { 0.0, 0.0, 1.0 } ); else c.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 1.0, 1.0 } ); cubanFlag.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 4.0, 0.4, 0.4 ) * Matrix4d.CreateTranslation( new Vector3d( 0.0, 0.0 - i * 0.4, 0.8 - i * 0.2 ) ) ); } CSGInnerNode wedge = new CSGInnerNode( SetOperation.Intersection ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 0.0, 0.0 } ); wedge.InsertChild( c, Matrix4d.CreateTranslation( -0.5, -0.5, -0.5 ) * Matrix4d.Scale( 2.0, 2.0, 2.0 ) * Matrix4d.CreateRotationZ( Math.PI / 4 ) ); c = new Cube(); c.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 0.0, 0.0 } ); wedge.InsertChild( c, Matrix4d.Scale( 4.0 ) * Matrix4d.CreateTranslation( 0.0, -2.0, -2.0 ) ); cubanFlag.InsertChild( wedge, Matrix4d.Scale( 0.7 ) * Matrix4d.CreateTranslation( -2.0001, -0.8, 0.4999 ) ); flags.InsertChild( cubanFlag, Matrix4d.Scale( 0.7 ) * Matrix4d.RotateY( Math.PI / 8 ) * Matrix4d.CreateTranslation( -4.0, -1.0, 0.0 ) ); }
/// <summary> /// Simple scene containing five colored spheres. /// </summary> public static void FiveBalls( IRayScene sc ) { Debug.Assert( sc != null ); // CSG scene: CSGInnerNode root = new CSGInnerNode( SetOperation.Union ); root.SetAttribute( PropertyName.REFLECTANCE_MODEL, new PhongModel() ); root.SetAttribute( PropertyName.MATERIAL, new PhongMaterial( new double[] { 0.5, 0.5, 0.5 }, 0.1, 0.6, 0.3, 16 ) ); sc.Intersectable = root; // Background color: sc.BackgroundColor = new double[] { 0.0, 0.05, 0.05 }; // Camera: sc.Camera = new StaticCamera( new Vector3d( 0.0, 0.0, -10.0 ), new Vector3d( 0.0, 0.0, 1.0 ), 60.0 ); // Light sources: sc.Sources = new LinkedList<ILightSource>(); sc.Sources.Add( new AmbientLightSource( 0.8 ) ); sc.Sources.Add( new PointLightSource( new Vector3d( -5.0, 3.0, -3.0 ), 1.0 ) ); // --- NODE DEFINITIONS ---------------------------------------------------- // sphere 1: Sphere s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 0.6, 0.0 } ); root.InsertChild( s, Matrix4d.Identity ); // sphere 2: s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 0.2, 0.9, 0.5 } ); root.InsertChild( s, Matrix4d.CreateTranslation( -2.2, 0.0, 0.0 ) ); // sphere 3: s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 0.1, 0.3, 1.0 } ); root.InsertChild( s, Matrix4d.CreateTranslation( -4.4, 0.0, 0.0 ) ); // sphere 4: s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1.0, 0.2, 0.2 } ); root.InsertChild( s, Matrix4d.CreateTranslation( 2.2, 0.0, 0.0 ) ); // sphere 5: s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 0.1, 0.4, 0.0 } ); s.SetAttribute( PropertyName.TEXTURE, new CheckerTexture( 80.0, 40.0, new double[] { 1.0, 0.8, 0.2 } ) ); root.InsertChild( s, Matrix4d.CreateTranslation( 4.4, 0.0, 0.0 ) ); }
protected static CSGInnerNode test6Spheres( SetOperation op ) { // scene: CSGInnerNode root = new CSGInnerNode( op ); Sphere s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1, 0.3, 1 } ); root.InsertChild( s, Matrix4d.Scale( 2 ) ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 0.5, 0.8, 0.2 } ); root.InsertChild( s, Matrix4d.CreateTranslation( 0, 0, -2 ) ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1, 0.3, 0 } ); root.InsertChild( s, Matrix4d.CreateTranslation( 0, 1, -0.5 ) ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1, 0.3, 0 } ); root.InsertChild( s, Matrix4d.CreateTranslation( 1, 0, -0.5 ) ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1, 0.3, 0 } ); root.InsertChild( s, Matrix4d.CreateTranslation( 0, -1, -0.5 ) ); s = new Sphere(); s.SetAttribute( PropertyName.COLOR, new double[] { 1, 0.3, 0 } ); root.InsertChild( s, Matrix4d.CreateTranslation( -1, 0, -0.5 ) ); return root; }