mirror of
https://github.com/MaddyThorson/StrawberryBF.git
synced 2024-11-25 16:18:56 +08:00
Cleaned up entity tracking. Scene.Camera. Matrix struct.
This commit is contained in:
parent
292213dae5
commit
fe3672f30c
|
@ -25,7 +25,10 @@ namespace Strawberry
|
|||
private Scene scene;
|
||||
private Scene switchToScene;
|
||||
private bool updating;
|
||||
private Dictionary<Type, List<Type>> entityAssignableLists;
|
||||
private Dictionary<Type, List<Type>> componentAssignableLists;
|
||||
|
||||
//SDL Vars
|
||||
public SDL.Renderer* Renderer { get; private set; }
|
||||
public Color ClearColor = .Black;
|
||||
|
||||
|
@ -78,7 +81,7 @@ namespace Strawberry
|
|||
SDLMixer.OpenAudio(44100, SDLMixer.MIX_DEFAULT_FORMAT, 2, 4096);
|
||||
SDLTTF.Init();
|
||||
|
||||
TypeTree.[Friend]Build();
|
||||
BuildTypeLists();
|
||||
Input.[Friend]Init(gamepadLimit);
|
||||
}
|
||||
|
||||
|
@ -99,7 +102,7 @@ namespace Strawberry
|
|||
delete VirtualInputs;
|
||||
}
|
||||
|
||||
TypeTree.[Friend]Dispose();
|
||||
DisposeTypeLists();
|
||||
Input.[Friend]Dispose();
|
||||
Game = null;
|
||||
}
|
||||
|
@ -210,5 +213,57 @@ namespace Strawberry
|
|||
switchToScene = value;
|
||||
}
|
||||
}
|
||||
|
||||
// Type assignable caching
|
||||
|
||||
private void BuildTypeLists()
|
||||
{
|
||||
/*
|
||||
For each Type that extends Entity, we build a list of all the other Entity Types that it is assignable to.
|
||||
We cache these lists, and use them later to bucket Entities as they are added to the Scene.
|
||||
This allows us to retrieve Entities by type very easily.
|
||||
*/
|
||||
|
||||
entityAssignableLists = new Dictionary<Type, List<Type>>();
|
||||
for (let type in Type.Enumerator())
|
||||
{
|
||||
if (type != typeof(Entity) && type.IsSubtypeOf(typeof(Entity)))
|
||||
{
|
||||
let list = new List<Type>();
|
||||
for (let check in Type.Enumerator())
|
||||
if (check != typeof(Entity) && check.IsSubtypeOf(typeof(Entity)) && type.IsSubtypeOf(check))
|
||||
list.Add(check);
|
||||
entityAssignableLists.Add(type, list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
And then we also do this for components
|
||||
*/
|
||||
|
||||
componentAssignableLists = new Dictionary<Type, List<Type>>();
|
||||
for (let type in Type.Enumerator())
|
||||
{
|
||||
if (type != typeof(Component) && type.IsSubtypeOf(typeof(Component)))
|
||||
{
|
||||
let list = new List<Type>();
|
||||
for (let check in Type.Enumerator())
|
||||
if (check != typeof(Component) && check.IsSubtypeOf(typeof(Component)) && type.IsSubtypeOf(check))
|
||||
list.Add(check);
|
||||
componentAssignableLists.Add(type, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void DisposeTypeLists()
|
||||
{
|
||||
for (let list in entityAssignableLists.Values)
|
||||
delete list;
|
||||
delete entityAssignableLists;
|
||||
|
||||
for (let list in componentAssignableLists.Values)
|
||||
delete list;
|
||||
delete componentAssignableLists;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ namespace Strawberry
|
|||
public float TimeStarted { get; private set; }
|
||||
public Grid SolidGrid;
|
||||
public Rect Bounds;
|
||||
public Vector Camera;
|
||||
|
||||
private List<Entity> entities;
|
||||
private HashSet<Entity> toRemove;
|
||||
|
@ -22,11 +23,11 @@ namespace Strawberry
|
|||
toRemove = new HashSet<Entity>();
|
||||
|
||||
entityTracker = new Dictionary<Type, List<Entity>>();
|
||||
for (let type in TypeTree.[Friend]EntityAssignableLists.Keys)
|
||||
for (let type in Game.[Friend]entityAssignableLists.Keys)
|
||||
entityTracker.Add(type, new List<Entity>());
|
||||
|
||||
componentTracker = new Dictionary<Type, List<Component>>();
|
||||
for (let type in TypeTree.[Friend]ComponentAssignableLists.Keys)
|
||||
for (let type in Game.[Friend]componentAssignableLists.Keys)
|
||||
componentTracker.Add(type, new List<Component>());
|
||||
}
|
||||
|
||||
|
@ -63,6 +64,8 @@ namespace Strawberry
|
|||
|
||||
public virtual void Update()
|
||||
{
|
||||
Camera.X += 20 * Time.Delta;
|
||||
|
||||
UpdateLists();
|
||||
for (var e in entities)
|
||||
if (e.Active)
|
||||
|
@ -132,7 +135,7 @@ namespace Strawberry
|
|||
|
||||
private void TrackEntity(Entity e)
|
||||
{
|
||||
for (let t in TypeTree.[Friend]EntityAssignableLists[e.GetType()])
|
||||
for (let t in Game.[Friend]entityAssignableLists[e.GetType()])
|
||||
entityTracker[t].Add(e);
|
||||
|
||||
for (let c in e.[Friend]components)
|
||||
|
@ -141,7 +144,7 @@ namespace Strawberry
|
|||
|
||||
private void UntrackEntity(Entity e)
|
||||
{
|
||||
for (let t in TypeTree.[Friend]EntityAssignableLists[e.GetType()])
|
||||
for (let t in Game.[Friend]entityAssignableLists[e.GetType()])
|
||||
entityTracker[t].Remove(e);
|
||||
|
||||
for (let c in e.[Friend]components)
|
||||
|
@ -150,13 +153,13 @@ namespace Strawberry
|
|||
|
||||
private void TrackComponent(Component c)
|
||||
{
|
||||
for (let t in TypeTree.[Friend]ComponentAssignableLists[c.GetType()])
|
||||
for (let t in Game.[Friend]componentAssignableLists[c.GetType()])
|
||||
componentTracker[t].Add(c);
|
||||
}
|
||||
|
||||
private void UntrackComponent(Component c)
|
||||
{
|
||||
for (let t in TypeTree.[Friend]ComponentAssignableLists[c.GetType()])
|
||||
for (let t in Game.[Friend]componentAssignableLists[c.GetType()])
|
||||
componentTracker[t].Remove(c);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,10 +4,12 @@ namespace Strawberry
|
|||
{
|
||||
static public class Draw
|
||||
{
|
||||
static public Point Camera => Game.Scene != null ? Game.Scene.Camera.Round() : Point.Zero;
|
||||
|
||||
static public void Rect(int x, int y, int w, int h, Color color)
|
||||
{
|
||||
SDL.SetRenderDrawColor(Game.Renderer, color.R, color.G, color.B, color.A);
|
||||
SDL.RenderFillRect(Game.Renderer, &SDL.Rect((int32)x, (int32)y, (int32)w, (int32)h));
|
||||
SDL.RenderFillRect(Game.Renderer, &SDL.Rect((int32)(x - Camera.X), (int32)(y - Camera.Y), (int32)w, (int32)h));
|
||||
}
|
||||
|
||||
static public void Rect(Rect rect, Color color)
|
||||
|
@ -18,7 +20,7 @@ namespace Strawberry
|
|||
static public void HollowRect(int x, int y, int w, int h, Color color)
|
||||
{
|
||||
SDL.SetRenderDrawColor(Game.Renderer, color.R, color.G, color.B, color.A);
|
||||
SDL.RenderDrawRect(Game.Renderer, &SDL.Rect((int32)x, (int32)y, (int32)w, (int32)h));
|
||||
SDL.RenderDrawRect(Game.Renderer, &SDL.Rect((int32)(x - Camera.X), (int32)(y - Camera.Y), (int32)w, (int32)h));
|
||||
}
|
||||
|
||||
static public void HollowRect(Rect rect, Color color)
|
||||
|
@ -28,8 +30,11 @@ namespace Strawberry
|
|||
|
||||
static public void Line(Point from, Point to, Color color)
|
||||
{
|
||||
let fromn = (Point)(from - Camera);
|
||||
let ton = (Point)(to - Camera);
|
||||
|
||||
SDL.SetRenderDrawColor(Game.Renderer, color.R, color.G, color.B, color.A);
|
||||
SDL.RenderDrawLine(Game.Renderer, (int32)from.X, (int32)from.Y, (int32)to.X, (int32)to.Y);
|
||||
SDL.RenderDrawLine(Game.Renderer, (int32)fromn.X, (int32)fromn.Y, (int32)ton.X, (int32)ton.Y);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,61 +0,0 @@
|
|||
using System.Collections;
|
||||
using System;
|
||||
|
||||
namespace Strawberry
|
||||
{
|
||||
static public class TypeTree
|
||||
{
|
||||
static private Dictionary<Type, List<Type>> EntityAssignableLists;
|
||||
static private Dictionary<Type, List<Type>> ComponentAssignableLists;
|
||||
|
||||
static private void Build()
|
||||
{
|
||||
/*
|
||||
For each Type that extends Entity, we build a list of all the other Entity Types that it is assignable to.
|
||||
We cache these lists, and use them later to bucket Entities as they are added to the Scene.
|
||||
This allows us to retrieve Entities by type very easily.
|
||||
*/
|
||||
|
||||
EntityAssignableLists = new Dictionary<Type, List<Type>>();
|
||||
for (let type in Type.Enumerator())
|
||||
{
|
||||
if (type != typeof(Entity) && type.IsSubtypeOf(typeof(Entity)))
|
||||
{
|
||||
let list = new List<Type>();
|
||||
for (let check in Type.Enumerator())
|
||||
if (check != typeof(Entity) && check.IsSubtypeOf(typeof(Entity)) && type.IsSubtypeOf(check))
|
||||
list.Add(check);
|
||||
EntityAssignableLists.Add(type, list);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
And then we also do this for components
|
||||
*/
|
||||
|
||||
ComponentAssignableLists = new Dictionary<Type, List<Type>>();
|
||||
for (let type in Type.Enumerator())
|
||||
{
|
||||
if (type != typeof(Component) && type.IsSubtypeOf(typeof(Component)))
|
||||
{
|
||||
let list = new List<Type>();
|
||||
for (let check in Type.Enumerator())
|
||||
if (check != typeof(Component) && check.IsSubtypeOf(typeof(Component)) && type.IsSubtypeOf(check))
|
||||
list.Add(check);
|
||||
ComponentAssignableLists.Add(type, list);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static private void Dispose()
|
||||
{
|
||||
for (let list in EntityAssignableLists.Values)
|
||||
delete list;
|
||||
delete EntityAssignableLists;
|
||||
|
||||
for (let list in ComponentAssignableLists.Values)
|
||||
delete list;
|
||||
delete ComponentAssignableLists;
|
||||
}
|
||||
}
|
||||
}
|
508
src/Struct/Matrix.bf
Normal file
508
src/Struct/Matrix.bf
Normal file
|
@ -0,0 +1,508 @@
|
|||
using System;
|
||||
namespace Strawberry
|
||||
{
|
||||
/*
|
||||
Based on Matrix3x2.cs by Microsoft, under MIT license
|
||||
Source: https://github.com/microsoft/referencesource/blob/master/System.Numerics/System/Numerics/Matrix3x2.cs
|
||||
|
||||
Copyright (c) Microsoft. All rights reserved.
|
||||
Licensed under the MIT license.
|
||||
*/
|
||||
|
||||
public struct Matrix
|
||||
{
|
||||
static public readonly Matrix Identity = Matrix(1, 0, 0, 1, 0, 0);
|
||||
|
||||
// Row--vv--Column
|
||||
public float M11;
|
||||
public float M12;
|
||||
public float M21;
|
||||
public float M22;
|
||||
public float M31;
|
||||
public float M32;
|
||||
|
||||
public this(float m11, float m12, float m21, float m22, float m31, float m32)
|
||||
{
|
||||
M11 = m11;
|
||||
M12 = m12;
|
||||
M21 = m21;
|
||||
M22 = m22;
|
||||
M31 = m31;
|
||||
M32 = m32;
|
||||
}
|
||||
|
||||
public bool IsIdentity
|
||||
{
|
||||
get
|
||||
{
|
||||
return M11 == 1f && M22 == 1f && // Check diagonal element first for early out.
|
||||
M12 == 0f &&
|
||||
M21 == 0f &&
|
||||
M31 == 0f && M32 == 0f;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector Translation
|
||||
{
|
||||
get
|
||||
{
|
||||
return .(M31, M32);
|
||||
}
|
||||
|
||||
set mut
|
||||
{
|
||||
M31 = value.X;
|
||||
M32 = value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector Scale
|
||||
{
|
||||
get
|
||||
{
|
||||
return .(M11, M22);
|
||||
}
|
||||
|
||||
set mut
|
||||
{
|
||||
M11 = value.X;
|
||||
M22 = value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector Up
|
||||
{
|
||||
get
|
||||
{
|
||||
return .(M21, -M22);
|
||||
}
|
||||
|
||||
set mut
|
||||
{
|
||||
M21 = value.X;
|
||||
M22 = -value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector Down
|
||||
{
|
||||
get
|
||||
{
|
||||
return .(M21, M22);
|
||||
}
|
||||
|
||||
set mut
|
||||
{
|
||||
M21 = -value.X;
|
||||
M22 = value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector Right
|
||||
{
|
||||
get
|
||||
{
|
||||
return .(M11, -M12);
|
||||
}
|
||||
|
||||
set mut
|
||||
{
|
||||
M11 = value.X;
|
||||
M12 = -value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public Vector Left
|
||||
{
|
||||
get
|
||||
{
|
||||
return .(-M11, M12);
|
||||
}
|
||||
|
||||
set mut
|
||||
{
|
||||
M11 = -value.X;
|
||||
M12 = value.Y;
|
||||
}
|
||||
}
|
||||
|
||||
public Result<Matrix> Inverse
|
||||
{
|
||||
get => Invert(this);
|
||||
|
||||
set mut
|
||||
{
|
||||
this = Invert(value);
|
||||
}
|
||||
}
|
||||
|
||||
//Static Helpers
|
||||
|
||||
public static Matrix CreateTranslation(Vector position)
|
||||
{
|
||||
return Matrix(
|
||||
1, 0,
|
||||
0, 1,
|
||||
position.X, position.Y
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix CreateScale(Vector scale)
|
||||
{
|
||||
return Matrix(
|
||||
scale.X, 0,
|
||||
0, scale.Y,
|
||||
0, 0
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix CreateScale(Vector scale, Vector origin)
|
||||
{
|
||||
float tx = origin.X * (1 - scale.X);
|
||||
float ty = origin.Y * (1 - scale.Y);
|
||||
|
||||
return Matrix(
|
||||
scale.X, 0,
|
||||
0, scale.Y,
|
||||
tx, ty
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix CreateScale(float scale)
|
||||
{
|
||||
return Matrix(
|
||||
scale, 0,
|
||||
0, scale,
|
||||
0, 0
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix CreateScale(float scale, Vector origin)
|
||||
{
|
||||
float tx = origin.X * (1 - scale);
|
||||
float ty = origin.Y * (1 - scale);
|
||||
|
||||
return Matrix(
|
||||
scale, 0,
|
||||
0, scale,
|
||||
tx, ty
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix CreateSkew(float radiansX, float radiansY)
|
||||
{
|
||||
float xTan = (float)Math.Tan(radiansX);
|
||||
float yTan = (float)Math.Tan(radiansY);
|
||||
|
||||
return Matrix(
|
||||
1, yTan,
|
||||
xTan, 1,
|
||||
0, 0
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix CreateSkew(float radiansX, float radiansY, Vector origin)
|
||||
{
|
||||
float xTan = (float)Math.Tan(radiansX);
|
||||
float yTan = (float)Math.Tan(radiansY);
|
||||
|
||||
float tx = -origin.Y * xTan;
|
||||
float ty = -origin.X * yTan;
|
||||
|
||||
return Matrix(
|
||||
1, yTan,
|
||||
xTan, 1,
|
||||
tx, ty
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix CreateRotation(float radians)
|
||||
{
|
||||
let rad = (float)Math.IEEERemainder(radians, Math.PI_f * 2);
|
||||
|
||||
float c, s;
|
||||
|
||||
const float epsilon = 0.001f * (float)Math.PI_f / 180f; // 0.1% of a degree
|
||||
|
||||
if (rad > -epsilon && rad < epsilon)
|
||||
{
|
||||
// Exact case for zero rotation.
|
||||
c = 1;
|
||||
s = 0;
|
||||
}
|
||||
else if (rad > Math.PI_f / 2 - epsilon && rad < Math.PI_f / 2 + epsilon)
|
||||
{
|
||||
// Exact case for 90 degree rotation.
|
||||
c = 0;
|
||||
s = 1;
|
||||
}
|
||||
else if (rad < -Math.PI_f + epsilon || rad > Math.PI_f - epsilon)
|
||||
{
|
||||
// Exact case for 180 degree rotation.
|
||||
c = -1;
|
||||
s = 0;
|
||||
}
|
||||
else if (rad > -Math.PI_f / 2 - epsilon && rad < -Math.PI_f / 2 + epsilon)
|
||||
{
|
||||
// Exact case for 270 degree rotation.
|
||||
c = 0;
|
||||
s = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary rotation.
|
||||
c = (float)Math.Cos(rad);
|
||||
s = (float)Math.Sin(rad);
|
||||
}
|
||||
|
||||
return Matrix(
|
||||
c, s,
|
||||
-s, c,
|
||||
0, 0
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix CreateRotation(float radians, Vector origin)
|
||||
{
|
||||
let rad = (float)Math.IEEERemainder(radians, Math.PI_f * 2);
|
||||
|
||||
float c, s;
|
||||
|
||||
const float epsilon = 0.001f * (float)Math.PI_f / 180f; // 0.1% of a degree
|
||||
|
||||
if (rad > -epsilon && rad < epsilon)
|
||||
{
|
||||
// Exact case for zero rotation.
|
||||
c = 1;
|
||||
s = 0;
|
||||
}
|
||||
else if (rad > Math.PI_f / 2 - epsilon && rad < Math.PI_f / 2 + epsilon)
|
||||
{
|
||||
// Exact case for 90 degree rotation.
|
||||
c = 0;
|
||||
s = 1;
|
||||
}
|
||||
else if (rad < -Math.PI_f + epsilon || rad > Math.PI_f - epsilon)
|
||||
{
|
||||
// Exact case for 180 degree rotation.
|
||||
c = -1;
|
||||
s = 0;
|
||||
}
|
||||
else if (rad > -Math.PI_f / 2 - epsilon && rad < -Math.PI_f / 2 + epsilon)
|
||||
{
|
||||
// Exact case for 270 degree rotation.
|
||||
c = 0;
|
||||
s = -1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Arbitrary rotation.
|
||||
c = (float)Math.Cos(rad);
|
||||
s = (float)Math.Sin(rad);
|
||||
}
|
||||
|
||||
float x = origin.X * (1 - c) + origin.Y * s;
|
||||
float y = origin.Y * (1 - c) - origin.X * s;
|
||||
|
||||
return Matrix(
|
||||
c, s,
|
||||
-s, c,
|
||||
x, y
|
||||
);
|
||||
}
|
||||
|
||||
/// Calculates the determinant for this matrix.
|
||||
/// The determinant is calculated by expanding the matrix with a third column whose values are (0,0,1).
|
||||
public float GetDeterminant()
|
||||
{
|
||||
// There isn't actually any such thing as a determinant for a non-square matrix,
|
||||
// but this 3x2 type is really just an optimization of a 3x3 where we happen to
|
||||
// know the rightmost column is always (0, 0, 1). So we expand to 3x3 format:
|
||||
//
|
||||
// [ M11, M12, 0 ]
|
||||
// [ M21, M22, 0 ]
|
||||
// [ M31, M32, 1 ]
|
||||
//
|
||||
// Sum the diagonal products:
|
||||
// (M11 * M22 * 1) + (M12 * 0 * M31) + (0 * M21 * M32)
|
||||
//
|
||||
// Subtract the opposite diagonal products:
|
||||
// (M31 * M22 * 0) + (M32 * 0 * M11) + (1 * M21 * M12)
|
||||
//
|
||||
// Collapse out the constants and oh look, this is just a 2x2 determinant!
|
||||
|
||||
return (M11 * M22) - (M21 * M12);
|
||||
}
|
||||
|
||||
public static Result<Matrix> Invert(Matrix matrix)
|
||||
{
|
||||
let det = (matrix.M11 * matrix.M22) - (matrix.M21 * matrix.M12);
|
||||
|
||||
if (Math.Abs(det) < float.Epsilon)
|
||||
return .Err;
|
||||
|
||||
let invDet = 1.0f / det;
|
||||
|
||||
return Matrix(
|
||||
matrix.M22 * invDet,
|
||||
-matrix.M12 * invDet,
|
||||
|
||||
-matrix.M21 * invDet,
|
||||
matrix.M11 * invDet,
|
||||
|
||||
(matrix.M21 * matrix.M32 - matrix.M31 * matrix.M22) * invDet,
|
||||
(matrix.M31 * matrix.M12 - matrix.M11 * matrix.M32) * invDet
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix Lerp(Matrix a, Matrix b, float t)
|
||||
{
|
||||
return Matrix(
|
||||
a.M11 + (b.M11 - a.M11) * t,
|
||||
a.M12 + (b.M12 - a.M12) * t,
|
||||
|
||||
a.M21 + (b.M21 - a.M21) * t,
|
||||
a.M22 + (b.M22 - a.M22) * t,
|
||||
|
||||
a.M31 + (b.M31 - a.M31) * t,
|
||||
a.M32 + (b.M32 - a.M32) * t
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix Negate(Matrix mat)
|
||||
{
|
||||
return Matrix(
|
||||
-mat.M11, -mat.M12,
|
||||
-mat.M21, -mat.M22,
|
||||
-mat.M31, -mat.M32
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix Add(Matrix a, Matrix b)
|
||||
{
|
||||
return Matrix(
|
||||
a.M11 + b.M11, a.M12 + b.M12,
|
||||
a.M21 + b.M21, a.M22 + b.M22,
|
||||
a.M31 + b.M31, a.M32 + b.M32
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix Subtract(Matrix a, Matrix b)
|
||||
{
|
||||
return Matrix(
|
||||
a.M11 - b.M11, a.M12 - b.M12,
|
||||
a.M21 - b.M21, a.M22 - b.M22,
|
||||
a.M31 - b.M31, a.M32 - b.M32
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix Multiply(Matrix a, Matrix b)
|
||||
{
|
||||
return Matrix(
|
||||
a.M11 * b.M11 + a.M12 * b.M21,
|
||||
a.M11 * b.M12 + a.M12 * b.M22,
|
||||
|
||||
a.M21 * b.M11 + a.M22 * b.M21,
|
||||
a.M21 * b.M12 + a.M22 * b.M22,
|
||||
|
||||
a.M31 * b.M11 + a.M32 * b.M21 + b.M31,
|
||||
a.M31 * b.M12 + a.M32 * b.M22 + b.M32
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix Multiply(Matrix a, float scale)
|
||||
{
|
||||
return Matrix(
|
||||
a.M11 * scale, a.M12 * scale,
|
||||
a.M21 * scale, a.M22 * scale,
|
||||
a.M31 * scale, a.M32 * scale
|
||||
);
|
||||
}
|
||||
|
||||
// Operators
|
||||
|
||||
public static Matrix operator -(Matrix mat)
|
||||
{
|
||||
return Matrix(
|
||||
-mat.M11, -mat.M12,
|
||||
-mat.M21, -mat.M22,
|
||||
-mat.M31, -mat.M32
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix operator +(Matrix a, Matrix b)
|
||||
{
|
||||
return Matrix(
|
||||
a.M11 + b.M11, a.M12 + b.M12,
|
||||
a.M21 + b.M21, a.M22 + b.M22,
|
||||
a.M31 + b.M31, a.M32 + b.M32
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix operator -(Matrix a, Matrix b)
|
||||
{
|
||||
return Matrix(
|
||||
a.M11 - b.M11, a.M12 - b.M12,
|
||||
a.M21 - b.M21, a.M22 - b.M22,
|
||||
a.M31 - b.M31, a.M32 - b.M32
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix operator *(Matrix a, Matrix b)
|
||||
{
|
||||
return Matrix(
|
||||
a.M11 * b.M11 + a.M12 * b.M21,
|
||||
a.M11 * b.M12 + a.M12 * b.M22,
|
||||
|
||||
a.M21 * b.M11 + a.M22 * b.M21,
|
||||
a.M21 * b.M12 + a.M22 * b.M22,
|
||||
|
||||
a.M31 * b.M11 + a.M32 * b.M21 + b.M31,
|
||||
a.M31 * b.M12 + a.M32 * b.M22 + b.M32
|
||||
);
|
||||
}
|
||||
|
||||
public static Matrix operator *(Matrix mat, float scale)
|
||||
{
|
||||
return Matrix(
|
||||
mat.M11 * scale, mat.M12 * scale,
|
||||
mat.M21 * scale, mat.M22 * scale,
|
||||
mat.M31 * scale, mat.M32 * scale
|
||||
);
|
||||
}
|
||||
|
||||
public static bool operator ==(Matrix a, Matrix b)
|
||||
{
|
||||
return (a.M11 == b.M11 && a.M22 == b.M22 && // Check diagonal element first for early out.
|
||||
a.M12 == b.M12 &&
|
||||
a.M21 == b.M21 &&
|
||||
a.M31 == b.M31 && a.M32 == b.M32);
|
||||
}
|
||||
|
||||
public static bool operator !=(Matrix a, Matrix b)
|
||||
{
|
||||
return (a.M11 != b.M11 || a.M12 != b.M12 ||
|
||||
a.M21 != b.M21 || a.M22 != b.M22 ||
|
||||
a.M31 != b.M31 || a.M32 != b.M32);
|
||||
}
|
||||
|
||||
public override void ToString(String strBuffer)
|
||||
{
|
||||
let str = scope String();
|
||||
|
||||
str.Append("[ ");
|
||||
M11.ToString(str);
|
||||
str.Append(", ");
|
||||
M12.ToString(str);
|
||||
str.Append(",\n");
|
||||
M21.ToString(str);
|
||||
str.Append(", ");
|
||||
M22.ToString(str);
|
||||
str.Append(",\n");
|
||||
M31.ToString(str);
|
||||
str.Append(", ");
|
||||
M32.ToString(str);
|
||||
str.Append(" ]");
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user