728x90
var http = require("http");

http
.createServer(function(request, response) {
  response
.writeHead(200, {"Content-Type": "text/plain"});
  response
.write("Hello World");
  response
.end();
}).listen(8888);

 

이게 기본 틀의 예로 볼수 있을듯..

 

http 서버를 만든거다.

require로 http 모듈을 읽어들이고 그 이후엔 http라는 변수를 통해서 접근을 할수 있다.

 

http 모듈에서 제공하는 createServer을 호출한다.

listen 함수는 http 서버에서 요청대기할 포트 번호를 나타내는 숫자를 받는다.

 

createServer의 함수의 파라미터를 함수로 넣고 있는데 자바스크립트에선 함수도 파라미터로 넘길수가 있다.

 

함수 안의 파라미터 두개 request와 response는 일반적인 웹 에서 사용하는 그 request와, response로 보면 될듯 하고

 

요청이 들어오면 response.writeHead() 함수를 이용해서 http 200, 너의 요청은 뭐 성공적이다 라는 응답과, content-type 은 text/plain 뭐 일반적인 평문 으로 설정해서 응답 헤더로 보내고

 

여기다 hello world 텍스트를 응답 바디로 보내는거고  end() 함수로 마무리를 하는 형태이다.

 

var http = require("http");

function start() {
 
function onRequest(request, response) {
    console
.log("Request received.");
    response
.writeHead(200, {"Content-Type": "text/plain"});
    response
.write("Hello World");
    response
.end();
 
}

  http
.createServer(onRequest).listen(8888);
  console
.log("Server has started.");
}

exports
.start = start;

 

이번엔 우리가 직접 모듈을 만들어 보는거다.

모듈을 만드는건 그냥 export 하면 된다.. 간단하군 크흠...

 

위에 코드를 보면뭐 주저리 주저리 응답 하는 함수를 start 라는 이름의 함수안에 넣고

아랫줄에 exports.start = start 함수를 연결해 export 해줌..

 

이 파일을 server.js 라는 이름으로 저장하고 호출 할땐

 

var server = require("./server");

server
.start();

 

요롷게 .. 우리가만든 모듈 불러오고

걍 start() .. 호우 간단하군.

 

이번엔 라우팅 .. 좀더 요청에 따른 다양한 반응을 하게 하려면 라우팅이 필요하다.

 

우리가 뭐 웹으로 요청을 보낼때 요청 url이랑, get/post 파라미터를 보통 보내는데.

router는 이것을 전달받으면 어떤 코드를 실행할지 결정을 한다. 즉 router는 요청을 받았을때 실제 일을 하는 request handler이다.

 

var http = require("http");
var url = require("url");

function start() {
 
function onRequest(request, response) {
   
var pathname = url.parse(request.url).pathname;
    console
.log("Request for " + pathname + " received.");
    response
.writeHead(200, {"Content-Type": "text/plain"});
    response
.write("Hello World");
    response
.end();
 
}

  http
.createServer(onRequest).listen(8888);
  console
.log("Server has started.");
}

exports
.start = start;

 

url 모듈은 url의 각각의 부분을 뽑아낼수 있는 메소드를 제공한다.

request 파라미터로 넘어온 url을 파싱해서 위 코드처럼 접근할수 있다. 이건 일단 server.js 파일.

 

function route(pathname) {
  console
.log("About to route a request for " + pathname);
}

exports
.route = route;

 

route라는 함수를 정의한 router.js 파일. 테스트 코드이므로 pathname으로 넘어오는 파라미터를 출력함.

 

 

var http = require("http");
var url = require("url");

function start(route) {
 
function onRequest(request, response) {
   
var pathname = url.parse(request.url).pathname;
    console
.log("Request for " + pathname + " received.");

 

    route(pathname);
 
    response
.writeHead(200, {"Content-Type": "text/plain"});
    response
.write("Hello World");
    response
.end();
 
}

  http
.createServer(onRequest).listen(8888);
  console
.log("Server has started.");
}

exports
.start = start;

 

http server가 route와 연결하기 위해, start함수에 route를 파라미터로 받는다.

 

var server = require("./server");
var router = require("./router");

server
.start(router.route);

 

index.js 파일이다.. 음.. 보통 어떤 웹을 공부하든 메인이 되는 파일의 이름은 index 인듯.

 

본론으로와서. server와, router 모듈을 가져오고

router 함수를 server의 start함수로 파라미터로 보내서 시작한다.

 

이제 node.js 실행해보면 뭐 .. http server에서 route 사용해서 pathname 넘기는 그런 환경이 구축된거임~ 음 대충 알겟스.

 

이제는 좀더 확장된 request handler라는 개념을 이용해서 라우팅을 해보기.

 

function start() {
  console
.log("Request handler 'start' was called.");
}

function upload() {
  console
.log("Request handler 'upload' was called.");
}

exports
.start = start;
exports
.upload = upload;

 

start 할때는 start() 함수, upload 할때는 upload() 함수.. 다양한 request handler가 들어 있다고 가정하는 requesthandler.js 파일.

 

var server = require("./server");
var router = require("./router");
var requestHandlers = require("./requestHandlers");

var handle = {}
handle
["/"] = requestHandlers.start;
handle
["/start"] = requestHandlers.start;
handle
["/upload"] = requestHandlers.upload;

server
.start(router.route, handle);

 

메인 파일인 index.js 파일이다.

보면 키/값 쌍으로.. / = requestHandlers.start , /upload = requestHandlers.upload 뭐 이렇게 매핑 시켜주고 server에 파라미터로 route 함수와, handle 을 넘겨주고 있다.

 

var http = require("http");
var url = require("url");

function start(route, handle) {
 
function onRequest(request, response) {
   
var pathname = url.parse(request.url).pathname;
    console
.log("Request for " + pathname + " received.");

    route
(handle, pathname);

    response
.writeHead(200, {"Content-Type": "text/plain"});
    response
.write("Hello World");
    response
.end();
 
}

  http
.createServer(onRequest).listen(8888);
  console
.log("Server has started.");
}

exports
.start = start;

 

server.js 파일.. start() 함수에서 handle을 받는 파라미터가 추가 되있다.

뭐 봐야할 부분은 route()함수를 호출할때 handle을 파라미터로 추가해서 넘겨준다는거다

 

function route(handle, pathname) {
  console
.log("About to route a request for " + pathname);
 
if (typeof handle[pathname] === 'function') {
    handle
[pathname]();
 
} else {
    console
.log("No request handler found for " + pathname);
 
}
}

exports
.route = route;

 

router.js 파일..  pathname에 해당하는 request handler가 있는지를 체크하고. 존재하면 해당 함수를 호출한다. 크흠.. 이것도 대충 알겟스.

 

깨알 추가 팁..은.. 위에 보면 비교 연산자에 === ? 3개다 우리가 보통 보는건 == 이거인데 말이다.

자바스크립트에선 ==, === 이 두개가 개별적으로 있는데 ==는 좀 더.. 느슨하게 비교 한다 하면 될려나 타입에 상관이 뭐 그냥 그 값이 같으면 참인거다.. 문자 0 과 숫자 0을 비교하면 참이 나옴.. 뭐 이런거?

 

