当前位置: 首页 > article >正文

【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
}


http://www.kler.cn/a/499826.html

相关文章:

  • Android实战经验篇-增加系统分区
  • Redis 多路复用(Multiplexing)
  • git相关操作笔记
  • LLM的实验平台有哪些:快速搭建测试大语言模型
  • 【Unity-和WPF结合的优势】
  • Pixel 6a手机提示无法连接移动网络,打电话失败!
  • 太原理工大学软件设计与体系结构 --javaEE
  • 算法 -归并排序
  • Linux:操作系统简介
  • Taro+Vue实现图片裁剪组件
  • pytest+allure 入门
  • CSS:定位
  • Vue3.js中如何将响应式数据与状态管理Vuex、Pinia结合使用
  • 【adb】5分钟入门adb操作安卓设备
  • 机器学习之奥卡姆剃刀定律
  • CNN Test Data
  • 学习RocketMQ
  • git commit 命令
  • 计算机视觉:解锁未来智能世界的钥匙
  • 迪威云服务支持的3D格式转换方法详解
  • MongoTemplate 性能优化指南