首次提交

This commit is contained in:
Bob.Song
2026-03-05 18:07:55 +08:00
commit e125bb869e
4534 changed files with 563920 additions and 0 deletions

View File

@@ -0,0 +1,328 @@
using System;
using FairyGUI;
using FairyGUI.Utils;
using System.Collections;
using UnityEngine;
using UnityEngine.Rendering.Universal;
using Object = UnityEngine.Object;
namespace NBF
{
[Serializable]
public class ModelViewRenderImage
{
public Transform modelRoot { get; private set; }
public Camera Camera => _camera;
public RenderTexture RT => _renderTexture;
public ModelViewerSettings ViewerSettings { get; private set; }
Camera _camera;
Image _image;
Transform _root;
Transform _background;
Transform _model;
RenderTexture _renderTexture;
int _width;
int _height;
bool _cacheTexture;
// Vector3 _rotating;
const int RENDER_LAYER = 22;
const int HIDDEN_LAYER = 22;
public ModelViewRenderImage(GGraph holder)
{
_width = (int)holder.width;
_height = (int)holder.height;
_cacheTexture = true;
_image = new Image();
holder.SetNativeObject(_image);
_root = new GameObject("RenderImage").transform;
_root.transform.position = Vector3.zero;
// _root.SetParent(_camera.transform, false);
SetLayer(_root.gameObject, HIDDEN_LAYER);
Object.DontDestroyOnLoad(_root.gameObject);
Object prefab = Resources.Load("RenderTexture/RenderImageCamera");
GameObject go = (GameObject)Object.Instantiate(prefab, _root, false);
_camera = go.GetComponent<Camera>();
_camera.transform.position = Vector3.zero;
_camera.cullingMask = 1 << RENDER_LAYER;
_camera.enabled = false;
Object.DontDestroyOnLoad(_camera.gameObject);
modelRoot = new GameObject("model_root").transform;
modelRoot.SetParent(_root, false);
_background = new GameObject("background").transform;
_background.SetParent(_root, false);
_image.onAddedToStage.Add(OnAddedToStage);
_image.onRemovedFromStage.Add(OnRemoveFromStage);
// _viewerSettings = new ModelViewerSettings();
if (_image.stage != null)
OnAddedToStage();
else
_camera.gameObject.SetActive(false);
}
public void SetModel(GameObject model, ModelViewerSettings settings)
{
this.UnloadModel();
ViewerSettings = settings;
if (model == null) return;
var joint = model.GetComponent<Joint>();
if (joint != null)
{
Object.Destroy(joint);
}
_model = model.transform;
_model.SetParent(this.modelRoot, false);
_model.localPosition = Vector3.zero;
_model.localScale = Vector3.one;
_model.localEulerAngles = Vector3.zero;
if (ViewerSettings == null)
{
ViewerSettings = new ModelViewerSettings();
ModelViewerUtils.InitSetting(model, ViewerSettings);
}
var meshArr = _model.GetComponentsInChildren<MeshRenderer>();
foreach (var meshRenderer in meshArr)
{
// 设置物体仅接受 Layer 2 的光照
meshRenderer.renderingLayerMask = 1 << 2;
}
Review();
}
public void UnloadModel()
{
if (_model != null)
{
ViewerSettings = null;
_model.gameObject.SetActive(false);
Object.Destroy(_model.gameObject);
_model = null;
}
}
public void Review()
{
_model.position = ViewerSettings.objectPosition;
_model.localScale = ViewerSettings.objectScale;
_model.eulerAngles = ViewerSettings.objectRotation;
_camera.clearFlags = CameraClearFlags.Nothing;
_camera.backgroundColor = new Color(0, 0, 0, 0); // 完全透明
_camera.transform.position = ViewerSettings.cameraPosition;
_camera.transform.LookAt(ViewerSettings.cameraTarget);
_camera.orthographic = ViewerSettings.cameraOrtho;
_camera.orthographicSize = ViewerSettings.cameraSize;
_camera.orthographicSize /= ViewerSettings.camerasScaleFactor;
_camera.fieldOfView = ViewerSettings.cameraFov;
float fov = 2 * Mathf.Rad2Deg * Mathf.Atan2(
Mathf.Tan(_camera.fieldOfView * Mathf.Deg2Rad / 2), ViewerSettings.camerasScaleFactor
);
if (fov < 0)
fov += 180;
_camera.fieldOfView = fov;
_camera.nearClipPlane = 0.001f;
_camera.farClipPlane = 10000;
_camera.depthTextureMode = DepthTextureMode.Depth;
_camera.clearFlags = CameraClearFlags.Color;
_camera.GetUniversalAdditionalCameraData().renderPostProcessing = false; //URP only
}
public void Dispose()
{
UnloadModel();
Object.Destroy(_camera.gameObject);
DestroyTexture();
_image.Dispose();
_image = null;
}
void CreateTexture()
{
if (_renderTexture != null)
return;
//1920
_renderTexture = new RenderTexture(_width, _height, 24, RenderTextureFormat.ARGB32)
{
antiAliasing = 8,
filterMode = FilterMode.Bilinear,
anisoLevel = 0,
useMipMap = false
};
// _renderTexture.Create();
_image.texture = new NTexture(_renderTexture);
_image.shader = "Unlit/Transparent";
}
void DestroyTexture()
{
if (_renderTexture != null)
{
Object.Destroy(_renderTexture);
_renderTexture = null;
_image.texture = null;
}
}
void OnAddedToStage()
{
if (_renderTexture == null)
CreateTexture();
Timers.inst.AddUpdate(Render);
_camera.gameObject.SetActive(true);
Render();
}
void OnRemoveFromStage()
{
if (!_cacheTexture)
DestroyTexture();
Timers.inst.Remove(Render);
_camera.gameObject.SetActive(false);
}
void Render(object param = null)
{
// if (_rotating != Vector3.zero && this.modelRoot != null)
// {
// // 使用 Quaternion 来避免欧拉角带来的问题
// modelRoot.Rotate(_rotating, Space.World);
// }
SetLayer(_root.gameObject, RENDER_LAYER);
_camera.targetTexture = _renderTexture;
RenderTexture old = RenderTexture.active;
RenderTexture.active = _renderTexture;
GL.Clear(true, true, Color.clear);
_camera.Render();
RenderTexture.active = old;
SetLayer(_root.gameObject, HIDDEN_LAYER);
UpdateDebugSave();
}
void SetLayer(GameObject go, int layer)
{
Transform[] transforms = go.GetComponentsInChildren<Transform>(true);
foreach (Transform t in transforms)
{
t.gameObject.layer = layer;
}
}
#region
// 在 ModelViewRenderImage 中添加新字段
private Vector2 _lastMousePosition;
private bool _isDragging;
public void StartRotate(Vector2 currentMousePosition)
{
_lastMousePosition = currentMousePosition;
_isDragging = true;
}
public void UpdateRotation(Vector2 currentMousePosition)
{
if (!_isDragging || modelRoot == null || _camera == null) return;
Vector2 delta = currentMousePosition - _lastMousePosition;
// 使用适中的灵敏度
float sensitivity = 0.2f;
float rotX = -delta.y * sensitivity;
float rotY = -delta.x * sensitivity;
Quaternion yRotation = Quaternion.AngleAxis(rotY, _camera.transform.up);
Quaternion xRotation = Quaternion.AngleAxis(rotX, _camera.transform.right);
// 组合旋转并应用
modelRoot.rotation = yRotation * xRotation * modelRoot.rotation;
_lastMousePosition = currentMousePosition;
}
public void StopRotate()
{
_isDragging = false;
}
// 重置到初始状态的方法
public void ResetToInitialRotation()
{
modelRoot.localRotation = Quaternion.identity;
_isDragging = false;
}
#endregion
#region MyRegion
void UpdateDebugSave()
{
if (Input.GetKeyDown(KeyCode.F9))
{
SaveRenderTextureToPNG(_renderTexture, "RenderTextureDebug.png");
}
}
void SaveRenderTextureToPNG(RenderTexture rt, string fileName)
{
if (rt == null)
{
Debug.LogWarning("RenderTexture 为 null无法保存。");
return;
}
RenderTexture current = RenderTexture.active;
RenderTexture.active = rt;
Texture2D tex = new Texture2D(rt.width, rt.height, TextureFormat.RGBA32, false);
tex.ReadPixels(new Rect(0, 0, rt.width, rt.height), 0, 0);
tex.Apply();
byte[] bytes = tex.EncodeToPNG();
string path = System.IO.Path.Combine(Application.dataPath, "../" + fileName);
System.IO.File.WriteAllBytes(path, bytes);
Debug.Log($"✅ RenderTexture 已保存到: {path}");
UnityEngine.Object.Destroy(tex);
RenderTexture.active = current;
}
#endregion
}
}