Sign in to follow this  
TedLowery

Does anyone know the code behind Vector3.Transform?

Recommended Posts

I thought it was simply MxV. But apparently there is more to it than that. Here is my attempt to reproduce it: public static Vector operator *(Matrix left, Vector v) { double w = (left.m41 * v.X) + (left.m42 * v.Y) + (left.m43 * v.Z) + left.m44; Vector v2 = new Vector( ((left.m11 * v.X) + (left.m12 * v.Y) + (left.m13 * v.Z) + left.m14) * w, ((left.m21 * v.X) + (left.m22 * v.Y) + (left.m23 * v.Z) + left.m24) * w, ((left.m31 * v.X) + (left.m32 * v.Y) + (left.m33 * v.Z) + left.m34) * w); return v2; } However, this gives a wierdly skewed results when compared with Transform() using the same Matrix and Vector. Anyone know what I have goofed? Thanks

Share this post


Link to post
Share on other sites
Nope, that's not it. Something else is going on. Here is some source code if anyone wants to check my math.

If you step through the call to after T2(), you will notice that works has the correct world coordinates (0,0) for this point after applying the view and projection matrix, however, you will notice broken has other coordinates. If you were to actually plot the coordinates returned by T2, it will be a skewed shape, however the actual skew seems to vary over the y-axis. It's an interesting effect, but unfortunately not the effect I was looking for.

using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using Microsoft.DirectX;
using Microsoft.DirectX.Direct3D;

namespace DirectX_Tutorial
{

public class WinForm : System.Windows.Forms.Form
{
private Device device;
private System.ComponentModel.Container components = null;

public WinForm()
{
InitializeComponent();
this.Setstyle(Controlstyles.AllPaintingInWmPaint | Controlstyles.Opaque, true);
}

public void InitializeDevice()
{
PresentParameters presentParams = new PresentParameters();
presentParams.Windowed = true;
presentParams.SwapEffect = SwapEffect.Discard;
device = new Device(0, DeviceType.Hardware, this, CreateFlags.SoftwareVertexProcessing, presentParams);
}

protected override void OnPaint(System.Windows.Forms.PaintEventArgs e)
{
//device.Transform.Projection = Matrix.PerspectiveFovLH((float)Math.PI / 4, this.Width / this.Height, 1f, 50f);
device.Transform.Projection = Matrix.OrthoLH(2, 2, -2f, 2f);
PrintMatrix(device.Transform.Projection);
device.Transform.View = Matrix.LookAtRH(new Vector3(1, 1, 1), new Vector3(0, 0, 0), new Vector3(0, 1, 0));
//device.Transform.View = Matrix.LookAtLH(new Vector3(1.1f, -2.2f, 3.3f), new Vector3(-4.4f, 5.5f, -6.6f), new Vector3(0, 1, 0));
PrintMatrix(device.Transform.View);
device.RenderState.Lighting = false;
device.RenderState.CullMode = Cull.None;
Matrix pxv = device.Transform.View * device.Transform.Projection;

CustomVertex.PositionColored[] vertices = new CustomVertex.PositionColored[6];
vertices[0].Position = new Vector3(.5f, .5f, .5f);
vertices[0].Color = Color.Red.ToArgb();
vertices[1].Position = new Vector3(-.5f, .5f, .5f);
vertices[1].Color = Color.Red.ToArgb();
vertices[2].Position = new Vector3(.5f, -.5f, .5f);
vertices[2].Color = Color.Red.ToArgb();
vertices[3].Position = new Vector3(-.5f, .5f, .5f);
vertices[3].Color = Color.Red.ToArgb();
vertices[4].Position = new Vector3(-.5f, -.5f, .5f);
vertices[4].Color = Color.Red.ToArgb();
vertices[5].Position = new Vector3(.5f, -.5f, .5f);
vertices[5].Color = Color.Red.ToArgb();

Vector4 thisWorks = Vector3.Transform(vertices[0].Position, pxv);
Vector3 broken = T2(pxv, vertices[0].Position);

device.Clear(ClearFlags.Target, Color.DarkSlateBlue, 1.0f, 0);

device.BeginScene();
device.VertexFormat = CustomVertex.PositionColored.Format;
device.DrawUserPrimitives(PrimitiveType.TriangleList, 2, vertices);
device.EndScene();

device.Present();

this.Invalidate();
}

public Vector3 T2(Matrix left, Vector3 v)
{
float w = (left.M41 * v.X) + (left.M42 * v.Y) + (left.M43 * v.Z) + left.M44;
Vector3 v2 = new Vector3(
((left.M11 * v.X) + (left.M12 * v.Y) + (left.M13 * v.Z) + left.M14) * w,
((left.M21 * v.X) + (left.M22 * v.Y) + (left.M23 * v.Z) + left.M24) * w,
((left.M31 * v.X) + (left.M32 * v.Y) + (left.M33 * v.Z) + left.M34) * w);
return v2;
}

protected override void Dispose(bool disposing)
{
if (disposing)
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose(disposing);
}

private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.Size = new System.Drawing.Size(500, 500);
this.Text = "DirectX Tutorial";
}

private void PrintMatrix(Matrix m)
{
Console.WriteLine(string.Format("[{0} {1} {2} {3}]", m.M11, m.M12, m.M13, m.M14));
Console.WriteLine(string.Format("[{0} {1} {2} {3}]", m.M21, m.M22, m.M23, m.M24));
Console.WriteLine(string.Format("[{0} {1} {2} {3}]", m.M31, m.M32, m.M33, m.M34));
Console.WriteLine(string.Format("[{0} {1} {2} {3}]", m.M41, m.M42, m.M43, m.M44));
}

static void Main()
{
using (WinForm our_directx_form = new WinForm())
{
our_directx_form.InitializeDevice();
Application.Run(our_directx_form);
}
}
}
}

