working, fixing texture mapping
This commit is contained in:
@@ -3,29 +3,39 @@
|
||||
// entity 0
|
||||
{
|
||||
"classname" "worldspawn"
|
||||
"_tb_textures" "textures/common;textures/dev"
|
||||
// brush 0
|
||||
{
|
||||
( -64 -64 -16 ) ( -64 -63 -16 ) ( -64 -64 -15 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( -64 -64 -16 ) ( -64 -64 -15 ) ( -63 -64 -16 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( -64 -64 -16 ) ( -63 -64 -16 ) ( -64 -63 -16 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 64 64 16 ) ( 64 65 16 ) ( 65 64 16 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 64 64 16 ) ( 65 64 16 ) ( 64 64 17 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 64 64 16 ) ( 64 64 17 ) ( 64 65 16 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 576 -32 ) ( 0 577 -32 ) ( 0 576 -31 ) common/slick 0 0 0 4 4 0 0 0
|
||||
( 224 0 -32 ) ( 224 0 -31 ) ( 225 0 -32 ) common/slick 0 0 0 4 4 0 0 0
|
||||
( 224 576 -512 ) ( 225 576 -512 ) ( 224 577 -512 ) common/slick 0 0 0 4 4 0 0 0
|
||||
( 256 608 0 ) ( 256 609 0 ) ( 257 608 0 ) common/slick 0 0 0 4 4 0 0 0
|
||||
( 256 512 -16 ) ( 257 512 -16 ) ( 256 512 -15 ) common/slick 0 0 0 4 4 0 0 0
|
||||
( 512 608 -16 ) ( 512 608 -15 ) ( 512 609 -16 ) common/slick 0 0 0 4 4 0 0 0
|
||||
}
|
||||
// brush 1
|
||||
{
|
||||
( -32 -32 48 ) ( -32 32 48 ) ( 0 0 80 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 0 80 ) ( 32 -32 48 ) ( -32 -32 48 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 32 32 48 ) ( -32 32 48 ) ( -32 -32 48 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 0 80 ) ( -32 32 48 ) ( 32 32 48 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 0 80 ) ( 32 32 48 ) ( 32 -32 48 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( -64 -64 16 ) ( -64 -63 16 ) ( -64 -64 17 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( -64 -64 16 ) ( -64 -64 17 ) ( -63 -64 16 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( -64 -64 16 ) ( -63 -64 16 ) ( -64 -63 16 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 64 64 48 ) ( 64 65 48 ) ( 65 64 48 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 64 64 48 ) ( 65 64 48 ) ( 64 64 49 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 64 64 48 ) ( 64 64 49 ) ( 64 65 48 ) common/slick 0 0 0 1 1 0 0 0
|
||||
}
|
||||
// brush 2
|
||||
{
|
||||
( 0 0 80 ) ( -32 32 112 ) ( -32 -32 112 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 0 80 ) ( -32 -32 112 ) ( 32 -32 112 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( -32 32 112 ) ( 32 32 112 ) ( 32 -32 112 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 0 80 ) ( 32 32 112 ) ( -32 32 112 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 32 -32 112 ) ( 32 32 112 ) ( 0 0 80 ) __TB_empty 0 0 0 0.0625 0.0625 0 0 0
|
||||
( -32 -32 48 ) ( -32 32 48 ) ( 0 0 80 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 0 0 80 ) ( 32 -32 48 ) ( -32 -32 48 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 32 32 48 ) ( -32 32 48 ) ( -32 -32 48 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 0 0 80 ) ( -32 32 48 ) ( 32 32 48 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 0 0 80 ) ( 32 32 48 ) ( 32 -32 48 ) common/slick 0 0 0 1 1 0 0 0
|
||||
}
|
||||
// brush 3
|
||||
{
|
||||
( 0 0 80 ) ( -32 32 112 ) ( -32 -32 112 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 0 0 80 ) ( -32 -32 112 ) ( 32 -32 112 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( -32 32 112 ) ( 32 32 112 ) ( 32 -32 112 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 0 0 80 ) ( 32 32 112 ) ( -32 32 112 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 32 -32 112 ) ( 32 32 112 ) ( 0 0 80 ) common/slick 0 0 0 1 1 0 0 0
|
||||
}
|
||||
}
|
||||
|
||||
33
Assets/Maps/problematic.map
Normal file
33
Assets/Maps/problematic.map
Normal file
@@ -0,0 +1,33 @@
|
||||
// Game: Goake
|
||||
// Format: Quake3
|
||||
// entity 0
|
||||
{
|
||||
"classname" "worldspawn"
|
||||
// brush 0
|
||||
{
|
||||
( 467.19999999999999 0 241.59999999999999 ) ( 442.21699999999998 249.83000000000001 291.56599999999997 ) ( 355.47199999999998 -55.863999999999997 465.05500000000001 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 160 8 ) ( 0 160 -248 ) ( -256 160 8 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 342 160 492 ) ( 426 160 492 ) ( 426 224 492 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 0 504 ) ( 256 0 504 ) ( 0 -256 504 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 224 8 ) ( 0 224 264 ) ( -256 224 8 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 147.19999999999999 0 -65.599999999999994 ) ( 122.217 -249.83000000000001 -115.566 ) ( 258.928 -55.863999999999997 157.85499999999999 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
}
|
||||
// brush 1
|
||||
{
|
||||
( 460 160 458 ) ( 460 160 360 ) ( 460 224 360 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( -88 0 184 ) ( 111.864 124.91500000000001 283.93200000000002 ) ( 23.728000000000002 -223.45500000000001 239.864 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 160 8 ) ( 0 160 -248 ) ( -256 160 8 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 0 360 ) ( -256 0 360 ) ( 0 -256 360 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 224 8 ) ( 0 224 264 ) ( -256 224 8 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 472 0 8 ) ( 472 -256 8 ) ( 472 0 264 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
}
|
||||
// brush 2
|
||||
{
|
||||
( 296 160 464 ) ( 296 224 464 ) ( 336 224 504 ) dev/dev_128_gray 0 0 -0 0.0625 0.0625 0 0 0
|
||||
( 241.59999999999999 0 491.19999999999999 ) ( 41.735999999999997 124.91500000000001 591.13199999999995 ) ( 129.87200000000001 -223.45500000000001 547.06399999999996 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 160 8 ) ( 0 160 -248 ) ( -256 160 8 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 0 224 8 ) ( 0 224 264 ) ( -256 224 8 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 308 160 458 ) ( 342 160 492 ) ( 342 224 492 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 467.19999999999999 0 241.59999999999999 ) ( 492.18299999999999 -249.83000000000001 191.63399999999999 ) ( 355.47199999999998 -55.863999999999997 465.05500000000001 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"ID": "3c7bc3854d42f9b1b0fea9ba0d7fa8e9",
|
||||
"TypeName": "FlaxEditor.Content.Settings.GameSettings",
|
||||
"EngineBuild": 6221,
|
||||
"EngineBuild": 6222,
|
||||
"Data": {
|
||||
"ProductName": "Goake",
|
||||
"CompanyName": "GoaLitiuM",
|
||||
"FirstScene": "0733cc9b40d3d05366be64bbd9b59e21",
|
||||
"FirstScene": "194e05f445ece24ec5448d886e1334df",
|
||||
"NoSplashScreen": true,
|
||||
"Time": "a55dc3c04da4ea3744b7f1994565beac",
|
||||
"Audio": "492a33824049ba25a8bdcdb148179e67",
|
||||
|
||||
Binary file not shown.
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ID": "0733cc9b40d3d05366be64bbd9b59e21",
|
||||
"TypeName": "FlaxEngine.SceneAsset",
|
||||
"EngineBuild": 6219,
|
||||
"EngineBuild": 6223,
|
||||
"Data": [
|
||||
{
|
||||
"ID": "0733cc9b40d3d05366be64bbd9b59e21",
|
||||
@@ -168,13 +168,13 @@
|
||||
"Transform": {
|
||||
"Translation": {
|
||||
"X": 0.0,
|
||||
"Y": 734.0,
|
||||
"Y": 735.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
},
|
||||
"Control": "FlaxEngine.GUI.Label",
|
||||
"Data": {
|
||||
"Text": "uFPS: 504\nrFPS: 493\npFPS: 30\nCon: NaNms\nDirectX11\nGC memory: 9.256392MB",
|
||||
"Text": "eFPS: 120\nuFPS: -2147483648\nrFPS: -2147483648\npFPS: -2147483648\nCon: 0ms\nDirectX11\nGC memory: 11.2093MB",
|
||||
"TextColor": {
|
||||
"R": 1.0,
|
||||
"G": 1.0,
|
||||
@@ -220,9 +220,9 @@
|
||||
},
|
||||
"Offsets": {
|
||||
"Left": 0.0,
|
||||
"Right": 143.0,
|
||||
"Right": 136.0,
|
||||
"Top": -80.0,
|
||||
"Bottom": 96.0
|
||||
"Bottom": 112.0
|
||||
},
|
||||
"Scale": {
|
||||
"X": 1.0,
|
||||
@@ -260,8 +260,8 @@
|
||||
"Name": "ContainerControl 0",
|
||||
"Transform": {
|
||||
"Translation": {
|
||||
"X": 45676.0,
|
||||
"Y": 1.0,
|
||||
"X": 44855.0,
|
||||
"Y": 1.5,
|
||||
"Z": 0.0
|
||||
}
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"ID": "194e05f445ece24ec5448d886e1334df",
|
||||
"TypeName": "FlaxEngine.SceneAsset",
|
||||
"EngineBuild": 6221,
|
||||
"EngineBuild": 6223,
|
||||
"Data": [
|
||||
{
|
||||
"ID": "194e05f445ece24ec5448d886e1334df",
|
||||
@@ -33,7 +33,7 @@
|
||||
"Transform": {
|
||||
"Translation": {
|
||||
"X": -32.320621490478519,
|
||||
"Y": 7.693744659423828,
|
||||
"Y": 203.23764038085938,
|
||||
"Z": -187.24435424804688
|
||||
}
|
||||
},
|
||||
@@ -51,6 +51,13 @@
|
||||
"ParentID": "19bf0c4f41c16717c90e05a0bdc62e44",
|
||||
"V": {}
|
||||
},
|
||||
{
|
||||
"ID": "d9d420ce476865e395a966913b5b32bd",
|
||||
"TypeName": "Game.PlayerMovement",
|
||||
"ParentID": "19bf0c4f41c16717c90e05a0bdc62e44",
|
||||
"V": {},
|
||||
"Enabled": false
|
||||
},
|
||||
{
|
||||
"ID": "39992ccc4fac12dab97aa4bfb52f0041",
|
||||
"TypeName": "FlaxEngine.EmptyActor",
|
||||
@@ -169,13 +176,13 @@
|
||||
"Transform": {
|
||||
"Translation": {
|
||||
"X": 0.0,
|
||||
"Y": 506.0,
|
||||
"Y": 484.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
},
|
||||
"Control": "FlaxEngine.GUI.Label",
|
||||
"Data": {
|
||||
"Text": "eFPS: 120\nuFPS: 120\nrFPS: 120\npFPS: 30\nCon: NaNms\nDirectX11\nGC memory: 8.026576MB",
|
||||
"Text": "eFPS: 121\nuFPS: -2147483648\nrFPS: -2147483648\npFPS: -2147483648\nCon: 0ms\nDirectX11\nGC memory: 9.544752MB",
|
||||
"TextColor": {
|
||||
"R": 1.0,
|
||||
"G": 1.0,
|
||||
@@ -261,8 +268,8 @@
|
||||
"Name": "ContainerControl 0",
|
||||
"Transform": {
|
||||
"Translation": {
|
||||
"X": 45279.0,
|
||||
"Y": -113.0,
|
||||
"X": 44635.0,
|
||||
"Y": -124.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
},
|
||||
@@ -1,13 +1,17 @@
|
||||
{
|
||||
"ID": "af2e52554f7faed7b4937181dd22d166",
|
||||
"TypeName": "FlaxEditor.Content.Settings.BuildSettings",
|
||||
"EngineBuild": 6216,
|
||||
"EngineBuild": 6222,
|
||||
"Data": {
|
||||
"MaxAssetsPerPackage": 4096,
|
||||
"MaxPackageSizeMB": 1024,
|
||||
"ContentKey": 0,
|
||||
"ForDistribution": false,
|
||||
"SkipPackaging": false,
|
||||
"AdditionalAssets": [
|
||||
"54a1ff4a42af9f018234f7b39b1366b3",
|
||||
"1ef4565844a4b36cdfda54b51f338c77"
|
||||
],
|
||||
"ShadersNoOptimize": false,
|
||||
"ShadersGenerateDebugData": false,
|
||||
"Presets": [
|
||||
|
||||
BIN
Content/Textures/dev/slick.flax
Normal file
BIN
Content/Textures/dev/slick.flax
Normal file
Binary file not shown.
@@ -264,34 +264,54 @@ namespace Cabrito
|
||||
// Echoes text to Console
|
||||
public void Print(string text)
|
||||
{
|
||||
ConsoleLine line = new ConsoleLine(text);
|
||||
consoleLines.Add(line);
|
||||
foreach (var line in text.Split(new []{'\n'}))
|
||||
{
|
||||
ConsoleLine lineEntry = new ConsoleLine(line);
|
||||
consoleLines.Add(lineEntry);
|
||||
OnPrint?.Invoke(text);
|
||||
}
|
||||
}
|
||||
|
||||
// Echoes warning text to Console
|
||||
public void PrintWarning(string text)
|
||||
{
|
||||
ConsoleLine line = new ConsoleLine(text);
|
||||
consoleLines.Add(line);
|
||||
foreach (var line in text.Split(new[] { '\n' }))
|
||||
{
|
||||
ConsoleLine lineEntry = new ConsoleLine(line);
|
||||
consoleLines.Add(lineEntry);
|
||||
OnPrint?.Invoke(text);
|
||||
}
|
||||
}
|
||||
|
||||
// Echoes error text to Console
|
||||
public void PrintError(string text)
|
||||
{
|
||||
ConsoleLine line = new ConsoleLine(text);
|
||||
consoleLines.Add(line);
|
||||
foreach (var line in text.Split(new[] { '\n' }))
|
||||
{
|
||||
ConsoleLine lineEntry = new ConsoleLine(line);
|
||||
consoleLines.Add(lineEntry);
|
||||
OnPrint?.Invoke(text);
|
||||
}
|
||||
|
||||
if (Debugger.IsAttached)
|
||||
{
|
||||
Debugger.Break();
|
||||
text = text;
|
||||
}
|
||||
else
|
||||
throw new Exception(text);
|
||||
}
|
||||
|
||||
// Echoes developer/debug text to Console
|
||||
public void PrintDebug(string text)
|
||||
{
|
||||
ConsoleLine line = new ConsoleLine(text);
|
||||
consoleLines.Add(line);
|
||||
foreach (var line in text.Split(new[] { '\n' }))
|
||||
{
|
||||
ConsoleLine lineEntry = new ConsoleLine(line);
|
||||
consoleLines.Add(lineEntry);
|
||||
OnPrint?.Invoke(text);
|
||||
}
|
||||
}
|
||||
|
||||
// Opens the Console
|
||||
public void Open()
|
||||
|
||||
@@ -9,13 +9,12 @@ namespace Game
|
||||
[Limit(0, 9000), Tooltip("Camera speed")]
|
||||
public float MoveSpeed { get; set; } = 400;
|
||||
|
||||
private float _pitch;
|
||||
private float _yaw;
|
||||
private float viewPitch;
|
||||
private float viewYaw;
|
||||
private float viewRoll;
|
||||
|
||||
private float xAxis;
|
||||
private float yAxis;
|
||||
private float inputH;
|
||||
private float inputV;
|
||||
|
||||
private InputEvent onExit = new InputEvent("Exit");
|
||||
|
||||
@@ -40,33 +39,45 @@ namespace Game
|
||||
public override void OnStart()
|
||||
{
|
||||
var initialEulerAngles = Actor.Orientation.EulerAngles;
|
||||
_pitch = initialEulerAngles.X;
|
||||
_yaw = initialEulerAngles.Y;
|
||||
viewPitch = initialEulerAngles.X;
|
||||
viewYaw = initialEulerAngles.Y;
|
||||
viewRoll = initialEulerAngles.Z;
|
||||
}
|
||||
|
||||
public override void OnUpdate()
|
||||
{
|
||||
var camTrans = Actor.Transform;
|
||||
var rootActor = Actor.GetChild(0);
|
||||
var camera = rootActor.GetChild<Camera>();
|
||||
|
||||
xAxis = InputManager.GetAxis("Mouse X");
|
||||
yAxis = InputManager.GetAxis("Mouse Y");
|
||||
|
||||
float xAxis = InputManager.GetAxisRaw("Mouse X");
|
||||
float yAxis = InputManager.GetAxisRaw("Mouse Y");
|
||||
if (xAxis != 0.0f || yAxis != 0.0f)
|
||||
{
|
||||
_pitch += yAxis;
|
||||
_yaw += xAxis;
|
||||
|
||||
camTrans.Orientation = Quaternion.Euler(_pitch, _yaw, 0);
|
||||
|
||||
|
||||
viewPitch += yAxis;
|
||||
viewYaw += xAxis;
|
||||
|
||||
viewPitch = Mathf.Clamp(viewPitch, -90.0f, 90.0f);
|
||||
|
||||
|
||||
// root orientation must be set first
|
||||
rootActor.Orientation = Quaternion.Euler(0, viewYaw, 0);
|
||||
camera.Orientation = Quaternion.Euler(viewPitch, viewYaw, viewRoll);
|
||||
}
|
||||
|
||||
inputH = InputManager.GetAxis("Horizontal");
|
||||
inputV = InputManager.GetAxis("Vertical");
|
||||
|
||||
|
||||
float inputH = InputManager.GetAxis("Horizontal");
|
||||
float inputV = InputManager.GetAxis("Vertical");
|
||||
var move = new Vector3(inputH, 0.0f, inputV);
|
||||
|
||||
if (!move.IsZero)
|
||||
{
|
||||
move.Normalize();
|
||||
move = camTrans.TransformDirection(move) * MoveSpeed;
|
||||
move = camera.Transform.TransformDirection(move) * MoveSpeed;
|
||||
|
||||
{
|
||||
Vector3 delta = move * Time.UnscaledDeltaTime;
|
||||
|
||||
@@ -275,6 +275,13 @@ namespace Game
|
||||
}
|
||||
|
||||
Vector3 vector = ParseVector3(data, ref index);
|
||||
// rounding
|
||||
/*float temp = vector.Z;
|
||||
vector.Z = vector.Y;
|
||||
vector.Y = temp;*/
|
||||
/*vector.X = (float)Math.Round(vector.X, 1);
|
||||
vector.Y = (float)Math.Round(vector.Y, 1);
|
||||
vector.Z = (float)Math.Round(vector.Z, 1);*/
|
||||
|
||||
while (index < data.Length)
|
||||
{
|
||||
|
||||
@@ -168,25 +168,100 @@ namespace Game
|
||||
public List<Vector3> Simplify(Vector3[] input)
|
||||
{
|
||||
triangles = new List<Triangle>(input.Length / 3);
|
||||
vertices = new List<Vertex>(input.Length);
|
||||
vertices = new List<Vertex>();
|
||||
|
||||
// TODO: no overlapping vertices, vertices must be unique
|
||||
|
||||
|
||||
{
|
||||
int i = 0;
|
||||
foreach (var vec in input)
|
||||
|
||||
Dictionary<Vector3, int> verticeMap = new Dictionary<Vector3, int>();
|
||||
for (int i = 0; i < input.Length; i++)
|
||||
{
|
||||
if (!verticeMap.ContainsKey(input[i]))
|
||||
verticeMap[input[i]] = verticeMap.Count;
|
||||
}
|
||||
|
||||
for (int i = 0; i < input.Length; i += 3)
|
||||
{
|
||||
int i1 = i + 0;
|
||||
int i2 = i + 1;
|
||||
int i3 = i + 2;
|
||||
Vector3 v1 = input[i1];
|
||||
Vector3 v2 = input[i2];
|
||||
Vector3 v3 = input[i3];
|
||||
|
||||
if (verticeMap.ContainsKey(v1))
|
||||
i1 = verticeMap[v1];
|
||||
else
|
||||
verticeMap.Add(v1, i1);
|
||||
|
||||
if (verticeMap.ContainsKey(v2))
|
||||
i2 = verticeMap[v2];
|
||||
else
|
||||
verticeMap.Add(v2, i2);
|
||||
|
||||
if (verticeMap.ContainsKey(v3))
|
||||
i3 = verticeMap[v3];
|
||||
else
|
||||
verticeMap.Add(v3, i3);
|
||||
|
||||
triangles.Add(new Triangle()
|
||||
{
|
||||
v = new Int3(i1, i2, i3),
|
||||
});
|
||||
}
|
||||
|
||||
foreach (KeyValuePair<Vector3,int> kvp in verticeMap)
|
||||
{
|
||||
vertices.Add(new Vertex()
|
||||
{
|
||||
p = kvp.Key,
|
||||
q = new SymetricMatrix(),
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/*foreach (var vec in input)
|
||||
{
|
||||
vertices.Add(new Vertex()
|
||||
{
|
||||
p = vec,
|
||||
q = new SymetricMatrix(),
|
||||
});
|
||||
i += 3;
|
||||
}*/
|
||||
}
|
||||
for (i = 0; i<input.Length; i+=3)
|
||||
triangles.Add(new Triangle()
|
||||
return Simplify();
|
||||
}
|
||||
|
||||
public List<Vector3> Simplify(Vector3[] verts, int[] indices)
|
||||
{
|
||||
v = new Int3(i, i+1, i+2),
|
||||
triangles = new List<Triangle>(indices.Length / 3);
|
||||
vertices = new List<Vertex>(verts.Length);
|
||||
|
||||
{
|
||||
foreach (var vec in verts)
|
||||
{
|
||||
vertices.Add(new Vertex()
|
||||
{
|
||||
p = vec,
|
||||
q = new SymetricMatrix(),
|
||||
});
|
||||
}
|
||||
|
||||
for (int i = 0; i < indices.Length; i += 3)
|
||||
{
|
||||
triangles.Add(new Triangle()
|
||||
{
|
||||
v = new Int3(indices[i]-1, indices[i+1]-1, indices[i+2]-1),
|
||||
});
|
||||
}
|
||||
}
|
||||
return Simplify();
|
||||
}
|
||||
|
||||
private List<Vector3> Simplify()
|
||||
{
|
||||
|
||||
// main iteration loop
|
||||
int deleted_triangles=0;
|
||||
@@ -198,11 +273,13 @@ namespace Game
|
||||
|
||||
//int iteration = 0;
|
||||
//loop(iteration,0,100)
|
||||
for (int iteration = 0; iteration < 9999; iteration ++)
|
||||
int iteration;
|
||||
for (iteration = 0; iteration < 9999; iteration++)
|
||||
{
|
||||
if (ratio < 1.0f && triangle_start_count-deleted_triangles<=target_count) break;
|
||||
if (ratio < 1.0f && triangle_start_count-deleted_triangles<=target_count)
|
||||
break;
|
||||
|
||||
// update mesh constantly
|
||||
if (ratio >= 1.0f || iteration % 5 == 0)
|
||||
update_mesh(iteration);
|
||||
// clear dirty flag
|
||||
for (int i = 0; i < triangles.Count; i++)
|
||||
@@ -214,7 +291,7 @@ namespace Game
|
||||
// If it does not, try to adjust the 3 parameters
|
||||
//
|
||||
//double threshold = 0.001; //1.0E-3 EPS;
|
||||
double threshold = 1.0E-3;
|
||||
double threshold = 1.0E-3;//1.0E-9;
|
||||
if (ratio < 1.0f)
|
||||
threshold = 0.000000001 * Math.Pow((double)(iteration+3),agressiveness);
|
||||
//if (verbose) {
|
||||
@@ -225,15 +302,26 @@ namespace Game
|
||||
for (int i = 0; i < triangles.Count; i++)
|
||||
{
|
||||
Triangle t = triangles[i];
|
||||
if(t.err[3]>threshold) continue;
|
||||
if(t.deleted) continue;
|
||||
if(t.dirty) continue;
|
||||
if (t.err[3] > threshold)
|
||||
{
|
||||
t = t;
|
||||
continue;
|
||||
}
|
||||
|
||||
if(t.deleted)
|
||||
continue;
|
||||
if(t.dirty)
|
||||
continue;
|
||||
|
||||
for (int j = 0; j < 3; j++)
|
||||
if(t.err[j]<threshold)
|
||||
{
|
||||
int i0=t.v[ j ]; Vertex v0 = vertices[i0];
|
||||
int i1=t.v[(j+1)%3]; Vertex v1 = vertices[i1];
|
||||
if (t.err[j] > threshold)
|
||||
continue;
|
||||
|
||||
int i0=t.v[ j ];
|
||||
Vertex v0 = vertices[i0];
|
||||
int i1=t.v[(j+1)%3];
|
||||
Vertex v1 = vertices[i1];
|
||||
|
||||
// Border check
|
||||
if(v0.border != v1.border)
|
||||
@@ -284,11 +372,16 @@ namespace Game
|
||||
v0.tcount=tcount;
|
||||
break;
|
||||
}
|
||||
if (ratio < 1.0f && triangle_start_count-deleted_triangles<=target_count) break;
|
||||
if (ratio < 1.0f && triangle_start_count-deleted_triangles<=target_count)
|
||||
break;
|
||||
}
|
||||
|
||||
if (ratio >= 1.0f)
|
||||
{
|
||||
if (deleted_triangles <= 0)
|
||||
break;
|
||||
deleted_triangles = 0;
|
||||
}
|
||||
} //for each iteration
|
||||
// clean up mesh
|
||||
compact_mesh();
|
||||
@@ -296,8 +389,15 @@ namespace Game
|
||||
if (triangles.Count == 0)
|
||||
return null;
|
||||
|
||||
List<Vector3> finalVerts = new List<Vector3>();
|
||||
foreach (var t in triangles)
|
||||
{
|
||||
finalVerts.Add(vertices[t.v[0]].p);
|
||||
finalVerts.Add(vertices[t.v[1]].p);
|
||||
finalVerts.Add(vertices[t.v[2]].p);
|
||||
}
|
||||
|
||||
return null;
|
||||
return finalVerts;
|
||||
}
|
||||
|
||||
// Check if a triangle flips when this edge is removed
|
||||
@@ -374,25 +474,6 @@ namespace Game
|
||||
}
|
||||
}
|
||||
|
||||
/*private Matrix MatrixPlane(float a, float b, float c, float d)
|
||||
{
|
||||
Matrix m = new Matrix();
|
||||
m[0] = a*a; m[1] = a*b; m[2] = a*c; m[3] = a*d;
|
||||
m[4] = b*b; m[5] = b*c; m[6] = b*d;
|
||||
m[7 ] = c*c; m[8 ] = c*d;
|
||||
m[9 ] = d*d;
|
||||
return m;
|
||||
}
|
||||
|
||||
private double MatrixDet(Matrix m, int a11, int a12, int a13,
|
||||
int a21, int a22, int a23,
|
||||
int a31, int a32, int a33)
|
||||
{
|
||||
double det = m[a11]*m[a22]*m[a33] + m[a13]*m[a21]*m[a32] + m[a12]*m[a23]*m[a31]
|
||||
- m[a13]*m[a22]*m[a31] - m[a11]*m[a23]*m[a32]- m[a12]*m[a21]*m[a33];
|
||||
return det;
|
||||
}*/
|
||||
|
||||
// compact triangles, compute edge error and build reference list
|
||||
|
||||
private void update_mesh(int iteration)
|
||||
@@ -416,23 +497,22 @@ namespace Game
|
||||
//
|
||||
if( iteration == 0 )
|
||||
{
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
vertices[i].q=new SymetricMatrix();//vertices[i].q=Matrix(0.0);
|
||||
//for (int i = 0; i < vertices.Count; i++)
|
||||
// vertices[i].q=new SymetricMatrix();//vertices[i].q=Matrix(0.0);
|
||||
|
||||
for (int i = 0; i < triangles.Count; i++)
|
||||
{
|
||||
if (i == 18)
|
||||
Console.Print(i.ToString());
|
||||
Triangle t=triangles[i];
|
||||
Vector3 n = new Vector3();
|
||||
|
||||
Vector3[] p = new Vector3[3];
|
||||
for (int j = 0; j<3; j++)
|
||||
p[j]=vertices[t.v[j]].p;
|
||||
n = Vector3.Cross(p[1]-p[0],p[2]-p[0]);
|
||||
|
||||
Vector3 n = Vector3.Cross(p[1]-p[0],p[2]-p[0]);
|
||||
n.Normalize();
|
||||
t.n=n;
|
||||
for (int j = 0; j<3; j++)
|
||||
vertices[t.v[j]].q = vertices[t.v[j]].q + new SymetricMatrix(n.X,n.Y,n.Z,-Vector3.Dot(n, p[0]));
|
||||
vertices[t.v[j]].q = vertices[t.v[j]].q + new SymetricMatrix(n.X,n.Y,n.Z,Vector3.Dot(-n, p[0]));
|
||||
}
|
||||
for (int i = 0; i < triangles.Count; i++)
|
||||
{
|
||||
@@ -453,7 +533,8 @@ namespace Game
|
||||
for (int i = 0; i < triangles.Count; i++)
|
||||
{
|
||||
Triangle t=triangles[i];
|
||||
for (int j = 0; j<3; j++) vertices[t.v[j]].tcount++;
|
||||
for (int j = 0; j<3; j++)
|
||||
vertices[t.v[j]].tcount++;
|
||||
}
|
||||
int tstart=0;
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
|
||||
@@ -4,6 +4,7 @@ using FlaxEngine;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Threading;
|
||||
using FlaxEngine.Assertions;
|
||||
using FlaxEngine.Utilities;
|
||||
using Console = Cabrito.Console;
|
||||
@@ -272,7 +273,7 @@ namespace Game
|
||||
}
|
||||
|
||||
ExportMesh(points, splitVerts, ref verts, ref tris, ref normals);
|
||||
VerifyMesh(points, ref verts, ref tris);
|
||||
//VerifyMesh(points, ref verts, ref tris);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -389,22 +390,22 @@ namespace Game
|
||||
// before those.
|
||||
openSetTail = openSet.Count - 5;
|
||||
|
||||
Assert(openSet.Count == points.Count);
|
||||
Assert.IsTrue(openSet.Count == points.Count);
|
||||
|
||||
// Assign all points of the open set. This does basically the same
|
||||
// thing as ReassignPoints()
|
||||
for (int i = 0; i <= openSetTail; i++) {
|
||||
Assert(openSet[i].Face == UNASSIGNED);
|
||||
Assert(openSet[openSetTail].Face == UNASSIGNED);
|
||||
Assert(openSet[openSetTail + 1].Face == INSIDE);
|
||||
Assert.IsTrue(openSet[i].Face == UNASSIGNED);
|
||||
Assert.IsTrue(openSet[openSetTail].Face == UNASSIGNED);
|
||||
Assert.IsTrue(openSet[openSetTail + 1].Face == INSIDE);
|
||||
|
||||
var assigned = false;
|
||||
var fp = openSet[i];
|
||||
|
||||
Assert(faces.Count == 4);
|
||||
Assert(faces.Count == faceCount);
|
||||
Assert.IsTrue(faces.Count == 4);
|
||||
Assert.IsTrue(faces.Count == faceCount);
|
||||
for (int j = 0; j < 4; j++) {
|
||||
Assert(faces.ContainsKey(j));
|
||||
Assert.IsTrue(faces.ContainsKey(j));
|
||||
|
||||
var face = faces[j];
|
||||
|
||||
@@ -483,8 +484,8 @@ namespace Game
|
||||
/// from its face.
|
||||
/// </summary>
|
||||
void GrowHull(List<Vector3> points) {
|
||||
Assert(openSetTail >= 0);
|
||||
Assert(openSet[0].Face != INSIDE);
|
||||
Assert.IsTrue(openSetTail >= 0);
|
||||
Assert.IsTrue(openSet[0].Face != INSIDE);
|
||||
|
||||
// Find farthest point and first lit face.
|
||||
var farthestPoint = 0;
|
||||
@@ -540,7 +541,7 @@ namespace Game
|
||||
|
||||
litFaces.Add(fi);
|
||||
|
||||
Assert(PointFaceDistance(point, points[face.Vertex0], face) > 0.0f);
|
||||
Assert.IsTrue(PointFaceDistance(point, points[face.Vertex0], face) > 0.0f);
|
||||
|
||||
// For the rest of the recursive search calls, we first check if the
|
||||
// triangle has already been visited and is part of litFaces.
|
||||
@@ -609,10 +610,10 @@ namespace Game
|
||||
/// Recursively search to find the horizon or lit set.
|
||||
/// </summary>
|
||||
void SearchHorizon(List<Vector3> points, Vector3 point, int prevFaceIndex, int faceCount, Face face) {
|
||||
Assert(prevFaceIndex >= 0);
|
||||
Assert(litFaces.Contains(prevFaceIndex));
|
||||
Assert(!litFaces.Contains(faceCount));
|
||||
Assert(faces[faceCount].Equals(face));
|
||||
Assert.IsTrue(prevFaceIndex >= 0);
|
||||
Assert.IsTrue(litFaces.Contains(prevFaceIndex));
|
||||
Assert.IsTrue(!litFaces.Contains(faceCount));
|
||||
Assert.IsTrue(faces[faceCount].Equals(face));
|
||||
|
||||
litFaces.Add(faceCount);
|
||||
|
||||
@@ -641,7 +642,7 @@ namespace Game
|
||||
edge1 = face.Vertex1;
|
||||
edge2 = face.Vertex2;
|
||||
} else {
|
||||
Assert(prevFaceIndex == face.Opposite2);
|
||||
Assert.IsTrue(prevFaceIndex == face.Opposite2);
|
||||
|
||||
nextFaceIndex0 = face.Opposite0;
|
||||
nextFaceIndex1 = face.Opposite1;
|
||||
@@ -704,7 +705,7 @@ namespace Game
|
||||
/// </summary>
|
||||
void ConstructCone(List<Vector3> points, int farthestPoint) {
|
||||
foreach (var fi in litFaces) {
|
||||
Assert(faces.ContainsKey(fi));
|
||||
Assert.IsTrue(faces.ContainsKey(fi));
|
||||
faces.Remove(fi);
|
||||
}
|
||||
|
||||
@@ -759,14 +760,14 @@ namespace Game
|
||||
var horizonFace = faces[horizon[i].Face];
|
||||
|
||||
if (horizonFace.Vertex0 == v1) {
|
||||
Assert(v2 == horizonFace.Vertex2);
|
||||
Assert.IsTrue(v2 == horizonFace.Vertex2);
|
||||
horizonFace.Opposite1 = fi;
|
||||
} else if (horizonFace.Vertex1 == v1) {
|
||||
Assert(v2 == horizonFace.Vertex0);
|
||||
Assert.IsTrue(v2 == horizonFace.Vertex0);
|
||||
horizonFace.Opposite2 = fi;
|
||||
} else {
|
||||
Assert(v1 == horizonFace.Vertex2);
|
||||
Assert(v2 == horizonFace.Vertex1);
|
||||
Assert.IsTrue(v1 == horizonFace.Vertex2);
|
||||
Assert.IsTrue(v2 == horizonFace.Vertex1);
|
||||
horizonFace.Opposite0 = fi;
|
||||
}
|
||||
|
||||
@@ -987,12 +988,12 @@ namespace Game
|
||||
void VerifyOpenSet(List<Vector3> points) {
|
||||
for (int i = 0; i < openSet.Count; i++) {
|
||||
if (i > openSetTail) {
|
||||
Assert(openSet[i].Face == INSIDE);
|
||||
Assert.IsTrue(openSet[i].Face == INSIDE);
|
||||
} else {
|
||||
Assert(openSet[i].Face != INSIDE);
|
||||
Assert(openSet[i].Face != UNASSIGNED);
|
||||
Assert.IsTrue(openSet[i].Face != INSIDE);
|
||||
Assert.IsTrue(openSet[i].Face != UNASSIGNED);
|
||||
|
||||
Assert(PointFaceDistance(
|
||||
Assert.IsTrue(PointFaceDistance(
|
||||
points[openSet[i].Point],
|
||||
points[faces[openSet[i].Face].Vertex0],
|
||||
faces[openSet[i].Face]) > 0.0f);
|
||||
@@ -1009,8 +1010,8 @@ namespace Game
|
||||
for (int i = 0; i < horizon.Count; i++) {
|
||||
var prev = i == 0 ? horizon.Count - 1 : i - 1;
|
||||
|
||||
Assert(horizon[prev].Edge1 == horizon[i].Edge0);
|
||||
Assert(HasEdge(faces[horizon[i].Face], horizon[i].Edge1, horizon[i].Edge0));
|
||||
Assert.IsTrue(horizon[prev].Edge1 == horizon[i].Edge0);
|
||||
Assert.IsTrue(HasEdge(faces[horizon[i].Face], horizon[i].Edge1, horizon[i].Edge0));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1024,23 +1025,23 @@ namespace Game
|
||||
var fi = kvp.Key;
|
||||
var face = kvp.Value;
|
||||
|
||||
Assert(faces.ContainsKey(face.Opposite0));
|
||||
Assert(faces.ContainsKey(face.Opposite1));
|
||||
Assert(faces.ContainsKey(face.Opposite2));
|
||||
Assert.IsTrue(faces.ContainsKey(face.Opposite0));
|
||||
Assert.IsTrue(faces.ContainsKey(face.Opposite1));
|
||||
Assert.IsTrue(faces.ContainsKey(face.Opposite2));
|
||||
|
||||
Assert(face.Opposite0 != fi);
|
||||
Assert(face.Opposite1 != fi);
|
||||
Assert(face.Opposite2 != fi);
|
||||
Assert.IsTrue(face.Opposite0 != fi);
|
||||
Assert.IsTrue(face.Opposite1 != fi);
|
||||
Assert.IsTrue(face.Opposite2 != fi);
|
||||
|
||||
Assert(face.Vertex0 != face.Vertex1);
|
||||
Assert(face.Vertex0 != face.Vertex2);
|
||||
Assert(face.Vertex1 != face.Vertex2);
|
||||
Assert.IsTrue(face.Vertex0 != face.Vertex1);
|
||||
Assert.IsTrue(face.Vertex0 != face.Vertex2);
|
||||
Assert.IsTrue(face.Vertex1 != face.Vertex2);
|
||||
|
||||
Assert(HasEdge(faces[face.Opposite0], face.Vertex2, face.Vertex1));
|
||||
Assert(HasEdge(faces[face.Opposite1], face.Vertex0, face.Vertex2));
|
||||
Assert(HasEdge(faces[face.Opposite2], face.Vertex1, face.Vertex0));
|
||||
Assert.IsTrue(HasEdge(faces[face.Opposite0], face.Vertex2, face.Vertex1));
|
||||
Assert.IsTrue(HasEdge(faces[face.Opposite1], face.Vertex0, face.Vertex2));
|
||||
Assert.IsTrue(HasEdge(faces[face.Opposite2], face.Vertex1, face.Vertex0));
|
||||
|
||||
Assert((face.Normal - Normal(
|
||||
Assert.IsTrue((face.Normal - Normal(
|
||||
points[face.Vertex0],
|
||||
points[face.Vertex1],
|
||||
points[face.Vertex2])).Length < EPSILON);
|
||||
@@ -1053,7 +1054,7 @@ namespace Game
|
||||
/// if DEBUG_QUICKHULL if defined.
|
||||
/// </summary>
|
||||
void VerifyMesh(List<Vector3> points, ref List<Vector3> verts, ref List<int> tris) {
|
||||
Assert(tris.Count % 3 == 0);
|
||||
Assert.IsTrue(tris.Count % 3 == 0);
|
||||
|
||||
for (int i = 0; i < points.Count; i++) {
|
||||
for (int j = 0; j < tris.Count; j+=3) {
|
||||
@@ -1061,7 +1062,10 @@ namespace Game
|
||||
var t1 = verts[tris[j + 1]];
|
||||
var t2 = verts[tris[j + 2]];
|
||||
|
||||
Assert(Dot(points[i] - t0, Vector3.Cross(t1 - t0, t2 - t0)) <= EPSILON);
|
||||
var dot = Dot(points[i] - t0, Vector3.Cross(t1 - t0, t2 - t0));
|
||||
//Assert.IsTrue(dot <= EPSILON, $"not convex hull: {dot} > {EPSILON}");
|
||||
if (!(dot <= EPSILON))
|
||||
Console.PrintError($"not convex hull: {dot} > {EPSILON}");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1076,21 +1080,6 @@ namespace Game
|
||||
|| (f.Vertex1 == e0 && f.Vertex2 == e1)
|
||||
|| (f.Vertex2 == e0 && f.Vertex0 == e1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Assert method, conditionally compiled with DEBUG_QUICKHULL.
|
||||
///
|
||||
/// I could just use Debug.Assert or the Assertions class, but I like
|
||||
/// the idea of just writing Assert(something), and I also want it to
|
||||
/// be conditionally compiled out with the same #define as the other
|
||||
/// debug methods.
|
||||
/// </summary>
|
||||
static void Assert(bool condition) {
|
||||
if (!condition) {
|
||||
FlaxEngine.Assertions.Assert.Fail("Assertion failed");
|
||||
//throw new UnityEngine.Assertions.AssertionException("Assertion failed", "");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1099,13 +1088,19 @@ namespace Game
|
||||
{
|
||||
private string mapPath = @"C:\dev\GoakeFlax\Assets\Maps\cube.map";
|
||||
//private string mapPath = @"C:\dev\Goake\maps\aerowalk\aerowalk.map";
|
||||
//private string mapPath = @"C:\dev\GoakeFlax\Assets\Maps\problematic.map";
|
||||
|
||||
Model model;
|
||||
public MaterialBase material;
|
||||
|
||||
const float epsilon = 0.00001f;
|
||||
const float epsilon = 0.01f;
|
||||
|
||||
Vector3[] QuickHull(Vector3[] points)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
void QuickHull(Vector3[] points, out Vector3[] outVertices)
|
||||
{
|
||||
var verts = new List<Vector3>();
|
||||
var tris = new List<int>();
|
||||
@@ -1121,22 +1116,142 @@ namespace Game
|
||||
finalPoints.Add(verts[tri]);
|
||||
}
|
||||
|
||||
return MergeCoplanarFaces(finalPoints.ToArray());
|
||||
outVertices = finalPoints.ToArray();
|
||||
}
|
||||
|
||||
Vector3[] MergeCoplanarFaces(Vector3[] points)
|
||||
private Color[] planeColors = new Color[]
|
||||
{
|
||||
// degenerate faces
|
||||
Color.Red,
|
||||
Color.Orange,
|
||||
Color.Yellow,
|
||||
Color.Green,
|
||||
Color.Cyan,
|
||||
Color.Blue,
|
||||
Color.Purple,
|
||||
Color.Magenta,
|
||||
};
|
||||
|
||||
return points;
|
||||
private int skipPlanes = 0;
|
||||
private int takePlanes = 5;
|
||||
|
||||
private List<Vector3> debugPoints = new List<Vector3>();
|
||||
|
||||
public override void OnDebugDraw()
|
||||
{
|
||||
return;
|
||||
if (root == null)
|
||||
return;
|
||||
|
||||
//foreach (var p in debugPoints)
|
||||
// DebugDraw.DrawSphere(new BoundingSphere(p, 30f), Color.LightBlue, 0f, false);
|
||||
|
||||
foreach (var brush in root.entities[0].brushes.Skip(1).Take(1))
|
||||
{
|
||||
int planeI = skipPlanes;
|
||||
foreach (var plane in brush.planes.Take(takePlanes))
|
||||
//foreach (var plane in brush.planes)
|
||||
{
|
||||
Plane p = new Plane(plane.v1, plane.v2, plane.v3);
|
||||
Vector3 planeNormal = -p.Normal;
|
||||
|
||||
const float w = 300f;
|
||||
|
||||
Vector3 p1 = new Vector3(-w, -w, 0f);
|
||||
Vector3 p2 = new Vector3(w, -w, 0f);
|
||||
Vector3 p3 = new Vector3(-w, w, 0f);
|
||||
Vector3 p4 = new Vector3(w, w, 0f);
|
||||
|
||||
Vector3 uu = Vector3.Up;
|
||||
if (Mathf.Abs(Vector3.Dot(planeNormal, uu)) > 0.9999f)
|
||||
uu = Vector3.Forward;
|
||||
|
||||
var q = Quaternion.LookAt(Vector3.Zero, planeNormal, -uu);
|
||||
|
||||
p1 = p1 * q;
|
||||
p2 = p2 * q;
|
||||
p3 = p3 * q;
|
||||
p4 = p4 * q;
|
||||
|
||||
p1 += p.D * planeNormal;
|
||||
p2 += p.D * planeNormal;
|
||||
p3 += p.D * planeNormal;
|
||||
p4 += p.D * planeNormal;
|
||||
|
||||
var color = planeColors[planeI%planeColors.Length] * 0.5f;
|
||||
DebugDraw.DrawTriangle(p1, p2, p3, color);
|
||||
DebugDraw.DrawTriangle(p2, p3, p4, color);
|
||||
|
||||
|
||||
|
||||
planeI++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private MapEntity root;
|
||||
|
||||
public override void OnStart()
|
||||
private IEnumerable<IEnumerable<T>> DifferentCombinations<T>(IEnumerable<T> elements, int k)
|
||||
{
|
||||
byte[] mapChars = File.ReadAllBytes(mapPath);
|
||||
var root = MapParser.Parse(mapChars);
|
||||
return k == 0 ? new[] { new T[0] } :
|
||||
elements.SelectMany((e, i) =>
|
||||
DifferentCombinations(elements.Skip(i + 1), (k - 1)).Select(c => (new[] {e}).Concat(c)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Triangulates the brush by calculating intersection points between triplets of planes.
|
||||
/// Does not work well with off-axis aligned planes.
|
||||
/// </summary>
|
||||
void TriangulateBrush(MapBrush brush, out Vector3[] vertices)
|
||||
{
|
||||
HashSet<Vector3> planePoints = new HashSet<Vector3>();
|
||||
|
||||
List<Plane> planes = new List<Plane>();
|
||||
foreach (var brushPlane in brush.planes)
|
||||
planes.Add(new Plane(brushPlane.v1, brushPlane.v2, brushPlane.v3));
|
||||
|
||||
var combinations = DifferentCombinations(planes, 3).ToList();
|
||||
foreach (var comb in Enumerable.Reverse(combinations))
|
||||
{
|
||||
var p1 = comb.Skip(0).First();
|
||||
var p2 = comb.Skip(1).First();
|
||||
var p3 = comb.Skip(2).First();
|
||||
|
||||
var maxDist = Math.Abs(p1.D * p2.D * p3.D);//Math.Max(p1.D, Math.Max(p2.D, p3.D));
|
||||
|
||||
// intersection of three planes
|
||||
double denom = Vector3.Dot(p1.Normal, Vector3.Cross(p2.Normal, p3.Normal));
|
||||
if (Math.Abs(denom) < 0.000001f)
|
||||
continue; // multiple or no intersections
|
||||
|
||||
if (Math.Abs(denom) < 0.000001f)
|
||||
denom = denom;
|
||||
|
||||
var intersection = (Vector3.Cross(p2.Normal, p3.Normal) * -p1.D +
|
||||
Vector3.Cross(p3.Normal, p1.Normal) * -p2.D +
|
||||
Vector3.Cross(p1.Normal, p2.Normal) * -p3.D) / (float)denom;
|
||||
|
||||
// Flip Y and Z
|
||||
/*var temp = intersection.Y;
|
||||
intersection.Y = intersection.Z;
|
||||
intersection.Z = temp;*/
|
||||
|
||||
//if (intersection.Length >= maxDist)
|
||||
// temp = temp;
|
||||
|
||||
planePoints.Add(intersection);
|
||||
}
|
||||
|
||||
if (planePoints.Count > 0)
|
||||
{
|
||||
QuickHull(planePoints.ToArray(), out vertices);
|
||||
return;
|
||||
}
|
||||
|
||||
vertices = new Vector3[0];
|
||||
}
|
||||
|
||||
Vector3[] TriangulateBrush2(MapBrush brush)
|
||||
{
|
||||
const float cs = 3000f;
|
||||
|
||||
Vector3[] cubePoints = new[]
|
||||
@@ -1150,23 +1265,16 @@ namespace Game
|
||||
new Vector3(-cs, cs, cs),
|
||||
new Vector3(cs, cs, cs),
|
||||
};
|
||||
Vector3[] cubeVerts = QuickHull(cubePoints).ToArray();
|
||||
|
||||
List<Vector3> vertices = new List<Vector3>();
|
||||
foreach (var brush in root.entities[0].brushes.Take(1))
|
||||
{
|
||||
Vector3[] cubeVerts;
|
||||
QuickHull(cubePoints, out cubeVerts);
|
||||
List<Vector3> brushVertices = new List<Vector3>(cubeVerts);
|
||||
//foreach (var plane in new [] { brush.planes.First() })
|
||||
foreach (var plane in brush.planes.Reverse().Take(1))
|
||||
//foreach (var plane in brush.planes)
|
||||
{
|
||||
Plane p = new Plane(plane.v1, plane.v2, plane.v3);
|
||||
Vector3 planeNormal = p.Normal;
|
||||
List<Vector3> newBrushVertices = new List<Vector3>();
|
||||
List<Vector3> faceVertices = new List<Vector3>();
|
||||
|
||||
if (true)
|
||||
foreach (var brushPlane in brush.planes.Take(1))
|
||||
{
|
||||
Plane plane = new Plane(brushPlane.v1, brushPlane.v2, brushPlane.v3);
|
||||
List<Vector3> faceVertices = new List<Vector3>();
|
||||
List<Vector3> clippedVertices = new List<Vector3>();
|
||||
|
||||
Func<float, bool> isFront = (f) => f > epsilon;
|
||||
Func<float, bool> isBack = (f) => f < -epsilon;
|
||||
|
||||
@@ -1176,33 +1284,91 @@ namespace Game
|
||||
Vector3 start = brushVertices[i];
|
||||
Vector3 end = brushVertices[i2];
|
||||
|
||||
var d1 = (start.X * planeNormal.X) + (start.Y * planeNormal.Y) + (start.Z * planeNormal.Z) +
|
||||
p.D;
|
||||
var d2 = (end.X * planeNormal.X) + (end.Y * planeNormal.Y) + (end.Z * planeNormal.Z) + p.D;
|
||||
var d1 = Plane.DotCoordinate(plane, start);
|
||||
var d2 = Plane.DotCoordinate(plane, end);
|
||||
|
||||
if (isBack(d1))
|
||||
{
|
||||
// include back
|
||||
// include the point behind the clipping plane
|
||||
faceVertices.Add(start);
|
||||
}
|
||||
|
||||
if (isBack(d1) && isFront(d2) || isFront(d1) && isBack(d2))
|
||||
{
|
||||
// the cutting plane clips the edge
|
||||
//if (isFront(d2))
|
||||
{
|
||||
// include clip
|
||||
Ray ray2 = new Ray(start, (end - start).Normalized);
|
||||
if (p.Intersects(ref ray2, out Vector3 intersect2))
|
||||
faceVertices.Add(intersect2);
|
||||
Ray ray = new Ray(start, (end - start).Normalized);
|
||||
if (plane.Intersects(ref ray, out Vector3 point))
|
||||
{
|
||||
|
||||
//faceVertices.Add(point);
|
||||
//clippedVertices.Add(point);
|
||||
|
||||
/*
|
||||
intersect
|
||||
start __._ (end)
|
||||
| |/
|
||||
| /
|
||||
|/
|
||||
next
|
||||
*/
|
||||
if (isBack(d1) && isFront(d2))
|
||||
{
|
||||
// finish the current triangle and start the next one
|
||||
// [start, intersect, next], [intersect, ...]
|
||||
|
||||
faceVertices.Add(point);
|
||||
|
||||
if ((faceVertices.Count % 3) == 2)
|
||||
{
|
||||
int i3 = ((i2 + 1) % 3 == 0) ? (i2 - 2) : (i2 + 1);
|
||||
Vector3 next = brushVertices[i3];
|
||||
faceVertices.Add(next);
|
||||
}
|
||||
else
|
||||
ray = ray;
|
||||
|
||||
faceVertices.Add(point);
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
____ (start)
|
||||
| |/
|
||||
| * intersect2
|
||||
|/
|
||||
end
|
||||
*/
|
||||
else if (isFront(d1) && isBack(d2))
|
||||
{
|
||||
// continue where we left off
|
||||
// [intersect, intersect2, ...]
|
||||
|
||||
faceVertices.Add(point);
|
||||
|
||||
if ((i % 3) == 2)
|
||||
{
|
||||
int i3 = ((i2 + 1) % 3 == 0) ? (i2 - 2) : (i2 + 1);
|
||||
Vector3 next = brushVertices[i3];
|
||||
faceVertices.Add(next);
|
||||
}
|
||||
else
|
||||
ray = ray;
|
||||
}
|
||||
else
|
||||
ray = ray;
|
||||
}
|
||||
else
|
||||
d1 = d1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (true)
|
||||
{
|
||||
var newMeshPoints = new List<Vector3>();
|
||||
brushVertices.Clear();
|
||||
brushVertices.AddRange(faceVertices);
|
||||
|
||||
/*var newMeshPoints = new List<Vector3>();
|
||||
int duplis = 0;
|
||||
foreach (var v in faceVertices)
|
||||
{
|
||||
@@ -1221,52 +1387,451 @@ namespace Game
|
||||
if (!found)
|
||||
newMeshPoints.Add(v);
|
||||
}
|
||||
|
||||
if (duplis > 0)
|
||||
Console.Print("duplicates: " + duplis);
|
||||
|
||||
if (newMeshPoints.Count > 0)
|
||||
{
|
||||
var tempPoints = newMeshPoints;
|
||||
newMeshPoints = new List<Vector3>(tempPoints.Count);
|
||||
foreach (var tp in tempPoints)
|
||||
{
|
||||
// Flip Y and Z
|
||||
newMeshPoints.Add(new Vector3(tp.X, tp.Z, tp.Y));
|
||||
}
|
||||
|
||||
var hullPoints = QuickHull(newMeshPoints.ToArray());
|
||||
var ms = new MeshSimplifier();
|
||||
var optimizedVerts = ms.Simplify(hullPoints);
|
||||
newBrushVertices.Clear();
|
||||
newBrushVertices.AddRange(hullPoints);
|
||||
brushVertices.Clear();
|
||||
brushVertices.AddRange(hullPoints);
|
||||
}
|
||||
else
|
||||
newBrushVertices.Clear();
|
||||
brushVertices.Clear();
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
return brushVertices.ToArray();
|
||||
}
|
||||
|
||||
void TriangulateBrush3(MapBrush brush, out Vector3[] vertices)
|
||||
{
|
||||
float cs = 3000f;
|
||||
|
||||
float maxD = 0f;
|
||||
float minD = 0f;
|
||||
foreach (var brushPlane in brush.planes)
|
||||
{
|
||||
var p = new Plane(brushPlane.v1, brushPlane.v2, brushPlane.v3);
|
||||
minD = Mathf.Min(p.D);
|
||||
maxD = Mathf.Max(p.D);
|
||||
}
|
||||
|
||||
//cs = maxD*2;
|
||||
|
||||
|
||||
Vector3[] cubePoints = new[]
|
||||
{
|
||||
new Vector3(-cs, -cs, -cs),
|
||||
new Vector3(cs, -cs, -cs),
|
||||
new Vector3(-cs, cs, -cs),
|
||||
new Vector3(cs, cs, -cs),
|
||||
new Vector3(-cs, -cs, cs),
|
||||
new Vector3(cs, -cs, cs),
|
||||
new Vector3(-cs, cs, cs),
|
||||
new Vector3(cs, cs, cs),
|
||||
};
|
||||
Vector3[] cubeVerts;
|
||||
QuickHull(cubePoints, out cubeVerts);
|
||||
List<Vector3> brushVertices = new List<Vector3>(cubeVerts);
|
||||
|
||||
int asdf = 0;
|
||||
//foreach (var brushPlane in brush.planes.Skip(skipPlanes).Take(takePlanes))
|
||||
foreach (var brushPlane in brush.planes)
|
||||
{
|
||||
Plane plane = new Plane(brushPlane.v1, brushPlane.v2, brushPlane.v3);
|
||||
//if (asdf % 2 == 0)
|
||||
//plane = new Plane(-plane.Normal, -plane.D);
|
||||
|
||||
|
||||
List<Vector3> faceVertices = new List<Vector3>();
|
||||
List<Vector3> clippedVertices = new List<Vector3>();
|
||||
|
||||
Func<float, bool> isFront = (f) => f < epsilon;
|
||||
Func<float, bool> isBack = (f) => f > epsilon;
|
||||
|
||||
List<Tuple<Vector3, Vector3>> edges = new List<Tuple<Vector3, Vector3>>();
|
||||
List<Tuple<Vector3, Vector3>> faceEdges = new List<Tuple<Vector3, Vector3>>();
|
||||
|
||||
void TriangulateEdges()
|
||||
{
|
||||
if (edges.Count > 0)
|
||||
{
|
||||
// heal discontinued edges
|
||||
for (int j = 0; j < edges.Count; j++)
|
||||
{
|
||||
var edgePrev = edges[j];
|
||||
var edgeNext = edges[(j + 1) % edges.Count];
|
||||
|
||||
//if (edgePrev.Item2 != edgeNext.Item1)
|
||||
if ((edgePrev.Item2 - edgeNext.Item1).Length > 0.0001f)
|
||||
{
|
||||
var newEdge = new Tuple<Vector3, Vector3>(edgePrev.Item2, edgeNext.Item1);
|
||||
edges.Insert(j + 1, newEdge);
|
||||
j--;
|
||||
}
|
||||
}
|
||||
|
||||
Assert.IsTrue(newBrushVertices.Count % 3 == 0,
|
||||
"invalid amount of vertices: " + newBrushVertices.Count);
|
||||
//Assert.IsTrue(newBrushVertices.Count > 0,
|
||||
// "brush was clipped completely, vertices: " + newBrushVertices.Count);
|
||||
// triangulate edges
|
||||
for (int j = 0; j < edges.Count - 1; j++)
|
||||
{
|
||||
var edgePrev = edges[j];
|
||||
var edgeNext = edges[(j + 1) % edges.Count];
|
||||
|
||||
Vector3 v0 = edges[0].Item1;
|
||||
Vector3 v1 = edgePrev.Item2;
|
||||
Vector3 v2 = edgeNext.Item2;
|
||||
|
||||
faceVertices.Add(v0);
|
||||
faceVertices.Add(v1);
|
||||
faceVertices.Add(v2);
|
||||
}
|
||||
|
||||
// triangulate clipped face
|
||||
/*for (int j = 0; j < clippedVertices.Count-1; j++)
|
||||
{
|
||||
Vector3 v0 = clippedVertices[0];
|
||||
Vector3 v1 = edgePrev.Item2;
|
||||
Vector3 v2 = edgeNext.Item2;
|
||||
}*/
|
||||
// TODO: maybe optimize the triangles here instead of using QuickHull
|
||||
}
|
||||
else
|
||||
plane = plane;
|
||||
|
||||
edges.Clear();
|
||||
}
|
||||
|
||||
for (int i = 0; i < brushVertices.Count; i++)
|
||||
{
|
||||
if (i > 0 && i % 3 == 0)
|
||||
TriangulateEdges();
|
||||
|
||||
int i2 = ((i + 1) % 3 == 0) ? (i - 2) : (i + 1);
|
||||
Vector3 start = brushVertices[i];
|
||||
Vector3 end = brushVertices[i2];
|
||||
|
||||
var d1 = Plane.DotCoordinate(plane, start);
|
||||
var d2 = Plane.DotCoordinate(plane, end);
|
||||
|
||||
Vector3 edgeStart = start;
|
||||
Vector3 edgeEnd = end;
|
||||
|
||||
|
||||
if (isBack(d1))
|
||||
{
|
||||
edgeStart = start;
|
||||
}
|
||||
|
||||
if (isBack(d1) && isFront(d2) || isFront(d1) && isBack(d2))
|
||||
{
|
||||
Ray ray = new Ray(start, (end - start).Normalized);
|
||||
Ray ray2 = new Ray(end, (start - end).Normalized);
|
||||
if (plane.Intersects(ref ray, out Vector3 point) /*|| plane.Intersects(ref ray2, out point)*/)
|
||||
{
|
||||
edgeEnd = point;
|
||||
clippedVertices.Add(point);
|
||||
|
||||
if (isFront(d1))
|
||||
{
|
||||
edgeStart = edgeEnd;
|
||||
edgeEnd = end;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isFront(d1) && isFront(d2))
|
||||
continue;
|
||||
|
||||
Tuple<Vector3, Vector3> edge = new Tuple<Vector3, Vector3>(edgeStart, edgeEnd);
|
||||
edges.Add(edge);
|
||||
}
|
||||
|
||||
TriangulateEdges();
|
||||
if (false)
|
||||
{
|
||||
// create edges from clipped points
|
||||
var clippedEdges = new List<Tuple<Vector3, Vector3>>();
|
||||
|
||||
//foreach (var e in edges)
|
||||
// newEdges.Add(new Tuple<Vector3, Vector3>(e.Item1, e.Item2));
|
||||
|
||||
for (int i = 0; i < clippedVertices.Count; i++)
|
||||
{
|
||||
int i2 = (i + 1) % clippedVertices.Count;
|
||||
Vector3 start = clippedVertices[i];
|
||||
Vector3 end = clippedVertices[i2];
|
||||
|
||||
while (i < clippedVertices.Count)
|
||||
{
|
||||
int i3 = (i + 2) % clippedVertices.Count;
|
||||
Vector3 end2 = clippedVertices[i3];
|
||||
|
||||
var edgeDirection = (end - start).Normalized;
|
||||
var edgeDirection2 = (end2 - start).Normalized;
|
||||
|
||||
if ((edgeDirection2 - edgeDirection).Length < 0.0001f)
|
||||
{
|
||||
end = end2;
|
||||
i++;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
clippedEdges.Add(new Tuple<Vector3, Vector3>(start, end));
|
||||
}
|
||||
|
||||
// triangulate edges
|
||||
for (int j = 0; j < clippedEdges.Count; j++)
|
||||
{
|
||||
var edgePrev = clippedEdges[j];
|
||||
var edgeNext = clippedEdges[(j + 1) % clippedEdges.Count];
|
||||
|
||||
Vector3 v0 = clippedEdges[0].Item1;
|
||||
Vector3 v1 = edgePrev.Item2;
|
||||
Vector3 v2 = edgeNext.Item2;
|
||||
|
||||
faceVertices.Add(v0);
|
||||
faceVertices.Add(v1);
|
||||
faceVertices.Add(v2);
|
||||
}
|
||||
}
|
||||
|
||||
if (true)
|
||||
{
|
||||
List<Vector3> uniqPoints = new List<Vector3>();
|
||||
foreach (var v in faceVertices)
|
||||
{
|
||||
bool found = false;
|
||||
foreach (var v2 in uniqPoints)
|
||||
{
|
||||
if ((v - v2).Length < 0.01f)
|
||||
{
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
uniqPoints.Add(v);
|
||||
//uniqPoints.Add(new Vector3((float)Math.Round(v.X, 3), (float)Math.Round(v.Y, 3), (float)Math.Round(v.Z, 3)));
|
||||
}
|
||||
|
||||
debugPoints = new List<Vector3>(uniqPoints);
|
||||
|
||||
|
||||
Vector3[] hullPoints;
|
||||
QuickHull(uniqPoints.ToArray(), out hullPoints);
|
||||
|
||||
var ms = new MeshSimplifier();
|
||||
var optimizedVerts = ms.Simplify(hullPoints);
|
||||
|
||||
brushVertices.Clear();
|
||||
brushVertices.AddRange(newBrushVertices);
|
||||
Console.Print("plane verts: " + newBrushVertices.Count);
|
||||
brushVertices.AddRange(optimizedVerts);
|
||||
}
|
||||
else
|
||||
{
|
||||
debugPoints = new List<Vector3>(faceVertices);
|
||||
|
||||
var hullPoints = faceVertices;
|
||||
|
||||
var ms = new MeshSimplifier();
|
||||
var optimizedVerts = hullPoints; //ms.Simplify(hullPoints);
|
||||
|
||||
brushVertices.Clear();
|
||||
brushVertices.AddRange(optimizedVerts);
|
||||
}
|
||||
|
||||
asdf++;
|
||||
|
||||
/*var newMeshPoints = new List<Vector3>();
|
||||
int duplis = 0;
|
||||
foreach (var v in faceVertices)
|
||||
{
|
||||
bool found = false;
|
||||
foreach (var vo in newMeshPoints)
|
||||
{
|
||||
if ((v - vo).Length < epsilon)
|
||||
{
|
||||
found = true;
|
||||
duplis++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//if (!newMeshPoints.Contains(v))
|
||||
if (!found)
|
||||
newMeshPoints.Add(v);
|
||||
}
|
||||
if (duplis > 0)
|
||||
Console.Print("duplicates: " + duplis);
|
||||
|
||||
if (newMeshPoints.Count > 0)
|
||||
{
|
||||
var tempPoints = newMeshPoints;
|
||||
newMeshPoints = new List<Vector3>(tempPoints.Count);
|
||||
foreach (var tp in tempPoints)
|
||||
{
|
||||
// Flip Y and Z
|
||||
newMeshPoints.Add(new Vector3(tp.X, tp.Z, tp.Y));
|
||||
}
|
||||
|
||||
var hullPoints = QuickHull(newMeshPoints.ToArray());
|
||||
var ms = new MeshSimplifier();
|
||||
var optimizedVerts = ms.Simplify(hullPoints);
|
||||
brushVertices.Clear();
|
||||
brushVertices.AddRange(hullPoints);
|
||||
}
|
||||
else
|
||||
brushVertices.Clear();
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
vertices = brushVertices.ToArray();
|
||||
}
|
||||
|
||||
|
||||
public override void OnStart()
|
||||
{
|
||||
byte[] mapChars = File.ReadAllBytes(mapPath);
|
||||
root = MapParser.Parse(mapChars);
|
||||
|
||||
List<Vector3> vertices = new List<Vector3>();
|
||||
List<Vector2> uvs = new List<Vector2>();
|
||||
List<Vector3> normals = new List<Vector3>();
|
||||
if (true)
|
||||
{
|
||||
int brushIndex = 0;
|
||||
//foreach (var brush in root.entities[0].brushes.Skip(1).Take(1))
|
||||
foreach (var brush in root.entities[0].brushes)
|
||||
{
|
||||
try
|
||||
{
|
||||
Vector3[] brushVertices;
|
||||
TriangulateBrush3(brush, out brushVertices);
|
||||
|
||||
Vector2[] brushUvs = new Vector2[brushVertices.Length];
|
||||
Vector3[] brushNormals = new Vector3[brushVertices.Length];
|
||||
|
||||
Vector2[] brushScaling = new Vector2[brushVertices.Length];
|
||||
|
||||
|
||||
for (int i=0; i<brushVertices.Length; i+=3)
|
||||
{
|
||||
Vector3 v1 = brushVertices[i+0];
|
||||
Vector3 v2 = brushVertices[i+1];
|
||||
Vector3 v3 = brushVertices[i+2];
|
||||
|
||||
Vector3 normal = Vector3.Cross(v3 - v1, v2 - v1).Normalized;
|
||||
Vector3 normal2 = normal;//new Vector3(normal.X, normal.Z, normal.Y);
|
||||
|
||||
// texture is projected to the surface from the closest axis
|
||||
|
||||
var dotX = Mathf.Abs(Vector3.Dot(normal2, Vector3.Right));
|
||||
var dotY = Mathf.Abs(Vector3.Dot(normal2, Vector3.Up));
|
||||
var dotZ = Mathf.Abs(Vector3.Dot(normal2, Vector3.Forward));
|
||||
Vector3 theUp = Vector3.Up;
|
||||
|
||||
if (dotX > dotY && dotX > dotZ)
|
||||
theUp = Vector3.Right;
|
||||
else if (dotZ > dotX && dotZ > dotY)
|
||||
theUp = Vector3.Forward;
|
||||
else if (dotY > dotX && dotY > dotZ)
|
||||
theUp = Vector3.Up;
|
||||
|
||||
|
||||
//rot = Quaternion.LookRotation(theUp, Vector3.Dot(normal, Vector3.Forward) < -0.01f ? Vector3.Forward : Vector3.Up);
|
||||
|
||||
//theUp = Vector3.Right;
|
||||
//theUp = new Vector3(theUp.X, theUp.Z, theUp.Y);
|
||||
var up1 = Vector3.Up;
|
||||
var up2 = Vector3.Forward;
|
||||
//theUp = Vector3.Forward;
|
||||
Quaternion rot = Quaternion.LookRotation(theUp, Mathf.Abs(Vector3.Dot(theUp, up1)) > 0.01f ? up2 : up1);
|
||||
|
||||
|
||||
Vector2 uvScale = new Vector2(1f / 16);
|
||||
float uvRotation = 0f;
|
||||
bool found = false;
|
||||
foreach (var brushPlane in brush.planes)
|
||||
{
|
||||
Plane plane = new Plane(brushPlane.v1, brushPlane.v2, brushPlane.v3);
|
||||
if ((plane.Normal - normal).Length < 0.01f)
|
||||
{
|
||||
uvScale = 1f / brushPlane.scale / 64f;
|
||||
//uvScale = brushPlane.scale;
|
||||
uvRotation = brushPlane.rotation;
|
||||
//uvScale = 1f / 512f;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!found)
|
||||
Console.Print("no found:/");
|
||||
|
||||
/*v1 = new Vector3(v1.X, v1.Z, v1.Y);
|
||||
v2 = new Vector3(v2.X, v2.Z, v2.Y);
|
||||
v3 = new Vector3(v3.X, v3.Z, v3.Y);*/
|
||||
|
||||
brushUvs[i + 0] = (Vector2)(v1 * rot) * uvScale;
|
||||
brushUvs[i + 1] = (Vector2)(v2 * rot) * uvScale;
|
||||
brushUvs[i + 2] = (Vector2)(v3 * rot) * uvScale;
|
||||
|
||||
brushNormals[i + 0] = normal;
|
||||
brushNormals[i + 1] = normal;
|
||||
brushNormals[i + 2] = normal;
|
||||
}
|
||||
|
||||
vertices.AddRange(brushVertices);
|
||||
uvs.AddRange(brushUvs);
|
||||
normals.AddRange(brushNormals);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.Print("Failed to hull brush " + brushIndex.ToString() + ": " + e.Message);
|
||||
}
|
||||
brushIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
if (vertices.Count > 0)
|
||||
{
|
||||
uint[] triangles = new uint[vertices.Count];
|
||||
for (uint i = 0; i < vertices.Count; i++)
|
||||
triangles[i] = i;
|
||||
|
||||
model = Content.CreateVirtualAsset<Model>();
|
||||
model.SetupLODs(new int[] { 1 });
|
||||
{
|
||||
var mesh = model.LODs[0].Meshes[0];
|
||||
List<int> triangles = new List<int>(vertices.Count);
|
||||
for (int i = 0; i < vertices.Count; i++)
|
||||
triangles.Add(i);
|
||||
Console.Print("verts: " + vertices.Count);
|
||||
mesh.UpdateMesh(vertices.ToArray(), triangles.ToArray(), vertices.ToArray());
|
||||
}
|
||||
model.LODs[0].Meshes[0].UpdateMesh(vertices.ToArray(), (int[])(object)triangles, normals.ToArray(), null, uvs.ToArray());
|
||||
|
||||
StaticModel childModel = Actor.AddChild<StaticModel>();
|
||||
childModel.Name = "MapModel";
|
||||
childModel.Model = model;
|
||||
childModel.SetMaterial(0, material);
|
||||
|
||||
CollisionData collisionData = Content.CreateVirtualAsset<CollisionData>();
|
||||
if (collisionData.CookCollision(CollisionDataType.TriangleMesh, vertices.ToArray(), triangles.ToArray()))
|
||||
throw new Exception("failed to cook final collision");
|
||||
var meshCollider = childModel.AddChild<MeshCollider>();
|
||||
meshCollider.CollisionData = collisionData;
|
||||
|
||||
// TODO: flip Y and Z
|
||||
childModel.Orientation = Quaternion.RotationYawPitchRoll(180f*Mathf.DegreesToRadians, -90f*Mathf.DegreesToRadians, 0f);
|
||||
childModel.Scale = new Vector3(1f, -1f, 1f);
|
||||
}
|
||||
}
|
||||
|
||||
public override void OnEnable()
|
||||
@@ -1281,7 +1846,6 @@ namespace Game
|
||||
|
||||
public override void OnUpdate()
|
||||
{
|
||||
// Here you can add code that needs to be called every frame
|
||||
}
|
||||
|
||||
public override void OnDestroy()
|
||||
|
||||
Reference in New Issue
Block a user