평면 ( 3개의 점 )과 직선 (원점과 방향)의 교차점을 구하는 방법이다.

수학적 개념보다 코드가 더 이해가 빠른거 같다.


Unity 상에서 C#코드를 통해 계산했습니다. (Intersect Triangle)


무한 평면 기준

    private bool IntersectTriangle(Vector3 RayOrigin, Vector3 RayDirection, Vector3 V0, Vector3 V1, Vector3 V2)
{
Vector3 edge1 = V1 - V0;
Vector3 edge2 = V2 - V0;

Vector3 pvec = Vector3.Cross(RayDirection, edge2);

dot = Vector3.Dot(edge1, pvec);

Vector3 tvec;
if (dot > 0) tvec = RayOrigin - V0;
else
{
tvec = V0 - RayOrigin;
dot = -dot;
}

if (dot < 0.0001f)
return false;

u = Vector3.Dot(tvec, pvec);
// if (u < 0.0f || u > dot)
// return false;

Vector3 qvec = Vector3.Cross(tvec, edge1);

v = Vector3.Dot(RayDirection, qvec);
// if (v < 0.0f || u + v > dot) return false;

t = Vector3.Dot(edge2, qvec);
float flnvDet = 1.0f / dot;

t *= flnvDet;
u *= flnvDet;
v *= flnvDet;

return true;
}

코드 자체의 원리는

1. 3개의 점을 통해서 2개의 직선을 구한다.

2. 2개의 직선을 외적해서 법선 벡터를 구한다.

3. 내적을 통해 직선의 방향을 결정한다.


3 - 1 유한 평면의 경우 내적을 통해 u를 계산, 평면의 좌, 우를 넘어갔는지 판단한다.

3 - 2 유한 평면의 경우 내적을 통해 v를 계산, 평면의 위, 아래를 넘어갔는지 판단한다.


if (IntersectTriangle(Line.position, Line.forward, P0.position, P1.position, P2.position))
{
Vector3 point = Line.position + (Line.forward * t);
Gizmos.DrawSphere(point, 0.1f);
}

true 일때만 교차점이 생기고 , 교차점은 직선의 원점 + 직선의 방향 * t로 구하면 된다.


유한 평면 기준

IntersectTriangle의 주석처리된 부분을 풀어주면 유한 평면에서만 충돌하는지 검사 가능



Vector3 Direction to Quaternion (Rotation)

방향 벡터를 이용해서 쿼터니언 (로테이션) 구하기


this.front.subVectors( this.finalTarget, this.resultPos );
this.front.normalize();

현재 좌표에서 바라볼 대상의 좌표를 뺀다.

정규화 (Normalize) 하면 대상을 바라보는 Look Vector (front)가 생긴다.


this.up.set( 0, 1, 0);

Up vector를 설정한다. (일반적으로 0, 1, 0인 상황)

만약 지구와 같은 구체주변을 맴돈다면


this.up.copy( this.object.position );
this.up.normalize();


자신의 좌표를 이용해서 Up벡터를 구한다. (지구의 중점이 0, 0, 0 이라는 기준으로)


this.right.crossVectors( this.up, this.front );
this.right.normalize();

up벡터와 front벡터를 Cross 시켜서 Right 벡터를 구한다.


this.up.crossVectors( this.front, this.right );
this.up.normalize();

front와 right를 이용해서 다시 Up벡터를 구한다.


일반적으론 이렇게 나온 right, up, front에 적용시키면 로테이션이 적용된다.

이번은 Matrix를 이용해서 Quaternion을 구해보자.


Matrix mBasis = new Matrix(vRight.X, vRight.Y, vRight.Z, 0.0f,
vUp.X, vUp.Y, vUp.Z, 0.0f,
vDirection.X, vDirection.Y, vDirection.Z, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f);

Quaternion qrot = new Quaternion();
qrot.W = (float)Math.Sqrt(1.0f + mBasis.M11 + mBasis.M22 + mBasis.M33) / 2.0f;
double dfWScale = qrot.W * 4.0;
qrot.X = (float)((mBasis.M32 - mBasis.M23) / dfWScale);
qrot.Y = (float)((mBasis.M13 - mBasis.M31) / dfWScale);
qrot.Z = (float)((mBasis.M21 - mBasis.M12) / dfWScale);

