Files
UltimateFishing2020/Assets/Scripts/Assembly-CSharp/Gaia/Scanner.cs
2026-03-04 10:03:45 +08:00

318 lines
11 KiB
C#

using System;
using System.IO;
using UnityEngine;
namespace Gaia
{
public class Scanner : MonoBehaviour
{
[Tooltip("The name of the stamp as it will be stored in the project. Initally based on the file name.")]
public string m_featureName = $"{DateTime.Now}";
[Tooltip("The type of stamp, also controls which directory the stamp will be loaded into.")]
public GaiaConstants.FeatureType m_featureType = GaiaConstants.FeatureType.Mountains;
[Range(0f, 1f)]
[Tooltip("Base level for this stamp, used by stamper to cut off all heights below the base. It is the highest point of the stamp around its edges.")]
public float m_baseLevel;
[HideInInspector]
[Range(0.1f, 1f)]
[Tooltip("Scan resolution in meters. Leave this at smaller values for higher quality scans.")]
public float m_scanResolution = 0.1f;
[Tooltip("The material that will be used to display the scan preview. This is just for visualisation and will not affect the scan.")]
public Material m_previewMaterial;
private HeightMap m_scanMap;
private Bounds m_scanBounds;
private int m_scanWidth = 1;
private int m_scanDepth = 1;
private int m_scanHeight = 500;
private Vector3 m_groundOffset = Vector3.zero;
private Vector3 m_groundSize = Vector3.zero;
private void OnEnable()
{
MeshFilter meshFilter = GetComponent<MeshFilter>();
if (meshFilter == null)
{
meshFilter = base.gameObject.AddComponent<MeshFilter>();
}
meshFilter.hideFlags = HideFlags.HideInInspector;
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
meshRenderer = base.gameObject.AddComponent<MeshRenderer>();
}
meshRenderer.hideFlags = HideFlags.HideInInspector;
}
private void Awake()
{
base.gameObject.SetActive(value: false);
}
public void Reset()
{
m_featureName = "";
m_scanMap = null;
m_scanBounds = new Bounds(base.transform.position, Vector3.one * 10f);
m_scanWidth = (m_scanDepth = (m_scanHeight = 0));
m_scanResolution = 0.1f;
m_baseLevel = 0f;
base.transform.localRotation = Quaternion.identity;
base.transform.localScale = Vector3.one;
}
public void LoadRawFile(string path, GaiaConstants.RawByteOrder byteOrder, ref GaiaConstants.RawBitDepth bitDepth, ref int resolution)
{
if (string.IsNullOrEmpty(path))
{
Debug.LogError("Must supply a valid path. Raw load Aborted!");
}
Reset();
m_featureName = Path.GetFileNameWithoutExtension(path);
m_scanMap = new HeightMap();
m_scanMap.LoadFromRawFile(path, byteOrder, ref bitDepth, ref resolution);
if (!m_scanMap.HasData())
{
Debug.LogError("Unable to load raw file. Raw load aborted.");
return;
}
m_scanWidth = m_scanMap.Width();
m_scanDepth = m_scanMap.Depth();
m_scanHeight = m_scanWidth / 2;
m_scanResolution = 0.1f;
m_scanBounds = new Bounds(base.transform.position, new Vector3((float)m_scanWidth * m_scanResolution, (float)m_scanWidth * m_scanResolution * 0.4f, (float)m_scanDepth * m_scanResolution));
m_baseLevel = m_scanMap.GetBaseLevel();
MeshFilter meshFilter = GetComponent<MeshFilter>();
if (meshFilter == null)
{
meshFilter = base.gameObject.AddComponent<MeshFilter>();
meshFilter.hideFlags = HideFlags.HideInInspector;
}
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
meshRenderer = base.gameObject.AddComponent<MeshRenderer>();
meshRenderer.hideFlags = HideFlags.HideInInspector;
}
meshFilter.mesh = GaiaUtils.CreateMesh(m_scanMap.Heights(), m_scanBounds.size);
if (m_previewMaterial != null)
{
m_previewMaterial.hideFlags = HideFlags.HideInInspector;
meshRenderer.sharedMaterial = m_previewMaterial;
}
}
public void LoadTextureFile(Texture2D texture)
{
if (texture == null)
{
Debug.LogError("Must supply a valid texture! Texture load aborted.");
return;
}
Reset();
m_featureName = texture.name;
m_scanMap = new UnityHeightMap(texture);
if (!m_scanMap.HasData())
{
Debug.LogError("Unable to load Texture file. Texture load aborted.");
return;
}
m_scanWidth = m_scanMap.Width();
m_scanDepth = m_scanMap.Depth();
m_scanHeight = m_scanWidth / 2;
m_scanResolution = 0.1f;
m_scanBounds = new Bounds(base.transform.position, new Vector3((float)m_scanWidth * m_scanResolution, (float)m_scanWidth * m_scanResolution * 0.4f, (float)m_scanDepth * m_scanResolution));
m_baseLevel = m_scanMap.GetBaseLevel();
MeshFilter meshFilter = GetComponent<MeshFilter>();
if (meshFilter == null)
{
meshFilter = base.gameObject.AddComponent<MeshFilter>();
meshFilter.hideFlags = HideFlags.HideInInspector;
}
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
meshRenderer = base.gameObject.AddComponent<MeshRenderer>();
meshRenderer.hideFlags = HideFlags.HideInInspector;
}
meshFilter.mesh = GaiaUtils.CreateMesh(m_scanMap.Heights(), m_scanBounds.size);
if (m_previewMaterial != null)
{
m_previewMaterial.hideFlags = HideFlags.HideInInspector;
meshRenderer.sharedMaterial = m_previewMaterial;
}
}
public void LoadTerain(Terrain terrain)
{
if (terrain == null)
{
Debug.LogError("Must supply a valid terrain! Terrain load aborted.");
return;
}
Reset();
m_featureName = terrain.name;
m_scanMap = new UnityHeightMap(terrain);
if (!m_scanMap.HasData())
{
Debug.LogError("Unable to load terrain file. Terrain load aborted.");
return;
}
m_scanMap.Flip();
m_scanWidth = m_scanMap.Width();
m_scanDepth = m_scanMap.Depth();
m_scanHeight = (int)terrain.terrainData.size.y;
m_scanResolution = 0.1f;
m_scanBounds = new Bounds(base.transform.position, new Vector3((float)m_scanWidth * m_scanResolution, (float)m_scanWidth * m_scanResolution * 0.4f, (float)m_scanDepth * m_scanResolution));
m_baseLevel = m_scanMap.GetBaseLevel();
MeshFilter meshFilter = GetComponent<MeshFilter>();
if (meshFilter == null)
{
meshFilter = base.gameObject.AddComponent<MeshFilter>();
meshFilter.hideFlags = HideFlags.HideInInspector;
}
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
meshRenderer = base.gameObject.AddComponent<MeshRenderer>();
meshRenderer.hideFlags = HideFlags.HideInInspector;
}
meshFilter.mesh = GaiaUtils.CreateMesh(m_scanMap.Heights(), m_scanBounds.size);
if (m_previewMaterial != null)
{
m_previewMaterial.hideFlags = HideFlags.HideInInspector;
meshRenderer.sharedMaterial = m_previewMaterial;
}
}
public void LoadGameObject(GameObject go)
{
if (go == null)
{
Debug.LogError("Must supply a valid game object! GameObject load aborted.");
return;
}
Reset();
m_featureName = go.name;
GameObject gameObject = UnityEngine.Object.Instantiate(go);
gameObject.transform.position = base.transform.position;
gameObject.transform.localRotation = Quaternion.identity;
gameObject.transform.localScale = Vector3.one;
Collider[] componentsInChildren = gameObject.GetComponentsInChildren<Collider>();
for (int i = 0; i < componentsInChildren.Length; i++)
{
UnityEngine.Object.DestroyImmediate(componentsInChildren[i]);
}
Transform[] componentsInChildren2 = gameObject.GetComponentsInChildren<Transform>();
foreach (Transform transform in componentsInChildren2)
{
if (transform.gameObject.activeSelf)
{
transform.gameObject.AddComponent<MeshCollider>();
}
}
m_scanBounds.center = gameObject.transform.position;
m_scanBounds.size = Vector3.zero;
MeshCollider[] componentsInChildren3 = gameObject.GetComponentsInChildren<MeshCollider>();
foreach (MeshCollider meshCollider in componentsInChildren3)
{
m_scanBounds.Encapsulate(meshCollider.bounds);
}
m_scanWidth = (int)Mathf.Ceil(m_scanBounds.size.x * (1f / m_scanResolution));
m_scanHeight = (int)Mathf.Ceil(m_scanBounds.size.y * (1f / m_scanResolution));
m_scanDepth = (int)Mathf.Ceil(m_scanBounds.size.z * (1f / m_scanResolution));
m_scanMap = new HeightMap(m_scanWidth, m_scanDepth);
Vector3 min = m_scanBounds.min;
Vector3 origin = min;
origin.y = m_scanBounds.max.y;
for (int j = 0; j < m_scanWidth; j++)
{
origin.x = min.x + m_scanResolution * (float)j;
for (int k = 0; k < m_scanDepth; k++)
{
origin.z = min.z + m_scanResolution * (float)k;
if (Physics.Raycast(origin, Vector3.down, out var hitInfo, m_scanBounds.size.y))
{
m_scanMap[j, k] = 1f - hitInfo.distance / m_scanBounds.size.y;
}
}
}
UnityEngine.Object.DestroyImmediate(gameObject);
if (!m_scanMap.HasData())
{
Debug.LogError("Unable to scan GameObject. GameObject load aborted.");
return;
}
m_scanBounds = new Bounds(base.transform.position, new Vector3((float)m_scanWidth * m_scanResolution, (float)m_scanWidth * m_scanResolution * 0.4f, (float)m_scanDepth * m_scanResolution));
m_baseLevel = m_scanMap.GetBaseLevel();
MeshFilter meshFilter = GetComponent<MeshFilter>();
if (meshFilter == null)
{
meshFilter = base.gameObject.AddComponent<MeshFilter>();
meshFilter.hideFlags = HideFlags.HideInInspector;
}
MeshRenderer meshRenderer = GetComponent<MeshRenderer>();
if (meshRenderer == null)
{
meshRenderer = base.gameObject.AddComponent<MeshRenderer>();
meshRenderer.hideFlags = HideFlags.HideInInspector;
}
meshFilter.mesh = GaiaUtils.CreateMesh(m_scanMap.Heights(), m_scanBounds.size);
if (m_previewMaterial != null)
{
m_previewMaterial.hideFlags = HideFlags.HideInInspector;
meshRenderer.sharedMaterial = m_previewMaterial;
}
}
public string SaveScan()
{
if (m_scanMap == null || !m_scanMap.HasData())
{
Debug.LogWarning("Cant save scan as none has been loaded");
return null;
}
string gaiaAssetPath = GaiaUtils.GetGaiaAssetPath(m_featureType, m_featureName);
GaiaUtils.CompressToSingleChannelFileImage(m_scanMap.Heights(), gaiaAssetPath, TextureFormat.RGBA32, exportPNG: false);
gaiaAssetPath = GaiaUtils.GetGaiaStampAssetPath(m_featureType, m_featureName);
gaiaAssetPath += ".bytes";
float[] obj = new float[5] { m_scanWidth, m_scanDepth, m_scanHeight, m_scanResolution, m_baseLevel };
byte[] array = new byte[obj.Length * 4];
Buffer.BlockCopy(obj, 0, array, 0, array.Length);
m_scanMap.SetMetaData(array);
m_scanMap.SaveToBinaryFile(gaiaAssetPath);
return gaiaAssetPath;
}
private void UpdateScanner()
{
base.transform.localRotation = Quaternion.identity;
base.transform.localScale = Vector3.one;
m_scanBounds.center = base.transform.position;
}
private void OnDrawGizmosSelected()
{
UpdateScanner();
Gizmos.color = Color.blue;
Gizmos.DrawWireCube(m_scanBounds.center, m_scanBounds.size);
m_groundOffset = m_scanBounds.center;
m_groundOffset.y = m_scanBounds.min.y + (m_scanBounds.max.y - m_scanBounds.min.y) * m_baseLevel;
m_groundSize = m_scanBounds.size;
m_groundSize.y = 0.1f;
Gizmos.color = Color.yellow;
Gizmos.DrawCube(m_groundOffset, m_groundSize);
}
}
}