3D for the Rest of Us, Part 1: 3D Coordinate System


Introduction


A hallway conversation which Chris Anderson made me realize that when people ask me about 3D support in Avalon I have a bad habit of telling them everything they do not need to know.  After all, it is all the details you do not have to worry about that consume the waking hours of our 3D team (and it is what gives the Avalon 3D platform its value.)  However, despite our efforts to abstract the hardware, to encapsulate the mathematics, and to keep the 2D and 3D APIs symmetrical, there are some concepts which are inherently unique to 3D such as cameras and lighting.


This is the first in a series of posts intended to fill in the missing pieces for a developer familiar with a 2D graphics API who wants to dabble in 3D with the Avalon platform.  The topics I initially intend to cover are:



  • The 3D coordinate system
  • Transforms – (Part 2 now online)
  • The Camera
  • Defining 3D Geometry
  • Lighting
  • Materials

…but I am happy to adjust according to feedback.


The 3D Coordinate System


Most people are aware that 3D adds an extra dimension, Z, perpendicular to the X and Y they are familiar with from 2D.  The 3D coordinate system is frequently explained to 2D developers as follows:



  • The origin is now in the center of the screen instead of the upper left.
  • The positive X axis still points right, but Y now points up instead of down.
  • There is a new axis, Z, that points out of the screen (assuming a right handed coordinate system like Avalon).

This is expressed pictorially in figures 1 and 2 below:



The issue with this description is that while we can choose a camera orientation consistent with the above criteria (Figure 3) we can also choose vantage points like Figures 4 or even turn the camera upside down like Figure 5.










LookAtPoint=(0,0,0)
Position=(0,0,5)
Up=(0,1,0)

Figure 3

LookAtPoint=(0,0,0)
Position=(3,3,-3)
Up=(0,1,0)

Figure 4

LookAtPoint=(1,1,0)
Position=(3,3,-3)
Up=(0,-1,0)

Figure 5


The global frame of reference (aka World Space)


From Figures 3-5 hopefully the reader begins to get a sense that there exists a space created by the 3 perpendicular axes.  This space is commonly referred to as world space.  World space extends infinitely in both the positive and negative directions for all three axes.  In the above screenshots (Figures 3-5), the three axes always meet at (0,0,0) in world space (even though the location on the screen changes).  In world space, the model of the arrow labeled X extends along the positive X-axis <1,0,0>, the Y arrow along <0,1,0>, and the Z along <0,0,1>.  Again this is true in all three screenshots (Figures 3-5) even though the directions appear to change based on the camera orientation.


The point is, we can position our camera anywhere in world space and point it in any direction to generate images, but moving the camera does not change where things exist in world space.  World space is the stationary global frame of reference.  Since we are not focusing on positioning the camera this time around we will choose to adopt an orientation like Figure 6 (which was used to make the screenshot in Figure 3) for the remainder of this post. 



Local Frames of Reference (aka Model space)


The fact that I stated that world space is the global frame of reference implies that there are other frames of reference.  Each model object has a Transform property which we can use to move, size, orientate, etc. the model.  When we do this, we create a local frame of reference.  These local frames of references are commonly referred to as model spaces.  The concept of model spaces also exists in 2D, although we do not call them that.  Consider a canvas which contains a red rectangle defined to as (0,0)-(100,100) relative to the canvas:





Now consider Figure 8 which shows the canvas in relation to the screen.  Here we can see that while the rectangle exists in (0,0) – (100,100) relative to the canvas’ local frame of reference, it may actually occupy (50,50)-(150,150) on the screen.


In 3D, it is common practice to author your geometry centered about the origin like the teapot shown in Figure 9.
 









Figure 9

And then use the three basic transforms (translate, scale, and rotate) to position, size and orientate the model to where you want it in world space.  The Avalon 3D object model exposes these transforms as the TranslateTransform3D, ScaleTransform3D and RotateTransform3D classes.  Like the camera, we will touch on how to configure these transform classes in a future post.  The point we want to make this time is that just like in Figure 8 where when the canvas is moved the rectangle is still defined as (0,0)-(100,100), when you apply a transform to a model 3D you are transforming the space in which the model is defined rather than the positions of the points in the geometry.  This local frame of reference is called model space.










translate
Figure 10


translate & scale
Figure 11


translate, scale, and rotate
Figure 12

Figures 10 through 12 show the effects of the basic transforms when applied to our teapot model.  A second axis has been added to show the effect this has on the model space of the teapot.  In Figure 10 we can see that when we add a translation of <0.5, 0,5, 0.5> this moved the teapot up, right, and towards the viewer.  This also created a model space where (0,0,0) in the model space is equal to (0.5, 0.5, 0.5) in the global world space.


