You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

89 lines
3.5 KiB

using UnityEngine;
public partial class RenderModule
{
private readonly UniQuake uq;
public RenderModule(UniQuake uniQuake)
{
uq = uniQuake;
BuildCallbacks();
}
private float xPos = -8f;
private int UploadAliasModel(string name, QVec3 boundsMin, QVec3 boundsMax, QAliasHeader header,
QTriVertex[][] poseVertices, QTriangle[] triangles, QSTVert[] stVertices)
{
Debug.Log($"Alias model '{name}' with {header.numVerts} vertices, {header.numTriangles} triangles, {header.numFrames} frame(s)");
// TODO: convert Quake poses into Mesh blend shapes with AddBlendShapeFrame
ConvertVertices(poseVertices[0], boundsMin.ToVector3(), boundsMax.ToVector3(), out var vertices, out var normals);
ConvertTriangles(triangles, out var indices);
ConvertUVs(stVertices, header.skinWidth, header.skinHeight, out var uvs);
var mesh = new Mesh { name = name };
mesh.SetVertices(vertices);
mesh.SetNormals(normals);
mesh.SetIndices(indices, MeshTopology.Triangles, 0);
mesh.SetUVs(0, uvs);
mesh.Optimize(); // This ensures that triangles will be properly fused and organized in the best possible way
mesh.UploadMeshData(true);
var go = new GameObject(System.IO.Path.GetFileNameWithoutExtension(name));
go.transform.SetPositionAndRotation(new Vector3(xPos, 0, 0), Quaternion.Euler(-90, 90, 0));
go.transform.localScale = Vector3.one * 0.01f;
var mf = go.AddComponent<MeshFilter>();
mf.sharedMesh = mesh;
var mr = go.AddComponent<MeshRenderer>();
mr.material = new Material(Shader.Find("Universal Render Pipeline/Simple Lit"));
xPos += 1f;
return 1;
}
private static void ConvertVertices(QTriVertex[] triVerts, Vector3 boundsMin, Vector3 boundsMax, out Vector3[] vertices, out Vector3[] normals)
{
int numVerts = triVerts.Length;
vertices = new Vector3[numVerts];
normals = new Vector3[numVerts];
for (int i = 0; i < numVerts; ++i)
{
byte[] v = triVerts[i].v;
Vector3 vec = new Vector3(v[0] / 255f, v[1] / 255f, v[2] / 255f);
vertices[i] = boundsMin + Vector3.Scale(boundsMax - boundsMin, vec);
normals[i] = QLightNormals.Get(triVerts[i].lightNormalIndex);
}
}
private static void ConvertTriangles(QTriangle[] triangles, out ushort[] indices)
{
int numTris = triangles.Length;
indices = new ushort[numTris * 3];
for (int i = 0; i < numTris; ++i)
{
indices[i * 3 + 0] = (ushort)triangles[i].vertIndex[2];
indices[i * 3 + 1] = (ushort)triangles[i].vertIndex[1];
indices[i * 3 + 2] = (ushort)triangles[i].vertIndex[0];
}
}
private static void ConvertUVs(QSTVert[] stVerts, int skinWidth, int skinHeight, out Vector2[] uvs)
{
int numVerts = stVerts.Length;
uvs = new Vector2[numVerts];
// TODO FIXME: this only works correctly for the front side of a model.
// To also correctly UV the back side, we need to duplicate vertices on the back/front seam,
// and add half the skin width to UVs that are on back side vertices.
Vector2 scale = new Vector2(1.0f / skinWidth, 1.0f / skinHeight);
for (int i = 0; i < numVerts; ++i)
{
uvs[i] = Vector2.Scale(new Vector2(stVerts[i].s, skinHeight - stVerts[i].t), scale);
}
}
}