===는 타입이랑 값이 다 똑같아야 참이 나오는거임.. 문자 0이랑 숫자 0 비교하면 거짓 임.. 대충 ㅇㅋ..?

 

이번엔 node.js의 비동기 방식에 대해서 좀더 알아보기.

 

function start() {
  console
.log("Request handler 'start' was called.");

 
function sleep(milliSeconds) {
   
var startTime = new Date().getTime();
   
while (new Date().getTime() < startTime + milliSeconds);
 
}

  sleep
(10000);
 
return "Hello Start";
}

function upload() {
  console
.log("Request handler 'upload' was called.");
 
return "Hello Upload";
}

exports
.start = start;
exports
.upload = upload;

 

위에 코드는 비동기가 아니라 동기라고 봐야댄다.. blocking

sleep 함수의 처리때문에 10초 후에 밑의 return 문이 실행된다.

 

여기서 클라이언트에서 start와, upload 요청 두개가 동시에 들어왔다면 upload 를 로드 하는것도 10초가 걸려버린다 왜냐 start() 함수에서 sleep 때문에 blocking 해버려서 다른 곳에서 일을 못하게 막아버리니 말이다. 우리가 원하는건 이런게 아니지 않겟니? 요청이오면 그에 따른 즉각적인 반응

 

node.js는 동시작업을 할수 있다. 하지만 쓰레드를 여러개 사용하는것이 아닌 단일 쓰레드 이고 .

event를 통해서 실행하므로 다양한 작업이 동시에 되게 하려면 non-blocking 동작을 사용해야 한다.

 

var exec = require("child_process").exec;

function start() {
  console
.log("Request handler 'start' was called.");
 
var content = "empty";

  exec
("ls -lah", function (error, stdout, stderr) {
    content
= stdout;
 
});

 
return content;
}

function upload() {
  console
.log("Request handler 'upload' was called.");
 
return "Hello Upload";
}

exports
.start = start;
exports
.upload = upload;

 

requestHandler.js 파일.. exec 함수는 비동기 동작을 한다. 뭐 주저리 주저리 함수 실행하고 얻어온 결과값 stdout을 content에 값으로 채우고 return 한다.

 

그럼 값이 재대로 나오느냐 .. 결론은 아니란다. empty 문자가 그대로 출력된단다 왜 ?

 

exec 함수를 호출하자마자 코드가 동기적으로 동작해서 node.js는 바로 return content를 실행해버린거다 exec()의 일이 아직 다 처리 되지도 않았는데 말이다.

 

그럼 이제 한번 비동기적으로 재대로 되게 고쳐본다.

 

var http = require("http");
var url = require("url");

function start(route, handle) {
 
function onRequest(request, response) {
   
var pathname = url.parse(request.url).pathname;
    console
.log("Request for " + pathname + " received.");

    route
(handle, pathname, response);
 
}

  http
.createServer(onRequest).listen(8888);
  console
.log("Server has started.");
}

exports
.start = start;

 

server.js 파일... route 함수 안에 파라미터로 넘겨주는 값이 추가 됬다. 바로 response 객체를 넘겨주는거다. 이제는 각각의 request handler들이 이 response 객체를 이용해서 응답을 해주는거다!

 

function route(handle, pathname, response) {
  console
.log("About to route a request for " + pathname);
 
if (typeof handle[pathname] === 'function') {
    handle
[pathname](response);
 
} else {
    console
.log("No request handler found for " + pathname);
    response
.writeHead(404, {"Content-Type": "text/plain"});
    response
.write("404 Not found");
    response
.end();
 
}
}

exports
.route = route;

router.js 파일...  해당하는 request handler을 찾지 못하면 직접 응답을 해주고 그게 아니라면 handler 쪽으로 response를 넘겨줌과 동시에 호출한다.

var exec = require("child_process").exec;

function start(response) {
  console
.log("Request handler 'start' was called.");

  exec
("ls -lah", function (error, stdout, stderr) {
    response
.writeHead(200, {"Content-Type": "text/plain"});
    response
.write(stdout);
    response
.end();
 
});
}

function upload(response) {
  console
.log("Request handler 'upload' was called.");
  response
.writeHead(200, {"Content-Type": "text/plain"});
  response
.write("Hello Upload");
  response
.end();
}

exports
.start = start;
exports
.upload = upload;

 

requestHandler.js 파일... handler 함수들이 respone을 파라미터로 받고 요청에 따른 응답을 각각 하고 있다.  이렇게 하고 작동해보면 이제 잘 반응 한다.

 

아까처럼 중간에 sleep이 잇다고 해도 upload 요청을 해도 바로바로 반응이 된다! 와후

 

좋았스 일단 기초는 요정도로 알고 가보자.

728x90
Posted by 정망스
,
728x90

 

출처 : http://kimseunghyun76.tistory.com/194

검색중 잘 정리 되어 있는 블로그가 있어서 출처를 남기고 제 블로그로 옴겼습니다.


1. MonoBehaviour 
  모든 스크립트가 상속받는 기본 클래스입니다.
 (Javascript
는 무조건 MonoBehaviour 를 상속받고 C#, Boo 의 경우 명시적으로 상속받아야 합니다.
  C#, Boo
에서 단순 데이터 보관용 클래스, 전역으로 동작하는 매니저 클래스같은 건 상속받지 않고 쓸 수 있습니다.)
  MonoBehaviour
Behaviour 클래스를 상속받고 Behaviour Component 를 상속받습니다.
 
MonoBehaviour 를 상속받은 클래스는 게임 오브젝트에 component 로 붙일 수 있다는 뜻입니다.(붙일 수 있다는 건 모두 알고 계시죠? ㅎㅎ)
Behaviour
클래스는 enable/disable 가능합니다.
때문에 MonoBehaviour 도 역시 켜고 끌 수 있습니다.
(
스크립트를 Inspector 에 붙이면 앞에 체크박스가 나오죠? 그겁니다.)
레퍼런스를 보면 MonoBehaviour,  Behaviour, script 라는 명칭을 혼재해서 쓰는데 혼란을 줄 수 있으니, 앞으로 모두 '스크립트'로 통칭하도록 하겠습니다.

2.
앞에 On 이 붙지 않는 함수

 1) Update

  Update
함수는 스크립트가 켜져 있을 때(enabled 상태일 때) 매 프레임마다 호출됩니다.
  Update
함수는 스크립트에서 가장 빈번하게 사용되는 함수입니다.
 
지나간 시간을 알고 싶으면, Time.deltaTime 을 사용하면 됩니다.
 
이 함수는 스크립트가 켜져 있을 때만 불립니다.

 2) LateUpdate

   LateUpdate
함수는 스크립트가 켜져 있을 때 매 프레임마다 호출됩니다.
   LateUpdate
함수는 모든 Update 함수가 호출된 후 호출됩니다.
  
이것은 스크립트의 실행 순서를 정하는 것에 도움이 됩니다.
  
