Been playing around with a 3D example and having trouble getting the rotation to be cumulative. The example is just a 3D box. I am trying to add ArcBall rotation to it via a quaternion and mouse click points. It works well with the exception of the Box resetting on the next click. I am no DirectX expert and do not fully understand matrix manipulation. I think what I need to do is set the rotated matrix as the current world matrix so that the succeeding matrix manipulation will become cumulative. Although I may be way off? But if so how do I do this? The Microsoft on line docs are pretty vague and it is kind of driving me nuts. Hopefully someone can help me out.
This is the Mouse Down event
if (e.Button == MouseButtons.Left)
{
HalfWidth = this.ClientRectangle.Width / 2.0f;
HalfHeight = this.ClientRectangle.Height / 2.0f;
MouseDownX = (e.X - HalfWidth) / HalfWidth;
MouseDownY = (HalfHeight - e.Y) / HalfHeight;
mouseroll = true;
}
This is the Mouse Move event
float curX = (e.X - HalfWidth) / HalfWidth;
float curY = (HalfHeight - e.Y) / HalfHeight;
LastWorldRotation = WorldRotation;
WorldRotation = ComputeRotation(MouseDownX, MouseDownY, curX, curY);
This is the Compute rotation function
public static Quaternion ComputeRotation(float p1x, float p1y, float p2x, float p2y)
{
Vector3 axis;
Vector3 p1;
Vector3 p2;
Vector3 d;
float phi;
float t;
if ((p1x == p2x) && (p1y == p2y))
{
return new Quaternion(0, 0, 0, 1.0f);
}
p1 = new Vector3(p1x, p1y, p_ProjectToSphere(TRACKBALLSIZE, p1x, p1y));
p2 = new Vector3(p2x, p2y, p_ProjectToSphere(TRACKBALLSIZE, p2x, p2y));
axis = Vector3.Cross(p1, p2);
d = p1 - p2;
t = d.Length() / (2.0f * TRACKBALLSIZE);
if (t > 1.0f) t = 1.0f;
if (t < -1.0f) t = -1.0f;
phi = 2.0f * (float)System.Math.Asin(t);
return Quaternion.RotationAxis(axis, phi);
}
private static float p_ProjectToSphere(float r, float x, float y)
{
float d, t, z;
d = (float)System.Math.Sqrt(x * x + y * y);
if (d < r * 0.70710678118654752440)
{
z = (float)System.Math.Sqrt(r * r - d * d);
}
else
{
t = (float)(r / 1.41421356237309504880);
z = t * t / d;
}
return -z;
}
And this is my Render function
private void Render()
{
d3dDevice.Clear(ClearFlags.Target | ClearFlags.ZBuffer,
Color.White, 1.0f, 0);
d3dDevice.BeginScene();
rotation_matrix = Matrix.RotationQuaternion(WorldRotation);
world_matrix = Matrix.Identity;
translation_matrix = Matrix.Translation(0.0f, 0.0f, 5.0f);
world_matrix = rotation_matrix * translation_matrix;
d3dDevice.SetTransform(TransformType.World, world_matrix);
d3dDevice.SetTransform(TransformType.View, world_matrix);
d3dDevice.SetTransform(TransformType.Projection, world_matrix);
d3dDevice.Transform.World = Matrix.Identity;
d3dDevice.Transform.Projection = Matrix.PerspectiveFovLH(Geometry.DegreeToRadian(45.0f), (float)this.ClientSize.Width / this.ClientSize.Height, 0.1f, 100.0f);
d3dDevice.VertexFormat = Vertex.FVF_Flags;
d3dDevice.SetStreamSource(0, vertexBuffer, 0);
d3dDevice.SetTexture(0, texture);
d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 0, 2);
d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 4, 2);
d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 8, 2);
d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 12, 2);
d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 16, 2);
d3dDevice.DrawPrimitives(PrimitiveType.TriangleStrip, 20, 2);
d3dDevice.EndScene();
d3dDevice.Present();
}