multiple materials

This commit is contained in:
GoaLitiuM
2021-08-31 20:03:37 +03:00
parent 1d2fc767e3
commit 4e2b122257
3 changed files with 136 additions and 79 deletions

View File

@@ -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
{

View File

@@ -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
}
},

View File

@@ -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");
}
}