Microsoft MVP성태의 닷넷 이야기
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
(연관된 글이 1개 있습니다.)
(시리즈 글이 6개 있습니다.)
Graphics: 15. Unity - shader의 World matrix(unity_ObjectToWorld)를 수작업으로 구성
; https://www.sysnet.pe.kr/2/0/11633

Graphics: 17. Unity - World matrix(unity_ObjectToWorld)로부터 TRS(이동/회전/크기) 행렬로 복원하는 방법
; https://www.sysnet.pe.kr/2/0/11637

Graphics: 18. Unity - World matrix(unity_ObjectToWorld)로부터 Position, Rotation, Scale 값을 복원하는 방법
; https://www.sysnet.pe.kr/2/0/11640

Graphics: 22. Unity - shader의 Camera matrix(UNITY_MATRIX_V)를 수작업으로 구성
; https://www.sysnet.pe.kr/2/0/11692

Graphics: 23. Unity - shader의 원근 투영(Perspective projection) 행렬(UNITY_MATRIX_P)을 수작업으로 구성
; https://www.sysnet.pe.kr/2/0/11695

Graphics: 25. Unity - shader의 직교 투영(Orthographic projection) 행렬(UNITY_MATRIX_P)을 수작업으로 구성
; https://www.sysnet.pe.kr/2/0/11700




Unity - World matrix(unity_ObjectToWorld)로부터 TRS(이동/회전/크기) 행렬을 복원하는 방법

지난 글에서,

Unity - shader의 World matrix(unity_ObjectToWorld)를 수작업으로 구성
; https://www.sysnet.pe.kr/2/0/11633

unity_ObjectToWorld 행렬을 직접 구성해 봤습니다.

월드 행렬은 T(Translate), R(Rotation), S(Scale) 연산으로 이뤄지는데요, 지난 글에서는 unity_ObjectToWorld로부터 Translate 값들만 복원하는 법을 설명했습니다.

moveMatrix[0] = float4(1, 0, 0, unity_ObjectToWorld._m03);
moveMatrix[1] = float4(0, 1, 0, unity_ObjectToWorld._m13);
moveMatrix[2] = float4(0, 0, 1, unity_ObjectToWorld._m23);
moveMatrix[3] = float4(0, 0, 0, unity_ObjectToWorld._m33);

그럼, 혹시 회전과 크기 연산에 대해서도 가져올 수 있지 않을까요? 다시 말해, Unity 에디터의 Inspector 창에서 설정한 Transform 설정들을 그대로 활용해 unity_ObjectToWorld를 다시 재구성해 보는 것입니다.

다행히, 이에 대해 아래의 글에서 공식을 설명하고 있습니다.

Given this transformation matrix, how do I decompose it into translation, rotation and scale matrices?
; https://math.stackexchange.com/questions/237369/given-this-transformation-matrix-how-do-i-decompose-it-into-translation-rotati

덧글에 따라 Scale의 경우 다음과 같이 복원할 수 있고,

float4x4 scaleMatrix; // Scale 행렬

vector sx = vector(unity_ObjectToWorld._m00, unity_ObjectToWorld._m10, unity_ObjectToWorld._m20, 0);
vector sy = vector(unity_ObjectToWorld._m01, unity_ObjectToWorld._m11, unity_ObjectToWorld._m21, 0);
vector sz = vector(unity_ObjectToWorld._m02, unity_ObjectToWorld._m12, unity_ObjectToWorld._m22, 0);

float scaleX = length(sx);
float scaleY = length(sy);
float scaleZ = length(sz);

scaleMatrix[0] = float4(scaleX, 0, 0, 0);
scaleMatrix[1] = float4(0, scaleY, 0, 0);
scaleMatrix[2] = float4(0, 0, scaleZ, 0);
scaleMatrix[3] = float4(0, 0, 0, 1);

Rotation은 이렇게 복원할 수 있습니다.

float4x4 rotationMatrix;

