본문 바로가기
개발/Unity

유니티 - 메시의 로컬 좌표를 월드 좌표로 변환하기 (How to Transform Local or World Position of Mesh Vertices)

by 피로물든딸기 2022. 11. 6.
반응형

Unity 전체 링크

 

쿼드를 아래와 같이 (0, 0, 0)에 배치하고 각 정점에 자식으로 Sphere를 배치하자.

 

Sphere는 총 4개가 필요하고 (± 0.5, ± 0.5, 0)의 좌표를 가진다.

 

자식 오브젝트의 좌표는 아래와 같으며, Mesh의 Vertices 순서대로 배치하였다.

 

 ContextMenu 이용하면 인스펙터에서 함수를 호출할 수 있다.

    [ContextMenu("Show Position")]
    void saveMesh()
    {
        string log = string.Empty;
        foreach (Vector3 v in mesh.vertices)
            log += v.ToString() + " ";

        Debug.Log(log + " << Mesh Pos");

        /* --------------------------------------- */

        childPos.Clear();
        foreach (Transform tr in this.transform)
            childPos.Add(tr.position);

        log = string.Empty;
        foreach (Vector3 v in childPos)
            log += v.ToString() + " ";

        Debug.Log(log + " << Child Pos");

        /* --------------------------------------- */
    }

 

게임을 실행하고 인스펙터에서 좌표를 출력해보자.

 

Mesh의 좌표와 자식오브젝트 = Sphere 들의 좌표가 완전히 일치한다.

 

(0, 0, 0)에서는 로컬 좌표와 월드 좌표가 일치하기 때문에 문제가 없다.

 

이제 Quad의 Position, Rotation, Scale을 옮겨보자.

 

Mesh의 좌표는 변하지 않았지만 자식 오브젝트의 좌표는 변하게 되었다.


로컬 좌표를 월드 좌표로 변환하기 (Transforms Position from Local Space to World Space)

 

런타임에 Mesh를 수정하거나, Mesh의 월드 좌표가 필요한 경우가 있다.

 

TransformPoint 또는 localToWorldMatrix를 이용하면 된다.

    log = string.Empty;
    foreach (Vector3 v in mesh.vertices)
    {
        Vector3 world = this.transform.TransformPoint(v);
        log += world.ToString() + " ";
    }

    Debug.Log(log + " << World Mesh Pos by TransformPoint");

    /* --------------------------------------- */

    log = string.Empty;
    Matrix4x4 localToWorld = transform.localToWorldMatrix;
    foreach (Vector3 v in mesh.vertices)
    {
        Vector3 world = localToWorld.MultiplyPoint3x4(v);
        log += world.ToString() + " ";
    }

    Debug.Log(log + " << World Mesh Pos by Matrix4x4");

 

두 방법 모두 월드 좌표로 잘 변환되었다.


월드 좌표를 로컬 좌표로 변환하기 (Transform Position from World Space to Local Space)

 

반대로 월드 좌표를 다시 로컬로 변환할 수도 있다.

 

InverseTransformPoint 또는 worldToLocalMatrix를 이용하면 된다.

    Debug.Log(log + " << World Mesh Pos by TransformPoint");

    /* --------------------------------------- */

    log = string.Empty;
    Matrix4x4 localToWorld = transform.localToWorldMatrix;
    foreach (Vector3 v in mesh.vertices)
    {
        Vector3 world = localToWorld.MultiplyPoint3x4(v);
        log += world.ToString() + " ";
    }

    Debug.Log(log + " << World Mesh Pos by Matrix4x4");

    /* --------------------------------------- */

    log = string.Empty;
    foreach (Vector3 v in childPos)
    {
        Vector3 local = this.transform.InverseTransformPoint(v);
        log += local.ToString() + " ";
    }

    Debug.Log(log + " << Local Mesh Pos by InverseTransformPoint");

    /* --------------------------------------- */
    log = string.Empty;
    Matrix4x4 worldToLocal = transform.worldToLocalMatrix;
    foreach (Vector3 v in childPos)
    {
        Vector3 local = worldToLocal.MultiplyPoint3x4(v);
        log += local.ToString() + " ";
    }

    Debug.Log(log + " << Local Mesh Pos by Matrix4x4");

 

자식 오브젝트의 좌표가 로컬 좌표로 돌아온 것을 알 수 있다.

 

전체 코드는 다음과 같다.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
public class MeshWorldPosition : MonoBehaviour
{
    Mesh mesh;
    List<Vector3> childPos = new List<Vector3>();

    [ContextMenu("Show Position")]
    void saveMesh()
    {
        string log = string.Empty;
        foreach (Vector3 v in mesh.vertices)
            log += v.ToString() + " ";

        Debug.Log(log + " << Mesh Pos");

        /* --------------------------------------- */

        childPos.Clear();
        foreach (Transform tr in this.transform)
            childPos.Add(tr.position);

        log = string.Empty;
        foreach (Vector3 v in childPos)
            log += v.ToString() + " ";

        Debug.Log(log + " << Child Pos");

        /* --------------------------------------- */
        
        log = string.Empty;
        foreach (Vector3 v in mesh.vertices)
        {
            Vector3 world = this.transform.TransformPoint(v);
            log += world.ToString() + " ";
        }

        Debug.Log(log + " << World Mesh Pos by TransformPoint");

        /* --------------------------------------- */

        log = string.Empty;
        Matrix4x4 localToWorld = transform.localToWorldMatrix;
        foreach (Vector3 v in mesh.vertices)
        {
            Vector3 world = localToWorld.MultiplyPoint3x4(v);
            log += world.ToString() + " ";
        }

        Debug.Log(log + " << World Mesh Pos by Matrix4x4");

        /* --------------------------------------- */

        log = string.Empty;
        foreach (Vector3 v in childPos)
        {
            Vector3 local = this.transform.InverseTransformPoint(v);
            log += local.ToString() + " ";
        }

        Debug.Log(log + " << Local Mesh Pos by InverseTransformPoint");

        /* --------------------------------------- */
        log = string.Empty;
        Matrix4x4 worldToLocal = transform.worldToLocalMatrix;
        foreach (Vector3 v in childPos)
        {
            Vector3 local = worldToLocal.MultiplyPoint3x4(v);
            log += local.ToString() + " ";
        }

        Debug.Log(log + " << Local Mesh Pos by Matrix4x4");
    }

    void Start()
    {
        mesh = this.GetComponent<MeshFilter>().mesh; 
    }
}

 

위의 실행결과는 아래의 unitypackage에서 확인 가능하다.

TransformWorldLocalPosition.unitypackage
0.02MB

 

Unity Plus:

 

Easy 2D, 3D, VR, & AR software for cross-platform development of games and mobile apps. - Unity Store

Have a 2D, 3D, VR, or AR project that needs cross-platform functionality? We can help. Take a look at the easy-to-use Unity Plus real-time dev platform!

store.unity.com

 

Unity Pro:

 

Unity Pro

The complete solutions for professionals to create and operate.

unity.com

 

Unity 프리미엄 학습:

 

Unity Learn

Advance your Unity skills with live sessions and over 750 hours of on-demand learning content designed for creators at every skill level.

unity.com

반응형

댓글