Skip to content

Commit

Permalink
Turn ModelRenderer and VoxelCache into traits
Browse files Browse the repository at this point in the history
  • Loading branch information
PunkPun committed Sep 23, 2023
1 parent c009f58 commit 3c8fc61
Show file tree
Hide file tree
Showing 33 changed files with 475 additions and 463 deletions.
4 changes: 2 additions & 2 deletions OpenRA.Game/Game.cs
Original file line number Diff line number Diff line change
Expand Up @@ -664,7 +664,7 @@ static void RenderTick()
// Prepare renderables (i.e. render voxels) before calling BeginFrame
using (new PerfSample("render_prepare"))
{
Renderer.WorldModelRenderer.BeginFrame();
worldRenderer?.BeginFrame();

// World rendering is disabled while the loading screen is displayed
if (worldRenderer != null && !worldRenderer.World.IsLoadingGameSave)
Expand All @@ -674,7 +674,7 @@ static void RenderTick()
}

Ui.PrepareRenderables();
Renderer.WorldModelRenderer.EndFrame();
worldRenderer?.EndFrame();
}

// worldRenderer is null during the initial install/download screen
Expand Down
55 changes: 12 additions & 43 deletions OpenRA.Game/Graphics/Model.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,8 @@
#endregion

using System;
using System.Collections.Generic;
using OpenRA.FileSystem;
using OpenRA.Primitives;
using OpenRA.Traits;

namespace OpenRA.Graphics
{
Expand All @@ -30,6 +29,14 @@ public interface IModel
Rectangle AggregateBounds { get; }
}

public interface IModelWidget
{
public string Palette { get; }
public float Scale { get; }
public void Setup(Func<bool> isVisible, Func<string> getPalette, Func<string> getPlayerPalette,
Func<float> getScale, Func<IModel> getVoxel, Func<WRot> getRotation);
}

public readonly struct ModelRenderData
{
public readonly int Start;
Expand All @@ -44,51 +51,13 @@ public ModelRenderData(int start, int count, Sheet sheet)
}
}

public interface IModelCache : IDisposable
public interface IModelCacheInfo : ITraitInfoInterface { }

public interface IModelCache
{
IModel GetModel(string model);
IModel GetModelSequence(string model, string sequence);
bool HasModelSequence(string model, string sequence);
IVertexBuffer<ModelVertex> VertexBuffer { get; }
}

public interface IModelSequenceLoader
{
Action<string> OnMissingModelError { get; set; }
IModelCache CacheModels(IReadOnlyFileSystem fileSystem, ModData modData, IReadOnlyDictionary<string, MiniYamlNode> modelDefinitions);
}

public class PlaceholderModelSequenceLoader : IModelSequenceLoader
{
public Action<string> OnMissingModelError { get; set; }

sealed class PlaceholderModelCache : IModelCache
{
public IVertexBuffer<ModelVertex> VertexBuffer => throw new NotImplementedException();

public void Dispose() { }

public IModel GetModel(string model)
{
throw new NotImplementedException();
}

public IModel GetModelSequence(string model, string sequence)
{
throw new NotImplementedException();
}

public bool HasModelSequence(string model, string sequence)
{
throw new NotImplementedException();
}
}

public PlaceholderModelSequenceLoader(ModData modData) { }

public IModelCache CacheModels(IReadOnlyFileSystem fileSystem, ModData modData, IReadOnlyDictionary<string, MiniYamlNode> modelDefinitions)
{
return new PlaceholderModelCache();
}
}
}
7 changes: 7 additions & 0 deletions OpenRA.Game/Graphics/PlatformInterfaces.cs
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,13 @@ public interface IGraphicsContext : IDisposable
string GLVersion { get; }
}

public interface IRenderer
{
void BeginFrame();
void EndFrame();
void SetPalette(ITexture palette);
}

public interface IVertexBuffer<T> : IDisposable where T : struct
{
void Bind();
Expand Down
244 changes: 0 additions & 244 deletions OpenRA.Game/Graphics/Util.cs
Original file line number Diff line number Diff line change
Expand Up @@ -313,249 +313,5 @@ public static Color PremultipliedColorLerp(float t, Color c1, Color c2)
(int)((byte)(t * a2 * c2.G + 0.5f) + (1 - t) * (byte)(a1 * c1.G + 0.5f)),
(int)((byte)(t * a2 * c2.B + 0.5f) + (1 - t) * (byte)(a1 * c1.B + 0.5f))));
}

