Click here to Skip to main content
16,017,881 members
Articles / Desktop Programming / WPF

Clipping Plane in WPF 3D

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
14 Aug 2018CPOL6 min read 12.4K   470   9  
Demonstrate Clipping Plane in WPF 3D

Image 1

Introduction

I recently needed to brush up on WPF and had the idea of adding a Clipping Plane to Rod Stephens' excellent WPF Menger Sponge. While I was at it, I added some other features which I will describe via the following links:

  1. Clipping Plane
  2. Axes
  3. Lighting
  4. Textures
  5. Progress Bar
  6. Menu Bar

Download and Build

Download the MengerSpongeClipping.zip file and extract it. Open the MengerSpongeClipping project with Visual Studio. Build it by pressing F6; the project should build successfully with no errors. Press F5 to run the MengerSpongeClipping project in debug mode.

Using the Code

To clip the Menger Sponge, simply click the "Clip" button. You can orient the clipping plane using the sliders as illustrated in the above image. You can rotate the clipping plane about the x, y, or z axes using the "Rotate Plane" Sliders, and you can translate it along the x, y, or z axes using "Translate Plane" sliders. For this version, the Clipping Plane is assumed to be infinite in all directions, so the translation is for demonstration purposes and does not affect the actual clipping. (In a future version, I plan on having the clipping algorithm assume a finite Clipping Plane, and therefore take into account the translation of the Clipping Plane, so parts of the Sponge that are outside are not clipped.) The positive side of the Clipping Plane is an opaque green; the negative side is an opaque blue.

Clipping Plane

My implementation of the clipping plane is simple: the distance from the plane to each rectangle center is computed, and rectangles with distance values less than zero (that is, behind the opaque blue side) are discarded. The method DrawClippingPlane() performs the following steps:

  1. Rotate the Clipping Plane
  2. Translate the Clipping Plane
  3. Get the transformed coordinates of the Clipping Plane
  4. Determine Equation of the Clipping Plane in the form Ax + By + Cz + D = 0

The method DistanceFromPlaneToPoint() uses the Equation of the Clipping Plane to determine the distance to the rectangle's center. The method RemoveClippedRectangles() (described below) computes the distance and removes clipped rectangles from RectanglesMade. The method DrawClippedSponge() (also described below) redraws the Menger Sponge.

Axes

I used Mr. Stephens' WPF Cylinder code to draw the x, y, z axes. You can toggle them on and off by pressing the "A" (the Axis Toggle Key), or by using "View" from the Menu Bar. To label the axes, I used Eric Sink's fantastic CreateTextLabel3D() method; I added another parameter, a Transform3DGroup transform. See TextLabel3D.cs for details.

Lighting

In WPF (and DirectX and OpenGL), a directional light is a light that projects its effect along a specified vector. The Vector3D lightVector1, Vector3D lightVector2, Color lightColor1 and Color lightColor2 are inputs to the DirectionalLight() constructor. Since it can sometimes be hard to visualize where the light is pointing by specifying a vector, I used Mr. Stephens' WPF Cone code to draw "flashlights" (a flashlight is known as a torch in the UK) that shows where the directional light is pointing. There are two directional lights named appropriately enough Light 1 and Light 2. The flashlights are disabled (not displayed) by default for clarity. To enable (display) them, press the "F" key (the Flashlight Toggle Key) or use "View" from the Menu Bar. Whether the flashlights are enabled or not does not affect the actual lighting; in other words, they are only used for making the lighting vectors easier to visualize.

You can experiment with the two lights by setting the sliders for the direction vectors and combo box for the colors. If you select "None" from the colors combo box, the corresponding DirectionalLight() is turned off, and the flashlight is displayed in wireframe code supplied by Mr. Stephens. (I spent some time trying to use 3D Tools wireframe, but to no avail.) In the illustration below, I've enabled the flashlights, zoomed out a little (using the minus key) and disabled the Clipping Plane (for clarity) by pressing the "P" key (the Clipping Plane Toggle Key). Next, I set the direction vectors as shown, set Light 1 (in the background) to blue and Light 2 (in the foreground) to red. Note how the red light illuminates the X and Z faces of the Menger Sponge to red, and the Y face is a shade of purple due to the combination of blue and red:

MengerSpongeLighting1

In the next illustration, after I rotate the scene 195 degrees using the arrow keys (note how theta goes from 60° to 255°), and tilt it from phi=30 degrees to phi=40 degrees, the effect of the Light 1, the blue light (now in the foreground) can be seen illuminating the -X and -Z faces of the Menger Sponge to blue:

MengerSpongeLighting 2

Textures

You can add textures to the Menger Sponge by selecting an image file from the "Texture" combo box as shown below. In order to use this feature, you first need to modify app.config to point to the image files, for example:

<setting name="ImageFileLocation" serializeAs="String">
	<value>C:\MyProjects\MengerSponge\MengerSpongeClipping\MengerSpongeClipping\Images\</value>
</setting>

The code for this is from yet another useful article by Mr. Stephens on textures.

MengerSpongeTexture

WPF Progress Bar

Since the number of rectangles drawn is determined by the SpongeDepth, I added a WPF Progress Bar to show the progress of re-drawing the clipped Menger Sponge, as illustrated below. The code demonstrates the use of a BackgroundWorker object. To get the full effect if you're running on a fast machine, you might want to run the program in Debug mode by pressing F5 since there is some console output in debug mode which slows the process somewhat.

MengerSpongeProgressBar

When you click the "Clip" button, the BtnClip_Click() callback creates the BackgroundWorker object in order to perform the clipping operation on a separate thread. Note the use of Dispatcher.Invoke in RemoveClippedRectangles() which is needed since the method DrawClippedSponge() accesses the spongeMesh object which is owned by a different thread. The method RemoveClippedRectangles() calculates the progress.

The Menu Bar has "File", "View" and "Help" menu items. "File->Save As..." allows you to save your settings to a text file, and "File->Open" allows you to retrieve them. File->Reset will reset the Clipping Plane rotations and translations, Camera movements, lighting settings, and textures to their initial values (as will pressing the Escape key). "View" allows you to toggle the Axes, Clipping Plane, Sponge, and Plane Normal. You can also use the "A", "P", "S", and "N" toggle keys, respectively. Since the Plane Normal is small (a unit vector), you will have to turn off the Sponge (and Axes, if the Plane Normal is aligned with an axis) in order to see it.

History

  • Version 1.0.0.0

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior)
United States United States
Chuck Peasley is a developer in Orange County, CA

Comments and Discussions

 
-- There are no messages in this forum --