unity 与cad 坐标系映射

cs 复制代码
 #region 坐标系转化
    [System.Serializable]
    public class CoordGroup
    {
        [Header("区域名称/备注")]
        public string areaName;

        [Header("现实三点(CAD原始坐标)")]
        public Vector3 W0, W1, W2;
        [Header("对应Unity三点(场景世界坐标)")]
        public Vector3 U0, U1, U2;

        [Header("坐标系适配配置")]
        [Tooltip("自动映射:CAD(XY平面+Z高程) → Unity(XZ平面+Y高程),建筑场景默认开启")]
        public bool autoMapAxes = true;
        [Tooltip("左手系适配:修正CAD右手系与Unity左手系的镜像偏差,默认开启")]
        public bool adaptLeftHand = true;

        [HideInInspector] public Matrix4x4 transMatrix;
        [HideInInspector] public Matrix4x4 transMatrixInv; // Unity转现实逆矩阵
        [HideInInspector] public bool isValid = false;
    }

    [Header("添加所有独立坐标系区域")]
    public CoordGroup[] coordGroups;

    /// <summary>
    /// 批量计算所有坐标系矩阵
    /// </summary>
    void BuildAllMatrix()
    {
        for (int i = 0; i < coordGroups.Length; i++)
        {
            var group = coordGroups[i];
            group.isValid = BuildSingleMatrix(group);
            if (!group.isValid)
            {
                Debug.LogError($"【{group.areaName}】坐标系三点共线,构建失败!");
            }
            else
            {
                Debug.Log($"【{group.areaName}】矩阵构建成功");
            }
        }
    }

    /// <summary>
    /// 构建单个坐标系矩阵(核心适配逻辑已改造)
    /// </summary>
    bool BuildSingleMatrix(CoordGroup group)
    {
        // ========== 1. CAD轴向自动对齐Unity ==========
        Vector3 w0, w1, w2;
        if (group.autoMapAxes)
        {
            // CAD原始(X,Y,Z) → 对齐Unity轴向:X不变,CAD平面Y→Unity平面Z,CAD高程Z→Unity高程Y
            w0 = new Vector3(group.W0.x, group.W0.z, group.W0.y);
            w1 = new Vector3(group.W1.x, group.W1.z, group.W1.y);
            w2 = new Vector3(group.W2.x, group.W2.z, group.W2.y);
        }
        else
        {
            w0 = group.W0;
            w1 = group.W1;
            w2 = group.W2;
        }

        // ========== 2. 计算两侧基向量 ==========
        // 现实(CAD)侧基向量
        Vector3 wAxisX = w1 - w0;
        Vector3 wAxisY = w2 - w0;
        Vector3 wAxisZ = Vector3.Cross(wAxisX, wAxisY);

        // Unity侧基向量
        Vector3 uAxisX = group.U1 - group.U0;
        Vector3 uAxisY = group.U2 - group.U0;
        Vector3 uAxisZ = Vector3.Cross(uAxisX, uAxisY);

        // 左手系适配:Unity为左手坐标系,第三轴取反消除镜像
        if (group.adaptLeftHand)
        {
            uAxisZ = -uAxisZ;
        }

        // 双侧校验三点共线
        if (wAxisZ.magnitude < Mathf.Epsilon || uAxisZ.magnitude < Mathf.Epsilon)
            return false;

        // ========== 3. 构建局部坐标系矩阵 ==========
        // 现实坐标系矩阵(已对齐轴向)
        Matrix4x4 worldLocal = Matrix4x4.identity;
        worldLocal.SetColumn(0, new Vector4(wAxisX.x, wAxisX.y, wAxisX.z, 0));
        worldLocal.SetColumn(1, new Vector4(wAxisY.x, wAxisY.y, wAxisY.z, 0));
        worldLocal.SetColumn(2, new Vector4(wAxisZ.x, wAxisZ.y, wAxisZ.z, 0));
        worldLocal.SetColumn(3, new Vector4(w0.x, w0.y, w0.z, 1));

        // Unity坐标系矩阵
        Matrix4x4 unityLocal = Matrix4x4.identity;
        unityLocal.SetColumn(0, new Vector4(uAxisX.x, uAxisX.y, uAxisX.z, 0));
        unityLocal.SetColumn(1, new Vector4(uAxisY.x, uAxisY.y, uAxisY.z, 0));
        unityLocal.SetColumn(2, new Vector4(uAxisZ.x, uAxisZ.y, uAxisZ.z, 0));
        unityLocal.SetColumn(3, new Vector4(group.U0.x, group.U0.y, group.U0.z, 1));

        // ========== 4. 计算最终变换矩阵 ==========
        group.transMatrix = unityLocal * worldLocal.inverse;
        group.transMatrixInv = group.transMatrix.inverse;
        return true;
    }

    /// <summary>
    /// 根据区域下标,CAD现实坐标转Unity坐标
    /// </summary>
    /// <param name="worldPos">CAD原始坐标(X,Y,Z)</param>
    /// <param name="areaIndex">区域下标(从0开始)</param>
    public Vector3 WorldToUnity(Vector3 worldPos, int areaIndex)
    {
        if (areaIndex < 0 || areaIndex >= coordGroups.Length)
        {
            Debug.LogError("区域下标越界");
            return Vector3.zero;
        }

        var group = coordGroups[areaIndex];
        if (!group.isValid)
        {
            Debug.LogError($"【{group.areaName}】坐标系无效");
            return Vector3.zero;
        }

        // 输入轴向对齐
        Vector3 input = worldPos;
        if (group.autoMapAxes)
        {
            input = new Vector3(worldPos.x, worldPos.z, worldPos.y);
        }
        return group.transMatrix.MultiplyPoint3x4(input);
    }

    /// <summary>
    /// 根据区域名称转换 CAD → Unity
    /// </summary>
    public Vector3 WorldToUnityByName(Vector3 worldPos, string areaName)
    {
        foreach (var group in coordGroups)
        {
            if (group.areaName == areaName && group.isValid)
            {
                Vector3 input = worldPos;
                if (group.autoMapAxes)
                {
                    input = new Vector3(worldPos.x, worldPos.z, worldPos.y);
                }
                return group.transMatrix.MultiplyPoint3x4(input);
            }
        }
        Debug.LogError($"未找到区域:{areaName}");
        return Vector3.zero;
    }

    /// <summary>
    /// 根据区域下标,Unity坐标转CAD现实坐标
    /// </summary>
    /// <param name="unityPos">Unity场景坐标</param>
    /// <param name="areaIndex">区域下标(从0开始)</param>
    public Vector3 UnityToWorld(Vector3 unityPos, int areaIndex)
    {
        if (areaIndex < 0 || areaIndex >= coordGroups.Length)
        {
            Debug.LogError("区域下标越界");
            return Vector3.zero;
        }

        var group = coordGroups[areaIndex];
        if (!group.isValid)
        {
            Debug.LogError($"【{group.areaName}】坐标系无效");
            return Vector3.zero;
        }

        Vector3 result = group.transMatrixInv.MultiplyPoint3x4(unityPos);
        // 输出轴向还原为CAD原始坐标
        if (group.autoMapAxes)
        {
            result = new Vector3(result.x, result.z, result.y);
        }
        return result;
    }

    /// <summary>
    /// 根据区域名称,Unity坐标转CAD现实坐标
    /// </summary>
    public Vector3 UnityToWorldByName(Vector3 unityPos, string areaName)
    {
        foreach (var group in coordGroups)
        {
            if (group.areaName == areaName && group.isValid)
            {
                Vector3 result = group.transMatrixInv.MultiplyPoint3x4(unityPos);
                if (group.autoMapAxes)
                {
                    result = new Vector3(result.x, result.z, result.y);
                }
                return result;
            }
        }
        Debug.LogError($"未找到区域:{areaName}");
        return Vector3.zero;
    }
    #endregion
相关推荐
神码编程3 小时前
【Unity】 HTFramework框架(七十)MultiChoiceDropdown可多选的下拉菜单
unity·游戏引擎·ugui·dropdown·下拉菜单
淡海水5 小时前
15-07-YooAsset面试篇-Unity性能优化与内存管理
java·unity·面试·性能优化·c#·游戏引擎
zhchyun20081 天前
# 【Unity UI 进阶】仿 Element UI 打造企业级 Unity UI 组件库(03)
unity
淡海水2 天前
15-02-YooAsset面试篇-Unity架构设计与源码
java·unity·面试·c#·游戏引擎·yooasset
郝学胜-神的一滴2 天前
中级OpenGL教程 030:gl_FragCoord解锁区域渲染与深度可视化新姿势
c++·unity·游戏引擎·图形渲染·unreal engine·opengl
ellis19702 天前
u3d插件xLua[四]Lua访问C#源码分析,反射,生成代码
unity
2401_894915532 天前
GEO 定位优化源码搭建常见报错排查:数据库、伪静态、接口调试
java·数据库·网络协议·tcp/ip·spring·unity