public static float[] IdentityMatrix()
{
return new float[]
{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1,
};
}

public static float[] ScaleMatrix(float sx, float sy, float sz)
{
return new float[]
{
sx, 0, 0, 0,
0, sy, 0, 0,
0, 0, sz, 0,
0, 0, 0, 1,
};
}

public static float[] TranslationMatrix(float x, float y, float z)
{
return new float[]
{
1, 0, 0, 0,
0, 1, 0, 0,
0, 0, 1, 0,
x, y, z, 1,
};
}

public static float[] MatrixMultiply(float[] lhs, float[] rhs)
{
var mtx = new float[16];
for (var i = 0; i < 4; i++)
for (var j = 0; j < 4; j++)
{
mtx[4 * i + j] = 0;
for (var k = 0; k < 4; k++)
mtx[4 * i + j] += lhs[4 * k + j] * rhs[4 * i + k];
}

return mtx;
}

public static float[] MatrixVectorMultiply(float[] mtx, float[] vec)
{
var ret = new float[4];
for (var j = 0; j < 4; j++)
{
ret[j] = 0;
for (var k = 0; k < 4; k++)
ret[j] += mtx[4 * k + j] * vec[k];
}

return ret;
}

public static float[] MatrixInverse(float[] m)
{
var mtx = new float[16];

mtx[0] = m[5] * m[10] * m[15] -
m[5] * m[11] * m[14] -
m[9] * m[6] * m[15] +
m[9] * m[7] * m[14] +
m[13] * m[6] * m[11] -
m[13] * m[7] * m[10];

mtx[4] = -m[4] * m[10] * m[15] +
m[4] * m[11] * m[14] +
m[8] * m[6] * m[15] -
m[8] * m[7] * m[14] -
m[12] * m[6] * m[11] +
m[12] * m[7] * m[10];

mtx[8] = m[4] * m[9] * m[15] -
m[4] * m[11] * m[13] -
m[8] * m[5] * m[15] +
m[8] * m[7] * m[13] +
m[12] * m[5] * m[11] -
m[12] * m[7] * m[9];

mtx[12] = -m[4] * m[9] * m[14] +
m[4] * m[10] * m[13] +
m[8] * m[5] * m[14] -
m[8] * m[6] * m[13] -
m[12] * m[5] * m[10] +
m[12] * m[6] * m[9];

mtx[1] = -m[1] * m[10] * m[15] +
m[1] * m[11] * m[14] +
m[9] * m[2] * m[15] -
m[9] * m[3] * m[14] -
m[13] * m[2] * m[11] +
m[13] * m[3] * m[10];

mtx[5] = m[0] * m[10] * m[15] -
m[0] * m[11] * m[14] -
m[8] * m[2] * m[15] +
m[8] * m[3] * m[14] +
m[12] * m[2] * m[11] -
m[12] * m[3] * m[10];

mtx[9] = -m[0] * m[9] * m[15] +
m[0] * m[11] * m[13] +
m[8] * m[1] * m[15] -
m[8] * m[3] * m[13] -
m[12] * m[1] * m[11] +
m[12] * m[3] * m[9];

mtx[13] = m[0] * m[9] * m[14] -
m[0] * m[10] * m[13] -
m[8] * m[1] * m[14] +
m[8] * m[2] * m[13] +
m[12] * m[1] * m[10] -
m[12] * m[2] * m[9];

mtx[2] = m[1] * m[6] * m[15] -
m[1] * m[7] * m[14] -
m[5] * m[2] * m[15] +
m[5] * m[3] * m[14] +
m[13] * m[2] * m[7] -
m[13] * m[3] * m[6];

mtx[6] = -m[0] * m[6] * m[15] +
m[0] * m[7] * m[14] +
m[4] * m[2] * m[15] -
m[4] * m[3] * m[14] -
m[12] * m[2] * m[7] +
m[12] * m[3] * m[6];

mtx[10] = m[0] * m[5] * m[15] -
m[0] * m[7] * m[13] -
m[4] * m[1] * m[15] +
m[4] * m[3] * m[13] +
m[12] * m[1] * m[7] -
m[12] * m[3] * m[5];

mtx[14] = -m[0] * m[5] * m[14] +
m[0] * m[6] * m[13] +
m[4] * m[1] * m[14] -
m[4] * m[2] * m[13] -
m[12] * m[1] * m[6] +
m[12] * m[2] * m[5];

mtx[3] = -m[1] * m[6] * m[11] +
m[1] * m[7] * m[10] +
m[5] * m[2] * m[11] -
m[5] * m[3] * m[10] -
m[9] * m[2] * m[7] +
m[9] * m[3] * m[6];

mtx[7] = m[0] * m[6] * m[11] -
m[0] * m[7] * m[10] -
m[4] * m[2] * m[11] +
m[4] * m[3] * m[10] +
m[8] * m[2] * m[7] -
m[8] * m[3] * m[6];

mtx[11] = -m[0] * m[5] * m[11] +
m[0] * m[7] * m[9] +
m[4] * m[1] * m[11] -
m[4] * m[3] * m[9] -
m[8] * m[1] * m[7] +
m[8] * m[3] * m[5];

mtx[15] = m[0] * m[5] * m[10] -
m[0] * m[6] * m[9] -
m[4] * m[1] * m[10] +
m[4] * m[2] * m[9] +
m[8] * m[1] * m[6] -
m[8] * m[2] * m[5];

var det = m[0] * mtx[0] + m[1] * mtx[4] + m[2] * mtx[8] + m[3] * mtx[12];
if (det == 0)
return null;

for (var i = 0; i < 16; i++)
mtx[i] *= 1 / det;

return mtx;
}

