multiple materials
This commit is contained in:
@@ -270,6 +270,15 @@
|
||||
( -304 832 144 ) ( -303 832 144 ) ( -304 832 145 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( -304 832 144 ) ( -304 832 145 ) ( -304 833 144 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
}
|
||||
// brush 30
|
||||
{
|
||||
( -64 640 160 ) ( -64 641 160 ) ( -64 640 161 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
( -64 640 160 ) ( -64 640 161 ) ( -63 640 160 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( -64 640 160 ) ( -63 640 160 ) ( -64 641 160 ) dev/dev_128_red 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 48 736 224 ) ( 48 737 224 ) ( 49 736 224 ) dev/dev_128_red 0 0 0 0.0625 0.0625 0 0 0
|
||||
( 48 704 176 ) ( 49 704 176 ) ( 48 704 177 ) common/slick 0 0 0 1 1 0 0 0
|
||||
( 0 736 176 ) ( 0 736 177 ) ( 0 737 176 ) dev/dev_128_gray 0 0 0 0.0625 0.0625 0 0 0
|
||||
}
|
||||
}
|
||||
// entity 1
|
||||
{
|
||||
|
||||
@@ -36,7 +36,8 @@
|
||||
"Y": 141.0,
|
||||
"Z": 587.0
|
||||
}
|
||||
}
|
||||
},
|
||||
"StaticFlags": 0
|
||||
},
|
||||
{
|
||||
"ID": "d5c84d67417ddf09908c76b6f0582b43",
|
||||
@@ -51,37 +52,43 @@
|
||||
"ID": "d1a76c334a514c99f8f5b2bd81abae2c",
|
||||
"PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
|
||||
"PrefabObjectID": "a67383834fc3f6f1106e8099e5557e32",
|
||||
"ParentID": "6c66fa4a4a5de8998eb84388d1648317"
|
||||
"ParentID": "6c66fa4a4a5de8998eb84388d1648317",
|
||||
"StaticFlags": 0
|
||||
},
|
||||
{
|
||||
"ID": "357077e9405b2a7ba50198bbed8bd5f9",
|
||||
"PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
|
||||
"PrefabObjectID": "b8fc420f4efe96fa2b4042bd98fd3e74",
|
||||
"ParentID": "d1a76c334a514c99f8f5b2bd81abae2c"
|
||||
"ParentID": "d1a76c334a514c99f8f5b2bd81abae2c",
|
||||
"StaticFlags": 0
|
||||
},
|
||||
{
|
||||
"ID": "905d23324e7f98c9f8287e8e49a83981",
|
||||
"PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
|
||||
"PrefabObjectID": "226bdb004e72848777178a9d1f207cbf",
|
||||
"ParentID": "357077e9405b2a7ba50198bbed8bd5f9"
|
||||
"ParentID": "357077e9405b2a7ba50198bbed8bd5f9",
|
||||
"StaticFlags": 0
|
||||
},
|
||||
{
|
||||
"ID": "89c02cd64b640185d9947ab451453c4c",
|
||||
"PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
|
||||
"PrefabObjectID": "8bd80bca49ac35da66aabaa2e473851d",
|
||||
"ParentID": "6c66fa4a4a5de8998eb84388d1648317"
|
||||
"ParentID": "6c66fa4a4a5de8998eb84388d1648317",
|
||||
"StaticFlags": 0
|
||||
},
|
||||
{
|
||||
"ID": "eebdb91647732ad3dfc7528c978cd19c",
|
||||
"PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
|
||||
"PrefabObjectID": "d9d61d314ad79d49ba08059cef50f802",
|
||||
"ParentID": "6c66fa4a4a5de8998eb84388d1648317"
|
||||
"ParentID": "6c66fa4a4a5de8998eb84388d1648317",
|
||||
"StaticFlags": 0
|
||||
},
|
||||
{
|
||||
"ID": "3e0f83fe407b2d9ed7c734a62fad0826",
|
||||
"PrefabID": "2d0e518b47d735c98312dd87cc42d6d7",
|
||||
"PrefabObjectID": "b377cc03418270d87e8a5b92cb5374ea",
|
||||
"ParentID": "6c66fa4a4a5de8998eb84388d1648317"
|
||||
"ParentID": "6c66fa4a4a5de8998eb84388d1648317",
|
||||
"StaticFlags": 0
|
||||
},
|
||||
{
|
||||
"ID": "ff6b6db54b5aa08e7286ef86246149ef",
|
||||
@@ -128,13 +135,13 @@
|
||||
"Transform": {
|
||||
"Translation": {
|
||||
"X": 0.0,
|
||||
"Y": 735.0,
|
||||
"Y": 730.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
},
|
||||
"Control": "FlaxEngine.GUI.Label",
|
||||
"Data": {
|
||||
"Text": "eFPS: 524\nuFPS: -2147483648\nrFPS: -2147483648\npFPS: -2147483648\nCon: 0ms\nDirectX11\nGC memory: 19.59182MB",
|
||||
"Text": "eFPS: 121\nuFPS: 120\nrFPS: 120\npFPS: 30\nCon: NaNms\nDirectX11\nGC memory: 23.96294MB",
|
||||
"TextColor": {
|
||||
"R": 1.0,
|
||||
"G": 1.0,
|
||||
@@ -221,8 +228,8 @@
|
||||
"Name": "ContainerControl 0",
|
||||
"Transform": {
|
||||
"Translation": {
|
||||
"X": 44861.0,
|
||||
"Y": 1.5,
|
||||
"X": 44793.0,
|
||||
"Y": -1.0,
|
||||
"Z": 0.0
|
||||
}
|
||||
},
|
||||
|
||||
@@ -9,15 +9,21 @@ using Console = Cabrito.Console;
|
||||
|
||||
namespace Game
|
||||
{
|
||||
public class BrushGeometryMesh
|
||||
{
|
||||
public List<Vector3> vertices = new List<Vector3>();
|
||||
public List<uint> indices = new List<uint>();
|
||||
public List<Vector2> uvs = new List<Vector2>();
|
||||
public List<Vector3> normals = new List<Vector3>();
|
||||
public MaterialBase material;
|
||||
}
|
||||
public class BrushGeometry
|
||||
{
|
||||
public MapBrush brush;
|
||||
public Vector3[] vertices;
|
||||
public uint[] indices;
|
||||
public Vector2[] uvs;
|
||||
public Vector3[] normals;
|
||||
public Model model = null;
|
||||
public MaterialBase brushMaterial = null; // FIXME: brush can have multiple textures
|
||||
public Vector3[] vertices; // all vertices
|
||||
public BrushGeometryMesh[] meshes;
|
||||
public Model model;
|
||||
public Dictionary<string, MaterialBase> brushMaterials;
|
||||
}
|
||||
|
||||
public class Q3MapImporter : Script
|
||||
@@ -50,6 +56,9 @@ namespace Game
|
||||
}
|
||||
|
||||
outVertices = finalPoints.ToArray();
|
||||
|
||||
//verts = new QuickHull().QuickHull2(points);
|
||||
//outVertices = verts.ToArray();
|
||||
}
|
||||
|
||||
private MapEntity root;
|
||||
@@ -172,7 +181,31 @@ namespace Game
|
||||
|
||||
if (!oneMesh)
|
||||
{
|
||||
Dictionary<string, MaterialBase> materials = null;
|
||||
Dictionary<string, MaterialBase> materials = new Dictionary<string, MaterialBase>();
|
||||
{
|
||||
BrushMaterialList brushMaterialList = Engine.GetCustomSettings("BrushMaterials")
|
||||
?.CreateInstance<BrushMaterialList>();
|
||||
if (brushMaterialList != null)
|
||||
{
|
||||
foreach (var m in brushMaterialList.materialAssets)
|
||||
materials.Add(m.name, m.asset);
|
||||
Console.Print("materials dictionary with " + materials.Count + " entries");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Print("no materials dictionary found");
|
||||
}
|
||||
|
||||
BrushMaterialList brushMaterialList2 = Engine.GetCustomSettings("BrushMaterialsLegacy")
|
||||
?.CreateInstance<BrushMaterialList>();
|
||||
if (brushMaterialList2 != null)
|
||||
{
|
||||
foreach (var m in brushMaterialList2.materialAssets)
|
||||
materials.Add(m.name, m.asset);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var mapRootActor = Actor.AddChild<Actor>();
|
||||
mapRootActor.Name = "MapRootActor";
|
||||
|
||||
@@ -195,6 +228,29 @@ namespace Game
|
||||
totalverts += geom.vertices.Length;
|
||||
|
||||
Assert.IsTrue(geom.vertices.Length > 0);
|
||||
|
||||
Dictionary<string, MaterialBase> brushMaterials = new Dictionary<string, MaterialBase>();
|
||||
foreach (var brushPlane in geom.brush.planes)
|
||||
{
|
||||
var textureName = brushPlane.texture;
|
||||
if (brushMaterials.ContainsKey(textureName))
|
||||
continue;
|
||||
|
||||
if (!materials.TryGetValue(textureName, out var brushMaterial))
|
||||
{
|
||||
Console.Print("Material '" + textureName + "' not found for brush");
|
||||
materials.Add(textureName, material);
|
||||
brushMaterial = material;
|
||||
}
|
||||
brushMaterials.Add(textureName, brushMaterial);
|
||||
}
|
||||
geom.brushMaterials = brushMaterials;
|
||||
geom.meshes = new BrushGeometryMesh[brushMaterials.Count];
|
||||
for (int i = 0; i < geom.meshes.Length; i++)
|
||||
{
|
||||
geom.meshes[i] = new BrushGeometryMesh();
|
||||
geom.meshes[i].material = geom.brushMaterials[geom.brushMaterials.Keys.ToList()[i]];
|
||||
}
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
@@ -204,52 +260,13 @@ namespace Game
|
||||
brushIndex++;
|
||||
}
|
||||
sw.Stop();
|
||||
Console.Print("Pass 1: triangulation: " + sw.Elapsed.TotalMilliseconds + "ms, total verts: " + totalverts + ", should be 1002");
|
||||
Console.Print("Pass 1: triangulation: " + sw.Elapsed.TotalMilliseconds + "ms");
|
||||
|
||||
// pass 2: texturing
|
||||
sw.Restart();
|
||||
foreach (var geom in brushGeometries)
|
||||
{
|
||||
var brushVertices = geom.vertices;
|
||||
Vector2[] brushUvs = new Vector2[brushVertices.Length];
|
||||
Vector3[] brushNormals = new Vector3[brushVertices.Length];
|
||||
|
||||
var textureName = geom.brush.planes[0].texture;
|
||||
|
||||
if (materials == null)
|
||||
{
|
||||
materials = new Dictionary<string, MaterialBase>();
|
||||
|
||||
BrushMaterialList brushMaterialList = Engine.GetCustomSettings("BrushMaterials")
|
||||
?.CreateInstance<BrushMaterialList>();
|
||||
if (brushMaterialList != null)
|
||||
{
|
||||
foreach (var m in brushMaterialList.materialAssets)
|
||||
materials.Add(m.name, m.asset);
|
||||
Console.Print("materials dictionary with " + materials.Count + " entries");
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Print("no materials dictionary found");
|
||||
}
|
||||
|
||||
BrushMaterialList brushMaterialList2 = Engine.GetCustomSettings("BrushMaterialsLegacy")
|
||||
?.CreateInstance<BrushMaterialList>();
|
||||
if (brushMaterialList2 != null)
|
||||
{
|
||||
foreach (var m in brushMaterialList2.materialAssets)
|
||||
materials.Add(m.name, m.asset);
|
||||
}
|
||||
}
|
||||
|
||||
// FIXME: brush can have multiple textures
|
||||
if (!materials.TryGetValue(textureName, out geom.brushMaterial))
|
||||
{
|
||||
Console.Print("Material '" + textureName + "' not found for brush");
|
||||
materials.Add(textureName, material);
|
||||
geom.brushMaterial = material;
|
||||
}
|
||||
|
||||
for (int i = 0; i < brushVertices.Length; i += 3)
|
||||
{
|
||||
Vector3 v1 = brushVertices[i + 0];
|
||||
@@ -263,6 +280,7 @@ namespace Game
|
||||
float uvRotation = 0f;
|
||||
Vector2 uvOffset = new Vector2(0f);
|
||||
bool found = false;
|
||||
int meshIndex = 0;
|
||||
foreach (var brushPlane in geom.brush.planes)
|
||||
{
|
||||
if ((brushPlane.plane.Normal - normal).Length < 0.01f)
|
||||
@@ -272,6 +290,7 @@ namespace Game
|
||||
uvRotation = brushPlane.rotation;
|
||||
uvOffset = brushPlane.offset * brushPlane.scale;
|
||||
found = true;
|
||||
meshIndex = geom.brushMaterials.Keys.ToList().IndexOf(brushPlane.texture); // ugh?
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -326,29 +345,39 @@ namespace Game
|
||||
uv2 = ((Vector2)(v2 * rot) + uvOffset) * uvScale;
|
||||
uv3 = ((Vector2)(v3 * rot) + uvOffset) * uvScale;
|
||||
}
|
||||
var mesh = geom.meshes[meshIndex];
|
||||
|
||||
brushUvs[i + 0] = uv1;
|
||||
brushUvs[i + 1] = uv2;
|
||||
brushUvs[i + 2] = uv3;
|
||||
mesh.indices.Add((uint)mesh.vertices.Count+0);
|
||||
mesh.indices.Add((uint)mesh.vertices.Count+1);
|
||||
mesh.indices.Add((uint)mesh.vertices.Count+2);
|
||||
|
||||
brushNormals[i + 0] = normal;
|
||||
brushNormals[i + 1] = normal;
|
||||
brushNormals[i + 2] = normal;
|
||||
mesh.vertices.Add(v1);
|
||||
mesh.vertices.Add(v2);
|
||||
mesh.vertices.Add(v3);
|
||||
|
||||
mesh.uvs.Add(uv1);
|
||||
mesh.uvs.Add(uv2);
|
||||
mesh.uvs.Add(uv3);
|
||||
|
||||
mesh.normals.Add(normal);
|
||||
mesh.normals.Add(normal);
|
||||
mesh.normals.Add(normal);
|
||||
}
|
||||
|
||||
geom.vertices = brushVertices;
|
||||
geom.uvs = brushUvs;
|
||||
geom.normals = brushNormals;
|
||||
geom.indices = new uint[geom.vertices.Length];
|
||||
for (uint i = 0; i < geom.vertices.Length; i++)
|
||||
geom.indices[i] = i;
|
||||
geom.model = Content.CreateVirtualAsset<Model>();
|
||||
geom.model.SetupLODs(new int[] { geom.meshes.Length });
|
||||
geom.model.SetupMaterialSlots(geom.meshes.Length);
|
||||
|
||||
if (geom.vertices.Length > 0)
|
||||
for (int i=0; i<geom.meshes.Length; i++)
|
||||
{
|
||||
geom.model = Content.CreateVirtualAsset<Model>();
|
||||
geom.model.SetupLODs(new int[] { 1 });
|
||||
geom.model.LODs[0].Meshes[0].UpdateMesh(geom.vertices, geom.indices, geom.normals,
|
||||
null, geom.uvs);
|
||||
var mesh = geom.meshes[i];
|
||||
if (mesh.vertices.Count == 0)
|
||||
continue;
|
||||
|
||||
geom.model.LODs[0].Meshes[i].UpdateMesh(mesh.vertices, mesh.indices, mesh.normals,
|
||||
null, mesh.uvs);
|
||||
geom.model.LODs[0].Meshes[i].MaterialSlotIndex = i;
|
||||
geom.model.MaterialSlots[i].Material = geom.meshes[i].material;
|
||||
}
|
||||
}
|
||||
sw.Stop();
|
||||
@@ -361,13 +390,19 @@ namespace Game
|
||||
{
|
||||
StaticModel childModel = Actor.AddChild<StaticModel>();
|
||||
childModel.Name = "Brush_" + brushIndex;
|
||||
childModel.Model = geom.model;
|
||||
childModel.SetMaterial(0, geom.brushMaterial);
|
||||
childModel.Parent = mapRootActor;
|
||||
childModel.Model = geom.model;
|
||||
|
||||
for (int i = 0; i < geom.meshes.Length; i++)
|
||||
childModel.SetMaterial(i, geom.meshes[i].material);
|
||||
|
||||
uint[] indices = new uint[geom.vertices.Length];
|
||||
for (uint i = 0; i < indices.Length; i++)
|
||||
indices[i] = i;
|
||||
|
||||
CollisionData collisionData = Content.CreateVirtualAsset<CollisionData>();
|
||||
if (collisionData.CookCollision(convexMesh ? CollisionDataType.ConvexMesh : CollisionDataType.TriangleMesh, geom.vertices,
|
||||
geom.indices))
|
||||
indices))
|
||||
{
|
||||
bool failed = true;
|
||||
if (convexMesh)
|
||||
@@ -375,7 +410,7 @@ namespace Game
|
||||
// fallback to triangle mesh
|
||||
failed = collisionData.CookCollision(CollisionDataType.TriangleMesh,
|
||||
geom.vertices,
|
||||
geom.indices);
|
||||
indices);
|
||||
if (!failed)
|
||||
Console.PrintWarning("Hull brush " + brushIndex.ToString() + " is not convex");
|
||||
}
|
||||
@@ -396,6 +431,7 @@ namespace Game
|
||||
List<Vector2> uvs = new List<Vector2>();
|
||||
List<Vector3> normals = new List<Vector3>();
|
||||
|
||||
sw.Restart();
|
||||
int brushIndex = 0;
|
||||
foreach (var brush in root.entities[0].brushes)
|
||||
{
|
||||
@@ -501,7 +537,10 @@ namespace Game
|
||||
|
||||
brushIndex++;
|
||||
}
|
||||
sw.Stop();
|
||||
Console.Print("Pass 1: triangulation and texturing: " + sw.Elapsed.TotalMilliseconds + "ms");
|
||||
|
||||
sw.Restart();
|
||||
if (vertices.Count > 0)
|
||||
{
|
||||
uint[] triangles = new uint[vertices.Count];
|
||||
@@ -525,6 +564,8 @@ namespace Game
|
||||
var meshCollider = childModel.AddChild<MeshCollider>();
|
||||
meshCollider.CollisionData = collisionData;
|
||||
}
|
||||
sw.Stop();
|
||||
Console.Print("Pass 2: model and collision: " + sw.Elapsed.TotalMilliseconds + "ms");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user