Click here to Skip to main content
15,887,214 members
Please Sign up or sign in to vote.
4.00/5 (1 vote)
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;
        }


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:

C#
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 { }
        }
Posted
Updated 17-May-11 23:01pm
v10
Comments
Sergey Alexandrovich Kryukov 18-May-11 3:46am    
Abuse of the term "conversion" is something that haunts CodeProject right now. It looks like somebody infected everyone else; and not this is pandemic.

Convert 3D to 2D simply means projecting a 3D geometry on some 2D plane. In your case this is an imaginary camera "sensor".

So, what's the problem? You don't want to see the names, right? I never saw such situation though...
--SA
Shendor 18-May-11 4:11am    
Yes, convertion 3D to 2D projects a 3D geometry on a 2D plane, but you didn't notice just one thing - Z points become 0 in this case and therefore all, let's say, TextBlocks are shown on the Canvas regardless they are in front of the camera or not.
Ok, I'll add a sample soon
Sergey Alexandrovich Kryukov 18-May-11 4:18am    
No, I do understand about 0 coordinates, so what..? Wait, wait, are you saying some objects are TexBlock instances..? Anyway, good to see your sample.
--SA
Shendor 18-May-11 4:55am    
The 3D objects and TextBlocks are separated from each other and they are lying on the different layouts. For ex., when I move a 3D object I call method MoveCanvas() which sets new position (the position of the 3D object) for a name (TextBlock) in the Canvas but if I move the 3D object behind the camera it will disappear from my view but its name won't.
Sergey Alexandrovich Kryukov 18-May-11 11:13am    
After this explanation the situation seems natural to me.
Why do you think this is a problem? What would you like to see in rendered picture?

Well, you miscalculated the position of the TextBlocks in 3D? Do I understand it right? Are you trying to move canvas to match 2D positions to 3D? By the way, why do you talk about zero Z? The Z coordinate supposed to be negative, right?

You don't show the code where you use TextBlock. It looks like you show only the geometrical calculations; I still don't understand well how you apply them...
--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
 
Share this answer
 
Comments
Shendor 18-May-11 12:35pm    
Thx, I'll try use it according your idea.
Sergey Alexandrovich Kryukov 18-May-11 12:38pm    
Great. Thanks for accepting this answer.
Good luck, call again,
--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
 
Share this answer
 

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



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900