Use WPF 3d techniques to draw a snowman with WPF and C#


[WPF 3d]

This example shows how to use the tools and techniques described in my book WPF 3d, Three-Dimensional Graphics with WPF and C# to draw a three-dimensional snowman. I won’t go into all of the details because there are a whole book’s worth, but here’s the code that builds the snowman model.

// Define the model.
private void DefineModel()
{
    // Show the axes.
    // MeshExtensions.AddAxes(MainGroup);

    // Make the snowman's body.
    const double bodyR = 2;
    const double headR = 1.25;
    MeshGeometry3D bodyMesh = new MeshGeometry3D();
    double headY = 0.8 * (headR + bodyR) - 1;
    MeshExtensions.AddSphere(bodyMesh,
        new Point3D(0, headY, 0),
        headR, 40, 20, true);
    MeshExtensions.AddSphere(bodyMesh,
        new Point3D(0, -1, 0),
        bodyR, 40, 20, true);
    MainGroup.Children.Add(bodyMesh.MakeModel(Brushes.White));

    // Nose.
    const double noseR = 0.2;
    MeshGeometry3D noseMesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(noseMesh,
        new Point3D(0, headY, 0),
        noseR, 20, 10, true);
    MainGroup.Children.Add(noseMesh.MakeModel(Brushes.Orange));
    noseMesh.ApplyTransformation(new ScaleTransform3D(1, 1, 3));
    noseMesh.ApplyTransformation(new TranslateTransform3D(0, 0, headR));

    // Eyes.
    const double eyeR = 0.15;
    MeshGeometry3D eyeMesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(eyeMesh,
        new Point3D(0.4, 0.4, -0.15),
        eyeR, 7, 3, false);
    MeshExtensions.AddSphere(eyeMesh,
        new Point3D(-0.4, 0.4, -0.15),
        eyeR, 6, 3, false);
    MainGroup.Children.Add(eyeMesh.MakeModel(Brushes.Black));
    eyeMesh.ApplyTransformation(
        new TranslateTransform3D(0, headY, headR));

    // Buttons.
    const double buttonR = 0.17;
    MeshGeometry3D button1Mesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(button1Mesh,
        new Point3D(0, 0, bodyR),
        buttonR, 7, 3, false);
    button1Mesh.ApplyTransformation(new TranslateTransform3D(0, -1, 0));
    MainGroup.Children.Add(button1Mesh.MakeModel(Brushes.DarkBlue));

    MeshGeometry3D button2Mesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(button2Mesh,
        new Point3D(0, 0, bodyR),
        buttonR, 6, 3, false);
    Rotation3D rotation2 =
        new AxisAngleRotation3D(new Vector3D(1, 0, 0), -23);
    button2Mesh.ApplyTransformation(
        new RotateTransform3D(rotation2, new Point3D()));
    button2Mesh.ApplyTransformation(new TranslateTransform3D(0, -1, 0));
    MainGroup.Children.Add(button2Mesh.MakeModel(Brushes.DarkBlue));

    MeshGeometry3D button3Mesh = new MeshGeometry3D();
    MeshExtensions.AddSphere(button3Mesh,
        new Point3D(0, 0, bodyR),
        buttonR, 7, 3, false);
    Rotation3D rotation3 =
        new AxisAngleRotation3D(new Vector3D(1, 0, 0), -46);
    button3Mesh.ApplyTransformation(
        new RotateTransform3D(rotation3, new Point3D()));
    button3Mesh.ApplyTransformation(new TranslateTransform3D(0, -1, 0));
    MainGroup.Children.Add(button3Mesh.MakeModel(Brushes.DarkBlue));

    // Hat.
    MeshGeometry3D hatMesh = new MeshGeometry3D();
    const double hatR = 0.8;
    const double hatL = 1.65;
    Point3D[] polygon = G3.MakePolygonPoints(20, new Point3D(),
        new Vector3D(hatR, 0, 0), new Vector3D(0, 0, hatR));
    MeshExtensions.AddConeFrustum(hatMesh, new Point3D(0, headY, 0),
        polygon, new Vector3D(0, -3 * hatL, 0), hatL);

    // Brim.
    const double brimR = 1.5 * hatR;
    Point3D[] brimPolygon = G3.MakePolygonPoints(20,
        new Point3D(0, -hatL / 2, 0),
        new Vector3D(brimR, 0, 0), new Vector3D(0, 0, brimR));
    MeshExtensions.AddCylinder(hatMesh, brimPolygon,
        new Vector3D(0, -0.2, 0), true);

    Rotation3D hatRotation =
        new AxisAngleRotation3D(new Vector3D(0, 0, 1), -10);
    hatMesh.ApplyTransformation(
        new RotateTransform3D(hatRotation, new Point3D()));
    hatMesh.ApplyTransformation(new TranslateTransform3D(0.5, headY + 2, 0));
    MainGroup.Children.Add(hatMesh.MakeModel(Brushes.Green));
}

The basic steps for creating a WPF 3d object are:

  1. Create a mesh to hold a shape’s geometry.
  2. Use methods defined by the MeshExtensions and G3 classes to create objects such as spheres, cubes, boxes, polygons, tori, frustums, parametric surfaces, and other shapes and add them to the mesh.
  3. Transform the mesh if desired to translate, rotate, or scale the objects.
  4. Add the mesh to the main object group specifying the color that you want to give the mesh.

This example uses those techniques to create the snowman’s two body parts, nose, eyes, buttons, and hat.


[WPF 3d]

My book WPF 3d includes many other options for working with 3D scenes. For example, it lets you determine whether objects are smoothed. This example makes the snowman’s body, nose, and hat smooth, but it makes its eyes and buttons not smooth (so they look a little bit more like coal).

Other techniques described in the book include:

  • The lights, cameras, materials, texture coordinates, and other details that you need to create a 3D scene
  • Orthographic, perspective, and other projections that emphasize different aspects of a scene
  • Special material treatments such as specular reflection, wireframes, and solid and translucent materials
  • Examples of many shapes including flat polygons, boxes, Platonic solids, spheres, tori, cones, and more
  • Advanced objects such as parametric surfaces, surfaces of transformation, fractal surfaces, and 2D and 3D text
  • Higher-level scene management to let users select and move objects
  • Advanced techniques such as loading models created in other applications and using skeletons
      Visit the WPF 3d web page to see sample pictures and more details.


      Download Example   Follow me on Twitter   RSS feed   Donate




About RodStephens

Rod Stephens is a software consultant and author who has written more than 30 books and 250 magazine articles covering C#, Visual Basic, Visual Basic for Applications, Delphi, and Java.
This entry was posted in 3D, 3D graphics, books, drawing, graphics, XAML and tagged , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.