I meet are having difficulty in moving my camera behind an object in a 3D world. I would create two view mode.
1: for fps (first person).
2nd: external view behind the character (second person).
I searched the net some example but it does not work in my project.
Here is my code used to change view if F2 is pressed
//Camera
double X1 = this.camera.PositionX;
double X2 = this.player.Position.X;
double Z1 = this.camera.PositionZ;
double Z2 = this.player.Position.Z;
//Verify that the user must not let the press F2
if (!this.camera.IsF2TurnedInBoucle)
{
// If the view mode is the second person
if (this.camera.ViewCamera_type == CameraSimples.ChangeView.SecondPerson)
{
this.camera.ViewCamera_type = CameraSimples.ChangeView.firstPerson;
//Calcul position - ?? Here my problem
double direction = Math.Atan2(X2 - X1, Z2 - Z1) * 180.0 / 3.14159265;
//Calcul angle - ?? Here my problem
this.camera.position = ..
this.camera.rotation = ..
this.camera.MouseRadian_LeftrightRot = (float)direction;
}
//IF mode view is first person
else
{
//....
Here is a very basic 3rd person camera (what you meant by 2nd person) in Xna. It assumes you have the player's world matrix stored and can access it:
Vector3 _3rdPersonCamPosition = playerWorldMatrix.Translation + (playerWorldMatrix.Backward * trailingDistance) + (playerWorldMatrix.Up * heightOffset);// add a right or left offset if desired too
Vector3 _3rdPersonCamTarget = playerWorldMatrix.Translation;//you can offset this similarly too if desired
view = Matrix.CreateLookAt(_3rdPersonCamPosition, _3rdPersonCamTarget , Vector3.Up);
If your FPS cam is working properly and assuming it is essentially the same location and orientation as the player, you can substitute it's view matrix in place of the playerWorldMatrix above like this:
Matrix FPSCamWorld = Matrix.Invert(yourWorkingFPSviewMatrixHere);
Now wherever I wrote playerWorldMatrix you can use FPSCamWorld instead.
If I were you, I would take your now-working FPS camera (I'm assuming that moves properly, has a positional matrix, etc?), and add another Translation Transform to it to "move it" back behind the player.
Put another way:
If your "translation/view matrix" for the FPS view is something like:
(sorry, haven't played with XNA in a while, so don't remember proper class names)
var camTranslateMatrix = [matrix representing player position];
var camDirectionMatrix = [matrix representing player direction, etc];
var camViewMatrix = camTranslateMatrix * camDirectionMatrix;
Then you could change it like so:
var camTranslateMatrix = [matrix representing player position];
var camDirectionMatrix = [matrix representing player direction, etc];
// If not in 3rd person, this will be identity == no effect
var camThirdPersonMatrix =
IsInThirdPersonMode ?
new TranslateMatrix(back a bit and up a bit) :
IdentityMatrix();
var camViewMatrix =
camTranslateMatrix *
camDirectionMatrix *
camThirdPersonMatrix;
Make sense? That way, it'd be trivial to toggle between the two views without tons of nasty math each time you do so.
Related
I've been working on a small project for some days, everything was working fine until I changed my "map" implementation to be the same as in the game (Dofus) I'm based on (it's a little helper for the community).
Basically, I've a grid layout rotated at 45° (see image below), contructed from top left to bottom right. Every cell as an xIndex and zIndex to represent where it is (xIndex ; zIndex) on the image, and I just want to get the distance between two cells, without traveling diagonally.
As I tried to explain on the picture:
GetDistanceBetweenTiles(A, B) should be 3
GetDistanceBetweenTiles(A, C) should be 5
GetDistanceBetweenTiles(B, C) should be 2
I found the "Manhattan distance" which looks like it is what I want, but it's not giving me the values above.
Here is the code:
private int GetDistanceBetweenTiles(MovableObject a, MovableObject b)
{
//int dist = Mathf.Abs(a.xIndex - b.xIndex) + Mathf.Abs(a.zIndex - b.zIndex);
int minX = a.xIndex < b.xIndex ? a.xIndex : b.xIndex;
int maxX = a.xIndex > b.xIndex ? a.xIndex : b.xIndex;
int minZ = a.zIndex < b.zIndex ? a.zIndex : b.zIndex;
int maxZ = a.zIndex > b.zIndex ? a.zIndex : b.zIndex;
int distX = (maxX - minX);
int distZ = (maxZ - minZ);
int dist = Mathf.Abs(maxX - minX) + Mathf.Abs(maxZ - minZ);
print($"Distance between {a.name} and {b.name} is {dist}");
return dist;
}
Any help would be gladly appreciated.
If it can help, here is the project working with the first map implementation I did (but not translated yet).
Let make new coordinates in inclined rows with simple formulae:
row = z/2 - x ("/" for **integer division**)
col = z - row
Now we can just calculate Manhattan distance as
abs(row2 - row1) + abs(col2 - col1)
For your example
x z r c
4, 2 => -3, 5
1, 4 => 1, 4
distance = (1-(-3)) + (5-4) = 4 + 1 = 5
To explain: your grid rotated by 45 degrees:
0 1 2 3 4 5 6 7 8 \column
40|41 row -4
30|31|42|43 row -3
20|21|32|33|44|45 row -2
10|11|22|23|34|35|46|47 row -1
00|01|12|13|24|15|36|37|48 row 0
02|03|14|15|26|27|38 row 1
04|05|16|17|28 row 2
06|07|18 row 3
The "No-Maths" solution
I maybe have a workaround solution for you. I'm kind of a lazy person and very bad in maths ... so I usually let Unity do the maths for me in situations like yours ;)
For that you would need one dedicated GameObject that is rotated in the way that it represents the grid "rotation" so 0,45,0.
Then - since your tiles move always in steps of exactly 1 just in the rotated coordinate system - you could inetad of using an index based distance rather directly compare the absolute positions using Transform.InverseTransformPoint in order to get the positions relative to that rotated object.
InverseTransformPoint retuns as said the given world position in the local space of the used transform so that if the object was originally placed at e.g. x=1, z=1 in our rotated local space it will have the position z=1.1414..., x=0.
I simply attached this component to my rotated object .. actually I totate in Awake just to be sure ;)
public class PositionsManager : MonoBehaviour
{
// I know .. singleton pattern .. buuu
// but that's the fastest way to prototype ;)
public static PositionsManager Singleton;
private void Awake()
{
// just for making sure this object is at world origin
transform.position = Vector3.zero;
// rotate the object liek you need it
// possible that in your case you rather wanted -45°
transform.eulerAngles = new Vector3(0, 45, 0);
// since InverseTransformPoint is affacted by scale
// just make sure this object has the default scale
transform.localScale = Vector3.one;
// set the singleton so we can easily access this reference
Singleton = this;
}
public Vector2Int GetDistance(Transform from, Transform to)
{
var localPosFrom = transform.InverseTransformPoint(from.position);
var localPosTo = transform.InverseTransformPoint(to.position);
// Now you can simply get the actual position distance and return
// them as vector2 so you can even still see the components
// seperately
var difference = localPosTo - localPosFrom;
// since you are using X-Z not X-Y you have to convert the vector "manually"
return new Vector2Int(Mathf.RoundToInt(difference.x), Mathf.RoundToInt(difference.z));
}
public int GetAbsoluteDistance(Transform from, Trasnform to)
{
var difference = GetDistance(from, to);
return Mathf.Abs(difference.x) + Mathf.Abs(difference.y);
}
}
Now when you need to get the absolute distance you could simply do
var difference = PositionsManager.Singleton.GetDistance(objectA.transform, objectB.transform);
var absoluteDistance = PositionsManager.Singleton.GetAbsoluteDistance(objectA.transform, objectB.transform);
Little Demo (used a chess board drawer since I had that ^^)
The maths solution
It just came to me while writing the upper explenation:
You already know your steps between the tiles: It is allways Mathf.Sqrt(2)!
So again you could simply use the absolute positions in your world and compare them like
private float Sqrt2;
private void Awake()
{
Sqrt2 = Mathf.Sqrt(2);
}
...
// devide the actual difference by Sqrt(2)
var difference = (objectA.position - objectB.position) / Mathf.Sqrt(2);
// again set the Vector2 manually since we use Z not Y
// This step is optional if you anyway aren't interrested in the Vector2
// distance .. jsut added it for completeness
// You might need the rounding part though
var fixedDifference = new Vector2Int(Mathf.RoundToInt(difference.x), Mathf.RoundToInt(difference.z));
// get the absolute difference
var absoluteDistance = Mathf.Abs(fixedDifference.x) + Mathf.Abs(fixedDifference.y);
...
still completely without having to deal with the indexes at all.
I am trying to draw an arc between two points that represents a projectile's path. The angle that the projectile leaves point A at is known, and the X/Y coordinates of both points are known.
I'm trying to figure out the math behind this, and how to draw it up in c#.
Here is my failed attempt, based on some path examples I found
var g = new StreamGeometry();
var xDistance = Math.Abs(pointA.X - pointB.X);
var yDistance = Math.Abs(pointA.Y - pointB.Y);
var angle = 60;
var radiusX = xDistance / angle;
var radiusY = yDistance / angle;
using (var gc = g.Open())
{
gc.BeginFigure(
startPoint: pointA,
isFilled: false,
isClosed: false);
gc.ArcTo(
point: pointB,
size: new Size(radiusX, radiusY),
rotationAngle: 0d,
isLargeArc: false,
sweepDirection: SweepDirection.Clockwise,
isStroked: true,
isSmoothJoin: false);
}
Any help would be greatly appreciated!
Edit #2 (added clarity): For this problem assume that physics play no role (no gravity, velocity, or any outside forces). The projectile is guaranteed to land at point B and move along a parabolic path. The vertex will be halfway between point A and point B on the horizontal axis. The angle that it launches at is the angle up from the ground (horizontal).
So Point A (Ax, Ay) is known.
Point B (Bx, By) is known.
The angle of departure is known.
The X half of the vertex is known (Vx = Abs(Ax - Bx)).
Does this really boil down to needing to figure out the Y coordinate of the vertex?
Following on from the comments, we need a quadratic Bezier curve. This is defined by 3 points, the start, end, and a control point:
It is defined by the following equation:
We therefore need to find P1 using the given conditions (note that the gravity strength is determined implicitly). For a 2D coordinate we need two constraints / boundary conditions. They are given by:
The tangent vector at P0:
We need to match the angle to the horizontal:
The apex of the curve must be directly below the control point P1:
Therefore the vertical coordinate is given by:
[Please let me know if you would like some example code for the above]
Now for how to add a quadratic Bezier; thankfully, once you have done the above, it is not too difficult
The following method creates the parabolic geometry for the simple symmetric case. The angle is measured in degrees counterclockwise from the horizontal.
public Geometry CreateParabola(double x1, double x2, double y, double angle)
{
var startPoint = new Point(x1, y);
var endPoint = new Point(x2, y);
var controlPoint = new Point(
0.5 * (x1 + x2),
y - 0.5 * (x2 - x1) * Math.Tan(angle * Math.PI / 180));
var geometry = new StreamGeometry();
using (var context = geometry.Open())
{
context.BeginFigure(startPoint, false, false);
context.QuadraticBezierTo(controlPoint, endPoint, true, false);
}
return geometry;
}
A body movement subject only to the force of gravity (air resistance is ignored) can be evaluated with the following equations:
DistanceX(t) = dx0 + Vx0·t
DistanceY(t) = dy0 + Vy0·t - g/2·t^2
Where
g : gravity acceleration (9.8 m/s^2)
dx0 : initial position in the X axis
dy0 : initial position in the Y axis
Vy0 : initial X velocity component (muzzle speed)
Vy0 : initial Y velocity component (muzzle speed)
Well that doesn't seem very helpful, but lets investigate further. Your cannon has a muzzle speed V we can consider constant, so Vx0 and Vy0 can be written as:
Vx0 = V·cos(X)
Vy0 = V·sin(X)
Where X is the angle at which you are shooting. Ok, that seems interesting, we finally have an input that is useful to whoever is shooting the cannon: X. Lets go back to our equations and rewrite them:
DistanceX(t) = dx0 + V·cos(X)·t
DistanceY(t) = dy0 + V·sin(X)·t - g/2·t^2
And now, lets think through what we are trying to do. We want to figure out a way to hit a specific point P. Lets give it coordinates: (A, B). And in order to do that, the projectile has to reach that point in both projections at the same time. We'll call that time T. Ok, lets rewrite our equations again:
A = dx0 + V·cos(X)·T
B = dy0 + V·sin(X)·T - g/2·T^2
Lets get ourselves rid of some unnecessary constants here; if our cannon is located at (0, 0) our equations are now:
A = V·cos(X)·T [1]
B = V·sin(X)·T - g/2·T^2 [2]
From [1] we know that: T = A/(V·cos(X)), so we use that in [2]:
B = V·sin(X)·A/(V·cos(X)) - g/2·A^2/(V^2·cos^2(X))
Or
B = A·tan(X) - g/2·A^2/(V^2*cos^2(X))
And now some trigonometry will tell you that 1/cos^2 = 1 + tan^2 so:
B = A·tan(X) - g/2·A^2/V^2·(1+tan^2(X)) [3]
And now you have quadratic equation in tan(X) you can solve.
DISCLAIMER: typing math is kind of hard, I might have an error in there somewhere, but you should get the idea.
UPDATE The previous approach would allow you to solve the angle X that hits a target P given a muzzle speed V. Based on your comments, the angle X is given, so what you need to figure out is the muzzle speed that will make the projectile hit the target with the specified cannon angle. If it makes you more comfortable, don't think of V as muzzle speed, think of it as a form factor of the parabola you are trying to find.
Solve Vin [3]:
B = A·tan(X) - g/2·A^2/V^2·(1+tan^2(X))
This is a trivial quadratic equation, simply isolate V and take the square root. Obviously the negative root has no physical meaning but it will also do, you can take any of the two solutions. If there is no real number solution for V, it would mean that there is simply no possible shot (or parabola) that reaches P(angle X is too big; imagine you shoot straight up, you'll hit yourself, nothing else).
Now simply eliminate t in the parametrized equations:
x = V·cos(X)·t [4]
y = V·sin(X)·t - g/2·t^2 [5]
From [4] you have t = x/(V·cos(X)). Substitute in [5]:
y = tan(X)·x - g·x^2 /(2·V^2*cos^2(X))
And there is your parabola equation. Draw it and see your shot hit the mark.
I've given it a physical interpretation because I find it easier to follow, but you could change all the names I've written here to purely mathematical terms, it doesn't really matter, at the end of the day its all maths and the parabola is the same, any which way you want to think about it.
Okay, so I am trying to simulate the collision of balls on a 2-Dimensional plane. I can detect the collisions pretty easily using a simple comparison of positions and the sum of radii, however, sometimes the simulation gets ahead of itself and the circles overlap, which plays havoc with the rest of the simulation.
So I have figured that finding the normal vector between the two circles at the point of contact and adding onto the position vectors in that direction is what I need to do basically, and luckily I had a similar algorithm handling the velocity changes due to collisions so I adapted it thusly:
Vector2 normal = orgA.getCenterPosition() - orgB.getCenterPosition();
Vector2 tangent = new Vector2((normal.Y * -1), normal.X);
float diff = (orgA.getRadius() + orgB.getRadius()) - normal.Length();
normal.Normalize();
float PAn = Vector2.Dot(normal, orgA.position);
float PAt = Vector2.Dot(tangent, orgA.position);
PAn += diff;
float PBn = Vector2.Dot(normal, orgB.position);
float PBt = Vector2.Dot(tangent, orgB.position);
PBn -= diff;
Vector2 PA = (PAn * normal) + (PAt * tangent);
Vector2 PB = (PBn * normal) + (PBt * tangent);
orgA.position = PA;
orgB.position = PB;
The trouble is that when I run the simulation, and two balls meet, the whole thing goes crazy and they're suddenly going all over the shop.
Can anyone see the flaw in my algorithm? I've looked at it loads and I still can't find what's causing this.
Hey buddy i think what you need is a loop. Its going crazy because once the balls touch they are constantly being upgraded with a new logic....
im not amazing at this but try putting the collision in a loop... should look something like this:
if ( diff < (orb radius))
{
Vector2 PA = (PAn * normal) + (PAt * tangent);
Vector2 PB = (PBn * normal) + (PBt * tangent);
orgA.position = PA;
orgB.position = PB;
}
something like that... I really hope this helps a little :/
from my understanding is this is in your update method, so keep in mind update runs constantly every millisecond... so its fine when your getting the difference between the spheres and sizes but after they collide and you you want them to move in a certain way you are calculating the same equation over and over...
Better yet make a bool such as isCollided and make sure you switch that true/false according to that statement
hope it helps i have an example project of collision if you want i can send it to you, samerhachem#hotmail.com
I am making a 3d car game and I have a problem with rotation.
I want to rotate a model around itself but when I move, it starts to move around
the world !
The question is: How do I make a center for the model to move around?
I tried to change the code like this :
effect.World = Matrix.CreateRotationZ(modelRotation) * effect.World = Matrix.CreateTranslation(position);
now instead of moving forward relative to the model, orientation it moves in a set direction !
& this is my code:
effect.World = Matrix.CreateTranslation(position) * Matrix.CreateRotationZ(modelRotation);
effect.View = camera.View;
effect.Projection = camera.Projection;
I have a few tips to get you started:
Matrix multiplication order in DirectX/Xna is differrent than you learned in school.
In school v = A B y meant: v = A (B y). So when chaining matrices, B is applied first.
If you want to combine matrix A and B, you multiply them like C = A B
In Directx/XNA, the order is reversed. To combine matrix B and A, you write var C = B * A;
To stop me from making mistakes, I adopt a naming convention: each matrix (or transform) is called AtoB: WorldToView, ModelToWorld, or ModelToRotatedModel.
This reminds you that the output of the first matrix must match the input of the right matrix :
var modelToView = modelToWorld * worldToView;
and not:
var nowhereToNowhere = worldToView * modelToWorld;
This helped me a lot, I hope it helps you sort out your matrix problems.
P.S.
I hope the origin of your car model is in the center of the car, otherwise the it will still move around strangely.
Try switching these values around:
effect.World = Matrix.CreateTranslation(position) * Matrix.CreateRotationZ(modelRotation);
so it becomes:
effect.World = Matrix.CreateRotationZ(modelRotation) * Matrix.CreateTranslation(position);
I follow a simple acronym thats called ISROT
Identity
Scale
Rotation
Orientation
Translation
You work right to left, so you always end your statement with Translation.
I would like to understand how to measure the distance between two 3D objects, let's call them a parent object and a child object. Think of the parent as the body of a car and the child being a wheel of the car.
I understand how to get the difference based on the objects position in world space but I would like to get the difference as a measurement based on the parents relative object space.
E.g if the parent is facing East and the child is 2X, 3Y from the parent, measured in a relative sense. Such that if the parent rotated 60 degrees, the relative location of the child remains at a distance of 2x, 3y in the object space. Where as in a world space sense the child objects measurement as a Vector3 would be quite different.
Basically I just want a predictable way to get the difference so that a child object which is on the right of the patent can always stay right of the parent object.
This is the parent component, this update is run every frame:
[Serializable]
public class Component_Parent : BaseComponentAutoSerialization<ISceneEntity>
{
public override void OnUpdate(GameTime gameTime)
{
PassThrough.ParentMatrix = ParentObject.World;
PassThrough.ParentTranslation = ParentObject.World.Translation;
}
}
This next part is the child component:
[Serializable]
public class Component_Child : BaseComponentAutoSerialization<ISceneEntity>
{
Vector3 _parentOffset;
Quaternion _parentQuaternionOffset;
public override void OnUpdate(GameTime gameTime)
{
// Get a sceneobject from the ParentObject
SceneObject sceneobject = (SceneObject)ParentObject;
// This relies on the position never being at 0,0,0 for setup, so please don't do that
// or change it with more look ups so that you don't need to rely on a Zero Vector3 :-)
if (PassThrough.GroupSetupMode || _parentOffset == Vector3.Zero)
{
if (PassThrough.ParentTranslation != Vector3.Zero)
{
_parentOffset = sceneobject.World.Translation - PassThrough.ParentTranslation;
// Decompose World Matrix (Parent)
Quaternion parentQ = new Quaternion();
Vector3 parentSpot = new Vector3();
Vector3 parentScale = new Vector3();
PassThrough.ParentMatrix.Decompose(out parentScale, out parentQ, out parentSpot);
Matrix identity = Matrix.Identity;
// Decompose Identity Matrix (Parent)
Quaternion identityQ = new Quaternion();
Vector3 identitySpot = new Vector3();
Vector3 identityScale = new Vector3();
identity.Decompose(out identityScale, out identityQ, out identitySpot);
_parentQuaternionOffset = identityQ - parentQ;
}
}
else
{
if (_parentOffset != Vector3.Zero)
{
// Decompose World Matrix (Child)
Quaternion rotationQ = new Quaternion();
Vector3 spot = new Vector3();
Vector3 scale = new Vector3();
sceneobject.World.Decompose(out scale, out rotationQ, out spot);
// Decompose World Matrix (Parent)
Quaternion parentQ = new Quaternion();
Vector3 parentSpot = new Vector3();
Vector3 parentScale = new Vector3();
PassThrough.ParentMatrix.Decompose(out parentScale, out parentQ, out parentSpot);
Matrix location = Matrix.CreateTranslation(PassThrough.ParentTranslation);
Matrix rotation = Matrix.CreateFromQuaternion(parentQ);
Matrix rotation2 = Matrix.CreateFromQuaternion(_parentQuaternionOffset);
Matrix newWorld = rotation * location;
Vector3 testTranslation = newWorld.Translation + ((newWorld.Left * _parentOffset.X) + (newWorld.Up * _parentOffset.Y) + (newWorld.Forward * _parentOffset.Z));
Matrix scaleM = Matrix.CreateScale(scale);
//sceneobject.World = scaleM * (rotation * (Matrix.CreateTranslation(testTranslation)));
sceneobject.World = (Matrix.CreateTranslation(testTranslation));
}
}
}
}
I think it has something to do with keeping track of an offset rotation, from the identity matrix and I have started trying to add some code to that effect but really unsure of what next now.
Additional:
If I have the parent object facing the direction of the world space it all works, if it's facing a different direction then it's an issue and the child seems to rotate by the same amount when they are grouped together.
I've uploaded a demo video to try and explain:
http://www.youtube.com/watch?v=BzAKW4WBWYs
I've also pasted up the complete code for the components, the static pass through and the scene entity.
http://pastebin.com/5hEmiVx9
Thanks
Think wheels on a car. I want the right wheel to always be in the same
spot relative to the body of the car.
It sounds like you want to be able to locate the position of the wheel for any given orientation or position of the car. One built in method that XNA has to help here is Model.CopyAbsoluteBoneTransformsTo(Matrix[]); However, your code looks like you want to handle parent child relationship manually. So here is a way to do it without using the built in method. It assumes you do have offset information at load time:
Before the game loops starts (say, in the LoadContent method), after loading the car & wheel and assuming they load into the proper positions, you can then create your offset vector ( _parentOffset )
Vector3 _parentOffset = wheel.meshes[?].ParentBone.Transform.Translation - car.meshes[?].ParentBone.Transform.Translation;//where ? is the mesh index of the mesh you are setting up.
Save that vector and don't modify it.
Later, after the car's matrix has been rotationally and or positionally displaced, set the wheel's matrix like this:
Matrix wheelMatrix = carMatrix;
wheelMatrix.Translation += (wheelMatrix.Right * _parentOffset.X) +
(wheelMatrix.Up * _parentOffset.Y) +
(wheelMatrix.Backward * _parentOffset.Z);
This allows that the wheel matrix will inherit any rotational and translational information from the car but will displace the wheel's position appropriately regardless of car's orientation/position.
The distance between two objects is NOT a function of either orientations.
What you basically want is the distance of the child object to the orientation line of the parent object. Assuming you have a global cartesian coordinate system this can be simply calculated as h=sqrt(x^2+y^2)*sin(Theta), x and y being the relative coordinates of the child with respect to the parent and Theta the orientation of the parent measured from x axis.
But still the question is a little bit confusing to me. If you only want to make sure that the child is on the right side of the parent why don't you simply check the relative x? If it's positive it's on the right and if it's negative it's on the left?
The issue was the way I was trying to use the offset of the world space.
Thanks to flashed from #XNA on EFnet, this code works perfectly:
[Serializable]
public class Component_Child_fromxna : BaseComponentAutoSerialization<ISceneEntity>
{
Vector3 _parentOffset;
Matrix _ParentMatrixOffset;
public override void OnUpdate(GameTime gameTime)
{
// Get a sceneobject from the ParentObject
SceneObject sceneObject = (SceneObject)ParentObject;
// This relies on the position never being at 0,0,0 for setup, so please don't do that
// or change it with more look ups so that you don't need to rely on a Zero Vector3 :-)
if (PassThrough.GroupSetupMode || _parentOffset == Vector3.Zero)
{
if (PassThrough.ParentTranslation != Vector3.Zero)
{
// The old offset - This is just in world space though...
_parentOffset = sceneObject.World.Translation - PassThrough.ParentTranslation;
// Get the distance between the child and the parent which we keep as the offset
// Inversing the ParentMatrix and multiplying it by the childs matrix gives an offset
// The offset is stored as a relative xyz, based on the parents object space
_ParentMatrixOffset = sceneObject.World * Matrix.Invert(PassThrough.ParentMatrix);
}
}
else
{
if (_parentOffset != Vector3.Zero)
{
//Matrix pLocation = Matrix.CreateTranslation(_parentOffset);
//sceneObject.World = Matrix.Multiply(pLocation, PassThrough.ParentMatrix);
sceneObject.World = Matrix.Multiply(_ParentMatrixOffset, PassThrough.ParentMatrix);
}
}
}
}