TIL (Today I Learned)
오늘 해야할 것
- Move 구현
- Rotate 구현
- Move 코드 비교 & 분석 -> 왜 다르고 뭐가 다르고 대표님은 왜 저렇게 짰을까?
- ProjectVectorOnToPlane, ProjectVectorOnToVector, ProjectOnTo
오늘 한 것
- World 좌표계 기준으로 Move 구현
- 코드는 내가 짰지만 왜 되는지 잘 모르겠다 -> 함수에 대한 이해가 부족한 것 같다. 아직 그림 맞추기를 하고 있는 것 같다.
if (_grabbed == false)
return;
FVector handPos = _handSocketRef->GetComponentLocation();//world
FVector handMoveDir = handPos - _lastHandSocketPos; //world
FVector _forward = _meshKeyLocker->GetForwardVector(); //world
_forward.Normalize();
handMoveDir = handMoveDir.ProjectOnTo(_forward); //world
_meshKeyLocker->AddWorldOffset(handMoveDir); //world로 움직이겠다(Offset = location)
FVector location = _meshKeyLocker->GetComponentLocation();
_meshKeyLocker->SetWorldLocation(location);
- Rotate 구현 계획
1. 레버를 잡는다.
2. 잡고 있는 상태면 forward축 기준으로 시계방향으로 돌리면 시계 방향으로 돌아가고, 반시계 방향으로 돌리면 반시계 방향으로 돌아간다.
- 레버를 잡았다
- 손 위치가 생긴다.
- 레버를 시계방향으로 돌린다.
- 손 위치가 바뀐다.
- 돌렸으니까 변화값(각)이 생긴다.
- 축은 레버의 forward
- 각과 축을 이용해서 회전 시켜준다.
- 레버를 잡았다
- 손 위치가 생긴다.
- 손 위치를 변수로 가져온다. 손 위치는 FVector handPos = _handSocketRef->GetComponentLocation(); //world
- 레버를 시계방향으로 돌린다.
손 위치가 바뀐다.- 잡은 채로 돌리는거니까 손의 위치가 바뀐다기보다는 컨트롤러의 위치가 바뀌는 것
- v1= prevHandPos -lever의 중심
- v2= HandPos - lever의 중심
- 축은 레버의 forward
- FVector _forward = _meshKeyLocker->GetForwardVector(); //world
- 각과 축을 이용해서 회전 시켜준다
- _forward의 ProjectVectorOnToPlane
- v1, v2가 평면에 Projection 된 상태여야 함
- Projection 시킨 후에 v1과 v2 사이의 각 구하기. FVector angle;
- 각만큼 회전 시켜주는데 (SetRelativeAngle) 이 때 시계방향으로 돌리는지 반시계로 돌리는지 알려면 외적도 구해야함
- 외적은 v1, v2로 구해서 나온 v라는 것.
- 각 판별
- _forward.Dot(v) > 0 : 예각 - 시계방향 -> 각은 -
- _forward.Dot(v) < 0 : 둔각 - 반시계방향 -> 각은 +
- 성공!
// Rotation
FVector v1 = _lastHandSocketPos - _meshKeyLocker->GetComponentLocation();
FVector v2 = handPos - _meshKeyLocker->GetComponentLocation();
//중심축
FVector _forward = _meshKeyLocker->GetForwardVector();
//Projection
v1 = UKismetMathLibrary::ProjectVectorOnToPlane(v1, _forward);
v2 = UKismetMathLibrary::ProjectVectorOnToPlane(v2, _forward);
//Projection 시킨 v1, v2의 각 구해주기
double angle = UKismetMathLibrary::Abs(R1Math::GetAngleBetweenTwoVectors(v1, v2));
//v1, v2 외적해주기
FVector v = UKismetMathLibrary::Cross_VectorVector(v1, v2);
if (_forward.Dot(v) > 0)
{
_meshKeyLocker->AddRelativeRotation(FRotator(0, 0, -angle));
}
else
{
_meshKeyLocker->AddRelativeRotation(FRotator(0, 0, angle));
}
_lastHandSocketPos = handPos;
- Rotate 각 제한 계획
1. forward 축이 0도에서 180사이일 때만 회전할 수 있다.
- (레버의)forward의 회전 값(Roll)을 가져온다.
FRotator lockerRotateValue = _meshKeyLocker->GetRelativeRotation();
- forward의 회전 값이 0보다 작으면 forward의 회전값을 0으로 만들고
forward의 회전 값이 180보다 크면 forward의 회전 값을 180으로 만든다.
if (lockerRotateValue.Roll < 0.f)
{
lockerRotateValue.Roll = 0.f;
_meshKeyLocker->SetRelativeRotation(lockerRotateValue);
}
if (lockerRotateValue.Roll > 180.f)
{
lockerRotateValue.Roll = 180.f;
_meshKeyLocker->SetRelativeRotation(lockerRotateValue);
}
- Move 이동범위 제한 계획
1. 키를 좌우로 왔다갔다 할 수 있다 -> OK
2. 키의 상태(모양)에 따라서 이동 범위를 다르게 주고 싶다.
- 키의 상태를 정의하자
1) 튀어나온 부분이 나를 향하고 있는 상태
2) 그렇지 않은 상태
- 키의 상태를 정의하면 각각 상태에 따라 키의 왼쪽 손잡이 기준으로 최대 최소 이동 가능 거리를 구해준다.
- 키의 상태에 따라 키를 움직이면 각각 상태에 따라 최대, 최소 이동 가능거리만큼 이동한다.
- 키의 상태를 정의하자
1) 튀어나온 부분이 나를 향하고 있는 상태
- _meshKeyLocker의 Roll이 75도 ~ 105도
2) 그렇지 않은 상태
- _meshKeyLocker의 Roll이 75도 ~ 105도가 아닌 상태
- 키의 상태를 정의하면 각각 상태에 따라 키의 왼쪽 손잡이 기준으로 최대 최소 이동 가능 범위를 구해준다.
- 누가 이동하는가?
- 기준점을 구해준다.
왼쪽 끝으로 기준을 잡으려 했더니 계산하기 어려울 것 같아서 그냥 기준점은 물체의 중심. 따로 계산 더 안해주고 중심 좌표만 받아오면 되니깐.
- 이동 가능한 부분과 가능하지 않은 부분을 알려면?
- 영역을 나눠주는게 좋겠다.
- 영역을 나눠줬는데 이동 가능 범위는 어떻게 구할까?
1) 튀어나온 부분이 나를 향하고 있는 상태
이동 가능 범위: _meshKeyLocker의 중심축위치에서
x축끼리 계산하면(5.f)--------->(25.f)
2) 그렇지 않은 상태
이동 가능 범위: _meshKeyLocker의 중심 축 위치에서
x축끼리 계산하면
(5.f)--------->(12.f)
- 키의 상태에 따라 키를 움직이면 각각 상태에 따라 최대, 최소 이동 가능거리만큼 이동한다.
- 이동 거리만큼 이동해보자!
- 만약 _meshKeyLocker.X <5.f이면 _meshKeyLocker.X=5.f
- 키의 상태를 정의하자
1) 튀어나온 부분이 나를 향하고 있는 상태
- _meshKeyLocker의 Roll이 75도 ~ 105도
2) 그렇지 않은 상태
- _meshKeyLocker의 Roll이 75도 ~ 105도가 아닌 상태
// KeyLockerRotateState 설정하는 함수
EKeyLockerRotateState AR1Level1StrongBox::GetKeyLockerRotateState()
{
float x = _meshKeyLocker->GetRelativeRotation().Roll;
if ((x >= 75.f)&&(x<=105.f))
return EKeyLockerRotateState::State1_UpState;
return EKeyLockerRotateState::State2_FrontState;
}
- 키의 상태를 정의했으니 어디서 키의 상태를 어디서 바꿔줄 것인가?
- Tick 함수!
- 어떻게 바꿔줄 것인가? ---> 여기서 막힘
각각 상태에 따라 키의 왼쪽 손잡이 기준으로 최대 최소 이동 가능 범위를 구해준다.
1) 튀어나온 부분이 나를 향하고 있는 상태
이동 가능 범위: _meshKeyLocker의 중심축위치에서
x축끼리 계산하면
(5.f)--------->(25.f)
2) 그렇지 않은 상태
이동 가능 범위: _meshKeyLocker의 중심 축 위치에서
x축끼리 계산하면
(5.f)--------->(12.f)
- 키의 상태에 따라 키를 움직이면 각각 상태에 따라 최대, 최소 이동 가능거리만큼 이동한다.
- 이동 거리만큼 이동해보자!
- 만약 _meshKeyLocker.X <-12.f이면 _meshKeyLocker.X=12.f
오늘 배운 것
- 구현할 때 어떻게 시작하고 왜 글로 먼저 써봐야 하는지 이해했다.
- 글로 명확히 쓰고 시작하니까 정확히 뭘 필요로 하는지, 순서는 어떻게 되는지, 어떤 결과가 나와야 하는지 다시 한번 정리되었다.
내일 진행할 것
- 삼각함수 문제 풀기
다음주에 진행할 것
- 금고 이어 하기
앞으로 진행할 것
- 오큘러스 내 빌드 해결
- SCP 914 찾아보기
https://www.youtube.com/watch?v=-9rbYP0cDjU
https://www.youtube.com/watch?v=V2Ps5bM4TwE
if (CanLockerMove())
{
FVector dir = handPos - _lastHandSocketPos;
FVector front = _meshKeyLocker->GetForwardVector();
// Projected Location
dir = UKismetMathLibrary::ProjectVectorOnToVector(dir, front);
// World -> Local
dir = _meshKeyLocker->GetComponentTransform().InverseTransformVector(dir);
_meshKeyLocker->AddLocalOffset(dir);
FVector location = _meshKeyLocker->GetRelativeLocation();
if (location.X < LOCKER_MIN_X)
{
location.X = LOCKER_MIN_X;
_meshKeyLocker->SetRelativeLocation(location);
}
if (location.X > LOCKER_MAX_X)
{
location.X = LOCKER_MAX_X;
_meshKeyLocker->SetRelativeLocation(location);
}
}
{
float roll = _meshKeyLocker->GetRelativeRotation().Roll;
FVector v1 = _lastHandSocketPos - _meshKeyLocker->GetComponentLocation();
FVector v2 = handPos - _meshKeyLocker->GetComponentLocation();
FVector front = _meshKeyLocker->GetForwardVector();
// Projected Location
v1 = UKismetMathLibrary::ProjectVectorOnToPlane(v1, front);
v2 = UKismetMathLibrary::ProjectVectorOnToPlane(v2, front);
// 외적으로 방향 구하기
FVector v = UKismetMathLibrary::Cross_VectorVector(v1, v2);
// 내적으로 각도 구하기
double angle = UKismetMathLibrary::Abs(R1Math::GetAngleBetweenTwoVectors(v1, v2));
if (front.Dot(v) < 0)
_meshKeyLocker->AddRelativeRotation(FRotator(0, 0, angle));
else
_meshKeyLocker->AddRelativeRotation(FRotator(0, 0, -angle));
FRotator rotation = _meshKeyLocker->GetRelativeRotation();
if (rotation.Roll < LOCKER_MIN_X)
{
rotation.Roll = LOCKER_MIN_X;
_meshKeyLocker->SetRelativeRotation(rotation);
}
if (rotation.Roll > LOCKER_MAX_ROLL)
{
rotation.Roll = LOCKER_MAX_ROLL;
_meshKeyLocker->SetRelativeRotation(rotation);
}
}
'회사 TIL' 카테고리의 다른 글
[TIL] 22.12.20 / Key Cover Lerp 구현, LeftDoor 구현 (0) | 2022.12.20 |
---|---|
[TIL] 22.12.19 (0) | 2022.12.20 |
[TIL] 22.12.15 /World, Local 좌표 이해하기😥, Strong Box 1단계 도전 (0) | 2022.12.16 |
[TIL] 22.12.14 / Lever, Drawer, Wheel 구현 (0) | 2022.12.14 |
[TIL] 22.12.13 / Drawer, Wheel 코드 분석 (0) | 2022.12.14 |
댓글