-
|
|
|
Hello,
I am newbie at Xna (but I have some experience in MDX and some other third party 3D Engines) and I want to ask some questions about the technology.
Primary goal of my applications built with Xna would not be classic 3D games but windows applications that primary visualize real world data through Xna, with some limited level of interactivity.
I have done some this before with MDX, some basic stuff and all, but I would like to switch to Xna for several reasons.
Is there any helper classes in Xna for creating basic primitives such as box, sphere, cylinder or it is created similar to MDX by creating series of vertices?
Also, I want to ask about a general approach how some things are accomplished:
I would like to use a example world like described below.
We have world which is consisted of cities. Each city is consisted of houses.
Each house is consisted of one or more rooms. Each room has furniture inside, for example shelves.
On each shelve we have some objects like books, vases, flowers, etc...
I would like to manage location, rotation and scale of each of these items on a hierarchical level rather than on absolute level.
This means that only location, scale and rotation of each city is given in a absolute world coordinate and everything else relative to it's parent.
Location of each house is given by it's location inside the parent city, not the absolute world location.
Also, the location of room is given relative to parent house, location of shelve is given relative to parent room and so on...
So, when I move the house to some location, all of the objects inside are also displayed on that location,
and if I rotate or scale the house same applies to child objects.
I have tried to apply this approach in MDX but I had some problems so I switched back to absolute position, rotation and scale of all objects
because the scene was fairly simple with not much hierarchy. My goal is to achieve this with Xna and this kind of approach would be mandatory - from my point of view, I only see and work with data relative to parent.
For Xna and MDX, I have not found much on this topic, the examples are generally simple and use absolute world coordinates so they are not much of an help.
So, my question is how is this kind of approach generally achieved using Xna, some custom 3D game engines or in theory?
Is there any examples and guidelines for this? Is this a good or bad approach?
Is there any hidden obstacles I should be aware of? What are the drawbacks?
What are the points in application where the translate, rotate and scale operations together with any other operations or calculations should take place?
Cheers!
|
|
-
|
|
|
I'm not sure exactly what your question is, but I've thrown together a working class that you can maybe experiment with.
Maybe I completely missed the mark, eh?
As for helper classes to make primitives, why not just load pre-modeled primitives and just draw those. I know you get into optimization issues and so forth, but maybe your scope is small enough such that you can just brute force the draw calls?
The following class is very basic, and you'd probably want some culling & to get what you need...
| using System; |
| using System.Collections.Generic; |
| using System.IO; |
| |
| using Microsoft.Xna.Framework; |
| using Microsoft.Xna.Framework.Audio; |
| using Microsoft.Xna.Framework.Content; |
| using Microsoft.Xna.Framework.GamerServices; |
| using Microsoft.Xna.Framework.Graphics; |
| using Microsoft.Xna.Framework.Input; |
| using Microsoft.Xna.Framework.Media; |
| using Microsoft.Xna.Framework.Net; |
| using Microsoft.Xna.Framework.Storage; |
| |
| namespace World |
| { |
| /// <summary> |
| /// Create a renderable 3D object with a parent (not necessarily) and many children. |
| /// </summary> |
| class Renderable |
| { |
| /// <summary> |
| /// This object's parent. |
| /// </summary> |
| Renderable Parent; |
| |
| /// <summary> |
| /// This object's children. |
| /// </summary> |
| List<Renderable> Children; |
| |
| /// <summary> |
| /// The model of this object. |
| /// </summary> |
| Model Model; |
| |
| /// <summary> |
| /// Recursive function that will get the absolute transform. |
| /// </summary> |
| public Matrix AbsoluteTransform |
| { |
| get |
| { |
| if (Parent != null) |
| return Transform * Parent.AbsoluteTransform; |
| else |
| return Transform; |
| } |
| } |
| |
| /// <summary> |
| /// The transform relative to the parent of this object. |
| /// </summary> |
| Matrix Transform; |
| |
| /// <summary> |
| /// Create a new object in the world with the specified model, relative transform and parent. If |
| /// the parent is null, then the object is assumed to be the root of it all. |
| /// </summary> |
| /// <param name="model">The model of the object.</param> |
| /// <param name="parent">The parent of the object.</param> |
| /// <param name="transform">The relative transform of the object.</param> |
| public Renderable(Model model, Renderable parent, Matrix transform) |
| { |
| Model = model; |
| Parent = parent; |
| Transform = transform; |
| |
| // If this isnt the root object, then add it to the heirarchy |
| if (parent != null) |
| parent.Children.Add(this); |
| } |
| |
| /// <summary> |
| /// Draw the object and its children. |
| /// </summary> |
| /// <param name="view">The view matrix of the camera.</param> |
| /// <param name="projection">The projection matrix of the camera.</param> |
| public void Draw(Matrix view, Matrix projection) |
| { |
| // Just draw the model with some very inefficient drawing code |
| Matrix[] transforms = new Matrix[Model.Bones.Count]; |
| Model.CopyAbsoluteBoneTransformsTo(transforms); |
| |
| foreach (ModelMesh mesh in Model.Meshes) |
| { |
| foreach (BasicEffect effect in mesh.Effects) |
| { |
| effect.EnableDefaultLighting(); |
| effect.World = transforms[mesh.ParentBone.Index] * AbsoluteTransform; |
| effect.View = view; |
| effect.Projection = projection; |
| } |
| mesh.Draw(); |
| } |
| |
| // Draw all the children |
| foreach (Renderable Child in Children) |
| Child.Draw(view, projection); |
| } |
| } |
| } |
Madness? This is SUNSHINE.
|
|
-
|
|
|
As for drawing primitive cubes, spheres, and cylinders, a sample project was recently added to the site for doing this:
http://creators.xna.com/en-US/sample/primitives3D
As for hidden obstacles, the only issues I potentially see are that, in the case of a city, you might have a large number of objects, so you might want to consider doing some sort of quad-tree or oct-tree implementation to limit the objects which are drawn to those that are actually within the camera's view. This could potentially boost your performance. You might also want some sort of algorithm to prevent the drawing of objects inside of buildings when the camera is outside of the buildings and these objects would not be visible anyway.
|
|
-
-
- (8307)
-
premium membership
MVP
-
Posts
6,143
|
|
In general, the best way to create "primitives" is to simply model them in a modeling application (like 3ds Max or XSI Mod Tool) and export them. Then, when you need a sphere, simply Content.Load<Model>("shapes/sphere"). If you make them with a known size (say, 1 m diameter), you can apply a scale to get them the size you want.
Jon Watte, Direct3D MVP Tweets, occasionallykW X-port 3ds Max .X exporter kW Animation source code
|
|
-
|
|
|
Thanks for the answers!
As I have understood, to achieve relative-to-parent transformations for some object, I need to multiply all transformation matrices starting from that object and going up through all of it's parents?
My question is also this - If I wish to perform all of the transformations (translate, scale and rotate) is there any specific order in which every transformation is applied - Does it make a difference
if I make translation, then the scale and then the rotation or there is a general rule in which order to apply these transforms?
And what if some of the parent objects have also these transformations, will it work correctly when I multiply transformation matrices as described in first question?
Also, I want to ask what coordinates should I use if I need the object picking or simple collision detection functionality.
Should I calculate absolute position of every object before performing hit-tests or some other operations or there is some other common way how this should be done?
Cheers!
|
|
-
|
|
|
Yes the order of matrices matters. It would be:
Child - Rotation then Translation
Parent - Rotation then Translation
Next Parent - Rotation then Translation
... and so on.
Remember that the rotation angles and translation coordinates are all values that are relative to the immediate parent. They are not absolute world values.
You might be able to use an event system such that matrices at each node are only updated if there is an actual change to that node's position relative to its parent. If there is no change, you can just store the previously generated matrix for a given node and re-use it without having to recalculate it on every frame.
The correct absolute position of objects will need to be calculated in order to perform hit tests. You should probably organize your code such that all of the necessary matrices are only calculated once per frame, such that the matrices can be used both for drawing and hit testing.
|
|
|