Files
UltimateFishing/Assets/Scripts/Assembly-CSharp/ONSPPropagationGeometry.cs
2026-02-21 16:45:37 +08:00

387 lines
11 KiB
C#

using System;
using System.Collections.Generic;
using Oculus.Spatializer.Propagation;
using UnityEngine;
public class ONSPPropagationGeometry : MonoBehaviour
{
private struct MeshMaterial
{
public MeshFilter meshFilter;
public ONSPPropagationMaterial[] materials;
}
private struct TerrainMaterial
{
public Terrain terrain;
public ONSPPropagationMaterial[] materials;
}
public static string GeometryAssetDirectory = "AudioGeometry";
public string filePathRelative = string.Empty;
public bool fileEnabled;
public bool includeChildMeshes = true;
private IntPtr geometryHandle = IntPtr.Zero;
public static int OSPSuccess;
private static int terrainDecimation = 4;
public static string GeometryAssetPath
{
get
{
return Application.streamingAssetsPath + "/" + GeometryAssetDirectory;
}
}
public string filePath
{
get
{
return GeometryAssetPath + "/" + filePathRelative;
}
}
public static string GetPath(Transform current)
{
if (current.parent == null)
{
return current.gameObject.scene.name + "/" + current.name;
}
return GetPath(current.parent) + "-" + current.name;
}
private void Awake()
{
CreatePropagationGeometry();
}
private void CreatePropagationGeometry()
{
if (ONSPPropagation.Interface.CreateAudioGeometry(out geometryHandle) != OSPSuccess)
{
throw new Exception("Unable to create geometry handle");
}
if (filePath != null && filePath.Length != 0 && fileEnabled && Application.isPlaying)
{
if (!ReadFile())
{
Debug.LogError("Failed to read file, attempting to regenerate audio geometry");
UploadGeometry();
}
}
else
{
UploadGeometry();
}
}
private void Update()
{
if (!(geometryHandle == IntPtr.Zero))
{
Matrix4x4 localToWorldMatrix = base.transform.localToWorldMatrix;
float[] matrix4x = new float[16]
{
localToWorldMatrix[0, 0],
localToWorldMatrix[1, 0],
0f - localToWorldMatrix[2, 0],
localToWorldMatrix[3, 0],
localToWorldMatrix[0, 1],
localToWorldMatrix[1, 1],
0f - localToWorldMatrix[2, 1],
localToWorldMatrix[3, 1],
localToWorldMatrix[0, 2],
localToWorldMatrix[1, 2],
0f - localToWorldMatrix[2, 2],
localToWorldMatrix[3, 2],
localToWorldMatrix[0, 3],
localToWorldMatrix[1, 3],
0f - localToWorldMatrix[2, 3],
localToWorldMatrix[3, 3]
};
ONSPPropagation.Interface.AudioGeometrySetTransform(geometryHandle, matrix4x);
}
}
private void OnDestroy()
{
if (geometryHandle != IntPtr.Zero && ONSPPropagation.Interface.DestroyAudioGeometry(geometryHandle) != OSPSuccess)
{
throw new Exception("Unable to destroy geometry");
}
geometryHandle = IntPtr.Zero;
}
private static void traverseMeshHierarchy(GameObject obj, ONSPPropagationMaterial[] currentMaterials, bool includeChildren, List<MeshMaterial> meshMaterials, List<TerrainMaterial> terrainMaterials, bool ignoreStatic)
{
if (!obj.activeInHierarchy)
{
return;
}
MeshFilter[] components = obj.GetComponents<MeshFilter>();
Terrain[] components2 = obj.GetComponents<Terrain>();
ONSPPropagationMaterial[] components3 = obj.GetComponents<ONSPPropagationMaterial>();
if (components3 != null && components3.Length > 0)
{
int num = components3.Length;
if (currentMaterials != null)
{
num = Math.Max(num, currentMaterials.Length);
}
ONSPPropagationMaterial[] array = new ONSPPropagationMaterial[num];
if (currentMaterials != null)
{
for (int i = components3.Length; i < num; i++)
{
array[i] = currentMaterials[i];
}
}
currentMaterials = array;
for (int j = 0; j < components3.Length; j++)
{
currentMaterials[j] = components3[j];
}
}
MeshFilter[] array2 = components;
foreach (MeshFilter meshFilter in array2)
{
Mesh sharedMesh = meshFilter.sharedMesh;
if (!(sharedMesh == null))
{
if (ignoreStatic && !sharedMesh.isReadable)
{
Debug.Log("Mesh: " + meshFilter.gameObject.name + " not readable, cannot be static.");
continue;
}
meshMaterials.Add(new MeshMaterial
{
meshFilter = meshFilter,
materials = currentMaterials
});
}
}
Terrain[] array3 = components2;
foreach (Terrain terrain in array3)
{
terrainMaterials.Add(new TerrainMaterial
{
terrain = terrain,
materials = currentMaterials
});
}
if (!includeChildren)
{
return;
}
foreach (Transform item in obj.transform)
{
if (item.GetComponent<ONSPPropagationGeometry>() == null)
{
traverseMeshHierarchy(item.gameObject, currentMaterials, includeChildren, meshMaterials, terrainMaterials, ignoreStatic);
}
}
}
private int uploadMesh(IntPtr geometryHandle, GameObject meshObject, Matrix4x4 worldToLocal, bool ignoreStatic)
{
List<MeshMaterial> list = new List<MeshMaterial>();
List<TerrainMaterial> list2 = new List<TerrainMaterial>();
traverseMeshHierarchy(meshObject, null, includeChildMeshes, list, list2, ignoreStatic);
int num = 0;
uint num2 = 0u;
int num3 = 0;
int num4 = 0;
foreach (MeshMaterial item in list)
{
Mesh sharedMesh = item.meshFilter.sharedMesh;
num4 += sharedMesh.subMeshCount;
num += sharedMesh.vertexCount;
for (int i = 0; i < sharedMesh.subMeshCount; i++)
{
MeshTopology topology = sharedMesh.GetTopology(i);
if (topology == MeshTopology.Triangles || topology == MeshTopology.Quads)
{
uint indexCount = sharedMesh.GetIndexCount(i);
num2 += indexCount;
switch (topology)
{
case MeshTopology.Triangles:
num3 += (int)indexCount / 3;
break;
case MeshTopology.Quads:
num3 += (int)indexCount / 4;
break;
}
}
}
}
foreach (TerrainMaterial item2 in list2)
{
TerrainData terrainData = item2.terrain.terrainData;
int heightmapWidth = terrainData.heightmapWidth;
int heightmapHeight = terrainData.heightmapHeight;
int num5 = (heightmapWidth - 1) / terrainDecimation + 1;
int num6 = (heightmapHeight - 1) / terrainDecimation + 1;
int num7 = num5 * num6;
int num8 = (num5 - 1) * (num6 - 1) * 6;
num4++;
num += num7;
num2 += (uint)num8;
num3 += num8 / 3;
}
List<Vector3> list3 = new List<Vector3>();
List<int> list4 = new List<int>();
MeshGroup[] array = new MeshGroup[num4];
float[] array2 = new float[num * 3];
int[] array3 = new int[num2];
int num9 = 0;
int num10 = 0;
int num11 = 0;
foreach (MeshMaterial item3 in list)
{
MeshFilter meshFilter = item3.meshFilter;
Mesh sharedMesh2 = meshFilter.sharedMesh;
Matrix4x4 matrix4x = worldToLocal * meshFilter.gameObject.transform.localToWorldMatrix;
list3.Clear();
sharedMesh2.GetVertices(list3);
int count = list3.Count;
for (int j = 0; j < count; j++)
{
Vector3 vector = matrix4x.MultiplyPoint3x4(list3[j]);
int num12 = (num9 + j) * 3;
array2[num12] = vector.x;
array2[num12 + 1] = vector.y;
array2[num12 + 2] = vector.z;
}
for (int k = 0; k < sharedMesh2.subMeshCount; k++)
{
MeshTopology topology2 = sharedMesh2.GetTopology(k);
if (topology2 != MeshTopology.Triangles && topology2 != MeshTopology.Quads)
{
continue;
}
list4.Clear();
sharedMesh2.GetIndices(list4, k);
int count2 = list4.Count;
for (int l = 0; l < count2; l++)
{
array3[num10 + l] = list4[l] + num9;
}
switch (topology2)
{
case MeshTopology.Triangles:
array[num11 + k].faceType = FaceType.TRIANGLES;
array[num11 + k].faceCount = (UIntPtr)(ulong)(count2 / 3);
break;
case MeshTopology.Quads:
array[num11 + k].faceType = FaceType.QUADS;
array[num11 + k].faceCount = (UIntPtr)(ulong)(count2 / 4);
break;
}
array[num11 + k].indexOffset = (UIntPtr)(ulong)num10;
if (item3.materials != null && item3.materials.Length != 0)
{
int num13 = k;
if (num13 >= item3.materials.Length)
{
num13 = item3.materials.Length - 1;
}
item3.materials[num13].StartInternal();
array[num11 + k].material = item3.materials[num13].materialHandle;
}
else
{
array[num11 + k].material = IntPtr.Zero;
}
num10 += count2;
}
num9 += count;
num11 += sharedMesh2.subMeshCount;
}
foreach (TerrainMaterial item4 in list2)
{
TerrainData terrainData2 = item4.terrain.terrainData;
Matrix4x4 matrix4x2 = worldToLocal * item4.terrain.gameObject.transform.localToWorldMatrix;
int heightmapWidth2 = terrainData2.heightmapWidth;
int heightmapHeight2 = terrainData2.heightmapHeight;
float[,] heights = terrainData2.GetHeights(0, 0, heightmapWidth2, heightmapHeight2);
Vector3 size = terrainData2.size;
size = new Vector3(size.x / (float)(heightmapWidth2 - 1) * (float)terrainDecimation, size.y, size.z / (float)(heightmapHeight2 - 1) * (float)terrainDecimation);
int num14 = (heightmapWidth2 - 1) / terrainDecimation + 1;
int num15 = (heightmapHeight2 - 1) / terrainDecimation + 1;
int num16 = num14 * num15;
int num17 = (num14 - 1) * (num15 - 1) * 2;
array[num11].faceType = FaceType.TRIANGLES;
array[num11].faceCount = (UIntPtr)(ulong)num17;
array[num11].indexOffset = (UIntPtr)(ulong)num10;
if (item4.materials != null && 0 < item4.materials.Length)
{
item4.materials[0].StartInternal();
array[num11].material = item4.materials[0].materialHandle;
}
else
{
array[num11].material = IntPtr.Zero;
}
for (int m = 0; m < num15; m++)
{
for (int n = 0; n < num14; n++)
{
int num18 = (num9 + m * num14 + n) * 3;
Vector3 vector2 = matrix4x2.MultiplyPoint3x4(Vector3.Scale(size, new Vector3(m, heights[n * terrainDecimation, m * terrainDecimation], n)));
array2[num18] = vector2.x;
array2[num18 + 1] = vector2.y;
array2[num18 + 2] = vector2.z;
}
}
for (int num19 = 0; num19 < num15 - 1; num19++)
{
for (int num20 = 0; num20 < num14 - 1; num20++)
{
array3[num10] = num9 + num19 * num14 + num20;
array3[num10 + 1] = num9 + (num19 + 1) * num14 + num20;
array3[num10 + 2] = num9 + num19 * num14 + num20 + 1;
array3[num10 + 3] = num9 + (num19 + 1) * num14 + num20;
array3[num10 + 4] = num9 + (num19 + 1) * num14 + num20 + 1;
array3[num10 + 5] = num9 + num19 * num14 + num20 + 1;
num10 += 6;
}
}
num9 += num16;
num11++;
}
return ONSPPropagation.Interface.AudioGeometryUploadMeshArrays(geometryHandle, array2, num, array3, array3.Length, array, array.Length);
}
public void UploadGeometry()
{
if (uploadMesh(geometryHandle, base.gameObject, base.gameObject.transform.worldToLocalMatrix, true) != OSPSuccess)
{
throw new Exception("Unable to upload audio mesh geometry");
}
}
public bool ReadFile()
{
if (filePath == null || filePath.Length == 0)
{
Debug.LogError("Invalid mesh file path");
return false;
}
if (ONSPPropagation.Interface.AudioGeometryReadMeshFile(geometryHandle, filePath) != OSPSuccess)
{
Debug.LogError("Error reading mesh file " + filePath);
return false;
}
return true;
}
}