thief-mission-viewer/project/code/Mission.cs

161 lines
3.6 KiB
C#
Raw Normal View History

2024-07-21 21:13:31 +00:00
using Godot;
using KeepersCompound.LGS;
using KeepersCompound.LGS.Database;
using KeepersCompound.LGS.Database.Chunks;
using Microsoft.VisualBasic;
using System;
using System.Collections.Generic;
namespace KeepersCompound;
[Tool]
public partial class Mission : Node3D
{
[Export(PropertyHint.GlobalFile, "*.mis")]
public string FileName { get; set; }
[Export]
public bool Build = false;
[Export]
public bool Clear = false;
2024-07-21 21:13:31 +00:00
DbFile _file;
public override void _Ready()
{
var fileNameLineEdit = GetNode<LineEdit>("%FileNameLineEdit");
fileNameLineEdit.Text = FileName;
fileNameLineEdit.TextSubmitted += (string text) => FileName = text;
GetNode<Button>("%BuildButton").Pressed += () => RebuildMap();
GetNode<Button>("%ClearButton").Pressed += () => ClearMap();
2024-07-21 21:13:31 +00:00
}
public override void _Process(double delta)
{
if (Build)
{
RebuildMap();
Build = false;
}
if (Clear)
{
ClearMap();
Clear = false;
}
2024-07-21 21:13:31 +00:00
}
public override void _Input(InputEvent @event)
{
if (@event is InputEventKey keyEvent && keyEvent.Pressed)
{
if (keyEvent.Keycode == Key.R)
{
Build = true;
}
}
}
public void ClearMap()
2024-07-21 21:13:31 +00:00
{
foreach (var node in GetChildren())
{
node.QueueFree();
}
}
public void RebuildMap()
{
ClearMap();
2024-07-21 21:13:31 +00:00
_file = new(FileName);
var wr = (WorldRep)_file.Chunks["WREXT"];
foreach (var cell in wr.Cells)
{
BuildCellMesh(cell);
}
}
private void BuildCellMesh(WorldRep.Cell cell)
{
var numPolys = cell.PolyCount;
var numRenderPolys = cell.RenderPolyCount;
var numPortalPolys = cell.PortalPolyCount;
if (numRenderPolys == 0 || numPortalPolys >= numPolys)
{
return;
}
2024-07-21 21:13:31 +00:00
var vertices = new List<Vector3>();
var normals = new List<Vector3>();
2024-07-22 18:37:56 +00:00
var indices = new List<int>();
2024-07-22 19:34:12 +00:00
var cellIdxOffset = 0;
var maxPolyIdx = Math.Min(numRenderPolys, numPolys - numPortalPolys);
for (int i = 0; i < maxPolyIdx; i++)
2024-07-21 21:13:31 +00:00
{
var poly = cell.Polys[i];
var plane = cell.Planes[poly.PlaneId];
var normal = plane.Normal;
2024-07-22 19:34:12 +00:00
var gNormal = normal.ToGodotVec3(4.0f);
2024-07-21 21:13:31 +00:00
var numPolyVertices = poly.VertexCount;
2024-07-22 19:34:12 +00:00
var meshIdxOffset = vertices.Count;
2024-07-22 18:37:56 +00:00
for (var j = 0; j < numPolyVertices; j++)
{
2024-07-22 19:34:12 +00:00
var vertex = cell.Vertices[cell.Indices[cellIdxOffset + j]];
2024-07-22 18:37:56 +00:00
vertices.Add(vertex.ToGodotVec3(4.0f));
2024-07-22 19:34:12 +00:00
normals.Add(gNormal);
2024-07-22 18:37:56 +00:00
}
2024-07-22 19:34:12 +00:00
// Simple triangulation
2024-07-21 21:13:31 +00:00
for (int j = 1; j < numPolyVertices - 1; j++)
{
2024-07-22 19:34:12 +00:00
indices.Add(meshIdxOffset);
indices.Add(meshIdxOffset + j);
indices.Add(meshIdxOffset + j + 1);
2024-07-21 21:13:31 +00:00
}
2024-07-22 19:34:12 +00:00
cellIdxOffset += poly.VertexCount;
2024-07-21 21:13:31 +00:00
}
2024-07-22 18:52:40 +00:00
var cellNode = new Node3D();
2024-07-21 21:13:31 +00:00
var arrMesh = new ArrayMesh();
var arrays = new Godot.Collections.Array();
arrays.Resize((int)Mesh.ArrayType.Max);
arrays[(int)Mesh.ArrayType.Vertex] = vertices.ToArray();
arrays[(int)Mesh.ArrayType.Normal] = normals.ToArray();
2024-07-22 18:37:56 +00:00
arrays[(int)Mesh.ArrayType.Index] = indices.ToArray();
2024-07-21 21:13:31 +00:00
arrMesh.AddSurfaceFromArrays(Mesh.PrimitiveType.Triangles, arrays);
2024-07-22 19:34:12 +00:00
2024-07-21 21:13:31 +00:00
var meshInstance = new MeshInstance3D
{
Mesh = arrMesh,
CastShadow = GeometryInstance3D.ShadowCastingSetting.On
};
2024-07-22 18:52:40 +00:00
cellNode.AddChild(meshInstance);
var occluder = new ArrayOccluder3D();
occluder.SetArrays(vertices.ToArray(), indices.ToArray());
2024-07-22 19:34:12 +00:00
var occluderInstance = new OccluderInstance3D
{
Occluder = occluder,
BakeSimplificationDistance = 0.0f
};
2024-07-22 18:52:40 +00:00
cellNode.AddChild(occluderInstance);
var r = new Random();
if (r.NextSingle() > 0.9 && cell.SphereRadius > 5.0)
{
var light = new OmniLight3D
{
Position = cell.SphereCenter.ToGodotVec3(4.0f),
OmniRange = cell.SphereRadius * (r.NextSingle() + 1.0f) * 0.5f,
};
2024-07-22 18:52:40 +00:00
cellNode.AddChild(light);
}
2024-07-22 18:52:40 +00:00
AddChild(cellNode);
2024-07-21 21:13:31 +00:00
}
}