WPF中的3D-2D转换问题 [英] Problem with 3D-2D conversion in WPF

查看:86
本文介绍了WPF中的3D-2D转换问题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

大家好
我的WPF应用程序出现问题.
我有一个Viewport3D,在运行时在其中添加了一些3D对象.我有一个Canvas,其中包含已构建的3D对象的名称(TextBlock或Label).因此,使用3DTools,我可以旋转,移动和缩放摄像机,并且正确显示了3D对象(在Canvas上)的所有名称,并位于3D对象所在的位置(在Viewport3D上).换句话说,一切正常,但是只有一个问题:当某些3D对象位于相机的背面(我们看不到它们)时,它们的名称始终显示在画布上,因此换句话说-我们看不到3D对象,但可以看到它们的名称.
(注意:仅当我沿Z轴前后移动相机时,才会发生这种情况.如果我沿X轴和Y轴移动相机,一切都会按预期进行)

任何决定如何解决这种情况?也许我从3D转换为2D(并反转)的功能不正确?
希望您理解我的问题,但是如果您需要一些代码片段或屏幕截图,我可以提供.


[更新]

我不知道如何在这里添加一些应用程序,所以我添加了一些图像.希望这会有所帮助:

3D对象在相机的前面.一切都很好
http://imageshack.us/photo/my-images/717/19999718.gif [ ^ ]

然后我将相机向前移动.
一些名称为badName#的3D对象位于相机的后面,但它们的名称却不在,我们看不到3D对象,但可以看到它们的名称!其他物体仍在相机前面(可以).

http://imageshack.us/photo/my-images/824/65567950.gif [ ^ ]

2D到3D转换和反向的代码:

Hi everyone
I''ve got a problem with my WPF application.
I have a Viewport3D where I add some 3D objects in runtime. I have a Canvas which contains the names (TextBlock or Label) of built 3D object. So using 3DTools, I can rotate, move and zoom a camera and all names of the 3D objects (on the Canvas) are shown correctly and are situated where 3D objects are situated (on the Viewport3D). In other words everything works fine, but there is just one problem: when some 3D objects are situated on the back side of the camera (we cannot see them) their names are shown on the Canvas anyway, so in other words - we cannot see the 3D objects but we can see their names.
(Note: this happens only if I move the camera by axis Z - back and forward. If I move the camera by axises X and Y everything works how it''s expected)

Any decisions how can fix this situation? Maybe I my function for converting from 3D to 2D (and revers) is not correct ?
Hope u understood my problem, but if u need some code snippets or screenshots I can provide.


[UPDATED]

i dont know how to add some appl here so I added some images. Hope this helps:

The 3D objects are in front of the camera. Everything is fine
http://imageshack.us/photo/my-images/717/19999718.gif[^]

Then I move the camera forward.
The some 3D objects with names: badName# are behind of the camera but their names are not and we cannot see the 3D objects but we can see their names ! Other objects are still in front of the camera (here is ok).

http://imageshack.us/photo/my-images/824/65567950.gif[^]

The code of the 2D to 3D conversion and reverse:

public static Point3D Convert2DPoint(Point pointToConvert, Visual3D sphere, TranslateTransform3D cameraPosition)        // transform world matrix
        {
            bool success = true;
            Viewport3DVisual viewport;
            Matrix3D screenTransform = TryTransformTo2DAncestor(sphere, out viewport, out success);
            Point3D pointInWorld = new Point3D();
            if (screenTransform.HasInverse)
            {
                Matrix3D reverseTransform = screenTransform;
                reverseTransform.Invert();
                Point3D pointOnScreen = new Point3D(pointToConvert.X, pointToConvert.Y, 1);
                pointInWorld = reverseTransform.Transform(pointOnScreen);
                pointInWorld = new Point3D(((pointInWorld.X + cameraPosition.OffsetX) / 2),
                                            ((pointInWorld.Y + cameraPosition.OffsetY) / 2),
                                            ((pointInWorld.Z + cameraPosition.OffsetZ) / 2));
            }
            return pointInWorld;
        }
        public static Point Convert3DPoint(Point3D p3d, Viewport3D vp)
        {
            bool TransformationResultOK;
            Viewport3DVisual vp3Dv = VisualTreeHelper.GetParent(vp.Children[0]) as Viewport3DVisual;
            Matrix3D m = TryWorldToViewportTransform(vp3Dv, out TransformationResultOK);
            if (!TransformationResultOK) return new Point(0, 0);
            Point3D pb = m.Transform(p3d);
            Point p2d = new Point(pb.X, pb.Y);
            return p2d;
        }



使用这些方法的类有440行代码(著名3DTools的MathUtils类),因此,如果您需要其他方法,可以在此处粘贴.

如果移动了3D对象或摄影机",则如何在此处将TextBlocks放置在画布上:



The class with these methods has 440 lines of code (class MathUtils from well-known 3DTools), so if u need the other methods I can paste them here.

Here how I position TextBlocks on the Canvas if the 3D objects or the Camera were moved:

public override void MoveCanvas(Viewport3D viewport)
        {
            try
            {
                Point point2D = MathUtils.Convert3DPoint((Point3D)Position, viewport);
                Canvas.SetTop(nameInCanvas, point2D.Y - 20);
                Canvas.SetLeft(nameInCanvas, point2D.X - 20);

                Canvas.SetTop(valueInCanvas, point2D.Y);
                Canvas.SetLeft(valueInCanvas, point2D.X);
            }
            catch { }
        }

推荐答案

