public void SetModelMatrix(string name, XFORM worldMatrix) { var n = LogicalNodes.FirstOrDefault(item => item.Name == name); if (n == null) { return; } n.ModelMatrix = worldMatrix; }
private void DrawEfficientlyInNoParticularOrder(ref Matrix worldMatrix) { Renderer.LightingEnabled = true; DrawSimpleObjectsWithoutImages(worldMatrix); DrawObjectsWithImages(worldMatrix); DrawCustomDrawables(worldMatrix); DrawChildObjects(worldMatrix); Graphics.CustomBatch.Flush(); Renderer.LightingEnabled = false; }
public void SetLocalMatrix(string name, XFORM localMatrix) { var n = LogicalNodes.FirstOrDefault(item => item.Name == name); if (n == null) { return; } n.LocalMatrix = localMatrix; }
private void DrawCustomDrawables(Matrix worldMatrix) { foreach (CustomDrawable o in objectsWithDrawMethod) { if (o.IsVisible) { o.Draw(worldMatrix); } } }
/// <summary> /// Transforms a vector using the transpose of a matrix. /// </summary> /// <param name="v">Vector to transform.</param> /// <param name="matrix">Transform to tranpose and apply to the vector.</param> /// <param name="result">Transformed vector.</param> public static void TransformNormalTranspose(ref System.Numerics.Vector3 v, ref System.Numerics.Matrix4x4 matrix, out System.Numerics.Vector3 result) { float vX = v.X; float vY = v.Y; float vZ = v.Z; result.X = vX * matrix.M11 + vY * matrix.M12 + vZ * matrix.M13 + matrix.M14; result.Y = vX * matrix.M21 + vY * matrix.M22 + vZ * matrix.M23 + matrix.M24; result.Z = vX * matrix.M31 + vY * matrix.M32 + vZ * matrix.M33 + matrix.M34; }
/// <summary> /// Creates a matrix representing the given axis aligned scale. /// </summary> /// <param name="scale">Scale to be represented by the matrix.</param> /// <param name="scaleSystem.Numerics.Matrix4x4">System.Numerics.Matrix4x4 representing the given scale.</param> public static void CreateScale(ref System.Numerics.Vector3 scale, out System.Numerics.Matrix4x4 scaleSystemMatrix4x4) { scaleSystemMatrix4x4 = new System.Numerics.Matrix4x4 { M11 = scale.X, M22 = scale.Y, M33 = scale.Z, M44 = 1 }; }
/// <summary> /// Creates a matrix representing the given axis aligned scale. /// </summary> /// <param name="x">Scale along the x axis.</param> /// <param name="y">Scale along the y axis.</param> /// <param name="z">Scale along the z axis.</param> /// <param name="scaleSystem.Numerics.Matrix4x4">System.Numerics.Matrix4x4 representing the given scale.</param> public static void CreateScale(float x, float y, float z, out System.Numerics.Matrix4x4 scaleSystemMatrix4x4) { scaleSystemMatrix4x4 = new System.Numerics.Matrix4x4 { M11 = x, M22 = y, M33 = z, M44 = 1 }; }
public void Begin(ref Matrix matrix, Image texture, IShader shader = null) { Debug.Assert(!beginHasBeenCalled); beginHasBeenCalled = true; this.matrix = matrix; this.texture = texture; iTexture = 0; customShader = shader; }
private Matrix4 ConvertToMatrix4(System.Numerics.Matrix4x4 m) { var row1 = new Vector4(m.M11, m.M12, m.M13, m.M14); var row2 = new Vector4(m.M21, m.M22, m.M23, m.M24); var row3 = new Vector4(m.M31, m.M32, m.M33, m.M34); var row4 = new Vector4(m.M41, m.M42, m.M43, m.M44); var m4 = new Matrix4(row1, row2, row3, row4); return(m4); }
/// <summary> /// Sets the matrix of a bone. /// </summary> /// <param name="name">The name of the node to be set.</param> /// <param name="modelMatrix">A matrix relative to the model.</param> public void SetModelMatrix(string name, XFORM modelMatrix) { var n = LogicalNodes.FirstOrDefault(item => item.Name == name); if (n == null) { throw new ArgumentException($"{name} not found", nameof(name)); } n.ModelMatrix = modelMatrix; }
/// <summary> /// Performs a conversion from <see cref="System.Numerics.Matrix4x4"/> to <see cref="Xenko.Core.Mathematics.Matrix"/>. /// </summary> /// <param name="value">The value.</param> /// <returns>The result of the conversion.</returns> public static Matrix ToMatrix(this System.Numerics.Matrix4x4 value) { return(new Matrix() { M11 = value.M11, M12 = value.M12, M13 = value.M13, M14 = value.M14, M21 = value.M21, M22 = value.M22, M23 = value.M23, M24 = value.M24, M31 = value.M31, M32 = value.M32, M33 = value.M33, M34 = value.M34, M41 = value.M41, M42 = value.M42, M43 = value.M43, M44 = value.M44 }); }
public static Matrix ToXna(this System.Numerics.Matrix4x4 m) { return(new Matrix ( m.M11, m.M12, m.M13, m.M14, m.M21, m.M22, m.M23, m.M24, m.M31, m.M32, m.M33, m.M34, m.M41, m.M42, m.M43, m.M44 )); }
public void Draw(Image img, Vector2 position, System.Drawing.Rectangle?sourceRectangle, System.Drawing.Color color, Vector2 scale, float angle, Vector2 origin) { Debug.Assert(beginHasBeenCalled); if (iTexture >= BufferSize) { Flush(); } texture = img; float iw = img.Width; float ih = img.Height; System.Drawing.Rectangle rect = sourceRectangle.Value; Vector transf = new Vector(position.X - origin.X * scale.X + (float)rect.Width / 2 * scale.X, position.Y + origin.Y * scale.Y - (float)rect.Height / 2 * scale.Y); Matrix matrix = Matrix.CreateScale(scale.X * rect.Width, scale.Y * rect.Height, 1f) * Matrix.CreateRotationZ(angle) * Matrix.CreateTranslation((float)transf.X, (float)transf.Y, 0); Vector3[] transformedPoints = new Vector3[VerticesPerTexture]; for (int i = 0; i < transformedPoints.Length; i++) { transformedPoints[i] = Vector3.Transform(Vertices[i], matrix); } uint startIndex = (iTexture * VerticesPerTexture); for (int i = 0; i < VerticesPerTexture; i++) { uint bi = (uint)((iTexture * VerticesPerTexture) + i); vertexBuffer[bi].Position = transformedPoints[i]; } // Triangle 1 vertexBuffer[startIndex + 0].TexCoords = new Vector2(rect.Left / iw, rect.Top / ih); vertexBuffer[startIndex + 0].SetColor(color); vertexBuffer[startIndex + 1].TexCoords = new Vector2(rect.Left / iw, rect.Bottom / ih); vertexBuffer[startIndex + 1].SetColor(color); vertexBuffer[startIndex + 2].TexCoords = new Vector2(rect.Right / iw, rect.Top / ih); vertexBuffer[startIndex + 2].SetColor(color); // Triangle 2 vertexBuffer[startIndex + 3].TexCoords = new Vector2(rect.Left / iw, rect.Bottom / ih); vertexBuffer[startIndex + 3].SetColor(color); vertexBuffer[startIndex + 4].TexCoords = new Vector2(rect.Right / iw, rect.Bottom / ih); vertexBuffer[startIndex + 4].SetColor(color); vertexBuffer[startIndex + 5].TexCoords = new Vector2(rect.Right / iw, rect.Top / ih); vertexBuffer[startIndex + 5].SetColor(color); iTexture++; }
public void Begin(ref Matrix matrix, PrimitiveType p = PrimitiveType.OpenGlTriangles, IShader shader = null) { Debug.Assert(!beginHasBeenCalled); beginHasBeenCalled = true; primitivetype = p; this.matrix = matrix; iVertexBuffer = 0; iIndexBuffer = 0; customShader = shader; }
public static void Validate(this System.Numerics.Matrix4x4 m) { m.GetRight().Validate(); m.GetUp().Validate(); m.GetBackward().Validate(); m.Translation.Validate(); if (IsInvalid(m.M14) || IsInvalid(m.M24) || IsInvalid(m.M34) || IsInvalid(m.M44)) { throw new NotFiniteNumberException("Invalid value."); } }
private static void DrawTexture(IGameObject o, ref Matrix parentTransformation) { Vector position = new Vector((float)o.Position.X, (float)o.Position.Y); Vector scale = new Vector((float)o.Size.X, (float)o.Size.Y); float rotation = o.RotateImage ? (float)o.Angle.Radians : 0; if (o.IsVisible) { if (o.TextureWrapSize == Vector.Diagonal) { Graphics.ImageBatch.Draw(defaultCoords, position, scale, rotation); } else { float wx = (float)(Math.Sign(o.TextureWrapSize.X)); float wy = (float)(Math.Sign(o.TextureWrapSize.Y)); float left = (float)(-wx / 2 + 0.5); float right = (float)(wx / 2 + 0.5); float top = (float)(-wy / 2 + 0.5); float bottom = (float)(wy / 2 + 0.5); TextureCoordinates customCoords = new TextureCoordinates() { TopLeft = new Vector(left, top), TopRight = new Vector(right, top), BottomLeft = new Vector(left, bottom), BottomRight = new Vector(right, bottom), }; if (o.TextureWrapSize.X == wx && o.TextureWrapSize.Y == wy) { // Draw only once Graphics.ImageBatch.Draw(customCoords, position, scale, rotation); return; } float topLeftX = -(float)(o.TextureWrapSize.X - 1) / 2; float topLeftY = -(float)(o.TextureWrapSize.Y - 1) / 2; Vector newScale = new Vector( scale.X / (wx * (float)o.TextureWrapSize.X), scale.Y / (wy * (float)o.TextureWrapSize.Y)); for (int y = 0; y < o.TextureWrapSize.Y; y++) { for (int x = 0; x < o.TextureWrapSize.X; x++) { Vector newPosition = position + new Vector((topLeftX + x) * newScale.X, (topLeftY + y) * newScale.Y); Graphics.ImageBatch.Draw(customCoords, newPosition, newScale, rotation); } } } } }
/// <inheritdoc/> public override void Draw(Matrix parentTransformation, Matrix transformation) { if (!IsTruncated) { base.Draw(parentTransformation, transformation, Text); } else { base.Draw(parentTransformation, transformation, ShownText()); } }
// derived from: // https://math.stackexchange.com/questions/180418/calculate-rotation-matrix-to-align-vector-a-to-vector-b-in-3d // public static EuclideanTransform ComputeInitialTransformation(Point3D q1, Point3D p1) { // p2 and q2 are anchors and we map p1 to q1 vector var p2 = new Point3D(0, 0, 0); var q2 = new Point3D(0, 0, 0); var vectorP = p1 - p2; var vectorQ = q1 - q2; var vectorPQ = q2 - p2; // Translate anchor points according to map var vectorPQNum = new System.Numerics.Vector3((float)vectorPQ.X, (float)vectorPQ.Y, (float)vectorPQ.Z); vectorP.Normalize(); vectorQ.Normalize(); var cross = Vector3D.CrossProduct(vectorQ, vectorP); var s = cross.Length; var c = Vector3D.DotProduct(vectorP, vectorQ); // compute skew-symmetric cross-product matrix of v var skewSymmetricMatrix = new System.Numerics.Matrix4x4( 0, (float)-cross.Z, (float)cross.Y, 0, (float)cross.Z, 0, (float)-cross.X, 0, (float)-cross.Y, (float)cross.X, 0, 0, 0, 0, 0, 1); var squaredSkewMatrix = System.Numerics.Matrix4x4.Multiply(skewSymmetricMatrix, skewSymmetricMatrix); var lastFraction = (1 - c) / (1 - (c * c)); var R = System.Numerics.Matrix4x4.Identity + skewSymmetricMatrix + (squaredSkewMatrix * (float)lastFraction); var m = new EuclideanTransform { translation = new System.Numerics.Vector3(0, 0, 0), rotation = System.Numerics.Quaternion.CreateFromRotationMatrix(R), }; //only rotate p1 and translate both p values var rotateP = ConvertPoint3DToVector3(p1); var rotatedP1 = m.Apply(rotateP); var vectorTranslation = (ConvertPoint3DToVector3(q1) - rotatedP1); m.translation = vectorTranslation; // Check that p1 is going to be transformed to q1 var pNum = new System.Numerics.Vector3((float)p1.X, (float)p1.Y, (float)p1.Z); var result = m.Apply(pNum); return(m); }
/// <summary> /// Retrieves the translation, rotation and scale components from a 4x4 transformation matrix. /// </summary> /// <param name="transformationMatrix">4x4 transformation matrix.</param> /// <param name="translation">Translation vector.</param> /// <param name="rotation">Rotation quaternion.</param> /// <param name="scale">Scale vector.</param> public static void GetTRSFromMatrix4x4(System.Numerics.Matrix4x4 transformationMatrix, out Vector3 translation, out Quaternion rotation, out Vector3 scale) { System.Numerics.Vector3 t; System.Numerics.Vector3 s; System.Numerics.Quaternion r; System.Numerics.Matrix4x4.Decompose(transformationMatrix, out s, out r, out t); translation = new Vector3(t.X, t.Y, t.Z); rotation = new Quaternion(r.X, r.Y, r.Z, r.W); scale = new Vector3(s.X, s.Y, s.Z); }
/// <summary> /// Transforms a vector using the transpose of a matrix. /// </summary> /// <param name="v">Vector to transform.</param> /// <param name="matrix">Transform to tranpose and apply to the vector.</param> /// <param name="result">Transformed vector.</param> public static void TransformTranspose(ref System.Numerics.Vector4 v, ref System.Numerics.Matrix4x4 matrix, out System.Numerics.Vector4 result) { float vX = v.X; float vY = v.Y; float vZ = v.Z; float vW = v.W; result.X = vX * matrix.M11 + vY * matrix.M12 + vZ * matrix.M13 + vW * matrix.M14; result.Y = vX * matrix.M21 + vY * matrix.M22 + vZ * matrix.M23 + vW * matrix.M24; result.Z = vX * matrix.M31 + vY * matrix.M32 + vZ * matrix.M33 + vW * matrix.M34; result.W = vX * matrix.M41 + vY * matrix.M42 + vZ * matrix.M43 + vW * matrix.M44; }
/// <summary> /// Helper to convert from Right hand to Left hand coordinates using <see cref="System.Numerics.Matrix4x4"/>. /// https://docs.microsoft.com/en-us/windows/mixed-reality/unity-xrdevice-advanced#converting-between-coordinate-systems /// </summary> /// <param name="matrix">The Right handed <see cref="System.Numerics.Matrix4x4"/>.</param> /// <returns>The <see cref="System.Numerics.Matrix4x4"/> in left hand form.</returns> public static System.Numerics.Matrix4x4 RightToLeftHanded(System.Numerics.Matrix4x4 matrix) { matrix.M13 = -matrix.M13; matrix.M23 = -matrix.M23; matrix.M43 = -matrix.M43; matrix.M31 = -matrix.M31; matrix.M32 = -matrix.M32; matrix.M34 = -matrix.M34; return(matrix); }
/// <summary> /// Inverts the matrix. /// </summary> /// <param name="m">System.Numerics.Matrix4x4 to invert.</param> /// <param name="inverted">Inverted version of the matrix.</param> public static void Invert(ref System.Numerics.Matrix4x4 m, out System.Numerics.Matrix4x4 inverted) { float s0 = m.M11 * m.M22 - m.M21 * m.M12; float s1 = m.M11 * m.M23 - m.M21 * m.M13; float s2 = m.M11 * m.M24 - m.M21 * m.M14; float s3 = m.M12 * m.M23 - m.M22 * m.M13; float s4 = m.M12 * m.M24 - m.M22 * m.M14; float s5 = m.M13 * m.M24 - m.M23 * m.M14; float c5 = m.M33 * m.M44 - m.M43 * m.M34; float c4 = m.M32 * m.M44 - m.M42 * m.M34; float c3 = m.M32 * m.M43 - m.M42 * m.M33; float c2 = m.M31 * m.M44 - m.M41 * m.M34; float c1 = m.M31 * m.M43 - m.M41 * m.M33; float c0 = m.M31 * m.M42 - m.M41 * m.M32; float inverseDeterminant = 1.0f / (s0 * c5 - s1 * c4 + s2 * c3 + s3 * c2 - s4 * c1 + s5 * c0); float m11 = m.M11; float m12 = m.M12; float m13 = m.M13; float m14 = m.M14; float m21 = m.M21; float m22 = m.M22; float m23 = m.M23; float m31 = m.M31; float m32 = m.M32; float m33 = m.M33; float m41 = m.M41; float m42 = m.M42; inverted.M11 = (m.M22 * c5 - m.M23 * c4 + m.M24 * c3) * inverseDeterminant; inverted.M12 = (-m.M12 * c5 + m.M13 * c4 - m.M14 * c3) * inverseDeterminant; inverted.M13 = (m.M42 * s5 - m.M43 * s4 + m.M44 * s3) * inverseDeterminant; inverted.M14 = (-m.M32 * s5 + m.M33 * s4 - m.M34 * s3) * inverseDeterminant; inverted.M21 = (-m.M21 * c5 + m.M23 * c2 - m.M24 * c1) * inverseDeterminant; inverted.M22 = (m11 * c5 - m13 * c2 + m14 * c1) * inverseDeterminant; inverted.M23 = (-m.M41 * s5 + m.M43 * s2 - m.M44 * s1) * inverseDeterminant; inverted.M24 = (m.M31 * s5 - m.M33 * s2 + m.M34 * s1) * inverseDeterminant; inverted.M31 = (m21 * c4 - m22 * c2 + m.M24 * c0) * inverseDeterminant; inverted.M32 = (-m11 * c4 + m12 * c2 - m14 * c0) * inverseDeterminant; inverted.M33 = (m.M41 * s4 - m.M42 * s2 + m.M44 * s0) * inverseDeterminant; inverted.M34 = (-m31 * s4 + m32 * s2 - m.M34 * s0) * inverseDeterminant; inverted.M41 = (-m21 * c3 + m22 * c1 - m23 * c0) * inverseDeterminant; inverted.M42 = (m11 * c3 - m12 * c1 + m13 * c0) * inverseDeterminant; inverted.M43 = (-m41 * s3 + m42 * s1 - m.M43 * s0) * inverseDeterminant; inverted.M44 = (m31 * s3 - m32 * s1 + m33 * s0) * inverseDeterminant; }
/// <summary> /// Creates a matrix representing a translation. /// </summary> /// <param name="translation">Translation to be represented by the matrix.</param> /// <param name="translationSystem.Numerics.Matrix4x4">System.Numerics.Matrix4x4 representing the given translation.</param> public static void CreateTranslation(ref System.Numerics.Vector3 translation, out System.Numerics.Matrix4x4 translationSystemMatrix4x4) { translationSystemMatrix4x4 = new System.Numerics.Matrix4x4 { M11 = 1, M22 = 1, M33 = 1, M44 = 1, M41 = translation.X, M42 = translation.Y, M43 = translation.Z }; }
public static NMatrix GetAbsoluteNMatrix(this FLVER.Bone b, List <FLVER.Bone> bones) { NMatrix result = NMatrix.Identity; var parentBone = b; while (parentBone != null) { var m = parentBone.GetNMatrix(); result *= m; parentBone = parentBone.GetParent(bones); } return(result); }
/// <inheritdoc/> public override void Draw(Matrix parentTransformation, Matrix transformation) { if (messages.Count == 0) { return; } Graphics.FontRenderer.Begin(); for (int i = 0; i < Math.Min(messages.Count, MaxMessageCount); i++) { Font.SpriteFont.DrawText(Graphics.FontRenderer, messages[i].Text, Position - new Vector(Width / 2, i * fontHeight - Height / 2), messages[i].Color.ToSystemDrawing()); } base.Draw(parentTransformation, transformation); }
/// <summary> /// Adds the two matrices together on a per-element basis. /// </summary> /// <param name="a">First matrix to add.</param> /// <param name="b">Second matrix to add.</param> /// <param name="result">Sum of the two matrices.</param> public static void Add(ref Matrix2x2 a, ref System.Numerics.Matrix4x4 b, out Matrix2x2 result) { float m11 = a.M11 + b.M11; float m12 = a.M12 + b.M12; float m21 = a.M21 + b.M21; float m22 = a.M22 + b.M22; result.M11 = m11; result.M12 = m12; result.M21 = m21; result.M22 = m22; }
/// <summary> /// Multiplies the two matrices. /// </summary> /// <param name="a">First matrix to multiply.</param> /// <param name="b">Second matrix to multiply.</param> /// <param name="result">Product of the multiplication.</param> public static void Multiply(ref System.Numerics.Matrix4x4 a, ref Matrix2x2 b, out Matrix2x2 result) { float resultM11 = a.M11 * b.M11 + a.M12 * b.M21; float resultM12 = a.M11 * b.M12 + a.M12 * b.M22; float resultM21 = a.M21 * b.M11 + a.M22 * b.M21; float resultM22 = a.M21 * b.M12 + a.M22 * b.M22; result.M11 = resultM11; result.M12 = resultM12; result.M21 = resultM21; result.M22 = resultM22; }
private void SetTransformToTimeWithinCurrentLoop(float localTime) { // Get sample at specified time. var sampleAtTime = SampleRootMotionData(localTime); // Rotate sample translation to be relative to loop start transform rotation. var translation = NVector3.Transform(sampleAtTime.XYZ(), NMatrix.CreateRotationY(LoopStartTransform.W)); sampleAtTime.X = translation.X; sampleAtTime.Y = translation.Y; sampleAtTime.Z = translation.Z; CurrentTransform = LoopStartTransform + sampleAtTime; }
protected void ProjectLayerOntoSurface(IImageProcessingContext <Rgba32> context, Matrix <float> transformMatrix) { var matrix4x4 = new System.Numerics.Matrix4x4( transformMatrix[0, 0], transformMatrix[1, 0], 0, transformMatrix[2, 0], transformMatrix[0, 1], transformMatrix[1, 1], 0, transformMatrix[2, 1], 0, 0, 1, 0, transformMatrix[0, 2], transformMatrix[1, 2], 0, transformMatrix[2, 2] ); context.Transform(matrix4x4, KnownResamplers.Lanczos3); foreach (var mask in Masks) { context.Opacity(0, mask); } }
public void RotationMatrix_ToQuaternion_VsSystemNumerics() { RotationMatrix m; Quaternion q; SysMatrix44 m44, m44bis; SysQuat sq; Vector vecX, vecY; int dir; int runs = 500; for (var i = 0; i < runs; i++) { if (i < 0.5 * runs) { vecX = Vector.RandomFromDoubles(-100, 100); vecY = Vector.RandomFromDoubles(-100, 100); } else { vecX = Vector.RandomFromInts(-1, 1); vecY = Vector.RandomFromInts(-1, 1); } dir = Vector.CompareDirections(vecX, vecY); m = new RotationMatrix(vecX, vecY); q = m.ToQuaternion(); Trace.WriteLine(""); Trace.WriteLine(vecX + " " + vecY + " dir:" + dir); Trace.WriteLine(m); Trace.WriteLine(q); // Use the matrix's orthogonal values to create a M44 matrix with just rotation values: m44 = new SysMatrix44((float)m.m00, (float)m.m01, (float)m.m02, 0, (float)m.m10, (float)m.m11, (float)m.m12, 0, (float)m.m20, (float)m.m21, (float)m.m22, 0, 0, 0, 0, 1); m44 = SysMatrix44.Transpose(m44); // Numerics.Matrix4x4 uses a transposed convention, meaning the translation vector is horizontal in m41-42-43 instead of vertical in m14-24-34 sq = SysQuat.CreateFromRotationMatrix(m44); m44bis = SysMatrix44.CreateFromQuaternion(sq); Trace.WriteLine(m44); Trace.WriteLine(sq); Trace.WriteLine(m44bis); Assert.IsTrue(q.IsEquivalent(new Quaternion(sq.W, sq.X, sq.Y, sq.Z)), "Quaternions are not equivalent!"); } }
/// <summary> /// Creates a 4x4 matrix from a 3x3 matrix. /// </summary> /// <param name="a">3x3 matrix.</param> /// <returns>Created 4x4 matrix.</returns> public static System.Numerics.Matrix4x4 ToMatrix4X4(Matrix3x3 a) { #if !WINDOWS System.Numerics.Matrix4x4 b = new System.Numerics.Matrix4x4(); #else System.Numerics.Matrix4x4 b; #endif b.M11 = a.M11; b.M12 = a.M12; b.M13 = a.M13; b.M21 = a.M21; b.M22 = a.M22; b.M23 = a.M23; b.M31 = a.M31; b.M32 = a.M32; b.M33 = a.M33; b.M44 = 1; b.M14 = 0; b.M24 = 0; b.M34 = 0; b.M41 = 0; b.M42 = 0; b.M43 = 0; return b; }
/// <summary> /// Creates a 4x4 matrix from a 3x3 matrix. /// </summary> /// <param name="a">3x3 matrix.</param> /// <param name="b">Created 4x4 matrix.</param> public static void ToMatrix4X4(ref Matrix3x3 a, out System.Numerics.Matrix4x4 b) { #if !WINDOWS b = new System.Numerics.Matrix4x4(); #endif b.M11 = a.M11; b.M12 = a.M12; b.M13 = a.M13; b.M21 = a.M21; b.M22 = a.M22; b.M23 = a.M23; b.M31 = a.M31; b.M32 = a.M32; b.M33 = a.M33; b.M44 = 1; b.M14 = 0; b.M24 = 0; b.M34 = 0; b.M41 = 0; b.M42 = 0; b.M43 = 0; }
/// <summary> /// This is a javascript application. /// </summary> /// <param name="page">HTML document rendered by the web server which can now be enhanced.</param> public Application(IDefault page = null) { var size = 600; var gl = new WebGLRenderingContext(); var canvas = gl.canvas.AttachToDocument(); Native.document.body.style.overflow = IStyle.OverflowEnum.hidden; canvas.style.SetLocation(0, 0, size, size); canvas.width = size; canvas.height = size; var gl_viewportWidth = size; var gl_viewportHeight = size; // can AssetLibrary create a special type // and define the variables // for it we need to parse glsl? // Geometry var shaderProgram = gl.createProgram( new GeometryVertexShader(), new GeometryFragmentShader() ); gl.linkProgram(shaderProgram); gl.useProgram(shaderProgram); var shaderProgram_vertexPositionAttribute = gl.getAttribLocation(shaderProgram, "aVertexPosition"); gl.enableVertexAttribArray((uint)shaderProgram_vertexPositionAttribute); // new in lesson 02 var shaderProgram_vertexColorAttribute = gl.getAttribLocation(shaderProgram, "aVertexColor"); gl.enableVertexAttribArray((uint)shaderProgram_vertexColorAttribute); var shaderProgram_pMatrixUniform = gl.getUniformLocation(shaderProgram, "uPMatrix"); var shaderProgram_mvMatrixUniform = gl.getUniformLocation(shaderProgram, "uMVMatrix"); // https://hacks.mozilla.org/2014/10/introducing-simd-js/ // https://github.com/toji/gl-matrix/blob/master/src/gl-matrix/mat4.js // http://www.i-programmer.info/news/167-javascript/8578-chrome-to-support-simdjs.html // https://code.google.com/p/v8/issues/detail?id=2228 var SIMD_mat4 = new System.Numerics.Matrix4x4(); var SIMD_mat4s = new Stack<System.Numerics.Matrix4x4>(); // can we convert this code to NDK friendly non GC library? // for gearVR 90FOV and cardboard wearality 150FOV #region __mat4 var __mat4 = new { // X:\jsc.svn\examples\javascript\Test\TestFloatArray\TestFloatArray\Application.cs // https://sites.google.com/a/jsc-solutions.net/backlog/knowledge-base/2015/20150706/20150708 // generic in the sens of caller choosing is the return type a new struct or out ref? perspective = new Func<float[], float, float, float, float, float[]>( (that, fovy, aspect, near, far) => { var f = 1.0f / (float)Math.Tan(fovy / 2f); var nf = 1f / (near - far); that[0] = f / aspect; that[1] = 0; that[2] = 0; that[3] = 0; that[4] = 0; that[5] = f; that[6] = 0; that[7] = 0; that[8] = 0; that[9] = 0; that[10] = (far + near) * nf; that[11] = -1; that[12] = 0; that[13] = 0; that[14] = (2 * far * near) * nf; that[15] = 0; return that; }), // reset content of mat4 identity = new Func<float[], float[]>( that => { //Array.Copy() //var xx =&that; var x = new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, }; //is this the best way to update array contents? x.CopyTo(that, 0); return x; } ), create = new Func<float[]>( () => //new mat4() new float[] { 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, } ), #region not used? clone = new Func<float[], float[]>( smat4 => //new mat4() new float[] { smat4[0], smat4[1], smat4[2], smat4[3], smat4[4], smat4[5], smat4[6], smat4[7], smat4[8], smat4[9], smat4[10], smat4[11], smat4[12], smat4[13], smat4[14], smat4[15], } ) #endregion , // X:\jsc.svn\examples\java\android\vr\OVRWindWheelNDK\OVRWindWheelNDK\References\VrApi.ovrMatrix4f.cs translate = new Func<float[], float[], float[], float[]>( (float[] that, float[] output, float[] xyz) => { float x = xyz[0], y = xyz[1], z = xyz[2]; if (output == that) { that[12] = output[0] * x + output[4] * y + output[8] * z + output[12]; that[13] = output[1] * x + output[5] * y + output[9] * z + output[13]; that[14] = output[2] * x + output[6] * y + output[10] * z + output[14]; that[15] = output[3] * x + output[7] * y + output[11] * z + output[15]; return that; } float a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23; a00 = output[0]; a01 = output[1]; a02 = output[2]; a03 = output[3]; a10 = output[4]; a11 = output[5]; a12 = output[6]; a13 = output[7]; a20 = output[8]; a21 = output[9]; a22 = output[10]; a23 = output[11]; that[0] = a00; that[1] = a01; that[2] = a02; that[3] = a03; that[4] = a10; that[5] = a11; that[6] = a12; that[7] = a13; that[8] = a20; that[9] = a21; that[10] = a22; that[11] = a23; that[12] = a00 * x + a10 * y + a20 * z + output[12]; that[13] = a01 * x + a11 * y + a21 * z + output[13]; that[14] = a02 * x + a12 * y + a22 * z + output[14]; that[15] = a03 * x + a13 * y + a23 * z + output[15]; return that; } ), rotate = new Func<float[], float[], float, float[], float[]>( (that, a, rad, axis) => { float x = axis[0], y = axis[1], z = axis[2]; float len = (float)Math.Sqrt(x * x + y * y + z * z), s, c, t, a00, a01, a02, a03, a10, a11, a12, a13, a20, a21, a22, a23, b00, b01, b02, b10, b11, b12, b20, b21, b22; if (Math.Abs(len) < float.Epsilon) return that; len = 1f / len; x *= len; y *= len; z *= len; s = (float)Math.Sin(rad); c = (float)Math.Cos(rad); t = 1 - c; a00 = a[0]; a01 = a[1]; a02 = a[2]; a03 = a[3]; a10 = a[4]; a11 = a[5]; a12 = a[6]; a13 = a[7]; a20 = a[8]; a21 = a[9]; a22 = a[10]; a23 = a[11]; // Construct the elements of the rotation matrix b00 = x * x * t + c; b01 = y * x * t + z * s; b02 = z * x * t - y * s; b10 = x * y * t - z * s; b11 = y * y * t + c; b12 = z * y * t + x * s; b20 = x * z * t + y * s; b21 = y * z * t - x * s; b22 = z * z * t + c; // Perform rotation-specific matrix multiplication that[0] = a00 * b00 + a10 * b01 + a20 * b02; that[1] = a01 * b00 + a11 * b01 + a21 * b02; that[2] = a02 * b00 + a12 * b01 + a22 * b02; that[3] = a03 * b00 + a13 * b01 + a23 * b02; that[4] = a00 * b10 + a10 * b11 + a20 * b12; that[5] = a01 * b10 + a11 * b11 + a21 * b12; that[6] = a02 * b10 + a12 * b11 + a22 * b12; that[7] = a03 * b10 + a13 * b11 + a23 * b12; that[8] = a00 * b20 + a10 * b21 + a20 * b22; that[9] = a01 * b20 + a11 * b21 + a21 * b22; that[10] = a02 * b20 + a12 * b21 + a22 * b22; that[11] = a03 * b20 + a13 * b21 + a23 * b22; if (a != that) { // If the source and destination differ, copy the unchanged last row that[12] = a[12]; that[13] = a[13]; that[14] = a[14]; that[15] = a[15]; } return that; } ) }; #endregion // set to identity var mvMatrix = __mat4.create(); var mvMatrixStack = new Stack<float[]>(); // set to perspective var pMatrix = __mat4.create(); #region new in lesson 03 // how would this translate to non GC, NDK? Action mvPushMatrix = delegate { var copy = __mat4.create(); mvMatrix.CopyTo(copy, 0); //glMatrix.mat4.set(mvMatrix, copy); mvMatrixStack.Push(copy); }; Action mvPopMatrix = delegate { mvMatrix = mvMatrixStack.Pop(); }; #endregion #region setMatrixUniforms Action setMatrixUniforms = delegate { gl.uniformMatrix4fv(shaderProgram_pMatrixUniform, false, pMatrix); gl.uniformMatrix4fv(shaderProgram_mvMatrixUniform, false, mvMatrix); }; #endregion #region init buffers #region cube var cubeVertexPositionBuffer = new WebGLBuffer(gl); gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer); var cubesize = 1.0f * 0.05f; var vertices = new[]{ // Front face -cubesize, -cubesize, cubesize, cubesize, -cubesize, cubesize, cubesize, cubesize, cubesize, -cubesize, cubesize, cubesize, // Back face -cubesize, -cubesize, -cubesize, -cubesize, cubesize, -cubesize, cubesize, cubesize, -cubesize, cubesize, -cubesize, -cubesize, // Top face -cubesize, cubesize, -cubesize, -cubesize, cubesize, cubesize, cubesize, cubesize, cubesize, cubesize, cubesize, -cubesize, // Bottom face -cubesize, -cubesize, -cubesize, cubesize, -cubesize, -cubesize, cubesize, -cubesize, cubesize, -cubesize, -cubesize, cubesize, // Right face cubesize, -cubesize, -cubesize, cubesize, cubesize, -cubesize, cubesize, cubesize, cubesize, cubesize, -cubesize, cubesize, // Left face -cubesize, -cubesize, -cubesize, -cubesize, -cubesize, cubesize, -cubesize, cubesize, cubesize, -cubesize, cubesize, -cubesize }; gl.bufferData(gl.ARRAY_BUFFER, vertices, gl.STATIC_DRAW); var cubeVertexPositionBuffer_itemSize = 3; var cubeVertexPositionBuffer_numItems = 6 * 6; var squareVertexColorBuffer = new WebGLBuffer(gl); gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer); // 216, 191, 18 var colors = new[]{ 1.0f, 0.6f, 0.0f, 1.0f, // Front face 1.0f, 0.6f, 0.0f, 1.0f, // Front face 1.0f, 0.6f, 0.0f, 1.0f, // Front face 1.0f, 0.6f, 0.0f, 1.0f, // Front face 0.8f, 0.4f, 0.0f, 1.0f, // Back face 0.8f, 0.4f, 0.0f, 1.0f, // Back face 0.8f, 0.4f, 0.0f, 1.0f, // Back face 0.8f, 0.4f, 0.0f, 1.0f, // Back face 0.9f, 0.5f, 0.0f, 1.0f, // Top face 0.9f, 0.5f, 0.0f, 1.0f, // Top face 0.9f, 0.5f, 0.0f, 1.0f, // Top face 0.9f, 0.5f, 0.0f, 1.0f, // Top face 1.0f, 0.5f, 0.0f, 1.0f, // Bottom face 1.0f, 0.5f, 0.0f, 1.0f, // Bottom face 1.0f, 0.5f, 0.0f, 1.0f, // Bottom face 1.0f, 0.5f, 0.0f, 1.0f, // Bottom face 1.0f, 0.8f, 0.0f, 1.0f, // Right face 1.0f, 0.8f, 0.0f, 1.0f, // Right face 1.0f, 0.8f, 0.0f, 1.0f, // Right face 1.0f, 0.8f, 0.0f, 1.0f, // Right face 1.0f, 0.8f, 0.0f, 1.0f, // Left face 1.0f, 0.8f, 0.0f, 1.0f, // Left face 1.0f, 0.8f, 0.0f, 1.0f, // Left face 1.0f, 0.8f, 0.0f, 1.0f // Left face }; gl.bufferData(gl.ARRAY_BUFFER, colors, gl.STATIC_DRAW); var cubeVertexColorBuffer_itemSize = 4; var cubeVertexColorBuffer_numItems = 24; // ELEMENT_ARRAY_BUFFER : WebGLBuffer? // drawElements var cubeVertexIndexBuffer = new WebGLBuffer(gl); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer); //var cubeVertexIndices = new UInt16[]{ var cubeVertexIndices = new byte[]{ 0, 1, 2, 0, 2, 3, // Front face 4, 5, 6, 4, 6, 7, // Back face 8, 9, 10, 8, 10, 11, // Top face 12, 13, 14, 12, 14, 15, // Bottom face 16, 17, 18, 16, 18, 19, // Right face 20, 21, 22, 20, 22, 23 // Left face }; // ushort[]? //gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint16Array(cubeVertexIndices), gl.STATIC_DRAW); gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndices, gl.STATIC_DRAW); var cubeVertexIndexBuffer_itemSize = 1; var cubeVertexIndexBuffer_numItems = 36; #endregion #endregion gl.clearColor(0.0f, 0.0f, 0.0f, alpha: 1.0f); gl.enable(gl.DEPTH_TEST); var rWindDelta = 0.0f; var rCubeDelta = 1.0f; if (page != null) { #region WindLeft page.WindLeft.onmousedown += delegate { rWindDelta = -2.0f; }; page.WindLeft.onmouseup += delegate { rWindDelta = 0.0f; }; #endregion #region WindRight page.WindRight.onmousedown += delegate { rWindDelta = 2.0f; }; page.WindRight.onmouseup += delegate { rWindDelta = 0.0f; }; #endregion #region SpeedSlow page.SpeedSlow.onmousedown += delegate { rCubeDelta = 0.1f; }; page.SpeedSlow.onmouseup += delegate { rCubeDelta = 1.0f; }; #endregion #region SpeedFast page.SpeedFast.onmousedown += delegate { rCubeDelta = 4.0f; }; page.SpeedFast.onmouseup += delegate { rCubeDelta = 1.0f; }; #endregion } #region animate var rCube = 0f; var rWind = 0f; var lastTime = 0L; Action animate = delegate { var timeNow = new IDate().getTime(); if (lastTime != 0) { var elapsed = timeNow - lastTime; rCube -= ((75 * elapsed) / 1000.0f) * rCubeDelta; rWind -= ((75 * elapsed) / 1000.0f) * rWindDelta; } lastTime = timeNow; }; #endregion #region degToRad Func<float, float> degToRad = (degrees) => { return degrees * (f)Math.PI / 180f; }; #endregion #region drawScene Action drawScene = delegate { gl.viewport(0, 0, gl_viewportWidth, gl_viewportHeight); gl.clear(gl.COLOR_BUFFER_BIT | gl.DEPTH_BUFFER_BIT); // glMatrix.mat4.perspective( // 45f, // (float)gl_viewportWidth / (float)gl_viewportHeight, // 0.1f, // 100.0f, // pMatrix //); __mat4.perspective( pMatrix, 45f, (float)gl_viewportWidth / (float)gl_viewportHeight, 0.1f, 100.0f ); __mat4.identity(mvMatrix); //glMatrix.mat4.identity(mvMatrix); __mat4.translate(mvMatrix, mvMatrix, new float[] { -1.5f, 0.0f, -7.0f }); //glMatrix.mat4.translate(mvMatrix, new float[] { -1.5f, 0.0f, -7.0f }); mvPushMatrix(); //glMatrix.mat4.rotate(mvMatrix, degToRad(rWind), new float[] { 0f, 1f, 0f }); __mat4.rotate(mvMatrix, mvMatrix, degToRad(rWind), new float[] { 0, 1f, 0f }); #region DrawFrameworkWingAtX Action<float, float> DrawFrameworkWingAtX = (WingX, WingY) => { #region draw center cube mvPushMatrix(); __mat4.translate(mvMatrix, mvMatrix, new float[] { cubesize * WingX, cubesize * WingY, 0 }); //glMatrix.mat4.translate(mvMatrix, new float[] { cubesize * WingX, cubesize * WingY, 0 }); gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer); gl.vertexAttribPointer((uint)shaderProgram_vertexPositionAttribute, cubeVertexPositionBuffer_itemSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer); gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer); setMatrixUniforms(); //gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_SHORT, 0); gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_BYTE, 0); mvPopMatrix(); #endregion }; #endregion #region DrawWingAtX Action<int, int, float, float> DrawWingAtX = (WingX, WingSize, WingRotationMultiplier, WingRotationOffset) => { mvPushMatrix(); __mat4.translate(mvMatrix, mvMatrix, new float[] { cubesize * WingX, 0, 0 }); //glMatrix.mat4.translate(mvMatrix, new float[] { cubesize * WingX, 0, 0 }); if (WingRotationOffset == 0) { DrawFrameworkWingAtX(0, 0); } #region DrawWingPart Action<float> DrawWingPart = PartIndex => { mvPushMatrix(); //glMatrix.mat4.rotate(mvMatrix, degToRad(WingRotationOffset + (rCube * WingRotationMultiplier)), new float[] { 1f, 0f, 0f }); __mat4.rotate(mvMatrix, mvMatrix, degToRad(WingRotationOffset + (rCube * WingRotationMultiplier)), new float[] { 1f, 0f, 0f }); //glMatrix.mat4.translate(mvMatrix, new float[] { 0f, cubesize * PartIndex * 2, 0 }); __mat4.translate(mvMatrix, mvMatrix, new float[] { 0f, cubesize * PartIndex * 2, 0 }); gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer); gl.vertexAttribPointer((uint)shaderProgram_vertexPositionAttribute, cubeVertexPositionBuffer_itemSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer); gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer); setMatrixUniforms(); //gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_SHORT, 0); gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_BYTE, 0); mvPopMatrix(); }; #endregion #region DrawWingWithSize Action<int> DrawWingWithSize = length => { for (int i = 4; i < length; i++) { DrawWingPart(i * 1.0f); DrawWingPart(-i * 1.0f); } }; #endregion DrawWingWithSize(WingSize); mvPopMatrix(); }; #endregion var x = 8; DrawFrameworkWingAtX(x - 8, 0); for (int i = 0; i < 24; i++) { DrawFrameworkWingAtX(x - 8, -2.0f * i); } DrawWingAtX(x - 6, 0, 1f, 0); DrawWingAtX(x - 4, 0, 1f, 0); DrawWingAtX(x - 2, 0, 1f, 0); DrawWingAtX(x + 0, 16, 1f, 0); DrawWingAtX(x + 0, 16, 1f, 30); DrawWingAtX(x + 0, 16, 1f, 60); DrawWingAtX(x + 0, 16, 1f, 90); DrawWingAtX(x + 0, 16, 1f, 120); DrawWingAtX(x + 0, 16, 1f, 150); DrawWingAtX(x + 2, 0, 1f, 0); DrawWingAtX(x + 4, 0, 1f, 0); DrawWingAtX(x + 6, 0, 1f, 0); DrawWingAtX(x + 8, 12, 0.4f, 0); DrawWingAtX(x + 8, 12, 0.4f, 60); DrawWingAtX(x + 8, 12, 0.4f, 120); DrawWingAtX(x + 8 + 2, 0, 1f, 0); DrawWingAtX(x + 8 + 4, 0, 1f, 0); DrawWingAtX(x + 8 + 6, 0, 1f, 0); DrawWingAtX(x + 16, 8, 0.3f, 0); DrawWingAtX(x + 16, 8, 0.3f, 90); mvPopMatrix(); #region draw cube on the right to remind where we started //glMatrix.mat4.translate(mvMatrix, new float[] { 3.0f, 2.0f, 0.0f }); __mat4.translate(mvMatrix, mvMatrix, new float[] { 3.0f, 2.0f, 0.0f }); mvPushMatrix(); //glMatrix.mat4.rotate(mvMatrix, degToRad(rCube), new float[] { 1f, 1f, 1f }); __mat4.rotate(mvMatrix, mvMatrix, degToRad(rCube), new float[] { 1f, 1f, 1f }); gl.bindBuffer(gl.ARRAY_BUFFER, cubeVertexPositionBuffer); gl.vertexAttribPointer((uint)shaderProgram_vertexPositionAttribute, cubeVertexPositionBuffer_itemSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer); gl.vertexAttribPointer((uint)shaderProgram_vertexColorAttribute, cubeVertexColorBuffer_itemSize, gl.FLOAT, false, 0, 0); gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, cubeVertexIndexBuffer); setMatrixUniforms(); //gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_SHORT, 0); gl.drawElements(gl.TRIANGLES, cubeVertexPositionBuffer_numItems, gl.UNSIGNED_BYTE, 0); mvPopMatrix(); #endregion }; drawScene(); #endregion #region AtResize Action AtResize = delegate { gl_viewportWidth = Native.window.Width; gl_viewportHeight = Native.window.Height; canvas.style.SetLocation(0, 0, gl_viewportWidth, gl_viewportHeight); canvas.width = gl_viewportWidth; canvas.height = gl_viewportHeight; }; Native.window.onresize += e => { AtResize(); }; AtResize(); #endregion #region IsDisposed var IsDisposed = false; this.Dispose = delegate { if (IsDisposed) return; IsDisposed = true; canvas.Orphanize(); }; #endregion #region requestFullscreen Native.document.body.ondblclick += delegate { if (IsDisposed) return; // http://tutorialzine.com/2012/02/enhance-your-website-fullscreen-api/ Native.document.body.requestFullscreen(); }; #endregion //var c = 0; #region tick Native.window.onframe += e => { if (IsDisposed) return; //c++; // frameID Native.document.title = "" + e.counter; drawScene(); animate(); }; #endregion if (page != null) page.Mission.Orphanize().AttachToDocument().style.SetLocation(left: size - 56, top: 16); }