public static float[] MakeFloatMatrix(Int32Matrix4x4 imtx)
{
var multipler = 1f / imtx.M44;
return new[]
{
imtx.M11 * multipler,
imtx.M12 * multipler,
imtx.M13 * multipler,
imtx.M14 * multipler,

imtx.M21 * multipler,
imtx.M22 * multipler,
imtx.M23 * multipler,
imtx.M24 * multipler,

imtx.M31 * multipler,
imtx.M32 * multipler,
imtx.M33 * multipler,
imtx.M34 * multipler,

imtx.M41 * multipler,
imtx.M42 * multipler,
imtx.M43 * multipler,
imtx.M44 * multipler,
};
}

public static float[] MatrixAABBMultiply(float[] mtx, float[] bounds)
{
// Corner offsets
var ix = new uint[] { 0, 0, 0, 0, 3, 3, 3, 3 };
var iy = new uint[] { 1, 1, 4, 4, 1, 1, 4, 4 };
var iz = new uint[] { 2, 5, 2, 5, 2, 5, 2, 5 };

// Vectors to opposing corner
var ret = new[]
{
float.MaxValue, float.MaxValue, float.MaxValue,
float.MinValue, float.MinValue, float.MinValue
};

// Transform vectors and find new bounding box
for (var i = 0; i < 8; i++)
{
var vec = new[] { bounds[ix[i]], bounds[iy[i]], bounds[iz[i]], 1 };
var tvec = MatrixVectorMultiply(mtx, vec);

ret[0] = Math.Min(ret[0], tvec[0] / tvec[3]);
ret[1] = Math.Min(ret[1], tvec[1] / tvec[3]);
ret[2] = Math.Min(ret[2], tvec[2] / tvec[3]);
ret[3] = Math.Max(ret[3], tvec[0] / tvec[3]);
ret[4] = Math.Max(ret[4], tvec[1] / tvec[3]);
ret[5] = Math.Max(ret[5], tvec[2] / tvec[3]);
}

return ret;
}
}
}
14 changes: 14 additions & 0 deletions OpenRA.Game/Graphics/WorldRenderer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ public sealed class WorldRenderer : IDisposable
readonly List<IFinalizedRenderable> preparedAnnotationRenderables = new();

readonly List<IRenderable> renderablesBuffer = new();
readonly IRenderer[] renderers;

internal WorldRenderer(ModData modData, World world)
{
Expand All @@ -66,11 +67,24 @@ internal WorldRenderer(ModData modData, World world)
palette.Initialize();

TerrainLighting = world.WorldActor.TraitOrDefault<ITerrainLighting>();
renderers = world.WorldActor.TraitsImplementing<IRenderer>().ToArray();
terrainRenderer = world.WorldActor.TraitOrDefault<IRenderTerrain>();

debugVis = Exts.Lazy(() => world.WorldActor.TraitOrDefault<DebugVisualizations>());
}

public void BeginFrame()
{
foreach (var r in renderers)
r.BeginFrame();
}

public void EndFrame()
{
foreach (var r in renderers)
r.EndFrame();
}

public void UpdatePalettesForPlayer(string internalName, Color color, bool replaceExisting)
{
foreach (var pal in World.WorldActor.TraitsImplementing<ILoadsPlayerPalettes>())
Expand Down

0 comments on commit 3c8fc61

Please sign in to comment.