【Unity3D】利用IJob、Burst优化处理切割物体

参考文章: 

【Unity】切割网格

【Unity3D】ECS入门学习(一)导入及基础学习_unity ecs教程-CSDN博客 

【Unity3D】ECS入门学习(十二)IJob、IJobFor、IJobParallelFor_unity ijobparallelfor-CSDN博客

工程资源地址: 

BStandShaderResources/job_burst_cut_demo.unitypackage at master · AMikeW/BStandShaderResources · GitHub

优化前

使用Job、Burst会将切割数据处理放到一个非主线程处理,并行加速计算。
麻烦的地方是所有List<T>都要改成NativeArray,所有Dictionary<K,V>都要改成NativeHashMap<K,V>,以及不能传递GameObject,Transform等,也就是不能有任何的引用类型对象出现在继承了IJob接口的脚本,而且CutJob是一个struct结构体。

注意:在CutManager脚本,必须引入:using Unity.Jobs; 才能使用job.Schedule接口方法,因为这玩意并不是IJor的方法,毕竟IJor只是个接口,它是一个扩展方法。

namespace Unity.Jobs
{
    //
    // 摘要:
    //     Extension methods for Jobs using the IJob interface.
    public static class IJobExtensions
    {
        public static void Run<T>(this T jobData) where T : struct, IJob;
        public static JobHandle Schedule<T>(this T jobData, JobHandle dependsOn = default) where T : struct, IJob;
    }
}

  只会切割CutGo标签的物体 

开启Job

using System;
using System.Collections;
using System.Collections.Generic;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;

/// <summary>
/// 切割平面信息
/// </summary>
public class CutInfo
{
    public Vector3 cutPoint;      //对应射线碰撞点
    public Vector3 cutHorizontal; //对应dir
    public Vector3 cutVertical;//对应vertical
    public Vector3 cutNormal;  //对应normal
}

/// <summary>
/// 必须挂在摄像机上才会有GL线条
/// 功能:凸网格切割网格(不支持凹网格)
/// 使用方法:按F开启和禁用切割功能,鼠标指向物体出现辅助线条,滑轮滚动控制切割线条旋转,鼠标左击进行切割物体
/// </summary>
public class CutManager : MonoBehaviour
{
    private static CutManager _instance;
    public static CutManager Instance
    {
        get { return _instance; }
    }
    bool isOn;

    public bool blockCut;

    Transform hitTarget;
    Vector3 hitPos;

    Vector3 dir;
    Vector3 cutVerticalDir;
    Vector3 cutNormalDir;

    float angle;
    float scrollSpeed = 25.0f;

    bool isCutting;

    Mesh targetMesh;

    const string TagName = "CutGo";

    public Transform generatePoint;
    //使用GL画线所需材质
    public Material mater;

    private float force = 0.8f;

    public float destroyTime = 0.5f;

    public List<CutInfo> cutInfos; //记录所有正常的切割(防止出现极其相似的切割平面造成奇怪的bug)

    public Material dissolveMat;

    private GameObject lastCutObject;

    private Vector3 cutStartPos;
    private Vector3 cutEndPos;

    private Action<float> cutCallback;

    public bool isUseJob;

    //试图尝试使用常驻的变量,但测试发现会导致数据混乱,具体表现是切割第二次时,整个模型的顶点乱了,如果使用TempJob临时的则不会发生
    //NativeArray<Vector3> _tempVert1;
    //NativeArray<Vector3> _tempVert2;
    //NativeArray<Vector3> _tempNormal1;
    //NativeArray<Vector3> _tempNormal2;
    //NativeArray<int> _tempTriangles1;
    //NativeArray<int> _tempTriangles2;
    //NativeArray<Vector2> _uvs1;
    //NativeArray<Vector2> _uvs2;
    //NativeHashMap<int, int> _tempIndex1;
    //NativeHashMap<int, int> _tempIndex2;

    //NativeArray<int> _temp1CountArray;
    //NativeArray<int> _temp2CountArray;

    //NativeArray<Vector3> _localPos;
    //NativeArray<Vector3> _allPos;

    //NativeArray<Vector3> targetMeshVert;
    //NativeArray<Vector3> targetMeshNormal;
    //NativeArray<int> targetMeshTriangles;

    private void Awake()
    {
        _instance = this;
    }

    private void OnDestroy()
    {
        //targetMeshVert.Dispose();
        //targetMeshNormal.Dispose();
        //targetMeshTriangles.Dispose();

        //_tempVert1.Dispose();
        //_tempNormal1.Dispose();
        //_tempTriangles1.Dispose();
        //_uvs1.Dispose();

        //_tempVert2.Dispose();
        //_tempNormal2.Dispose();
        //_tempTriangles2.Dispose();
        //_uvs2.Dispose();

        //_temp1CountArray.Dispose();
        //_temp2CountArray.Dispose();
        //_tempIndex1.Dispose();
        //_tempIndex2.Dispose();
        //_localPos.Dispose();
        //_allPos.Dispose();
    }

    void Start()
    {
        isOn = false;
        tempVert1 = new List<Vector3>();
        tempNormal1 = new List<Vector3>();
        tempTriangles1 = new List<int>();
        tempIndex1 = new Dictionary<int, int>();
        uvs1 = new List<Vector2>();

        tempVert2 = new List<Vector3>();
        tempNormal2 = new List<Vector3>();
        tempTriangles2 = new List<int>();
        tempIndex2 = new Dictionary<int, int>();
        uvs2 = new List<Vector2>();

        localPos = new List<Vector3>();
        allPos = new List<Vector3>();
        cutInfos = new List<CutInfo>();

        //targetMeshVert = new Unity.Collections.NativeArray<Vector3>(5000, Unity.Collections.Allocator.Persistent);
        //targetMeshNormal = new Unity.Collections.NativeArray<Vector3>(2500, Unity.Collections.Allocator.Persistent);
        //targetMeshTriangles = new Unity.Collections.NativeArray<int>(9000, Unity.Collections.Allocator.Persistent);

        //_tempVert1 = new Unity.Collections.NativeArray<Vector3>(5000, Unity.Collections.Allocator.Persistent);
        //_tempNormal1 = new Unity.Collections.NativeArray<Vector3>(2500, Unity.Collections.Allocator.Persistent);
        //_tempTriangles1 = new Unity.Collections.NativeArray<int>(9000, Unity.Collections.Allocator.Persistent);
        //_uvs1 = new Unity.Collections.NativeArray<Vector2>(5000, Unity.Collections.Allocator.Persistent);
        //_tempIndex1 = new Unity.Collections.NativeHashMap<int, int>(9000, Unity.Collections.Allocator.Persistent);
        //_temp1CountArray = new NativeArray<int>(5, Allocator.Persistent);
        //_tempVert2 = new Unity.Collections.NativeArray<Vector3>(5000, Unity.Collections.Allocator.Persistent);
        //_tempNormal2 = new Unity.Collections.NativeArray<Vector3>(2500, Unity.Collections.Allocator.Persistent);
        //_tempTriangles2 = new Unity.Collections.NativeArray<int>(9000, Unity.Collections.Allocator.Persistent);
        //_uvs2 = new Unity.Collections.NativeArray<Vector2>(5000, Unity.Collections.Allocator.Persistent);
        //_tempIndex2 = new Unity.Collections.NativeHashMap<int, int>(9000, Unity.Collections.Allocator.Persistent);
        //_temp2CountArray = new NativeArray<int>(5, Allocator.Persistent);
        //_localPos = new NativeArray<Vector3>(1000, Allocator.Persistent);
        //_allPos = new NativeArray<Vector3>(1000, Allocator.Persistent);
    }

    void Update()
    {
        ControlIsOn();
        ControlCutSpace();
    }

    void OnPostRender()
    {
        if (!isOn || !isCutting)
            return;

        if (!mater)
        {
            Debug.LogError("Please Assign a material on the inspector");
            return;
        }

        GL.PushMatrix();
        mater.SetPass(0);
        GL.Color(Color.yellow);
        GL.Begin(GL.LINES);
        GL.Vertex(hitPos + cutVerticalDir * 12f + dir * 1f);
        GL.Vertex(hitPos - cutVerticalDir * 12f + dir * 1f);
        GL.Vertex(hitPos + dir * 1f);
        GL.Vertex(hitPos + cutNormalDir * 0.2f + dir * 1f);
        GL.End();
        GL.PopMatrix();

    }

    void ControlIsOn()
    {
        isOn = true;
    }


    void ControlCutSpace()
    {
        //射线发射射线计算出射线交点,以射线为轴计算出另外2个轴向 (红线为射线,绿线为垂直于射线和法线的线, 黄线为法线)        

        Ray ray = Camera.main.ScreenPointToRay(InputController.GetPosition());

        Debug.DrawRay(Camera.main.transform.position, InputController.GetPosition(), Color.red);

        RaycastHit hit;
        if (Physics.Raycast(ray, out hit))
        {
            if (hit.transform.tag != TagName)
            {
                TryCut();
                cutStartPos = Vector3.zero;
                cutEndPos = Vector3.zero;
                return;
            }
            if (cutStartPos == null || cutStartPos == Vector3.zero)
            {
                cutStartPos = hit.point;
            }
            isCutting = true;
            hitTarget = hit.transform;
            hitPos = hit.point;
            cutEndPos = hitPos;
            MeshFilter meshFilter = hit.transform.GetComponent<MeshFilter>();
            if (meshFilter != null)
            {
                targetMesh = hit.transform.GetComponent<MeshFilter>().mesh;
            }
            else
            {
                Debug.LogWarning("尝试切割没有网格的物品");
                cutStartPos = Vector3.zero;
                cutEndPos = Vector3.zero;
                return;
            }

            //dir = (Camera.main.transform.position - hitPos).normalized;
            //cutVerticalDir = (Vector3.Dot(dir, Vector3.up) * -dir + Vector3.up).normalized;//dir和cutVerticalDir保持垂直

            使用鼠标滚轮旋转切割平面
            //if (Input.GetAxis("Mouse ScrollWheel") < 0)
            //{
            //    angle += scrollSpeed * Time.deltaTime;
            //}
            //else if (Input.GetAxis("Mouse ScrollWheel") > 0)
            //{
            //    angle -= scrollSpeed * Time.deltaTime;
            //}

            //cutVerticalDir = Quaternion.AngleAxis(Mathf.Rad2Deg * angle, dir) * cutVerticalDir; //围绕dir轴旋转

            //cutNormalDir = Vector3.Cross(dir, cutVerticalDir).normalized; //计算出切割面的法线

#if DEBUG
            //Debug.DrawRay(hitPos, cutVerticalDir, Color.green);
            //Debug.DrawRay(hitPos, dir, Color.red);
            //Debug.DrawRay(hitPos, cutNormalDir, Color.yellow);
#endif            
        }
        else
        {
            TryCut();
            cutStartPos = Vector3.zero;
            cutEndPos = Vector3.zero;
            isCutting = false;
        }

        滑动切割
        //Ray ray1 = Camera.main.ScreenPointToRay(InputController.GetPosition());
        //Physics.Raycast(ray);
        //if (Input.GetKeyDown(KeyCode.Mouse0))
        //{
        //    CutInfo tempCutInfo = new CutInfo();
        //    tempCutInfo.cutHorizontal = dir;
        //    tempCutInfo.cutVertical = cutVerticalDir;
        //    tempCutInfo.cutNormal = cutNormalDir;
        //    Cutting();
        //}
    }

    IEnumerator TryCutting1()
    {
        for (int i = 0; i < 3; i++)
        {
            if ((cutEndPos != null && cutEndPos != Vector3.zero) && (cutStartPos != null && cutStartPos != Vector3.zero))
            {
                isCutting = true;
                var point = (cutStartPos + cutEndPos) / 2;
                dir = (Camera.main.transform.position - point).normalized;

                var tempDir = (cutEndPos - cutStartPos).normalized;
                cutVerticalDir = (Vector3.Dot(dir, tempDir) * -dir + tempDir).normalized;//dir和cutVerticalDir保持垂直

                cutNormalDir = Vector3.Cross(dir, cutVerticalDir).normalized; //计算出切割面的法线

                Cutting();
                yield return new WaitForSeconds(0.1f);
            }
        }
        cutEndPos = Vector3.zero;
        cutStartPos = Vector3.zero;
    }

