public void Render(Bitmap output, SceneBrep scene) { if (output == null || scene == null) { return; } Vector3 center; float diameter = scene.GetDiameter(out center); if (Distance < diameter) { Distance = diameter; } // and the rest of projection matrix goes here: int width = output.Width; int height = output.Height; float aspect = width / (float)height; double az = Azimuth / 180.0 * Math.PI; double el = Elevation / 180.0 * Math.PI; Vector3 eye = new Vector3((float)(center.X + Distance * Math.Sin(az) * Math.Cos(el)), (float)(center.Y + Distance * Math.Sin(el)), (float)(center.Z + Distance * Math.Cos(az) * Math.Cos(el))); Matrix4 modelView = Matrix4.LookAt(eye, center, Vector3.UnitY); Matrix4 proj; if (Perspective) { float vv = (float)(2.0 * Math.Atan2(diameter * 0.5, Distance)); proj = Matrix4.CreatePerspectiveFieldOfView(vv, aspect, 1.0f, 50.0f); } else { float vHalf = diameter * 0.52f; proj = Matrix4.CreateOrthographicOffCenter(-vHalf, vHalf, -vHalf / aspect, vHalf / aspect, 1.0f, 50.0f); } Matrix4 compound = Matrix4.Mult(modelView, proj); Matrix4 viewport = Geometry.SetViewport(0, 0, width, height); compound = Matrix4.Mult(compound, viewport); // wireframe rendering: Graphics gr = Graphics.FromImage(output); Pen pen = new Pen(Color.FromArgb(255, 255, 80), 1.0f); int n = scene.Triangles; for (int i = 0; i < n; i++) { Vector4 A, B, C; scene.GetTriangleVertices(i, out A, out B, out C); A = Vector4.Transform(A, compound); B = Vector4.Transform(B, compound); C = Vector4.Transform(C, compound); Vector2 a = new Vector2(A.X / A.W, A.Y / A.W); Vector2 b = new Vector2(B.X / B.W, B.Y / B.W); Vector2 c = new Vector2(C.X / C.W, C.Y / C.W); gr.DrawLine(pen, a.X, a.Y, b.X, b.Y); gr.DrawLine(pen, b.X, b.Y, c.X, c.Y); gr.DrawLine(pen, c.X, c.Y, a.X, a.Y); } if (DrawNormals && scene.Normals > 0) { pen = new Pen(Color.FromArgb(255, 80, 80), 1.0f); n = scene.Vertices; for (int i = 0; i < n; i++) { Vector4 V = new Vector4(scene.GetVertex(i), 1.0f); Vector3 N = scene.GetNormal(i); N.Normalize(); N *= diameter * 0.03f; Vector4 W = V + new Vector4(N); V = Vector4.Transform(V, compound); W = Vector4.Transform(W, compound); Vector2 v = new Vector2(V.X / V.W, V.Y / V.W); Vector2 w = new Vector2(W.X / W.W, W.Y / W.W); gr.DrawLine(pen, v.X, v.Y, w.X, w.Y); } } }
/// <summary> /// Generic OBJ-loading scene definition routine. /// </summary> /// <param name="dir">Viewing direction of a camera.</param> /// <param name="FoVy">Field of View in degrees.</param> /// <param name="correction">Value less than 1.0 brings camera nearer.</param> /// <param name="name">OBJ file-name.</param> /// <param name="names">Substitute file-name[s].</param> /// <returns>Number of triangles.</returns> protected static long SceneObj( IRayScene sc, Vector3d dir, double FoVy, double correction, string name, string[] names, double[] surfaceColor ) { Debug.Assert( sc != null ); Vector3 center = Vector3.Zero; // center of the mesh dir.Normalize(); // normalized viewing vector of the camera float diameter = 2.0f; // default scene diameter int faces = 0; // CSG scene: CSGInnerNode root = new CSGInnerNode( SetOperation.Union ); // OBJ file to read: if ( names.Length == 0 || names[ 0 ].Length == 0 ) names = new string[] { name }; string[] paths = Scenes.SmartFindFiles( names ); if ( paths[ 0 ] == null || paths[ 0 ].Length == 0 ) { for ( int i = 0; i < names.Length; i++ ) if ( names[ i ].Length > 0 ) names[ i ] += ".gz"; paths = Scenes.SmartFindFiles( names ); } if ( paths[ 0 ] == null || paths[ 0 ].Length == 0 ) root.InsertChild( new Sphere(), Matrix4d.Identity ); else { // B-rep scene construction: WavefrontObj objReader = new WavefrontObj(); objReader.MirrorConversion = false; SceneBrep brep = new SceneBrep(); faces = objReader.ReadBrep( paths[ 0 ], brep ); brep.BuildCornerTable(); diameter = brep.GetDiameter( out center ); TriangleMesh m = new TriangleMesh( brep ); root.InsertChild( m, Matrix4d.Identity ); } root.SetAttribute( PropertyName.REFLECTANCE_MODEL, new PhongModel() ); root.SetAttribute( PropertyName.MATERIAL, new PhongMaterial( surfaceColor, 0.2, 0.5, 0.4, 32 ) ); root.SetAttribute( PropertyName.COLOR, surfaceColor ); sc.Intersectable = root; // Background color: sc.BackgroundColor = new double[] { 0.0, 0.05, 0.07 }; // Camera: double dist = (0.5 * diameter * correction) / Math.Tan( MathHelper.DegreesToRadians( (float)(0.5 * FoVy) ) ); Vector3d cam = (Vector3d)center - dist * dir; sc.Camera = new StaticCamera( cam, dir, FoVy ); // Light sources: sc.Sources = new LinkedList<ILightSource>(); sc.Sources.Add( new AmbientLightSource( 0.8 ) ); Vector3d lightDir = Vector3d.TransformVector( dir, Matrix4d.CreateRotationY( -2.0 ) ); lightDir = Vector3d.TransformVector( lightDir, Matrix4d.CreateRotationZ( -0.8 ) ); sc.Sources.Add( new PointLightSource( (Vector3d)center + diameter * lightDir, 1.0 ) ); return faces; }
public void Render( Bitmap output, SceneBrep scene ) { if ( output == null || scene == null ) return; Vector3 center; float diameter = scene.GetDiameter( out center ); if ( Distance < diameter ) Distance = diameter; // and the rest of projection matrix goes here: int width = output.Width; int height = output.Height; float aspect = width / (float)height; double az = Azimuth / 180.0 * Math.PI; double el = Elevation / 180.0 * Math.PI; Vector3 eye = new Vector3( (float)(center.X + Distance * Math.Sin( az ) * Math.Cos( el )), (float)(center.Y + Distance * Math.Sin( el )), (float)(center.Z + Distance * Math.Cos( az ) * Math.Cos( el )) ); Matrix4 modelView = Matrix4.LookAt( eye, center, Vector3.UnitY ); Matrix4 proj; if ( Perspective ) { float vv = (float)(2.0 * Math.Atan2( diameter * 0.5, Distance )); proj = Matrix4.CreatePerspectiveFieldOfView( vv, aspect, 1.0f, 50.0f ); } else { float vHalf = diameter * 0.52f; proj = Matrix4.CreateOrthographicOffCenter( -vHalf, vHalf, -vHalf / aspect, vHalf / aspect, 1.0f, 50.0f ); } Matrix4 compound = Matrix4.Mult( modelView, proj ); Matrix4 viewport = Geometry.SetViewport( 0, 0, width, height ); compound = Matrix4.Mult( compound, viewport ); // wireframe rendering: Graphics gr = Graphics.FromImage( output ); Pen pen = new Pen( Color.FromArgb( 255, 255, 80 ), 1.0f ); int n = scene.Triangles; for ( int i = 0; i < n; i++ ) { Vector4 A, B, C; scene.GetTriangleVertices( i, out A, out B, out C ); A = Vector4.Transform( A, compound ); B = Vector4.Transform( B, compound ); C = Vector4.Transform( C, compound ); Vector2 a = new Vector2( A.X / A.W, A.Y / A.W ); Vector2 b = new Vector2( B.X / B.W, B.Y / B.W ); Vector2 c = new Vector2( C.X / C.W, C.Y / C.W ); gr.DrawLine( pen, a.X, a.Y, b.X, b.Y ); gr.DrawLine( pen, b.X, b.Y, c.X, c.Y ); gr.DrawLine( pen, c.X, c.Y, a.X, a.Y ); } if ( DrawNormals && scene.Normals > 0 ) { pen = new Pen( Color.FromArgb( 255, 80, 80 ), 1.0f ); n = scene.Vertices; for ( int i = 0; i < n; i++ ) { Vector4 V = new Vector4( scene.GetVertex( i ), 1.0f ); Vector3 N = scene.GetNormal( i ); N.Normalize(); N *= diameter * 0.03f; Vector4 W = V + new Vector4( N ); V = Vector4.Transform( V, compound ); W = Vector4.Transform( W, compound ); Vector2 v = new Vector2( V.X / V.W, V.Y / V.W ); Vector2 w = new Vector2( W.X / W.W, W.Y / W.W ); gr.DrawLine( pen, v.X, v.Y, w.X, w.Y ); } } }