이렇게 나온 쿼터니언 (Quaternion)을 이용해서 Rotation을 적용시키면 된다.

acos(x) 로 구했다가 난감한 경험이 있었다.


제대로된 Angle을 구하고 싶다면


let angle = Math.atan2( y, x ) * RAD2DEG; 하면 정상적인 각도가 나옴


디스플레이 화면 특성상 Y값이 밑으로 갈수록 증가하기 때문에


실제로는 다음과 같은 식으로 구현했다.


var RAD2DEG = 180 / Math.PI;
let angle = Math.atan2( -y, x ) * RAD2DEG;


색상코드를 보면 가끔 RGB도 HEX도 아닌 Decimal로 되어있는 색상 코드가 있다.


예시

RGB : 255, 255, 255 => 16777215

RGB : 255, 0, 0 => 16711680


이러한 Decimal 색상 코드를 RGB 로 변환해 보자.


Color = 16777215


R = Math.floor( Color / ( 256 * 256 ) )

G = Math.floor( Color / 256 ) % 256;

B = Color % 256;


빛이 벽을 통해서 반사 되거나


공튕기기 게임에서 벽에 부딪힐때 반사각을 구해보자


1. 진행방향 벡터 (p) 와 충돌한 부분의 법선벡터 (n) 가 필요하다.

let n = this.result.normal; // 법선 벡터
let p = []; // 원래 벡터
p2.vec2.sub( p, this.rayClosest.from, this.rayClosest.to );

2. 진행방향 벡터의 역벡터 (-p) 를 구한다.

let minusP = [];         // 역 벡터
p2.vec2.sub( minusP, this.rayClosest.to, this.rayClosest.from);

3. 역벡터 (-p) 와 법선 벡터의 (n) 내적 (dot)을 구한다.

// 내적 계산
let dot = p2.vec2.dot( minusP, n );

4. 법선 벡터를 2배로 (2 * n) 늘린다.

// 법선 벡터 2배
let mulNormal = [];
p2.vec2.scale( mulNormal, this.result.normal, 2 );

5. 2배 길이의 법선벡터를 내적이 계산된 값만큼 스케일을 조절한다. ( 2 * n * dot(-p, n) )

let finalNormal = [];
p2.vec2.scale( finalNormal, mulNormal, dot );

6. 원래 진행방향 벡터 (p)에 5번에서 계산된 벡터 (스케일 조절된 법선 벡터) 를 더한다. ( p + 5번 결과 벡터 )

p2.vec2.add( reflect, p, finalNormal ); // 반사벡터 산출

7. 구해진 반사벡터를 정규화시킨다. ( normalize reflect )

p2.vec2.normalize( reflect, reflect );  // 정규화

8. 2d Screen의 특성에 따라 (y값이 밑으로 갈수록 증가) 역벡터를 구하면 완성( negate reflect )

p2.vec2.negate( reflect, reflect );     // 스크린 특성


마지막으로 계산된 reflect를 물체의 방향 (direction) 으로 사용하면 잘 반사된다.


- 참고 하면 좋은 수학적 개념 -

http://toymaker.tistory.com/entry/%EB%B0%98%EC%82%AC-%EB%B2%A1%ED%84%B0-Reflection-Vector

https://www.slideshare.net/cancan21st/ss-17299826

http://ifyouwanna.tistory.com/entry/%EB%B0%98%EC%82%AC%EB%B2%A1%ED%84%B0

Duplicate Class Define 에러가 발생하는데 빌드는 당장 해야되면


빌드 옵션 설정 -> Minify 에서 Proguard를 사용하지 않는다.

'기타 > ETC' 카테고리의 다른 글

유니티 안드로이드 APK 빌드 하기 (Unity to Android APK)  (1) 2017.08.16
API 에러창 띄우기  (0) 2017.04.20
size_t 란 무엇인가? C++  (0) 2017.04.09

Unity로 만든 게임을 휴대폰 APK로 빌드해서 실행 해보자.