    private void TryCut()
    {
        if (!blockCut && (cutEndPos != null && cutEndPos != Vector3.zero) && (cutStartPos != null && cutStartPos != Vector3.zero))
        {
            isCutting = true;
            var point = (cutStartPos + cutEndPos) / 2;
            dir = (Camera.main.transform.position - point).normalized;

            var tempDir = (cutEndPos - cutStartPos).normalized;
            cutVerticalDir = (Vector3.Dot(dir, tempDir) * -dir + tempDir).normalized;//dir和cutVerticalDir保持垂直

            cutNormalDir = Vector3.Cross(dir, cutVerticalDir).normalized; //计算出切割面的法线
            Cutting();
        }
        cutEndPos = Vector3.zero;
        cutStartPos = Vector3.zero;
        isCutting = false;
    }

    private bool IsValidCutInfo(Vector3 dir, Vector3 vertical, Vector3 normal)
    {
        float limitValue = 0.15f;
        foreach (var v in cutInfos)
        {
            if (Mathf.Abs(dir.x - v.cutHorizontal.x) < limitValue && Mathf.Abs(dir.y - v.cutHorizontal.y) < limitValue && Mathf.Abs(dir.z - v.cutHorizontal.z) < limitValue
                && Mathf.Abs(vertical.x - v.cutVertical.x) < limitValue && Mathf.Abs(vertical.y - v.cutVertical.y) < limitValue && Mathf.Abs(vertical.z - v.cutVertical.z) < limitValue
                && Mathf.Abs(normal.x - v.cutNormal.x) < limitValue && Mathf.Abs(normal.y - v.cutNormal.y) < limitValue && Mathf.Abs(normal.z - v.cutNormal.z) < limitValue)
            {
                return false;
            }
        }
        return true;
    }

    List<Vector3> tempVert1;
    List<Vector3> tempNormal1;
    List<int> tempTriangles1;
    Dictionary<int, int> tempIndex1;
    List<Vector2> uvs1;

    List<Vector3> tempVert2;
    List<Vector3> tempNormal2;
    List<int> tempTriangles2;
    Dictionary<int, int> tempIndex2;
    List<Vector2> uvs2;

    int[] triangles;

    List<Vector3> localPos;
    List<Vector3> allPos;