예를 들어 따라다니는 카메라는 언제나 LateUpdate 를 구현해야 하는데, 그 이유는 이 카메라가 따라가는 오브젝트들은
   Update
함수 안에서 움직일 가능성이 있기 때문입니다. 이 함수는 스크립트가 켜져 있을 때만 불립니다.

 3) FixedUpdate

   FixedUpdate
함수는 스크립트가 켜져 있을 때 매 프레임마다 호출됩니다.
   FixedUpdate
함수는 Rigidbody 를 다룰 때 Update 대신에 사용됩니다.
  
예를 들어 rigidbody에 일정한 힘을 가할 때, FixedUpdate를 구현하여 매 fixed frame 마다 힘을 가해주어야 합니다.
  
FixedUpdate 는 매 프레임마다 호출되지만 한 프레임에 여러번 호출될 수도 있습니다. ??
  

* FixedUpdate 는 매 프레임마다 호출됩니다. 그런데 한 프레임에 여러번 호출될 수도 있습니다. 사실 이거 거짓말입니다.
  
그냥 알기 쉽게 하려고 이렇게 적어넣은 것이고... 정확히 하면 'FixedUpdate 1초에 50번 매 0.02초마다 호출됩니다
.
  
그러니까 실제 렌더링 프레임 사이에 여러번 호출될 수도 있습니다
.
   Update
는 실제 렌더링 프레임 기반으로 동작하지만 FixedUpdate 는 고정 프레임(아마 50fps)으로 다른 쓰레드에서

  
동작한다고 생각하시면 됩니다
.

  
이렇게 나뉘어져 있는 이유는 주로 '물리 연산 중의 충돌 체크 및 정확한 움직임 처리의 근사' 때문입니다
.
  
물체는 곡선운동도 하고 회전운동도 하므로 그 궤적이 항상 직사각형이나 실린더 모양이라고 생각할 수 없습니다
.
  
물리 공식에 의해 곡선으로 움직이는 궤적도 계산해 낼 수 있고, 궤적 사이에 충돌 체크를 할 수도 있겠지만 여기에는

  
막대한 CPU 자원이 들어갈 것입니다. (사실 3차원 곡면 사이의 충돌 검출이라.... 생각하는 것만으로도 머리 아퍼
)
  
그래서 대체로 물리 엔진은 시간을 아주 짧게 잘라서 물체를 이동시키고 충돌 체킹을 하게 됩니다
.

   3D
에서 평면 폴리곤으로 곡면을 표현하는 걸 생각하시면 될 것 같네요
.
  
잘게 자르면 자를 수록 점점 원하는 모양에 근사시킬 수 있죠
?
 
, 전체적인 모습을 보면 곡선의 움직임이지만 자세히 들여다 보면 직선 움직임의 덩어리라는 것이죠
.
  
계산상으로 직선을 처리하는 것 (1차 방정식) 과 곡선 (2차 이상의 방정식 or 심하면 음함수 그래프 같은 움직임까지)

 
처리하는 것은 넘사벽의 차이가 있습니다
.
 
어쨌든 계산을 빠르고 편하게, 하지만 나름 정확하게 하기 위해 이런 방식을 씁니다
.
  (
제가 예전에 담당하고 있던 라이브 게임에도 이펙트 코드에 가끔씩 이전 프레임과의 시간 차이를 계산한 후에

 
더 자잘하게 잘라서 실제 처리하는 함수를 여러번 호출하는 루틴도 있었습니다
.)
 
  
참고로 테스트 해 보니 아무런 조작도 없을 때 FixedUpdate 실행 주기는 0.02 초 정도인 듯 합니다
.
   (
위에서 50fps 라고 적은 이유
)
  
  
사실 스크립트 짜는 데 아무런 도움도 안될 것 같은 느낌이 드는데 그냥 '이런 저런 사정 때문에 이런 함수가 있고
,
  
이렇게 동작한다.' 정도만 아시면 될 것 같습니다.


   

 // 매 프레임마다 rigid body 에 위로 향하는 힘을 가해준다.
 //
즉 이 예는 등가속 운동입니다. (Vector3.down 하면 중력을 받는 것과 동일하다는 뜻입니다
.)
function FixedUpdate()
 {
     rigidbody.AddForce(Vector3.up);
 }

 

4) Awake

  Awake
함수는 스크립트 객체가 로딩될 때 호출됩니다.
  Awake
함수는 게임이 시작하기 전에 변수나 게임 상태를 초기화하기 위해 사용합니다.
  Awake
함수는 스크립트 객체의 라이프타임 동안 단 한번만 호출됩니다.
 
Awake 함수는 모든 오브젝트가 초기화된 후 호출되기 때문에, 다른 오브젝트에 메시지를 날리거나 GameObject.FindWithTag 같은 함수를 안전하게 사용할 수 있습니다.
이런 이유로 Awake 함수에서 스크립트를 레퍼런싱한 후, Start 함수에서 필요한 정보를 넘겨받거나 넘겨줄 수 있습니다.
Awake
함수는 언제나 Start 함수 전에 호출됩니다. 이것은 스크립트의 초기화 순서를 정할 수 있게 합니다.
Awake
함수는 coroutine 으로 동작할 수 없습니다.

 5) Start

  Start
함수는 Update 함수가 처음 호출될 때 Update 함수 직전에 호출됩니다.
  Start
함수는 스크립트가 동작하는 라이프타임 동안 단 한번만 호출됩니다.
  Awake
함수와의 차이는 Start 함수는 스크립트가 켜져있을 때만 호출된다는 것입니다.
  
이것은 정말로 필요할 때까지 초기화 코드 실행을 연기시킬 수 있습니다.
  Awake
함수는 언제나 Start 함수가 호출되기 전에 호출됩니다. 이것은 스크립트의 초기화 순서를 정할 수 있게 합니다.
  Start
함수는 모든 스크립트 객체의 Awake 함수가 호출된 후에 호출됩니다.

 6) Reset

 
기본값으로 리셋합니다.
  Reset
함수는 유저가 Inspector context menu 에서 Reset 버튼을 눌렀을 때나, 게임 오브젝트에 스크립트를 처음 붙였을 때 호출됩니다. 이 함수는 에디터 모드에서만 호출됩니다.
Reset
Inspector에 초기 값을 설정할 때 가장 자주 사용하는 함수입니다.

 
 7 ) Awake, Start, Update, LateUpdate
순서도

'A,  B, C 라는 게임 오브젝트가 있고, A, B 에 스크립트가 하나씩 붙어있습니다. B는 스크립트가 비활성화 되어 있습니다.'
 
라는 상황을 가정하겠습니다.

 1. 게임이 로딩되면 우선 A, B, C 모든 게임 오브젝트가 초기화 됩니다.
 
 2.
이후 A, B 에 붙어있는 스크립트의 Awake 함수가 호출됩니다.
   (
이 상황에서도 이미 A, B, C 게임 오브젝트와 구성 컴포넌트는 모두 메모리에 들어있는 상태이므로 null 체크
  
이런 거 없이 안심하고 데이터 전달 등을 할 수 있습니다.)

 3.