Unity 설정변경 + NVIDIA Codeworks 에서 받은 파일을 설치, 빌드 할 예정이다.


유니티 메뉴중 File 메뉴 -> Build Settings 를 클릭한다.



빌드 설정을 변경하는 부분이다.


1. Scenes In Build (맨위 창) 에는 게임에 사용될 씬이 모두 있어야 한다. 만약 없다면 씬전환이 이루어 지지 않는다.

2. Platform에서 Android를 클릭한다.

3. 왼쪽 밑의 Switch Platform을 클릭하면 변환이 진행된다. 상당히 오래 걸린다.


만약 안드로이드를 눌렀는데 오른쪽 밑의 화면이 안뜬다면 ?

이 사진처럼 Open Download Page가 있을것이다. (예시는 IOS) Open Download Page클릭 한뒤 설치하면 된다.


변환이 모두 완료됬다면 https://developer.nvidia.com/codeworks-android 사이트로 이동한다.

다음과 같은 창이 뜰텐데 Download 녹색 버튼을 클릭한다.

오른쪽의 DOWNLOADS 밑의 녹색 글씨중 Windows ( 64-bit)를 클릭해서 다운로드 한다. (맥이면 맥으로 다운로드)

이때 NVIDIA 계정이 필요하다.

CodeWorksforAndroid-1R6-windows.z01

CodeWorksforAndroid-1R6-windows.zip

CodeWorksforAndroid-1R6-windows.z02


언제 까지 될진 모르겠는데 첨부파일을 다운로드 해도 된다.



실행하면 다음과 같은 창이 반겨준다. Next > 를 클릭하자.


여기서도 다음 클릭

설치 경로 와 임시 다운로드 경로 (PATH)를 설정해야 하는데 가급적 기본 설정 그대로 두는것을 추천한다. Next > 클릭

다음과 같은 화면이 뜨게 될텐데

어떠한 버전으로 빌드하느냐에 따라 설정이 달라진다.

내 핸드폰은 안드로이드 7.0이고 안드로이드 5.0이상에서만 실행할 생각이기 때문에 5.0 이전 버전은 설치를 안할 예정

설치를 안할 버전은 클릭해서 no action으로 변경해 주면 된다.

no action을 선택하면 다음과 같은 창이 뜨는데 Keep & Apply 클릭해주면 된다.

나는 다음과 같이 설정했다. 5.0이전 버전만 no action으로 선택하고 나머지는 그대로 두었다.


그다음 왼쪽 아래에 있는 Automatically resolve dependency conflicts 에 체크하고 설치하는게 편하다.

체크 안하면 확인확인 엄청 눌러줘야됨

Next 를 누르면 다음과 같은 창이 나온다.

Accept All 한뒤 Accept 버튼 누르면 된다. 어차피 체크 안하면 못씀

다운로드가 시작되면 용량이 상당하다. 전부 설치시 약 11기가를 차지한다고 설명에 나온다.

설치가 완료됬다면 재부팅 하라고 알림이 뜰텐데 재부팅 해주자


재부팅 이후 이제 Unity에서 Path (경로) 설정을 해주자


유니티 Edit 메뉴의 Preferences를 클릭한다.

External Tools 메뉴에 들어가면 SDK, JDK 경로가 빈칸인데 이 부분을 설정할 거다.

SDK 옆의 Brose버튼을 누르면

경로를 변경하지 않고 그대로 설치했다면

C드라이브 -> NVPACK -> android-sdk-windows 폴더를 선택하면 된다.


마찬가지로 JDK 옆의 Browse 버튼을 누른뒤

C드라이브 -> NVPACK -> jdk1.8.0_77 폴더를 선택해 주면 된다.

위 사진처럼 경로가 정상적으로 설정 됬으면 완료이다.


다음은 프로젝트 이름, 조직과 관련된 설정을 할것이다.


유니티 메뉴 File -> Build Settings에서 왼쪽 밑의 "Player Settings..." 버튼을 클릭해 보자.

오른쪽 인스펙터에 다음과 같은 창이 표시될 것이다.

Company Name은 조직명이다.

Product Name은 상품명이다. 일반적으로는 게임 이름이다.