Similarly, Figure 11 illustrates that adding a uniform scale of 0.5 not only scales the teapot, but also scales the local model space in which the teapot resides.  Moving 1 unit in this model space moves 0.5 units in global space.  Finally Figure 12 shows that applying a rotation changes the orientation of the teapot and at the same time changes the orientation of model space.  Moving along the Z axis in figure 12, for example, causes a change in all of X, Y, and Z in world space.


The importance of model space will became more clear next time when we investigate the transforms and the Model3DCollection class which allows us to build hierarchies of model spaces that allow us to do things like take the cone and cylinder which make one of the arrows in the axes we have been seeing in the screenshots and treat them as one “arrow” model even though they are separate primitives.


Continue: Part 2 now online


Comments (27)

  1. Kieran Benton says:

    Great blog! I look forward to reading the rest of your articles. Incidentally, the camera is of particular interest to myself…

  2. Excellent post … I wonder what kind of support there will be for loading geometry authored in other environments. Is there at least .X loading functionality?

  3. sk says:

    What was the reason right handed system was chosen? Rendering performance?!

  4. danlehen says:

    Kieran – Thx for the feedback. I was planning to show how you can use transforms to move geometry in front of a stationary camera in my next post, then talk about setting up cameras in part 3.

    Joel – We are still working on our story for importing content from 3D tools into Avalon. We know we need to make this easy, we just do not know if the best approach is building support for specific 3D file formats into Avalon or relying on converts/exporters like this one (http://blogs.msdn.com/danlehen/archive/2004/06/11/154028.aspx). We would love to hear your thoughts.

    SK – I am glad you asked. There is no technical advantage. The decision came about by first deciding that while there have been many religious debates on LH vs. RH, the decision really is arbitrary. Most recent 3D platforms have been RH to be consistent with the majority of math and physics texts and we chose to follow the trend.

    A similar decision was made regarding row vs. column vectors where we chose not to follow the trend. Even though most recent graphics platforms choose column vectors we chose to stick with row vectors because we thought it was the right decision for our years of GDI+/DX customers who want to migrate their row vector based code to Avalon. It’s not my personal preference, but the motivation makes sense and so far all of the code I have written for samples, etc. uses our Transform classes so I haven’t had to think about it.

    RH vs. LH and row vs. column vectors are clearly religious arguments. However if you have an opinion I encourage you to express it. Finding out that 98% of our customers always use a LH camera when working in D3D would be very useful information to have. :)

  5. Well, the converters/exporters concept is great for when you want to hardcode a model into your application. But I am sure there will be situations where that would like to be dynamic.

    If I had my say, I would like to have at least .x loading functionality … and of course that could be exposed as a xaml tag in addition to an api call. But do it such that it is extensible (using the provider model for example) so people can author their own loaders and plug it right into the system.

    On the issue of lh vs rh … I say that as long as that is easily changed, it doesn’t matter. That being said, I’ve always used lh :-)

  6. You know what … I just came across your other post about using xaml as a persistence format. If there is already an existing way to load a model from a .xaml file, then that fulfills my requirement. Any model that I may have can simply be converted into a .xaml file for deployment.

    Thanks for all the updates … it’s great to get a behind the scenes peek at what’s coming up.

  7. Out of curiosity … Does avalon 3D transparently take care of optimizations such as culling unseen geometry?

  8. danlehen says:

    Joel – Being a retained scene graph oriented platform we have created the opportunity for us to do a lot of optimizations behind the scenes. However, our 3D support in build 4074 is still very immature in this regard. 2D is already culling geometry known to be off screen before it is even marshalled to the render thread.

    PS – Thanks for the feedback on file content importion / LH camera.

  9. flex-mx says:

    3D for the Rest of Us…

  10. Capo says:

    In mathematics, conventional 3D coordinate systems use y as the horizontal axis, z as the vertical axis, and x as the "depth" axis. Why wasn’t this convention used?

  11. kingsley says:

    I would love u to tutor me more on site building and making my site look superb.

  12. BCampney says:

    Excellent tutorial. This really brought home the details of using Avalon 3D transforms. I am much better prepared to work on my 3D projects! I am looking forward to the rest of the articles in this series.

  13. .Frenz says:

    Fandt lige et par grundl

  14. Two very interesting-looking articles about doing 3D in Avalon, 3D for the rest of us part 1 and part…