    void Cutting()
    {
        if (!isCutting || !isOn || targetMesh == null || hitTarget == null)
            return;

        tempVert1.Clear();
        tempNormal1.Clear();
        tempTriangles1.Clear();
        tempIndex1.Clear();
        uvs1.Clear();

        tempVert2.Clear();
        tempNormal2.Clear();
        tempTriangles2.Clear();
        tempIndex2.Clear();
        uvs2.Clear();

        allPos.Clear();

        System.Diagnostics.Stopwatch sw = System.Diagnostics.Stopwatch.StartNew();
        if (isUseJob)
        {
            CutJob job = new CutJob();

            var vertices = targetMesh.vertices;
            var normals = targetMesh.normals;
            var triangles = targetMesh.triangles;

            var _tempVert1 = new Unity.Collections.NativeArray<Vector3>(5000, Unity.Collections.Allocator.TempJob);
            var _tempNormal1 = new Unity.Collections.NativeArray<Vector3>(2500, Unity.Collections.Allocator.TempJob);
            var _tempTriangles1 = new Unity.Collections.NativeArray<int>(9000, Unity.Collections.Allocator.TempJob);
            var _uvs1 = new Unity.Collections.NativeArray<Vector2>(5000, Unity.Collections.Allocator.TempJob);
            var _tempIndex1 = new Unity.Collections.NativeHashMap<int, int>(9000, Unity.Collections.Allocator.TempJob);
            var _temp1CountArray = new NativeArray<int>(5, Allocator.TempJob);
            var _tempVert2 = new Unity.Collections.NativeArray<Vector3>(5000, Unity.Collections.Allocator.TempJob);
            var _tempNormal2 = new Unity.Collections.NativeArray<Vector3>(2500, Unity.Collections.Allocator.TempJob);
            var _tempTriangles2 = new Unity.Collections.NativeArray<int>(9000, Unity.Collections.Allocator.TempJob);
            var _uvs2 = new Unity.Collections.NativeArray<Vector2>(5000, Unity.Collections.Allocator.TempJob);
            var _tempIndex2 = new Unity.Collections.NativeHashMap<int, int>(9000, Unity.Collections.Allocator.TempJob);
            var _temp2CountArray = new NativeArray<int>(5, Allocator.TempJob);
            var _localPos = new NativeArray<Vector3>(1000, Allocator.TempJob);
            var _allPos = new NativeArray<Vector3>(1000, Allocator.TempJob);

            var targetMeshVert = new Unity.Collections.NativeArray<Vector3>(vertices.Length, Unity.Collections.Allocator.TempJob);
            var targetMeshNormal = new Unity.Collections.NativeArray<Vector3>(normals.Length, Unity.Collections.Allocator.TempJob);
            var targetMeshTriangles = new Unity.Collections.NativeArray<int>(triangles.Length, Unity.Collections.Allocator.TempJob);

            for (int i = 0; i < vertices.Length; i++)
            {
                targetMeshVert[i] = vertices[i];
            }
            job.targetMeshVert = targetMeshVert;


            for (int i = 0; i < normals.Length; i++)
            {
                targetMeshNormal[i] = normals[i];
            }
            job.targetMeshNormal = targetMeshNormal;

            for (int i = 0; i < triangles.Length; i++)
            {
                targetMeshTriangles[i] = triangles[i];
            }
            job.targetMeshTriangles_Count = triangles.Length;
            job.targetMeshTriangles = targetMeshTriangles;

            //job.hitTarget = hitTarget;
            job.hitTarget_LocalScale = hitTarget.localScale;
            job.hitTarget_o2w = hitTarget.localToWorldMatrix;
            job.hitTarget_w2o = hitTarget.worldToLocalMatrix;

            job.hitPos = hitPos;
            job.dir = dir;
            job.cutVerticalDir = cutVerticalDir;
            job.cutNormalDir = cutNormalDir;

            job.tempVert1_Count = 0;
            job.tempVert1 = _tempVert1;

            job.tempNormal1_Count = 0;
            job.tempNormal1 = _tempNormal1;

            job.tempTriangles1_Count = 0;
            job.tempTriangles1 = _tempTriangles1;

            job.uvs1_Count = 0;
            job.uvs1 = _uvs1;

            job.tempIndex1 = _tempIndex1;

            job.temp1CountArray = _temp1CountArray;

            job.tempVert2_Count = 0;
            job.tempVert2 = _tempVert2;

            job.tempNormal2_Count = 0;
            job.tempNormal2 = _tempNormal2;

            job.tempTriangles2_Count = 0;
            job.tempTriangles2 = _tempTriangles2;

            job.uvs2_Count = 0;
            job.uvs2 = _uvs2;

            job.tempIndex2 = _tempIndex2;

            job.temp2CountArray = _temp2CountArray;

            job.localPos = _localPos;

            job.allPos = _allPos;

            JobHandle jobHandle = job.Schedule();
            jobHandle.Complete();

            //数据转化 切割后的2个模型数据(顶点、法线、索引、UV)
            int temp1_VertCount = job.temp1CountArray[0];
            int temp1_NormalCount = job.temp1CountArray[1];
            int temp1_TrianglesCount = job.temp1CountArray[2];
            int temp1_UvsCount = job.temp1CountArray[3];

            int temp2_VertCount = job.temp2CountArray[0];
            int temp2_NormalCount = job.temp2CountArray[1];
            int temp2_TrianglesCount = job.temp2CountArray[2];
            int temp2_UvsCount = job.temp2CountArray[3];

            for (int i = 0; i < temp1_VertCount; i++)
            {
                tempVert1.Add(_tempVert1[i]);
            }
            for (int i = 0; i < temp2_VertCount; i++)
            {
                tempVert2.Add(_tempVert2[i]);
            }

            for (int i = 0; i < temp1_NormalCount; i++)
            {
                tempNormal1.Add(_tempNormal1[i]);
            }
            for (int i = 0; i < temp2_NormalCount; i++)
            {
                tempNormal2.Add(_tempNormal2[i]);
            }

            for (int i = 0; i < temp1_TrianglesCount; i++)
            {
                tempTriangles1.Add(_tempTriangles1[i]);
            }
            for (int i = 0; i < temp2_TrianglesCount; i++)
            {
                tempTriangles2.Add(_tempTriangles2[i]);
            }

            for (int i = 0; i < temp1_UvsCount; i++)
            {
                uvs1.Add(_uvs1[i]);
            }
            for (int i = 0; i < temp2_UvsCount; i++)
            {
                uvs2.Add(_uvs2[i]);
            }

            //>>>>>>>>>>>>>>>>>>>>>>>>>>>>第一个切割出的物体开始构建
            Mesh originMesh = new Mesh(), newMesh = new Mesh();       
            originMesh.vertices = tempVert1.ToArray();
            originMesh.normals = tempNormal1.ToArray();
            originMesh.triangles = tempTriangles1.ToArray();
            originMesh.uv = uvs1.ToArray();
            hitTarget.GetComponent<MeshFilter>().mesh = originMesh;

            Collider collider = hitTarget.GetComponent<Collider>();
            if (collider != null)
            {
                Destroy(collider);
            }
            //hitTarget.gameObject.AddComponent<BoxCollider>();
            MeshCollider meshCollider = hitTarget.gameObject.AddComponent<MeshCollider>();


            hitTarget.gameObject.tag = TagName;
            hitTarget.gameObject.layer = 11;
            hitTarget.SetParent(generatePoint);

            float obj1Volume = CalculateVolumeHelper.CalculateSumVolume(hitTarget.transform.lossyScale, hitTarget.GetComponent<MeshFilter>());

            //>>>>>>>>>>>>>>>>>>>>>>>>>>切割出的第二个物体开始构建
            newMesh.vertices = tempVert2.ToArray();
            newMesh.normals = tempNormal2.ToArray();
            newMesh.triangles = tempTriangles2.ToArray();
            newMesh.uv = uvs2.ToArray();

            GameObject newobj = new GameObject();
            newobj.transform.position = hitTarget.position;
            newobj.transform.rotation = hitTarget.rotation;
            newobj.transform.localScale = hitTarget.localScale;
            newobj.AddComponent<MeshFilter>().mesh = newMesh;
            newobj.AddComponent<MeshRenderer>();
            Material mat = hitTarget.GetComponent<MeshRenderer>().material;
            newobj.GetComponent<MeshRenderer>().material = new Material(mat);
            newobj.tag = TagName;
            newobj.layer = 11;
            newobj.transform.SetParent(generatePoint);

            //顶点少的情况可以使用它 否则会报错超出顶点限制
            MeshCollider meshCollider2 = newobj.AddComponent<MeshCollider>();

            try
            {
                meshCollider.convex = true;
                meshCollider2.convex = true;
            }
            catch (Exception e)
            {
                Debug.LogWarning(e.Message);
            }


            float obj2Volume = CalculateVolumeHelper.CalculateSumVolume(newobj.transform.lossyScale, newobj.GetComponent<MeshFilter>());

            //this.cutCallback(Mathf.Min(obj1Volume, obj2Volume));
            //比较两者体积,较小的一个进行添加刚体 自由落体...
            if (obj1Volume < obj2Volume)
            {
                //hitTarget物体掉落 消失
                Rigidbody rigidbody1 = hitTarget.gameObject.GetOrAddComponent<Rigidbody>();
                rigidbody1.AddForce((hitTarget.InverseTransformDirection(cutNormalDir) * force), ForceMode.Impulse); //可去掉这个力            
                CutObjectDestroyBySelf cutObjectDestroyBySelf = hitTarget.gameObject.GetComponent<CutObjectDestroyBySelf>();
                if (!cutObjectDestroyBySelf)
                {
                    cutObjectDestroyBySelf = hitTarget.gameObject.AddComponent<CutObjectDestroyBySelf>();
                    cutObjectDestroyBySelf.time = destroyTime;
                }
                cutObjectDestroyBySelf.SetMat(dissolveMat);

                Rigidbody newobjRigidbody = newobj.GetComponent<Rigidbody>();
                if (newobjRigidbody)
                {
                    Destroy(newobjRigidbody);
                }
                lastCutObject = newobj;
            }
            else
            {
                Rigidbody rigidbody2 = newobj.GetOrAddComponent<Rigidbody>();
                rigidbody2.AddForce(-newobj.transform.InverseTransformDirection(cutNormalDir) * force, ForceMode.Impulse);//可去掉这个力            
                CutObjectDestroyBySelf cutObjectDestroyBySelf = newobj.GetComponent<CutObjectDestroyBySelf>();
                if (!cutObjectDestroyBySelf)
                {
                    cutObjectDestroyBySelf = newobj.AddComponent<CutObjectDestroyBySelf>();
                    cutObjectDestroyBySelf.time = destroyTime;
                }
                cutObjectDestroyBySelf.SetMat(dissolveMat);

                Rigidbody hitTargetRigidbody = hitTarget.gameObject.GetComponent<Rigidbody>();
                if (hitTargetRigidbody)
                {
                    Destroy(hitTargetRigidbody);
                }
                lastCutObject = hitTarget.gameObject;
            }

            //Destroy(newobj, 5f);

            targetMeshVert.Dispose();
            targetMeshNormal.Dispose();
            targetMeshTriangles.Dispose();

            _tempVert1.Dispose();
            _tempNormal1.Dispose();
            _tempTriangles1.Dispose();
            _uvs1.Dispose();

            _tempVert2.Dispose();
            _tempNormal2.Dispose();
            _tempTriangles2.Dispose();
            _uvs2.Dispose();

            _temp1CountArray.Dispose();
            _temp2CountArray.Dispose();
            _tempIndex1.Dispose();
            _tempIndex2.Dispose();
            _localPos.Dispose();
            _allPos.Dispose();
        }
        else
        {
            triangles = targetMesh.triangles;



            for (int i = 0; i < triangles.Length; i += 3)
            {
                int index1 = triangles[i];
                int index2 = triangles[i + 1];
                int index3 = triangles[i + 2];

                Vector3 vertex1 = targetMesh.vertices[index1];
                Vector3 vertex2 = targetMesh.vertices[index2];
                Vector3 vertex3 = targetMesh.vertices[index3];

                float vert1 = Vector3.Dot(cutNormalDir, (hitTarget.TransformPoint(vertex1) - hitPos).normalized);
                float vert2 = Vector3.Dot(cutNormalDir, (hitTarget.TransformPoint(vertex2) - hitPos).normalized);
                float vert3 = Vector3.Dot(cutNormalDir, (hitTarget.TransformPoint(vertex3) - hitPos).normalized);

                if (vert1 >= 0 && vert2 >= 0 && vert3 >= 0)
                {
                    //同面
                    if (!tempIndex1.ContainsKey(index1)) //过滤相同顶点
                    {
                        tempVert1.Add(vertex1);
                        tempNormal1.Add(targetMesh.normals[index1]);

                        tempIndex1.Add(index1, tempVert1.Count - 1); //旧索引为key,新索引为value
                    }

                    if (!tempIndex1.ContainsKey(index2)) //过滤相同顶点
                    {
                        tempVert1.Add(vertex2);
                        tempNormal1.Add(targetMesh.normals[index2]);

                        tempIndex1.Add(index2, tempVert1.Count - 1); //旧索引为key,新索引为value
                    }

                    if (!tempIndex1.ContainsKey(index3)) //过滤相同顶点
                    {
                        tempVert1.Add(vertex3);
                        tempNormal1.Add(targetMesh.normals[index3]);

                        tempIndex1.Add(index3, tempVert1.Count - 1); //旧索引为key,新索引为value
                    }

                    tempTriangles1.Add(tempIndex1[index1]); //使用旧索引index1 获取对应的新索引
                    tempTriangles1.Add(tempIndex1[index2]); //使用旧索引index2 获取对应的新索引
                    tempTriangles1.Add(tempIndex1[index3]); //使用旧索引index3 获取对应的新索引

                    if (tempIndex1[index1] == tempIndex1[index2] || tempIndex1[index1] == tempIndex1[index3] || tempIndex1[index2] == tempIndex1[index3])
                    {
                        Debug.LogError("[1]問題");
                    }
                }
                else if (vert1 <= 0 && vert2 <= 0 && vert3 <= 0)
                {
                    //另一个同面                
                    if (!tempIndex2.ContainsKey(index1)) //过滤相同顶点
                    {
                        tempVert2.Add(vertex1);
                        tempNormal2.Add(targetMesh.normals[index1]);

                        tempIndex2.Add(index1, tempVert2.Count - 1); //旧索引为key,新索引为value
                    }

                    if (!tempIndex2.ContainsKey(index2)) //过滤相同顶点
                    {
                        tempVert2.Add(vertex2);
                        tempNormal2.Add(targetMesh.normals[index2]);

                        tempIndex2.Add(index2, tempVert2.Count - 1); //旧索引为key,新索引为value
                    }

                    if (!tempIndex2.ContainsKey(index3)) //过滤相同顶点
                    {
                        tempVert2.Add(vertex3);
                        tempNormal2.Add(targetMesh.normals[index3]);

                        tempIndex2.Add(index3, tempVert2.Count - 1); //旧索引为key,新索引为value
                    }

                    tempTriangles2.Add(tempIndex2[index1]); //使用旧索引index1 获取对应的新索引
                    tempTriangles2.Add(tempIndex2[index2]); //使用旧索引index2 获取对应的新索引
                    tempTriangles2.Add(tempIndex2[index3]); //使用旧索引index3 获取对应的新索引
                    if (tempIndex2[index1] == tempIndex2[index2] || tempIndex2[index1] == tempIndex2[index3] || tempIndex2[index2] == tempIndex2[index3])
                    {
                        Debug.LogError("[2]問題");
                    }
                }
                else
                {
                    //continue;

                    localPos.Clear();
                    //不同面情况 (PS:不存在3点不同面情况)

                    bool isV1V2Sample = (vert1 > 0 && vert2 > 0 || vert1 < 0 && vert2 < 0);
                    bool isV2V3Sample = (vert2 > 0 && vert3 > 0 || vert2 < 0 && vert3 < 0);
                    bool isV3V1Sample = (vert3 > 0 && vert1 > 0 || vert3 < 0 && vert1 < 0);

                    Vector3 normal = Vector3.Cross(vertex2 - vertex1, vertex3 - vertex2);

                    //1. index1 和 index2 顶点不同面
                    if (!(isV1V2Sample))
                    {
                        CaculateIntersectionPoint(vertex1, vertex2);
                    }

                    //2. index2 和 index3 顶点不同面
                    if (!(isV2V3Sample))
                    {
                        CaculateIntersectionPoint(vertex2, vertex3);
                    }

                    //3. index3 和 index1 顶点不同面
                    if (!(isV3V1Sample))
                    {
                        CaculateIntersectionPoint(vertex3, vertex1);
                    }

                    //此时localPos保存2个交点, allPos是保存所有交点的
                    if (isV1V2Sample)
                    {
                        if (vert1 > 0 && vert2 > 0)
                        {
                            if (index1 == index2)
                            {
                                Debug.LogError(">>>>>>>>>>>>>>>>>>>>>1 : " + index1);
                            }
                            ConnectPointToTriangle(index1, index2, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1, index3);
                            ConnectPointToTriangle(index3, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2);
                        }
                        else
                        {
                            if (index1 == index2)
                            {
                                Debug.LogError(">>>>>>>>>>>>>>>>>>>>>2 : " + index1);
                            }
                            ConnectPointToTriangle(index1, index2, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2, index3);
                            ConnectPointToTriangle(index3, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1);
                        }
                    }

                    if (isV2V3Sample)
                    {
                        if (vert2 > 0 && vert3 > 0)
                        {
                            if (index2 == index3)
                            {
                                Debug.LogError(">>>>>>>>>>>>>>>>>>>>>3 : " + index2);
                            }
                            ConnectPointToTriangle(index2, index3, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1, index1);
                            ConnectPointToTriangle(index1, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2);
                        }
                        else
                        {
                            if (index2 == index3)
                            {
                                Debug.LogError(">>>>>>>>>>>>>>>>>>>>>4 : " + index2);
                            }
                            ConnectPointToTriangle(index2, index3, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2, index1);
                            ConnectPointToTriangle(index1, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1);
                        }
                    }

                    if (isV3V1Sample)
                    {
                        if (vert3 > 0 && vert1 > 0)
                        {
                            if (index3 == index1)
                            {
                                Debug.LogError(">>>>>>>>>>>>>>>>>>>>>5 : " + index3);
                            }
                            ConnectPointToTriangle(index3, index1, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1, index2);
                            ConnectPointToTriangle(index2, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2);
                        }
                        else
                        {
                            if (index3 == index1)
                            {
                                Debug.LogError(">>>>>>>>>>>>>>>>>>>>>6 : " + index3);
                            }
                            ConnectPointToTriangle(index3, index1, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2, index2);
                            ConnectPointToTriangle(index2, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1);
                        }
                    }

                }
            }

            //补全截面
            FillCutSurface();

            //注释下面两行代码,UV纹理全没但报错没了(目前UV组成有问题可能会导致模型某一面完全透明)
            //BUG已查明:上面代码生成新2个网格数据 会存在三角面的3个顶点位置数据一样,导致UV无法正常出现,因此此时简单地做个后处理 剔除这些异常三角面 ...      
            //bool isFilter1 = TempFuncFilterErrorTriangle(ref tempVert1, ref tempTriangles1, ref tempNormal1); //依然有问题 待修复...
            //bool isFilter2 = TempFuncFilterErrorTriangle(ref tempVert2, ref tempTriangles2, ref tempNormal2);
            CalculateUV(hitTarget.transform.localScale, tempVert1, tempTriangles1, tempNormal1, ref uvs1);
            CalculateUV(hitTarget.transform.localScale, tempVert2, tempTriangles2, tempNormal2, ref uvs2);

            //>>>>>>>>>>>>>>>>>>>>>>>>>>>>第一个切割出的物体开始构建
            Mesh originMesh = new Mesh(), newMesh = new Mesh();

            originMesh.vertices = tempVert1.ToArray();
            originMesh.normals = tempNormal1.ToArray();
            originMesh.triangles = tempTriangles1.ToArray();
            originMesh.uv = uvs1.ToArray();
            hitTarget.GetComponent<MeshFilter>().mesh = originMesh;

            Collider collider = hitTarget.GetComponent<Collider>();
            if (collider != null)
            {
                Destroy(collider);
            }
            //hitTarget.gameObject.AddComponent<BoxCollider>();
            MeshCollider meshCollider = hitTarget.gameObject.AddComponent<MeshCollider>();


            hitTarget.gameObject.tag = TagName;
            hitTarget.gameObject.layer = 11;
            hitTarget.SetParent(generatePoint);

            float obj1Volume = CalculateVolumeHelper.CalculateSumVolume(hitTarget.transform.lossyScale, hitTarget.GetComponent<MeshFilter>());

            //>>>>>>>>>>>>>>>>>>>>>>>>>>切割出的第二个物体开始构建
            newMesh.vertices = tempVert2.ToArray();
            newMesh.normals = tempNormal2.ToArray();
            newMesh.triangles = tempTriangles2.ToArray();
            newMesh.uv = uvs2.ToArray();

            GameObject newobj = new GameObject();
            newobj.transform.position = hitTarget.position;
            newobj.transform.rotation = hitTarget.rotation;
            newobj.transform.localScale = hitTarget.localScale;
            newobj.AddComponent<MeshFilter>().mesh = newMesh;
            newobj.AddComponent<MeshRenderer>();
            Material mat = hitTarget.GetComponent<MeshRenderer>().material;
            newobj.GetComponent<MeshRenderer>().material = new Material(mat);
            newobj.tag = TagName;
            newobj.layer = 11;
            newobj.transform.SetParent(generatePoint);

            //顶点少的情况可以使用它 否则会报错超出顶点限制
            MeshCollider meshCollider2 = newobj.AddComponent<MeshCollider>();

            try
            {
                meshCollider.convex = true;
                meshCollider2.convex = true;
            }
            catch (Exception e)
            {
                Debug.LogWarning(e.Message);
            }


            float obj2Volume = CalculateVolumeHelper.CalculateSumVolume(newobj.transform.lossyScale, newobj.GetComponent<MeshFilter>());

            //this.cutCallback(Mathf.Min(obj1Volume, obj2Volume));
            //比较两者体积,较小的一个进行添加刚体 自由落体...
            if (obj1Volume < obj2Volume)
            {
                //hitTarget物体掉落 消失
                Rigidbody rigidbody1 = hitTarget.gameObject.GetOrAddComponent<Rigidbody>();
                rigidbody1.AddForce((hitTarget.InverseTransformDirection(cutNormalDir) * force), ForceMode.Impulse); //可去掉这个力            
                CutObjectDestroyBySelf cutObjectDestroyBySelf = hitTarget.gameObject.GetComponent<CutObjectDestroyBySelf>();
                if (!cutObjectDestroyBySelf)
                {
                    cutObjectDestroyBySelf = hitTarget.gameObject.AddComponent<CutObjectDestroyBySelf>();
                    cutObjectDestroyBySelf.time = destroyTime;
                }
                cutObjectDestroyBySelf.SetMat(dissolveMat);

                Rigidbody newobjRigidbody = newobj.GetComponent<Rigidbody>();
                if (newobjRigidbody)
                {
                    Destroy(newobjRigidbody);
                }
                lastCutObject = newobj;
            }
            else
            {
                Rigidbody rigidbody2 = newobj.GetOrAddComponent<Rigidbody>();
                rigidbody2.AddForce(-newobj.transform.InverseTransformDirection(cutNormalDir) * force, ForceMode.Impulse);//可去掉这个力            
                CutObjectDestroyBySelf cutObjectDestroyBySelf = newobj.GetComponent<CutObjectDestroyBySelf>();
                if (!cutObjectDestroyBySelf)
                {
                    cutObjectDestroyBySelf = newobj.AddComponent<CutObjectDestroyBySelf>();
                    cutObjectDestroyBySelf.time = destroyTime;
                }
                cutObjectDestroyBySelf.SetMat(dissolveMat);

                Rigidbody hitTargetRigidbody = hitTarget.gameObject.GetComponent<Rigidbody>();
                if (hitTargetRigidbody)
                {
                    Destroy(hitTargetRigidbody);
                }
                lastCutObject = hitTarget.gameObject;
            }
            //Destroy(newobj, 5f);
        }

        sw.Stop();
        Debug.Log($"代码块执行时间: {sw.ElapsedMilliseconds} 毫秒"); // 输出执行时间
    }