이후 A Update 함수가 호출되려고 합니다. B 는 스크립트가 비활성화 상태이기 때문에 동작하지 않습니다.

 4. A
Update 함수가 호출되려고 하는데, 이번이 첫번째 호출이네요! 우선 Start 가 호출됩니다.

 5. A
Start 가 호출되었으니 Update 가 호출됩니다. 앞으로 매 프레임마다 호출되겠네요.

 6. A
LateUpdate 도 호출됩니다. 역시 앞으로 매 프레임마다 호출됩니다.

 - 여기서 B의 스크립트를 활성화시켰습니다.

 7. B Update 함수도 호출되기 시작합니다. 제일 처음 Update 호출될 때 역시 Start 가 우선 한 번 호출됩니다.

 8. A, B
Update 함수가 모두 호출된 후 A, B LateUpdate 가 호출됩니다.

 - 여기서 C에 스크립트 컴포넌트를 붙였습니다.

 9. C 에 스크립트가 붙자 C Awake 가 호출됩니다.

 10. A, B, C
Update 차례. C의 경우 처음 Update 호출이라서 그전에 Start 함수가 우선 호출됩니다.

 11. A, B, C
LateUpdate 차례. A, B, C 의 모든 Update가 끝나면 호출되기 시작합니다.

 

 


3. On~
계열 함수

 1) OnMouse~ 함수군

 
마우스와 GUIElement, Collider 사이의 인터랙션에 관련한 함수 집합입니다.
  
게임 오브젝트가 Ignore Raycast 레이어에 속해있으면 호출되지 않습니다. (내부적으로 Raycast 를 하는 듯.)
  
이 함수들은 co-routine 으로 사용할 수 있습니다. (yield 사용 가능.)
  이 이벤트는 GUIElement, Collider 에 붙어있는 모든 스크립트에 전달됩니다.

  OnMouseEnter - 마우스가 처음 오브젝트 위로 올라왔을 때 호출.
  OnMouseOver -
마우스가 오브젝트 위에 있을 경우 매 프레임마다 호출.
  OnMouseExit -
마우스가 처음 오브젝트 밖으로 나갔을 때 호출.
  OnMouseDown -
오브젝트 위에서 마우스 버튼을 눌렀을 때 호출.
  OnMouseUp -
오브젝트 위에서 마우스 버튼을 땠을 때 호출. 눌렀을 때의 오브젝트와 같은 오브젝트일 때만 호출됨.
  OnMouseDrag -
오브젝트 위에서 마우스 버튼을 누른 상태로 있을 때 매 프레임마다 호출.

  여기서 Drag 는 일반적으로 생각하는 드래그가 아니라 그냥 꾸욱 누르고 있는 상태를 나타냅니다.
 (
물론 그 상태로 마우스를 움직이면 드래그지만..)
 
그리고 오브젝트 위에 마우스를 올려놓고 누르고 있으면 Over Drag 가 매 프레임마다 호출됩니다.
  Drag
호출된다고 Over 호출 안된다거나 하는 거 없습니다. **

  스크립트가 enable / disable 과 상관없이 호출됩니다.
 
Inspector 에서 체크박스를 해제해도 스크립트가 붙어있다면 무조건 호출됩니다.
 
앞으로 '스크립트가 켜져있을 때만 호출된다.' 는 말이 없으면 기본적으로 비활성화 상태에서도 호출된다고 생각하세요.

 2) OnTrigger~(other : Collider), OnCollision~(collisionInfo : Collision)
함수

  OnTrigger~, OnCollision~
은 모두 충돌 관련 함수입니다.
 
충돌이 일어나려면 두 오브젝트 모두 Collider 를 가져야 하고 둘 중 하나는 Rigidbody 를 가져야 합니다.
 
그리고 Rigidbody 를 가진 쪽이 움직여서 서로 만날 경우만 이벤트가 일어납니다. 물론 둘 다 움직이고 있어도 됩니다.
  (그러니까 Rigidbody 를 가진 녀석은 가만히 있는데 그냥 Collider 가 아무리 와서 들이박아도 아무런 일도 생기지 않는다는 겁니다. ==> 중요한것입니다.)

  Trigger Inspector 창에서 Collider Is Trigger 속성이 켜져있을 때 발생합니다.
  Trigger
가 켜져있을 때는 Collision 관련 함수는 호출되지 않습니다.
  Trigger
가 켜져있을 때는 두 오브젝트 사이에 물리 계산이 이루어지지 않습니다.
  
그래서 Trigger 는 단순한 '영역' 으로 이해하는 것이 좋습니다.

  Collision 은 두 오브젝트 중 적어도 하나가 Inspector 창에서 Rigidbody Is Kinematic 속성이 꺼져있을 때 발생합니다.
   (Is Kinematic
이 켜져있으면 이 오브젝트는 내부 물리연산을 하지 않기 때문에 부딪쳐도 그냥 뚫고 지나갑니다.)
  두 오브젝트 모두 Kinematic 속성이 켜져있으면 어느 쪽이 움직여서 겹치더라도 물리 연산이 이루어지지 않기 때문에
 
충돌 함수가 호출되지 않습니다.

  Trigger 는 함수의 파라메터로 Collider 변수가 들어옵니다. 이것은 자신과 접촉한 오브젝트의 Collider 입니다.
  Collision
은 함수의 파라메터로 Collision 변수가 들어옵니다. 이것은 접촉에 대한 여러가지 정보를 담고 있는 클래스입니다.

  relativeVelocity -
두 오브젝트의 상대 속도입니다. 충격량이라는 느낌일까요? (읽기 전용)
  rigidbody -
자신과 접촉한 Rigidbody 입니다.
                 
만약 상대가 Rigidbody 가 없는 Collider 라면 이 값은 null 입니다. (읽기 전용)
  collider -
자신과 접촉한 Collider 입니다. (읽기 전용)
  transform -
자신과 접촉한 오브젝트의 Transform 정보입니다. (읽기 전용)
  gameObject -
자신과 접촉한 오브젝트입니다. (읽기 전용)
  contacts -
물리 엔진에서 연산한 접촉 포인트 정보입니다. ContactPoint 의 배열입니다.

두 종류 모두 ~Enter, ~Stay, ~Exit 함수를 제공합니다.

Enter
는 접촉을 시작했을 때 호출,
Stay
는 접촉 중일 때 매 프레임마다 호출,
Exit
는 접촉이 끝났을 때 호출됩니다.

두 함수군 모두 yield 사용 가능합니다.


 * Mesh Collider 관련해 추가 설명

