• Create Account

We're offering banner ads on our site from just \$5!

# Transform

Old topic!
Guest, the last post of this topic is over 60 days old and at this point you may not reply in this topic. If you wish to continue this conversation start a new topic.

11 replies to this topic

### #1granberg  Members   -  Reputation: 56

Like
0Likes
Like

Posted 09 September 2011 - 01:01 AM

Hi guys,could you give me a hand ,now I trapped in the XNA transform problem,I write a simply demo about a helicopter fly with a propeller and rotor,now the problem is I'm going to change the Y value of the helicopter also change the propeller and rotor,after I done it,the strage thing appear rotor and propeller didn't fowllow the direction
of helicoper,even the rotor is far away from helicopter!How could I do?

### #2SuperVGA  Members   -  Reputation: 1118

Like
0Likes
Like

Posted 09 September 2011 - 01:29 AM

Try this (pseudo code, trick works for OpenGL and DX8 as i remember it, probably does for XNA too)

DrawHelicopter()
{
DrawHull
DrawPropeller
Transform(Rotate)
PushMatrix
DrawRotator
PopMatrix
}

Render()
{
Transform(Translate)
PushMatrix
DrawHelicopter()
PopMatrix
}


### #3granberg  Members   -  Reputation: 56

Like
0Likes
Like

Posted 09 September 2011 - 05:36 AM

I can't understand popMatrix and pushMatrix,but now I can show my code,could you check the error for me

private void DrawRotor()
{
Vector3 RotorPosition = new Vector3(airplanePosition.X +0.7f - 0.2f + 0.25f, airplanePosition.Y - 0.3f , airplanePosition.Z + 0.4f); ;
Matrix RotorTranslation, world, scale, rotationZ, OrbitTranslation, OrbitRotateY;
scale = Matrix.CreateScale(0.3f, 0.7f, 0.0f);
OrbitRotateY = Matrix.CreateRotationY(RotationAngle() - 0.04f);
rotationZ = Matrix.CreateRotationZ(propellerSpin);
OrbitTranslation = Matrix.CreateTranslation(1.04f , 0.0f, 0.2f);
RotorTranslation = Matrix.CreateTranslation(RotorPosition);
world = scale * rotationZ * OrbitTranslation * OrbitRotateY * RotorTranslation;
// world = scale * rotationZ * RotorTranslation;
positionColorEffectWVP.SetValue(world * cam.viewMatrix
* cam.projectionMatrix);

// 5: draw object - primitive type, vertices, # of primitives

RotorPosition = new Vector3(airplanePosition.X + 0.7f - 0.2f + 0.22f, airplanePosition.Y + 0.3f, airplanePosition.Z);
RotorTranslation = Matrix.CreateTranslation(RotorPosition);
OrbitTranslation = Matrix.CreateTranslation(1.17f, 0.0f, 0.0f);
OrbitRotateY = Matrix.CreateRotationY(RotationAngle() + 0.04f);
world = scale * rotationZ * OrbitTranslation * OrbitRotateY * RotorTranslation;
// world = scale * rotationZ * OrbitRotateY * RotorTranslation;
positionColorEffectWVP.SetValue(world * cam.viewMatrix
* cam.projectionMatrix);

// 5: draw object - primitive type, vertices, # of primitives
}
rotor sometime sideways from airplane.

### #4SuperVGA  Members   -  Reputation: 1118

Like
0Likes
Like

Posted 09 September 2011 - 06:45 AM

PushMatrix pushes the transformation stack, telling that all the following transformations will happen together, and not affect the previously transformed vertices.
PopMatrix pops the stack. Back to the level above. Or below, depending on how you see it. Towards the root level.

### #5granberg  Members   -  Reputation: 56

Like
0Likes
Like

Posted 09 September 2011 - 08:58 AM

still doesn't make sence,I just think the peoblem is within that function show to you,you should check that code for the result.

### #6granberg  Members   -  Reputation: 56

Like
0Likes
Like

Posted 09 September 2011 - 09:20 AM

Hi guys,I think you shoud consider the code I was telling you,because the rotor and propeller always sideway control by this section of code.

### #7SuperVGA  Members   -  Reputation: 1118

Like
0Likes
Like

Posted 09 September 2011 - 10:04 AM

I'm not experienced with XNA. Can you point out the places in the code where you actually perform draw calls?

### #8granberg  Members   -  Reputation: 56

Like
0Likes
Like

Posted 09 September 2011 - 10:45 AM

positionColorEffectWVP.SetValue(world * cam.viewMatrix
* cam.projectionMatrix);

// 5: draw object - primitive type, vertices, # of primitives
two calls darw the primitive

### #9GGulati  Members   -  Reputation: 109

Like
0Likes
Like

Posted 22 September 2011 - 10:17 PM

So one of your problems is that rotor position is a direct offset from the plane.

