Turn ModelRenderer and VoxelCache into traits
This commit is contained in:
committed by
Matthias Mailänder
parent
d427072cc9
commit
686040a316
@@ -664,7 +664,7 @@ namespace OpenRA
|
||||
// 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)
|
||||
@@ -674,7 +674,7 @@ namespace OpenRA
|
||||
}
|
||||
|
||||
Ui.PrepareRenderables();
|
||||
Renderer.WorldModelRenderer.EndFrame();
|
||||
worldRenderer?.EndFrame();
|
||||
}
|
||||
|
||||
// worldRenderer is null during the initial install/download screen
|
||||
|
||||
@@ -10,9 +10,8 @@
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
{
|
||||
@@ -30,6 +29,14 @@ namespace OpenRA.Graphics
|
||||
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;
|
||||
@@ -44,51 +51,13 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,13 @@ namespace OpenRA
|
||||
string GLVersion { get; }
|
||||
}
|
||||
|
||||
public interface IRenderer
|
||||
{
|
||||
void BeginFrame();
|
||||
void EndFrame();
|
||||
void SetPalette(ITexture palette);
|
||||
}
|
||||
|
||||
public interface IVertexBuffer<T> : IDisposable where T : struct
|
||||
{
|
||||
void Bind();
|
||||
|
||||
@@ -313,249 +313,5 @@ namespace OpenRA.Graphics
|
||||
(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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,6 +44,7 @@ namespace OpenRA.Graphics
|
||||
readonly List<IFinalizedRenderable> preparedAnnotationRenderables = new();
|
||||
|
||||
readonly List<IRenderable> renderablesBuffer = new();
|
||||
readonly IRenderer[] renderers;
|
||||
|
||||
internal WorldRenderer(ModData modData, World world)
|
||||
{
|
||||
@@ -66,11 +67,24 @@ namespace OpenRA.Graphics
|
||||
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>())
|
||||
|
||||
@@ -43,17 +43,6 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ModelSequenceFormat : IGlobalModData
|
||||
{
|
||||
public readonly string Type;
|
||||
public readonly IReadOnlyDictionary<string, MiniYaml> Metadata;
|
||||
public ModelSequenceFormat(MiniYaml yaml)
|
||||
{
|
||||
Type = yaml.Value;
|
||||
Metadata = new ReadOnlyDictionary<string, MiniYaml>(yaml.ToDictionary());
|
||||
}
|
||||
}
|
||||
|
||||
public class ModMetadata
|
||||
{
|
||||
public string Title;
|
||||
|
||||
@@ -33,7 +33,6 @@ namespace OpenRA
|
||||
public readonly ISpriteLoader[] SpriteLoaders;
|
||||
public readonly ITerrainLoader TerrainLoader;
|
||||
public readonly ISpriteSequenceLoader SpriteSequenceLoader;
|
||||
public readonly IModelSequenceLoader ModelSequenceLoader;
|
||||
public readonly IVideoLoader[] VideoLoaders;
|
||||
public readonly HotkeyManager Hotkeys;
|
||||
public ILoadScreen LoadScreen { get; }
|
||||
@@ -90,15 +89,6 @@ namespace OpenRA
|
||||
|
||||
SpriteSequenceLoader = (ISpriteSequenceLoader)sequenceCtor.Invoke(new[] { this });
|
||||
|
||||
var modelFormat = Manifest.Get<ModelSequenceFormat>();
|
||||
var modelLoader = ObjectCreator.FindType(modelFormat.Type + "Loader");
|
||||
var modelCtor = modelLoader?.GetConstructor(new[] { typeof(ModData) });
|
||||
if (modelLoader == null || !modelLoader.GetInterfaces().Contains(typeof(IModelSequenceLoader)) || modelCtor == null)
|
||||
throw new InvalidOperationException($"Unable to find a model loader for type '{modelFormat.Type}'.");
|
||||
|
||||
ModelSequenceLoader = (IModelSequenceLoader)modelCtor.Invoke(new[] { this });
|
||||
ModelSequenceLoader.OnMissingModelError = s => Log.Write("debug", s);
|
||||
|
||||
Hotkeys = new HotkeyManager(ModFiles, Game.Settings.Keys, Manifest);
|
||||
|
||||
defaultRules = Exts.Lazy(() => Ruleset.LoadDefaults(this));
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace OpenRA
|
||||
public SpriteRenderer WorldSpriteRenderer { get; }
|
||||
public RgbaSpriteRenderer WorldRgbaSpriteRenderer { get; }
|
||||
public RgbaColorRenderer WorldRgbaColorRenderer { get; }
|
||||
public ModelRenderer WorldModelRenderer { get; }
|
||||
public IRenderer[] WorldRenderers = Array.Empty<IRenderer>();
|
||||
public RgbaColorRenderer RgbaColorRenderer { get; }
|
||||
public SpriteRenderer SpriteRenderer { get; }
|
||||
public RgbaSpriteRenderer RgbaSpriteRenderer { get; }
|
||||
@@ -92,7 +92,6 @@ namespace OpenRA
|
||||
WorldSpriteRenderer = new SpriteRenderer(this, Context.CreateShader(combinedBindings));
|
||||
WorldRgbaSpriteRenderer = new RgbaSpriteRenderer(WorldSpriteRenderer);
|
||||
WorldRgbaColorRenderer = new RgbaColorRenderer(WorldSpriteRenderer);
|
||||
WorldModelRenderer = new ModelRenderer(this, Context.CreateShader(new ModelShaderBindings()));
|
||||
SpriteRenderer = new SpriteRenderer(this, Context.CreateShader(combinedBindings));
|
||||
RgbaSpriteRenderer = new RgbaSpriteRenderer(SpriteRenderer);
|
||||
RgbaColorRenderer = new RgbaColorRenderer(SpriteRenderer);
|
||||
@@ -259,8 +258,6 @@ namespace OpenRA
|
||||
if (lastWorldViewport != worldViewport)
|
||||
{
|
||||
WorldSpriteRenderer.SetViewportParams(worldSheet.Size, WorldDownscaleFactor, depthMargin, worldViewport.Location);
|
||||
WorldModelRenderer.SetViewportParams();
|
||||
|
||||
lastWorldViewport = worldViewport;
|
||||
}
|
||||
|
||||
@@ -308,7 +305,9 @@ namespace OpenRA
|
||||
|
||||
SpriteRenderer.SetPalette(currentPaletteTexture, palette.ColorShifts);
|
||||
WorldSpriteRenderer.SetPalette(currentPaletteTexture, palette.ColorShifts);
|
||||
WorldModelRenderer.SetPalette(currentPaletteTexture);
|
||||
|
||||
foreach (var r in WorldRenderers)
|
||||
r.SetPalette(currentPaletteTexture);
|
||||
}
|
||||
|
||||
public void EndFrame(IInputHandler inputHandler)
|
||||
@@ -385,6 +384,16 @@ namespace OpenRA
|
||||
}
|
||||
}
|
||||
|
||||
public IFrameBuffer CreateFrameBuffer(Size s)
|
||||
{
|
||||
return Context.CreateFrameBuffer(s);
|
||||
}
|
||||
|
||||
public IShader CreateShader(IShaderBindings bindings)
|
||||
{
|
||||
return Context.CreateShader(bindings);
|
||||
}
|
||||
|
||||
public IVertexBuffer<T> CreateVertexBuffer<T>(int length) where T : struct
|
||||
{
|
||||
return Context.CreateVertexBuffer<T>(length);
|
||||
@@ -514,7 +523,6 @@ namespace OpenRA
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
WorldModelRenderer.Dispose();
|
||||
tempVertexBuffer.Dispose();
|
||||
quadIndexBuffer.Dispose();
|
||||
fontSheetBuilder?.Dispose();
|
||||
|
||||
@@ -49,7 +49,6 @@ namespace OpenRA
|
||||
|
||||
public readonly MersenneTwister SharedRandom;
|
||||
public readonly MersenneTwister LocalRandom;
|
||||
public readonly IModelCache ModelCache;
|
||||
public LongBitSet<PlayerBitMask> AllPlayersMask = default;
|
||||
public readonly LongBitSet<PlayerBitMask> NoPlayersMask = default;
|
||||
|
||||
@@ -214,8 +213,6 @@ namespace OpenRA
|
||||
SharedRandom = new MersenneTwister(orderManager.LobbyInfo.GlobalSettings.RandomSeed);
|
||||
LocalRandom = new MersenneTwister();
|
||||
|
||||
ModelCache = modData.ModelSequenceLoader.CacheModels(Map, modData, Map.Rules.ModelSequences);
|
||||
|
||||
var worldActorType = type == WorldType.Editor ? SystemActors.EditorWorld : SystemActors.World;
|
||||
WorldActor = CreateActor(worldActorType.ToString(), new TypeDictionary());
|
||||
ActorMap = WorldActor.Trait<IActorMap>();
|
||||
@@ -598,8 +595,6 @@ namespace OpenRA
|
||||
if (IsLoadingGameSave)
|
||||
Game.Sound.DisableAllSounds = false;
|
||||
|
||||
ModelCache.Dispose();
|
||||
|
||||
// Dispose newer actors first, and the world actor last
|
||||
foreach (var a in actors.Values.Reverse())
|
||||
a.Dispose();
|
||||
|
||||
@@ -48,7 +48,7 @@ namespace OpenRA.Mods.Cnc.FileFormats
|
||||
Transforms[c + ids[k]] = s.ReadFloat();
|
||||
|
||||
Array.Copy(Transforms, 16 * (LimbCount * j + i), testMatrix, 0, 16);
|
||||
if (OpenRA.Graphics.Util.MatrixInverse(testMatrix) == null)
|
||||
if (Util.MatrixInverse(testMatrix) == null)
|
||||
throw new InvalidDataException(
|
||||
$"The transformation matrix for HVA file `{fileName}` section {i} frame {j} is invalid because it is not invertible!");
|
||||
}
|
||||
|
||||
@@ -11,12 +11,15 @@
|
||||
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Cnc.Traits;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Mods.Common.Graphics
|
||||
namespace OpenRA.Mods.Cnc.Graphics
|
||||
{
|
||||
public class ModelPreview : IActorPreview
|
||||
{
|
||||
readonly ModelRenderer renderer;
|
||||
readonly ModelAnimation[] components;
|
||||
readonly float scale;
|
||||
readonly float[] lightAmbientColor;
|
||||
@@ -29,10 +32,11 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
readonly WVec offset;
|
||||
readonly int zOffset;
|
||||
|
||||
public ModelPreview(ModelAnimation[] components, in WVec offset, int zOffset, float scale, WAngle lightPitch, WAngle lightYaw,
|
||||
public ModelPreview(ModelRenderer renderer, ModelAnimation[] components, in WVec offset, int zOffset, float scale, WAngle lightPitch, WAngle lightYaw,
|
||||
float[] lightAmbientColor, float[] lightDiffuseColor, WAngle cameraPitch,
|
||||
PaletteReference colorPalette, PaletteReference normalsPalette, PaletteReference shadowPalette)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.components = components;
|
||||
this.scale = scale;
|
||||
this.lightAmbientColor = lightAmbientColor;
|
||||
@@ -53,14 +57,14 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
|
||||
IEnumerable<IRenderable> IActorPreview.RenderUI(WorldRenderer wr, int2 pos, float scale)
|
||||
{
|
||||
yield return new UIModelRenderable(components, WPos.Zero + offset, pos, zOffset, camera, scale * this.scale,
|
||||
yield return new UIModelRenderable(renderer, components, WPos.Zero + offset, pos, zOffset, camera, scale * this.scale,
|
||||
lightSource, lightAmbientColor, lightDiffuseColor,
|
||||
colorPalette, normalsPalette, shadowPalette);
|
||||
}
|
||||
|
||||
IEnumerable<IRenderable> IActorPreview.Render(WorldRenderer wr, WPos pos)
|
||||
{
|
||||
yield return new ModelRenderable(components, pos + offset, zOffset, camera, scale,
|
||||
yield return new ModelRenderable(renderer, components, pos + offset, zOffset, camera, scale,
|
||||
lightSource, lightAmbientColor, lightDiffuseColor,
|
||||
colorPalette, normalsPalette, shadowPalette);
|
||||
}
|
||||
@@ -13,12 +13,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Cnc.Traits;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Mods.Common.Graphics
|
||||
namespace OpenRA.Mods.Cnc.Graphics
|
||||
{
|
||||
public class ModelRenderable : IPalettedRenderable, IModifyableRenderable
|
||||
{
|
||||
readonly ModelRenderer renderer;
|
||||
readonly IEnumerable<ModelAnimation> models;
|
||||
readonly WRot camera;
|
||||
readonly WRot lightSource;
|
||||
@@ -29,20 +31,21 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
readonly float scale;
|
||||
|
||||
public ModelRenderable(
|
||||
IEnumerable<ModelAnimation> models, WPos pos, int zOffset, in WRot camera, float scale,
|
||||
ModelRenderer renderer, IEnumerable<ModelAnimation> models, WPos pos, int zOffset, in WRot camera, float scale,
|
||||
in WRot lightSource, float[] lightAmbientColor, float[] lightDiffuseColor,
|
||||
PaletteReference color, PaletteReference normals, PaletteReference shadow)
|
||||
: this(models, pos, zOffset, camera, scale,
|
||||
: this(renderer, models, pos, zOffset, camera, scale,
|
||||
lightSource, lightAmbientColor, lightDiffuseColor,
|
||||
color, normals, shadow, 1f,
|
||||
float3.Ones, TintModifiers.None) { }
|
||||
|
||||
public ModelRenderable(
|
||||
IEnumerable<ModelAnimation> models, WPos pos, int zOffset, in WRot camera, float scale,
|
||||
ModelRenderer renderer, IEnumerable<ModelAnimation> models, WPos pos, int zOffset, in WRot camera, float scale,
|
||||
in WRot lightSource, float[] lightAmbientColor, float[] lightDiffuseColor,
|
||||
PaletteReference color, PaletteReference normals, PaletteReference shadow,
|
||||
float alpha, in float3 tint, TintModifiers tintModifiers)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.models = models;
|
||||
Pos = pos;
|
||||
ZOffset = zOffset;
|
||||
@@ -71,7 +74,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
public IPalettedRenderable WithPalette(PaletteReference newPalette)
|
||||
{
|
||||
return new ModelRenderable(
|
||||
models, Pos, ZOffset, camera, scale,
|
||||
renderer, models, Pos, ZOffset, camera, scale,
|
||||
lightSource, lightAmbientColor, lightDiffuseColor,
|
||||
newPalette, normalsPalette, shadowPalette, Alpha, Tint, TintModifiers);
|
||||
}
|
||||
@@ -79,7 +82,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
public IRenderable WithZOffset(int newOffset)
|
||||
{
|
||||
return new ModelRenderable(
|
||||
models, Pos, newOffset, camera, scale,
|
||||
renderer, models, Pos, newOffset, camera, scale,
|
||||
lightSource, lightAmbientColor, lightDiffuseColor,
|
||||
Palette, normalsPalette, shadowPalette, Alpha, Tint, TintModifiers);
|
||||
}
|
||||
@@ -87,7 +90,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
public IRenderable OffsetBy(in WVec vec)
|
||||
{
|
||||
return new ModelRenderable(
|
||||
models, Pos + vec, ZOffset, camera, scale,
|
||||
renderer, models, Pos + vec, ZOffset, camera, scale,
|
||||
lightSource, lightAmbientColor, lightDiffuseColor,
|
||||
Palette, normalsPalette, shadowPalette, Alpha, Tint, TintModifiers);
|
||||
}
|
||||
@@ -97,7 +100,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
public IModifyableRenderable WithAlpha(float newAlpha)
|
||||
{
|
||||
return new ModelRenderable(
|
||||
models, Pos, ZOffset, camera, scale,
|
||||
renderer, models, Pos, ZOffset, camera, scale,
|
||||
lightSource, lightAmbientColor, lightDiffuseColor,
|
||||
Palette, normalsPalette, shadowPalette, newAlpha, Tint, TintModifiers);
|
||||
}
|
||||
@@ -105,7 +108,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
public IModifyableRenderable WithTint(in float3 newTint, TintModifiers newTintModifiers)
|
||||
{
|
||||
return new ModelRenderable(
|
||||
models, Pos, ZOffset, camera, scale,
|
||||
renderer, models, Pos, ZOffset, camera, scale,
|
||||
lightSource, lightAmbientColor, lightDiffuseColor,
|
||||
Palette, normalsPalette, shadowPalette, Alpha, newTint, newTintModifiers);
|
||||
}
|
||||
@@ -127,7 +130,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
|
||||
var map = wr.World.Map;
|
||||
var groundOrientation = map.TerrainOrientation(map.CellContaining(model.Pos));
|
||||
renderProxy = Game.Renderer.WorldModelRenderer.RenderAsync(
|
||||
renderProxy = model.renderer.RenderAsync(
|
||||
wr, draw, model.camera, model.scale, groundOrientation, model.lightSource,
|
||||
model.lightAmbientColor, model.lightDiffuseColor,
|
||||
model.Palette, model.normalsPalette, model.shadowPalette);
|
||||
@@ -199,17 +202,17 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
|
||||
// Draw bounding box
|
||||
var draw = model.models.Where(v => v.IsVisible);
|
||||
var scaleTransform = OpenRA.Graphics.Util.ScaleMatrix(model.scale, model.scale, model.scale);
|
||||
var cameraTransform = OpenRA.Graphics.Util.MakeFloatMatrix(model.camera.AsMatrix());
|
||||
var scaleTransform = Util.ScaleMatrix(model.scale, model.scale, model.scale);
|
||||
var cameraTransform = Util.MakeFloatMatrix(model.camera.AsMatrix());
|
||||
|
||||
foreach (var v in draw)
|
||||
{
|
||||
var bounds = v.Model.Bounds(v.FrameFunc());
|
||||
var rotation = OpenRA.Graphics.Util.MakeFloatMatrix(v.RotationFunc().AsMatrix());
|
||||
var worldTransform = OpenRA.Graphics.Util.MatrixMultiply(scaleTransform, rotation);
|
||||
var rotation = Util.MakeFloatMatrix(v.RotationFunc().AsMatrix());
|
||||
var worldTransform = Util.MatrixMultiply(scaleTransform, rotation);
|
||||
|
||||
var pxPos = pxOrigin + wr.ScreenVectorComponents(v.OffsetFunc());
|
||||
var screenTransform = OpenRA.Graphics.Util.MatrixMultiply(cameraTransform, worldTransform);
|
||||
var screenTransform = Util.MatrixMultiply(cameraTransform, worldTransform);
|
||||
DrawBoundsBox(wr, pxPos, screenTransform, bounds, 1, Color.Yellow);
|
||||
}
|
||||
}
|
||||
@@ -224,7 +227,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
var vec = new[] { bounds[CornerXIndex[i]], bounds[CornerYIndex[i]], bounds[CornerZIndex[i]], 1 };
|
||||
var screen = OpenRA.Graphics.Util.MatrixVectorMultiply(transform, vec);
|
||||
var screen = Util.MatrixVectorMultiply(transform, vec);
|
||||
corners[i] = wr.Viewport.WorldToViewPx(pxPos + new float3(screen[0], screen[1], screen[2]));
|
||||
}
|
||||
|
||||
@@ -250,8 +253,8 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
{
|
||||
var pxOrigin = wr.ScreenPosition(model.Pos);
|
||||
var draw = model.models.Where(v => v.IsVisible);
|
||||
var scaleTransform = OpenRA.Graphics.Util.ScaleMatrix(model.scale, model.scale, model.scale);
|
||||
var cameraTransform = OpenRA.Graphics.Util.MakeFloatMatrix(model.camera.AsMatrix());
|
||||
var scaleTransform = Util.ScaleMatrix(model.scale, model.scale, model.scale);
|
||||
var cameraTransform = Util.MakeFloatMatrix(model.camera.AsMatrix());
|
||||
|
||||
var minX = float.MaxValue;
|
||||
var minY = float.MaxValue;
|
||||
@@ -263,16 +266,16 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
foreach (var v in draw)
|
||||
{
|
||||
var bounds = v.Model.Bounds(v.FrameFunc());
|
||||
var rotation = OpenRA.Graphics.Util.MakeFloatMatrix(v.RotationFunc().AsMatrix());
|
||||
var worldTransform = OpenRA.Graphics.Util.MatrixMultiply(scaleTransform, rotation);
|
||||
var rotation = Util.MakeFloatMatrix(v.RotationFunc().AsMatrix());
|
||||
var worldTransform = Util.MatrixMultiply(scaleTransform, rotation);
|
||||
|
||||
var pxPos = pxOrigin + wr.ScreenVectorComponents(v.OffsetFunc());
|
||||
var screenTransform = OpenRA.Graphics.Util.MatrixMultiply(cameraTransform, worldTransform);
|
||||
var screenTransform = Util.MatrixMultiply(cameraTransform, worldTransform);
|
||||
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
var vec = new float[] { bounds[CornerXIndex[i]], bounds[CornerYIndex[i]], bounds[CornerZIndex[i]], 1 };
|
||||
var screen = OpenRA.Graphics.Util.MatrixVectorMultiply(screenTransform, vec);
|
||||
var screen = Util.MatrixVectorMultiply(screenTransform, vec);
|
||||
minX = Math.Min(minX, pxPos.X + screen[0]);
|
||||
minY = Math.Min(minY, pxPos.Y + screen[1]);
|
||||
minZ = Math.Min(minZ, pxPos.Z + screen[2]);
|
||||
@@ -13,12 +13,14 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Cnc.Traits;
|
||||
using OpenRA.Primitives;
|
||||
|
||||
namespace OpenRA.Mods.Common.Graphics
|
||||
namespace OpenRA.Mods.Cnc.Graphics
|
||||
{
|
||||
public class UIModelRenderable : IRenderable, IPalettedRenderable
|
||||
{
|
||||
readonly ModelRenderer renderer;
|
||||
readonly IEnumerable<ModelAnimation> models;
|
||||
readonly int2 screenPos;
|
||||
readonly WRot camera;
|
||||
@@ -30,10 +32,11 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
readonly float scale;
|
||||
|
||||
public UIModelRenderable(
|
||||
IEnumerable<ModelAnimation> models, WPos effectiveWorldPos, int2 screenPos, int zOffset,
|
||||
ModelRenderer renderer, IEnumerable<ModelAnimation> models, WPos effectiveWorldPos, int2 screenPos, int zOffset,
|
||||
in WRot camera, float scale, in WRot lightSource, float[] lightAmbientColor, float[] lightDiffuseColor,
|
||||
PaletteReference color, PaletteReference normals, PaletteReference shadow)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.models = models;
|
||||
Pos = effectiveWorldPos;
|
||||
this.screenPos = screenPos;
|
||||
@@ -56,7 +59,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
public IPalettedRenderable WithPalette(PaletteReference newPalette)
|
||||
{
|
||||
return new UIModelRenderable(
|
||||
models, Pos, screenPos, ZOffset, camera, scale,
|
||||
renderer, models, Pos, screenPos, ZOffset, camera, scale,
|
||||
lightSource, lightAmbientColor, lightDiffuseColor,
|
||||
newPalette, normalsPalette, shadowPalette);
|
||||
}
|
||||
@@ -80,7 +83,7 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
this.model = model;
|
||||
var draw = model.models.Where(v => v.IsVisible);
|
||||
|
||||
renderProxy = Game.Renderer.WorldModelRenderer.RenderAsync(
|
||||
renderProxy = model.renderer.RenderAsync(
|
||||
wr, draw, model.camera, model.scale, WRot.None, model.lightSource,
|
||||
model.lightAmbientColor, model.lightDiffuseColor,
|
||||
model.Palette, model.normalsPalette, model.shadowPalette);
|
||||
@@ -112,8 +115,8 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
{
|
||||
var pxOrigin = model.screenPos;
|
||||
var draw = model.models.Where(v => v.IsVisible);
|
||||
var scaleTransform = OpenRA.Graphics.Util.ScaleMatrix(model.scale, model.scale, model.scale);
|
||||
var cameraTransform = OpenRA.Graphics.Util.MakeFloatMatrix(model.camera.AsMatrix());
|
||||
var scaleTransform = Util.ScaleMatrix(model.scale, model.scale, model.scale);
|
||||
var cameraTransform = Util.MakeFloatMatrix(model.camera.AsMatrix());
|
||||
|
||||
var minX = float.MaxValue;
|
||||
var minY = float.MaxValue;
|
||||
@@ -125,16 +128,16 @@ namespace OpenRA.Mods.Common.Graphics
|
||||
foreach (var v in draw)
|
||||
{
|
||||
var bounds = v.Model.Bounds(v.FrameFunc());
|
||||
var rotation = OpenRA.Graphics.Util.MakeFloatMatrix(v.RotationFunc().AsMatrix());
|
||||
var worldTransform = OpenRA.Graphics.Util.MatrixMultiply(scaleTransform, rotation);
|
||||
var rotation = Util.MakeFloatMatrix(v.RotationFunc().AsMatrix());
|
||||
var worldTransform = Util.MatrixMultiply(scaleTransform, rotation);
|
||||
|
||||
var pxPos = pxOrigin + wr.ScreenVectorComponents(v.OffsetFunc());
|
||||
var screenTransform = OpenRA.Graphics.Util.MatrixMultiply(cameraTransform, worldTransform);
|
||||
var screenTransform = Util.MatrixMultiply(cameraTransform, worldTransform);
|
||||
|
||||
for (var i = 0; i < 8; i++)
|
||||
{
|
||||
var vec = new float[] { bounds[CornerXIndex[i]], bounds[CornerYIndex[i]], bounds[CornerZIndex[i]], 1 };
|
||||
var screen = OpenRA.Graphics.Util.MatrixVectorMultiply(screenTransform, vec);
|
||||
var screen = Util.MatrixVectorMultiply(screenTransform, vec);
|
||||
minX = Math.Min(minX, pxPos.X + screen[0]);
|
||||
minY = Math.Min(minY, pxPos.Y + screen[1]);
|
||||
minZ = Math.Min(minZ, pxPos.Z + screen[2]);
|
||||
@@ -74,8 +74,8 @@ namespace OpenRA.Mods.Cnc.Graphics
|
||||
t[14] *= l.Scale * (l.Bounds[5] - l.Bounds[2]) / l.Size[2];
|
||||
|
||||
// Center, flip and scale
|
||||
t = OpenRA.Graphics.Util.MatrixMultiply(t, OpenRA.Graphics.Util.TranslationMatrix(l.Bounds[0], l.Bounds[1], l.Bounds[2]));
|
||||
t = OpenRA.Graphics.Util.MatrixMultiply(OpenRA.Graphics.Util.ScaleMatrix(l.Scale, -l.Scale, l.Scale), t);
|
||||
t = Util.MatrixMultiply(t, Util.TranslationMatrix(l.Bounds[0], l.Bounds[1], l.Bounds[2]));
|
||||
t = Util.MatrixMultiply(Util.ScaleMatrix(l.Scale, -l.Scale, l.Scale), t);
|
||||
|
||||
return t;
|
||||
}
|
||||
@@ -119,7 +119,7 @@ namespace OpenRA.Mods.Cnc.Graphics
|
||||
};
|
||||
|
||||
// Calculate limb bounding box
|
||||
var bb = OpenRA.Graphics.Util.MatrixAABBMultiply(TransformationMatrix(j, frame), b);
|
||||
var bb = Util.MatrixAABBMultiply(TransformationMatrix(j, frame), b);
|
||||
for (var i = 0; i < 3; i++)
|
||||
{
|
||||
ret[i] = Math.Min(ret[i], bb[i]);
|
||||
|
||||
@@ -14,7 +14,7 @@ using OpenRA.Mods.Cnc.Traits;
|
||||
using OpenRA.Scripting;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.CnC.Scripting
|
||||
namespace OpenRA.Mods.Cnc.Scripting
|
||||
{
|
||||
[ScriptPropertyGroup("Support Powers")]
|
||||
public class IonCannonProperties : ScriptActorProperties, Requires<IonCannonPowerInfo>
|
||||
|
||||
@@ -13,15 +13,18 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Cnc.Graphics;
|
||||
using OpenRA.Mods.Common;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits.Render
|
||||
namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
{
|
||||
public interface IRenderActorPreviewVoxelsInfo : ITraitInfoInterface
|
||||
{
|
||||
IEnumerable<ModelAnimation> RenderPreviewVoxels(
|
||||
IEnumerable<ModelAnimation> RenderPreviewVoxels(IModelCache cache,
|
||||
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p);
|
||||
}
|
||||
|
||||
@@ -56,6 +59,8 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public virtual IEnumerable<IActorPreview> RenderPreview(ActorPreviewInitializer init)
|
||||
{
|
||||
var renderer = init.World.WorldActor.Trait<ModelRenderer>();
|
||||
var cache = init.World.WorldActor.Trait<IModelCache>();
|
||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||
var faction = init.GetValue<FactionInit, string>(this);
|
||||
var ownerName = init.Get<OwnerInit>().InternalName;
|
||||
@@ -67,10 +72,10 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
var palette = init.WorldRenderer.Palette(Palette ?? PlayerPalette + ownerName);
|
||||
|
||||
var components = init.Actor.TraitInfos<IRenderActorPreviewVoxelsInfo>()
|
||||
.SelectMany(rvpi => rvpi.RenderPreviewVoxels(init, this, image, init.GetOrientation(), facings, palette))
|
||||
.SelectMany(rvpi => rvpi.RenderPreviewVoxels(cache, init, this, image, init.GetOrientation(), facings, palette))
|
||||
.ToArray();
|
||||
|
||||
yield return new ModelPreview(components, WVec.Zero, 0, Scale, LightPitch,
|
||||
yield return new ModelPreview(renderer, components, WVec.Zero, 0, Scale, LightPitch,
|
||||
LightYaw, LightAmbientColor, LightDiffuseColor, body.CameraPitch,
|
||||
palette, init.WorldRenderer.Palette(NormalsPalette), init.WorldRenderer.Palette(ShadowPalette));
|
||||
}
|
||||
@@ -104,6 +109,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
}
|
||||
|
||||
public readonly RenderVoxelsInfo Info;
|
||||
public readonly ModelRenderer Renderer;
|
||||
|
||||
readonly List<ModelAnimation> components = new();
|
||||
readonly Dictionary<ModelAnimation, AnimationWrapper> wrappers = new();
|
||||
@@ -116,6 +122,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
public RenderVoxels(Actor self, RenderVoxelsInfo info)
|
||||
{
|
||||
this.self = self;
|
||||
Renderer = self.World.WorldActor.Trait<ModelRenderer>();
|
||||
Info = info;
|
||||
body = self.Trait<BodyOrientation>();
|
||||
camera = new WRot(WAngle.Zero, body.CameraPitch - new WAngle(256), new WAngle(256));
|
||||
@@ -150,7 +157,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
return new IRenderable[]
|
||||
{
|
||||
new ModelRenderable(
|
||||
components, self.CenterPosition, 0, camera, Info.Scale,
|
||||
Renderer, components, self.CenterPosition, 0, camera, Info.Scale,
|
||||
lightSource, Info.LightAmbientColor, Info.LightDiffuseColor,
|
||||
colorPalette, normalsPalette, shadowPalette)
|
||||
};
|
||||
@@ -14,9 +14,10 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits.Render
|
||||
namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
{
|
||||
public class WithVoxelBarrelInfo : ConditionalTraitInfo, IRenderActorPreviewVoxelsInfo, Requires<RenderVoxelsInfo>, Requires<ArmamentInfo>, Requires<TurretedInfo>
|
||||
{
|
||||
@@ -37,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public override object Create(ActorInitializer init) { return new WithVoxelBarrel(init.Self, this); }
|
||||
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(IModelCache cache,
|
||||
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
|
||||
{
|
||||
if (!EnabledByDefault)
|
||||
@@ -49,7 +50,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
var t = init.Actor.TraitInfos<TurretedInfo>()
|
||||
.First(tt => tt.Turret == armament.Turret);
|
||||
|
||||
var model = init.World.ModelCache.GetModelSequence(image, Sequence);
|
||||
var model = cache.GetModelSequence(image, Sequence);
|
||||
|
||||
var turretOrientation = t.PreviewOrientation(init, orientation, facings);
|
||||
WVec BarrelOffset() => body.LocalToWorld(t.Offset + LocalOffset.Rotate(turretOrientation()));
|
||||
@@ -77,7 +78,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
.First(tt => tt.Name == armament.Info.Turret);
|
||||
|
||||
var rv = self.Trait<RenderVoxels>();
|
||||
rv.Add(new ModelAnimation(self.World.ModelCache.GetModelSequence(rv.Image, Info.Sequence),
|
||||
rv.Add(new ModelAnimation(rv.Renderer.ModelCache.GetModelSequence(rv.Image, Info.Sequence),
|
||||
BarrelOffset, BarrelRotation,
|
||||
() => IsTraitDisabled, () => 0, info.ShowShadow));
|
||||
}
|
||||
@@ -13,10 +13,11 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits.Render
|
||||
namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
{
|
||||
[Desc("Also returns a default selection size that is calculated automatically from the voxel dimensions.")]
|
||||
public class WithVoxelBodyInfo : ConditionalTraitInfo, IRenderActorPreviewVoxelsInfo, Requires<RenderVoxelsInfo>
|
||||
@@ -29,11 +30,11 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public override object Create(ActorInitializer init) { return new WithVoxelBody(init.Self, this); }
|
||||
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(IModelCache cache,
|
||||
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
|
||||
{
|
||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||
var model = init.World.ModelCache.GetModelSequence(image, Sequence);
|
||||
var model = cache.GetModelSequence(image, Sequence);
|
||||
yield return new ModelAnimation(model, () => Offset,
|
||||
() => body.QuantizeOrientation(orientation(), facings),
|
||||
() => false, () => 0, ShowShadow);
|
||||
@@ -51,7 +52,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
var body = self.Trait<BodyOrientation>();
|
||||
rv = self.Trait<RenderVoxels>();
|
||||
|
||||
var model = self.World.ModelCache.GetModelSequence(rv.Image, info.Sequence);
|
||||
var model = rv.Renderer.ModelCache.GetModelSequence(rv.Image, info.Sequence);
|
||||
modelAnimation = new ModelAnimation(model, () => info.Offset,
|
||||
() => body.QuantizeOrientation(self.Orientation),
|
||||
() => IsTraitDisabled, () => 0, info.ShowShadow);
|
||||
@@ -14,9 +14,10 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Common.Traits.Render
|
||||
namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
{
|
||||
public class WithVoxelTurretInfo : ConditionalTraitInfo, IRenderActorPreviewVoxelsInfo, Requires<RenderVoxelsInfo>, Requires<TurretedInfo>
|
||||
{
|
||||
@@ -31,7 +32,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
|
||||
public override object Create(ActorInitializer init) { return new WithVoxelTurret(init.Self, this); }
|
||||
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(IModelCache cache,
|
||||
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
|
||||
{
|
||||
if (!EnabledByDefault)
|
||||
@@ -40,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
var t = init.Actor.TraitInfos<TurretedInfo>()
|
||||
.First(tt => tt.Turret == Turret);
|
||||
|
||||
var model = init.World.ModelCache.GetModelSequence(image, Sequence);
|
||||
var model = cache.GetModelSequence(image, Sequence);
|
||||
var turretOffset = t.PreviewPosition(init, orientation);
|
||||
var turretOrientation = t.PreviewOrientation(init, orientation, facings);
|
||||
yield return new ModelAnimation(model, turretOffset, turretOrientation, () => false, () => 0, ShowShadow);
|
||||
@@ -58,7 +59,7 @@ namespace OpenRA.Mods.Common.Traits.Render
|
||||
.First(tt => tt.Name == Info.Turret);
|
||||
|
||||
var rv = self.Trait<RenderVoxels>();
|
||||
rv.Add(new ModelAnimation(self.World.ModelCache.GetModelSequence(rv.Image, Info.Sequence),
|
||||
rv.Add(new ModelAnimation(rv.Renderer.ModelCache.GetModelSequence(rv.Image, Info.Sequence),
|
||||
() => turreted.Position(self), () => turreted.WorldOrientation,
|
||||
() => IsTraitDisabled, () => 0, info.ShowShadow));
|
||||
}
|
||||
@@ -14,7 +14,6 @@ using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Mods.Common.Traits.Render;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
@@ -34,11 +33,11 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
|
||||
public override object Create(ActorInitializer init) { return new WithVoxelUnloadBody(init.Self, this); }
|
||||
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(IModelCache cache,
|
||||
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
|
||||
{
|
||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||
var model = init.World.ModelCache.GetModelSequence(image, IdleSequence);
|
||||
var model = cache.GetModelSequence(image, IdleSequence);
|
||||
yield return new ModelAnimation(model, () => WVec.Zero,
|
||||
() => body.QuantizeOrientation(orientation(), facings),
|
||||
() => false, () => 0, ShowShadow);
|
||||
@@ -57,7 +56,7 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
var body = self.Trait<BodyOrientation>();
|
||||
rv = self.Trait<RenderVoxels>();
|
||||
|
||||
var idleModel = self.World.ModelCache.GetModelSequence(rv.Image, info.IdleSequence);
|
||||
var idleModel = rv.Renderer.ModelCache.GetModelSequence(rv.Image, info.IdleSequence);
|
||||
modelAnimation = new ModelAnimation(idleModel, () => WVec.Zero,
|
||||
() => body.QuantizeOrientation(self.Orientation),
|
||||
() => docked,
|
||||
@@ -65,7 +64,7 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
|
||||
rv.Add(modelAnimation);
|
||||
|
||||
var unloadModel = self.World.ModelCache.GetModelSequence(rv.Image, info.UnloadSequence);
|
||||
var unloadModel = rv.Renderer.ModelCache.GetModelSequence(rv.Image, info.UnloadSequence);
|
||||
rv.Add(new ModelAnimation(unloadModel, () => WVec.Zero,
|
||||
() => body.QuantizeOrientation(self.Orientation),
|
||||
() => !docked,
|
||||
|
||||
@@ -14,7 +14,6 @@ using System.Collections.Generic;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Mods.Common.Traits;
|
||||
using OpenRA.Mods.Common.Traits.Render;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
@@ -31,10 +30,10 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
public readonly bool ShowShadow = true;
|
||||
public override object Create(ActorInitializer init) { return new WithVoxelWalkerBody(init.Self, this); }
|
||||
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(
|
||||
public IEnumerable<ModelAnimation> RenderPreviewVoxels(IModelCache cache,
|
||||
ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func<WRot> orientation, int facings, PaletteReference p)
|
||||
{
|
||||
var model = init.World.ModelCache.GetModelSequence(image, Sequence);
|
||||
var model = cache.GetModelSequence(image, Sequence);
|
||||
var body = init.Actor.TraitInfo<BodyOrientationInfo>();
|
||||
var frame = init.GetValue<BodyAnimationFrameInit, uint>(this, 0);
|
||||
|
||||
@@ -61,7 +60,7 @@ namespace OpenRA.Mods.Cnc.Traits.Render
|
||||
var body = self.Trait<BodyOrientation>();
|
||||
rv = self.Trait<RenderVoxels>();
|
||||
|
||||
var model = self.World.ModelCache.GetModelSequence(rv.Image, info.Sequence);
|
||||
var model = rv.Renderer.ModelCache.GetModelSequence(rv.Image, info.Sequence);
|
||||
frames = model.Frames;
|
||||
modelAnimation = new ModelAnimation(model, () => WVec.Zero,
|
||||
() => body.QuantizeOrientation(self.Orientation),
|
||||
|
||||
@@ -12,9 +12,11 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Primitives;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Graphics
|
||||
namespace OpenRA.Mods.Cnc.Traits
|
||||
{
|
||||
public class ModelRenderProxy
|
||||
{
|
||||
@@ -32,7 +34,14 @@ namespace OpenRA.Graphics
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ModelRenderer : IDisposable
|
||||
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
|
||||
[Desc("Render voxels")]
|
||||
public class ModelRendererInfo : TraitInfo, Requires<IModelCacheInfo>
|
||||
{
|
||||
public override object Create(ActorInitializer init) { return new ModelRenderer(this, init.Self); }
|
||||
}
|
||||
|
||||
public sealed class ModelRenderer : IDisposable, IRenderer, INotifyActorDisposing
|
||||
{
|
||||
// Static constants
|
||||
static readonly float[] ShadowDiffuse = new float[] { 0, 0, 0 };
|
||||
@@ -46,28 +55,31 @@ namespace OpenRA.Graphics
|
||||
|
||||
readonly Renderer renderer;
|
||||
readonly IShader shader;
|
||||
public readonly IModelCache ModelCache;
|
||||
|
||||
readonly Dictionary<Sheet, IFrameBuffer> mappedBuffers = new();
|
||||
readonly Stack<KeyValuePair<Sheet, IFrameBuffer>> unmappedBuffers = new();
|
||||
readonly List<(Sheet Sheet, Action Func)> doRender = new();
|
||||
readonly int sheetSize;
|
||||
|
||||
SheetBuilder sheetBuilderForFrame;
|
||||
bool isInFrame;
|
||||
|
||||
public ModelRenderer(Renderer renderer, IShader shader)
|
||||
{
|
||||
this.renderer = renderer;
|
||||
this.shader = shader;
|
||||
}
|
||||
|
||||
public void SetPalette(ITexture palette)
|
||||
{
|
||||
shader.SetTexture("Palette", palette);
|
||||
}
|
||||
|
||||
public void SetViewportParams()
|
||||
public ModelRenderer(ModelRendererInfo info, Actor self)
|
||||
{
|
||||
var a = 2f / renderer.SheetSize;
|
||||
renderer = Game.Renderer;
|
||||
shader = renderer.CreateShader(new ModelShaderBindings());
|
||||
renderer.WorldRenderers = renderer.WorldRenderers.Append(this).ToArray();
|
||||
|
||||
ModelCache = self.Trait<IModelCache>();
|
||||
|
||||
sheetSize = Game.Settings.Graphics.SheetSize;
|
||||
var a = 2f / sheetSize;
|
||||
var view = new[]
|
||||
{
|
||||
a, 0, 0, 0,
|
||||
@@ -176,8 +188,8 @@ namespace OpenRA.Graphics
|
||||
var spriteCenter = new float2(sb.Left + sb.Width / 2, sb.Top + sb.Height / 2);
|
||||
var shadowCenter = new float2(ssb.Left + ssb.Width / 2, ssb.Top + ssb.Height / 2);
|
||||
|
||||
var translateMtx = Util.TranslationMatrix(spriteCenter.X - spriteOffset.X, renderer.SheetSize - (spriteCenter.Y - spriteOffset.Y), 0);
|
||||
var shadowTranslateMtx = Util.TranslationMatrix(shadowCenter.X - shadowSpriteOffset.X, renderer.SheetSize - (shadowCenter.Y - shadowSpriteOffset.Y), 0);
|
||||
var translateMtx = Util.TranslationMatrix(spriteCenter.X - spriteOffset.X, sheetSize - (spriteCenter.Y - spriteOffset.Y), 0);
|
||||
var shadowTranslateMtx = Util.TranslationMatrix(shadowCenter.X - shadowSpriteOffset.X, sheetSize - (shadowCenter.Y - shadowSpriteOffset.Y), 0);
|
||||
var correctionTransform = Util.MatrixMultiply(translateMtx, FlipMtx);
|
||||
var shadowCorrectionTransform = Util.MatrixMultiply(shadowTranslateMtx, ShadowScaleFlipMtx);
|
||||
|
||||
@@ -213,12 +225,12 @@ namespace OpenRA.Graphics
|
||||
// Transform light vector from shadow -> world -> limb coords
|
||||
var lightDirection = ExtractRotationVector(Util.MatrixMultiply(it, lightTransform));
|
||||
|
||||
Render(rd, wr.World.ModelCache, Util.MatrixMultiply(transform, t), lightDirection,
|
||||
Render(rd, ModelCache, Util.MatrixMultiply(transform, t), lightDirection,
|
||||
lightAmbientColor, lightDiffuseColor, color.TextureMidIndex, normals.TextureMidIndex);
|
||||
|
||||
// Disable shadow normals by forcing zero diffuse and identity ambient light
|
||||
if (m.ShowShadow)
|
||||
Render(rd, wr.World.ModelCache, Util.MatrixMultiply(shadow, t), lightDirection,
|
||||
Render(rd, ModelCache, Util.MatrixMultiply(shadow, t), lightDirection,
|
||||
ShadowAmbient, ShadowDiffuse, shadowPalette.TextureMidIndex, normals.TextureMidIndex);
|
||||
}
|
||||
}
|
||||
@@ -298,14 +310,14 @@ namespace OpenRA.Graphics
|
||||
Game.Renderer.Flush();
|
||||
fbo.Bind();
|
||||
|
||||
Game.Renderer.Context.EnableDepthBuffer();
|
||||
Game.Renderer.EnableDepthBuffer();
|
||||
return fbo;
|
||||
}
|
||||
|
||||
static void DisableFrameBuffer(IFrameBuffer fbo)
|
||||
{
|
||||
Game.Renderer.Flush();
|
||||
Game.Renderer.Context.DisableDepthBuffer();
|
||||
Game.Renderer.DisableDepthBuffer();
|
||||
fbo.Unbind();
|
||||
}
|
||||
|
||||
@@ -353,8 +365,7 @@ namespace OpenRA.Graphics
|
||||
return kv.Key;
|
||||
}
|
||||
|
||||
var size = new Size(renderer.SheetSize, renderer.SheetSize);
|
||||
var framebuffer = renderer.Context.CreateFrameBuffer(size);
|
||||
var framebuffer = renderer.CreateFrameBuffer(new Size(sheetSize, sheetSize));
|
||||
var sheet = new Sheet(SheetType.BGRA, framebuffer.Texture);
|
||||
mappedBuffers.Add(sheet, framebuffer);
|
||||
|
||||
@@ -371,6 +382,12 @@ namespace OpenRA.Graphics
|
||||
|
||||
mappedBuffers.Clear();
|
||||
unmappedBuffers.Clear();
|
||||
renderer.WorldRenderers = renderer.WorldRenderers.Where(r => r != this).ToArray();
|
||||
}
|
||||
|
||||
void INotifyActorDisposing.Disposing(Actor a)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -12,50 +12,45 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using OpenRA.FileSystem;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Cnc.Graphics;
|
||||
using OpenRA.Traits;
|
||||
|
||||
namespace OpenRA.Mods.Cnc.Graphics
|
||||
namespace OpenRA.Mods.Cnc.Traits
|
||||
{
|
||||
public class VoxelModelSequenceLoader : IModelSequenceLoader
|
||||
[TraitLocation(SystemActors.World | SystemActors.EditorWorld)]
|
||||
[Desc("Loads voxel models.")]
|
||||
public sealed class VoxelCacheInfo : TraitInfo, IModelCacheInfo
|
||||
{
|
||||
public Action<string> OnMissingModelError { get; set; }
|
||||
|
||||
public VoxelModelSequenceLoader(ModData modData) { }
|
||||
|
||||
public IModelCache CacheModels(IReadOnlyFileSystem fileSystem, ModData modData, IReadOnlyDictionary<string, MiniYamlNode> modelSequences)
|
||||
{
|
||||
var cache = new VoxelModelCache(fileSystem);
|
||||
foreach (var kv in modelSequences)
|
||||
{
|
||||
modData.LoadScreen.Display();
|
||||
try
|
||||
{
|
||||
cache.CacheModel(kv.Key, kv.Value.Value);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
Console.WriteLine(ex);
|
||||
|
||||
// Eat the FileNotFound exceptions from missing sprites
|
||||
OnMissingModelError(ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
cache.LoadComplete();
|
||||
|
||||
return cache;
|
||||
}
|
||||
public override object Create(ActorInitializer init) { return new VoxelCache(this, init.Self); }
|
||||
}
|
||||
|
||||
public sealed class VoxelModelCache : IModelCache
|
||||
public sealed class VoxelCache : IModelCache, INotifyActorDisposing, IDisposable
|
||||
{
|
||||
readonly VoxelLoader loader;
|
||||
readonly Dictionary<string, Dictionary<string, IModel>> models = new();
|
||||
|
||||
public VoxelModelCache(IReadOnlyFileSystem fileSystem)
|
||||
public VoxelCache(VoxelCacheInfo info, Actor self)
|
||||
{
|
||||
loader = new VoxelLoader(fileSystem);
|
||||
var map = self.World.Map;
|
||||
loader = new VoxelLoader(map);
|
||||
foreach (var kv in map.Rules.ModelSequences)
|
||||
{
|
||||
Game.ModData.LoadScreen.Display();
|
||||
try
|
||||
{
|
||||
CacheModel(kv.Key, kv.Value.Value);
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
{
|
||||
// Eat the FileNotFound exceptions from missing sprites.
|
||||
Console.WriteLine(ex);
|
||||
Log.Write("debug", ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
loader.RefreshBuffer();
|
||||
loader.Finish();
|
||||
}
|
||||
|
||||
public void CacheModel(string model, MiniYaml definition)
|
||||
@@ -63,12 +58,6 @@ namespace OpenRA.Mods.Cnc.Graphics
|
||||
models.Add(model, definition.ToDictionary(my => LoadVoxel(model, my)));
|
||||
}
|
||||
|
||||
public void LoadComplete()
|
||||
{
|
||||
loader.RefreshBuffer();
|
||||
loader.Finish();
|
||||
}
|
||||
|
||||
IModel LoadVoxel(string unit, MiniYaml info)
|
||||
{
|
||||
var vxl = unit;
|
||||
@@ -120,5 +109,10 @@ namespace OpenRA.Mods.Cnc.Graphics
|
||||
{
|
||||
loader.Dispose();
|
||||
}
|
||||
|
||||
void INotifyActorDisposing.Disposing(Actor a)
|
||||
{
|
||||
Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,8 @@
|
||||
*/
|
||||
#endregion
|
||||
|
||||
using System;
|
||||
|
||||
namespace OpenRA.Mods.Cnc
|
||||
{
|
||||
public static class Util
|
||||
@@ -65,5 +67,249 @@ namespace OpenRA.Mods.Cnc
|
||||
|
||||
return Common.Util.QuantizeFacing(facing, steps);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,12 +11,13 @@
|
||||
|
||||
using System;
|
||||
using OpenRA.Graphics;
|
||||
using OpenRA.Mods.Common.Graphics;
|
||||
using OpenRA.Mods.Cnc.Graphics;
|
||||
using OpenRA.Mods.Cnc.Traits;
|
||||
using OpenRA.Widgets;
|
||||
|
||||
namespace OpenRA.Mods.Common.Widgets
|
||||
namespace OpenRA.Mods.Cnc.Widgets
|
||||
{
|
||||
public class ModelWidget : Widget
|
||||
public class ModelWidget : Widget, IModelWidget
|
||||
{
|
||||
public string Palette = "terrain";
|
||||
public string PlayerPalette = "player";
|
||||
@@ -75,6 +76,20 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
WorldRenderer = other.WorldRenderer;
|
||||
}
|
||||
|
||||
string IModelWidget.Palette => GetPalette();
|
||||
float IModelWidget.Scale => GetScale();
|
||||
|
||||
void IModelWidget.Setup(Func<bool> isVisible, Func<string> getPalette, Func<string> getPlayerPalette,
|
||||
Func<float> getScale, Func<IModel> getVoxel, Func<WRot> getRotation)
|
||||
{
|
||||
IsVisible = isVisible;
|
||||
GetPalette = getPalette;
|
||||
GetPlayerPalette = getPlayerPalette;
|
||||
GetScale = getScale;
|
||||
GetVoxel = getVoxel;
|
||||
GetRotation = getRotation;
|
||||
}
|
||||
|
||||
public override Widget Clone()
|
||||
{
|
||||
return new ModelWidget(this);
|
||||
@@ -188,7 +203,10 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
|
||||
var animations = new ModelAnimation[] { animation };
|
||||
|
||||
var renderer = WorldRenderer.World.WorldActor.Trait<ModelRenderer>();
|
||||
|
||||
var preview = new ModelPreview(
|
||||
renderer,
|
||||
new ModelAnimation[] { animation }, WVec.Zero, 0,
|
||||
cachedScale,
|
||||
new WAngle(cachedLightPitch),
|
||||
@@ -206,6 +224,7 @@ namespace OpenRA.Mods.Common.Widgets
|
||||
|
||||
var camera = new WRot(WAngle.Zero, cachedCameraAngle - new WAngle(256), new WAngle(256));
|
||||
var modelRenderable = new UIModelRenderable(
|
||||
renderer,
|
||||
animations, WPos.Zero, origin, 0, camera, scale,
|
||||
WRot.None, cachedLightAmbientColor, cachedLightDiffuseColor,
|
||||
paletteReferencePlayer, paletteReferenceNormals, paletteReferenceShadow);
|
||||
@@ -151,17 +151,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
if (playerWidget != null)
|
||||
playerWidget.IsVisible = () => isVideoLoaded && !isLoadError;
|
||||
|
||||
var modelWidget = panel.GetOrNull<ModelWidget>("VOXEL");
|
||||
if (modelWidget != null)
|
||||
if (panel.GetOrNull<Widget>("VOXEL") is IModelWidget modelWidget)
|
||||
{
|
||||
modelWidget.GetVoxel = () => currentVoxel;
|
||||
currentPalette = modelWidget.Palette;
|
||||
modelScale = modelWidget.Scale;
|
||||
modelWidget.GetPalette = () => currentPalette;
|
||||
modelWidget.GetPlayerPalette = () => currentPalette;
|
||||
modelWidget.GetRotation = () => modelOrientation;
|
||||
modelWidget.IsVisible = () => !isVideoLoaded && !isLoadError && currentVoxel != null;
|
||||
modelWidget.GetScale = () => modelScale;
|
||||
modelWidget.Setup(
|
||||
() => !isVideoLoaded && !isLoadError && currentVoxel != null,
|
||||
() => currentPalette,
|
||||
() => currentPalette,
|
||||
() => modelScale,
|
||||
() => currentVoxel,
|
||||
() => modelOrientation);
|
||||
}
|
||||
|
||||
var errorLabelWidget = panel.GetOrNull("ERROR");
|
||||
@@ -530,7 +530,7 @@ namespace OpenRA.Mods.Common.Widgets.Logic
|
||||
else if (allowedModelExtensions.Contains(fileExtension))
|
||||
{
|
||||
var voxelName = Path.GetFileNameWithoutExtension(filename);
|
||||
currentVoxel = world.ModelCache.GetModel(prefix + voxelName);
|
||||
currentVoxel = world.WorldActor.Trait<IModelCache>().GetModel(prefix + voxelName);
|
||||
currentSprites = null;
|
||||
}
|
||||
else if (allowedAudioExtensions.Contains(fileExtension))
|
||||
|
||||
@@ -33,7 +33,5 @@ TerrainFormat: DefaultTerrain
|
||||
|
||||
SpriteSequenceFormat: DefaultSpriteSequence
|
||||
|
||||
ModelSequenceFormat: PlaceholderModelSequence
|
||||
|
||||
DiscordService:
|
||||
ApplicationId: 699222659766026240
|
||||
|
||||
@@ -240,8 +240,6 @@ TerrainFormat: DefaultTerrain
|
||||
|
||||
SpriteSequenceFormat: ClassicTilesetSpecificSpriteSequence
|
||||
|
||||
ModelSequenceFormat: PlaceholderModelSequence
|
||||
|
||||
AssetBrowser:
|
||||
SpriteExtensions: .shp, .tem, .win, .sno, .des, .jun
|
||||
AudioExtensions: .aud, .wav, .v00, .v01, .v02, .v03, .var
|
||||
|
||||
@@ -222,8 +222,6 @@ TerrainFormat: DefaultTerrain
|
||||
|
||||
SpriteSequenceFormat: DefaultSpriteSequence
|
||||
|
||||
ModelSequenceFormat: PlaceholderModelSequence
|
||||
|
||||
AssetBrowser:
|
||||
SpriteExtensions: .shp, .r8, .tmp
|
||||
AudioExtensions: .aud, .wav
|
||||
|
||||
@@ -71,5 +71,3 @@ SpriteFormats: PngSheet
|
||||
TerrainFormat: DefaultTerrain
|
||||
|
||||
SpriteSequenceFormat: DefaultSpriteSequence
|
||||
|
||||
ModelSequenceFormat: PlaceholderModelSequence
|
||||
|
||||
@@ -243,8 +243,6 @@ TerrainFormat: DefaultTerrain
|
||||
|
||||
SpriteSequenceFormat: ClassicTilesetSpecificSpriteSequence
|
||||
|
||||
ModelSequenceFormat: PlaceholderModelSequence
|
||||
|
||||
AssetBrowser:
|
||||
SpriteExtensions: .shp, .tmp, .tem, .des, .sno, .int
|
||||
AudioExtensions: .aud, .wav, .r00, .r01, .r02, .r03, .v00, .v01, .v02, .v03
|
||||
|
||||
@@ -273,8 +273,6 @@ TerrainFormat: DefaultTerrain
|
||||
|
||||
SpriteSequenceFormat: TilesetSpecificSpriteSequence
|
||||
|
||||
ModelSequenceFormat: VoxelModelSequence
|
||||
|
||||
AssetBrowser:
|
||||
SpriteExtensions: .shp, .tem, .sno
|
||||
ModelExtensions: .vxl
|
||||
|
||||
@@ -8,6 +8,8 @@
|
||||
MusicPlaylist:
|
||||
VictoryMusic: score
|
||||
DefeatMusic: fsmap
|
||||
VoxelCache:
|
||||
ModelRenderer:
|
||||
TerrainRenderer:
|
||||
TerrainLighting:
|
||||
ShroudRenderer:
|
||||
|
||||
Reference in New Issue
Block a user