Matrix3D != ProjectionMatrix SL4
-
Monday, March 07, 2011 8:58 AM
After a projection transform the resulting ProjectionMatrix does not equal a valid Matrix3D
Specifically the X properties are all 0.0.
Here is xaml to create two planes one with a projection.
<Canvas x:Name="LayoutRoot" Background="White" Width="800" Height="400" MouseMove="LayoutRoot_MouseMove"> <Canvas Background="Yellow" Width="400" Height="400" x:Name="testCanvas"> <Canvas.Projection> <PlaneProjection x:Name="GProj" RotationX="-45" CenterOfRotationY="1.0" /> </Canvas.Projection> </Canvas> <Canvas Background="Red" Width="400" Height="400" x:Name="testCanvas2" Canvas.Left="400"> </Canvas> <StackPanel Orientation="Horizontal"> <Button Content="calc" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click" /> </StackPanel> </Canvas>
Once the button is clicked the code copies the properties and sets the resulting matix to the second plane.private void Button_Click(object sender, RoutedEventArgs e) { Matrix3D m3dp = GProj.ProjectionMatrix; Matrix3DProjection matrix3DProjection = new Matrix3DProjection(); Matrix3D matrix3D = new Matrix3D(); matrix3D.M11 = m3dp.M11; matrix3D.M12 = m3dp.M12; matrix3D.M13 = m3dp.M13; matrix3D.M14 = m3dp.M14; matrix3D.M21 = m3dp.M21; matrix3D.M22 = m3dp.M22; matrix3D.M23 = m3dp.M23; matrix3D.M24 = m3dp.M24; matrix3D.M31 = m3dp.M31; matrix3D.M32 = m3dp.M32; matrix3D.M33 = m3dp.M33; matrix3D.M34 = m3dp.M34; matrix3D.OffsetX = m3dp.OffsetX; matrix3D.OffsetY = m3dp.OffsetY; matrix3D.OffsetZ = m3dp.OffsetZ; matrix3D.M44 = m3dp.M44; matrix3DProjection.ProjectionMatrix = matrix3D; testCanvas2.Projection = matrix3DProjection; }
Discovered when trying to perform matrix multiplications where the source matrix was the above projection.M11, M21, M31, OffsetX is always 0.0
All Replies
-
Thursday, March 10, 2011 3:26 AM
After a projection transform the resulting ProjectionMatrix does not equal a valid Matrix3D
Hi,
You are running into a wrong direction. The ProjectionMatrix is for projection only, not the matrix used to see the final result. We need to use multiple Matrix to build the result like a PlaneProjection. Actually for a given 3D objects if you view (camera viewpoint) it on different point you’ll see different results. Below is a sample of using ProjectionMatrix. Please try to adjust the final matrix to revert to whatever you need.
using System; using System.Collections.Generic; using System.Linq; using System.Net; using System.Windows; using System.Windows.Controls; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; using System.Windows.Media.Media3D; using System.Windows.Threading; namespace SilverlightApplication17 { public partial class MainPage : UserControl { public MainPage() { InitializeComponent(); this.Loaded += new RoutedEventHandler(MainPage_Loaded); } void MainPage_Loaded(object sender, RoutedEventArgs e) { DispatcherTimer dt = new DispatcherTimer(); dt.Interval = TimeSpan.FromMilliseconds(50); dt.Tick += new EventHandler(dt_Tick); dt.Start(); } double i = 0; void dt_Tick(object sender, EventArgs e) { i++; if (i >= 10000) i = 0; GProj.RotationX = i; Sync(); } private Matrix3D TranslationTransform(double tx, double ty, double tz) { Matrix3D m = new Matrix3D(); m.M11 = 1.0; m.M12 = 0.0; m.M13 = 0.0; m.M14 = 0.0; m.M21 = 0.0; m.M22 = 1.0; m.M23 = 0.0; m.M24 = 0.0; m.M31 = 0.0; m.M32 = 0.0; m.M33 = 1.0; m.M34 = 0.0; m.OffsetX = tx; m.OffsetY = ty; m.OffsetZ = tz; m.M44 = 1.0; return m; } private Matrix3D CreateScaleTransform(double sx, double sy, double sz) { Matrix3D m = new Matrix3D(); m.M11 = sx; m.M12 = 0.0; m.M13 = 0.0; m.M14 = 0.0; m.M21 = 0.0; m.M22 = sy; m.M23 = 0.0; m.M24 = 0.0; m.M31 = 0.0; m.M32 = 0.0; m.M33 = sz; m.M34 = 0.0; m.OffsetX = 0.0; m.OffsetY = 0.0; m.OffsetZ = 0.0; m.M44 = 1.0; return m; } private Matrix3D RotateYTransform(double theta) { double sin = Math.Sin(theta); double cos = Math.Cos(theta); Matrix3D m = new Matrix3D(); m.M11 = cos; m.M12 = 0.0; m.M13 = -sin; m.M14 = 0.0; m.M21 = 0.0; m.M22 = 1.0; m.M23 = 0.0; m.M24 = 0.0; m.M31 = sin; m.M32 = 0.0; m.M33 = cos; m.M34 = 0.0; m.OffsetX = 0.0; m.OffsetY = 0.0; m.OffsetZ = 0.0; m.M44 = 1.0; return m; } private Matrix3D RotateZTransform(double theta) { double cos = Math.Cos(theta); double sin = Math.Sin(theta); Matrix3D m = new Matrix3D(); m.M11 = cos; m.M12 = sin; m.M13 = 0.0; m.M14 = 0.0; m.M21 = -sin; m.M22 = cos; m.M23 = 0.0; m.M24 = 0.0; m.M31 = 0.0; m.M32 = 0.0; m.M33 = 1.0; m.M34 = 0.0; m.OffsetX = 0.0; m.OffsetY = 0.0; m.OffsetZ = 0.0; m.M44 = 1.0; return m; } private Matrix3D PerspectiveTransformFovRH(double fieldOfViewY, double aspectRatio, double zNearPlane, double zFarPlane) { double height = 1.0 / Math.Tan(fieldOfViewY / 2.0); double width = height / aspectRatio; double d = zNearPlane - zFarPlane; Matrix3D m = new Matrix3D(); m.M11 = width; m.M12 = 0; m.M13 = 0; m.M14 = 0; m.M21 = 0; m.M22 = height; m.M23 = 0; m.M24 = 0; m.M31 = 0; m.M32 = 0; m.M33 = zFarPlane / d; m.M34 = -1; m.OffsetX = 0; m.OffsetY = 0; m.OffsetZ = zNearPlane * zFarPlane / d; m.M44 = 0; return m; } private Matrix3D ViewportTransform(double width, double height) { Matrix3D m = new Matrix3D(); m.M11 = width / 2.0; m.M12 = 0.0; m.M13 = 0.0; m.M14 = 0.0; m.M21 = 0.0; m.M22 = -height / 2.0; m.M23 = 0.0; m.M24 = 0.0; m.M31 = 0.0; m.M32 = 0.0; m.M33 = 1.0; m.M34 = 0.0; m.OffsetX = width / 2.0; m.OffsetY = height / 2.0; m.OffsetZ = 0.0; m.M44 = 1.0; return m; } private void Button_Click(object sender, RoutedEventArgs e) { Sync(); } private void Sync() { Matrix3D m3dp = GProj.ProjectionMatrix; Matrix3DProjection matrix3DProjection = new Matrix3DProjection(); Matrix3D matrix3D = new Matrix3D(); matrix3D.M11 = m3dp.M11; matrix3D.M12 = m3dp.M12; matrix3D.M13 = m3dp.M13; matrix3D.M14 = m3dp.M14; matrix3D.M21 = m3dp.M21; matrix3D.M22 = m3dp.M22; matrix3D.M23 = m3dp.M23; matrix3D.M24 = m3dp.M24; matrix3D.M31 = m3dp.M31; matrix3D.M32 = m3dp.M32; matrix3D.M33 = m3dp.M33; matrix3D.M34 = m3dp.M34; matrix3D.OffsetX = m3dp.OffsetX; matrix3D.OffsetY = m3dp.OffsetY; matrix3D.OffsetZ = m3dp.OffsetZ; matrix3D.M44 = m3dp.M44; // far plane matrix3DProjection.ProjectionMatrix = matrix3D; //* viewport; double fovY = Math.PI / 2.0; double translationZ = -testCanvas.ActualHeight / Math.Tan(fovY / 2.0); Matrix3D centerImageAtOrigin = TranslationTransform( -testCanvas.ActualWidth / 2.0, -testCanvas.ActualHeight / 2.0, 0); Matrix3D rotateAboutX = matrix3D; Matrix3D translateAwayFromCamera = TranslationTransform(0, 0, translationZ); Matrix3D perspective = PerspectiveTransformFovRH(fovY, LayoutRoot.ActualWidth / LayoutRoot.ActualHeight, // aspect ratio 1.0, // near plane 1000.0); // far plane Matrix3D viewport = ViewportTransform(LayoutRoot.ActualWidth, LayoutRoot.ActualHeight); Matrix3D m = centerImageAtOrigin; m = m * rotateAboutX; m = m * translateAwayFromCamera; m = m * perspective; m = m * viewport; testCanvas2.Projection = new Matrix3DProjection() { ProjectionMatrix = m }; } } } <UserControl x:Class="SilverlightApplication17.MainPage" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="400"> <Canvas x:Name="LayoutRoot" Background="White" Width="800" Height="400" > <Canvas Background="Red" Width="400" Height="400" x:Name="testCanvas2" Canvas.Left="400"> </Canvas> <Canvas Background="Yellow" Width="400" Height="400" x:Name="testCanvas"> <Canvas.Projection> <PlaneProjection x:Name="GProj" RotationX="-85" CenterOfRotationY="1.0" /> </Canvas.Projection> </Canvas> <StackPanel Orientation="Horizontal"> <Button Content="calc" HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click" /> </StackPanel> </Canvas> </UserControl>
-
Friday, March 11, 2011 9:32 AM
thanks for that, I will digest all that scary math.
The example works great.