기본 도형으로 이루어진 Collider 이외에 실제 모델같은 Mesh Collider 를 붙일 수도 있습니다. (알고 계시겠죠? )
그런데 기본적으로 Mesh Collider 는 다른 Mesh Collider 와 충돌 계산이 이루어지지 않습니다.
아마 계산이 오래 걸리기 때문에 막아놓은 것으로 보입니다. 기본 도형은 대체로 방정식 몇번 풀면 체크 끝나지만, Mesh ... 모든 폴리곤을 순회하면서 체크해야 하니까요.
그래도 하고 싶은 사람을 위해 준비된 Inspector 창의 Mesh Collider Convex 속성을 켜면 다른 Mesh Collider 와 충돌 계산을 합니다. , Convex 속성을 켜기 위해서는 Mesh Collider 의 폴리곤 개수가 255개를 넘으면 안됩니다.
이런 제한이 있습니다~ 간단한 게임이나 계산 파워가 부족한 iphone 게임을 만들 때는 굳이 Mesh Collider 쓸 필요는 없을 것 같습니다.

3) OnControllerColliderHit(hit:ControllerColliderHit)
 CharacterController Move 함수로 이동하는 도중 다른 Collider 와 충돌했을 때 호출됩니다.
 (CharacterController
가 붙어있는 gameObject Translate 로 움직여서 충돌할 때는 호출되지 않습니다
  
무조건 CharacterController Move 함수로 움직일 때만 호출됩니다.)
CharacterController
는 이전 충돌 함수 때처럼 따로 Rigidbody, Collider 가 필요없습니다.

4) OnJointBreak(breakForce:float)
게임 오브젝트에 붙어있는 조인트가 끊어질 때 호출됩니다.
조인트에 설정된 breakForce 보다 높은 힘이 가해지면 조인트는 끊어집니다.
조인트가 끊어질 때 주어진 힘이 파라메터로 들어옵니다.
조인트가 끊어지고 OnJointBreak 가 호출된 후 조인트는 자동적으로 게임 오브젝트에서 지워집니다.

5) OnParticleCollision(other:GameObject)
파티클이 Collider 와 충돌했을 때 호출됩니다.
WorldParticleCollider
와 충돌한 Collider 에 붙어있는 모든 스크립트에 호출됩니다.
Inspector
창에서 WorldParticleCollider sendCollisionMessage 속성을 켜야지 호출됩니다.
 (
, 기본적으로 WorldParticleCollider 가 붙어있어야 합니다.)
Collider
는 따로 Rigidbody 일 필요 없습니다. yield 사용 가능합니다.

6) OnBecameVisible / OnBecameInvisible
 renderer 가 어떤 카메라에 보이기 시작할 때, 보이지 않기 시작할 때 호출됩니다.

레퍼런스 설명은 위와 같은데, '어떤' 카메라라는 것은 여러대의 카메라가 있을 때 그 중 하나라도 보이기 시작하면 Visible, 모두 보이지 않을 때 Invisible 이라는 것이며, , 카메라가 있어도 비활성화 상태이거나 화면에 보이지 않을 경우 ( View Port Rect width, height 0일 때) '어떤' 카메라에 포함되지 않습니다.
오브젝트의 renderer 컴포넌트를 꺼도 마찬가지로 Invisible 입니다.

그러니까 단순히 말해서  어쨌든 화면에 보이기만 하면 Visible, 안보이면 Invisible 입니다.

renderer 에 붙어있는 모든 스크립트에 호출됩니다.
화면에 보일 때만 스크립트가 처리되도록 할 때 유용합니다.
yield
사용 가능합니다.

 // 화면에 보일 때만 스크립트 활성화.
function OnBecameVisible ()
 {
     enabled = true;
 }
 function OnBecameInvisible()
 {
     enabled = false;
 }


주의점이 있습니다. 툴에서 작업할 때 Scene View 에도 동일하게 동작합니다.
Game View
에서 안보여도 Scene View 에서 보이고 있는 상태라면 Invisible 호출이 안됩니다.

7) OnLevelWasLoaded(level:int)
새로운 레벨(scene)이 로딩되었을 때 호출됩니다.
level
파라메터는 로딩된 레벨의 인덱스를 나타냅니다.
메뉴 File - Build Settings... 에서 레벨과 인덱스를 설정할 수 있습니다.
yield
사용 가능합니다.
레퍼런스에는 적혀있지 않지만 해당 장면의 모든 스크립트에서 호출되는 것 같습니다.

8) OnEnable/OnDisable
스크립트가 켜지거나 꺼졌을 때 호출됩니다.
추가로 OnDisable 의 경우 스크립트가 붙은 게임 오브젝트가 제거될 때도 호출되므로 파괴자로 사용할 수 있습니다.
툴에서 플래이 모드 중에 스크립트를 편집할 경우, 편집이 끝난 후 스크립트가 다시 로딩되면서 OnDisable, OnEnable 이 순차적으로 호출됩니다.
참고로 툴에서 플래이 중 스크립트를 고쳤을 때 고쳐진 스크립트의 Awake, Start 는 호출되지 않습니다.
그리고 OnEnable Awake 함수 바로 다음에 호출됩니다. (켜져있을 경우)

9) OnGUI
 GUI
를 그리거나 이벤트를 처리하기 위해 호출됩니다.
이벤트 처리도 맡고있기 때문에 한 프레임에 여러번 호출될 수 있습니다. (한 이벤트에 한 번) 스크립트가 꺼져있으면 호출되지 않습니다.
OnGUI
함수 안에서 Event.current 를 사용하면 현재 처리하고 있는 이벤트 내용을 알 수 있습니다.
이 때 사용되는 Event 클래스의 내용은 다음과 같습니다.

 type - 이벤트의 타입. (http://unity3d.com/support/documentation/scriptReference/EventType.html)
 mousePosition -
마우스 위치. (Vector2)
 delta -
지난번 처리한 이벤트와 현재 마우스 위치의 차이. (Vector2)
 button -
어떤 마우스 버튼이 눌려졌는지. (int) (0:왼쪽, 1:오른쪽, 2:가운데)
 clickCount -
마우스 클릭 횟수. (int)
 character -
키보드로 입력한 문자. (char)
 commandName -
단축키로 입력된 명령. (string) ("Copy", "Cut", "Paste", "Delete"... 툴에서만 호출.)
 keyCode -
키보드로 입력한 가공되지 않은 키코드.(http://unity3d.com/support/documentation/scriptReference/KeyCode.html)
 shift -
쉬프트 눌려져 있는지.
 control -
컨트롤 눌려져 있는지.
 alt -
알트 눌려져 있는지.
 command - Command(
)/Windows(윈도우) 키 눌려져 있는지.
 capsLock - CapsLock
켜져있는지.
 numeric -
키패드 입력인지.
 functionKey -
펑션키 입력인지.
 isKey -
키보드 이벤트인지.
 isMouse -
마우스 이벤트인지.

Event 클래스의 기타 함수는 영역이 애매해서 따로 설명하지 않습니다. (http://unity3d.com/support/documentation/scriptReference/Event.html)

10)  OnApplicationPause(pause:bool)
플레이어가 정지/재개될 때 모든 스크립트에서 호출됩니다. yield 사용 가능합니다.

11) OnApplicationQuit
어플리케이션이 종료되기 직전에 모든 스크립트에서 호출됩니다.

12) OnDrawGizmos
게임 오브젝트에 기즈모를 추가합니다.
이 기즈모는 선택할 때 사용할 수 있고 언제나 그려집니다.

