Add support for EF2 terrainDef structures.

This commit is contained in:
Will
2016-02-20 03:27:32 -07:00
parent bdde60d78c
commit f9bd13ae35
2 changed files with 140 additions and 1 deletions

View File

@@ -13,6 +13,7 @@ namespace LibBSP {
public List<MAPBrushSide> sides = new List<MAPBrushSide>(6);
public MAPPatch patch;
public MAPTerrain terrain;
public bool isDetail = false;
public bool isWater = false;
@@ -30,6 +31,7 @@ namespace LibBSP {
int braceCount = 0;
bool brushDef3 = false;
bool inPatch = false;
bool inTerrain = false;
List<string> child = new List<string>();
foreach (string line in lines) {
if (line[0] == '{') {
@@ -45,7 +47,7 @@ namespace LibBSP {
if (line.Length >= "side".Length && line.Substring(0, "side".Length) == "side") {
continue;
}
// id Tech does this kinda thing
// id Tech does this kinda thing
else if (line.Length >= "patch".Length && line.Substring(0, "patch".Length) == "patch") {
inPatch = true;
// Gonna need this line too. We can switch on the type of patch definition, make things much easier.
@@ -57,6 +59,16 @@ namespace LibBSP {
patch = new MAPPatch(child.ToArray());
child = new List<string>();
continue;
} else if (line.Length >= "terrainDef".Length && line.Substring(0, "terrainDef".Length) == "terrainDef") {
inTerrain = true;
child.Add(line);
continue;
} else if (inTerrain) {
child.Add(line);
inTerrain = false;
terrain = new MAPTerrain(child.ToArray());
child = new List<string>();
continue;
} else if (line.Length >= "brushDef3".Length && line.Substring(0, "brushDef3".Length) == "brushDef3") {
brushDef3 = true;
continue;

View File

@@ -0,0 +1,127 @@
#if (UNITY_2_6 || UNITY_2_6_1 || UNITY_3_0 || UNITY_3_0_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 || UNITY_4_0 || UNITY_4_0_1 || UNITY_4_2 || UNITY_4_3 || UNITY_4_5 || UNITY_4_6 || UNITY_5)
#define UNITY
#endif
using System;
using System.Collections.Generic;
using System.Globalization;
#if UNITY
using UnityEngine;
#else
using System.Drawing;
#endif
namespace LibBSP {
#if !UNITY
using Vector4 = Vector4d;
using Vector3 = Vector3d;
#endif
/// <summary>
/// Class containing all data necessary to render a Bezier patch.
/// </summary>
[Serializable] public class MAPTerrain {
private static IFormatProvider _format = CultureInfo.CreateSpecificCulture("en-US");
public int side;
public string texture;
public double textureShiftS;
public double textureShiftT;
public float texRot;
public double texScaleX;
public double texScaleY;
public int flags;
public double sideLength;
public Vector3 start;
public Vector4 IF;
public Vector4 LF;
public float[][] heightMap;
public float[][] alphaMap;
/// <summary>
/// Creates a new empty <see cref="MAPTerrain"/> object. Internal data will have to be set manually.
/// </summary>
public MAPTerrain() { }
/// <summary>
/// Constructs a new <see cref="MAPTerrain"/> object using the supplied string array as data.
/// </summary>
/// <param name="lines">Data to parse.</param>
public MAPTerrain(string[] lines) {
texture = lines[2];
switch (lines[0]) {
case "terrainDef": {
for (int i = 2; i < lines.Length; ++i) {
string[] line = lines[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
switch (line[0]) {
case "TEX(": {
texture = line[1];
textureShiftS = Single.Parse(line[2], _format);
textureShiftT = Single.Parse(line[3], _format);
texRot = Single.Parse(line[4], _format);
texScaleX = Double.Parse(line[5], _format);
texScaleY = Double.Parse(line[6], _format);
flags = Int32.Parse(line[8]);
break;
}
case "TD(": {
sideLength = Int32.Parse(line[1], _format);
start = new Vector3(Single.Parse(line[2], _format), Single.Parse(line[3], _format), Single.Parse(line[4], _format));
break;
}
case "IF(": {
IF = new Vector4(Single.Parse(line[1], _format), Single.Parse(line[2], _format), Single.Parse(line[3], _format), Single.Parse(line[4], _format));
break;
}
case "LF(": {
LF = new Vector4(Single.Parse(line[1], _format), Single.Parse(line[2], _format), Single.Parse(line[3], _format), Single.Parse(line[4], _format));
break;
}
case "V(": {
++i;
line = lines[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (side == 0) {
side = line.Length;
}
heightMap = new float[side][];
for (int j = 0; j < side; ++j) {
heightMap[j] = new float[side];
for (int k = 0; k < side; ++k) {
heightMap[j][k] = Single.Parse(line[k], _format);
}
++i;
line = lines[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
}
break;
}
case "A(": {
++i;
line = lines[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
if (side == 0) {
side = line.Length;
}
alphaMap = new float[side][];
for (int j = 0; j < side; ++j) {
alphaMap[j] = new float[side];
for (int k = 0; k < side; ++k) {
alphaMap[j][k] = Single.Parse(line[k], _format);
}
++i;
line = lines[i].Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);
}
break;
}
}
}
break;
}
default: {
throw new ArgumentException(string.Format("Unknown terrain type {0}!", lines[0]));
}
}
}
}
}