일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- NRVO
- algorithm
- directx
- 백준
- const
- RVO
- 팰린드롬 만들기
- IFileDialog
- RootMotion
- Unreal Engine5
- Programmers
- 2294
- 티스토리챌린지
- GeeksForGeeks
- winapi
- DirectX11
- UE5
- C
- Frustum
- 1563
- 프로그래머스
- baekjoon
- 오블완
- UnrealEngine5
- C++
- softeer
- UnrealEngine4
- 언리얼엔진5
- DeferredRendering
- 줄 세우기
- Today
- Total
Game Develop
nan값 조심하자 본문
예전에 2D포폴했을때는 몬스터->플레이어의 방향벡터를 정규화하는 과정에서 nan값이 발생했었다.
분모에 0이 들어가면 안되는데, 몬스터랑 플레이어랑 거의 겹쳐져버리면 x2-x1값도 0, y2-y1값도 0이라 분모에 루트0값이 들어가버려서 nan값이 발생했었다.
근데 이번에도 몬스터가 증발하길래 열심히 추적해서 해결했다.
먼저 여차저차해서 몬스터의 WorldMatrix값에 nan값들이 포함되어있는걸 확인 -> rotation.y가 nan값이 발생되는걸 확인-> assert이용해서 어떤 함수에서 rotation.y에 nan값이 대입되는지 확인 -> 해당함수 벡터값 다 출력찍어봐서 확인 -> cmath::acos 함수에서 nan값이 리턴(!).
acos 관련 글 :
https://runebook.dev/ko/docs/cpp/numeric/math/acos
즉,매개변수가 -1 ~ 1의 범위를 벗어나면 nan값을 리턴.
일단 해당함수코드.
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
|
void Transform::RotateToDestinationForModel(Transform* transform, Vector3 dest) // 회전시키고자 하는 transform과 목표지점벡터.
{
dest = dest - transform->mPosition;
dest.Normalize(); // 정규화
Vector3 tempForward = transform->GetForwardVector();
Vector3 forward = tempForward * -1.0f; // 모델 포워드 거꾸로 되어있어서 -1 곱
float dotValue = Vector3::Dot(forward, dest); // 얼마나 회전할지.
if (dotValue < -1.0f)
{
dotValue = -0.99f;
}
if (dotValue >= 1.0f)
{
dotValue = 0.99f;
}
dotValue = acos(dotValue);
Vector3 tempDirection = Vector3::Cross(forward, dest); // 어디로 회전할지
if (tempDirection.y < 0.0f) // 목표지점디렉션이 포워드벡터보다 왼쪽에 있으면
{
transform->mRotation.y -= dotValue;
}
else if (tempDirection.y >= 0.0f) // 디렉션이 포워드벡터보다 오른쪽에 있으면
{
transform->mRotation.y += dotValue;
}
bool check = false;
if (isnan(tempForward.x) || isnan(tempForward.y) || isnan(tempForward.z))
{
check = true;
}
assert(!check && "mRotation.y is Nan!!!!");
}
|
cs |
딱히 별다를게 없는 오브젝트를 타겟을 향해 회전시키는 코드.
말했듯이 acos에 값이 1이 들어가서 nan값이 발생한걸 확인. 1은 내적값 결과라서 확인해본 결과 내적을 위한 두 벡터가 거의 같은값의 벡터가 되버리는 경우가 발생. 거의 같은방향벡터면 사이각이 0이라 코사인 0도인 1을 리턴했기 때문에 acos에 1이 들어가서 nan값을 리턴했던 것.
이제서야 보고나니 런타임중에 충분히 두 벡터가 같을 경우가 있을만 하다고 생각했다.
일단은 저렇게 임시코드..를 작성. 당장의 생각으로는 저렇게해도 큰 문제가 없다고 판단했다.
애초에 worldMatrix의 값을 건드는 코드일 경우, 반드시 nan값을 체크하는 assert를 박아넣자.
'ComputerGraphics > My Project' 카테고리의 다른 글
그림자매핑 구현. (0) | 2022.10.03 |
---|---|
여러가지 개선. (0) | 2022.08.16 |
기본 UI 구현 (0) | 2022.08.03 |
고유이름(태그) 설정하기. (0) | 2022.07.29 |
DLL파일 버전 교체할 때 알아두면 좋은 점. (0) | 2022.07.28 |