原文:WPF中的3D Wireframe

WPF不支持画三维线,但开发人员提供了ScreenSpaceLines3D 类用于实现这个功能。我已经在程序中实现并成功显示3D Wireframe,并能够进行3D Solid和3D Wireframe的切换。

我在熟悉这个类的基础上,自己定义了3D Wireframe xml文件的格式,用于保存3D Wireframe数据。

格式如下:

<Wireframe>
  <ScreenSpaceLines3D
    Form="Generic"
    Color="#00FF00"
    Thickness="1.0"
    Points="1540.681396, 706.149353, 449.837555,  1540.681396, 706.149353, 466.246826" />
  <ScreenSpaceLines3D
    Form="Generic"
    Color="#00FF00"
    Thickness="1.0"
    Points="1460.956909, 792.438416, 51.958309,  1460.877686, 784.031250, 54.853123" />
..................................................

</Wireframe>

然后,解析这个xml文件,遍历points属性,并将每个点按照一定规则加到ScreenSpaceLines3D .Points里面,这样有了点wireframe就有了内容,然后将ScreenSpaceLines3D ._model应用到视图就可以正常显示了。具体方法以后有空再总结。

 

下面是我看到有关wireframe的一些文章,摘录一下。

 

How to Draw WPF 3D Wireframe Graphics

A question I periodically see on forums and discussions with WPF 3D graphics users is, "how do I draw wireframe" content for 3D. This isn't supported out of the box, but couple strategies I would suggest are:

 

  • The out of band 3DTools library from members of the WPF 3D team includes "ScreenSpaceLines" which allows for wireframe rendering of lines.

http://www.codeplex.com/3DTools

  •  Charles Petzold has also posted about wireframe rendering with his own implementation.

 (as below)

 

 

 

As Eric Sink pointed out recently, "WPF 3D doesn't know how to draw lines.". Fortunately, the WPF 3D team at Microsoft has made available the 3DTools library that includes the ScreenSpaceLines3D class that derives from ModelVisual3D and draws lines in a 3D scene. The "screen space" in the name of this class indicates that you specify the thickness of the lines in terms of device-independent units, which are 1/96th inch and hence often pixels.

What's really nice is that the source code to ScreenSpaceLines3D is also available so you can see the clever techniques at work to make this happen: Basically, each line is a pair of triangles arranged in a long thin rectangle. While you specify the begin point and end point of this "line" in 3D coordinates, the ScreenSpaceLines3D class must determine the thickness of this "line" at each end so that after the various transforms have been applied to it (including the camera transforms — see Chapter 7 of my book 3D Programming for Windows) it ends up on the screen with a uniform thickness with a surface that is always oriented perpendicularly to the viewer.

This job requires that ScreenSpaceLines3D know about all the transforms that are applied to the visual because it must invert the transform chain to determine the dimensions and orientation of the line that it renders. What makes this job particularly tricky is that these transforms can be animated. For that reason, ScreenSpaceLines3D installs a handler for the CompositionTarget.Rendering event, and walks the parent/child chain up to Viewport3D on each vertical retrace of the video display. As Eric notes, this is a problem.

I spent a lot of time studying ScreenSpaceLines3D because I knew I wanted to implement something similar in my own Petzold.Media3D library (available here). At one point I derived from Viewport3D specifically to provide support for my "wire" classes (as I began thinking of them), but I eventually abandoned that approach.

Instead, my abstract WireBase class installs a handler for CompositionTarget.Rendering but it does so from a static constructor, so regardless how many WireBase objects you have, there's only one call to this handler per vertical retrace. Each instance of WireBase puts itself into a static collection that the CompositionTarget.Rendering handler enumerates for each call, at that point essentially performing the same logic as ScreenSpaceLines3D. However, if a particular WireBase instance discovers that its chain of visual parents no longer ends in a Window object, then it removes itself from this collection and is abandoned. This is how I hope my implementation is a little less insane than ScreenSpaceLines3D.

I had decided that I would be using XAML files to create all the illustrations in my book. Many of the illustrations were created from 400 DPI bitmaps that I generated from XamlCruncher 2.0. At that resolution, ScreenSpaceLines3D had some limitiations I simply couldn't tolerate. Not only did I need to shamelessly copy the technique of ScreenSpaceLines3D but I had to enhance it.

The "wire" classes I eventually created for the Petzold.Media3D begin with WireBase and are shown here roughly in increasing levels of complexity:

  • Object
       DispatcherObject
          DependencyObject
             Visual3D
                ModelVisual3D
                   WireBase
                      WireLine
                      WireLines
                      WirePolyline
                      WirePath
                      WireText
                      Axes