在您的计算中,您对画布点使用了一些线性坐标变换.至少,在您的代码上看起来如此.线性变换原则上不能处理不可见对象的情况.什么,您是否希望TextBlock的实例从3D立场出发是不可见的(进入摄像机的后部)将自动超出摄像机的范围?不是这种情况.想象一下,您将摄像机直接移动通过3D对象.它应该首先填充视图的100%,然后在相机和物体之间的距离变为负数时发生的奇异性消失.这种奇异性原则上不能用线性方程式描述.如果仅检查对象与摄像机之间的距离(摄像机传感器可能被认为大小为零)并在对象为零或更小时隐藏对象,则将发生非线性行为.对象跳转"的可见性为零,这与广义的theta函数相似(解释很长话,维基百科甚至不存在,请参阅Dirac delta函数,它是一个完整的分支或数学函数).用离散计算词,您只需将对象隐藏在摄像机后面.这是一种非线性行为,您甚至都不会尝试为您的2D投影"实现,这毕竟不是真正的投影:文本不会根据距离进行缩放.

只是一个主意:

无论如何,画布上的2D对象(例如TextBlockLabel的实例)都不令人满意.例如,当您将3D对象(您​​的球或行星或类似物体)移入和移出相机视图时,它们无法正确缩放.为什么不将标签变成真实的3D对象,然后将它们全部放在一起并通过同一Viewport3D进行查看,而不是动手做呢?

它看起来更复杂(实际上),但实际上看起来更容易实现,并且效果更好.您可以分别开发和调试此类3D文本对象,并在完全调试后将其添加到项目中.之后,WPF 3D机制将确保您的文本对象将正确显示.

替代方案:

进行自己的3D模型和投影计算,并在2D画布和视口中显示一切,所有对象.这是完全有可能的.当您的所有形状都恒定时,这很容易.您可以在矢量编辑器中绘制形状并将其另存为XAML,将XAML图像包括在资源字典中并重复使用.这样的预测将得到简化;您将只能使用缩放.为此,理想的矢量编辑器应该是免费的(GNU)InkScape( http://en.wikipedia.org/wiki/Inkscape [ ^ ],http://www.inkscape.org/ [ ^ ]),它可与SVG( http://en.wikipedia.org/wiki/Scalable_Vector_Graphics 一起使用> [ ^ ]),并且可以完美地导出到XAML.

—SA
In your calculation, you use some linear coordinate transform for point of canvas. At least, it looks so on your code. The linear transform cannot handle the situation with invisible object in principle. What, did you hope that the instance of TextBlock supposed to be invisible from the 3D stand point (in would go to back of the camera) would automatically go outside of the bounds of the camera? This is not the case. Imagine you move you camera straight through the 3D object. It should first fill 100% of the view and then disappear in a singularity taking place at the moment when distance between the camera and the object became negative. Such singularity cannot be described by linear equations in principle. The non-linear behavior takes place if you simply check the distance between object and the camera (camera sensor is probable considered to be of zero size) and hide the object when it is zero or less. The visibility of object "jump" to zero, which is similar to a generalized theta-function (explaining it would long story, it is even absent from Wikipedia, see Dirac delta function, it''s a whole branch or mathematics). In discrete computing word, you simply hide the objects behind the camera. This is non-linear behavior you don''t even try to implement for your 2D "projection", which is not a real projection anyway: the text is not scaled depending on distance.

Just an idea:

Your 2D object on canvas, such as your instances of TextBlock or Label are not satisfactory anyway. For example, they do not scale properly as you move a 3D object (your ball or planet or what is that) in and out of camera view. Instead of doing your tricks, why not making your labels real 3D object and place them all together and view through the same Viewport3D?

It looks more complex (it is) but in reality it may appear easier to achieve, with better results. You can develop and debug such 3D text object separately and add to the project when it is fully debugged. After that, WPF 3D mechanism will guarantee your text objects would be shown correctly.

Alternative idea:

Make your own 3D model and projection calculation and show everything, all your objects in 2D canvas and view port. This is quite possible. It''s easy when all your shapes are constant. You can draw your shape in vector editors and save as XAML, include XAML images in resource dictionary and reuse. Such projections would be simplified; you would only be able to use scaling. The ideal vector editor for this purpose would be free (GNU) InkScape (http://en.wikipedia.org/wiki/Inkscape[^], http://www.inkscape.org/[^]), it works with SVG (http://en.wikipedia.org/wiki/Scalable_Vector_Graphics[^]) and can perfectly export to XAML.

—SA


我从未见过这样的事情,也不知道会发生什么.因此,显示您的代码会有所帮助,但是您需要做一些出色的工作才能显示它.请不要显示您的所有代码,也不要显示我们不会构建的任何代码.您需要创建最简单的代码(例如,一个简单的对象,一台摄像机和摄像机的两个固定位置:看到对象时以及看到它的名称时),这些代码很容易构建和查看.有可能,寄生效应会消失.那已经是一个线索.您需要参加显示问题的最简单的演示.您可以在准备此类演示时找到解决方案.

—SA
I never saw such thing and never knew it could happen. So, showing your code would help, but you need to do some good job to show it. Please, don''t show all of your code, but also don''t show any code which we won''t build. You need to create simplest possible code (let''s say, one simple object, one camera and two fixed positions of the camera: when it sees the object and when it sees its name) which is easy to build and review. Chances are, the parasitic effect will disappear. That would already be a clue. You need to come to the simplest demo where the problem is manifested. You have a chance to find a resolution while preparing such demo.

—SA


这篇关于WPF中的3D-2D转换问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