13) OnDrawGizmosSelected
게임 오브젝트가 선택되었을 때 기즈모를 그리고 싶을 때 구현합니다. 이 기즈모는 선택에 사용할 수 없습니다.
Gizmos
클래스는 http://unity3d.com/support/documentation/scriptReference/Gizmos.html 에서 사용법을 확인할 수 있습니다.

혹 기즈모가 뭔지 모르시는 분은..
툴의 Scene 뷰에 빛이나 카메라의 위치를 볼 수 있게 해 주는 아이콘이 기즈모입니다.
눈에 보이지 않지만 위치 설정이 필요할 때, 중요한 오브젝트를 보기 좋게 표현하기 위해.. 기타 여러가지 이유로 사용할 수 있습니다. 실제 어플리케이션에는 표시되지 않지만 툴로 작업할 때 여러모로 편하게 해 줍니다.
공동 작업할 때 자주 사용하면 좋을 거라 생각합니다.

4.
렌더링에 관련한 고급 기능

 1) OnPreCull
 
카메라에서 장면을 컬링하기 전에 호출됩니다. 여기서 컬링이란 프러스텀 컬링입니다. (후면 컬링 아님)
 
카메라에 붙어있는 스크립트에만 호출됩니다.
 
카메라의 속성을 바꾸고 싶을 때, 이 함수 안에서 하면 좋습니다.
 
이 함수가 호출된 후 실제 프러스텀 컬링을 하고 각 오브젝트가 화면에 그려질지 그려지지 않을지 정해집니다.

 2) OnPreRender
 
카메라가 장면을 렌더링하기 전에 호출됩니다.
 
카메라에 붙어있는 스크립트에만 호출됩니다.
  yield
사용 가능합니다.

 3) OnPostRender
 
카메라가 장면을 렌더링한 후 호출됩니다.
 
카메라에 붙어있는 스크립트에만 호출됩니다.
  yield
사용 가능합니다.
 
이 함수는 해당 카메라가 모든 오브젝트를 렌더링한 후 호출됩니다.
 
만약 '모든' 카메라와 GUI가 렌더링된 후 무언가를 하고 싶으면 WaitForEndOfFrame coroutine 을 사용하면 됩니다.

 4) OnWillRenderObject()
 
해당 오브젝트를 렌더링하는 카메라마다 한 번 호출됩니다.
  (
세 대의 카메라가 하나의 오브젝트를 보고 있으면 그 오브젝트에 붙어있는 스크립트에서 세 번 불린다는 뜻.)
  (
툴에서 작업할 때는 Scene View 카메라도 들어갑니다.)
 
이 함수는 렌더링하기 전, 컬링 중에 호출됩니다.
  Camera.current
를 사용하면 현재 어떤 카메라가 렌더링할 것인지 알 수 있습니다.

 5) OnRenderObject(queueIndex:int)
 
오브젝트가 렌더링될 때 호출됩니다. queueIndex 는 해당 오브젝트를 렌더링할 때 사용하는 렌더 큐의 값입니다.
  RenderBeforeQueues
속성으로 특정한 렌더링 큐에서 동작하도록 설정할 수 있습니다.
 
이 함수도 OnWillRenderObject 함수처럼 각 카메라가 그릴 때마다 한 번 호출됩니다.

 6) OnRenderImage(source:RenderTexture, destination:RenderTexture)
 
모든 렌더링이 끝난 후 호출됩니다. 카메라에 붙어있는 모든 스크립트에서 호출됩니다.
 
포스트 프로세스 효과를 줄 때 사용합니다. (Pro 전용)
  source
는 렌더링이 끝난 화면이며 destination 텍스쳐에 결과물을 그려주면 됩니다.
 
카메라에 여러 이미지 필터가 붙어있을 경우 순차적으로 진행됩니다.


게임의 경우 때깔내는데 가장 중요한 포스트 프로세싱 부분이 Pro 전용으로 빠져있습니다.
(
그러고 보니 free 에서 렌더 타겟이 사용 불가였으니 당연히 이것도 사용이 불가능하겠네요.)
여기 있는 함수들은 제가 사용해 본 적이 없고, 지금 당장 특별히 어떻게 쓰면 좋을지 잘 모르는 관계로 특별한 부연 설명 없이 레퍼런스를 옮겨적기만 했습니다.

참고로 3.0 부터 이쪽 함수들은 스크립트가 꺼져있으면 동작하지 않는다고 합니다.

5.
네트워킹 관련 함수
점점 써 본적이 없는 함수만 나와서 정말 난감하네요;;;

 1) OnPlayerConnected(player:NetworkPlayer)
  
새 유저가 성공적으로 접속했을 경우 서버에서 호출됩니다.

 2) OnServerInitialized
   Network.InitializeServer
를 호출한 후 완료되었을 때 서버에서 호출됩니다.

 3) OnConnectedToServer
  
서버에 성공적으로 접속했을 경우 클라이언트에서 호출됩니다.

 4) OnPlayerDisconnected(player:NetworkPlayer)
  
유저의 접속이 끊겼을 경우 서버에서 호출됩니다.

 5) OnDisconnectedFromServer(mode:NetworkDisconnection)
 
서버와 접속이 끊기거나 접속을 종료했을 때 클라이언트에서 호출됩니다.

 6) OnFailedToConnect(error:NetworkConnectionError)
 
접속 시도가 실패했을 때 클라이언트에서 호출됩니다.

 7) OnFailedToConnectToMasterServer(error:NetworkConnectionError)
 
서버나 클라이언트에서 마스터 서버로의 접속에 문제가 있을 경우 호출됩니다.

 8) OnMasterServerEvent(msEvent:MasterServerEvent)
 
서버나 클라이언트로 마스터 서버에서 보낸 이벤트를 받았을 때 호출됩니다.

 9) OnNetworkInstantiate(info:NetworkMessageInfo)
  Network.Instantiate
함수로 네트워크를 통해 게임 오브젝트가 생성되었을 때 해당 오브젝트에서 호출됩니다.
 
네트워크 상에서 새 게임 오브젝트가 생성되었을 때 다른 사람이 생성했는지 내가 생성했는지에 따라 오브젝트에 특별한
 
처리를 할 때 유용합니다.

 10) OnSerializeNetworkView(stream:BitStream, info:NetworkMessageInfo)
 
네트워크 상에서 전달되는 변수들(variables in a script watched by a network view)의 동기화 처리를 커스터마이징할
 
때 사용합니다..
 
이 함수는 직렬화된 값 ( BitStream으로 바뀐 정보)을 전달할 것인지 받을 것인지에 대해서 자동으로 판단합니다.
 (
이 오브젝트를 소유권에 따라서 처리됩니다. 소유자는 보내고 나머지는 받고.)

사실 저같은 경우 tcp, udp 연결이 필요한 게임을 만드는 게 아니라 그냥 WWW 클래스만으로도 충분합니다..

 

728x90
Posted by 정망스
,
728x90

