Optimize GC for group frame.

This commit is contained in:
2022-12-20 16:05:52 +08:00
parent 571320630b
commit 06d8012675
3 changed files with 30 additions and 24 deletions

View File

@@ -1,9 +1,13 @@
namespace Cryville.Common.Math { using System;
namespace Cryville.Common.Math {
/// <summary> /// <summary>
/// Represents a square matrix. /// Represents a square matrix.
/// </summary> /// </summary>
public class SquareMatrix { public class SquareMatrix {
readonly float[,] content; readonly float[,] content;
readonly float[,] buffer;
readonly int[] refl;
/// <summary> /// <summary>
/// The size of the matrix. /// The size of the matrix.
/// </summary> /// </summary>
@@ -17,6 +21,8 @@
/// <param name="size">The size of the matrix.</param> /// <param name="size">The size of the matrix.</param>
public SquareMatrix(int size) { public SquareMatrix(int size) {
content = new float[size, size]; content = new float[size, size];
buffer = new float[size, size];
refl = new int[size];
Size = size; Size = size;
} }
/// <summary> /// <summary>
@@ -38,38 +44,36 @@
/// <returns>The column vector eliminated.</returns> /// <returns>The column vector eliminated.</returns>
public ColumnVector<T> Eliminate<T>(ColumnVector<T> v, IVectorOperator<T> o) { public ColumnVector<T> Eliminate<T>(ColumnVector<T> v, IVectorOperator<T> o) {
int s = Size; int s = Size;
float[,] d = (float[,])content.Clone(); Array.Copy(content, buffer, Size * Size);
int[] refl = new int[s]; for (int i = 0; i < s; i++) refl[i] = i;
for (int i = 0; i < s; i++)
refl[i] = i;
for (int r = 0; r < s; r++) { for (int r = 0; r < s; r++) {
for (int r0 = r; r0 < s; r0++) for (int r0 = r; r0 < s; r0++)
if (d[refl[r0], r] != 0) { if (buffer[refl[r0], r] != 0) {
refl[r] = r0; refl[r] = r0;
refl[r0] = r; refl[r0] = r;
break; break;
} }
int or = refl[r]; int or = refl[r];
float sf0 = d[or, r]; float sf0 = buffer[or, r];
for (int c0 = r; c0 < s; c0++) for (int c0 = r; c0 < s; c0++)
d[or, c0] /= sf0; buffer[or, c0] /= sf0;
v[or] = o.ScalarMultiply(1 / sf0, v[or]); v[or] = o.ScalarMultiply(1 / sf0, v[or]);
for (int r1 = r + 1; r1 < s; r1++) { for (int r1 = r + 1; r1 < s; r1++) {
int or1 = refl[r1]; int or1 = refl[r1];
float sf1 = d[or1, r]; float sf1 = buffer[or1, r];
for (int c1 = r; c1 < s; c1++) for (int c1 = r; c1 < s; c1++)
d[or1, c1] -= d[or, c1] * sf1; buffer[or1, c1] -= buffer[or, c1] * sf1;
v[or1] = o.Add(v[or1], o.ScalarMultiply(-sf1, v[or])); v[or1] = o.Add(v[or1], o.ScalarMultiply(-sf1, v[or]));
} }
} }
T[] res = new T[s]; ColumnVector<T> res = new ColumnVector<T>(s);
for (int r2 = s - 1; r2 >= 0; r2--) { for (int r2 = s - 1; r2 >= 0; r2--) {
var v2 = v[refl[r2]]; var v2 = v[refl[r2]];
for (int c2 = r2 + 1; c2 < s; c2++) for (int c2 = r2 + 1; c2 < s; c2++)
v2 = o.Add(v2, o.ScalarMultiply(-d[refl[r2], c2], res[refl[c2]])); v2 = o.Add(v2, o.ScalarMultiply(-buffer[refl[r2], c2], res[refl[c2]]));
res[refl[r2]] = v2; res[refl[r2]] = v2;
} }
return new ColumnVector<T>(res); return res;
} }
/// <summary> /// <summary>
/// Creates a square matrix and fills it with polynomial coefficients. /// Creates a square matrix and fills it with polynomial coefficients.

View File

@@ -1,7 +1,6 @@
using Cryville.Common.Math; using Cryville.Common.Math;
using Cryville.Crtr.Event; using Cryville.Crtr.Event;
using System; using System;
using System.Collections.Generic;
using System.Linq; using System.Linq;
using UnityEngine; using UnityEngine;
@@ -10,7 +9,7 @@ namespace Cryville.Crtr {
public ChartHandler ch; public ChartHandler ch;
SquareMatrix matFrame; SquareMatrix matFrame;
List<ContainerState> tracks; ContainerState[] tracks;
public GroupHandler(Chart.Group tg, ChartHandler ch) : base() { public GroupHandler(Chart.Group tg, ChartHandler ch) : base() {
this.ch = ch; this.ch = ch;
@@ -28,20 +27,22 @@ namespace Cryville.Crtr {
from c in cs.Children from c in cs.Children
where c.Value.Container is Chart.Track where c.Value.Container is Chart.Track
select c.Value select c.Value
).ToList(); ).ToArray();
matFrame = SquareMatrix.WithPolynomialCoefficients(tracks.Count); matFrame = SquareMatrix.WithPolynomialCoefficients(tracks.Length);
frame = new ColumnVector<Vector3>(tracks.Length);
} }
ColumnVector<Vector3> frame;
public ColumnVector<Vector3> GetCurrentFrame(Func<ContainerState, Vector3> func) { public ColumnVector<Vector3> GetCurrentFrame(Func<ContainerState, Vector3> func) {
var vl = from t in tracks select func(t); for (int i = 0; i < tracks.Length; i++)
return matFrame.Eliminate( frame[i] = func(tracks[i]);
new ColumnVector<Vector3>(vl.ToArray()), return matFrame.Eliminate(frame, Vector3Operator.Instance);
new Vector3Operator()
);
} }
} }
class Vector3Operator : IVectorOperator<Vector3> { class Vector3Operator : IVectorOperator<Vector3> {
public static Vector3Operator Instance = new Vector3Operator();
public Vector3 Add(Vector3 lhs, Vector3 rhs) { public Vector3 Add(Vector3 lhs, Vector3 rhs) {
return lhs + rhs; return lhs + rhs;
} }

View File

@@ -117,6 +117,7 @@ namespace Cryville.Crtr {
return Quaternion.LookRotation(r, state.Normal); return Quaternion.LookRotation(r, state.Normal);
} }
List<Vector3> ctrl = new List<Vector3>(2);
Vector3 GetFrame(ContainerState state, float track, Func<ContainerState, Vector3> func) { Vector3 GetFrame(ContainerState state, float track, Func<ContainerState, Vector3> func) {
// TODO // TODO
int id = Mathf.FloorToInt(track); int id = Mathf.FloorToInt(track);
@@ -134,7 +135,7 @@ namespace Cryville.Crtr {
if (c0 && c1) if (c0 && c1)
return (1 - t) * p1 + t * p2; return (1 - t) * p1 + t * p2;
else { else {
var ctrl = new List<Vector3>(2); ctrl.Clear();
if (!c0) { if (!c0) {
var tp = ts0.GetControlPoint(true, deltaz); var tp = ts0.GetControlPoint(true, deltaz);
if (tp != Vector3.zero) ctrl.Add(tp); if (tp != Vector3.zero) ctrl.Add(tp);
@@ -149,7 +150,7 @@ namespace Cryville.Crtr {
ColumnVector<float>.WithPolynomialCoefficients( ColumnVector<float>.WithPolynomialCoefficients(
frame.Size, track frame.Size, track
), ),
new Vector3Operator() Vector3Operator.Instance
); );
} }
else if (ctrl.Count == 1) { else if (ctrl.Count == 1) {