엘리트 컨트롤러 2 개봉기
한국에 정발된 엘리트 컨트롤러2를 질렀다.
엘리트 컨트롤러 1을 잘 썼었기에 2도 바로 질렀다.
11월 4일에 배송한다더니 5일에 옴.....
1. 하드웨어 및 박스
2. 소프트웨어
'전자기기' 카테고리의 다른 글
서피스 프로 4 (0) | 2015.11.20 |
---|---|
신티크 컴패니언 2 (3) | 2015.03.18 |
한국에 정발된 엘리트 컨트롤러2를 질렀다.
엘리트 컨트롤러 1을 잘 썼었기에 2도 바로 질렀다.
11월 4일에 배송한다더니 5일에 옴.....
서피스 프로 4 (0) | 2015.11.20 |
---|---|
신티크 컴패니언 2 (3) | 2015.03.18 |
신티크 컴패니언 2를 팔고 서피스 프로 4를 구입했다.
신티크 컴패니언 2는 사고 싶어서 산 게 아니라 그 당시 쓸만한 것 중에 그림 그릴만한 걸 찾다보니 어쩔 수 없이 고르게 된 것이었어서,
서피스 프로 4가 나온다는 소식에 얼른 중고로 내놓고 서피스 프로 4를 구매하였다.
모델은 i5, 8GB 램, 256GB SSD. 가격은 169만 9천원.
개봉기
1) 박스샷
2) 박스 안의 본체
3) 본체 & 본체 밑에 펜
4) 충전기
5) 서피스 충전기 특유의 USB 포트도 건재
6) 본체 비닐샷
7) 본체 비닐에 붙어있는 아이콘들
8) 본체
9) 뒷면
10) 좌측. 이어폰 구멍이 전부다
11) 우측. Mini DP, USB 3.0, 그리고 충전기 포트
12) 타입 커버 붙이고 킥스탠드 세워본 모습
13) 타입 커버. 살짝 흔들렸다...
14) 윗면. 전원 버튼 & 볼륨 버튼
15) 까만 로딩 화면을 찍으려 했으나 찍는 순간 윈도우 설정 화면이...
16) 펜 설정 화면
17) 펜. 버튼이 있는 면에 한해서 연필처럼 육각 효과를 주었다
18) 펜촉 박스샷
19) 펜촉 케이스
20) 윈도우 설정 끝
평가
매우 만족한다. 기존에 쓰던 신티크는 일반적인 노트북으로 사용하기에는 너무 무겁고,
키보드도 블루투스 키보드를 사용해야 되서 매우 불편했다.
까페처럼, 노트북을 올려놓을 수 있는 곳에서 사용하기에는 아무 문제가 없었으나,
급하게 켜야 되거나 무릎 위에 올려놓고 사용하는 건 사실상 불가능했었다.
그에 비해 서피스 프로 4는 매우 가볍고, 스크린 크기도 비슷하고, 타입 커버를 이용해서 키보드도 매우 편하게 사용할 수 있고,
올려놓을 장소가 없는 곳에서도 충분히 잘 쓸 수 있고, 올려놓을 곳이 있으면 더욱 편하게 쓸 수 있다.
스탠드도 매우 편하다. 일반적인 플립 커버처럼 단계별로 구분되는 것이 아닌, 그냥 원하는 만큼 각도를 정하는 방식이다.
대신에 펼 때 힘이 좀 들긴 하나.... 자유 각도가 되는데 그 쯤이야.
헤비한 작업을 할 때 팬 돌아가는 소리가 들리긴 하는데.... 사실상 없는 수준이다.
신티크에 비하면 없는 수준이고, 굳이 신티크에 비하지 않더라도, 도서관 등에서도 충분히 쓸 수 있을 거 같다.
펜의 경우 만족한다. 테스트 프로그램에선 필압 인식이 되는데 사용하는 그림 프로그램에서는 안 되길래,
아직 호환성 문제가 좀 있나.... 싶었으나 그냥 옵션 설정을 안 해줘서 그런 것이었다(...). 설정해주니 잘 된다.
이 부분은 내가 전문적으로 그림 그리는 사람이 아니라 취미로 그리는 사람 수준에서의 평가이니, 판단은 알아서.....
가격은 개인적으로는 만족한다. 본체 + 타입 커버 + 펜촉 다 합쳐도 190만원 조금 안 된다.
노트북 혹은 태블릿 PC 치고는 비싼 가격일 수 있으나, 그만큼 퀄리티가 보장해준다.
펜도 되고....
총평은 대만족.
잉여하는 용도로도, 그림 용도로도, 프로그래밍 용도로도 다 만족스럽다.
엘리트 컨트롤러 2 개봉기 (0) | 2019.11.05 |
---|---|
신티크 컴패니언 2 (3) | 2015.03.18 |
256GB 모델이다.
원래 서피스 프로 2를 잘 쓰고 있었으나,
가족 중 한 명이 노트북이 필요하게 되서 싸게 판 후,
내가 쓸 걸 찾다가 결국 이걸 사게 되었다.
'프로그래밍용 + 그림용 + 13인치 이상의 스크린 + 8GB 이상의 램'의 스펙을 만족하는 노트북을 원했었고,
저기서 13인치 이상의 스크린 조건만 빼면 서피스 프로2가 딱 맞는 조건이라 구매해서 썼었다.
이제 새로 사는 김에 스크린도 만족시키는 제품을 찾게 된 것이다.
개봉기
1) 살 때 같이 줬던 봉투
2) 본체 케이스 & 와콤 블루투스 키보드 케이스
3) 본체 비닐샷
4) 본체 들어내면 나오는 퀵가이드 & 스탠드
5) 스탠드 들어내면 나오는 파우치
6) 파우치 들어내면 나오는 각종 전선들
7) 저 전선들 밑에 숨겨져있던 케이블
8) 6번에 보이는 CD 케이스 같이 보이는 거 + 퀵 가이드.
진짜 CD 있을 줄 알았는데 그냥 제품 보증서 + 액정 클리너
9) 스탠드 뒷면. 참고로 재질이 매우 싸구려 같다
10) 스탠드 앞면
11) 스탠드 하나하나 펼쳐본 모양. 실제 착용샷은 뒤에 있습니당
12) 파우치 앞면. 스탠드와는 다르게 재질이 매우 좋다
13) 파우치 뒷면
14) 각종 파워 케이블들.
와콤 녀석들이 귀찮았는지 온갖 코드 종류를 다 넣어놨음...
220V용 빼고 나머지는 다 박스에 봉인
15) 박스 제일 밑에 따로 있던 케이블.
이걸 써서 데스크탑에 연결해서 일반 신티크처럼 쓰는거다.
왼쪽 건 잘 모르겠고, 오른쪽 두 개는 HDMI랑 USB.
HDMI로 화면 전송하고 USB로 펜 데이터 전송하는 듯
16) 맨 왼쪽 젠더 확대샷.
어디서 많이 본 건데 뭔지 모르겠다...
17) 신티크 펜 케이스
18) 펜 케이스 내부.
구성은 펜 + 색깔 링 3개 + 펜심 9개 + 펜심 교체기
19) 와콤 블루투스 키보드 & 들어있던 충전잭.
원래 예약 구매자한테만 주는건데 출시일 다음날이라 그런지 물량이 남았다고 주셨다
20) 드디어 본체!
저기 비친 건 내 손과 내 비루한 갤노트2...
사진 화질이 안 좋은 건 다 이유가 있는법입니다 허허
21) 본체 뒷면.
위 아래에 큰 홈은 스탠드 끼우는 구멍
22) 스탠드 제일 낮은 각도.
아 그리고 스탠드가..... 스탠드 그 자체도 그렇지만,
끼우는 방법도 매우 저퀄이다.
매우 잘 빠지기도 한다.
스탠드는 진짜 못 만들었다
23) 스탠드 중간 각도
24) 스탠도 제일 높은 각도 + 기르는 고양이.
참고로 스탠드의 경우 위아래를 바꿔 끼울 수 있는데,
그렇게 할 경우 이렇게 가파른 각도가 아니라 땅에 거의 붙는 각도가 된다.
즉 낮은 각도가 가능하다는 소리다
25) 인튜어스 프로 & 신티크 계열에 달려있는 흔한 버튼들.
참고로 오른손잡이 사용자 기준으로 이게 왼쪽이다
26) 25번의 버튼 반대편에 달려있는 와콤 로고.
오른손잡이 사용자 기준으로 오른쪽
27) 왼쪽의 버튼들.
사진상 맨 왼쪽 두 개가 볼륨 버튼이고,
왼쪽에서 세 번째 홈 같이 생긴 건 홈이 아니라 슬라이드식으로 동작하는 전원 버튼이다.
NDS 전원부를 생각하시면 될 듯
오른쪽에 있는 세 개는.... 솔직히 뭔지 모르겠다.
오른쪽 세 개 중 가운데 것도 슬라이드식 버튼인데, 뭐에 쓰는 걸까...
28) 오른쪽 포트들.
포트를 전부 오른쪽에 몰아놨다.
왼쪽부터 순서대로
이어폰 단자,
USB 3.0,
SD 카드 포트(SDHC 규격),
미니 DisplayPort,
데탑에 연결해서 일반 신티크로 쓸 수 있도록 하는 포트,
배터리 상태 나타내는 점멸등,
충전 포트,
USB 3.0 2개,
마이크로 SD 카드 포트
이다.
USB 3.0이 세 개라니.. 좋은 노트북이닷
29) 처음 부팅할 때 화면
30) 그냥 뭔가 웃겨서 찍은 거...
왜 북한은 North Korea인데 한국은 그냥 Korea죠...
31) 팬 돌아가는 소리를 듣고 관찰하러 온 고양이
32) 신티크 담아온 종이 봉투에 들어간 고양이
평가
무게도 괜찮고, 화면 크기도 괜찮고, 웬만한 건 다 좋다.
단점은 세 가지 정도.
그것도 별로 큰 단점은 아니다.
하나는 스탠드.
위에 개봉기에서도 적었었지만, 스탠드가 재질도 재질이고,
적용 방법도 너무 싸구려다.
서피스 프로3 보고 좀 따라했으면 안 되나....
거기에 웃긴 게, 스탠드를 스탠드 홈에 끼우면 후면 카메라가 완벽하게 가려진다.......
어쩌자는 거지.
두 번째는 화면.
화면 그 자체는 문제가 아니고 필름 때문인데,
기본적으로 안티글레어 필름이 붙어있다.
맨 처음에 봤을 때 그래픽 드라이버 안 깔았나... 싶었는데,
그래픽 쪽 작업하는 사람들은 안티글레어 필름을 많이 쓰는 모양이다.
어쨌든 순수 그래픽 쪽이라면 모를까,
코딩 & 텍스트 읽기 & 컨텐츠 소모용으로도 사용해야 하는 나한테는 단점.
뭐 그래도 보다보면 익숙해지겠지.
세 번째는 팬 소음...
팬이 뭐만 했다하면 돌아간다.
소리도 엄청 시끄러운 정도는 아닌데,
요새 팬 소리를 들을 일 자체가 거의 없다보니 쪼끔 거슬린다.
팬이 돌아가도 별로 뜨겁지는 않다.
즉 팬 돌아가는 소리만이 문제.
단점을 적고보니 스탠드만 제외하면 사람에 따라 단점이 될 수도, 안 될 수도 있을 것 같다.
스탠드는............. 후.
서피스도 2세대까지는 스탠드가 세 가지 각도 밖에 안 되서 많이 까인 후,
3세대에서 자유 각도가 되었다.
서피스 2세대는 스탠드 퀄리티라도 좋지, 이건 뭐...
가격은 동사양의 노트북 치고는 비싼 편.
물론 컴패니언은 신티크 기술값을 포함해서 생각해야 한다.
내가 산 모델은 i7 코어, 256GB SSD, 8GB 램 모델이고 259만원이다.
동급의 서피스 프로3가 189만원.
판단은 알아서....
어쨌든 총평은, 만족스럽다.
성능 좋고, 화면 크기도 시원시원하다.
프로그래밍용 & 그림용으로도 잘 쓸 수 있다.
P.S.
위에 스탠드 끼운 사진에서 이상한 각도로만 찍어서 그렇지,
홈 끼우는 방향을 반대로 하면 낮은 각도로도 세울 수 있다.
거의 땅에 붙는 수준까지 가능하다.
정방향으로 세 가지 각도, 역방향으로 세 가지 각도, 총 여섯 가지가 가능하다.
각도는 걱정없다.
엘리트 컨트롤러 2 개봉기 (0) | 2019.11.05 |
---|---|
서피스 프로 4 (0) | 2015.11.20 |
목표 : NodeJS C++ addon을 붙여서 네트워크 통신은 NodeJS가 담당하고 게임 로직은 C++이 담당하는 것
통신 방식 : ProtoBuf + socket.io
삽질기
0. 자동화 작업
.proto 파일을 통한 Auto generated 코드를 만들어서 통신하는 게 프로토버프의 기본.
근데 이 .proto 파일 하나를 C++/NodeJS/브라우저 세 곳에서 써야되기에,
파일을 한 군데서 작성하고, 나머지 위치에 복사해주는 방식을 택했다.
모든 빌드의 중심은 Visual Studio.
Visual Studio에서 prebuild, postbuild event로 스크립트를 돌리고,
거기서 protobuf C++ 코드 자동 생성도 하고, node 확장자 생성도 하고, .proto 파일 복사도 하고, 다 한다.
1. 클라 -> 서버
ProtoBuf.js를 이용해서 NodeJS/브라우저에서 .proto 파일을 파싱하고,
그 파싱한 정보로 decode/encode를 한다.
여기서 가장 효율이 좋은 것은 ArrayBuffer 통한 바이너리 형태의 데이터.
근데 문제는 socket.io는 바이너리 데이터의 전송을 지원하지 않는다.
문자열 온리......
찾아보면 socket.io로 바이너리 데이터를 보내고 받는 플러그인도 있으나,
귀찮아서(..) 그냥 hex 데이터를 보내고 받기로 했다.
ProtoBuf.js에서 base64, hex, AB(이게 뭐지), binary 네 가지 형태의 암호화 방식을 지원하고 있어서 가능한 방법이다.
어쨌든 브라우저는 패킷을 encodeHex로 보내고,
NodeJS는 그걸 받아서 decodeHex를 한 후,
그걸 다시 binary로 encode해서 C++ addon에 넘긴다.
C++ protobuf에서는 binary 데이터가 아니면 읽을 수 없기에.....
비효율적이긴 하지만, 나중에 브라우저 - NodeJS 패킷 통신을 바이너리로 직접 하게 바꾸면 해결되는 문제라 그냥 냅뒀다.
C++에 넘겨줄 때 패킷의 enum 값을 같이 넘겨주고, 그 enum 값에 따라 적절한 protobuf message 클래스를 이용해서
직렬화하면 완성! 나머지는 로직의 영역이다.
2. 서버 -> 클라
간단할줄 알았으나 내 코딩 시간을 며칠이나 잡아먹은 원흉 되시겠다.
일단 며칠 간의 삽질을 단 5분 만에 끝내도록 도와주신 최모군(28세, 백수)님에게 감사의 말을 올립니다.
C++ addon에서 NodeJS로 바이너리와 패킷 enum 값을 보내면
NodeJS에서는 그걸 encodeHex 해서 브라우저로 보내는 방식이다.
브라우저는 decodeHex 하면 되고.
문제가 두 가지가 있었다.
첫 번째는 NodeJS에서 C++로 넘겨준 자바스크립트 콜백 함수가 계속 증발하는 문제,
두 번째는 바이너리 데이터를 C++에서 NodeJS로 넘기는 문제였다.
첫 번째 문제가 며칠을 잡아먹은 문제다.
일단 C++ addon에서 SetSendFunction을 통해 콜백을 받고,
그 콜백을 멤버 변수로 저정해둔다.
그리고 나중에 Send를 할 때 그 콜백에 인자를 적절하게 넘기고 호출한다.
여기서 발생한 현상이, SetSendFunction으로 콜백을 저장하면
SetSendFunction 내부에서는 callback->IsFunction() 이 true로 나오지만,
나중에 Send 할 때 확인해보면 false가 나온다.
이게 도대체 왜 이러는지 알 수가 없어서, 구글링도 해보고,
gc가 알지 못하고 걍 죽여버리는 게 원인인가 싶어서(결국 이게 맞긴 했지만..)
NodeJS 쪽에서 로컬 변수로 함수를 만들고, 그 변수를 대입하는 방식도 써봤고,
C++ nodeJS addon을 만들어본 친구가 하필 일본에 가서 좌절도 해봤고,
진짜 온갖 꼼수 및 디버깅을 해봤지만 해결을 할 수 없었다.
열심히 삽질을 하고 있는 와중에, 잉챗에서 열심히 불평을 하고 있으려니까
최모군(28세, 백수)님이 보우하사, Local 대신 Persistent를 써보라고 말해주셨고,
Local<T> ->Persistent<T>로 못 바꾸고 고생하고 있자 친히 구글링을 하셔셔 stackoverflow 문서도 찾아주셨다.
그리고 해결이 되었다.
검색을 해본 결과, Persistent로 사용하면 v8 gc 관리 대상에 들어가고,
Local로 하면 안 들어간다고 한다.
그래서 Local로 저장해두면 나중에 gc가 회수해버려서 사라져버렸던 것이다.
어쨌든 Persistent로 콜백 저장 문제는 해결했다.
두 번째 문제는, 자바스크립트에서 binary data를 받을 때는 typed array를 쓰는데,
이걸 어떻게 C++에서 생성해야 하나... 라는 고민이었는데,
다행히도 NodeJS C++ 코드에서 node::Buffer라는 클래스를 제공해준다.
이걸 쓰면 raw data를 NodeJS 단으로 쉽게 넘길 수 있다.
해결 완료.
3. 결론
hex 값 부분만 일단 떼놓고 보면, C++/NodeJS/브라우저 간 protobuf를 이용한 통신을 구축 완료하였다.
적절한 자동화와 prebuild/postscript를 거치면 당신도 이제 C++과 Javascrip를 이용한 서버/클라이언트 환경을 구축할 수 있다.
도전해보세요!
사실 다른 거 다 필요없고 자바스크립트 변수(특히 콜백 함수)를 C++ 측에 저장할 때는
Local이 아니라 Persistent를 써야한다는 것만 기억하면 된다... 제길.
람다는 C++11에 새로 등장한 문법이다.
기존에 클래스를 이용해서 만들어 쓰던 함수 객체(Functor)를 문법에 추가한 것이다.
int a = 3; int b = 4; auto test = [&a, b] (int c) -> int { a = a + b + c; return c; } std::cout<<test(3)<<std::endl; std::cout<<a<<std::endl;
출력
3 10
문법
[] () {}
세 쌍의 괄호들로 이루어진다.
1. []
변수를 캡쳐하는 부분이다.
람다가 정의되는 부분에서 접근 가능한 변수들을 저장해놓는 역할을 한다.
람다는 std::function이나 템플릿 유추 등을 통해 함수 포인터로써 기능하는 경우가 많다.
[]을 통해서 변수를 캡쳐하게 되면, 캡쳐하는 순간의 그 변수의 정보를 람다 함수가 들고 있게 된다.
캡쳐를 한다는 것은, 람다 객체의 멤버 변수로 넣겠다는 말과 같다.
위에서 적었다시피, 람다는 Functor를 문법으로 만든 것이고,
원래 Functor는 클래스로 만들었다.
Functor를 쓸 때 외부 변수가 필요할 경우, 멤버 변수에 값을 넣어둔 다음에
그 멤버 변수의 값을 사용했다.
그 부분이 람다에서는 캡쳐이다.
외부의 변수를 람다 내부에서 사용할 수 있도록 하는 것이다.
캡쳐에는 2종류가 있다.
값을 캡쳐하는 것과 주소를 캡쳐하는 것.
int a = 3;
이런 변수가 있을 때,
[a] - a의 값을 캡쳐한다.
[&a] a의 주소를 캡쳐한다.
a의 값을 캡쳐하는 경우,
a는 const 속성이 붙게 된다.
값을 변경할 수 없게 되는 것이다.
뒤에 적을 mutable 키워드를 붙이면 값의 변경은 가능하지만,
람다 안에서 a의 값을 바꾸더라도
람다 밖의 원본 a의 값은 전혀 변하지 않는다.
하지만 람다 안에서의 a는 바뀐다.
위에서 말했다시피, 람다에서 캡쳐는 멤버 변수의 역할을 한다.
외부 변수의 값을 가져온 다음 아무리 바꿔봤자 외부 변수는 바뀌지 않는 것과 같다.
int a = 3; auto lambda = [a]() mutable { ++a; std::cout<<a<<std::endl; } lambda(); lambda();
이 코드를 실행하면,
4 5
이렇게 출력이 된다.
a의 주소를 캡쳐하는 경우,
람다 안에서 a를 사용하는 것은 캡쳐된 변수 a의 레퍼런스를 사용하는 것이 된다.
이 때 주의해야 할 것은,
레퍼런스로 캡쳐할 경우, 람다가 실제로 수행될 때 그 원본 변수가 제대로 살아있는지 여부를 확인해야 한다.
Dangling pointer를 주의해야 하는 것이다.
예를 들어, 어떤 함수 안에서 선언된 변수를 레퍼런스로 캡쳐한 후,
그 함수를 빠져나간 다음에 람다가 실행되게 되면
람다는 잘못된 메모리에 접근하는 것이 된다.
캡쳐할 때, 기본 캡쳐 방식을 지정할 수 있다.
[=] 이렇게 쓰게 되면, 모든 외부 변수를 값으로 캡쳐하고,
[&] 이렇게 쓰게 되면, 모든 외부 변수를 주소로 캡쳐하게 된다.
기본 캡쳐 방식을 지정한 후에, 기본 캡쳐 방식과 다른 방식으로 캡쳐하고 싶은 변수들을 따로 캡쳐할 수 있다.
[=, &a, &b, &c] 이런 식이나,
[&, a, b, c] 이런 식으로.
기본 캡쳐 방식과 같은 방식의 추가 캡쳐는 못 한다.( [=, a] , [&, &b])
특수한 상황이 한 가지 있다.
클래스 안에서 선언된 람다의 경우,
멤버 변수는 캡쳐할 수 없다.
대신 this 포인터를 값으로 캡쳐해서 사용할 수 있다.
this는 주소로 캡쳐할 수 없다.
당연하지만, 아무것도 캡쳐하고 싶지 않을 경우
그냥 []를 쓰면 된다.
2. ()
일반적인 함수의 인자를 받는 것과 똑같다.
std::function<void(int)> print = [](int a) { std::cout<<a; }); print(4);
이러면 4를 출력한다.
<algorithm> 헤더에 있는 함수들 중
인자로 함수 포인터 또는 Functor를 받는 함수가 있다.
std::for_each 가 대표적인데,
첫 번째 인자와 두 번째 인자로 자료구조의 시작과 끝을 받고,
세 번째 인자로 함수 포인터나 Functor를 받는데,
그 함수의 인자는 첫 번째와 두 번째로 받은 자료구조의 자료형이어야 한다.
std::vector<int> container; std::for_each(container.begin(), container.end(), [](int value) { std::cout<<value; }
3. {}
일반적인 함수에서의 역할과 같다.
람다 함수의 본문을 넣는 곳이다.
4. 리턴 타입
람다도 함수이니만큼, 리턴을 할 수 있다.
리턴은 두 가지 방식으로 한다.
1) 암시적 리턴
람다 본문 내부에서 return 키워드가 한 개만 쓰일 경우,
람다의 리턴 타입은 리턴하는 값/변수의 타입이 된다.
int 변수를 리턴할 경우 리턴 타입은 int이고,
Widget* 변수를 리턴할 경우 Widget*,
true를 리턴할 경우 bool이 되는 식이다.
2) 명시적 리턴
[] () -> 리턴 타입 { 함수본문 }
이런 식으로 리턴 타입을 명시적으로 나타낼 수 있다.
[] () -> int { return 3.0f; }이렇게 할 경우, 일반적인 함수에서와 같이
3.0f가 int로 형변환 되서 리턴이 된다.
리턴 문이 2개 이상일 경우,
그 어떤 경우에도 암시적 리턴을 쓸 수 없다.
반드시 명시적 리턴을 써야 한다.
if(조건) return false; else return true;
이런 식으로 모든 리턴문의 리턴 타입을 같게 해주었더라도,
명시적 리턴을 사용해야 한다.
5. 키워드
함수에서 () 다음에 const, override 같은 키워드를 붙이듯이,
람다에서도 () 다음에 키워드를 붙일 수 있다.
mutable, exception, attribute 이렇게 세 개의 키워드를 쓸 수 있다.
mutable
값으로 캡쳐한 변수의 경우, 기본적으로 const로 취급이 된다.
mutable을 붙일 경우, const로 취급하지 않는다.
exception과 attribute는 각각 C++의 예외 처리 문법, 그리고 attribute 키워드에 대응한다.
이 쪽은 잘 모르는 데다가, C++ 기본 문법과 똑같은 역할을 한다고 하니 패스...
NodeJS C++ addon 바이너리 데이터 넘기기 삽질기 (0) | 2014.07.08 |
---|
3D 게임이라면, 모델링과 텍스쳐를 사용할 것이다.
이건 당연한 건데...
요지는, 모델링과 텍스쳐를 불러와서 보여줄 때
어떻게 하면 효율적으로 할 수 있는가 이다.
1. 미리 불러오기
기본적으로, 그래픽 데이터들은
'로딩' 시점에 불러오는 방식이 제일 많이 쓰인다.
어떤 물체에 대해서 모델링과 텍스쳐 정보가 필요한 시점에서
그 데이터를 메모리에 올리기 시작한다면,
올린 시점~실제로 다 올라간 시점 사이에서는
물체는 보이지 않을 것이다.
물론 올리는 시간이 1프레임 이내로 끝난다면 상관없겠지만,
그건 현재 컴퓨터의 사양으로는 불가능하다.
그렇기 때문에, 어떤 모델링 또는 텍스쳐 정보가 필요할 거 같다 싶은 지점이 오기 전에
로딩 화면이 있고, 그 로딩화면에서 데이터를 메모리에 올리는 방식을 사용하는 게 일반적이다.
게임에 따라 다르지만
맵 이동이 있는 게임은 맵 사이사이에서 로드할 것이고,
스테이지 단위로 되어있는 게임은 스테이지 시작할 때 로드할 것이고,
심리스 맵으로 되어 있는 구조고, 맵이 매우 크다면,
전체 맵을 적절하게 나눠서,
다음 구역으로 넘어가기 전에 해당 구역의 정보를 불러올 것이다.
적당한 시점을 선택해서,
그 시점 이후로 필요한 데이터를 불러오면 된다.
2. 실시간
온라인 3D MMORPG에서 다른 사람 캐릭터가 주변에 지나갈 때,
그 캐릭터의 모델 & 텍스쳐 정보를 불러와야 한다.
그런데 위에 써놨듯이, 옆에 지나가는 캐릭터를
그 순간 로딩해서 보여주는 건 불가능하다.
따라서, 일정 거리에 들어왔을 때 불러오기 시작하는 방법이 많이 쓰인다.
또는, 마비노기 영웅전에서 사용하는 후드 같은
적은 폴리곤 수/적은 메모리를 먹는 텍스쳐를 보여준 후,
실제 장비/외모 정보를 불러오기 시작하는 방법도 있다.
(마영전은 MMORPG는 아니지만...)
1. Bounding Volume
어떤 물체가 있으면, 그 물체를 완전히 포함하는
단위 부피로 감싼다(보통 구 또는 큐브를 사용한다고 한다).
그리고 주어진 알고리즘에 따라서
인근해 있는 두 개 이상의 부피를 완전히 포함하는
또다른 단위 부피로 감싼다.
(부피 안에 있는 물체를 포함하는 게 아니라
그 물체를 포함하는 부피 그 자체를 완전히 포함하는 것이다)
하위 두 개의 부피를 자식으로 하고,
두 부피를 감싸는 큰 부피를 부모로 하는
트리를 만든다.
이런 식으로 계속 부피들을 더 큰 부피로 감싸다 보면
최종적으로 한 개의 부피가 만들어질 것이고,
그 부피는 트리의 root일 것이다.
(알고리즘에 따라 다르다. 꼭 최종 한 개가 아닐수도 있다)
이 때, 실제 물체를 가지고 있는 부피는
잎사귀 노드들 밖에 없다.
(이 역시 알고리즘에 따라 다르지만,
트리 구성에 따른 유용한 공식들을 사용하려면 이 방법이 유리하다)
Fine collision detection을 수행할 때는, 트리의 꼭대기에서부터
아래로 내려온다.
자식 노드들 간에
단위 부피 형태에 따른 충돌 체크를 한다.
(단위 부피를 구나 큐브로 하는 이유가 여기에 있다.
최대한 트리 내에서의 충돌처리 비용을 줄이기 위해서)
만약 충돌을 하지 않는다면
그 노드들의 자식들 역시 절대로 충돌할 일이 없다는 뜻이 된다.
즉, 그 노드들의 자식들끼리는 절대 충돌체크를 할 일이 없다.
반대로 충돌을 한다면,
그 자식들 역시 충돌할 가능성이 있다는 뜻이다.
따라서, 충돌한 노드이 있으면
그 자식들끼리도 충돌체크를 한다.
마찬가지로, 충돌을 하지 않으면 앞으로 볼 일 없는 거고,
충돌을 하면 그 자식들끼리 또 체크를 한다(으아아아아아).
-Coarse Collision Detection 끝-
Array, Object가 하나씩 있고,
각각에 대해 원소들을 순서대로 접근하고 싶다면,
Array는 그냥 for문에다가 조건을 Array.length로 잡고,
Object는 Enhanced for문을 쓰면 된다.
Array에서 Enhanced for문을 쓰면 Array 클래스에 내재된 함수까지 모조리 Enhanced에 걸린다. 그래서 결과가 이상하게 나오게 된다(isArray, copy, size 등등. push, pop 같은 건 Array 객체에만 있는 거라서 나오지 않는다).
반대로, Object에서 Object.length를 쓰게 되면 length가 undefined로 나온다. 당연한 것이, Object는 배열이 아니기 때문에 원소의 개수를 셀 수 없다. 해쉬된 원소들을 셀 수 없냐고 하면 글쎄.... 셀 수는 있을 거 같지만 위에서처럼 멤버 함수까지 모조리 세어지기 때문에 안 하지 않았을까 싶다.
실수하면 디버깅이 안 되는 자바스크립트 실수 (0) | 2011.12.18 |
---|
일단 이 물리엔진을 만들기 시작한 이유는
웜즈를 만들기 위해서이죠.
그래서 기본적인 물리엔진 기능 + 픽셀 충돌 처리가 가능한
물리 엔진을 목표로 하고 있습니다.
하지만 일단은 웜즈를 구현할 수 있는 정도로 만족하기로 했습니다.
회전이 너무 어려워서.... 허허.
그래서 일단은 사각형 + 픽셀 + 원에 대한 것만 처리하고
무회전으로 구현하기로 했습니다.
1. Coarse Collision Detection (0) | 2012.07.30 |
---|
CSS에서 danlging div (2) | 2011.07.11 |
---|