    bool IsEqualFloat(float a, float b)
    {
        float num = a - b;
        if (num < 0.01f && num > -0.01f)
        {
            return true;
        }
        return false;
    }

    bool IsEqualTwoPoint(Vector3 a, Vector3 b)
    {
        if (IsEqualFloat(a.x, b.x) && IsEqualFloat(a.y, b.y) && IsEqualFloat(a.z, b.z))
        {
            return true;
        }
        return false;
    }

    //临时方法过滤异常三角面
    bool TempFuncFilterErrorTriangle(ref List<Vector3> vertices, ref List<int> triangles, ref List<Vector3> normals)
    {
        bool isFilter = false;
        List<Vector3> newVertices = new List<Vector3>();
        List<int> newTriangles = new List<int>();
        List<Vector3> newNormals = new List<Vector3>();
        int index = 0;
        //剔除三角面的3个顶点位置数据全相同的三角面
        for (int i = 0; i < triangles.Count / 3; i++)
        {
            int i0 = triangles[i * 3];
            int i1 = triangles[i * 3 + 1];
            int i2 = triangles[i * 3 + 2];

            Vector3 v0 = vertices[i0];
            Vector3 v1 = vertices[i1];
            Vector3 v2 = vertices[i2];

            if (IsEqualTwoPoint(v0, v1) || IsEqualTwoPoint(v1, v2) || IsEqualTwoPoint(v2, v0))
            {
                isFilter = true;
                //Debug.Log("有过滤!");
            }
            else
            {
                newVertices.Add(v0);
                newVertices.Add(v1);
                newVertices.Add(v2);

                newTriangles.Add(index++);
                newTriangles.Add(index++);
                newTriangles.Add(index++);

                newNormals.Add(normals[i0]);
                newNormals.Add(normals[i1]);
                newNormals.Add(normals[i2]);
            }
        }
        //if (isFilter)
        //{
        //    Debug.Log(vertices.Count + ", " + newVertices.Count + "," + triangles.Count + "," + normals.Count);
        //}
        vertices = newVertices;
        triangles = newTriangles;
        normals = newNormals;
        return isFilter;
    }

    //计算交点
    void CaculateIntersectionPoint(Vector3 v1, Vector3 v2)
    {
        Vector3 localIntersectionPointPos = hitTarget.InverseTransformPoint(MathHelper.GetIntersectionPoint(cutNormalDir, hitPos, hitTarget.TransformPoint(v1), hitTarget.TransformPoint(v2)));
        localPos.Add(localIntersectionPointPos);
        allPos.Add(localIntersectionPointPos);
    }

    void ConnectPointToTriangle(int index, Vector3 p1, Vector3 p2, Vector3 normal, ref List<Vector3> tempVert, ref List<Vector3> tempNormal, ref List<int> tempTriangle, ref Dictionary<int, int> tempIndex)
    {
        //可能还未添加
        if (!tempIndex.ContainsKey(index))
        {
            tempVert.Add(targetMesh.vertices[index]);
            tempNormal.Add(targetMesh.normals[index]);
            tempIndex.Add(index, tempVert.Count - 1);
        }

        Vector3 v = targetMesh.vertices[index];
        Vector3 vp1 = p1 - v;
        Vector3 p1p2 = p2 - p1;
        Vector3 p2v = v - p2;

        tempVert.Add(p1);
        int p1Index = tempVert.Count - 1;
        tempVert.Add(p2);
        int p2Index = tempVert.Count - 1;
        tempNormal.Add(targetMesh.normals[index]);
        tempNormal.Add(targetMesh.normals[index]);

        int vIndex = tempIndex[index];

        //v -> p1 -> p2
        if (Vector3.Dot(normal, Vector3.Cross(vp1, p1p2)) > 0)
        {
            tempTriangle.Add(vIndex);
            tempTriangle.Add(p1Index);
            tempTriangle.Add(p2Index);
        }
        else
        {
            //p2 -> p1 -> v
            tempTriangle.Add(p2Index);
            tempTriangle.Add(p1Index);
            tempTriangle.Add(vIndex);
        }
    }

    void ConnectPointToTriangle(int index1, int index2, Vector3 p1, Vector3 p2, Vector3 normal, ref List<Vector3> tempVert, ref List<Vector3> tempNormal, ref List<int> tempTriangle, ref Dictionary<int, int> tempIndex
        , int index3)
    {

        //可能还未添加
        if (!tempIndex.ContainsKey(index1))
        {
            tempVert.Add(targetMesh.vertices[index1]);
            tempNormal.Add(targetMesh.normals[index1]);
            tempIndex.Add(index1, tempVert.Count - 1);
        }
        if (!tempIndex.ContainsKey(index2))
        {
            tempVert.Add(targetMesh.vertices[index2]);
            tempNormal.Add(targetMesh.normals[index2]);
            tempIndex.Add(index2, tempVert.Count - 1);
        }

        //1.切割点放入tempVert tempNormal
        tempVert.Add(p1);
        int p1Index = tempVert.Count - 1;
        tempVert.Add(p2);
        int p2Index = tempVert.Count - 1;
        tempNormal.Add(targetMesh.normals[index1]);
        tempNormal.Add(targetMesh.normals[index2]);

        Vector3 v1 = targetMesh.vertices[index1];
        Vector3 v2 = targetMesh.vertices[index2];
        //试错方式进行连接
        Vector3 v1v2 = v2 - v1;
        Vector3 v2p1 = p1 - v2;

        Vector3 p1v1 = v1 - p1;

        //说明是正确的顺时针
        if (Vector3.Dot(normal, Vector3.Cross(v1v2, v2p1)) > 0)
        {
            //获取到真正的索引
            int v1Index = tempIndex[index1];
            int v2Index = tempIndex[index2];

            //v1->v2->p1
            tempTriangle.Add(v1Index);
            tempTriangle.Add(v2Index);
            tempTriangle.Add(p1Index);
            if (v1Index == v2Index || v1Index == p1Index || v2Index == p1Index)
            {
                Debug.LogError("if(v1Index == v2Index || v1Index == p1Index || v2Index == p1Index) 222");
            }

            //Vector3 
            //1. v2 -> p2, p2->p1 , p1 -> v2  

            //证明不与另一个三角面相交
            if (!MathHelper.IsIntectsect(v2, p2, v1, v2) && !MathHelper.IsIntectsect(p2, p1, v1, v2) && !MathHelper.IsIntectsect(p1, v2, v1, v2)
                && !MathHelper.IsIntectsect(v2, p2, v2, p1) && !MathHelper.IsIntectsect(p2, p1, v2, p1) && !MathHelper.IsIntectsect(p1, v2, v2, p1)
                && !MathHelper.IsIntectsect(v2, p2, p1, v1) && !MathHelper.IsIntectsect(p2, p1, p1, v1) && !MathHelper.IsIntectsect(p1, v2, p1, v1))
            {
                Vector3 _v2p2 = p2 - v2;
                Vector3 _p2p1 = p1 - p2;
                Vector3 _p1v2 = v2 - p1;

                //(v2 -> p2 -> p1)
                if (Vector3.Dot(normal, Vector3.Cross(_v2p2, _p2p1)) > 0)
                {
                    tempTriangle.Add(v2Index);
                    tempTriangle.Add(p2Index);
                    tempTriangle.Add(p1Index);
                    if (v2Index == p2Index || p2Index == p1Index || p1Index == v2Index)
                    {
                        Debug.LogError("if (v2Index == p2Index || p2Index == p1Index || p1Index == v2Index) 1111");
                    }
                }
                else
                {
                    //p1 -> p2 -> v2 (反转)
                    tempTriangle.Add(p1Index);
                    tempTriangle.Add(p2Index);
                    tempTriangle.Add(v2Index);
                    if (p1Index == p2Index || p2Index == v2Index || v2Index == p1Index)
                    {
                        Debug.LogError(" if (p1Index == p2Index || p2Index == v2Index || v2Index == p1Index) 8888");
                    }
                }
            }
            else if (!MathHelper.IsIntectsect(v1, p2, v1, v2) && !MathHelper.IsIntectsect(p2, p1, v1, v2) && !MathHelper.IsIntectsect(p1, v1, v1, v2)
                && !MathHelper.IsIntectsect(v1, p2, v2, p1) && !MathHelper.IsIntectsect(p2, p1, v2, p1) && !MathHelper.IsIntectsect(p1, v1, v2, p1)
                && !MathHelper.IsIntectsect(v1, p2, p1, v1) && !MathHelper.IsIntectsect(p2, p1, p1, v1) && !MathHelper.IsIntectsect(p1, v1, p1, v1))
            {
                //2. v1->p2, p2->p1, p1->v1
                Vector3 _v1p2 = p2 - v1;
                Vector3 _p2p1 = p1 - p2;
                Vector3 _p1v1 = v1 - p1;

                //(v1 -> p2 -> p1)
                if (Vector3.Dot(normal, Vector3.Cross(_v1p2, _p2p1)) > 0)
                {
                    tempTriangle.Add(v1Index);
                    tempTriangle.Add(p2Index);
                    tempTriangle.Add(p1Index);
                    if (v1Index == p2Index || p2Index == p1Index || p1Index == v1Index)
                    {
                        Debug.LogError(" if (p1Index == p2Index || p2Index == v2Index || v2Index == p1Index) 8888");
                    }
                }
                else
                {
                    //p1 -> p2 -> v1 (反转)
                    tempTriangle.Add(p1Index);
                    tempTriangle.Add(p2Index);
                    tempTriangle.Add(v1Index);
                    if (p1Index == p2Index || p2Index == v1Index || v1Index == p1Index)
                    {
                        Debug.LogError("if (p1Index == p2Index || p2Index == v1Index || v1Index == p1Index) 66666");
                    }
                }
            }
            else
            {
                //发现是p1,p2是相同的...v1,v2非常相近的情况 没有很大影响 暂时忽略
                Debug.Log(v1);
                Debug.Log(v2);
                Debug.Log(p1 + "\n");

                Debug.Log(v2);
                Debug.Log(p2);
                Debug.Log(p1 + "\n");

                Debug.Log(v1);
                Debug.Log(p2);
                Debug.Log(p1 + "\n");
                Debug.LogWarning("绝对不会出现的....但是出现过,具体原因未知"); //?? 一般切割2D的平面会出现这种情况,但实际每有很大影响 
            }
        }
        else
        {
            //Debug.DrawLine(v1, v2, Color.blue);
            //Debug.DrawLine(p1, p1, Color.green);

            //Debug.DrawLine(v2, p1, Color.red);

            //出现了v1和v2相同情况,p1和p2也相同..然后就这样了
            //确实是会存在顶点相同的情况这种情况无法构成面应该忽略!

            if (v1 == p1 || v2 == p1 || v1 == v2)
            {
                //正常现象 或者你可以控制。。交点确实是有可能存在和v1,v2相同的情况...
                //Debug.LogError(">>>>111//正常现象 或者你可以控制。。交点确实是有可能存在和v1,v2相同的情况...");
            }
            else
            {
                //当点之间非常相近时会出现这种情况,暂时忽略。。 或者是API的问题
                //Debug.Log(index1);
                //Debug.Log(index2);
                //Debug.Log(index3);
                //Debug.Log("v1:" + v1 + "," + (v1 == p1));
                //Debug.Log("v2:" + v2 + "," + (v2 == p1));
                //Debug.Log("v3:" + targetMesh.vertices[index3]);
                //Debug.Log("p1:" + p1);
                //Debug.Log("p2:" + p2);
                //Debug.Log("Cross:" + Vector3.Dot(normal, Vector3.Cross(v1v2, v2p1)));
                 p1 -> v2 -> v1 相反
                //Debug.LogWarning("从逻辑上看,不可能进入! 但是进去了 不知道为什么...");  //????
            }
        }
    }

