2020년 11월 23일 월요일

삼성 Notebook 9 metal NVME SSD 교체기

삼성 Notebook 9 metal(NT900X5L)에 기본 장착되어 있는

Liteon의 128 GB M.2 SATA SSD를 M.2 NVME SSD로 교체하고자 관련 글들을 찾아 보았지만

NVME 지원 여부에 대한 글이 없어 교체기를 써보고자 합니다.




백 커버를 분리한 사진입니다.
오른쪽에 Liteon의 128 GB M.2 SATA SSD가 장착되어 있습니다.




SSD를 분리한 사진입니다.
단자가 3개로 분리되어 있는데 이를 통해 M.2 SATA 규격의 SSD 임을 알 수 있습니다.


https://en.wikipedia.org/wiki/M.2#cite_note-rog-asus-313352014-10


M.2 단자는 B키와 M키가 있는데, M.2 SATA 규격은 B/M키가 모두 있고
M.2 NVME 규격은 보다 넓은 대역폭을 사용하기 위해 M 키만 존재합니다.
따라서 단자의 종류에 따라 3개로 구분되는 경우 M.2 SATA,
2개로 구분되는 경우 M.2 NVME 규격으로 확인할 수 있습니다.



SSD를 분리한 M.2 단자를 확대하여 찍은 사진입니다.

단자가 M키를 기준으로 2갈래로 나누어 진 것으로 보아 

M.2 NVME SSD도 장착이 가능하나,

메인보드에서 M.2 NVME SSD를 지원하는지 여부는 설치 후 부팅하여 확인해야 합니다.




장착할 삼성 M.2 NVME SSD (PM961) 입니다.
PCIe 3.0 x4 규격으로 Seq 읽기 속도는 3000MB/s 이상입니다. 


노트북에 장착한 사진입니다.
노트북은 정상적으로 부팅 되었습니다.



CrystalDiskMark로 속도를 측정 하였을 때 Seq 읽기 속도가 2000MB/s 이하로 측정 되는 것으로 보아,
노트북이 SSD의 PCIe 3.0 x4 를 지원하진 않지만 보다 낮은 속도로 동작함을 알 수 있었습니다.

이상 Samsung Notebook 9 metal NVME SSD 교체기를 마칩니다.

2019년 5월 6일 월요일

3D Model Loading

버텍스, UV, 인덱스 정보를 담고있는 3D Model을 로드하여 화면에 그리고자 한다.
OBJ파일을 읽고 분류하여 데이터화 한다.

먼저, OBJ 파일을 자바의 FileReader 객체를 이용하여 Load하고, Line by Line으로 처리한다.


OBJ 파일로 3D Model Loading을 하기 위해서, Vertex, Texture(UV), Normal, Index 배열을 만든다. List를 사용하여 데이터를 구성하고 추후 Array 형태로 리턴한다.


OBJ 파일은 데이터가 Line 별로 구분되어 있으며, 각 라인의 Header에 따라 데이터를 분류할 수 있다. 각 라인의 데이터는 공백 문자로 구분되어 있으므로, 공백 문자로 Split하여 배열로 만든다.

v로 시작하는 라인은 Vertex 데이터로써, 3개의 좌표값으로 구성되어 있고 각각 x, y, z를 나타낸다.
vt는 Texture(UV)로써, 2개의 좌표값으로 구성되어 있고 각각 텍스쳐의 x, y 좌표를 나타낸다.
vn으로 시작하는 라인은 Normal 데이터로써, 3개의 좌표값으로 구성되어 있고 각각 x, y, z를 나타낸다. 각 버텍스에서의 법선 벡터를 나타낸다. 법선 데이터가 없어도 렌더링이 가능하지만, Light를 사용하는 경우 빛의 자연스러운 반사를 위해 법선 데이터가 필요하다.
f는 Face로, (v/vt/vn)의 순으로 위의 데이터의 Index를 나타낸다. Face 데이터의 경우 아래에서 분리하여 처리하기 위해 배열을 만들고 다음으로 넘긴다.



Face 데이터 또한 Space를 구분자로 사용하여 배열로 만든다.
각각의 배열은 면을 구성하는 3개의 버텍스에 대한 v, vt, vn의 인덱스를 담고 있으며, (v/vt/vn) 형태로 이루어져 있으므로 추가적으로 Slash를 구분자로 사용하여 다시 한번 배열로 분리한다.
분리한 버텍스 데이터는 processVertex() 함수를 호출하여 처리한다.



processVertex() 함수에서는 파싱한 버텍스 인덱스 데이터와 List, Array의 레퍼런스를 파라미터로 받는다.
버텍스의 인덱스 데이터는 (버텍스 인덱스, 텍스쳐 인덱스, 법선 인덱스) 순으로 전달된다.



처리할 버텍스 인덱스를 currentVertexPointer 변수에 저장한다. OBJ 파일에서의 인덱스는 1에서부터 시작하므로, 0부터 시작하는 기존 시스템에 적용하기 위해 인덱스 데이터에서 1을 뺀다. 버텍스 인덱스는 Indices List에 넣는다.


Texture(UV)를 처리할 차례이다. OBJ 파일에서 UV 값들을 파싱하여 추가했던 Textures List에서 인덱스 값을 활용하여 UV 데이터를 읽고 Vector2f 변수로 저장한다.
저장한 변수는 텍스쳐 배열에 저장하며, Serialize하게 저장하기 위해 버텍스 인덱스 포인터에 2를 곱한 위치에 x 값을, 이로부터 1 증가한 위치에 y값을 저장한다.

이 때, 1에서 y 값을 뺀 수를 배열에 저장하는데, 이는 3D Object를 만든 Blender에서 사용하는 좌표계와 OpenGL에서 사용하는 좌표계가 다르기에 이를 보정하기 위해 필요한 과정이다.
Blender는 일반적인 좌표계인 Bottom-Left 부터 시작하며 1사분면 영역으로 생각할 수 있다. OpenGL은 Top-Left 부터 시작하며, 4사분면 영역으로 생각할 수 있다. 위 좌표계는 x축 대칭이다.


위와 동일하게, 법선 데이터를 처리한다.


다시 loadObjModel() 함수로 돌아와서, 남은 Vertex, Index 배열에 데이터를 담는 작업을 진행한다. 아래와 같이 배열을 선언하고, List를 읽어 배열로 전환하여 저장한다.
배열로 전환이 완료되면 Loader의 loadToVao() 함수를 호출하여 VAO에 저장한다.

기존의 Static 데이터를 제거하고, 위에서 만든 loadObjMode()함수를 호출하여, OBJ 파일을 RawModel 객체로 변환한다. 텍스쳐를 로딩하고 Entity 객체로 만든다. Entity의 위치를 조정하고, 매 Loop 마다 Rotation의 y 값을 증가하여 y축 회전하도록 한다.

2019년 4월 29일 월요일

Obj export 및 파일 분석

이전 예제(http://blog.daechan.net/2019/04/blender-textured-cube.html) 에서 만든 Cube를 Obj 형식으로 Export 하고, Obj 파일 형식을 분석하고자 한다.

Blender로 Cube 프로젝트를 열고, 아래와 같이 File - Export - Obj 를 선택한다.

저장한 경로로 이동하여 Obj 파일을 선택하고, 텍스트 에디터로 열면 아래 그림과 같다.
본 예제에서는 Visual Studio Code를 사용하였다.

위의 Obj 파일은 아래와 같이 구성되어 있다.

  1. 주석 : Blender 버전 및 Original 파일 정보.
  2. mtllib : Material 파일 이름 (Texture)
  3. o : Object 이름
  4. v : Vertex 좌표값. (x, y, z)가 각각 space로 구분됨
  5. vt : Vertex Texture Coordinate. 0과 1 사이로 UV 좌표값을 나타낸다.
  6. vn : Vertex Normal. Vertex에 대한 Normal 좌표
  7. usemtl : Material 이름
  8. s : Smooth Shading 활성화 여부
  9. f : Face. 각 면의 정보. (v/vt/vn)의 순으로 위의 데이터의 Index를 나타낸다.

위의 Obj 구성 정보를 가지고, Cube 데이터에 적용하면 다음과 같다.

<V>
각 Vertex 좌표값을 나타낸다. -1 또는 +1 의 값으로 이루어지며 Cube의 각각의 Vertex를 의미하므로 총 8개로 구성되어 있다.

<VT>
X 좌표는 (0, 0.25, 0.5, 0.75, 1)로 나눌 수 있다. (소수점 오차가 있으나 무시한다.)
UV의 X좌표는 0에서 1 사이에서 Texture의 위치를 나타내며,
아래와 같이 가로 영역을 5개의 점으로 구분 한 만큼, 5가지의 X 좌표값이 존재하게 된다.

Y 좌표는 (0, 0.33, 0.66, 1)로 나눌 수 있고, 아래와 같이 세로 영역을 4개의 점으로 구분하였기에 4가지의 Y 좌표값이 존재하게 된다.

X 축으로는 5개의 점, Y 축으로는 4개의 점으로 나뉘어진다.
<VN>
Normal 좌표에 대한 정보로써, 각 Vertex에서의 법선 Vector 값을 가지고 있다.

<F>
각 면에 대한 정보를 가지고 있다.
정 육면체로써 6개의 Face로 구성되어 있다.
각 Face는 4개의 데이터셋으로 이루어져 있으며, v, vt, vn 의 Index를 나타낸다.
각 Index는 1부터 시작한다.
마지막 줄의 첫번째 데이터셋인 (8/13/6)은 각각 8번째의 v값, 13번째의 vt값, 6번째의 vn값을 나타내며 이를 변환하면 다음과 같다.
array의 index가 0부터 시작한다고 가정하여 각 Index에서 1을 빼주었다.

v[8 - 1] = (1.000000 1.000000 -1.000000)
vt[13 - 1] = (0.500000 0.995752)
vn[6 - 1] = (0.0000 1.0000 0.0000)

Index로 나타냄으로써 데이터의 중복을 막아 데이터 크기 감소의 효과가 있다.

예제에서 사용한 obj 파일 링크

Blender로 Textured Cube 만들기

1. Blender.org에서 Blender 다운로드 및 설치

Blender 실행 모습

블렌더를 시작하면 아래와 같이 초기 프로젝트가 로딩된다.
초기 프로젝트

모든 객체를 선택하기 위해 화면 클릭 후 A 키를 두번 누른다.
전체 선택 후 X키를 눌러 삭제 팝업을 띄우고 Delete를 선택하면 모든 객체가 삭제된다.


삭제 후 좌측 Create 탭에서 Cube를 눌러 Cube를 생성한다.


Cube가 생성되었다.

Cube의 위치를 (0, 0, 0)으로 이동하기 위해, N키를 눌러 우측 Transform 패널을 연 후 x, y, z 좌표를 모두 0으로 변경한다.

아래와 같이 좌표가 변경되었다.
이후 우측 Hierarchy 메뉴에서 Cube 옆 뒤집어진 삼각형을 눌러 버텍스 편집모드로 이동한다.

하단의 Edge select 를 눌러 Edge 선택 모드로 전환한다.

Cube를 십자가 형태로 펴기 위해 재봉선을 넣는 과정이다.
아래와 같이 Shift + 우 클릭으로 Edge를 선택한다.
잘 못 선택한 경우 A를 두번 눌러 선택을 초기화한다.

마우스 가운데 버튼을 클릭하고 드래그하면 Cube의 다른 면으로 이동할 수 있다.
하단의 Edge도 아래와 같이 선택한다.

재봉선(Seam)을 넣는 과정이다.
하단의 Mesh - Edges - Mark Seam 을 눌러 선택한 Edge에 Seam을 넣는다.

Seam은 붉은 색으로 표시된다.

이제 만든 Cube에 텍스쳐를 입히는 과정이다.
A를 두 번 눌러 모든 버텍스를 선택하고, Mesh - UV Unwrap - Unwrap을 눌러 Mesh를 UV Unwrap 한다.

상단의 Default view를 UV Editing 뷰로 전환한다.

아래와 같이 UV Unwrap 됨을 확인할 수 있다.

하단의 Image - Open Image 메뉴로 이동하여 Cube에 입힐 텍스쳐 이미지를 로드한다.
이미지 로드 후 Default 뷰에서 Mesh - UV Unwrap - Unwrap 과정을 반복하여, 버텍스들이 텍스쳐 위치를 이미지 크기에 맞게 이동하도록 한다.

아래와 같이 이미지가 로드 되었다.
하지만, 아래와 같이 UV 좌표가 잘 못 위치되어 있다.

UVs - Mirror - X Axis 메뉴를 눌러 모든 UV 좌표들에 대해 X축으로 Flip 시킨다.

결과물을 확인하기 위해 Default 뷰로 이동하여 하단의 Viewport Shading - Texture 를 선택한다.

아래와 같이 텍스쳐가 Cube에 입혀졌다.

Scroll로 Cube 내로 이동한 모습은 다음과 같다.

아래는 위의 예제에서 사용한 Cube 이미지이다.
https://en.wikipedia.org/wiki/Cube_mapping
예제에서 사용한 Blender 파일은 다음과 같다.

2019년 4월 8일 월요일

객체 정리

Vertices, Texture Coords(UV), Indices로 만든 VAO는 RawModel에 아래와 같이 저장한다.


또한, Texture는 Loader의 loadToTexture() 함수를 사용하여 ModelTexture 객체에 저장하며, ModelTexture는 int형식의 texture id를 저장한다.


ModelTexture 객체는 int형식의 texture id를 저장한다.

Object의 구성정보를 담은 RawModel과 Texture를 담은 ModelTexture를 묶어 TexturedModel 객체로 관리한다.



객체들간의 관계를 정리하면 다음과 같이 나타낼 수 있다.



Entity 객체는 Object의 구성정보 및 Texture 데이터를 담고 있는 TexturedModel과 3D 공간에서의 객체의 위치, 회전정보 및 Scale값을 담고있는 개체이다.



위의 관계를 정리하면 다음과 같이 나타낼 수 있다.