Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Shift hotkey added & Z level splicing #87

Merged
merged 1 commit into from
Oct 23, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions ACViewer/Config/MapViewerOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,9 @@ namespace ACViewer.Config
public class MapViewerOptions
{
public MapViewerMode Mode { get; set; }
public bool EnableZSlicing { get; set; } = false;
public int CurrentZLevel { get; set; } = 1;
public float LevelHeight { get; set; } = 10.0f;

public MapViewerOptions()
{
Expand Down
1 change: 1 addition & 0 deletions ACViewer/Extensions/CommandHandler.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System;
using System.Windows.Input;
using ACViewer.Config;

namespace ACViewer.Extensions
{
Expand Down
5 changes: 5 additions & 0 deletions ACViewer/Extensions/Vector3Extensions.cs
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
using System;

using Microsoft.Xna.Framework;

using System.Numerics;

using ACE.Server.Physics;

namespace ACViewer
{
public static class Vector3Extensions
{

public static System.Numerics.Vector3 ToNumerics(this Microsoft.Xna.Framework.Vector3 v)
{
return new System.Numerics.Vector3(v.X, v.Y, v.Z);
Expand Down
3 changes: 2 additions & 1 deletion ACViewer/Model/VertexInstance.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,10 @@ namespace ACViewer.Model
{
public struct VertexInstance : IVertexType
{
public Vector3 Position;
public Vector3 Position { get; set; }
public Vector4 Orientation;
public Vector3 Scale;


public readonly static VertexDeclaration VertexDeclaration = new VertexDeclaration
(
Expand Down
93 changes: 92 additions & 1 deletion ACViewer/Render/Buffer.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

using ACE.DatLoader.Entity;
using ACE.Server.Physics;

using ACViewer.Config;
using ACViewer.Extensions;
using ACViewer.Enum;
using ACViewer.Model;

Expand Down Expand Up @@ -86,6 +88,95 @@ public void Init()

AnimatedTextureAtlasChains = new Dictionary<TextureFormat, TextureAtlasChain>();
}

private bool IsInCurrentZLevel(Vector3 position)
{
if (!ConfigManager.Config.MapViewer.EnableZSlicing)
return true;

var config = ConfigManager.Config.MapViewer;
float levelBottom = (config.CurrentZLevel - 1) * config.LevelHeight;
float levelTop = levelBottom + config.LevelHeight;

return position.Z >= levelBottom && position.Z < levelTop;
}

public void DrawWithZSlicing()
{
Effect.Parameters["xWorld"].SetValue(Matrix.Identity);
Effect.Parameters["xLightDirection"].SetValue(-Vector3.UnitZ);
Effect.Parameters["xAmbient"].SetValue(0.5f);

Effect_Clamp.Parameters["xWorld"].SetValue(Matrix.Identity);
Effect_Clamp.Parameters["xLightDirection"].SetValue(-Vector3.UnitZ);
Effect_Clamp.Parameters["xAmbient"].SetValue(0.5f);

PerfTimer.Start(ProfilerSection.Draw);

if (drawTerrain)
{
SetRasterizerState();
TerrainBatch.DrawWithZFiltering(IsInCurrentZLevel);
}

if (drawEnvCells)
DrawBufferWithZSlicing(RB_EnvCell, true);

if (drawStaticObjs)
DrawBufferWithZSlicing(RB_StaticObjs);

if (drawBuildings)
DrawBufferWithZSlicing(RB_Buildings);

if (drawScenery)
DrawBufferWithZSlicing(RB_Scenery);

if (drawInstances && Server.InstancesLoaded)
DrawBufferWithZSlicing(RB_Instances);

if (drawEncounters && Server.EncountersLoaded)
DrawBufferWithZSlicing(RB_Encounters);

DrawBufferWithZSlicing(RB_Animated);

if (Picker.HitVertices != null)
Picker.DrawHitPoly();

PerfTimer.Stop(ProfilerSection.Draw);
}

private void DrawBufferWithZSlicing(Dictionary<uint, GfxObjInstance_Shared> batches)
{
SetRasterizerState(CullMode.None);

foreach (var batch in batches.Values)
batch.DrawFiltered(IsInCurrentZLevel);
}

private void DrawBufferWithZSlicing(Dictionary<GfxObjTexturePalette, GfxObjInstance_Shared> batches)
{
SetRasterizerState(CullMode.None);

foreach (var batch in batches.Values)
batch.DrawFiltered(IsInCurrentZLevel);
}

private void DrawBufferWithZSlicing(Dictionary<TextureSet, InstanceBatch> batches, bool culling = false)
{
var cullMode = WorldViewer.Instance.DungeonMode || culling ?
CullMode.CullClockwiseFace : CullMode.None;

SetRasterizerState(cullMode);

Effect.CurrentTechnique = Effect.Techniques["TexturedInstanceEnv"];
Effect_Clamp.CurrentTechnique = Effect_Clamp.Techniques["TexturedInstanceEnv"];

foreach (var batch in batches.Values)
{
batch.DrawFiltered(IsInCurrentZLevel);
}
}


public void ClearBuffer()
{
Expand Down
26 changes: 26 additions & 0 deletions ACViewer/Render/Camera.cs
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,31 @@ public void Update(GameTime gameTime)
Position -= Vector3.Cross(Up, Dir) * Speed;
if (keyboardState.IsKeyDown(Keys.Space))
Position += Up * Speed;
// Shift key control for downward movement
if (keyboardState.IsKeyDown(Keys.LeftShift) || keyboardState.IsKeyDown(Keys.RightShift))
Position -= Up * Speed;

// Z-level controls
if (keyboardState.IsKeyDown(Keys.F3) && LastKeyboardState != null && !LastKeyboardState.IsKeyDown(Keys.F3))
{
ConfigManager.Config.MapViewer.EnableZSlicing = !ConfigManager.Config.MapViewer.EnableZSlicing;
ConfigManager.Config.MapViewer.CurrentZLevel = 1;
}

// Z-level adjustment
if (ConfigManager.Config.MapViewer.EnableZSlicing)
{
if ((keyboardState.IsKeyDown(Keys.LeftAlt) || keyboardState.IsKeyDown(Keys.RightAlt)))
{
var config = ConfigManager.Config.MapViewer;
if (keyboardState.IsKeyDown(Keys.OemPlus) && !LastKeyboardState.IsKeyDown(Keys.OemPlus))
config.CurrentZLevel = Math.Min(config.CurrentZLevel + 1, 20);
if (keyboardState.IsKeyDown(Keys.OemMinus) && !LastKeyboardState.IsKeyDown(Keys.OemMinus))
config.CurrentZLevel--;
}
}

LastKeyboardState = keyboardState;

// camera speed control
if (mouseState.ScrollWheelValue != PrevMouseState.ScrollWheelValue)
Expand Down Expand Up @@ -368,6 +393,7 @@ public void Update(GameTime gameTime)
//Console.WriteLine("Camera dir: " + GameView.Instance.Render.Camera.Dir);
}

private KeyboardState LastKeyboardState;
public int centerX => GameView.GraphicsDevice.Viewport.Width / 2;
public int centerY => GameView.GraphicsDevice.Viewport.Height / 2;

Expand Down
55 changes: 49 additions & 6 deletions ACViewer/Render/GfxObjInstance_Shared.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using System.Collections.Generic;

using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

Expand All @@ -25,9 +26,8 @@ public class GfxObjInstance_Shared
public Dictionary<TextureFormatChain, GfxObjInstance_TextureFormat> BaseFormats_Alpha { get; set; }

public List<VertexPositionNormalTextures> Vertices { get; set; }

public List<VertexInstance> Instances { get; set; }

public VertexInstance[] Instances_ { get; set; }

public VertexBuffer Shared_VB { get; set; }
Expand All @@ -39,9 +39,7 @@ public class GfxObjInstance_Shared
public GfxObjInstance_Shared(GfxObj gfxObj, Dictionary<TextureFormat, TextureAtlasChain> textureAtlasChains, Dictionary<uint, uint> textureChanges = null, PaletteChanges paletteChanges = null)
{
GfxObj = gfxObj;

BuildStatic(gfxObj, textureAtlasChains, textureChanges, paletteChanges);

Instances = new List<VertexInstance>();
}

Expand Down Expand Up @@ -185,6 +183,51 @@ public void Draw()
foreach (var baseFormat in BaseFormats_Alpha.Values)
baseFormat.Draw(Instances.Count);
}

public void DrawFiltered(Func<Vector3, bool> filter)
{
if (Bindings == null) return;

if (isDirty)
{
Instances_VB.SetData(Instances_);
isDirty = false;
}

// Store original instances
var originalInstances = Instances_.ToArray();

// Filter instances
var filteredInstances = Instances.Where(instance => filter(instance.Position)).ToArray();

if (filteredInstances.Length > 0)
{
// Update vertex buffer with filtered instances
Instances_ = filteredInstances;
Instances_VB.SetData(filteredInstances);

GraphicsDevice.SetVertexBuffers(Bindings);

Effect.CurrentTechnique = Effect.Techniques["TexturedInstance"];
Effect_Clamp.CurrentTechnique = Effect_Clamp.Techniques["TexturedInstance"];

foreach (var baseFormat in BaseFormats_Solid.Values)
baseFormat.Draw(filteredInstances.Length);

if (Buffer.drawAlpha)
{
Effect.CurrentTechnique = Effect.Techniques["TexturedInstanceAlpha"];
Effect_Clamp.CurrentTechnique = Effect_Clamp.Techniques["TexturedInstanceAlpha"];
}

foreach (var baseFormat in BaseFormats_Alpha.Values)
baseFormat.Draw(filteredInstances.Length);
}

// Restore original instances
Instances_ = originalInstances;
Instances_VB.SetData(originalInstances);
}

public void Dispose()
{
Expand Down
29 changes: 26 additions & 3 deletions ACViewer/Render/InstanceBatch.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
using System.Collections.Generic;

using System;
using System.Collections.Generic;
using System.Linq;
using ACE.Entity.Enum;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;

namespace ACViewer.Render
Expand All @@ -17,6 +18,28 @@ public class InstanceBatch
public VertexBuffer InstanceBuffer { get; set; }

public R_Environment R_Environment { get; set; }

public void DrawFiltered(Func<Vector3, bool> filter)
{
// Store original instances
var originalInstances = new List<VertexInstanceEnv>(Instances_Env);

// Filter instances based on Z position
Instances_Env = Instances_Env.Where(instance => filter(instance.Position)).ToList();

if (Instances_Env.Count > 0)
{
// Rebuild instance buffer with filtered instances
BuildInstanceBuffer();
BuildBindings();
Draw();
}

// Restore original instances
Instances_Env = originalInstances;
BuildInstanceBuffer();
BuildBindings();
}

public InstanceBatch(R_EnvCell envCell)
{
Expand Down
34 changes: 27 additions & 7 deletions ACViewer/Render/Render.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,9 @@ public class Render

// multiple SamplerStates in the same .fx file apparently don't work
public static Effect Effect_Clamp { get; set; }

// Add to existing properties
private MapViewerOptions Config => ConfigManager.Config.MapViewer;

public Camera Camera
{
Expand Down Expand Up @@ -67,21 +70,23 @@ public void SetRasterizerState(bool wireframe = true)

GraphicsDevice.RasterizerState = rs;
}

public void Draw()
{
GraphicsDevice.Clear(ConfigManager.Config.BackgroundColors.WorldViewer);

SetRasterizerState(false);

Effect.Parameters["xView"].SetValue(Camera.ViewMatrix);
Effect_Clamp.Parameters["xView"].SetValue(Camera.ViewMatrix);

//landblock.Draw();
Buffer.Draw();
if (ConfigManager.Config.MapViewer.EnableZSlicing)
Buffer.DrawWithZSlicing();
else
Buffer.Draw();

//DrawEmitters_Naive();
DrawEmitters_Batch();
DrawHUD();
}

public bool ParticlesInitted { get; set; }
Expand Down Expand Up @@ -186,14 +191,29 @@ public void DestroyEmitters()

private static readonly Vector2 TextPos = new Vector2(10, 10);

// DrawHUD to show Z-slice information
public void DrawHUD()
{
var cameraPos = GameView.Camera.GetPosition();
var text = "";

if (ConfigManager.Config.MapViewer.EnableZSlicing)
{
var config = ConfigManager.Config.MapViewer;
string levelPrefix = config.CurrentZLevel < 0 ? "B" : ""; // Add "B" prefix for basement levels
int displayLevel = config.CurrentZLevel < 0 ? -config.CurrentZLevel : config.CurrentZLevel;

text += $"Current Z-Level: {levelPrefix}{displayLevel}\n"; // Shows B1, B2, etc. for basement levels
text += $"Height Range: {(config.CurrentZLevel - 1) * config.LevelHeight:F1}m - {config.CurrentZLevel * config.LevelHeight:F1}m\n";
}

var cameraPos = Camera.GetPosition();
if (cameraPos != null)
text += $"Location: {cameraPos}";

if (!string.IsNullOrEmpty(text))
{
SpriteBatch.Begin(SpriteSortMode.Deferred, null, SamplerState.LinearClamp);
SpriteBatch.DrawString(Font, $"Location: {cameraPos}", TextPos, Color.White);
SpriteBatch.DrawString(Font, text, TextPos, Color.White);
SpriteBatch.End();
}
}
Expand Down
Loading