Imagine your helicopter has three transform matrices: Scale, Rotate (for what direction it's facing), Translate (from the origin)
Imagine your rotor has two transform matrices: Scale, Rotate (for the degrees it's spun), Translate (to translate it from the helicopter body)

So your final transform matrix for the helicopter is: Helicopter.Transform = Helicopter.Scale * Helicopter.Rotate * Helicopter.Translate
But for the rotor, you have to apply the helicopter's matrices as well so that its offset from the helicopter properly: Rotor.Transform = Rotor.Scale * Rotor.Rotate * Rotor.Translate * Helicopter.Rotate + Matrix.CreateTranslation(Vector3.Transform(Vector3.Zero, Helicopter.Transform))
You multiply the rotor's transform matrix by Helicopter.Rotate so that the rotor will be angled properly against the fin rather than, say, be perpendicular to the fin since the user rotated the helicopter 90 degrees to the right. You then basically add the helicopter's position to the rotor's position so that the rotor isn't floating at (0,0) when the helicopter is at (30, 5) and rotated 10 degrees in the yaw.

Maybe this will fix your code? It's just off the top of my head.

### #10Starnick  Members   -  Reputation: 1232

Like
0Likes
Like

Posted 23 September 2011 - 03:04 AM

In addition to GGulati's explanation, you can represent (logically, or in your code) the helicopter cockpit and its rotor(s) as a transform hierarchy of the transforms he describes. Your rotors will be spinning in a certain direction, and at a certain speed that should not affect the helicopter cockpit at all. However, the rotor positions in world space have to be rigid to the cockpit, e.g. the helicopter goes up, the rotors spin but are translated up accordingly. Each piece, therefore, maintains its own "local" transform - the cockpit probably is centered at the origin, but the main rotor is translated some units up the y-axis and so on. Then when you're updating the scene, you combine these local transforms into a final world transform for each piece of geometry.

For example, from my own code organization:

1. Each geometry has a local/world Transform, where a Transform is comprised of a Vector3 for Scale, a Quaternion for Rotation, and a Vector3 for Translation. You can of course use a rotation matrix rather than a quaternion, or keep three matrices for each component - but I tend to shy away from matrices.

2. The scene is organized with parent-child relationships. So the cockpit would be a parent, and the two rotors would be children (they have a reference to their parent and vice versa).

3. Every Update() call on the scene, each child combines their local transform with their parent's world transform:

Cockpit - No parent, simply uses its local Transform as its world transform.

Rotors - Parent is the cockpit, so their locals are combined with the cockpit's world transform.

The actual combination code looks something like this:


private Vector3 _scale;
private Quaterion _rotation;
private Vector3 _translation;
private bool _cacheRefresh;
private Matrix _cachedMatrix;

...

//Combines the components into a matrix
public Matrix Matrix {
get {
if(_cacheRefresh) {
Matrix scaleM;
Matrix rotationM;
Matrix translationM;

Matrix.FromScale(ref _scale, out scaleM);
Matrix.FromQuaternion(ref _rotation, out rotationM);
Matrix.FromTranslation(ref _translation, out translationM);

_cachedMatrix = scaleM * rotationM * translationM;
_cacheRefresh = false;
}

return _cachedMatrix;
}
}

public void CombineWithParent(Transform parent) {
//Multiply scaling
Vector3.Multiply(ref parent._scale, ref _scale, out _scale);

//Multiply rotation
Quaternion.Multiply(ref parent._rotation, ref _rotation, out _rotation);

//Combine translation
Vector3.Multiply(ref _translation, ref parent._scale, out _translation);
Vector3.Transform(ref _translation, ref parent._rotation, out _translation);
Vector3.Add(ref _translation, ref parent._translation, out _translation);

_cacheRefresh = true;
}


The (world) transform class I use has a matrix property which would then be used in with your view/projection matrices when setting the world-view-projection to the effect you're using. I cache that matrix too, so it's only computed once unless if any of the individual components change. Likewise, my scene management only updates world transforms if a scene object's transform has changed to reduce redundant computations. For example, the cockpit's transform may not change, but the rotor's rotation will, so only the world matrix is recomputed for the rotor and not for the cockpit. If the cockpit's transform changed, both would need to be updated. (Basically update any scene object, and any other objects it would influence - so children).

I mention this because your DrawRotor() could be made a lot simpler where each geometry has its own transforms, that get compiled to a world matrix in some general function like I posted above, making it easy to add new objects to Render, since you may only need to change a few transform properties without having to re-write the same sort of code. Also, you can reduce computations for parts of your models that don't actually move in a frame.

Starnick

### #11granberg  Members   -  Reputation: 56

Like
0Likes
Like

Posted 23 September 2011 - 10:59 AM

Could someone draw a easily understand figures of how to transform the rotor to me,my imagination is not very clear,thanks!

### #12NEXUSKill  Members   -  Reputation: 462

Like
0Likes
Like

Posted 21 June 2012 - 07:34 AM

Granberg, look up NESTED TRANSFORMATION.

This is what you need.
The concept being, you have a world, with its coordinate space (positions relative to a zero point and arbitrary orientations of Up, Right and Forward), when you send stuff to be rendered, the graphics system uses your models transformations as well as the point of view (or camera transformation) to take that world to the coordinate space of the screen,

When the position of one model is relative to another, in this case the rotor is relative to the chopper, for this to be represented the rotor must not be in the world's coordinate space, but in that of the chopper, so the transformation of the rotor needs to first be applied that of the chopper before you send it to the graphics system.
Seriously look up nested transformations, once you understand it, it will make your life easy.
Game making is godlike