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

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