From 63d424520fb0a3a9790cf4646e2e6857759813b4 Mon Sep 17 00:00:00 2001 From: James Munro Date: Wed, 21 Oct 2020 17:51:37 +0100 Subject: [PATCH] Element: Temporary hack to bypass inability for constraint matching on bools, updates to standard library (fixed vector cross product, plane functions, minor matrix updates, renaming) --- .../ElementPackages/StandardLibrary/Line.ele | 4 +- .../ElementPackages/StandardLibrary/Math.ele | 2 +- .../StandardLibrary/Matrices.ele | 74 ++++++++----------- .../ElementPackages/StandardLibrary/Plane.ele | 67 +++++++++-------- .../StandardLibrary/Vectors.ele | 8 +- Element.NET/!3-Instructions/Instruction.cs | 15 +++- .../Tests/L4-Standard-Library/Vector2.cs | 6 +- .../Tests/L4-Standard-Library/Vector3.cs | 6 +- .../Tests/L4-Standard-Library/Vector4.cs | 6 +- 9 files changed, 92 insertions(+), 96 deletions(-) diff --git a/ContentFiles/ElementPackages/StandardLibrary/Line.ele b/ContentFiles/ElementPackages/StandardLibrary/Line.ele index f204ce3e4..35d9b57b7 100644 --- a/ContentFiles/ElementPackages/StandardLibrary/Line.ele +++ b/ContentFiles/ElementPackages/StandardLibrary/Line.ele @@ -5,7 +5,7 @@ struct Line2(direction:Vector2, offset:Vector2) distanceFromPoint(line:Line2, point:Vector2):Num { w = point.sub(line.offset) - l = line.direction.normalize + l = line.direction.normalise return = w.sub(l.mul(w.dot(l))).magnitude } } @@ -15,7 +15,7 @@ struct Line3(direction:Vector3, offset:Vector3) distanceFromPoint(line:Line3, point:Vector3):Num { w = point.sub(line.offset) - l = line.direction.normalize + l = line.direction.normalise return = w.sub(l.mul(w.dot(l))).magnitude } } \ No newline at end of file diff --git a/ContentFiles/ElementPackages/StandardLibrary/Math.ele b/ContentFiles/ElementPackages/StandardLibrary/Math.ele index e55d60b29..306bd7cc6 100644 --- a/ContentFiles/ElementPackages/StandardLibrary/Math.ele +++ b/ContentFiles/ElementPackages/StandardLibrary/Math.ele @@ -13,7 +13,7 @@ random(seed:Num):Num return = t4.rem(E).div(E) } -# + #ellipse(a:Num, b:Num):Num #{ # l = a.div(b); diff --git a/ContentFiles/ElementPackages/StandardLibrary/Matrices.ele b/ContentFiles/ElementPackages/StandardLibrary/Matrices.ele index 53f9044e5..5bdf2de2f 100644 --- a/ContentFiles/ElementPackages/StandardLibrary/Matrices.ele +++ b/ContentFiles/ElementPackages/StandardLibrary/Matrices.ele @@ -1,3 +1,19 @@ +#column-major 2x2 coordinate matrix for representing linear transformations - INCOMPLETE +struct Matrix2x2(x:Vector2, y:Vector2) +{ + xRow(a:Matrix2x2) = Vector2(a.x.x, a.y.x) + yRow(a:Matrix2x2) = Vector2(a.x.y, a.y.y) + + transpose(m:Matrix2x2):Matrix2x2 = Matrix2x2(m.xRow, m.yRow) + + determinant(m:Matrix2x2):Num + { + return = m.x.x.mul(m.y.y).sub(m.x.y.mul(m.y.x)) + } +} + + + #column-major 3x3 coordinate matrix for representing linear transformations - INCOMPLETE struct Matrix3x3(x:Vector3, y:Vector3, z:Vector3) { @@ -5,20 +21,20 @@ struct Matrix3x3(x:Vector3, y:Vector3, z:Vector3) yRow(a:Matrix3x3) = Vector3(a.x.y, a.y.y, a.z.y) zRow(a:Matrix3x3) = Vector3(a.x.z, a.y.z, a.z.z) - transpose(m:Matrix4x4):Matrix3x3 = Matrix3x3(m.xRow, m.yRow, m.zRow) + transpose(m:Matrix3x3):Matrix3x3 = Matrix3x3(m.xRow, m.yRow, m.zRow) + #UNTESTED determinant(m:Matrix3x3):Num { - component_x = m.x.x.mul(m.y.y.mul(m.z.z).sub(m.y.z.mul(m.z.y))) - component_y = m.y.x.mul(m.y.y.mul(m.z.z).sub(m.y.z.mul(m.z.y))) - component_z = m.z.x.mul(m.y.y.mul(m.z.z).sub(m.y.z.mul(m.z.y))) + a = m.x.x.mul(m.y.y.mul(m.z.z).sub(m.y.z.mul(m.z.y))) + b = m.y.x.mul(m.x.x.mul(m.z.z).sub(m.x.z.mul(m.z.x))) + c = m.z.x.mul(m.x.x.mul(m.y.y).sub(m.x.y.mul(m.x.y))) - return = component_x.add(component_y).add(component_z) + return = a.sub(b).add(c) } } - #column-major 4x4 homogeneous coordinate matrix for representing affine transformations struct Matrix4x4(x:Vector4, y:Vector4, z:Vector4, w:Vector4) { @@ -38,10 +54,10 @@ struct Matrix4x4(x:Vector4, y:Vector4, z:Vector4, w:Vector4) position(m:Matrix4x4):Vector3 = Vector3(m.w.x, m.w.y, m.w.z) - rotation_submatrix(m:Matrix4x4):Matrix3x3 = Matrix3x3( - Vector3(m.x.x, m.y.x, m.z.x), - Vector3(m.x.y, m.y.y, m.z.y), - Vector3(m.x.z, m.y.z, m.z.z)) + rotation(m:Matrix4x4):Matrix3x3 = Matrix3x3( + Vector3(m.x.x, m.y.x, m.z.x), + Vector3(m.x.y, m.y.y, m.z.y), + Vector3(m.x.z, m.y.z, m.z.z)) #this makes the assumption that Matrix4x4 is affine hasInverse(a:Matrix4x4):Bool = a.rotation_submatrix.determinant.neq(0) @@ -53,12 +69,12 @@ struct Matrix4x4(x:Vector4, y:Vector4, z:Vector4, w:Vector4) Vector4(0, 0, 1, 0), Vector4(translation.x, translation.y, translation.z, 1)) - rotation(axis:Vector3, angle:Num):Matrix4x4 + fromAxisAngle(axis:Vector3, angle:Num):Matrix4x4 { c = Num.cos(angle) s = Num.sin(angle) t = 1.sub(c) - a = axis.normalize + a = axis.normalise m_00 = t.mul(a.x).mul(a.x).add(c) m_11 = t.mul(a.y).mul(a.y).add(c) @@ -127,36 +143,4 @@ struct Matrix4x4(x:Vector4, y:Vector4, z:Vector4, w:Vector4) Vector4(a.z.add(b.z)), Vector4(a.w.add(b.w))) } -} - - - - - - -#check these produce the same output -#memberwise is important... spot the typo in this mess... hopefully I didn't make any, but... -#multiply(a:Matrix4x4, b:Matrix4x4) { -# -# x = Vector4(a.x.x.mul(b.x.x).add(a.y.x.mul(b.x.y)).add(a.z.x.mul(b.x.z)).add(a.w.x.mul(b.x.w)), -# a.x.x.mul(b.y.x).add(a.y.x.mul(b.y.y)).add(a.z.x.mul(b.y.z)).add(a.w.x.mul(b.y.w)), -# a.x.x.mul(b.z.x).add(a.y.x.mul(b.z.y)).add(a.z.x.mul(b.z.z)).add(a.w.x.mul(b.z.w)), -# a.x.x.mul(b.w.x).add(a.y.x.mul(b.w.y)).add(a.z.x.mul(b.w.z)).add(a.w.x.mul(b.w.w))) -# -# y = Vector4(a.x.y.mul(b.x.x).add(a.y.y.mul(b.x.y)).add(a.z.y.mul(b.x.z)).add(a.w.y.mul(b.x.w)), -# a.x.y.mul(b.y.x).add(a.y.y.mul(b.y.y)).add(a.z.y.mul(b.y.z)).add(a.w.y.mul(b.y.w)), -# a.x.y.mul(b.z.x).add(a.y.y.mul(b.z.y)).add(a.z.y.mul(b.z.z)).add(a.w.y.mul(b.z.w)), -# a.x.y.mul(b.w.x).add(a.y.y.mul(b.w.y)).add(a.z.y.mul(b.w.z)).add(a.w.y.mul(b.w.w))) -# -# z = Vector4(a.x.z.mul(b.x.x).add(a.y.z.mul(b.x.y)).add(a.z.z.mul(b.x.z)).add(a.w.z.mul(b.x.w)), -# a.x.z.mul(b.y.x).add(a.y.z.mul(b.y.y)).add(a.z.z.mul(b.y.z)).add(a.w.z.mul(b.y.w)), -# a.x.z.mul(b.z.x).add(a.y.z.mul(b.z.y)).add(a.z.z.mul(b.z.z)).add(a.w.z.mul(b.z.w)), -# a.x.z.mul(b.w.x).add(a.y.z.mul(b.w.y)).add(a.z.z.mul(b.w.z)).add(a.w.z.mul(b.w.w))) -# -# w = Vector4(a.x.w.mul(b.x.x).add(a.y.w.mul(b.x.y)).add(a.z.w.mul(b.x.z)).add(a.w.w.mul(b.x.w)), -# a.x.w.mul(b.y.x).add(a.y.w.mul(b.y.y)).add(a.z.w.mul(b.y.z)).add(a.w.w.mul(b.y.w)), -# a.x.w.mul(b.z.x).add(a.y.w.mul(b.z.y)).add(a.z.w.mul(b.z.z)).add(a.w.w.mul(b.z.w)), -# a.x.w.mul(b.w.x).add(a.y.w.mul(b.w.y)).add(a.z.w.mul(b.w.z)).add(a.w.w.mul(b.w.w))) -# -# return = Matrix4x4(x, y, z, w) -#} \ No newline at end of file +} \ No newline at end of file diff --git a/ContentFiles/ElementPackages/StandardLibrary/Plane.ele b/ContentFiles/ElementPackages/StandardLibrary/Plane.ele index 6434d949a..740398176 100644 --- a/ContentFiles/ElementPackages/StandardLibrary/Plane.ele +++ b/ContentFiles/ElementPackages/StandardLibrary/Plane.ele @@ -1,40 +1,43 @@ struct Plane(normal:Vector3, distance:Num) { - #UNTESTED - #fromVertices(a:Vector3, b:Vector3, c:Vector3):Plane - #{ - # ba = b.sub(a) - # ca = c.sub(a) - # - # n = ba.cross(ca) - # normal = n.normalize - # d = normal.dot(a).negate - # - # return = Plane(normal, d) - #} - # - ##UNTESTED - #signedDistanceFromPoint(plane:Plane, point:Vector3):Num - #{ - # closestPointOnPlane = plane.normal.mul(plane.distance) - # projectedPoint = point.sub(closestPointOnPlane) - # return = projectedPoint.dot(planeNormal) - #} - - #UNTESTED - intersection(a:Plane, b:Plane):Line3 + fromVertices(a:Vector3, b:Vector3, c:Vector3):Plane { - direction = a.normal.Cross(b.normal) - - perpendicularVector = b.normal.Cross(direction) - denominator = a.normal.Dot(perpendicularVector) - planeAPosition = a.normal.mul(a.distance) - planeBPosition = b.normal.mul(b.distance) + ba = b.sub(a) + ca = c.sub(a) + + n = ba.cross(ca) + normal = n.normalise + d = normal.dot(a).negate + + return = Plane(normal, d) + } - planePositionDifference = planeAPosition.sub(planeBPosition) - t = a.normal.dot(planePositionDifference).div(denominator) - point = planeBPosition.add(perpendicularVector.mul(t)) + intersection(a:Plane, b:Plane):Line3 + { + #http://geomalgorithms.com/a05-_intersect-1.html + + #sanity check on normals + d1 = a.distance + n1 = a.normal.normalise + + d2 = b.distance + n2 = b.normal.normalise + + direction = n1.cross(n2) + difference = n1.mul(d2).sub(n2.mul(d1)) + point = direction.cross(difference).div(direction.magnitudeSquared) + return = Line3(direction, point) } + + signedDistanceFromPoint(plane:Plane, point:Vector3):Num + { + #creates a position vector from the origin to the nearest point on the plane + closestPointOnPlane = plane.normal.mul(plane.distance) + #creates a position vector from point on plane to target point + projectedPoint = point.sub(closestPointOnPlane) + #projects position vector onto normal to determine distance from the plane + return = projectedPoint.dot(plane.normal) + } } \ No newline at end of file diff --git a/ContentFiles/ElementPackages/StandardLibrary/Vectors.ele b/ContentFiles/ElementPackages/StandardLibrary/Vectors.ele index bd11b499f..aef3abd77 100644 --- a/ContentFiles/ElementPackages/StandardLibrary/Vectors.ele +++ b/ContentFiles/ElementPackages/StandardLibrary/Vectors.ele @@ -27,7 +27,7 @@ struct Vector2(x:Num, y:Num) #operations opposite(v:Vector2):Vector2 = Zero.sub(v) - normalize(v:Vector2):Vector2 + normalise(v:Vector2):Vector2 { #return zero vector if len = 0 len = magnitude(v) @@ -96,7 +96,7 @@ struct Vector3(x:Num, y:Num, z:Num) #operations opposite(v:Vector3):Vector3 = Zero.sub(v) - normalize(v:Vector3):Vector3 + normalise(v:Vector3):Vector3 { #return zero vector if len = 0 len = magnitude(v) @@ -154,7 +154,7 @@ struct Vector3(x:Num, y:Num, z:Num) ax_by = a.x.mul(b.y) ay_bx = a.y.mul(b.x) - return = Vector3(ay_bz.sub(az_by), az_bx.sub(ax_bz), az_by.sub(ay_bx)) + return = Vector3(ay_bz.sub(az_by), az_bx.sub(ax_bz), ax_by.sub(ay_bx)) } transformPosition(a:Vector3, matrix:Matrix4x4):Vector3 @@ -182,7 +182,7 @@ struct Vector4(x:Num, y:Num, z:Num, w:Num) #operations opposite(v:Vector4):Vector4 = Zero.sub(v) - normalize(v:Vector4):Vector4 + normalise(v:Vector4):Vector4 { #return zero vector if len = 0 len = magnitude(v) diff --git a/Element.NET/!3-Instructions/Instruction.cs b/Element.NET/!3-Instructions/Instruction.cs index 49f57e5c9..07983b67d 100644 --- a/Element.NET/!3-Instructions/Instruction.cs +++ b/Element.NET/!3-Instructions/Instruction.cs @@ -49,9 +49,18 @@ public override Result Index(Identifier id, Context context) => public override Result Deserialize(Func nextValue, Context context) { var result = nextValue(); - return result.StructImplementation == StructImplementation - ? new Result(result) - : context.Trace(EleMessageCode.SerializationError, $"'{result}' deserialized to incorrect type: is '{result.StructImplementation}' - expected '{StructImplementation}'"); + + //HACK: REMOVE THIS WHEN BUG IS FIXED, TEMPORARILY REQUIRED FOR INITIAL IMPLEMENTATION OF FORCEFIELD + if (StructImplementation is BoolStruct && result.StructImplementation is NumStruct) + { + return new Result(result); + } + + if (result.StructImplementation == StructImplementation) + return new Result(result); + else + return context.Trace(EleMessageCode.SerializationError, + $"'{result}' deserialized to incorrect type: is '{result.StructImplementation}' - expected '{StructImplementation}'"); } } diff --git a/Laboratory/Tests/L4-Standard-Library/Vector2.cs b/Laboratory/Tests/L4-Standard-Library/Vector2.cs index c51ac7965..065bf83c1 100644 --- a/Laboratory/Tests/L4-Standard-Library/Vector2.cs +++ b/Laboratory/Tests/L4-Standard-Library/Vector2.cs @@ -42,9 +42,9 @@ public void Opposite(string expression, string expected) => AssertApproxEqual(ValidatedCompilerInput, expected, expression); [ - TestCase("Vector2(0, 0).normalize", "Vector2(Num.NaN, Num.NaN)"), - TestCase("Vector2(1, 1).normalize", "Vector2(1.div(2.sqrt), 1.div(2.sqrt))"), - TestCase("Vector2(3, 4).normalize", "Vector2(3.div(5), 4.div(5))"), + TestCase("Vector2(0, 0).normalise", "Vector2(Num.NaN, Num.NaN)"), + TestCase("Vector2(1, 1).normalise", "Vector2(1.div(2.sqrt), 1.div(2.sqrt))"), + TestCase("Vector2(3, 4).normalise", "Vector2(3.div(5), 4.div(5))"), ] public void Normalize(string expression, string expected) => AssertApproxEqual(ValidatedCompilerInput, expected, expression); diff --git a/Laboratory/Tests/L4-Standard-Library/Vector3.cs b/Laboratory/Tests/L4-Standard-Library/Vector3.cs index f9da7808f..bec40bcfc 100644 --- a/Laboratory/Tests/L4-Standard-Library/Vector3.cs +++ b/Laboratory/Tests/L4-Standard-Library/Vector3.cs @@ -44,9 +44,9 @@ public void Opposite(string expression, string expected) => AssertApproxEqual(ValidatedCompilerInput, expected, expression); [ - TestCase("Vector3(0, 0, 0).normalize", "Vector3(Num.NaN, Num.NaN, Num.NaN)"), - TestCase("Vector3(1, 1, 1).normalize", "Vector3(1.div(3.sqrt), 1.div(3.sqrt), 1.div(3.sqrt))"), - TestCase("Vector3(1, 2, 2).normalize", "Vector3(1.div(3), 2.div(3), 2.div(3))"), + TestCase("Vector3(0, 0, 0).normalise", "Vector3(Num.NaN, Num.NaN, Num.NaN)"), + TestCase("Vector3(1, 1, 1).normalise", "Vector3(1.div(3.sqrt), 1.div(3.sqrt), 1.div(3.sqrt))"), + TestCase("Vector3(1, 2, 2).normalise", "Vector3(1.div(3), 2.div(3), 2.div(3))"), ] public void Normalize(string expression, string expected) => AssertApproxEqual(ValidatedCompilerInput, expected, expression); diff --git a/Laboratory/Tests/L4-Standard-Library/Vector4.cs b/Laboratory/Tests/L4-Standard-Library/Vector4.cs index f17e33192..23ac935ee 100644 --- a/Laboratory/Tests/L4-Standard-Library/Vector4.cs +++ b/Laboratory/Tests/L4-Standard-Library/Vector4.cs @@ -38,9 +38,9 @@ public void Opposite(string expression, string expected) => AssertApproxEqual(ValidatedCompilerInput, expected, expression); [ - TestCase("Vector4(0, 0, 0, 0).normalize", "Vector4(Num.NaN, Num.NaN, Num.NaN, Num.NaN)"), - TestCase("Vector4(1, 1, 1, 1).normalize", "Vector4(1.div(2), 1.div(2), 1.div(2), 1.div(2))"), - TestCase("Vector4(2, 2, 4, 5).normalize", "Vector4(2.div(7), 2.div(7), 4.div(7), 5.div(7))"), + TestCase("Vector4(0, 0, 0, 0).normalise", "Vector4(Num.NaN, Num.NaN, Num.NaN, Num.NaN)"), + TestCase("Vector4(1, 1, 1, 1).normalise", "Vector4(1.div(2), 1.div(2), 1.div(2), 1.div(2))"), + TestCase("Vector4(2, 2, 4, 5).normalise", "Vector4(2.div(7), 2.div(7), 4.div(7), 5.div(7))"), ] public void Normalize(string expression, string expected) => AssertApproxEqual(ValidatedCompilerInput, expected, expression);