Share this post


Link to post
Share on other sites
Try this:

public Vector3 T2(Matrix left, Vector3 v)
{
float w = 1.0 / ((left.M14 * v.X) + (left.M24 * v.Y) + (left.M34 * v.Z) + left.M44);
Vector3 v2 = new Vector3(
((left.M11 * v.X) + (left.M21 * v.Y) + (left.M31 * v.Z) + left.M41) * w,
((left.M12 * v.X) + (left.M22 * v.Y) + (left.M32 * v.Z) + left.M42) * w,
((left.M13 * v.X) + (left.M23 * v.Y) + (left.M33 * v.Z) + left.M43) * w);
return v2;
}

Since its DirectX and not OpenGL, vector & matrix multiplication goes like this:
result_vector = vector * matrix

in your function it goes:
result_vector = matrix * vector

I hope this is it:-)

Share this post


Link to post
Share on other sites
to tranform a vector you multiply each column of matrix with corresponding scallar from transformed vector and then add those 4 vectors.

COL1*vecx+COL2*vecy+COL3*vecz+COL4*vecw=TRVEC

to multiply a vector by a scalar you multiply each coordinate with the number. Result is a vector.
to add vectors you just add each coordinate from vector 1 and vector 2.
Result is a vector.

to transform a vector by 4 dimensianal matrix you write


vector* Transform4Vec(float* matrix,vector tovect)
{
vector* TRVEC=new vector();
vector.x=COL1.x*tovect.x+COL2.x*tovect.y+COL3.x*tovect.z+COL4.x*tovect.w
vector.y=COL1.y*tovect.x+COL2.y*tovect.y+COL3.y*tovect.z+COL4.y*tovect.w
vector.z=COL1.z*tovect.x+COL2.z*tovect.y+COL3.z*tovect.z+COL4.z*tovect.w
vector.w=COL1.w*tovect.x+COL2.w*tovect.y+COL3.w*tovect.z+COL4.w*tovect.w
return TRVEC;
}

Share this post


Link to post
Share on other sites
MDX calls into D3DX for all of its math functions, so you aren't going to find any help by reflectoring the internals. You can, however, look at the source for SlimMath, which is checked for correctness against D3DX via a unit test.

For the lazy:

public static void Transform(ref Vector3 vector, ref Matrix transform, out Vector4 result)
{
result = new Vector4(
(vector.X * transform.M11) + (vector.Y * transform.M21) + (vector.Z * transform.M31) + transform.M41,
(vector.X * transform.M12) + (vector.Y * transform.M22) + (vector.Z * transform.M32) + transform.M42,
(vector.X * transform.M13) + (vector.Y * transform.M23) + (vector.Z * transform.M33) + transform.M43,
(vector.X * transform.M14) + (vector.Y * transform.M24) + (vector.Z * transform.M34) + transform.M44);
}

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this