rotationMatrix[0] = float4(unity_ObjectToWorld._m00 / scaleX, unity_ObjectToWorld._m01 / scaleY, unity_ObjectToWorld._m02 / scaleZ, 0);
rotationMatrix[1] = float4(unity_ObjectToWorld._m10 / scaleX, unity_ObjectToWorld._m11 / scaleY, unity_ObjectToWorld._m12 / scaleZ, 0);
rotationMatrix[2] = float4(unity_ObjectToWorld._m20 / scaleX, unity_ObjectToWorld._m21 / scaleY, unity_ObjectToWorld._m22 / scaleZ, 0);
rotationMatrix[3] = float4(0, 0, 0, 1);

그래서 최종적으로 다음과 같은 유형으로 unity_ObjectToWorld를 분해 후 재구성할 수 있습니다.

v2f vert (appdata v)
{
    v2f o;

    float4 pos = v.vertex;

    float4x4 scaleMatrix;

    vector sx = vector(unity_ObjectToWorld._m00, unity_ObjectToWorld._m10, unity_ObjectToWorld._m20, 0);
    vector sy = vector(unity_ObjectToWorld._m01, unity_ObjectToWorld._m11, unity_ObjectToWorld._m21, 0);
    vector sz = vector(unity_ObjectToWorld._m02, unity_ObjectToWorld._m12, unity_ObjectToWorld._m22, 0);

    float scaleX = length(sx);
    float scaleY = length(sy);
    float scaleZ = length(sz);

    scaleMatrix[0] = float4(scaleX, 0, 0, 0);
    scaleMatrix[1] = float4(0, scaleY, 0, 0);
    scaleMatrix[2] = float4(0, 0, scaleZ, 0);
    scaleMatrix[3] = float4(0, 0, 0, 1);

    float4x4 rotationMatrix;

    rotationMatrix[0] = float4(unity_ObjectToWorld._m00 / scaleX, unity_ObjectToWorld._m01 / scaleY, unity_ObjectToWorld._m02 / scaleZ, 0);
    rotationMatrix[1] = float4(unity_ObjectToWorld._m10 / scaleX, unity_ObjectToWorld._m11 / scaleY, unity_ObjectToWorld._m12 / scaleZ, 0);
    rotationMatrix[2] = float4(unity_ObjectToWorld._m20 / scaleX, unity_ObjectToWorld._m21 / scaleY, unity_ObjectToWorld._m22 / scaleZ, 0);
    rotationMatrix[3] = float4(0, 0, 0, 1);
                
    float4x4 moveMatrix;

    moveMatrix[0] = float4(1, 0, 0, unity_ObjectToWorld._m03);
    moveMatrix[1] = float4(0, 1, 0, unity_ObjectToWorld._m13);
    moveMatrix[2] = float4(0, 0, 1, unity_ObjectToWorld._m23);
    moveMatrix[3] = float4(0, 0, 0, unity_ObjectToWorld._m33);

    float4x4 transformMatrix = mul(mul(moveMatrix, rotationMatrix), scaleMatrix);
    pos = mul(transformMatrix, pos);

    pos = mul(UNITY_MATRIX_V, pos);
    pos = mul(UNITY_MATRIX_P, pos);
    o.vertex = pos;

    o.uv = TRANSFORM_TEX(v.uv, _MainTex);
    return o;
}

이렇게 shader를 구성하고 Unity 에디터의 Transform 영역에서 Position, Rotation, Scale 값을 변경하면 그대로 값이 반영되는 것을 확인할 수 있습니다. (물론, 부동 소수점 연산의 특성상 미세한 오차는 있습니다.)

(첨부 파일은 이 글의 shader를 포함합니다.)




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]

[연관 글]






[최초 등록일: ]
[최종 수정일: 8/2/2018]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 