랜더링 할때 정점 버퍼와 인덱스 버퍼를 이용해서 할때 DrawIndexedPrimitive() 함수를 호출하는데

넘겨줄 인자값이 재대로 이해가 되질 않아서

다른 블로그에서 계속 찾아 보던중 잘 정리가 되어있는 블로그를 발견해서 여기다가 쓴다..

 

출처 : http://blog.naver.com/lgmpfree/100055862741

 

※ 이 글에 앞서서 필히 확인해야 할것.

g_pD3D->CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd,
  D3DCREATE_SOFTWARE_VERTEXPROCESSING,
  &d3dpp, &g_pd3dDevice )

 

이와 같이.. 디바이스 생성할때, 위와 같이 SOFTWARE로 되어 있어야지 밑에 설명처럼 결과가 나오고 이것저것 실험 할수가 있다.

만약 HARDWARE로 설정할경우.. 하드웨어에서 임의대로 정점을 다 계산해버리고  결과가 좋게(?)만 나와 버린다..

-------------------------------------------------------------------------------------------------------------

DrawIndexedPrimitive 함수에 대하여..!! 정리.

 

 

 

struct CUSTOMVERTEX
{
 float x, y, z;            //좌표
 float nx, ny, nz;       //노말 값
 float tu, tv;              //uv 좌표계
};

 

//버텍스 버퍼

CUSTOMVERTEX pCustVerts[] =
 {
  // 정면
  { -2.0f,-2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.25f, 0.6666f }, // v0
  { -2.0f, 2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.25f, 0.3333f }, // v1
  {  2.0f,-2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.6666f },  // v2
  {  2.0f, 2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.3333f },  // v3

  // 뒷면
  {  2.0f,-2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.6666f },  // v4
  {  2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.3333f },  // v5
  { -2.0f,-2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.6666f },  // v6
  { -2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.3333f }, // v7

  // 위
  { -2.0f, 2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.25f, 0.3333f }, // v8
  { -2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.25f, 0.0f },  // v9
  {  2.0f, 2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.3333f },  // v10
  {  2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.0f },  // v11

  // 아래
  {  2.0f,-2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.5f, 1.0f },  // v12
  { -2.0f,-2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.25f, 1.0f },  // v13
  {  2.0f,-2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.6666f },  // v14
  { -2.0f,-2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.25f, 0.6666f }, // v15

  // 왼쪽
  { -2.0f,-2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.6666f },  // v16
  { -2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.3333f },  // v17
  { -2.0f,-2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.25f, 0.6666f }, // v18
  { -2.0f, 2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.25f, 0.3333f }, // v19

  // 오른쪽
  {  2.0f,-2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.6666f },  // v20
  {  2.0f, 2.0f,-2.0f, 0.0f, 0.0f, 0.0f, 0.5f, 0.3333f },  // v21
  {  2.0f,-2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.6666f }, // v22
  {  2.0f, 2.0f, 2.0f, 0.0f, 0.0f, 0.0f, 0.75f, 0.3333f } // v23

}

 

//인덱스 버퍼

INDEX pCustIndices[] =
 {
  { 0, 1, 2 },
  { 2, 1, 3 },

  { 4, 5, 6 },
  { 6, 5, 7 },

  { 8, 9, 10 },
  { 10, 9, 11 },

  { 12, 13, 14 },
  { 14, 13, 15 },

  { 16, 17, 18 },
  { 18, 17, 19 },

  { 20, 21, 22 },
  { 22, 21, 23 }

}

//위와 같은 정점과 인덱스 정보가 있다는 가정하에..

 

g_pd3dDevice->DrawIndexedPrimitive(
   D3DPT_TRIANGLELIST,   // Primitive 타입
   0,       //BaseVertexIndex,

   0,       //MinIndex
   24,      //NumVertices

   0,       //StartIndex
   12       //PrimitiveCount
   );

 

BaseVertexIndex,: 버텍스 버퍼의 v0, v1, v2, v3, v4가 보일것이다..이것은 1번째 정점이 인덱스 0번 2번째 점이 인덱스 1번 이라고 기본적으로 정해지는것인데. 이 첫번째 인자를 4라고 할경우. 4번째 정점이 v0, 5번째 정점이 v1이 되는것이다. 이 렇게 될경우 인덱스 버퍼의 영향을끼친다.!! 이 부분이 많이 헷갈릴수 있는 부분이고 어려운 인자이다..  이해가 안돼면 밑에 예제를 참고하세요.

 

MinIndex : 인덱스 버퍼에서 쓸 가장 적은 숫자를 쓴다 . 예를 들어 0,1,2,3 을 쓰지 않을경우(정면의 삼각형을 안그릴경우) 4를써준다.

그럼 4번 인덱스부터 사용하겠다는 것이다. 이 인자는 5번째 인자의 그릴 삼각형 갯수에 영향을 끼치지 않는다 여기서 정면 삼각형 2개 그리지 않기때문에 5번재 인자를 12에서 10으로 할경우 가장끝의 11, 12면이 그려지지 않고 물론 정면의 1,2면도 눈에는 안보인다 4번인덱스부터 그리기때문이다.

 

NumVertices : 그려질 정점의 갯수를쓴다. BaseVertexIndex  MinIndex 만큼 빼주면 된다. 예를 들어서 BaseVertexIndex 에 4를 쓰고 MinIndex  는 4를쓰면 24에서 8을빼서 16을써주면 된다. 이 값이 정확히 썼는데 이상한 출력이 나오면  PrimitiveCount이 인자 값을 잘못쓸경우 출력이 이상하니 이 값을 의심해보자. (* 이 값은 StartIndex 인자값의 영향을 받지 않는다)

 

StartIndex :  인덱스 버퍼의 시작 인덱스를 정한다. { 0, 1, 2 },  { 2, 1, 3 },  { 4, 5, 6 },.... (이하 생략) 이렇게 있을때 3이라고 쓰면 { 0, 1, 2 },  다음에 있는 2부터 시작해서 그리고.. 6이라고 쓸경우 { 0, 1, 2 },  { 2, 1, 3 },   다음 인덱스인 4부터 삼각형을 그리겠다는것이다. 7을쓸경우 1부터 그린다.

 

PrimitiveCount : 삼각형의 갯수를쓴다. MinIndex 의 영향을 받지 않으며, 그려질 삼각형의 갯수를 잘 계산해서 써야한다.

 

 

 

 

 

 

------------------------------------------------------------------------------------------------

이해를 돕기 위해 그림과 같이 설명 .

 

g_pd3dDevice->DrawIndexedPrimitive(
   D3DPT_TRIANGLELIST,   

   0,       

   0,       
   24,       

   0,       
   12       
   );

 

이렇게 입력하면.. 다음과 같이 정상적인 정육면체 출력

 

 

 

 

그림 설명 : 빨간 큰 숫자 -> 1번째 삼각형 2번재 삼각형.. 12번째 삼각형까지 있음. (그려진 순서대로 1,2,....12번)

                작은시퍼런 숫자 -> 인덱스 번호 0번 1번 2번 ...24번까지 있음. (위의 인덱스 버퍼 선언과 같은 위치)

 