For me, the most serious problem with ScreenSpaceLines3D was the line joins. Here's a ScreenSpaceLines3D element with a width of 40 device-independent units:

  • <tools:ScreenSpaceLines3D
               Points="-1 0 0, 0 0.5 0, 0 0.5 0, 0.5 0 0"
               Thickness="40" Color="Blue" />

In ScreenSpaceLines3D you set the Points property to an even number of Point3D objects; each pair of points define one line. And here's what it looks like:

It's obviously two lines rather than a connected line. The class in the Petzold.Media3D library that's closest in syntax to ScreenSpaceLines3D is WireLines except the property is named Lines rather than Points:

  • <cp:WireLines Lines="-1 0 0, 0 0.5 0, 0 0.5 0, 0.5 0 0"
                  Thickness="40" Color="Blue" />

The image produced by that markup is the same as the ScreenSpaceLines3D example. However, I've also provided a property in WireBase named Rounding of type int that lets you specify the number of little pie slices used to approximate the rounding of the ends of each line:

  • <cp:WireLines Lines="-1 0 0, 0 0.5 0, 0 0.5 0, 0.5 0 0"
                  Thickness="40" Color="Blue" Rounding="10" />

And now the lines are rendered like this:

You can alternatively use the WirePolyline class and just specify the three points that make up this particular figure:

  • <cp:WirePolyline Points="-1 0 0, 0 0.5 0, 0.5 0 0"
                     Thickness="40" Color="Blue"
                     Rounding="10" />

Or, to draw a single straight line, you can use WireLine and set the Point1 and Point2 properties. The WireBase class also defines ArrowEnds, ArrowLength, and ArrowAngle properties to draw arrows at the end of the line (handy for symbolizing vectors in 3D space.)

Similar to the WPF 2D Path class, my WirePath class has a Data property of type PathGeometry3D, and if you check the Paths directory of the Petzold.Media3D source code, you'll find that my PathGeometry3D class defines a Figures property of type PathFigure3DCollection, and PathFigure3D defines a StartPoint property and a Segments property of type PathSegment3DCollection, and PathSegment3D is parent to the four classes LineSegment3D, PolyLineSegment3D, BezierSegment3D, and PolyBezierSegment3D. In other words, I've tried to duplicate the 2D path geometry classes in 3D. (What I didn't get around to doing was a PathGeometry3DConverter that would let you specify a whole path as an encoded text string, but it's high on my to-do list.)

For example, these classes allowed me to create the following XAML file for a figure in Chapter 6 of 3D Programming for Windows:

LongitudeAndLatitude.xaml

You can run that XAML file in XamlCruncher 2.0 if you have the Petzold.Media3D library loaded, or you can just run an XBAP created from the XAML file:

LongitudeAndLatitude.xbap

It looks like this:

It looks better in the book (page 240) because that image was created at 400 DPI rather than 96 DPI as it is here. (It also looks better on the screen with a Tier 2 graphics board because you get anti-aliasing. You don't get anti-aliasing when you're rendering 3D scenes on bitmaps.) All the lines of longitude and latitude are WirePath objects, but inside is a sphere colored with a translucent brush to make the lines around the back a little less dark.

The WireText text class is based around the polylines from the ancient Windows plotter fonts. You set the Font property to a member of the Font enumeration (Modern, Roman, or Script) and FontSize to an approximate character height in 3D units. Set the Origin property to a Point3D where the text is to begin, and HorizontalAlignment (default is Left) and VerticalAlignment (default is Top) to indicate the meaning of that origin. You'll also need to set two vectors: BaselineDirection (default is (1, 0, 0)) and UpDirection (default is (0, 1, 0)). The cross product of BaselineDirection and UpDirection indicates the direction from which the text appears normal. Set the Text property to the text you wish to display.

The size of the text characters will get smaller as the text recedes to the background, but the actual strokes that make up the characters will not. Those are governed by the Thickness property defined by WireBase.

Finally, the Axes class combines lines and text to display the 3D coordinate axes:

Of course, several properties let you set the Extent of the axes (the default is 3), whether it will ShowNumbers, the length of LargeTick and SmallTick, and you can even replace the Labels from X, Y, and Z to something else, such as shown on page 317 of my book.

The Petzold.Media3D Library: The "Wire" Classes

