Browse Source
Reconstruct brush model data based on glpoly_t data generated by GLQuake. We can now successfully display BSP maps in Unity!
console
Reconstruct brush model data based on glpoly_t data generated by GLQuake. We can now successfully display BSP maps in Unity!
console
7 changed files with 139 additions and 43 deletions
-
5Assets/Scripts/Data/QExtensions.cs
-
7Assets/Scripts/Data/QMath.cs
-
75Assets/Scripts/Data/QModel.cs
-
81Assets/Scripts/Modules/BrushModel.cs
-
3Assets/Scripts/Modules/BrushModel.cs.meta
-
5Assets/Scripts/Modules/RenderModule.Interop.cs
-
4Assets/Scripts/Modules/RenderModule.cs
@ -0,0 +1,81 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
using UnityEngine; |
||||
|
using UnityEngine.Rendering; |
||||
|
|
||||
|
public class BrushModel |
||||
|
{ |
||||
|
private readonly string name; |
||||
|
private readonly List<Mesh> meshes = new List<Mesh>(); |
||||
|
|
||||
|
public BrushModel(string name) |
||||
|
{ |
||||
|
this.name = name; |
||||
|
} |
||||
|
|
||||
|
public void ImportMeshData(QModel model, QSurface[] surfaces) |
||||
|
{ |
||||
|
List<Vector3> vertices = new List<Vector3>(); |
||||
|
List<Vector2> textureUVs = new List<Vector2>(); |
||||
|
List<Vector2> lightmapUVs = new List<Vector2>(); |
||||
|
List<ushort> indices = new List<ushort>(); |
||||
|
|
||||
|
for (int surfIdx = 0; surfIdx < surfaces.Length; ++surfIdx) |
||||
|
{ |
||||
|
foreach (var polyVerts in surfaces[surfIdx].GetPolygons()) |
||||
|
{ |
||||
|
vertices.Clear(); |
||||
|
textureUVs.Clear(); |
||||
|
lightmapUVs.Clear(); |
||||
|
indices.Clear(); |
||||
|
|
||||
|
for (int vertIdx = 0; vertIdx < polyVerts.Length; ++vertIdx) |
||||
|
{ |
||||
|
vertices.Add(polyVerts[vertIdx].position.ToVector3()); |
||||
|
textureUVs.Add(polyVerts[vertIdx].textureUV.ToVector2()); |
||||
|
lightmapUVs.Add(polyVerts[vertIdx].lightmapUV.ToVector2()); |
||||
|
} |
||||
|
|
||||
|
// Reconstruct triangle fan (in reverse order)
|
||||
|
for (ushort index = 2; index < polyVerts.Length; ++index) |
||||
|
{ |
||||
|
indices.Add(index); |
||||
|
indices.Add((ushort)(index - 1)); |
||||
|
indices.Add(0); |
||||
|
} |
||||
|
|
||||
|
Mesh mesh = new Mesh(); |
||||
|
mesh.SetVertices(vertices); |
||||
|
mesh.SetUVs(0, textureUVs); |
||||
|
mesh.SetUVs(1, lightmapUVs); |
||||
|
mesh.SetIndices(indices, MeshTopology.Triangles, 0); |
||||
|
mesh.RecalculateNormals(); |
||||
|
mesh.UploadMeshData(true); |
||||
|
meshes.Add(mesh); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
// DEBUG
|
||||
|
var go = new GameObject(name); |
||||
|
var mat = new Material(Shader.Find("Universal Render Pipeline/Simple Lit")); |
||||
|
|
||||
|
for (int i = 0; i < meshes.Count; ++i) |
||||
|
{ |
||||
|
var mesh = meshes[i]; |
||||
|
|
||||
|
var meshGO = new GameObject($"Surface_{i}"); |
||||
|
meshGO.transform.SetParent(go.transform); |
||||
|
|
||||
|
var mf = meshGO.AddComponent<MeshFilter>(); |
||||
|
mf.sharedMesh = mesh; |
||||
|
|
||||
|
var mr = meshGO.AddComponent<MeshRenderer>(); |
||||
|
mr.sharedMaterial = mat; |
||||
|
mr.shadowCastingMode = ShadowCastingMode.Off; |
||||
|
mr.receiveShadows = false; |
||||
|
mr.lightProbeUsage = LightProbeUsage.Off; |
||||
|
mr.reflectionProbeUsage = ReflectionProbeUsage.Off; |
||||
|
} |
||||
|
|
||||
|
go.transform.SetPositionAndRotation(Vector3.zero, Quaternion.Euler(-90, 90, 0)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,3 @@ |
|||||
|
fileFormatVersion: 2 |
||||
|
guid: 20d063dc6801478691510afa943bc87e |
||||
|
timeCreated: 1619358727 |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue