데카르트 좌표에서의 이동을 구면좌표 이동으로 mapping 하였다.
데카르트 좌표는 x,y축만 있는 좌표를 의미한다. (2차원 좌표이다. )
구면 좌표는 구체 표면을 좌표화한 것으로 구체 표면에서의 움직임을 위하여 사용한다.
*여담으로 양자역학에서 전자의 운동을 계산하기 위해서 사용한다고 한다! 슈뢰딩거~
<실습>
첫번째로, 할 일은 x축 y축으로만 이동하는 특정 범위 안에 있는 컨트롤러를 만드는 것이다.
위와 관련된 스크립트는 지난번 포스팅에 마우스를 따라서 이동하는 개체 코드를 보면 된다.
코드에 대해서 간략하게 설명하자면 rayCast를 받아서 좌표에 찍는 방식을 사용하였다.
x축 y축만 제어하기 위해서 position.z는 0으로 두었다.
두번째로, 할 일은 이제 위의 좌표 값을 받아와서 구면좌표에서 움직이는 개체를 만드는 것이다.
데카르트 좌표를 구면 좌표로 만들기 위해서는 우선, 지도에 대해서 생각해보아야 한다.
지도는 위도, 경도를 가지고 있고 이 2차원 좌표는 구를 표현하는 것이다.
위도 경도를 구면에 mapping하는 코드 관련해서는 아래 링크를 참고하였다.
https://github.com/mapbox/mapbox-unity-sdk/issues/238
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | private Vector3 CoordinateTrans(float Lon, float Lat) { Vector3 result; float ltR = Lat * Mathf.Deg2Rad; float lnR = Lon * Mathf.Deg2Rad; float xPos = (radius * transform.lossyScale.z) * Mathf.Cos(ltR) * Mathf.Cos(lnR); float zPos = (radius * transform.lossyScale.z) * Mathf.Cos(ltR) * Mathf.Sin(lnR); float yPos = (radius * transform.lossyScale.z) * Mathf.Sin(ltR); Vector3 earthPositon = transform.position; result = new Vector3(xPos , yPos , zPos); return result; } | cs |
여기에서 한 가지 발생하는 문제점은 위에 x축, y축을 만들어 두었던 좌표가
위도와 경도의 범위인
-90 =< 위도 =< 90
-180 =< 경도 =< 180
가 아니라는 것이다.
이 문제를 해결하기 위해서 remap을 위한 코드를 짰다.
*processing에 있는 map()이라는 함수를 떠올리면 된다.
코드는 아래와 같다.
1 2 3 4 5 6 | private float remap(float aValue, float from1, float to1, float from2, float to2) { float normal = Mathf.InverseLerp(from1, to1, aValue); float bValue = Mathf.Lerp(from2, to2, normal); return bValue; } | cs |
잘 작동된다.
전체 코드
* <Manual>
1. cardesianMove 스크립트는 데카르트 좌표계로 움직이는 개체의 스크립트이다.
2. radius는 기준 구체의 반지름이다. (기준 구체는 태양계 기준으로 설명하자면, 태양이다. )
3. sphereSize는 움직이는 개체의 크기이다. (움직이는 개체는 태양계 기준으로 지구라고 생각하면 된다. )
*sphereSize를 pos에서 나누어주는 이유는 size에 따라서 이동해야되는 크기가 다르기 때문이다.
4. latitude(위도)의 범위를 -180에서 180으로 둔 이유는 위도로 360도 회전을 하기 위해서이다.
5. remap함수는 본인의 좌표에 따라서 변경하면 된다.
remap(input값, 기존 최솟값, 기존 최댓값, 맵핑할 최솟값, 맵핑할 최댓값 )
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 | using System.Collections; using System.Collections.Generic; using UnityEngine; public class sphericalMove : MonoBehaviour { public CardesianMove carde; //다른 스크립트에서 2d 위치 벡터 받아옴 public float radius = 2.0f; public float sphereSize = 0.1f; public float X; public float Y; public float Longitude; public float Latitude; private Vector3 convertPos = Vector3.zero; void Start () { carde = FindObjectOfType<CardesianMove>(); } void Update () { X = carde.transform.position.x ; Y = carde.transform.position.y ; //remap Longitude = remap(X, -2, 2, -180, 180);//longitude Latitude = remap(Y, -2, 2, -180, 180);//latitude Vector3 pos = CoordinateTrans(Longitude, Latitude); transform.position = pos/sphereSize; } //mapping private float remap(float aValue, float from1, float to1, float from2, float to2) { float normal = Mathf.InverseLerp(from1, to1, aValue); float bValue = Mathf.Lerp(from2, to2, normal); return bValue; } private Vector3 CoordinateTrans(float Lon, float Lat) { Vector3 result; float ltR = Lat * Mathf.Deg2Rad; float lnR = Lon * Mathf.Deg2Rad; float xPos = (radius * transform.lossyScale.z) * Mathf.Cos(ltR) * Mathf.Cos(lnR); float zPos = (radius * transform.lossyScale.z) * Mathf.Cos(ltR) * Mathf.Sin(lnR); float yPos = (radius * transform.lossyScale.z) * Mathf.Sin(ltR); Vector3 earthPositon = transform.position; result = new Vector3(xPos , yPos , zPos); return result; } } | cs |
'Project > Galapagos' 카테고리의 다른 글
unity에서 kinect input값 받아오기 (1) | 2019.01.15 |
---|---|
* 코드 타입 확인하기, structure과 class, 보간으로 이동 (0) | 2019.01.15 |
구면 좌표계 Day1(공식) (0) | 2019.01.11 |
마우스를 따라서 이동하는 개체 코드 (0) | 2019.01.11 |
*클래스 타입이 list인 코드 분석 (0) | 2019.01.11 |