    void FillCutSurface()
    {
        //Debug.Log("allPos.Count = " + allPos.Count);
        if (allPos.Count <= 0)
        {
            //Debug.LogError("切割面的顶点全都没有..."); //?????? 算正常吧???....
            return;
        }
        Vector3 center = (allPos[0] + allPos[allPos.Count / 2]) * 0.5f;
        Vector3 normal = hitTarget.InverseTransformDirection(cutNormalDir);

        tempVert1.Add(center);
        int center1Index = tempVert1.Count - 1;
        tempNormal1.Add(-normal);

        tempVert2.Add(center);
        int center2Index = tempVert2.Count - 1;
        tempNormal2.Add(normal);

        for (int i = 0; i < allPos.Count; i += 2)
        {
            //排除相同顶点的情况,只要有三角面2点位置相同,那就无法构成三角面 忽略...(不然会出问题)
            if (allPos[i] == allPos[i + 1] || allPos[i] == center || center == allPos[i + 1])
            {
                continue;
            }
            tempVert1.Add(allPos[i]);
            int tempVert1AllPos1Index = tempVert1.Count - 1;
            tempVert1.Add(allPos[i + 1]);
            int tempVert1AllPos2Index = tempVert1.Count - 1;

            tempNormal1.Add(-normal);
            tempNormal1.Add(-normal);

            Vector3 a1 = allPos[i] - center;
            //Vector3 a2 = allPos[i + 1] - allPos[i];
            Vector3 a2 = allPos[i + 1] - center;
            Vector3 crossA1A2 = Vector3.Cross(a1, a2);

            if (Vector3.Dot(-normal, crossA1A2) >= 0)
            {
                tempTriangles1.Add(center1Index);
                tempTriangles1.Add(tempVert1AllPos1Index);
                tempTriangles1.Add(tempVert1AllPos2Index);
                if (center1Index == tempVert1AllPos1Index || center1Index == tempVert1AllPos2Index || tempVert1AllPos1Index == tempVert1AllPos2Index)
                {
                    Debug.Log(
                         center + "," + allPos[i] + "," + allPos[i + 1]
                         + "\n " + tempVert1.LastIndexOf(center) + "," + tempVert1AllPos1Index + "," + tempVert1AllPos2Index + "," + allPos.Count);
                    Debug.LogError("tempVert1.LastIndexOf(center) == tempVert1AllPos1Index || tempVert1.LastIndexOf(center) == tempVert1AllPos2Index || tempVert1AllPos1Index == tempVert1AllPos2Index 9999999999");
                }
            }
            else
            {
                tempTriangles1.Add(tempVert1AllPos2Index);
                tempTriangles1.Add(tempVert1AllPos1Index);
                tempTriangles1.Add(center1Index);
                if (center1Index == tempVert1AllPos1Index || center1Index == tempVert1AllPos2Index || tempVert1AllPos1Index == tempVert1AllPos2Index)
                {
                    Debug.Log(
                        center + "," + allPos[i] + "," + allPos[i + 1] + "\n" +
                        tempVert1.LastIndexOf(center) + "," + tempVert1AllPos1Index + "," + tempVert1AllPos2Index + "," + allPos.Count);
                    Debug.LogError("if (tempVert1.LastIndexOf(center) == tempVert1AllPos1Index || tempVert1.LastIndexOf(center) == tempVert1AllPos2Index || tempVert1AllPos1Index == tempVert1AllPos2Index) -----------");
                }
            }

            tempVert2.Add(allPos[i]);
            int tempV1Index = tempVert2.Count - 1;
            tempVert2.Add(allPos[i + 1]);
            int tempV2Index = tempVert2.Count - 1;

            tempNormal2.Add(normal);
            tempNormal2.Add(normal);

            if (Vector3.Dot(normal, crossA1A2) >= 0)
            {
                tempTriangles2.Add(center2Index);
                tempTriangles2.Add(tempV1Index);
                tempTriangles2.Add(tempV2Index);
                if (center2Index == tempV1Index || center2Index == tempV2Index || tempV1Index == tempV2Index)
                {
                    Debug.Log(
                        center + "," + allPos[i] + "," + allPos[i + 1] + "\n" +
                        tempVert2.LastIndexOf(center) + "," + tempV1Index + "," + tempV2Index + "," + allPos.Count);
                    Debug.LogError("tempVert2.LastIndexOf(center) == tempV1Index || tempVert2.LastIndexOf(center) == tempV2Index || tempV1Index == tempV2Index /");
                }
            }
            else
            {
                tempTriangles2.Add(tempV2Index);
                tempTriangles2.Add(tempV1Index);
                tempTriangles2.Add(center2Index);
                if (center2Index == tempV1Index || center2Index == tempV2Index || tempV1Index == tempV2Index)
                {
                    Debug.Log(
                        center + "," + allPos[i] + "," + allPos[i + 1] + "\n" +
                        tempVert2.LastIndexOf(center) + "," + tempV1Index + "," + tempV2Index + "," + allPos.Count);
                    Debug.LogError("tempVert2.LastIndexOf(center) == tempV1Index || tempVert2.LastIndexOf(center) == tempV2Index || tempV1Index == tempV2Index qqqqqqq");
                }
            }

        }
    }

    /// <summary>
    /// 计算Box的UV方法 
    /// </summary>
    void CalculateUV(Vector3 size, List<Vector3> vertices, List<int> triangles, List<Vector3> normals, ref List<Vector2> uvs)
    {
        uvs = new List<Vector2>();
        for (int i = 0; i < vertices.Count; i++)
        {
            uvs.Add(new Vector2(0, 0));
        }
        for (int i = 0; i < triangles.Count / 3; i++)
        {
            int i0 = triangles[i * 3];
            int i1 = triangles[i * 3 + 1];
            int i2 = triangles[i * 3 + 2];

            //Vector3 v0 = vertices[i0] - center + size / 2f;
            //Vector3 v1 = vertices[i1] - center + size / 2f;
            //Vector3 v2 = vertices[i2] - center + size / 2f;

            Vector3 v0 = vertices[i0];
            Vector3 v1 = vertices[i1];
            Vector3 v2 = vertices[i2];

            string str = string.Format("原始数据:({0},{1},{2}) index:({3},{4},{5})", v0.ToString(), v1.ToString(), v2.ToString(), i0, i1, i2);

            // 除以size.x,y,z是为了缩小范围到[0,1] UV的范围
            v0 = new Vector3(v0.x / size.x, v0.y / size.y, v0.z / size.z);
            v1 = new Vector3(v1.x / size.x, v1.y / size.y, v1.z / size.z);
            v2 = new Vector3(v2.x / size.x, v2.y / size.y, v2.z / size.z);

            //Vector3 a = v0 - v1;
            //Vector3 b = v2 - v1; 
            Vector3 a = v1 - v0;
            Vector3 b = v2 - v1;

            //我老感觉这法线计算错了...v0->v1-v2             
            Vector3 dir = normals[i0]; //Vector3.Cross(a, b);  //改用顶点法线作为法线
            float x = Mathf.Abs(Vector3.Dot(dir, Vector3.right));
            float y = Mathf.Abs(Vector3.Dot(dir, Vector3.up));
            float z = Mathf.Abs(Vector3.Dot(dir, Vector3.forward));
            //法线倾向于X轴,用Z作为X,Y作为Y
            if (x > y && x > z)
            {
                uvs[i0] = new Vector2(v0.z, v0.y);
                uvs[i1] = new Vector2(v1.z, v1.y);
                uvs[i2] = new Vector2(v2.z, v2.y);
            }
            else if (y > z && y > x)
            {
                //法线倾向于Y轴,用X作为X,Z作为Y
                uvs[i0] = new Vector2(v0.x, v0.z);
                uvs[i1] = new Vector2(v1.x, v1.z);
                uvs[i2] = new Vector2(v2.x, v2.z);
            }
            else if (z > x && z > y)
            {
                //法线倾向于Z轴,用X作为X,Y作为Y
                uvs[i0] = new Vector2(v0.x, v0.y);
                uvs[i1] = new Vector2(v1.x, v1.y);
                uvs[i2] = new Vector2(v2.x, v2.y);
            }
            else
            {
                //防止出现UV不正常情况
                uvs[i0] = new Vector2(0, 0);
                uvs[i1] = new Vector2(1, 1);
                uvs[i2] = new Vector2(0, 0);
                //Debug.LogWarning("UV出问题啦..." + x + ", " + y + "," + z + "\n"
                //    + v0 + ", " + v1 + "," + v2 + " \n"
                //    + a + ", " + b + "\n"
                //    + dir + "\n"
                //    + str);//虽然已经处理了异常三角面,但仍然会出现(x,y,z)全为0的情况...先放任不管看看效果...
            }
        }
    }


    public void ClearCutInfos()
    {
        cutInfos?.Clear();
    }

    public void DestroyLastCutObject()
    {
        if (lastCutObject != null)
        {
            Destroy(lastCutObject);
        }
    }

    public void SetLastCutObject(GameObject obj)
    {
        lastCutObject = obj;
    }

    public void AddCutCallback(Action<float> action)
    {
        cutCallback = action;
    }
}
using System.Collections;
using System.Collections.Generic;
using Unity.Burst;
using Unity.Collections;
using Unity.Jobs;
using UnityEngine;

[BurstCompile]
public struct CutJob : IJob
{
    public int targetMeshTriangles_Count;
    public NativeArray<Vector3> targetMeshVert;
    public NativeArray<Vector3> targetMeshNormal;
    public NativeArray<int> targetMeshTriangles;

    public Matrix4x4 hitTarget_o2w;
    public Matrix4x4 hitTarget_w2o;
    public Vector3 hitTarget_LocalScale;

    int localPos_Count;
    int allPos_Count;
    public NativeArray<Vector3> localPos;
    public NativeArray<Vector3> allPos;

    public int tempVert1_Count;
    public int tempNormal1_Count;
    public int tempTriangles1_Count;
    public int uvs1_Count;
    public NativeArray<Vector3> tempVert1;
    public NativeArray<Vector3> tempNormal1;
    public NativeArray<int> tempTriangles1;
    public NativeHashMap<int, int> tempIndex1;
    public NativeArray<Vector2> uvs1;
    public NativeArray<int> temp1CountArray;

    public int tempVert2_Count;
    public int tempNormal2_Count;
    public int tempTriangles2_Count;
    public int uvs2_Count;
    public NativeArray<Vector3> tempVert2;
    public NativeArray<Vector3> tempNormal2;
    public NativeArray<int> tempTriangles2;
    public NativeHashMap<int, int> tempIndex2;
    public NativeArray<Vector2> uvs2;
    public NativeArray<int> temp2CountArray;

    public Vector3 hitPos;

    public Vector3 dir;
    public Vector3 cutVerticalDir;
    public Vector3 cutNormalDir;

    public void Execute()
    {
        Cutting();
    }

    #region 切割

    void Cutting()
    {

        //tempVert1.Clear();
        //tempNormal1.Clear();
        //tempTriangles1.Clear();
        //tempIndex1.Clear();
        //uvs1.Clear();

        //tempVert2.Clear();
        //tempNormal2.Clear();
        //tempTriangles2.Clear();
        //tempIndex2.Clear();
        //uvs2.Clear();

        //allPos.Clear();

        for (int i = 0; i < targetMeshTriangles.Length; i += 3)
        {
            int index1 = targetMeshTriangles[i];
            int index2 = targetMeshTriangles[i + 1];
            int index3 = targetMeshTriangles[i + 2];

            Vector3 vertex1 = targetMeshVert[index1];
            Vector3 vertex2 = targetMeshVert[index2];
            Vector3 vertex3 = targetMeshVert[index3];

            float vert1 = Vector3.Dot(cutNormalDir, (hitTarget_o2w.MultiplyPoint(vertex1) - hitPos).normalized);
            float vert2 = Vector3.Dot(cutNormalDir, (hitTarget_o2w.MultiplyPoint(vertex2) - hitPos).normalized);
            float vert3 = Vector3.Dot(cutNormalDir, (hitTarget_o2w.MultiplyPoint(vertex3) - hitPos).normalized);

            if (vert1 >= 0 && vert2 >= 0 && vert3 >= 0)
            {
                //同面
                if (!tempIndex1.ContainsKey(index1)) //过滤相同顶点
                {
                    tempVert1[tempVert1_Count++] = vertex1;
                    tempNormal1[tempNormal1_Count++] = targetMeshNormal[index1];
                    tempIndex1.Add(index1, tempVert1_Count - 1); //旧索引为key,新索引为value
                }

                if (!tempIndex1.ContainsKey(index2)) //过滤相同顶点
                {
                    tempVert1[tempVert1_Count++] = vertex2;
                    tempNormal1[tempNormal1_Count++] = targetMeshNormal[index2];

                    tempIndex1.Add(index2, tempVert1_Count - 1); //旧索引为key,新索引为value
                }

                if (!tempIndex1.ContainsKey(index3)) //过滤相同顶点
                {
                    tempVert1[tempVert1_Count++] = vertex3;
                    tempNormal1[tempNormal1_Count++] = targetMeshNormal[index3];

                    tempIndex1.Add(index3, tempVert1_Count - 1); //旧索引为key,新索引为value
                }


                tempTriangles1[tempTriangles1_Count++] = tempIndex1[index1]; //使用旧索引index1 获取对应的新索引
                tempTriangles1[tempTriangles1_Count++] = tempIndex1[index2]; //使用旧索引index2 获取对应的新索引
                tempTriangles1[tempTriangles1_Count++] = tempIndex1[index3]; //使用旧索引index3 获取对应的新索引

                if (tempIndex1[index1] == tempIndex1[index2] || tempIndex1[index1] == tempIndex1[index3] || tempIndex1[index2] == tempIndex1[index3])
                {
                    //Debug.LogError("[1]問題");
                }
            }
            else if (vert1 <= 0 && vert2 <= 0 && vert3 <= 0)
            {
                //另一个同面                
                if (!tempIndex2.ContainsKey(index1)) //过滤相同顶点
                {
                    tempVert2[tempVert2_Count++] = (vertex1);
                    tempNormal2[tempNormal2_Count++] = (targetMeshNormal[index1]);

                    tempIndex2.Add(index1, tempVert2_Count - 1); //旧索引为key,新索引为value
                }

                if (!tempIndex2.ContainsKey(index2)) //过滤相同顶点
                {
                    tempVert2[tempVert2_Count++] = (vertex2);
                    tempNormal2[tempNormal2_Count++] = (targetMeshNormal[index2]);

                    tempIndex2.Add(index2, tempVert2_Count - 1); //旧索引为key,新索引为value
                }

                if (!tempIndex2.ContainsKey(index3)) //过滤相同顶点
                {
                    tempVert2[tempVert2_Count++] = (vertex3);
                    tempNormal2[tempNormal2_Count++] = (targetMeshNormal[index3]);

                    tempIndex2.Add(index3, tempVert2_Count - 1); //旧索引为key,新索引为value
                }

                tempTriangles2[tempTriangles2_Count++] = (tempIndex2[index1]); //使用旧索引index1 获取对应的新索引
                tempTriangles2[tempTriangles2_Count++] = (tempIndex2[index2]); //使用旧索引index2 获取对应的新索引
                tempTriangles2[tempTriangles2_Count++] = (tempIndex2[index3]); //使用旧索引index3 获取对应的新索引
                if (tempIndex2[index1] == tempIndex2[index2] || tempIndex2[index1] == tempIndex2[index3] || tempIndex2[index2] == tempIndex2[index3])
                {
                    //Debug.LogError("[2]問題");
                }
            }
            else
            {
                //continue;

                localPos_Count = 0;
                //不同面情况 (PS:不存在3点不同面情况)

                bool isV1V2Sample = (vert1 > 0 && vert2 > 0 || vert1 < 0 && vert2 < 0);
                bool isV2V3Sample = (vert2 > 0 && vert3 > 0 || vert2 < 0 && vert3 < 0);
                bool isV3V1Sample = (vert3 > 0 && vert1 > 0 || vert3 < 0 && vert1 < 0);

                Vector3 normal = Vector3.Cross(vertex2 - vertex1, vertex3 - vertex2);

                //1. index1 和 index2 顶点不同面
                if (!(isV1V2Sample))
                {
                    CaculateIntersectionPoint(vertex1, vertex2);
                }

                //2. index2 和 index3 顶点不同面
                if (!(isV2V3Sample))
                {
                    CaculateIntersectionPoint(vertex2, vertex3);
                }

                //3. index3 和 index1 顶点不同面
                if (!(isV3V1Sample))
                {
                    CaculateIntersectionPoint(vertex3, vertex1);
                }

                //此时localPos保存2个交点, allPos是保存所有交点的
                if (isV1V2Sample)
                {
                    if (vert1 > 0 && vert2 > 0)
                    {
                        if (index1 == index2)
                        {
                            //Debug.LogError(">>>>>>>>>>>>>>>>>>>>>1 : " + index1);
                        }
                        ConnectPointToTriangle(index1, index2, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1, index3
                            , ref tempVert1_Count, ref tempNormal1_Count, ref tempTriangles1_Count);
                        ConnectPointToTriangle(index3, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2
                            , ref tempVert2_Count, ref tempNormal2_Count, ref tempTriangles2_Count);
                    }
                    else
                    {
                        if (index1 == index2)
                        {
                            //Debug.LogError(">>>>>>>>>>>>>>>>>>>>>2 : " + index1);
                        }
                        ConnectPointToTriangle(index1, index2, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2, index3
                            , ref tempVert2_Count, ref tempNormal2_Count, ref tempTriangles2_Count);
                        ConnectPointToTriangle(index3, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1
                            , ref tempVert1_Count, ref tempNormal1_Count, ref tempTriangles1_Count);
                    }
                }

                if (isV2V3Sample)
                {
                    if (vert2 > 0 && vert3 > 0)
                    {
                        if (index2 == index3)
                        {
                            //Debug.LogError(">>>>>>>>>>>>>>>>>>>>>3 : " + index2);
                        }
                        ConnectPointToTriangle(index2, index3, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1, index1
                            , ref tempVert1_Count, ref tempNormal1_Count, ref tempTriangles1_Count);
                        ConnectPointToTriangle(index1, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2
                            , ref tempVert2_Count, ref tempNormal2_Count, ref tempTriangles2_Count);
                    }
                    else
                    {
                        if (index2 == index3)
                        {
                            //Debug.LogError(">>>>>>>>>>>>>>>>>>>>>4 : " + index2);
                        }
                        ConnectPointToTriangle(index2, index3, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2, index1
                            , ref tempVert2_Count, ref tempNormal2_Count, ref tempTriangles2_Count);
                        ConnectPointToTriangle(index1, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1
                            , ref tempVert1_Count, ref tempNormal1_Count, ref tempTriangles1_Count);
                    }
                }

                if (isV3V1Sample)
                {
                    if (vert3 > 0 && vert1 > 0)
                    {
                        if (index3 == index1)
                        {
                            //Debug.LogError(">>>>>>>>>>>>>>>>>>>>>5 : " + index3);
                        }
                        ConnectPointToTriangle(index3, index1, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1, index2
                            , ref tempVert1_Count, ref tempNormal1_Count, ref tempTriangles1_Count);
                        ConnectPointToTriangle(index2, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2
                            , ref tempVert2_Count, ref tempNormal2_Count, ref tempTriangles2_Count);
                    }
                    else
                    {
                        if (index3 == index1)
                        {
                            //Debug.LogError(">>>>>>>>>>>>>>>>>>>>>6 : " + index3);
                        }
                        ConnectPointToTriangle(index3, index1, localPos[0], localPos[1], normal, ref tempVert2, ref tempNormal2, ref tempTriangles2, ref tempIndex2, index2
                            , ref tempVert2_Count, ref tempNormal2_Count, ref tempTriangles2_Count);
                        ConnectPointToTriangle(index2, localPos[0], localPos[1], normal, ref tempVert1, ref tempNormal1, ref tempTriangles1, ref tempIndex1
                            , ref tempVert1_Count, ref tempNormal1_Count, ref tempTriangles1_Count);
                    }
                }

            }
        }

        //补全截面
        FillCutSurface();

        //注释下面两行代码,UV纹理全没但报错没了(目前UV组成有问题可能会导致模型某一面完全透明)
        //BUG已查明:上面代码生成新2个网格数据 会存在三角面的3个顶点位置数据一样,导致UV无法正常出现,因此此时简单地做个后处理 剔除这些异常三角面 ...      
        //bool isFilter1 = TempFuncFilterErrorTriangle(ref tempVert1, ref tempTriangles1, ref tempNormal1); //依然有问题 待修复...
        //bool isFilter2 = TempFuncFilterErrorTriangle(ref tempVert2, ref tempTriangles2, ref tempNormal2);

        CalculateUV(hitTarget_LocalScale, ref tempVert1, ref tempTriangles1, ref tempNormal1, ref uvs1
            , ref tempVert1_Count, ref tempTriangles1_Count, ref tempNormal1_Count, ref uvs1_Count);

        CalculateUV(hitTarget_LocalScale, ref tempVert2, ref tempTriangles2, ref tempNormal2, ref uvs2
            , ref tempVert2_Count, ref tempTriangles2_Count, ref tempNormal2_Count, ref uvs2_Count);


        temp1CountArray[0] = tempVert1_Count;
        temp1CountArray[1] = tempNormal1_Count;
        temp1CountArray[2] = tempTriangles1_Count;
        temp1CountArray[3] = uvs1_Count;

        temp2CountArray[0] = tempVert2_Count;
        temp2CountArray[1] = tempNormal2_Count;
        temp2CountArray[2] = tempTriangles2_Count;
        temp2CountArray[3] = uvs2_Count;
    }

    bool IsEqualFloat(float a, float b)
    {
        float num = a - b;
        if (num < 0.01f && num > -0.01f)
        {
            return true;
        }
        return false;
    }
    

    //计算交点
    void CaculateIntersectionPoint(Vector3 v1, Vector3 v2)
    {
        Vector3 localIntersectionPointPos = hitTarget_w2o.MultiplyPoint(MathHelper.GetIntersectionPoint(cutNormalDir, hitPos, hitTarget_o2w.MultiplyPoint(v1), hitTarget_o2w.MultiplyPoint(v2)));
        localPos[localPos_Count++] = (localIntersectionPointPos);
        allPos[allPos_Count++] = (localIntersectionPointPos);
    }

    void ConnectPointToTriangle(int index, Vector3 p1, Vector3 p2, Vector3 normal, ref NativeArray<Vector3> tempVert, ref NativeArray<Vector3> tempNormal, ref NativeArray<int> tempTriangle, ref NativeHashMap<int, int> tempIndex
        , ref int tempVertCount, ref int tempNormalCount, ref int tempTriangleCount)
    {
        //可能还未添加
        if (!tempIndex.ContainsKey(index))
        {
            tempVert[tempVertCount++] = (targetMeshVert[index]);
            tempNormal[tempNormalCount++] = (targetMeshNormal[index]);
            tempIndex.Add(index, tempVertCount - 1);
        }

        Vector3 v = targetMeshVert[index];
        Vector3 vp1 = p1 - v;
        Vector3 p1p2 = p2 - p1;
        Vector3 p2v = v - p2;

        tempVert[tempVertCount++] = (p1);
        int p1Index = tempVertCount - 1;
        tempVert[tempVertCount++] = (p2);
        int p2Index = tempVertCount - 1;
        tempNormal[tempNormalCount++] = (targetMeshNormal[index]);
        tempNormal[tempNormalCount++] = (targetMeshNormal[index]);

        int vIndex = tempIndex[index];

        //v -> p1 -> p2
        if (Vector3.Dot(normal, Vector3.Cross(vp1, p1p2)) > 0)
        {
            tempTriangle[tempTriangleCount++] = (vIndex);
            tempTriangle[tempTriangleCount++] = (p1Index);
            tempTriangle[tempTriangleCount++] = (p2Index);
        }
        else
        {
            //p2 -> p1 -> v
            tempTriangle[tempTriangleCount++] = (p2Index);
            tempTriangle[tempTriangleCount++] = (p1Index);
            tempTriangle[tempTriangleCount++] = (vIndex);
        }
    }

    void ConnectPointToTriangle(int index1, int index2, Vector3 p1, Vector3 p2, Vector3 normal, ref NativeArray<Vector3> tempVert, ref NativeArray<Vector3> tempNormal, ref NativeArray<int> tempTriangle, ref NativeHashMap<int, int> tempIndex
        , int index3, ref int tempVertCount, ref int tempNormalCount, ref int tempTriangleCount)
    {

        //可能还未添加
        if (!tempIndex.ContainsKey(index1))
        {
            tempVert[tempVertCount++] = (targetMeshVert[index1]);
            tempNormal[tempNormalCount++] = (targetMeshNormal[index1]);
            tempIndex.Add(index1, tempVertCount - 1);
        }
        if (!tempIndex.ContainsKey(index2))
        {
            tempVert[tempVertCount++] = (targetMeshVert[index2]);
            tempNormal[tempNormalCount++] = (targetMeshNormal[index2]);
            tempIndex.Add(index2, tempVertCount - 1);
        }

        //1.切割点放入tempVert tempNormal
        tempVert[tempVertCount++] = (p1);
        int p1Index = tempVertCount - 1;
        tempVert[tempVertCount++] = (p2);
        int p2Index = tempVertCount - 1;
        tempNormal[tempNormalCount++] = (targetMeshNormal[index1]);
        tempNormal[tempNormalCount++] = (targetMeshNormal[index2]);

        Vector3 v1 = targetMeshVert[index1];
        Vector3 v2 = targetMeshVert[index2];
        //试错方式进行连接
        Vector3 v1v2 = v2 - v1;
        Vector3 v2p1 = p1 - v2;

        Vector3 p1v1 = v1 - p1;

        //说明是正确的顺时针
        if (Vector3.Dot(normal, Vector3.Cross(v1v2, v2p1)) > 0)
        {
            //获取到真正的索引
            int v1Index = tempIndex[index1];
            int v2Index = tempIndex[index2];

            //v1->v2->p1
            tempTriangle[tempTriangleCount++] = (v1Index);
            tempTriangle[tempTriangleCount++] = (v2Index);
            tempTriangle[tempTriangleCount++] = (p1Index);
            if (v1Index == v2Index || v1Index == p1Index || v2Index == p1Index)
            {
                //Debug.LogError("if(v1Index == v2Index || v1Index == p1Index || v2Index == p1Index) 222");
            }

            //Vector3 
            //1. v2 -> p2, p2->p1 , p1 -> v2  

            //证明不与另一个三角面相交
            if (!MathHelper.IsIntectsect(v2, p2, v1, v2) && !MathHelper.IsIntectsect(p2, p1, v1, v2) && !MathHelper.IsIntectsect(p1, v2, v1, v2)
                && !MathHelper.IsIntectsect(v2, p2, v2, p1) && !MathHelper.IsIntectsect(p2, p1, v2, p1) && !MathHelper.IsIntectsect(p1, v2, v2, p1)
                && !MathHelper.IsIntectsect(v2, p2, p1, v1) && !MathHelper.IsIntectsect(p2, p1, p1, v1) && !MathHelper.IsIntectsect(p1, v2, p1, v1))
            {
                Vector3 _v2p2 = p2 - v2;
                Vector3 _p2p1 = p1 - p2;
                Vector3 _p1v2 = v2 - p1;

                //(v2 -> p2 -> p1)
                if (Vector3.Dot(normal, Vector3.Cross(_v2p2, _p2p1)) > 0)
                {
                    tempTriangle[tempTriangleCount++] = (v2Index);
                    tempTriangle[tempTriangleCount++] = (p2Index);
                    tempTriangle[tempTriangleCount++] = (p1Index);
                    if (v2Index == p2Index || p2Index == p1Index || p1Index == v2Index)
                    {
                        //Debug.LogError("if (v2Index == p2Index || p2Index == p1Index || p1Index == v2Index) 1111");
                    }
                }
                else
                {
                    //p1 -> p2 -> v2 (反转)
                    tempTriangle[tempTriangleCount++] = (p1Index);
                    tempTriangle[tempTriangleCount++] = (p2Index);
                    tempTriangle[tempTriangleCount++] = (v2Index);
                    if (p1Index == p2Index || p2Index == v2Index || v2Index == p1Index)
                    {
                        //Debug.LogError(" if (p1Index == p2Index || p2Index == v2Index || v2Index == p1Index) 8888");
                    }
                }
            }
            else if (!MathHelper.IsIntectsect(v1, p2, v1, v2) && !MathHelper.IsIntectsect(p2, p1, v1, v2) && !MathHelper.IsIntectsect(p1, v1, v1, v2)
                && !MathHelper.IsIntectsect(v1, p2, v2, p1) && !MathHelper.IsIntectsect(p2, p1, v2, p1) && !MathHelper.IsIntectsect(p1, v1, v2, p1)
                && !MathHelper.IsIntectsect(v1, p2, p1, v1) && !MathHelper.IsIntectsect(p2, p1, p1, v1) && !MathHelper.IsIntectsect(p1, v1, p1, v1))
            {
                //2. v1->p2, p2->p1, p1->v1
                Vector3 _v1p2 = p2 - v1;
                Vector3 _p2p1 = p1 - p2;
                Vector3 _p1v1 = v1 - p1;

                //(v1 -> p2 -> p1)
                if (Vector3.Dot(normal, Vector3.Cross(_v1p2, _p2p1)) > 0)
                {
                    tempTriangle[tempTriangleCount++] = (v1Index);
                    tempTriangle[tempTriangleCount++] = (p2Index);
                    tempTriangle[tempTriangleCount++] = (p1Index);
                    if (v1Index == p2Index || p2Index == p1Index || p1Index == v1Index)
                    {
                        //Debug.LogError(" if (p1Index == p2Index || p2Index == v2Index || v2Index == p1Index) 8888");
                    }
                }
                else
                {
                    //p1 -> p2 -> v1 (反转)
                    tempTriangle[tempTriangleCount++] = (p1Index);
                    tempTriangle[tempTriangleCount++] = (p2Index);
                    tempTriangle[tempTriangleCount++] = (v1Index);
                    if (p1Index == p2Index || p2Index == v1Index || v1Index == p1Index)
                    {
                        //Debug.LogError("if (p1Index == p2Index || p2Index == v1Index || v1Index == p1Index) 66666");
                    }
                }
            }
            else
            {
                //发现是p1,p2是相同的...v1,v2非常相近的情况 没有很大影响 暂时忽略
                //Debug.Log(v1);
                //Debug.Log(v2);
                //Debug.Log(p1 + "\n");

                //Debug.Log(v2);
                //Debug.Log(p2);
                //Debug.Log(p1 + "\n");

                //Debug.Log(v1);
                //Debug.Log(p2);
                //Debug.Log(p1 + "\n");
                //Debug.LogWarning("绝对不会出现的....但是出现过,具体原因未知"); //?? 一般切割2D的平面会出现这种情况,但实际每有很大影响 
            }
        }
        else
        {
            //Debug.DrawLine(v1, v2, Color.blue);
            //Debug.DrawLine(p1, p1, Color.green);

            //Debug.DrawLine(v2, p1, Color.red);

            //出现了v1和v2相同情况,p1和p2也相同..然后就这样了
            //确实是会存在顶点相同的情况这种情况无法构成面应该忽略!

            if (v1 == p1 || v2 == p1 || v1 == v2)
            {
                //正常现象 或者你可以控制。。交点确实是有可能存在和v1,v2相同的情况...
                //Debug.LogError(">>>>111//正常现象 或者你可以控制。。交点确实是有可能存在和v1,v2相同的情况...");
            }
            else
            {
                //当点之间非常相近时会出现这种情况,暂时忽略。。 或者是API的问题
                //Debug.Log(index1);
                //Debug.Log(index2);
                //Debug.Log(index3);
                //Debug.Log("v1:" + v1 + "," + (v1 == p1));
                //Debug.Log("v2:" + v2 + "," + (v2 == p1));
                //Debug.Log("v3:" + targetMeshVert[index3]);
                //Debug.Log("p1:" + p1);
                //Debug.Log("p2:" + p2);
                //Debug.Log("Cross:" + Vector3.Dot(normal, Vector3.Cross(v1v2, v2p1)));
                 p1 -> v2 -> v1 相反
                //Debug.LogWarning("从逻辑上看,不可能进入! 但是进去了 不知道为什么...");  //????
            }
        }
    }

    void FillCutSurface()
    {
        //Debug.Log("allPos_Count = " + allPos_Count);
        if (allPos_Count <= 0)
        {
            //Debug.LogError("切割面的顶点全都没有..."); //?????? 算正常吧???....
            return;
        }
        Vector3 center = (allPos[0] + allPos[allPos_Count / 2]) * 0.5f;

        Vector3 normal = hitTarget_w2o.MultiplyVector(cutNormalDir); // hitTarget.InverseTransformDirection(cutNormalDir);

        tempVert1[tempVert1_Count++] = (center);
        int center1Index = tempVert1_Count - 1;
        tempNormal1[tempNormal1_Count++] = (-normal);

        tempVert2[tempVert2_Count++] = (center);
        int center2Index = tempVert2_Count - 1;
        tempNormal2[tempNormal2_Count++] = (normal);

        for (int i = 0; i < allPos_Count; i += 2)
        {
            //排除相同顶点的情况,只要有三角面2点位置相同,那就无法构成三角面 忽略...(不然会出问题)
            if (allPos[i] == allPos[i + 1] || allPos[i] == center || center == allPos[i + 1])
            {
                continue;
            }
            tempVert1[tempVert1_Count++] = (allPos[i]);
            int tempVert1AllPos1Index = tempVert1_Count - 1;
            tempVert1[tempVert1_Count++] = (allPos[i + 1]);
            int tempVert1AllPos2Index = tempVert1_Count - 1;

            tempNormal1[tempNormal1_Count++] = (-normal);
            tempNormal1[tempNormal1_Count++] = (-normal);

            Vector3 a1 = allPos[i] - center;
            //Vector3 a2 = allPos[i + 1] - allPos[i];
            Vector3 a2 = allPos[i + 1] - center;
            Vector3 crossA1A2 = Vector3.Cross(a1, a2);

            if (Vector3.Dot(-normal, crossA1A2) >= 0)
            {
                tempTriangles1[tempTriangles1_Count++] = (center1Index);
                tempTriangles1[tempTriangles1_Count++] = (tempVert1AllPos1Index);
                tempTriangles1[tempTriangles1_Count++] = (tempVert1AllPos2Index);
                if (center1Index == tempVert1AllPos1Index || center1Index == tempVert1AllPos2Index || tempVert1AllPos1Index == tempVert1AllPos2Index)
                {
                    //Debug.Log(
                    //     center + "," + allPos[i] + "," + allPos[i + 1]
                    //     + "\n " + tempVert1.IndexOf(center) + "," + tempVert1AllPos1Index + "," + tempVert1AllPos2Index + "," + allPos_Count);
                    //Debug.LogError("tempVert1.LastIndexOf(center) == tempVert1AllPos1Index || tempVert1.LastIndexOf(center) == tempVert1AllPos2Index || tempVert1AllPos1Index == tempVert1AllPos2Index 9999999999");
                }
            }
            else
            {
                tempTriangles1[tempTriangles1_Count++] = (tempVert1AllPos2Index);
                tempTriangles1[tempTriangles1_Count++] = (tempVert1AllPos1Index);
                tempTriangles1[tempTriangles1_Count++] = (center1Index);
                if (center1Index == tempVert1AllPos1Index || center1Index == tempVert1AllPos2Index || tempVert1AllPos1Index == tempVert1AllPos2Index)
                {
                    //Debug.Log(
                    //    center + "," + allPos[i] + "," + allPos[i + 1] + "\n" +
                    //    tempVert1.IndexOf(center) + "," + tempVert1AllPos1Index + "," + tempVert1AllPos2Index + "," + allPos_Count);
                    //Debug.LogError("if (tempVert1.LastIndexOf(center) == tempVert1AllPos1Index || tempVert1.LastIndexOf(center) == tempVert1AllPos2Index || tempVert1AllPos1Index == tempVert1AllPos2Index) -----------");
                }
            }

            tempVert2[tempVert2_Count++] = (allPos[i]);
            int tempV1Index = tempVert2_Count - 1;
            tempVert2[tempVert2_Count++] = (allPos[i + 1]);
            int tempV2Index = tempVert2_Count - 1;

            tempNormal2[tempNormal2_Count++] = (normal);
            tempNormal2[tempNormal2_Count++] = (normal);

            if (Vector3.Dot(normal, crossA1A2) >= 0)
            {
                tempTriangles2[tempTriangles2_Count++] = (center2Index);
                tempTriangles2[tempTriangles2_Count++] = (tempV1Index);
                tempTriangles2[tempTriangles2_Count++] = (tempV2Index);
                if (center2Index == tempV1Index || center2Index == tempV2Index || tempV1Index == tempV2Index)
                {
                    //Debug.Log(
                    //    center + "," + allPos[i] + "," + allPos[i + 1] + "\n" +
                    //    tempVert2.IndexOf(center) + "," + tempV1Index + "," + tempV2Index + "," + allPos_Count);
                    //Debug.LogError("tempVert2.LastIndexOf(center) == tempV1Index || tempVert2.LastIndexOf(center) == tempV2Index || tempV1Index == tempV2Index /");
                }
            }
            else
            {
                tempTriangles2[tempTriangles2_Count++] = (tempV2Index);
                tempTriangles2[tempTriangles2_Count++] = (tempV1Index);
                tempTriangles2[tempTriangles2_Count++] = (center2Index);
                if (center2Index == tempV1Index || center2Index == tempV2Index || tempV1Index == tempV2Index)
                {
                    //Debug.Log(
                    //    center + "," + allPos[i] + "," + allPos[i + 1] + "\n" +
                    //    tempVert2.IndexOf(center) + "," + tempV1Index + "," + tempV2Index + "," + allPos_Count);
                    //Debug.LogError("tempVert2.LastIndexOf(center) == tempV1Index || tempVert2.LastIndexOf(center) == tempV2Index || tempV1Index == tempV2Index qqqqqqq");
                }
            }

        }
    }

    /// <summary>
    /// 计算Box的UV方法 
    /// </summary>
    void CalculateUV(Vector3 size, ref NativeArray<Vector3> vertices, ref NativeArray<int> triangles, ref NativeArray<Vector3> normals, ref NativeArray<Vector2> uvs
        , ref int verticesCount, ref int trianglesCount, ref int normalsCount, ref int uvsCount)
    {
        for (int i = 0; i < verticesCount; i++)
        {
            uvs[uvsCount++] = (new Vector2(0, 0));
        }
        for (int i = 0; i < trianglesCount / 3; i++)
        {
            int i0 = triangles[i * 3];
            int i1 = triangles[i * 3 + 1];
            int i2 = triangles[i * 3 + 2];

            //Vector3 v0 = vertices[i0] - center + size / 2f;
            //Vector3 v1 = vertices[i1] - center + size / 2f;
            //Vector3 v2 = vertices[i2] - center + size / 2f;

            Vector3 v0 = vertices[i0];
            Vector3 v1 = vertices[i1];
            Vector3 v2 = vertices[i2];

            //string str = string.Format("原始数据:({0},{1},{2}) index:({3},{4},{5})", v0.ToString(), v1.ToString(), v2.ToString(), i0, i1, i2);

            // 除以size.x,y,z是为了缩小范围到[0,1] UV的范围
            v0 = new Vector3(v0.x / size.x, v0.y / size.y, v0.z / size.z);
            v1 = new Vector3(v1.x / size.x, v1.y / size.y, v1.z / size.z);
            v2 = new Vector3(v2.x / size.x, v2.y / size.y, v2.z / size.z);

            //Vector3 a = v0 - v1;
            //Vector3 b = v2 - v1; 
            Vector3 a = v1 - v0;
            Vector3 b = v2 - v1;

            //我老感觉这法线计算错了...v0->v1-v2             
            Vector3 dir = normals[i0]; //Vector3.Cross(a, b);  //改用顶点法线作为法线
            float x = Mathf.Abs(Vector3.Dot(dir, Vector3.right));
            float y = Mathf.Abs(Vector3.Dot(dir, Vector3.up));
            float z = Mathf.Abs(Vector3.Dot(dir, Vector3.forward));
            //法线倾向于X轴,用Z作为X,Y作为Y
            if (x > y && x > z)
            {
                uvs[i0] = new Vector2(v0.z, v0.y);
                uvs[i1] = new Vector2(v1.z, v1.y);
                uvs[i2] = new Vector2(v2.z, v2.y);
            }
            else if (y > z && y > x)
            {
                //法线倾向于Y轴,用X作为X,Z作为Y
                uvs[i0] = new Vector2(v0.x, v0.z);
                uvs[i1] = new Vector2(v1.x, v1.z);
                uvs[i2] = new Vector2(v2.x, v2.z);
            }
            else if (z > x && z > y)
            {
                //法线倾向于Z轴,用X作为X,Y作为Y
                uvs[i0] = new Vector2(v0.x, v0.y);
                uvs[i1] = new Vector2(v1.x, v1.y);
                uvs[i2] = new Vector2(v2.x, v2.y);
            }
            else
            {
                //防止出现UV不正常情况
                uvs[i0] = new Vector2(0, 0);
                uvs[i1] = new Vector2(1, 1);
                uvs[i2] = new Vector2(0, 0);
                //Debug.LogWarning("UV出问题啦..." + x + ", " + y + "," + z + "\n"
                //    + v0 + ", " + v1 + "," + v2 + " \n"
                //    + a + ", " + b + "\n"
                //    + dir + "\n"
                //    + str);//虽然已经处理了异常三角面,但仍然会出现(x,y,z)全为0的情况...先放任不管看看效果...
            }
        }
    }
    #endregion
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/953323.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Armv8/Armv9架构从入门到精通-介绍

CSDN学院课程连接&#xff1a;https://edu.csdn.net/course/detail/39573 1 讲师介绍 拥有 12 年手机安全、汽车安全、芯片安全开发经验&#xff0c;擅长 Trustzone/TEE/ 安全的设计与开发&#xff0c;对 ARM 架构的安全领域有着深入的研究和丰富的实践经验&#xff0c;能够…

Cesium小知识:pointPrimitive collection 详解

Cesium.PointPrimitiveCollection 是 Cesium 中用于高效管理和渲染大量点(points)的一个类。它允许你创建和管理大量的 PointPrimitive 实例,这些实例可以用来表示地理空间中的点数据,如传感器位置、车辆位置、兴趣点等。与直接使用 Cesium.Entity 相比,PointPrimitiveCol…

Threejs实现 区块链网络效应

大家好&#xff01;我是 [数擎 AI]&#xff0c;一位热爱探索新技术的前端开发者&#xff0c;在这里分享前端和 Web3D、AI 技术的干货与实战经验。如果你对技术有热情&#xff0c;欢迎关注我的文章&#xff0c;我们一起成长、进步&#xff01; 开发领域&#xff1a;前端开发 | A…

GitCode G-Star 光引计划终审前十名获奖项目公示

在技术的浩瀚星空中&#xff0c;GitCode 平台上的 G-Star 项目熠熠生辉。如今&#xff0c;“光引计划” 已圆满落幕&#xff0c;众多 G-Star 项目作者&#xff0c;一同分享项目在 GitCode 平台托管的宝贵体验&#xff0c;并深入挖掘平台的多样玩法。 众多投稿纷至沓来&#xf…

VRRP技术

堆叠 堆叠指将支持堆叠特性的交换机通过堆叠线缆连接到一起&#xff0c;解决交换机问题 &#xff08;物理多台交换机变成逻辑上的一台交换机 去进行一个数据转发&#xff09;聚合解决链路问题在不同的厂商中堆叠的技术: 思科&#xff1a;stackwise 思科智能堆叠VSS Virt…

primitive 的 Appearance编写着色器材质

import { nextTick, onMounted, ref } from vue import * as Cesium from cesium import gsap from gsaponMounted(() > { ... })// 1、创建矩形几何体&#xff0c;Cesium.RectangleGeometry&#xff1a;几何体&#xff0c;Rectangle&#xff1a;矩形 let rectGeometry new…

31_搭建Redis分片集群

Redis的主从复制模式和哨兵模式可以解决高可用、高并发读的问题。但是依然有两个问题没有解决:海量数据存储问题、高并发写的问题。由于数据量过大,单个master复制集难以承担,因此需要对多个复制集进行集群,形成水平扩展每个复制集只负责存储整个数据集的一部分,这就是Red…

快速上手 INFINI Console 的 TopN 指标功能

背景 在分布式搜索引擎系统&#xff08;如 Easysearch、Elasticsearch 和 OpenSearch&#xff09;中&#xff0c;性能监控至关重要。为了确保系统的高效运行和资源的合理分配&#xff0c;我们通常需要关注一段时间内关键资源的使用情况&#xff0c;特别是索引、节点和分片的内…

风水算命系统架构与功能分析

系统架构 服务端&#xff1a;Java&#xff08;最低JDK1.8&#xff0c;支持JDK11以及JDK17&#xff09;数据库&#xff1a;MySQL数据库&#xff08;标配5.7版本&#xff0c;支持MySQL8&#xff09;ORM框架&#xff1a;Mybatis&#xff08;集成通用tk-mapper&#xff0c;支持myb…

探索AGI:智能助手与自我赋能的新时代

目录 1 AGI1.1 DeepMind Levels&#xff08;2023年11月)1.2 OpenAI Levels&#xff08;2024年7月&#xff09;1.3 对比与总结1.4 AGI可能诞生哪里 2 基于AI的智能自动化助手2.1 通用型大模型2.2 专业的Agent和模型工具开发框架2.3 编程与代码生成助手2.4 视频和多模态生成2.5 商…

工具推荐:PDFgear——免费且强大的PDF编辑工具 v2.1.12

PDFgear——免费且强大的PDF编辑工具 v2.1.12 软件简介 PDFgear 是一款 完全免费的 PDF 软件&#xff0c;支持 阅读、编辑、转换、合并 以及 跨设备签署 PDF 文件&#xff0c;无需注册即可使用。它提供了丰富的 PDF 处理功能&#xff0c;极大提升了 PDF 文件管理的便捷性和效…

【机器学习】L1正则化与L2正则化

L1&#xff0c;L2正则化解决过拟合问题 目录 过拟合的原因 正则化的目标 L1&#xff0c;L2正则化 L1正则化 L2正则化 从概率的角度来看 L1 正则化与拉普拉斯分布 L2 正则化与高斯分布 过拟合的原因 过拟合发生时&#xff0c;模型学习到了训练数据中的噪声或细节&am…

【PyQt】如何在mainwindow中添加菜单栏

[toc]如何在mainwindow中添加菜单栏 如何在mainwindow中添加菜单栏 主要有两种方法&#xff1a; 1.直接创建mainwindow进行添加 2.使用ui文件加载添加 第二种方法更为常见&#xff0c;可以应用到实际 1.直接创建mainwindow进行添加 import sysfrom PyQt5.QtWidgets import …

1.组件的三大组成部分注意点(结构/样式/逻辑)scoped解决样式冲突/data是一个函数2.组件通信组件通信语法父传子子传父

学习目标 1.组件的三大组成部分注意点&#xff08;结构/样式/逻辑&#xff09; scoped解决样式冲突/data是一个函数 2.组件通信 组件通信语法 父传子 子传父 非父子通信&#xff08;扩展&#xff09; 3.综合案例&#xff1a;小黑记事本&#xff08;组件版&#xff09; …

Sqoop1.4.7安装

环境说明 准备三台服务器&#xff0c;分别为&#xff1a;bigdata141&#xff08;hadoop 主节点&#xff09;、bigdata142、bigdata143确保 hadoop 集群先启动好&#xff0c;hadoop 版本为 3.2.0如果只安装不使用的话&#xff0c;以上可以暂时不用管另准备一台服务器&#xff0…

Oracle重启后业务连接大量library cache lock

一、现象 数据库和前段应用重启后&#xff0c;出现大量library cache lock等待事件。 二、分析解决 本次异常原因是&#xff1a;原因定位3&#xff1a; 库缓存对象无效 Library cache object Invalidations 三、各类情况具体分析如下 原因定位1&#xff1a;由于文字导致的非…

Demo15:DS1302涓流充电时钟芯片

一、实验现象 通过DS1302 涓流充电时钟芯片&#xff0c;在数码管上显示电子时钟时分秒&#xff0c;格式为“XX-XX-XX” 二、核心知识点 - DS1302时序 三、项目结构 main.c /************************************************************************************** 实验名称…

HTB:Bastion[WriteUP]

目录 连接至HTB服务器并启动靶机 信息收集 使用rustscan对靶机TCP端口进行开放扫描 将靶机TCP开放端口号提取并保存 使用nmap对靶机TCP开放端口进行脚本、服务扫描 使用nmap对靶机TCP开放端口进行漏洞、系统扫描 使用nmap对靶机常用UDP端口进行开放扫描 使用enum4linux…

易语言文字识别OCR

一.引言 文字识别&#xff0c;也称为光学字符识别&#xff08;Optical Character Recognition, OCR&#xff09;&#xff0c;是一种将不同形式的文档&#xff08;如扫描的纸质文档、PDF文件或数字相机拍摄的图片&#xff09;中的文字转换成可编辑和可搜索的数据的技术。随着技…

Harry技术添加存储(minio、aliyun oss)、短信sms(aliyun、模拟)、邮件发送等功能

Harry技术添加存储&#xff08;minio、aliyun oss&#xff09;、短信sms&#xff08;aliyun、模拟&#xff09;、邮件发送等功能 基于SpringBoot3Vue3前后端分离的Java快速开发框架 项目简介&#xff1a;基于 JDK 17、Spring Boot 3、Spring Security 6、JWT、Redis、Mybatis-P…