... 151  152  153  154  155  156  157  158  159  160  161  162  [163]  164  165  ...
NoWriterDateCnt.TitleFile(s)
972정성태1/7/201124248개발 환경 구성: 95. SQL Server 2008 R2 이하 버전 정보 확인
971정성태1/5/201133826.NET Framework: 199. .NET 코드 - Named Pipe 닷넷 서버와 VC++ 클라이언트 제작 [2]파일 다운로드1
970정성태1/4/201134339.NET Framework: 198. 윈도우 응용 프로그램에 Facebook 로그인 연동 [1]파일 다운로드1
969정성태12/31/201040413VC++: 45. Winsock 2 Layered Service Provider - Visual Studio 2010용 프로젝트 [1]파일 다운로드1
968정성태12/30/201026708개발 환경 구성: 94. 개발자가 선택할 수 있는 윈도우에서의 네트워크 프로그래밍 기술 [2]
967정성태12/27/201028438.NET Framework: 197. .NET 코드 - 단일 Process 실행파일 다운로드1
966정성태12/26/201026386.NET Framework: 196. .NET 코드 - 창 흔드는 효과파일 다운로드1
965정성태12/25/201027907개발 환경 구성: 93. MSBuild를 이용한 닷넷 응용프로그램의 다중 어셈블리 출력 빌드파일 다운로드1
964정성태12/21/2010143080개발 환경 구성: 92. 윈도우 서버 환경에서, 최대 생성 가능한 소켓(socket) 연결 수는 얼마일까? [14]
963정성태12/13/201027962개발 환경 구성: 91. MSBuild를 이용한 닷넷 응용프로그램의 플랫폼(x86/x64)별 빌드 [2]파일 다운로드1
962정성태12/10/201022771오류 유형: 110. GAC 등록 - Failure adding assembly to the cache: Invalid file or assembly name.
961정성태12/10/201099850개발 환경 구성: 90. 닷넷에서 접근해보는 PostgreSQL DB [5]
960정성태12/8/201045168.NET Framework: 195. .NET에서 코어(Core) 관련 CPU 정보 알아내는 방법파일 다운로드1
959정성태12/8/201031971.NET Framework: 194. Facebook 연동 - API Error Description: Invalid OAuth 2.0 Access Token
958정성태12/7/201028979개발 환경 구성: 89. 배치(batch) 파일에서 또 다른 배치 파일을 동기 방식으로 실행 및 반환값 얻기 [2]
957정성태12/6/201031741디버깅 기술: 31. Windbg - Visual Studio 디버그 상태에서 종료해 버리는 응용 프로그램 [3]
953정성태11/28/201036982.NET Framework: 193. 페이스북(Facebook) 계정으로 로그인하는 C# 웹 사이트 제작 [5]
952정성태11/25/201025377.NET Framework: 192. GC의 부하는 상대적인 것! [4]
950정성태11/18/201076756.NET Framework: 191. ClickOnce - 관리자 권한 상승하는 방법 [17]파일 다운로드2
954정성태11/29/201048759    답변글 .NET Framework: 191.1. [답변] 클릭원스 - 요청한 작업을 수행하려면 권한 상승이 필요합니다. (Exception from HRESULT: 0x800702E4) [2]
949정성태11/16/201027275오류 유형: 109. System.ServiceModel.Security.SecurityNegotiationException
948정성태11/16/201036157.NET Framework: 190. 트위터 계정으로 로그인하는 C# 웹 사이트 제작 [7]파일 다운로드1
947정성태11/14/201041724.NET Framework: 189. Mono Cecil로 만들어 보는 .NET Decompiler [1]파일 다운로드1
946정성태11/11/201041604.NET Framework: 188. .NET 64비트 응용 프로그램에서 왜 (2GB) OutOfMemoryException 예외가 발생할까? [1]파일 다운로드1
945정성태11/11/201025098VC++: 44. C++/CLI 컴파일 오류 - error C4368: mixed types are not supported
944정성태11/11/201031629VC++: 43. C++/CLI 컴파일 오류 - error C2872: 'IServiceProvider' : ambiguous symbol could be ...
... 151  152  153  154  155  156  157  158  159  160  161  162  [163]  164  165  ...