--------------------------------------------------------------------------------------------------------------------

g_pd3dDevice->DrawIndexedPrimitive(
   D3DPT_TRIANGLELIST,   // Primitive 타입
   0,       

   4,       
   20,       //4개의 인덱스를쓰지 않기때문에 20개의 점만있어도 된다.

   0,       
   12         //2개 삼각형이 없지만 인덱스 0,1,2,3만을안쓰겠다고 한거기때문에 여기는 변하면 안됀다 10개 할경우 마지막 2개면 11,12면이 그려지지 않는다   
   );

 

이렇게 변경(굵은글씨) 하면 다음과 같이 정면이 뚤려서 나온다.

뚤려 나오는 이유는 인덱스 버퍼의 0,1,2,3 을 안쓴다고 선언 하기때문이다 4부터 쓰기때문에 정면이 나오지 않는다

 

 

 

 

(참고 - 현재는 g_pd3dDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); 상태 이다..)

 

--------------------------------------------------------------------------------------------------------------------

 

g_pd3dDevice->DrawIndexedPrimitive(
   D3DPT_TRIANGLELIST,   // Primitive 타입
   4,       //버텍스 버퍼의 4번재 점을 v0 으로 시작 한다는것이다.

   0,       
   20,       //버텍스 버퍼의 정점 4번재꺼부터 쓰기때문에 20개의 정점만을쓴다.

   0,       
   10      // 정면 2개의 삼각형이 빠져서 10개면 된다.
   );

결과는 위와 마찬가지로 정면이 뚤려 보인다. 하지만 중요한것은 여기선 뒤의(보이진 않지만) 3면의 인덱스 번호가 0,1,2라는것이다. 위의 결과는 3면이 4,5,6이다.

 

 

 

 

--------------------------------------------------------------------------------------------------------------------

g_pd3dDevice->DrawIndexedPrimitive(
   D3DPT_TRIANGLELIST,  

   4,       //버텍스 버퍼의 4번재 점을 v0 으로 시작 한다는것이다.

   0,       
   11,     //5번째 인자 가 5개의 삼각형만 그리므로 11개면 된다. 이해가 안되면 잘생각해보기 바란다.

   0,       
   5       //  3면부터 그리기때문에(1번재 인자가 4이므로) 3,4,5,6,7면 5개의 삼각형을 그리리겠다는 것.  밑에 그림처럼 나온다.
   );

 

 

 

 

--------------------------------------------------------------------------------------------------------------------

g_pd3dDevice->DrawIndexedPrimitive(
   D3DPT_TRIANGLELIST,   

   0,       //위와 다르게 이것을 0으로 하면

   0,       
   11,     //5번째 인자 가 5개의 삼각형만 그리므로 11개면 된다.

   0,       
   5       //  1번째 인자가 0이므로 1면부터 그린다.. 1,2,3,4,5 면의  5개의 삼각형을 그린다.
   );

결과는 밑에 그림 처럼..단, 3차원이라..공간적 이해를 하시면서 보시길..

 

 

 

 

--------------------------------------------------------------------------------------------------------------------

 

g_pd3dDevice->DrawIndexedPrimitive(
   D3DPT_TRIANGLELIST,   

   0,      

   0,      

   24,       // 4번째 인자 값에 영향을 받지 않는다 . 여기서 정점수를 24이하로 할경우 이상한 결과를 볼것이다.

   15,       //15번째 인덱스 정점부터 쓴다.

   7          //7개의 삼각형이 그려질것이므로 7이다.   6이라고쓰면 마지막 12면이 나오지 않는다.

};

이렇게 할경우 결과를 보자.

 

 

 

728x90
Posted by 정망스
,
728x90

GDI(Graphic Device Interface)

그래픽 함수들을 구현하는 일을 담당하는 윈도우의 구성요소, 그래픽 출력을 위하여 응용 프로그램이 사용할 수 있는 함수와 그에 관련된 구조를 제공한다.

윈도우 프로그램이 하드웨어에 독립적으로 그래픽 장치를 쓸 수 있도록 제공하는 인터페이스이다.


GPU(Graphic Processing Unit)

CPU에서 혼자 처리하기에 작업량이 많아서 그래픽 연산의 전용 프로세서 GPU라는 것이 개발되어 cpu의 연산 결과를 바탕으로 그림과 글로 변환하여 모니터 화면에 출력을 담당한다. 그래픽카드라고도 부르며 gpu라고도 부른다.


HAL(Hardware Abstraction Layer)

컴퓨터의 물리적인 하드웨어와 컴퓨터에서 실행되는 소프트웨어 사이의 추상화 계층으로써 추상적인 계층에서 하드웨어 서비스와 상호작용할 수 있게 해주는 프로그램 계층이다. 여기서 추상화라는것은 주어진 문제나 시스템 중에서 중요하고 관계있는 부분만을 분리하여 간결하고 이해하기 쉽게 만드는 작업을 뜻한다.

728x90

'DirectX' 카테고리의 다른 글

(directX) 나만의..정리중...  (0) 2014.05.19
Posted by 정망스
,

빅오표기법 정리.

C++ 2015. 1. 7. 12:24
728x90

빅오표기법이란?

시간 복잡도를 표현하는 표기법으로써

시간 복잡도란 해당하는 알고리즘이 데이터 양에 따라서 처리하는 시간이 얼마나 걸리는지에 대한 표현이다.

 

1. O(1)

상수형 빅-오 , 데이터의 양과는 상관없이 일정한 실행 시간을 가진다

ex) 해쉬검색 알고리즘

 

2. O(log n)

로그형 빅-오, 데이터 양이 많아져도 증가율에 비해서 연산횟수의 증가율이 훨씬 낮다.

ex) divide&conquer(이진 검색, mergesort, quicksort)

 

3. O(n)

선형 빅-오, 데이터 양에 따라 시간이 정비례 한다.

ex) 선형탐색, 1중 for문

 

4. O(n*log n)

선형로그형 빅-오, 데이터양이 N배 많아지면 실행 시간은 N배 보다 조금더 많아 진다.(정비례 하지 않음)

ex) divide&conquer 이후에 다시 하나로 모으는 경우, 이진 트리 검색시 로직에 for문을 덮어 씌우는 경우

 

5. O(n²) (n의 제곱)

데이터 양에 따라 걸리는 시간은 제곱에 비례한다.

ex) 2중 for문, 삽입정렬, 선택정렬, 버블정렬

 

6. O(n³) (n의 세제곱)

데이터 양에 따라 걸리는 시간은 세제곱에 비례한다.

ex) 3중으로 중첩된 반복문

 

7. O(2ⁿ)

지수형 빅-오,  지수적 증가라는 무서운 연산횟수의 증가를 보임, 사용하는것 자체가 비현실적인 알고리즘

 

속도가 빠른 순서는 1번부터 ~ 7번 순서이다.

728x90
Posted by 정망스
,


맨 위로
홈으로 ▲위로 ▼아래로 ♥댓글쓰기 새로고침