밑의 Identification의 Package Name을 보면 com.Company.ProductName 이렇게 하는게 일반적이다.

(www.naver.com 이런 주소처럼 역순으로 com.회사이름.제품이름 이렇게 서술한다.)

이때 숫자를 맨 앞에 표기하거나 한글을 사용하지 않는다.

스크립트를 만들때 맨앞에 숫자를 사용해서 만들어 봤으면 알겠지만 정상적으로 동작하지 않는다.


Identification안의 메뉴중 Minimum API Level은 이 프로그램이 작동할 최소 버전을 선택하는 것이다.

나는 안드로이드 5.0 롤리팝 부터 지원하도록 5.0을 선택했다

이렇게 했으면 설정은 끝났다.


File -> Build Settings에서 Build 버튼을 클릭한다.

APK 파일명을 뭐로 할지 정해주고 저장을 누르면 빌드를 시작한다.

이 파일을 핸드폰에 넣어준뒤 설치해주면 휴대폰에서 실행할 수 있다.

'기타 > ETC' 카테고리의 다른 글

Unity Gradle Build 에러시  (0) 2018.07.02
API 에러창 띄우기  (0) 2017.04.20
size_t 란 무엇인가? C++  (0) 2017.04.09

코딩을 하다보면 다음 사진과 같은 화면이 필요할 때가 있다.

어느부분에서 에러가 났는지 확인하기 위한 용도인데 이번에는 이 에러창을 띄워보자.


필요한것 : assert.h


공용헤더(stdafx.h)에 assert.h를 선언한다.

그뒤 에러를 확인하고자 하는 부분에서 다음과 같은 코드를 삽입하자.


지금 이 코드는 만들어진 객체 하나를 해제하는 과정이다.

m_pD3DDevice->Release(); 밑에

error = 1; 로 하게되면

창을 닫았을때 저렇게 에러 창이 발생한다.


assert를 이용해서 저런식으로 에러창을 만들수 있다.

'기타 > ETC' 카테고리의 다른 글

Unity Gradle Build 에러시  (0) 2018.07.02
유니티 안드로이드 APK 빌드 하기 (Unity to Android APK)  (1) 2017.08.16
size_t 란 무엇인가? C++  (0) 2017.04.09

정방행렬 == 정사각행렬 == 가로줄 개수와 (행) 세로줄 개수 (열)이 같은 행렬


항등행렬 : Identity

A행렬 X 항등행렬 = A행렬이 나오게 하는 행렬

항등행렬은 정방행렬일때만 가능하다.

전치행렬 : Transpose

원래 행렬에서 행과 열을 서로 바꿔주는것

행렬식 : Determinant

행렬식의 값이 0이라면 역행렬이 나올수 없고 행렬식의 값이 !0(0이아니라면)이면 유일한 해를 가진다.

라플라스 전개를 통한 정의 (재귀함수)를 이용해 구할 수 있다.


소행렬식 : Minor

각 차수를 제외하고 나머지를 행렬로 만든것

   1 2 3           a11의 소행렬식은             a22의 소행렬식은

   4 5 6   ->             5 6              ->              1 3

   7 8 9                   8 9                               7 9


여인자 : Cofactor

거기에 1 또는 -1을 값으로 하는 계수를 곱한것.





여기서 det == determinent , C == Cofactor

수반행렬 : adjoint

그 행렬의 전치행렬에서 각 원소의 복소켤레를 취한것

->모든 항의 Cofactor(여인자)를 구하고 행렬을 Transpose(전치) 한 행렬



역행렬 : Inverse

A행렬 X A역행렬 = 항등행렬

lAl는 A의 Determinant값 , C는 Cofactor , 차수위치에 있는 T는 Transpose



벡터 : 방향과 크기를 가지고 있다.

스칼라 : 힘의 크기 또는 위치만을 가지고 있다.


우리가 지금까지 알고있는 개념은 전부 스칼라.

총알이 날라가고 있다. 이 총알의 좌표가 아니라 총알이 어느 방향으로 얼마만큼의 힘으로 가는지 표현해야한다.

이때 사용되는게 벡터의 개념 (어느 방향으로 얼만큼의 힘으로 가는지)


+ Recent posts