diff --git a/OpenRA.Game/Game.cs b/OpenRA.Game/Game.cs index 6520b0476a..3eab00cc53 100644 --- a/OpenRA.Game/Game.cs +++ b/OpenRA.Game/Game.cs @@ -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 diff --git a/OpenRA.Game/Graphics/Model.cs b/OpenRA.Game/Graphics/Model.cs index 2e3893cf91..ffa3fd184d 100644 --- a/OpenRA.Game/Graphics/Model.cs +++ b/OpenRA.Game/Graphics/Model.cs @@ -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 isVisible, Func getPalette, Func getPlayerPalette, + Func getScale, Func getVoxel, Func 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 VertexBuffer { get; } } - - public interface IModelSequenceLoader - { - Action OnMissingModelError { get; set; } - IModelCache CacheModels(IReadOnlyFileSystem fileSystem, ModData modData, IReadOnlyDictionary modelDefinitions); - } - - public class PlaceholderModelSequenceLoader : IModelSequenceLoader - { - public Action OnMissingModelError { get; set; } - - sealed class PlaceholderModelCache : IModelCache - { - public IVertexBuffer 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 modelDefinitions) - { - return new PlaceholderModelCache(); - } - } } diff --git a/OpenRA.Game/Graphics/PlatformInterfaces.cs b/OpenRA.Game/Graphics/PlatformInterfaces.cs index 70c4c42e24..76c9001231 100644 --- a/OpenRA.Game/Graphics/PlatformInterfaces.cs +++ b/OpenRA.Game/Graphics/PlatformInterfaces.cs @@ -104,6 +104,13 @@ namespace OpenRA string GLVersion { get; } } + public interface IRenderer + { + void BeginFrame(); + void EndFrame(); + void SetPalette(ITexture palette); + } + public interface IVertexBuffer : IDisposable where T : struct { void Bind(); diff --git a/OpenRA.Game/Graphics/Util.cs b/OpenRA.Game/Graphics/Util.cs index abe28ca29f..e72d9e9c37 100644 --- a/OpenRA.Game/Graphics/Util.cs +++ b/OpenRA.Game/Graphics/Util.cs @@ -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; - } } } diff --git a/OpenRA.Game/Graphics/WorldRenderer.cs b/OpenRA.Game/Graphics/WorldRenderer.cs index 0ab10beed6..d61352b2af 100644 --- a/OpenRA.Game/Graphics/WorldRenderer.cs +++ b/OpenRA.Game/Graphics/WorldRenderer.cs @@ -44,6 +44,7 @@ namespace OpenRA.Graphics readonly List preparedAnnotationRenderables = new(); readonly List renderablesBuffer = new(); + readonly IRenderer[] renderers; internal WorldRenderer(ModData modData, World world) { @@ -66,11 +67,24 @@ namespace OpenRA.Graphics palette.Initialize(); TerrainLighting = world.WorldActor.TraitOrDefault(); + renderers = world.WorldActor.TraitsImplementing().ToArray(); terrainRenderer = world.WorldActor.TraitOrDefault(); debugVis = Exts.Lazy(() => world.WorldActor.TraitOrDefault()); } + 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()) diff --git a/OpenRA.Game/Manifest.cs b/OpenRA.Game/Manifest.cs index 8f3da202da..a07c5e7138 100644 --- a/OpenRA.Game/Manifest.cs +++ b/OpenRA.Game/Manifest.cs @@ -43,17 +43,6 @@ namespace OpenRA } } - public sealed class ModelSequenceFormat : IGlobalModData - { - public readonly string Type; - public readonly IReadOnlyDictionary Metadata; - public ModelSequenceFormat(MiniYaml yaml) - { - Type = yaml.Value; - Metadata = new ReadOnlyDictionary(yaml.ToDictionary()); - } - } - public class ModMetadata { public string Title; diff --git a/OpenRA.Game/ModData.cs b/OpenRA.Game/ModData.cs index f22a4daf43..22b3a59dc4 100644 --- a/OpenRA.Game/ModData.cs +++ b/OpenRA.Game/ModData.cs @@ -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(); - 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)); diff --git a/OpenRA.Game/Renderer.cs b/OpenRA.Game/Renderer.cs index 27e0e67e32..877dc7b205 100644 --- a/OpenRA.Game/Renderer.cs +++ b/OpenRA.Game/Renderer.cs @@ -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(); 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 CreateVertexBuffer(int length) where T : struct { return Context.CreateVertexBuffer(length); @@ -514,7 +523,6 @@ namespace OpenRA public void Dispose() { - WorldModelRenderer.Dispose(); tempVertexBuffer.Dispose(); quadIndexBuffer.Dispose(); fontSheetBuilder?.Dispose(); diff --git a/OpenRA.Game/World.cs b/OpenRA.Game/World.cs index 6a69c15aee..505fdba1d1 100644 --- a/OpenRA.Game/World.cs +++ b/OpenRA.Game/World.cs @@ -49,7 +49,6 @@ namespace OpenRA public readonly MersenneTwister SharedRandom; public readonly MersenneTwister LocalRandom; - public readonly IModelCache ModelCache; public LongBitSet AllPlayersMask = default; public readonly LongBitSet 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(); @@ -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(); diff --git a/OpenRA.Mods.Cnc/FileFormats/HvaReader.cs b/OpenRA.Mods.Cnc/FileFormats/HvaReader.cs index 52984cd532..282f989ac8 100644 --- a/OpenRA.Mods.Cnc/FileFormats/HvaReader.cs +++ b/OpenRA.Mods.Cnc/FileFormats/HvaReader.cs @@ -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!"); } diff --git a/OpenRA.Mods.Common/Graphics/ModelActorPreview.cs b/OpenRA.Mods.Cnc/Graphics/ModelActorPreview.cs similarity index 80% rename from OpenRA.Mods.Common/Graphics/ModelActorPreview.cs rename to OpenRA.Mods.Cnc/Graphics/ModelActorPreview.cs index 1e9561e2e9..2f5feb434c 100644 --- a/OpenRA.Mods.Common/Graphics/ModelActorPreview.cs +++ b/OpenRA.Mods.Cnc/Graphics/ModelActorPreview.cs @@ -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 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 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); } diff --git a/OpenRA.Mods.Common/Graphics/ModelRenderable.cs b/OpenRA.Mods.Cnc/Graphics/ModelRenderable.cs similarity index 85% rename from OpenRA.Mods.Common/Graphics/ModelRenderable.cs rename to OpenRA.Mods.Cnc/Graphics/ModelRenderable.cs index 0f86a680b5..a5fc236b02 100644 --- a/OpenRA.Mods.Common/Graphics/ModelRenderable.cs +++ b/OpenRA.Mods.Cnc/Graphics/ModelRenderable.cs @@ -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 models; readonly WRot camera; readonly WRot lightSource; @@ -29,20 +31,21 @@ namespace OpenRA.Mods.Common.Graphics readonly float scale; public ModelRenderable( - IEnumerable models, WPos pos, int zOffset, in WRot camera, float scale, + ModelRenderer renderer, IEnumerable 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 models, WPos pos, int zOffset, in WRot camera, float scale, + ModelRenderer renderer, IEnumerable 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]); diff --git a/OpenRA.Mods.Common/Graphics/UIModelRenderable.cs b/OpenRA.Mods.Cnc/Graphics/UIModelRenderable.cs similarity index 85% rename from OpenRA.Mods.Common/Graphics/UIModelRenderable.cs rename to OpenRA.Mods.Cnc/Graphics/UIModelRenderable.cs index 19cb37b82c..7e8fddde5e 100644 --- a/OpenRA.Mods.Common/Graphics/UIModelRenderable.cs +++ b/OpenRA.Mods.Cnc/Graphics/UIModelRenderable.cs @@ -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 models; readonly int2 screenPos; readonly WRot camera; @@ -30,10 +32,11 @@ namespace OpenRA.Mods.Common.Graphics readonly float scale; public UIModelRenderable( - IEnumerable models, WPos effectiveWorldPos, int2 screenPos, int zOffset, + ModelRenderer renderer, IEnumerable 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]); diff --git a/OpenRA.Mods.Cnc/Graphics/Voxel.cs b/OpenRA.Mods.Cnc/Graphics/Voxel.cs index 9d0552054a..d9f149d9ca 100644 --- a/OpenRA.Mods.Cnc/Graphics/Voxel.cs +++ b/OpenRA.Mods.Cnc/Graphics/Voxel.cs @@ -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]); diff --git a/OpenRA.Mods.Cnc/Scripting/Properties/IonCannonProperties.cs b/OpenRA.Mods.Cnc/Scripting/Properties/IonCannonProperties.cs index 4f44b8adef..ec40be6759 100644 --- a/OpenRA.Mods.Cnc/Scripting/Properties/IonCannonProperties.cs +++ b/OpenRA.Mods.Cnc/Scripting/Properties/IonCannonProperties.cs @@ -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 diff --git a/OpenRA.Mods.Common/Traits/Render/RenderVoxels.cs b/OpenRA.Mods.Cnc/Traits/Render/RenderVoxels.cs similarity index 88% rename from OpenRA.Mods.Common/Traits/Render/RenderVoxels.cs rename to OpenRA.Mods.Cnc/Traits/Render/RenderVoxels.cs index d0f43f82c4..eebdfd90b5 100644 --- a/OpenRA.Mods.Common/Traits/Render/RenderVoxels.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/RenderVoxels.cs @@ -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 RenderPreviewVoxels( + IEnumerable RenderPreviewVoxels(IModelCache cache, ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func orientation, int facings, PaletteReference p); } @@ -56,6 +59,8 @@ namespace OpenRA.Mods.Common.Traits.Render public virtual IEnumerable RenderPreview(ActorPreviewInitializer init) { + var renderer = init.World.WorldActor.Trait(); + var cache = init.World.WorldActor.Trait(); var body = init.Actor.TraitInfo(); var faction = init.GetValue(this); var ownerName = init.Get().InternalName; @@ -67,10 +72,10 @@ namespace OpenRA.Mods.Common.Traits.Render var palette = init.WorldRenderer.Palette(Palette ?? PlayerPalette + ownerName); var components = init.Actor.TraitInfos() - .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 components = new(); readonly Dictionary 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(); Info = info; body = self.Trait(); 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) }; diff --git a/OpenRA.Mods.Common/Traits/Render/WithVoxelBarrel.cs b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelBarrel.cs similarity index 91% rename from OpenRA.Mods.Common/Traits/Render/WithVoxelBarrel.cs rename to OpenRA.Mods.Cnc/Traits/Render/WithVoxelBarrel.cs index 8c8e18cc78..cc65439f8b 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithVoxelBarrel.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelBarrel.cs @@ -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, Requires, Requires { @@ -37,7 +38,7 @@ namespace OpenRA.Mods.Common.Traits.Render public override object Create(ActorInitializer init) { return new WithVoxelBarrel(init.Self, this); } - public IEnumerable RenderPreviewVoxels( + public IEnumerable RenderPreviewVoxels(IModelCache cache, ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func orientation, int facings, PaletteReference p) { if (!EnabledByDefault) @@ -49,7 +50,7 @@ namespace OpenRA.Mods.Common.Traits.Render var t = init.Actor.TraitInfos() .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(); - 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)); } diff --git a/OpenRA.Mods.Common/Traits/Render/WithVoxelBody.cs b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelBody.cs similarity index 88% rename from OpenRA.Mods.Common/Traits/Render/WithVoxelBody.cs rename to OpenRA.Mods.Cnc/Traits/Render/WithVoxelBody.cs index cf4b44e703..9ca91e7416 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithVoxelBody.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelBody.cs @@ -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 @@ -29,11 +30,11 @@ namespace OpenRA.Mods.Common.Traits.Render public override object Create(ActorInitializer init) { return new WithVoxelBody(init.Self, this); } - public IEnumerable RenderPreviewVoxels( + public IEnumerable RenderPreviewVoxels(IModelCache cache, ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func orientation, int facings, PaletteReference p) { var body = init.Actor.TraitInfo(); - 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(); rv = self.Trait(); - 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); diff --git a/OpenRA.Mods.Common/Traits/Render/WithVoxelTurret.cs b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelTurret.cs similarity index 87% rename from OpenRA.Mods.Common/Traits/Render/WithVoxelTurret.cs rename to OpenRA.Mods.Cnc/Traits/Render/WithVoxelTurret.cs index 025e2ec170..a22067cd07 100644 --- a/OpenRA.Mods.Common/Traits/Render/WithVoxelTurret.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelTurret.cs @@ -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, Requires { @@ -31,7 +32,7 @@ namespace OpenRA.Mods.Common.Traits.Render public override object Create(ActorInitializer init) { return new WithVoxelTurret(init.Self, this); } - public IEnumerable RenderPreviewVoxels( + public IEnumerable RenderPreviewVoxels(IModelCache cache, ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func orientation, int facings, PaletteReference p) { if (!EnabledByDefault) @@ -40,7 +41,7 @@ namespace OpenRA.Mods.Common.Traits.Render var t = init.Actor.TraitInfos() .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(); - 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)); } diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithVoxelUnloadBody.cs b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelUnloadBody.cs index a00adc70e7..b66ef6ee69 100644 --- a/OpenRA.Mods.Cnc/Traits/Render/WithVoxelUnloadBody.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelUnloadBody.cs @@ -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 RenderPreviewVoxels( + public IEnumerable RenderPreviewVoxels(IModelCache cache, ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func orientation, int facings, PaletteReference p) { var body = init.Actor.TraitInfo(); - 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(); rv = self.Trait(); - 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, diff --git a/OpenRA.Mods.Cnc/Traits/Render/WithVoxelWalkerBody.cs b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelWalkerBody.cs index bf32d35f37..4f4f9bf284 100644 --- a/OpenRA.Mods.Cnc/Traits/Render/WithVoxelWalkerBody.cs +++ b/OpenRA.Mods.Cnc/Traits/Render/WithVoxelWalkerBody.cs @@ -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 RenderPreviewVoxels( + public IEnumerable RenderPreviewVoxels(IModelCache cache, ActorPreviewInitializer init, RenderVoxelsInfo rv, string image, Func orientation, int facings, PaletteReference p) { - var model = init.World.ModelCache.GetModelSequence(image, Sequence); + var model = cache.GetModelSequence(image, Sequence); var body = init.Actor.TraitInfo(); var frame = init.GetValue(this, 0); @@ -61,7 +60,7 @@ namespace OpenRA.Mods.Cnc.Traits.Render var body = self.Trait(); rv = self.Trait(); - 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), diff --git a/OpenRA.Game/Graphics/ModelRenderer.cs b/OpenRA.Mods.Cnc/Traits/World/ModelRenderer.cs similarity index 89% rename from OpenRA.Game/Graphics/ModelRenderer.cs rename to OpenRA.Mods.Cnc/Traits/World/ModelRenderer.cs index 146d90819b..7bd6c98753 100644 --- a/OpenRA.Game/Graphics/ModelRenderer.cs +++ b/OpenRA.Mods.Cnc/Traits/World/ModelRenderer.cs @@ -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 + { + 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 mappedBuffers = new(); readonly Stack> 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(); + + 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(); } } } diff --git a/OpenRA.Mods.Cnc/Graphics/VoxelModelSequenceLoader.cs b/OpenRA.Mods.Cnc/Traits/World/VoxelCache.cs similarity index 71% rename from OpenRA.Mods.Cnc/Graphics/VoxelModelSequenceLoader.cs rename to OpenRA.Mods.Cnc/Traits/World/VoxelCache.cs index 8eea699f4c..a1c8c76d48 100644 --- a/OpenRA.Mods.Cnc/Graphics/VoxelModelSequenceLoader.cs +++ b/OpenRA.Mods.Cnc/Traits/World/VoxelCache.cs @@ -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 OnMissingModelError { get; set; } - - public VoxelModelSequenceLoader(ModData modData) { } - - public IModelCache CacheModels(IReadOnlyFileSystem fileSystem, ModData modData, IReadOnlyDictionary 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> 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(); + } } } diff --git a/OpenRA.Mods.Cnc/Util.cs b/OpenRA.Mods.Cnc/Util.cs index b38589fd1a..53e0e1271f 100644 --- a/OpenRA.Mods.Cnc/Util.cs +++ b/OpenRA.Mods.Cnc/Util.cs @@ -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; + } } } diff --git a/OpenRA.Mods.Common/Widgets/ModelWidget.cs b/OpenRA.Mods.Cnc/Widgets/ModelWidget.cs similarity index 90% rename from OpenRA.Mods.Common/Widgets/ModelWidget.cs rename to OpenRA.Mods.Cnc/Widgets/ModelWidget.cs index bf5652a7b9..1ed7b67fc5 100644 --- a/OpenRA.Mods.Common/Widgets/ModelWidget.cs +++ b/OpenRA.Mods.Cnc/Widgets/ModelWidget.cs @@ -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 isVisible, Func getPalette, Func getPlayerPalette, + Func getScale, Func getVoxel, Func 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(); + 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); diff --git a/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs b/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs index 8c77a81646..25d7e9ed4f 100644 --- a/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs +++ b/OpenRA.Mods.Common/Widgets/Logic/AssetBrowserLogic.cs @@ -151,17 +151,17 @@ namespace OpenRA.Mods.Common.Widgets.Logic if (playerWidget != null) playerWidget.IsVisible = () => isVideoLoaded && !isLoadError; - var modelWidget = panel.GetOrNull("VOXEL"); - if (modelWidget != null) + if (panel.GetOrNull("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().GetModel(prefix + voxelName); currentSprites = null; } else if (allowedAudioExtensions.Contains(fileExtension)) diff --git a/mods/all/mod.yaml b/mods/all/mod.yaml index b674078b64..1429b17a5a 100644 --- a/mods/all/mod.yaml +++ b/mods/all/mod.yaml @@ -33,7 +33,5 @@ TerrainFormat: DefaultTerrain SpriteSequenceFormat: DefaultSpriteSequence -ModelSequenceFormat: PlaceholderModelSequence - DiscordService: ApplicationId: 699222659766026240 diff --git a/mods/cnc/mod.yaml b/mods/cnc/mod.yaml index 9402de252f..b3b8af0dff 100644 --- a/mods/cnc/mod.yaml +++ b/mods/cnc/mod.yaml @@ -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 diff --git a/mods/d2k/mod.yaml b/mods/d2k/mod.yaml index c5703d257b..21513d3c03 100644 --- a/mods/d2k/mod.yaml +++ b/mods/d2k/mod.yaml @@ -222,8 +222,6 @@ TerrainFormat: DefaultTerrain SpriteSequenceFormat: DefaultSpriteSequence -ModelSequenceFormat: PlaceholderModelSequence - AssetBrowser: SpriteExtensions: .shp, .r8, .tmp AudioExtensions: .aud, .wav diff --git a/mods/modcontent/mod.yaml b/mods/modcontent/mod.yaml index 0d90cf9a0b..585c6a003b 100644 --- a/mods/modcontent/mod.yaml +++ b/mods/modcontent/mod.yaml @@ -71,5 +71,3 @@ SpriteFormats: PngSheet TerrainFormat: DefaultTerrain SpriteSequenceFormat: DefaultSpriteSequence - -ModelSequenceFormat: PlaceholderModelSequence diff --git a/mods/ra/mod.yaml b/mods/ra/mod.yaml index f8d94c26a3..c3ba7e977c 100644 --- a/mods/ra/mod.yaml +++ b/mods/ra/mod.yaml @@ -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 diff --git a/mods/ts/mod.yaml b/mods/ts/mod.yaml index e41828aa41..d24241a036 100644 --- a/mods/ts/mod.yaml +++ b/mods/ts/mod.yaml @@ -273,8 +273,6 @@ TerrainFormat: DefaultTerrain SpriteSequenceFormat: TilesetSpecificSpriteSequence -ModelSequenceFormat: VoxelModelSequence - AssetBrowser: SpriteExtensions: .shp, .tem, .sno ModelExtensions: .vxl diff --git a/mods/ts/rules/world.yaml b/mods/ts/rules/world.yaml index bdd59bcfb1..e1ca8228cc 100644 --- a/mods/ts/rules/world.yaml +++ b/mods/ts/rules/world.yaml @@ -8,6 +8,8 @@ MusicPlaylist: VictoryMusic: score DefeatMusic: fsmap + VoxelCache: + ModelRenderer: TerrainRenderer: TerrainLighting: ShroudRenderer: