-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
When Ron says create the cabinet at 000, imagine that the center of the cabinet, when you build it, is at 000. So, the left panel would be at -X something, the right panel at +X something, the top at +Y something, the bottom at -Y something.
Once those are in place, as if the model was centered over 000 you can then rotate the entire set and place the entire set at once.
I've got your project, will give it a lookover shortly,
Best,
Byron
..shaders make you feel... powerful, or very very stupid. http://drjbn.spaces.live.com/
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
Ben Andersen:Create two transformation matrices, one to transform the components of the structure to their relative position and rotations, and one to place and rotate the structure Globally.
The transformation for any piece of the structure is then Relative * Global
Each transform would be made of a rotation matrix * translation matrix.
2 transformation matrices, this now is another idea to solve this particular problem, it souds like the way to go, cause NED Gold also recommended creating two transforms one local and one global. I ask now how could that be done?
This whole thing seems like it requires one full week from me to learn about local-global transformations in xna, you must admit this issue is not trivial for anyone to get their head around (unless they are super smart, which I'm not)
To Ned : thanks for the corrections it's better now, but Cabrotation = 45 (or any value) dont do any rotations to the cabinet, it just keeps rotating on its Y axis unrealistically, a cabinet does not rotate on its own.
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
mysdn:
To Ned : thanks for the corrections it's better now, but Cabrotation = 45 (or any value) dont do any rotations to the cabinet, it just keeps rotating on its Y axis unrealistically, a cabinet does not rotate on its own.
I put the spinning cabinet in there to show you that everything moves together as it should. To remove the spinning aspect, just remove the code I put in the Update section. FYI, I added //NED Gold to all the places I made changes to in your code.
-Ron XNA Neophyte
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
Once you get each piece placed relative to each other using your position variables, you put those into a transform matrix to move them in the draw. Once you get them placed correctly relative to each other as if the cabinet was centered at 000 (which is what I suspect Ned changed in your code), and get it rotated how you want it, then multiply by another transform matrix with the position there being where you want the whole box to be in your scene.
best,
Byron
..shaders make you feel... powerful, or very very stupid. http://drjbn.spaces.live.com/
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
Byron Nelson:Once you get each piece placed relative to each other using your position variables, you put those into a transform matrix to move them in the draw. Once you get them placed correctly relative to each other as if the cabinet was centered at 000 (which is what I suspect Ned changed in your code), and get it rotated how you want it, then multiply by another transform matrix with the position there being where you want the whole box to be in your scene.
BINGO, NED nailed it, you confirm it, I applied and it worked, it works. Thank you guys very much. I have 2 more concerns though.
1- here , would line 1 and 3 (Width, Height issue) taken into account for final positioning have any adverse affects? eg. wrong positioning
cause If I dont add half width or height model positions that much off
SceneViewerControl.m_moveTo[i].X = (int)Node_Built.GlobalBounds.Left + (Node_Built.Width/ 2);
SceneViewerControl.m_moveTo[i].Y = (int)Node_Built.OC_M_YerdenAlt;
SceneViewerControl.m_moveTo[i].Z = (int)Node_Built.GlobalBounds.Top + (Node_Built.Height / 2);
2- according to below method , how would we open the door to any angle we want?
private void Construct_Door()//cabinet door
{
i = SceneViewerControl.modelCount;
//scale
SceneViewerControl.m_scale[i].X = (Node_Built.Width - 1f) * 0.01f;
SceneViewerControl.m_scale[i].Y = (Node_Built.OC_M_Yuks - 1f) * 0.01f;
SceneViewerControl.m_scale[i].Z = 1f;//Node_Built.Height * 0.01f;
//rotate , this rotate rotates the door with the case, not independently, am I wrong?
SceneViewerControl.m_rotations[i].X = -Node_Built.GlobalRotation;
SceneViewerControl.m_rotations[i].Y = 0;
SceneViewerControl.m_rotations[i].Z = 0f;
//create node
SceneViewerControl.m_position[i].X = 0;
SceneViewerControl.m_position[i].Y = 0;
SceneViewerControl.m_position[i].Z = (int)+Node_Built.Height / 2;
//move to final position in the scene
SceneViewerControl.m_moveTo[i].X = (int)Node_Built.GlobalBounds.Left + (Node_Built.Width/ 2);
SceneViewerControl.m_moveTo[i].Y = (int)Node_Built.OC_M_YerdenAlt;
SceneViewerControl.m_moveTo[i].Z = (int)Node_Built.GlobalBounds.Top + (Node_Built.Height / 2);
SceneViewerControl.m_model[i] = content.Load<Model>("model_4");
//texture
SceneViewerControl.m_texture[i] = content.Load<Texture2D>("texture");
SceneViewerControl.modelCount += 1;
}
Thanks a lot again, you guys are SUPER!!!!! I mean it.
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
I'm not clear on your first question, but I'll tackle the second one for you. Remember we were talking about setting the pivot point on your models in Max (via email) and I said to center the pivot on your models. Well, that advice makes it easy to later position your models when building your case, however for the special purpose of rotating a door it would complicate things. What you need to understand is that when you position your models, you are positioning the pivot point of that model. So if you have the pivot placed in the center of the door and rotate it, then the rotation occurs about that center. Rather than locate the door at 000 prior to placement, you would have to move it off-center by half the width and then rotate it to the desired open angle. Offset to the right for a left door or offset left for a right door (think of where the hinge will be). A slightly less complicated method is to create left and right doors in Max and have the pivot point already set along the proper hinge side. This would allow you to rotate the door to the desired angle prior to placement.
Note 1:
In an email to you, I gave you the wrong formula by accident, so I'd like to correct that here:
Matrix Order = Scale x Local Translation x Local Rotation x World Translation x World Rotation
To affect the door open angle, we want to use the Local Rotation matrix.
Note 2:
Recall that I had your cabinet spinning about the Y-axis in the code I sent you, however in the code I was actually manipulating the X axis variables. You (or someone) should look into why this is happening and get it fixed.
-Ron XNA Neophyte
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
N E D Gold:I'm not clear on your first question,
Ron, consider this scenario,
put 2 cabinets side by side, now change 2nd cabinets width and/or height , even though they were adjacent before size change, now 2nd cabinet looks off in , but in 2D graph they are touching sides as real cabinets do. This is because I use below code
//cabinet case created at
SceneViewerControl.m_position[i].X = 0f;//(int)Node_Built.GlobalBounds.Left + (Node_Built.Width / 2);
SceneViewerControl.m_position[i].Y = 0f;//(int)Node_Built.OC_M_YerdenAlt;
SceneViewerControl.m_position[i].Z = 0f;//(int)Node_Built.GlobalBounds.Top + (Node_Built.Height / 2);
//case moved to final position
SceneViewerControl.m_moveTo[i].X = (int)Node_Built.GlobalBounds.Left + (Node_Built.Width / 2);
SceneViewerControl.m_moveTo[i].Y = (int)Node_Built.OC_M_YerdenAlt;
SceneViewerControl.m_moveTo[i].Z = (int)Node_Built.GlobalBounds.Top + (Node_Built.Height / 2);
these (Node_Built.Width / 2); and (Node_Built.Height / 2); additions are causing the error I believe, what do you think?
as for door rotations I couldn't get it to work either, I tried positioning the door at different places. It's not that important to show opened door, but it's very important that I grasp the concept to do it. Without a firm grasp of translations in xna I guess I will always be at the mercy of others. Thank you for everything you do.
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
Still not clear, but I think you want to know how to place two cabinets side by side?
Let's say that the width of cabinet 1 is 20 units and cabinet 2 is 30 units.
Recall that when constructing the cabinet about 000, the left side would be placed at -width/2 and the right side at +width/2.
If we place the first cabinet at X=20, this moves the center of the cabinet to 20.
So this means that the right side is at 20 + width/2 = 20 + 10 = 30.
We want the second cabinets left side to touch the firsts right side, and the formula for right side is center - width/2 so..
30 = center - width /2
30 = center - 30/2
30 = center - 15
45 = center
so the second cabinets center will be at X=45. Repeat exercise for remaining Y and Z axises (or is it axes?)
-Ron XNA Neophyte
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
mysdn:
It's actually quite simple, the local transform matrix, contains the rotation and translation it will take to construct the object at the origin. The parts and their local transform would be like a definition of the object. Once you've put it in place at the origin, at it's default position, you then transform the parts again by the transform matrix that it would take to move the constructed object to it's position and rotation in 3d space.
Local = LocalRotation * LocalTranslation
Global = GlobalRotation * GlobalTranslation
Final = Local * Global
Rotation Matrices would be matrices created with Matrix.CreateFromQuaternion(QRotation)
QRotation would be some quaternion that describes the rotation of the object (the advantage of quaternions is that there is no gimble lock)
You could also just use a standard rotation matrix, made with one of the other matrix.CreateRotation* methods and a set of floats.
Translation Matrices would be matrices created with Matrix.CreateTranslation(float x, float y, float z)
It's not really THAT complex, but if you need any more explanation let me know.
Edit: Jumped the gun again, anyway, I'm just glad I was of some help. Good luck.
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
Ben Andersen:It's not really THAT complex, but if you need any more explanation let me know.
Ben, thank you for your help. Can you give me a sample code snippet of actually creating a box and and applying what you talk about in that sample code? I dont understand where (in Draw method or outside) to create, rotate and translate the box. What is the difference between local and global (rotation/translation)? How to tell one from the other? I am smart enough to build an application that sells for a thousand dollars but I am stupid enough not to comprehend all this without handholding.
I appreciate any help anyone offers anytime. Thank you.
this pic will explain my problem http://www.kitchendesigned.com/download/rotation.jpg
the code I use is, "note" the position translated to
------ OBJECT CREATION CODE
//scale
SceneViewerControl.m_scale[i].X = Node_Built.Width * 0.01f;//width
SceneViewerControl.m_scale[i].Y = Node_Built.OC_M_Yuks * 0.01f;//height
SceneViewerControl.m_scale[i].Z = (Node_Built.Height - 2) * 0.01f;//depth
//rotate
SceneViewerControl.m_rotations[i].X = -Node_Built.GlobalRotation;
SceneViewerControl.m_rotations[i].Y = 0f;
SceneViewerControl.m_rotations[i].Z = 0f;
//position created
SceneViewerControl.m_position[i].X = 0f;
SceneViewerControl.m_position[i].Y = 0f;
SceneViewerControl.m_position[i].Z = 0f;
//position translated to
SceneViewerControl.m_moveTo[i].X = (int)Node_Built.GlobalBounds.Left + (Node_Built.Width / 2);
SceneViewerControl.m_moveTo[i].Y = (int)Node_Built.OC_M_YerdenAlt;
SceneViewerControl.m_moveTo[i].Z = (int)Node_Built.GlobalBounds.Top + (Node_Built.Height / 2);
------------- DRAW METHOD
for (int i = 0; i < modelCount; i++)
{
if (modelCount == 0) return;//no model to draw
if (m_model[i] == null) continue;
Matrix world = Matrix.CreateScale(m_scale[i].X ,m_scale[i].Y ,m_scale[i].Z ) *
Matrix.CreateTranslation(m_position[i].X, m_position[i].Y, m_position[i].Z)*
Matrix.CreateFromYawPitchRoll(MathHelper.ToRadians(m_rotations[i].X),
MathHelper.ToRadians(m_rotations[i].Y),
MathHelper.ToRadians(m_rotations[i].Z));
// Look up the absolute bone transforms for this model.
boneTransforms = new Matrix[m_model[i].Bones.Count];
m_model[i].CopyAbsoluteBoneTransformsTo(boneTransforms);
// Draw the model.
foreach (ModelMesh mesh in m_model[i].Meshes)
{
foreach (BasicEffect effect in mesh.Effects)
{
effect.World = boneTransforms[mesh.ParentBone.Index] * world;
effect.View = view;
effect.Projection = projection;
effect.World *= Matrix.CreateTranslation(new Vector3(m_moveTo[i].X, m_moveTo[i].Y, m_moveTo[i].Z)); // N E D Gold
effect.EnableDefaultLighting();
//effect.PreferPerPixelLighting = true;//messes up FPS dont delete
effect.SpecularPower = 16;
effect.Texture = m_texture[i];
effect.TextureEnabled = true;
}
mesh.Draw();
}
}
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
Sorry for the lateness of my reply, I've been very busy lately, as such I'm afraid I can't give you real code for this. I can however explain it as well as I can in hopes that you can take the ideas and express them in code.
XNA has many utilities built in to aid the process.
First of all, your model components will need to be positioned and rotated to their relative locations with respect to the origin, these are the transformations that are required to simply build the object at the origin. Each part of the object would have it's relative transformation matrix = to a translation multiplied by a rotation matrix. the translation and rotation parameters here are for a specific part of the object, and putting it within the object at the right location and rotation.
relative = matrix.CreateTranslation(x, y, z) * matrix.CreatefromQuaternion(rotation);
Then you make a global transformation matrix which will take something at the origin, and rotate and translate it to where you want to the object to end up. and setting the global transform matrix is the same as the above only you make sure you use the translation and rotation parameters for the object as a whole to move it to where you want the object.
There really isn't anything else to it.
For each part of the object
local translate the part to it's position and rotation within the object (treating the origin as the center of the object)
global translate all parts within the object the position and rotation of the object.
That's it. There is nothing else to it.
EDIT: btw this has nothing to do with drawing, this is just positioning the parts within the game space. Once everything is in place, draw the scene as you would normally.
|
|
-
|
|
Re: combine multiple models at load time and rotate, translate as one
|
Ben, thank you very much for your effort at explanining this to me, actually I got my rotations 90% right by cheating (switching Width and Depth for different rotations in positioning calculations) For example if object (w=50, d=60)is 90 degrees rotated I consider its width as depth and if object is 0 rotated vice versa. but there is a glaring gap if objects are wider (or deeper ) than a regular cabinet's width (say 20 inches or 50cm). Of course with that cheating it's impossible to precisely place objects, let alone show cabinet doors opened, or draw walls at different angles other than 90-270-18-360 or 0.
I will try to produce actual working code from your suggestions, thanks again.
ibrahim dogan
|
|
|