Open xposure opened 7 years ago
I implemented this myself in what I would call a very hacky way, but putting it here in case anyone else is interested or is looking for a foundation to do it the right way.
Added to MatrixType.cs
right before matrix-vector-multiplication
if (Columns == 4 && Rows == 4)
{
var cols = new int[] { 0, 1, 3 };
foreach (var line in "Executes a matrix-vector-multiplication.".AsComment()) yield return line;
yield return string.Format("public static {0} operator*({1} m, {2} v) => new {0}({3});", BaseType.Prefix + "vec" + 2, NameThat, BaseType.Prefix + "vec" + 2,
2.ForIndexUpTo(r => cols.ForEach(c => c < 2 ? "m.m" + c + r + " * v." + "xyzw"[c] : "m.m" + c + r).Aggregated(" + ")).CommaSeparated());
foreach (var line in "Executes a matrix-vector-multiplication.".AsComment()) yield return line;
yield return string.Format("public static {0} operator*({1} m, {2} v) => new {0}({3});", BaseType.Prefix + "vec" + 3, NameThat, BaseType.Prefix + "vec" + 3,
3.ForIndexUpTo(r => Columns.ForIndexUpTo(c => c < 3 ? "m.m" + c + r + " * v." + "xyzw"[c] : "m.m" + c + r).Aggregated(" + ")).CommaSeparated());
}
Looking at monogame, vec2 needs to skip m2X, I couldn't figure out a way to do that with ForIndexUpTo and I didn't want to modify Aggregrated to skip empty strings so I choose to add this method to Extensions.cs
public static IEnumerable<T> ForEach<T>(this int[] n, Func<int, T> f)
{
for (var i = 0; i < n.Length; i++)
yield return f(n[i]);
}
Unfortunately, it is ambiguous how to implement that.
if you have M * new vec2(x,y)
it could be
A: M * new vec4(x,y,0,1)
(treating the vector as a point), or
B: M * new vec4(x,y,0,0)
(treating the vector as a vector).
Both are valid interpretations, so I'm a bit reluctant to decide for either for operator*
.
However, we can discuss about functions that do this, e.g. Mat4.TransformPoint
and Mat4.TransformVector
.
That makes sense. One question, are you trying to keep this close to glm? I have other things I have changed and was wondering if its something you would want to implement.
For example I added perpendicular to 2d after // angle
// perpendicular 2d
if (Components == 2)
{
if (BaseType.IsSigned)
{
yield return new Property("Perpendicular", this)
{
GetterLine = "new " + Name + "(y, -x)",
Comment = "Returns a perpendicular vector."
};
}
else if (BaseType.IsBool)
{
yield return new Property("Perpendicular", this)
{
GetterLine = "new " + Name + "(y, !x)",
Comment = "Returns a perpendicular vector."
};
}
}
That's a good one, I think I'll add that.
I don't want to be as close as possible to glm, it's more like the "glm spirit in C#".
That means that everything glm and GlmSharp have in common should behave similar/the same. Otherwise I'll try to extrapolate the intent of glm.
Any chance of adding mat4 multiplication for vec2/3 and returning a vec2/3?
This for example is taken for Axiom (orge3d port)...
EDIT: This is what I came up with from looking at glm code and comparing to monogame