WPF中的3D Wireframe的更多相关文章

  1. WPF中反转3D列表项

    原文:WPF中反转3D列表项 WPF中反转3D列表项                                                         周银辉记得在苹果电脑中有一个很酷的 ...

  2. WPF中的3D特性和常见的几个类

    原文:WPF中的3D特性和常见的几个类 WPF 3D 常用的几个类及其关系 1.  Visual 类      所有二维可视化元素的基类,为 WPF 中的呈现提供支持,其中包括命中测试.坐标转换和边界 ...

  3. 在WPF中添加3D特性

    原文:在WPF中添加3D特性 35.4  在WPF中添加3D特性 本节介绍WPF中的3D特性,其中包含了开始使用该特性的信息. 提示: WPF中的3D特性在System.Windows.Media.M ...

  4. WPF中的3D变换PlaneProjection

    在UWP中有一个比较好用的伪3D变换PlaneProjection,可以以一种轻量级和非常简单的方式实现3D的效果.这种效果在Silverlight中也有这种变换,但在WPF中确一直没有提供. 虽然W ...

  5. WPF中的三维空间(1)

    原文:WPF中的三维空间(1) WPF中可以创建三维几何图形,支持3D对象的应用,支持从3D Max等软件将3D文件obj导入设计中,但是目前还不支持将材质同时导入,这样需要在WPF中对3D对象重新设 ...

  6. WPF中的简单水动画

    原文 https://stuff.seans.com/2008/08/21/simple-water-animation-in-wpf/ 很多年前(80年代中期),我在一家拥有Silicon Grap ...

  7. 在WPF中使用PlaneProjection模拟动态3D效果

    原文:在WPF中使用PlaneProjection模拟动态3D效果 虽然在WPF中也集成了3D呈现的功能,在简单的3D应用中,有时候并不需要真实光影的3D场景.毕竟使用3D引擎会消耗很多资源,有时候使 ...

  8. WPF中3D旋转的实现

    原文:WPF中3D旋转的实现 关于3D旋转的原理,请看Daniel Lehenbauer的文章 <Rotating the Camera with the Mouse> http://vi ...

  9. WPF中使用TranslateTransform3D修改CAD的3D旋转中心

    原文:WPF中使用TranslateTransform3D修改CAD的3D旋转中心        前面一篇文章讲述了2D旋转功能的实现,文章提到了修改3D旋转中心,这一节主要总结一下具体的修改3D旋转 ...

随机推荐

  1. 【转载】zookeeper数据模型

    [转载请注明作者和原文链接,  如有谬误, 欢迎在评论中指正. ] ZooKeeper的数据结构, 与普通的文件系统极为类似. 见下图: 图片引用自developerworks 图中的每个节点称为一个 ...

  2. php 转义html标签 反转html标签 符号

    $a = '<strong>123</strong>';     //假设这是html代码$b =  htmlspecialchars($a);          //将< ...

  3. 【2024】求X到Y之间的整数和

    Time Limit: 3 second Memory Limit: 2 MB [问题描述] 计算X到Y之间的整数和(要求用函数实现).注意输入时X不一定小于Y,且X.Y不一定都是整数. [输入] 两 ...

  4. SharedPreferences基础 分类: H1_ANDROID 2013-11-04 22:35 2559人阅读 评论(0) 收藏

    见归档项目:SharedPreferencesDemo.zip 1.对于数据量较小,且有明显的K-V形式的数据而言,适合用SharedPreferences保存.SharedPreferences的数 ...

  5. 探讨jsp相对路径和绝对路径

    原文链接:http://blog.csdn.net/qq_37936542/article/details/79076768 问题:当在jsp使用相对路径引入其他js文件的时候,通过浏览器访问该页面一 ...

  6. 【t058】拜年

    Time Limit: 1 second Memory Limit: 128 MB [问题描述] 拜年是中国人少不了的风俗.还没过年呢,刚上小学的妮妮已经等不及要给她的小伙伴去拜年了,但是她不知道如何 ...

  7. 具体分析contrex-A9的汇编代码__switch_to(进程切换)

    //函数原型:版本号linux-3.0.8 struct task_struct *__switch_to(structtask_struct *, struct thread_info *, str ...

  8. android之ContentProvider和Uri具体解释

    一.使用ContentProvider(内容提供者)共享数据 在android中ContentProvider的作用是对外共享数据,就是说能够通过ContentProvider把应用中的数据共享给其它 ...

  9. JavaScript调用ATL COM(二)

    作者:朱金灿 来源:http://blog.csdn.net/clever101 在上篇文章中介绍了如何在JS中调用ATL COM: JS调用ATL COM中的C++接口的做法 现在我们可以把它嵌入到 ...

  10. 关于使用Timer定时监测网络是否ping通

    项目需要连接某台具体服务端,如果连不上则实时提示,开始使用Timer实时检测 void timer_Tick(object sender, EventArgs e) { Ping pingSender ...