코드 타입 확인(정의로 이동)

 

kinect의 position값을 받아올려고 하였는데. 

Vector3 type이 아니었다. 

1
var pos = body.Joints[Trackedjoint].Position;
cs

Position에 마우스 커서를 갔다대면 CameraSpacePoint라는 알 수 없는 변수형이 뜬다. ^^;;

어떤 타입으로 받아와야 될지 몰라서 선생님께 질문하였다...

 

이럴 경우 파고들어가고 싶은 코드에 블록처리를 하고 우클릭을 누르고 

'정의로 이동(window-f12/ mac - command + D)' 을 선택하면, 코드 내에 내장된 코드들이 나온다.

 

CameraSpacePoint의 타입은 들어가보니, struct구조로

Vector값을 float형으로 X,Y,Z로 가져오고 있었다.

1
2
3
4
5
public struct CameraSpacePoint
    {
        public float X { get; set; }
        public float Y { get; set; }
        public float Z { get; set; }
cs

 

pos값을 가져오기 위해서 새로운 벡터를 만들고

CameraSpacePoint의 내부에 있는 X, Y, Z값을 가져왔다.

1
2
3
var pos = body.Joints[Trackedjoint].Position;
 
                Vector3 movePos = new Vector3(pos.X, pos.Y, pos.Z);
cs


 

structure과 class의 차이


둘 다 변수와 함수의 집합이다. 

차이는 저장 위치이다. 


structure - 스택에 저장 ex) rayCast.hit

class - 힙에 저장


*스택 : 함수 호출시 생성, 호출 완료되면 사라짐.(임시할당) 

지역변수 매개변수 저장되는 영역.

LIFO(last in first out) - 마지막에 입력된 자료를 가장 먼저 삭제함.

 

*힙 : 할당할 메모리의 크기를 런타임에 정함. (동적할당) 

호출이 끝나도 사라지지 않음.(가비지 컬렉터로 지워야함.) 

static, 전역변수가 저장되는 영역.

FIFO(first in first out) - 가장 먼저 들어간 데이터를 먼저 삭제함.

/-------------------------/  메모리상에서
|                         |       높은 구역
|         Stack           |
|                         |
/-------------------------/
|                         |
|          Heap           |
|                         |
/-------------------------/
|   Uninitialized data    |
| ---------Data---------- |
|    Initialized data     | 
/-------------------------/
|                         |
|          Text           | 
|                         |  메모리상에서
/-------------------------/       낮은 구역

[참고] 

https://m.blog.naver.com/PostView.nhn?blogId=codingspecialist&logNo=221195242403&proxyReferer=https%3A%2F%2Fwww.google.com%2F

http://dsnight.tistory.com/50

https://kldp.org/node/199

 

 

 

보간

 

tracking하는데 position에 multiplier를 적용해서 끊김현상이 심하게 일어나서 보간을 해주었다.

보간 코드는 아래와 같다.

1
transform.position = Vector3.Lerp(transform.position, movePos * multiplier, Time.deltaTime * 10.0f);
cs

 

multiplier는 이동해야될 목적지 코드에 곱해주면 된다.

이후에 곱하면 보간이 잘 작동하지 않더라...

Posted by 도이(doi)
,


데카르트 좌표에서의 이동을 구면좌표 이동으로 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, -22-180180);//longitude
        Latitude = remap(Y, -22-180180);//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


Posted by 도이(doi)
,

구면좌표계 개념 관련

http://underwatch.tistory.com/47


구면좌표로 이동하는 개체와 총알 스크립트

https://answers.unity.com/questions/41050/how-can-i-make-movement-on-a-sphere.html


Posted by 도이(doi)
,

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
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
 
public class CardesianMove : MonoBehaviour {
 
    public Vector3 position;
 
    private RaycastHit hit;
    private Vector3 movePos;
 
    private void Start()
    {
        movePos = transform.position;
    }
    
    private void Update()
    {
        Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition);
        if (Physics.Raycast(ray, out hit, 10000))
        {
            movePos = hit.point;
        }
 
        //movePos로 이동하는 벡터의 절대값이 
        if ((movePos - transform.position).sqrMagnitude >= 0.3f * 0.3f)
        {
            Vector3 lookDir = hit.point - transform.position;
            lookDir.z = 0;
            transform.rotation = Quaternion.LookRotation(lookDir);
            transform.Translate(Vector3.forward * Time.deltaTime * 10.0f);
 
            Vector3 pos = transform.position;
            pos.z = 0;
            transform.position = pos;
 
            position = transform.position;
        }
    }
}
 
cs


미래의 내가 아마 정리하겠지...


sqrMagnitude를 왜 사용해야되는지 잘 정리해둔 블로그 

http://teddy.tistory.com/19


간략히 정리하자면 sqrMagnitude는 거리와 관련된 계산을 위해서 사용함. 

Magnitude에 비해서 루트 연산을 하지 않기 때문에 계산이 더 빠르다고 한다. 

Posted by 도이(doi)
,