public static bool UnProject(Vector4d winPos, Matrix4d modelMatrix, Matrix4d projMatrix, double[] viewport, ref Vector4d objPos) { Matrix4d p = Matrix4d.Mult(modelMatrix, projMatrix); Matrix4d finalMatrix = Matrix4d.Invert(p); Vector4d @in = winPos; // Map x and y from window coordinates @in.X = (@in.X - viewport[0]) / viewport[2]; @in.Y = (@in.Y - viewport[1]) / viewport[3]; // Map to range -1 to 1 @in.X = @in.X * 2.0 - 1.0; @in.Y = @in.Y * 2.0 - 1.0; @in.Z = @in.Z * 2.0 - 1.0; @in.W = 1.0; Vector4d @out = Vector4d.Transform(@in, finalMatrix); if (@out.W == 0.0) { return(false); } @out.X /= @out.W; @out.Y /= @out.W; @out.Z /= @out.W; objPos = @out; return(true); }
/// <summary> /// Inserts one new child node to this parent node. /// </summary> /// <param name="ch">Child node to add.</param> /// <param name="toParent">Transform from local space of the child to the parent's space.</param> public virtual void InsertChild(ISceneNode ch, Matrix4d toParent) { children.AddLast(ch); ch.ToParent = toParent; toParent.Invert(); ch.FromParent = toParent; ch.Parent = this; }
/// <summary> /// Projects a 2d screenspace coordinate to world coordinates. /// </summary> public static Vector3d Unproject(Vector3d Point, Matrix4d View, Matrix4d Proj) { Matrix4d ma = Matrix4d.Mult(View, Proj); Matrix4d ima = Matrix4d.Invert(ma); Vector4d coord = new Vector4d(Point.X, Point.Y, Point.Z, 1.0); Vector4d res = Vector4d.Transform(coord, ima); return(new Vector3d(res.X / res.W, res.Y / res.W, res.Z / res.W)); }
/// <summary> /// Complete non-mandatory (deferred) values in the Intersection instance. /// </summary> public void Complete() { if (Solid != null) { // World coordinates. LocalToWorld = Solid.ToWorld(); WorldToLocal = LocalToWorld; WorldToLocal.Invert(); Vector3d.TransformPosition(ref CoordLocal, ref LocalToWorld, out CoordWorld); // Object coordinates. LocalToObject = Solid.ToObject(); Vector3d.TransformPosition(ref CoordLocal, ref LocalToObject, out CoordObject); // Appearance. // Reflectance model. ReflectanceModel = (IReflectanceModel)Solid.GetAttribute(PropertyName.REFLECTANCE_MODEL); if (ReflectanceModel == null) { ReflectanceModel = new PhongModel(); } // Material. Material = (IMaterial)Solid.GetAttribute(PropertyName.MATERIAL); if (Material == null) { Material = ReflectanceModel.DefaultMaterial(); } // Surface color (accepts a color provided by a Solid). if (SurfaceColor == null) { double[] col = (double[])Solid.GetAttribute(PropertyName.COLOR); SurfaceColor = (double[])((col != null) ? col.Clone() : Material.Color.Clone()); } // List of textures. Textures = Solid.GetTextures(); // Solid is responsible for completing remaining values. // Usually: Normal, TextureCoord. Solid.CompleteIntersection(this); Normal.Normalize(); if (Enter != Front) { Vector3d.Multiply(ref Normal, -1.0, out Normal); } } if (SurfaceColor == null) { SurfaceColor = new double[] { 0.0, 0.0, 0.0 } } ; completed = true; }
private static Vector3d UnProject(Vector3d screen, Matrix4d modelviewMatrix, Matrix4d projectionMatrix, int[] viewport) { Vector4d pos = Vector4d.Zero; pos.X = ((screen.X - (double)viewport[0]) / (double)viewport[2]) * 2.0 - 1.0; pos.Y = ((screen.Y - (double)viewport[1]) / (double)viewport[3]) * 2.0 - 1.0; pos.Z = (2.0 * screen.Z) - 1.0; pos.W = 1.0; Vector4d pos2 = Vector4d.Transform(pos, Matrix4d.Invert(Matrix4d.Mult(modelviewMatrix, projectionMatrix))); return(new Vector3d(pos2.X, pos2.Y, pos2.Z) / pos2.W); }
/// <summary> /// Unprojects the specified point on the screen with the specified depth /// to the 3D space. /// </summary> /// <param name="screenLocation">The point on the screen</param> /// <param name="depth">The depth value in the range [0, 1] (near to far)</param> /// <returns>The corresponding 3D point on the screen</returns> public static Vector3d UnProject(Point screenLocation, double depth) { int[] viewport = GetViewportArray(); Vector4d pos = new Vector4d(); // Map x and y from window coordinates, map to range -1 to 1 pos.X = (screenLocation.X - viewport[0]) / (double)viewport[2] * 2.0f - 1.0f; pos.Y = 1 - (screenLocation.Y - viewport[1]) / (double)viewport[3] * 2.0f; pos.Z = depth * 2.0f - 1.0f; pos.W = 1.0f; Vector4d pos2 = Vector4d.Transform(pos, Matrix4d.Invert(GetModelViewMatrix() * GetProjectionMatrix())); Vector3d pos_out = new Vector3d(pos2.X, pos2.Y, pos2.Z); return(pos_out / pos2.W); }
/// <summary> /// Complete non-mandatory (deferred) values in the Intersection instance. /// </summary> public void Complete() { if (Solid != null) { // world coordinates: LocalToWorld = Solid.ToWorld(); WorldToLocal = LocalToWorld; WorldToLocal.Invert(); Vector3d.TransformPosition(ref CoordLocal, ref LocalToWorld, out CoordWorld); // object coordinates: LocalToObject = Solid.ToObject(); Vector3d.TransformPosition(ref CoordLocal, ref LocalToObject, out CoordObject); // appearance: ReflectanceModel = (IReflectanceModel)Solid.GetAttribute(PropertyName.REFLECTANCE_MODEL); if (ReflectanceModel == null) { ReflectanceModel = new PhongModel(); } Material = (IMaterial)Solid.GetAttribute(PropertyName.MATERIAL); if (Material == null) { Material = ReflectanceModel.DefaultMaterial(); } double[] col = (double[])Solid.GetAttribute(PropertyName.COLOR); SurfaceColor = (double[])((col != null) ? col.Clone() : Material.Color.Clone()); Textures = Solid.GetTextures(); // Solid is responsible for completing remaining values: Solid.CompleteIntersection(this); Normal.Normalize(); if (Enter != Front) { Vector3d.Multiply(ref Normal, -1.0, out Normal); } } if (SurfaceColor == null) { SurfaceColor = new double[] { 0.0, 0.2, 0.3 } } ; completed = true; }
/// <summary> /// Bestimmt die Kosten für die Kontraktion der angegebenen Vertices. /// </summary> /// <param name="s"> /// Der erste Vertex des Paares. /// </param> /// <param name="t"> /// Der zweite Vertex des Paares. /// </param> /// <returns> /// Eine Instanz der Pair-Klasse. /// </returns> Pair ComputeMinimumCostPair(int s, int t) { Vector3d target; double cost; var q = Q[s] + Q[t]; // Siehe [Gar97], Abschnitt 4 ("Approximating Error With Quadrics"). var m = new Matrix4d() { M11 = q.M11, M12 = q.M12, M13 = q.M13, M14 = q.M14, M21 = q.M12, M22 = q.M22, M23 = q.M23, M24 = q.M24, M31 = q.M13, M32 = q.M23, M33 = q.M33, M34 = q.M34, M41 = 0, M42 = 0, M43 = 0, M44 = 1 }; // Wenn m invertierbar ist, lässt sich die optimale Position bestimmen. // if (m.Determinant != 0) { try { // Determinante ist ungleich 0 für invertierbare Matrizen. var inv = Matrix4d.Invert(m); target = new Vector3d(inv.M14, inv.M24, inv.M34); cost = ComputeVertexError(target, q); } catch (InvalidOperationException) { // } else { // Ansonsten den besten Wert aus Position von Vertex 1, Vertex 2 und // Mittelpunkt wählen. var v1 = vertices[s]; var v2 = vertices[t]; var mp = new Vector3d() { X = (v1.X + v2.X) / 2, Y = (v1.Y + v2.Y) / 2, Z = (v1.Z + v2.Z) / 2 }; var candidates = new[] { new { cost = ComputeVertexError(v1, q), target = v1 }, new { cost = ComputeVertexError(v2, q), target = v2 }, new { cost = ComputeVertexError(mp, q), target = mp } }; var best = (from p in candidates orderby p.cost select p).First(); target = best.target; cost = best.cost; } return(new Pair(s, t, target, cost)); }
/// <summary> /// Converts a screen space point into a corresponding point in world space. /// </summary> /// <param name="coordinate">The coordinate to project</param> /// <param name="viewport">The viewport dimensions</param> /// <param name="projection">The projection matrix</param> /// <param name="modelview">The modelview matrix</param> /// <returns>The coordinate in world space.</returns> public static Coordinate Unproject(Coordinate coordinate, int[] viewport, Matrix4d projection, Matrix4d modelview) { var matrix = Matrix4d.Invert(Matrix4d.Mult(modelview, projection)); var source = new Vector4d( (coordinate.DX - viewport[0]) * 2 / viewport[2] - 1, (coordinate.DY - viewport[1]) * 2 / viewport[3] - 1, 2 * coordinate.DZ - 1, 1); var vector = Vector4d.Transform(source, matrix); if (Math.Abs(vector.W - 0) < 0.00001) { return(null); } var result = Vector3d.Divide(vector.Xyz, vector.W); return(new Coordinate((decimal)result.X, (decimal)result.Y, (decimal)result.Z)); }
/// <summary>Gets the vector of where the mouse cursor currently is.</summary> /// <param name="projection"></param> /// <param name="modelView"></param> /// <param name="offsetX">will get the coords of the pixel to the right of the mouse cursor if true</param> /// <param name="offsetY">will get the coords of the pixel below the mouse cursor if true</param> private static Vector3d GetMousePosition(ref Matrix4d projection, ref Matrix4d modelView, bool offsetX, bool offsetY) { Matrix4d view; Matrix4d.Mult(ref modelView, ref projection, out view); int x = Settings.Game.Mouse.X + (offsetX ? 1 : 0); int y = Settings.Game.Height + (offsetY ? 1 : 0) - Settings.Game.Mouse.Y - 1; //invert Y, window coords are opposite float depth = 0; GL.ReadPixels(x, y, 1, 1, PixelFormat.DepthComponent, PixelType.Float, ref depth); var viewPosition = new Vector4d ( (float)x / Settings.Game.Width * 2.0f - 1.0f, //map X to -1 to 1 range (float)y / Settings.Game.Height * 2.0f - 1.0f, //map Y to -1 to 1 range depth * 2.0f - 1.0f, //map Z to -1 to 1 range 1.0f ); var temp = Vector4d.Transform(viewPosition, Matrix4d.Invert(view)); return(new Vector3d(temp.X, temp.Y, temp.Z) / temp.W); }
private static Vector4d UnProject(Matrix4d projection, Matrix4d view, Size viewport, Vector2d mouse) { Vector4d vec; vec.X = 2.0f * mouse.X / (float)viewport.Width - 1; vec.Y = -(2.0f * mouse.Y / (float)viewport.Height - 1); vec.Z = 0; vec.W = 1.0f; Matrix4d viewInv = Matrix4d.Invert(view); Matrix4d projInv = Matrix4d.Invert(projection); Vector4d.Transform(ref vec, ref projInv, out vec); Vector4d.Transform(ref vec, ref viewInv, out vec); if (vec.W > float.Epsilon || vec.W < float.Epsilon) { vec.X /= vec.W; vec.Y /= vec.W; vec.Z /= vec.W; } return(vec); }
/// <summary>Transform a Normal by the given Matrix</summary> /// <remarks> /// This calculates the inverse of the given matrix, use TransformNormalInverse if you /// already have the inverse to avoid this extra calculation /// </remarks> /// <param name="norm">The normal to transform</param> /// <param name="mat">The desired transformation</param> /// <param name="result">The transformed normal</param> public static void TransformNormal(ref Vector3d norm, ref Matrix4d mat, out Vector3d result) { Matrix4d Inverse = Matrix4d.Invert(mat); Vector3d.TransformNormalInverse(ref norm, ref Inverse, out result); }
/// <summary>Transform a Normal by the given Matrix</summary> /// <remarks> /// This calculates the inverse of the given matrix, use TransformNormalInverse if you /// already have the inverse to avoid this extra calculation /// </remarks> /// <param name="norm">The normal to transform</param> /// <param name="mat">The desired transformation</param> /// <returns>The transformed normal</returns> public static Vector3d TransformNormal(Vector3d norm, Matrix4d mat) { mat.Invert(); return(TransformNormalInverse(norm, mat)); }
private void UpdateTransposeInverse() { if (!transposeInverseDirty) { return; } transposeInverseDirty = false; transposeInverse = Matrix4d.Scale(scale); // TODO: Apply rotation transposeInverse = Matrix4d.Mult(Matrix4d.CreateTranslation(translation), transposeInverse); transposeInverse.Invert(); transposeInverse.Transpose(); }
public UMatrix4 Invert() { return(new UMatrix4(Matrix4d.Invert(Matrix))); }
/// <summary> /// Complete non-mandatory (deferred) values in the Intersection instance. /// </summary> public void Complete() { if (Solid != null) { // World coordinates. LocalToWorld = Solid.ToWorld(); WorldToLocal = LocalToWorld; WorldToLocal.Invert(); Vector3d.TransformPosition(ref CoordLocal, ref LocalToWorld, out CoordWorld); // Object coordinates. LocalToObject = Solid.ToObject(); Vector3d.TransformPosition(ref CoordLocal, ref LocalToObject, out CoordObject); // Appearance. // Reflectance model. ReflectanceModel = (IReflectanceModel)Solid.GetAttribute(PropertyName.REFLECTANCE_MODEL); if (ReflectanceModel == null) { ReflectanceModel = new PhongModel(); } // Material. Material = (IMaterial)Solid.GetAttribute(PropertyName.MATERIAL); if (Material == null) { Material = ReflectanceModel.DefaultMaterial(); } // Surface color (accepts a color provided by a Solid). if (SurfaceColor == null) { double[] col = (double[])Solid.GetAttribute(PropertyName.COLOR); SurfaceColor = (double[])((col != null) ? col.Clone() : Material.Color.Clone()); } // List of textures. Textures = Solid.GetTextures(); // Solid is responsible for completing remaining values. // Usually: TangentU, TangentV, NormalLocal, TextureCoord. Solid.CompleteIntersection(this); // Tangent space - NormalLocal, TangentU, TangentV. if (Geometry.IsZeroFast(TangentU.LengthFast)) { // I need NormalLocal if I have no tangent vecotrs. Geometry.GetTangents(ref NormalLocal, out TangentU, out TangentV); } else if (Geometry.IsZeroFast(NormalLocal.LengthFast)) { // I have local tangent vectors but no local normal. Vector3d.Cross(ref TangentU, ref TangentV, out NormalLocal); } // Normal vector: if not computed yet, 'TangentU x TangentV' will do the job. if (Geometry.IsZeroFast(Normal.LengthFast)) { Vector3d tu, tv; tu = Vector3d.TransformVector(TangentU, LocalToWorld); tv = Vector3d.TransformVector(TangentV, LocalToWorld); Vector3d.Cross(ref tu, ref tv, out Normal); } Normal.Normalize(); // to be sure... if (Enter != Front) { Vector3d.Multiply(ref Normal, -1.0, out Normal); } } if (SurfaceColor == null) { SurfaceColor = new double[] { 0.0, 0.0, 0.0 } } ; completed = true; }