首次提交
This commit is contained in:
328
Assets/Scripts/UI/Common/ModelViewer/ModelViewRenderImage.cs
Normal file
328
Assets/Scripts/UI/Common/ModelViewer/ModelViewRenderImage.cs
Normal 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
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 14ecd9c69c8a4eb28e8f102cca593c0b
|
||||
timeCreated: 1761412504
|
||||
27
Assets/Scripts/UI/Common/ModelViewer/ModelViewer.Designer.cs
generated
Normal file
27
Assets/Scripts/UI/Common/ModelViewer/ModelViewer.Designer.cs
generated
Normal file
@@ -0,0 +1,27 @@
|
||||
/**本脚本为自动生成,每次生成会覆盖!请勿手动修改,生成插件文档及项目地址:https://git.whoot.com/whoot-games/whoot.fguieditorplugin**/
|
||||
|
||||
|
||||
using FairyGUI;
|
||||
using FairyGUI.Utils;
|
||||
using NBC;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public partial class ModelViewer
|
||||
{
|
||||
public const string URL = "ui://6hgkvlauxd2fml";
|
||||
|
||||
public GGraph ModelHolder;
|
||||
public GGraph TouchHolder;
|
||||
|
||||
public override void ConstructFromXML(XML xml)
|
||||
{
|
||||
base.ConstructFromXML(xml);
|
||||
|
||||
ModelHolder = (GGraph)GetChild("ModelHolder");
|
||||
TouchHolder = (GGraph)GetChild("TouchHolder");
|
||||
OnInited();
|
||||
UILanguage.TrySetComponentLanguage(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d1f6b336c0f70ab428b9ab14c0f1bd6f
|
||||
179
Assets/Scripts/UI/Common/ModelViewer/ModelViewer.cs
Normal file
179
Assets/Scripts/UI/Common/ModelViewer/ModelViewer.cs
Normal file
@@ -0,0 +1,179 @@
|
||||
// 本脚本只在不存在时会生成一次。组件逻辑写在当前脚本内。已存在不会再次生成覆盖
|
||||
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
using FairyGUI;
|
||||
using Fantasy;
|
||||
using NBF.Fishing2;
|
||||
using Log = NBC.Log;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public partial class ModelViewer : GComponent
|
||||
{
|
||||
ModelViewRenderImage _renderImage;
|
||||
|
||||
public ModelViewRenderImage RenderImage => _renderImage;
|
||||
private Transform ModelRoot => _renderImage?.modelRoot;
|
||||
private Camera ViewCamera => _renderImage.Camera;
|
||||
|
||||
public ModelViewerSettings ViewerSettings => _renderImage.ViewerSettings;
|
||||
|
||||
private void OnInited()
|
||||
{
|
||||
|
||||
TouchHolder.onRollOver.Set(OnFocusIn);
|
||||
TouchHolder.onRollOut.Set(OnFocusOut);
|
||||
Stage.inst.onMouseWheel.Add(OnMouseWheel);
|
||||
|
||||
onAddedToStage.Add(OnAddedToStage);
|
||||
|
||||
SetRotateListening();
|
||||
}
|
||||
|
||||
void OnAddedToStage()
|
||||
{
|
||||
_renderImage = new ModelViewRenderImage(ModelHolder.asGraph);
|
||||
}
|
||||
|
||||
|
||||
public override void Dispose()
|
||||
{
|
||||
Stage.inst.onMouseWheel.Remove(OnMouseWheel);
|
||||
_renderImage.Dispose();
|
||||
base.Dispose();
|
||||
}
|
||||
|
||||
|
||||
public void SetData(ItemInfo itemInfo)
|
||||
{
|
||||
_renderImage.SetModel(PrefabsHelper.CreateItem(itemInfo.Config), ModelViewerSettings.Load((int)itemInfo.ConfigId));
|
||||
}
|
||||
|
||||
public void SetData(cfg.Item itemConfig)
|
||||
{
|
||||
_renderImage.SetModel(PrefabsHelper.CreateItem(itemConfig), ModelViewerSettings.Load(itemConfig.Id));
|
||||
}
|
||||
|
||||
|
||||
public void UnloadModel()
|
||||
{
|
||||
_renderImage.UnloadModel();
|
||||
}
|
||||
|
||||
#region 用户输入操作(滑动,拖动等)
|
||||
|
||||
private bool _focus;
|
||||
|
||||
private float _minFOV = 10f;
|
||||
private float _maxFOV = 120f;
|
||||
|
||||
private void SetRotateListening()
|
||||
{
|
||||
var dragObj = TouchHolder;
|
||||
var gesture1 = new SwipeGesture(dragObj);
|
||||
gesture1.onBegin.Set(OnSwipeBegin);
|
||||
gesture1.onMove.Set(OnSwipeMove);
|
||||
gesture1.onEnd.Set(OnSwipeEnd);
|
||||
}
|
||||
|
||||
private void OnSwipeBegin(EventContext context)
|
||||
{
|
||||
var gesture = context.sender as SwipeGesture;
|
||||
if (gesture == null) return;
|
||||
if (context.inputEvent.button == 0)
|
||||
{
|
||||
_renderImage.StartRotate(gesture.position);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSwipeMove(EventContext context)
|
||||
{
|
||||
var gesture = context.sender as SwipeGesture;
|
||||
if (gesture == null) return;
|
||||
|
||||
if (context.inputEvent.button == 0)
|
||||
{
|
||||
_renderImage.UpdateRotation(gesture.position);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnSwipeEnd(EventContext context)
|
||||
{
|
||||
_renderImage.StopRotate();
|
||||
}
|
||||
|
||||
private void OnFocusIn()
|
||||
{
|
||||
_focus = true;
|
||||
Log.Info("focus true");
|
||||
}
|
||||
|
||||
private void OnFocusOut()
|
||||
{
|
||||
_focus = false;
|
||||
Log.Info("focus false");
|
||||
}
|
||||
|
||||
private void OnMouseWheel(EventContext context)
|
||||
{
|
||||
if (!_focus) return;
|
||||
float delta = context.inputEvent.mouseWheelDelta / Stage.devicePixelRatio;
|
||||
SetZoom(delta);
|
||||
}
|
||||
|
||||
private void SetZoom(float delta)
|
||||
{
|
||||
ViewCamera.fieldOfView = Mathf.Clamp(ViewCamera.fieldOfView + delta, _minFOV, _maxFOV);
|
||||
}
|
||||
|
||||
#endregion
|
||||
|
||||
public void SaveRenderTextureToPNG(int id)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
RenderTexture rt = RenderImage.RT;
|
||||
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();
|
||||
|
||||
Texture2D resizedTex = new Texture2D(256, 256, TextureFormat.RGBA32, false);
|
||||
|
||||
// 使用双线性滤波进行缩放
|
||||
for (int y = 0; y < 256; y++)
|
||||
{
|
||||
for (int x = 0; x < 256; x++)
|
||||
{
|
||||
// 计算在原始纹理中的对应坐标
|
||||
float u = (float)x / 255f;
|
||||
float v = (float)y / 255f;
|
||||
|
||||
// 获取插值后的颜色
|
||||
Color color = tex.GetPixelBilinear(u, v);
|
||||
resizedTex.SetPixel(x, y, color);
|
||||
}
|
||||
}
|
||||
|
||||
resizedTex.Apply();
|
||||
|
||||
byte[] bytes = resizedTex.EncodeToPNG();
|
||||
var path = Path.Combine(Application.dataPath, $"Resources/Icons/{id}.png");
|
||||
File.WriteAllBytes(path, bytes);
|
||||
Debug.Log($"✅ RenderTexture 已保存到: {path}");
|
||||
Notices.Info($"生成:{id}");
|
||||
|
||||
Object.Destroy(tex);
|
||||
RenderTexture.active = current;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
2
Assets/Scripts/UI/Common/ModelViewer/ModelViewer.cs.meta
Normal file
2
Assets/Scripts/UI/Common/ModelViewer/ModelViewer.cs.meta
Normal file
@@ -0,0 +1,2 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c4925b571afa6b84382089b71d8603f2
|
||||
81
Assets/Scripts/UI/Common/ModelViewer/ModelViewerSettings.cs
Normal file
81
Assets/Scripts/UI/Common/ModelViewer/ModelViewerSettings.cs
Normal file
@@ -0,0 +1,81 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using NBC.Asset;
|
||||
using Newtonsoft.Json;
|
||||
using UnityEngine;
|
||||
using Color = UnityEngine.Color;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
[Serializable]
|
||||
public class ModelViewerSettings
|
||||
{
|
||||
//物体设置
|
||||
public Vector3 objectPosition;
|
||||
public Vector3 objectRotation;
|
||||
public Vector3 objectScale;
|
||||
|
||||
//摄像机设置
|
||||
public Vector3 cameraPosition;
|
||||
public Vector3 cameraTarget;
|
||||
public bool autoPosition;
|
||||
public bool autoScale;
|
||||
public bool cameraOrtho;
|
||||
public float cameraFov;
|
||||
public float cameraSize;
|
||||
public float camerasScaleFactor;
|
||||
public float perspLastScale;
|
||||
|
||||
//灯光设置
|
||||
public Color lightColour;
|
||||
public Vector3 lightDir;
|
||||
public float lightIntensity;
|
||||
public Color ambientLightColour;
|
||||
|
||||
|
||||
public static ModelViewerSettings Load(int id)
|
||||
{
|
||||
var configAsset = Assets.Load<TextAsset>($"Assets/ResRaw/config/Viewer/{id}");
|
||||
if (configAsset != null)
|
||||
{
|
||||
return JsonConvert.DeserializeObject<ModelViewerSettings>(configAsset.text);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public ModelViewerSettings()
|
||||
{
|
||||
SetDefValues();
|
||||
}
|
||||
|
||||
public ModelViewerSettings(Shader objRenderShader, string rapidIconRootFolder, GameObject rootObject)
|
||||
{
|
||||
SetDefValues();
|
||||
}
|
||||
|
||||
private void SetDefValues()
|
||||
{
|
||||
objectPosition = Vector3.zero;
|
||||
objectRotation = Vector3.zero;
|
||||
objectScale = Vector3.one;
|
||||
autoPosition = true;
|
||||
|
||||
|
||||
cameraPosition = new Vector3(1, Mathf.Sqrt(2), 1);
|
||||
perspLastScale = 1;
|
||||
cameraOrtho = false;
|
||||
cameraFov = 60;
|
||||
cameraSize = 5;
|
||||
camerasScaleFactor = 1;
|
||||
cameraTarget = Vector3.zero;
|
||||
autoScale = true;
|
||||
|
||||
ambientLightColour = Color.gray;
|
||||
lightColour = Color.white;
|
||||
lightDir = new Vector3(50, -30, 0);
|
||||
lightIntensity = 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7ff80ea34f5f43069392dc52c7b49831
|
||||
timeCreated: 1761415395
|
||||
99
Assets/Scripts/UI/Common/ModelViewer/ModelViewerUtils.cs
Normal file
99
Assets/Scripts/UI/Common/ModelViewer/ModelViewerUtils.cs
Normal file
@@ -0,0 +1,99 @@
|
||||
using UnityEngine;
|
||||
|
||||
namespace NBF
|
||||
{
|
||||
public class ModelViewerUtils
|
||||
{
|
||||
public static ModelViewerSettings InitSetting(GameObject go, ModelViewerSettings settings)
|
||||
{
|
||||
if (settings.objectPosition.magnitude < 0.0001f)
|
||||
settings.objectPosition = Vector3.zero;
|
||||
|
||||
//---Zero the GameObject euler angles if they're very small in magnitude---//
|
||||
settings.objectRotation = go.transform.eulerAngles;
|
||||
if (settings.objectRotation.magnitude < 0.0001f)
|
||||
settings.objectRotation = Vector3.zero;
|
||||
|
||||
//---Set the object scale variable---//
|
||||
settings.objectScale = go.transform.localScale;
|
||||
|
||||
//将默认对象位置设为使其位于图标中心的位置
|
||||
Bounds bounds = GetObjectBounds(go);
|
||||
settings.objectPosition = GetObjectAutoOffset(bounds);
|
||||
|
||||
// 将默认的相机设置调整为适合图标渲染中对象的呈现效果
|
||||
float camAuto = GetCameraAuto(bounds);
|
||||
settings.cameraSize = camAuto;
|
||||
settings.cameraPosition = Vector3.one * camAuto;
|
||||
|
||||
|
||||
return settings;
|
||||
}
|
||||
|
||||
public static Bounds GetObjectBounds(GameObject go)
|
||||
{
|
||||
// 在将其位置归零之前先保存其位置信息
|
||||
Vector3 prefabPos = go.transform.position;
|
||||
go.transform.position = Vector3.zero;
|
||||
|
||||
// 创建一个边界对象,并将对象网格的边界进行封装。
|
||||
MeshRenderer mr = go.GetComponent<MeshRenderer>();
|
||||
Bounds bounds = new Bounds(Vector3.zero, 0.000001f * Vector3.one);
|
||||
if (mr != null)
|
||||
bounds.Encapsulate(mr.bounds);
|
||||
else
|
||||
{
|
||||
SkinnedMeshRenderer smr = go.GetComponent<SkinnedMeshRenderer>();
|
||||
if (smr != null)
|
||||
bounds.Encapsulate(smr.bounds);
|
||||
}
|
||||
|
||||
//同时将对象的子对象的范围也进行封装起来
|
||||
EncapsulateChildBounds(go.transform, ref bounds);
|
||||
|
||||
//将预制物的位置重置为存储的值
|
||||
go.transform.position = prefabPos;
|
||||
|
||||
return bounds;
|
||||
}
|
||||
|
||||
public static Vector3 GetObjectAutoOffset(Bounds bounds)
|
||||
{
|
||||
//将偏移量应用到图标对象的位置上
|
||||
return -bounds.center;
|
||||
}
|
||||
|
||||
public static float GetCameraAuto(Bounds bounds)
|
||||
{
|
||||
//---Scale camera size and position so that the object fits in the render---//
|
||||
Matrix4x4 trs = Matrix4x4.TRS(Vector3.zero, Quaternion.Euler(0, 45, 0), 1.05f * Vector3.one);
|
||||
Vector3 corner = new Vector3(bounds.extents.x, bounds.extents.y, bounds.extents.z);
|
||||
corner = trs * corner;
|
||||
|
||||
Vector2 refB2 = new Vector2(0.74f, 0.53f);
|
||||
Vector2 b2 = refB2 * corner.magnitude;
|
||||
|
||||
return b2.magnitude;
|
||||
}
|
||||
|
||||
public static void EncapsulateChildBounds(Transform t, ref Bounds bounds)
|
||||
{
|
||||
// 遍历所有子对象,封装边界
|
||||
MeshRenderer mr;
|
||||
for (int i = 0; i < t.childCount; i++)
|
||||
{
|
||||
mr = t.GetChild(i).GetComponent<MeshRenderer>();
|
||||
if (mr != null)
|
||||
bounds.Encapsulate(mr.bounds);
|
||||
else
|
||||
{
|
||||
SkinnedMeshRenderer smr = t.GetChild(i).GetComponent<SkinnedMeshRenderer>();
|
||||
if (smr != null)
|
||||
bounds.Encapsulate(smr.bounds);
|
||||
}
|
||||
|
||||
EncapsulateChildBounds(t.GetChild(i), ref bounds);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 61157ac2e9594f58ae919731a4a5028c
|
||||
timeCreated: 1761487911
|
||||
Reference in New Issue
Block a user