# 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 on other sites
You have to divide the vector with w, not multiply. Thats how you get rid of homogeneous coordinate.

double w = 1.f / ((left.m41 * v.X) + (left.m42 * v.Y) + (left.m43 * v.Z) + left.m44);

##### 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;
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 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

result_vector = matrix * vector

I hope this is it:-)

##### 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.wvector.y=COL1.y*tovect.x+COL2.y*tovect.y+COL3.y*tovect.z+COL4.y*tovect.wvector.z=COL1.z*tovect.x+COL2.z*tovect.y+COL3.z*tovect.z+COL4.z*tovect.wvector.w=COL1.w*tovect.x+COL2.w*tovect.y+COL3.w*tovect.z+COL4.w*tovect.wreturn TRVEC;}

##### Share on other sites
It is trivial to look at the code for Vector3.Transform if you have Reflector, unless it's an internal call (seems unlikely).

##### 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);}

## Create an account

Register a new account

• ### Forum Statistics

• Total Topics
628373
• Total Posts
2982306

• 10
• 9
• 13
• 24
• 11