mirror of
https://github.com/simtactics/mysimulation.git
synced 2025-07-15 18:46:42 -04:00
Added FSO.Files for use with the API server
Don't ask me. FreeSO is the prime example of dependency hell.
This commit is contained in:
parent
4b5e584eeb
commit
8fec258215
104 changed files with 14653 additions and 163 deletions
267
server/tso.files/RC/FSOF.cs
Executable file
267
server/tso.files/RC/FSOF.cs
Executable file
|
@ -0,0 +1,267 @@
|
|||
using FSO.Common;
|
||||
using FSO.Common.Utils;
|
||||
using FSO.Files.Utils;
|
||||
using Microsoft.Xna.Framework;
|
||||
using Microsoft.Xna.Framework.Graphics;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.IO.Compression;
|
||||
using System.Linq;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace FSO.Files.RC
|
||||
{
|
||||
public class FSOF
|
||||
{
|
||||
public int TexCompressionType; //RGBA8, DXT5
|
||||
|
||||
public int FloorWidth;
|
||||
public int FloorHeight;
|
||||
public int WallWidth;
|
||||
public int WallHeight;
|
||||
|
||||
public Color NightLightColor;
|
||||
|
||||
public byte[] FloorTextureData;
|
||||
public byte[] WallTextureData;
|
||||
|
||||
public byte[] NightFloorTextureData;
|
||||
public byte[] NightWallTextureData;
|
||||
|
||||
public int[] FloorIndices;
|
||||
public DGRP3DVert[] FloorVertices;
|
||||
|
||||
public int[] WallIndices;
|
||||
public DGRP3DVert[] WallVertices;
|
||||
|
||||
//loaded data
|
||||
public Texture2D FloorTexture;
|
||||
public Texture2D WallTexture;
|
||||
public Texture2D NightFloorTexture;
|
||||
public Texture2D NightWallTexture;
|
||||
|
||||
public VertexBuffer FloorVGPU;
|
||||
public IndexBuffer FloorIGPU;
|
||||
public int FloorPrims;
|
||||
|
||||
public VertexBuffer WallVGPU;
|
||||
public IndexBuffer WallIGPU;
|
||||
public int WallPrims;
|
||||
|
||||
public static int CURRENT_VERSION = 1;
|
||||
public int Version = CURRENT_VERSION;
|
||||
public bool Compressed = true;
|
||||
|
||||
public void Save(Stream stream)
|
||||
{
|
||||
var io = IoWriter.FromStream(stream, ByteOrder.LITTLE_ENDIAN);
|
||||
io.WriteCString("FSOf", 4);
|
||||
io.WriteInt32(CURRENT_VERSION);
|
||||
|
||||
io.WriteByte((byte)(Compressed ? 1 : 0));
|
||||
|
||||
MemoryStream target = null;
|
||||
GZipStream compressed = null;
|
||||
var cio = io;
|
||||
if (Compressed)
|
||||
{
|
||||
//target = new MemoryStream();
|
||||
compressed = new GZipStream(stream, CompressionMode.Compress);
|
||||
cio = IoWriter.FromStream(compressed, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
cio.WriteInt32(TexCompressionType);
|
||||
cio.WriteInt32(FloorWidth);
|
||||
cio.WriteInt32(FloorHeight);
|
||||
cio.WriteInt32(WallWidth);
|
||||
cio.WriteInt32(WallHeight);
|
||||
cio.WriteByte((byte)((NightFloorTextureData == null)?0:1)); //has night tex?
|
||||
|
||||
cio.WriteInt32(FloorTextureData.Length);
|
||||
cio.WriteBytes(FloorTextureData);
|
||||
cio.WriteInt32(WallTextureData.Length);
|
||||
cio.WriteBytes(WallTextureData);
|
||||
|
||||
if (NightFloorTextureData != null)
|
||||
{
|
||||
cio.WriteInt32(NightFloorTextureData.Length);
|
||||
cio.WriteBytes(NightFloorTextureData);
|
||||
cio.WriteInt32(NightWallTextureData.Length);
|
||||
cio.WriteBytes(NightWallTextureData);
|
||||
cio.WriteUInt32(NightLightColor.PackedValue);
|
||||
}
|
||||
|
||||
WriteVerts(FloorVertices, FloorIndices, cio);
|
||||
WriteVerts(WallVertices, WallIndices, cio);
|
||||
|
||||
if (Compressed)
|
||||
{
|
||||
compressed.Close();
|
||||
}
|
||||
}
|
||||
|
||||
public void Read(Stream stream)
|
||||
{
|
||||
using (var io = IoBuffer.FromStream(stream, ByteOrder.LITTLE_ENDIAN))
|
||||
{
|
||||
var fsof = io.ReadCString(4);
|
||||
if (fsof != "FSOf") throw new Exception("Invalid FSOf!");
|
||||
Version = io.ReadInt32();
|
||||
Compressed = io.ReadByte() > 0;
|
||||
|
||||
GZipStream compressed = null;
|
||||
var cio = io;
|
||||
if (Compressed)
|
||||
{
|
||||
compressed = new GZipStream(stream, CompressionMode.Decompress);
|
||||
cio = IoBuffer.FromStream(compressed, ByteOrder.LITTLE_ENDIAN);
|
||||
}
|
||||
|
||||
TexCompressionType = cio.ReadInt32();
|
||||
FloorWidth = cio.ReadInt32();
|
||||
FloorHeight = cio.ReadInt32();
|
||||
WallWidth = cio.ReadInt32();
|
||||
WallHeight = cio.ReadInt32();
|
||||
var hasNight = cio.ReadByte() > 0;
|
||||
|
||||
var floorTSize = cio.ReadInt32();
|
||||
FloorTextureData = cio.ReadBytes(floorTSize);
|
||||
var wallTSize = cio.ReadInt32();
|
||||
WallTextureData = cio.ReadBytes(wallTSize);
|
||||
|
||||
if (hasNight)
|
||||
{
|
||||
floorTSize = cio.ReadInt32();
|
||||
NightFloorTextureData = cio.ReadBytes(floorTSize);
|
||||
wallTSize = cio.ReadInt32();
|
||||
NightWallTextureData = cio.ReadBytes(wallTSize);
|
||||
NightLightColor = new Color(cio.ReadUInt32());
|
||||
}
|
||||
|
||||
var floor = ReadVerts(cio);
|
||||
FloorVertices = floor.Item1;
|
||||
FloorIndices = floor.Item2;
|
||||
var wall = ReadVerts(cio);
|
||||
WallVertices = wall.Item1;
|
||||
WallIndices = wall.Item2;
|
||||
}
|
||||
}
|
||||
|
||||
private SurfaceFormat GetTexFormat()
|
||||
{
|
||||
return (TexCompressionType == 1) ? SurfaceFormat.Dxt5 : SurfaceFormat.Color;
|
||||
}
|
||||
|
||||
public void LoadGPU(GraphicsDevice gd)
|
||||
{
|
||||
var format = GetTexFormat();
|
||||
if (format == SurfaceFormat.Dxt5 && !FSOEnvironment.TexCompressSupport)
|
||||
{
|
||||
//todo: software decode DXT5
|
||||
FloorTexture = new Texture2D(gd, FloorWidth, FloorHeight, false, SurfaceFormat.Color);
|
||||
FloorTexture.SetData(TextureUtils.DXT5Decompress(FloorTextureData, FloorWidth, FloorHeight));
|
||||
WallTexture = new Texture2D(gd, WallWidth, WallHeight, false, SurfaceFormat.Color);
|
||||
WallTexture.SetData(TextureUtils.DXT5Decompress(WallTextureData, WallWidth, WallHeight));
|
||||
if (NightFloorTextureData != null)
|
||||
{
|
||||
NightFloorTexture = new Texture2D(gd, FloorWidth, FloorHeight, false, SurfaceFormat.Color);
|
||||
NightFloorTexture.SetData(TextureUtils.DXT5Decompress(NightFloorTextureData, FloorWidth, FloorHeight));
|
||||
NightWallTexture = new Texture2D(gd, WallWidth, WallHeight, false, SurfaceFormat.Color);
|
||||
NightWallTexture.SetData(TextureUtils.DXT5Decompress(NightWallTextureData, WallWidth, WallHeight));
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FloorTexture = new Texture2D(gd, FloorWidth, FloorHeight, false, format);
|
||||
FloorTexture.SetData(FloorTextureData);
|
||||
WallTexture = new Texture2D(gd, WallWidth, WallHeight, false, format);
|
||||
WallTexture.SetData(WallTextureData);
|
||||
if (NightFloorTextureData != null)
|
||||
{
|
||||
NightFloorTexture = new Texture2D(gd, FloorWidth, FloorHeight, false, format);
|
||||
NightFloorTexture.SetData(NightFloorTextureData);
|
||||
NightWallTexture = new Texture2D(gd, WallWidth, WallHeight, false, format);
|
||||
NightWallTexture.SetData(NightWallTextureData);
|
||||
}
|
||||
}
|
||||
|
||||
if (FloorVertices.Length > 0)
|
||||
{
|
||||
FloorVGPU = new VertexBuffer(gd, typeof(DGRP3DVert), FloorVertices.Length, BufferUsage.None);
|
||||
FloorVGPU.SetData(FloorVertices);
|
||||
FloorIGPU = new IndexBuffer(gd, IndexElementSize.ThirtyTwoBits, FloorIndices.Length, BufferUsage.None);
|
||||
FloorIGPU.SetData(FloorIndices);
|
||||
FloorPrims = FloorIndices.Length / 3;
|
||||
}
|
||||
|
||||
if (WallVertices.Length > 0)
|
||||
{
|
||||
WallVGPU = new VertexBuffer(gd, typeof(DGRP3DVert), WallVertices.Length, BufferUsage.None);
|
||||
WallVGPU.SetData(WallVertices);
|
||||
WallIGPU = new IndexBuffer(gd, IndexElementSize.ThirtyTwoBits, WallIndices.Length, BufferUsage.None);
|
||||
WallIGPU.SetData(WallIndices);
|
||||
WallPrims = WallIndices.Length / 3;
|
||||
}
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
FloorTexture?.Dispose();
|
||||
WallTexture?.Dispose();
|
||||
NightFloorTexture?.Dispose();
|
||||
NightWallTexture?.Dispose();
|
||||
FloorVGPU?.Dispose();
|
||||
FloorIGPU?.Dispose();
|
||||
WallVGPU?.Dispose();
|
||||
WallIGPU?.Dispose();
|
||||
}
|
||||
|
||||
private Tuple<DGRP3DVert[], int[]> ReadVerts(IoBuffer io)
|
||||
{
|
||||
var vertCount = io.ReadInt32();
|
||||
var bytes = io.ReadBytes(vertCount * Marshal.SizeOf(typeof(DGRP3DVert)));
|
||||
var readVerts = new DGRP3DVert[vertCount];
|
||||
var pinnedHandle = GCHandle.Alloc(readVerts, GCHandleType.Pinned);
|
||||
Marshal.Copy(bytes, 0, pinnedHandle.AddrOfPinnedObject(), bytes.Length);
|
||||
pinnedHandle.Free();
|
||||
|
||||
var indCount = io.ReadInt32();
|
||||
var indices = ToTArray<int>(io.ReadBytes(indCount * 4));
|
||||
|
||||
return new Tuple<DGRP3DVert[], int[]>(readVerts, indices);
|
||||
}
|
||||
|
||||
private void WriteVerts(DGRP3DVert[] verts, int[] indices, IoWriter io)
|
||||
{
|
||||
io.WriteInt32(verts.Length);
|
||||
foreach (var vert in verts)
|
||||
{
|
||||
io.WriteFloat(vert.Position.X);
|
||||
io.WriteFloat(vert.Position.Y);
|
||||
io.WriteFloat(vert.Position.Z);
|
||||
io.WriteFloat(vert.TextureCoordinate.X);
|
||||
io.WriteFloat(vert.TextureCoordinate.Y);
|
||||
io.WriteFloat(vert.Normal.X);
|
||||
io.WriteFloat(vert.Normal.Y);
|
||||
io.WriteFloat(vert.Normal.Z);
|
||||
}
|
||||
|
||||
io.WriteInt32(indices.Length);
|
||||
io.WriteBytes(ToByteArray(indices.ToArray()));
|
||||
}
|
||||
|
||||
private static T[] ToTArray<T>(byte[] input)
|
||||
{
|
||||
var result = new T[input.Length / Marshal.SizeOf(typeof(T))];
|
||||
Buffer.BlockCopy(input, 0, result, 0, input.Length);
|
||||
return result;
|
||||
}
|
||||
|
||||
private static byte[] ToByteArray<T>(T[] input)
|
||||
{
|
||||
var result = new byte[input.Length * Marshal.SizeOf(typeof(T))];
|
||||
Buffer.BlockCopy(input, 0, result, 0, result.Length);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue