2008년 5월 19일 월요일

[잡담]EA는 이런것도 하는구나..

http://www.open-std...pers/2007/n2271.html
STL을 개조해서 EASTL이란 것을 만든다는 말을 들었다

출처는 gpgstudy에서이고...

이런것도 하는구만...

왠지 EA라는 회사의 이미지는 안좋은 것이 좀 있었는데...

2008년 5월 7일 수요일

[Project]AI쪽 구상

인공지능 쪽은 크게 길찾기와 행동설정으로 구분했다
여기서 말하려고 하는 것은 우선 길찾기이다.

길찾기는 Ai Game Programming Wisdom을 참고해서 a*를 기본으로 해서 구현할 생각이다.
길찾기의 특성상 맵그래프와 관계가 생길 것이라고 예상하고 있다.
현재의 구상은 그래프클래스와 휴리스틱함수를 인자로 받아서
그래프의 노드아이디 리스트를 반환하는 형식을 취할 생각이다.
그래야 나중에 최적화를 위해 맵의 노드들을 자동으로 병합한다든지하는 일이 생겨도
길찾기 클래스에서는 변화가 적을 것이라고 생각해서이다.

여기에서는 몇가지 제약사항이 있는데,
1. 노드는 아이디로 바로 접근가능해야하고
2. 노드간의 연결은 맵 그래프에서 함수를 통해 얻어내고
3. 노드간의 이동시의 이동소요시간(이동시 사용되는 포인트)도
맵 그래프에서 함수를 통해 얻어낸다.

현재 생각하고 구현중인 것은 이것이다.
추가적으로 구현이 이루어진다면 계속해서 글을 추가할 예정이다
(어딘가 써놔야지 자꾸 잊어버려서..)

[잡담]RTS를 만들기로 했다!

심심해서는 아니고, 예전회사에서 퇴사하고나서
내 능력을 키우려면 뭔가 만들어보는 것이 가장 나을 것같다는 생각도 있고,
포트폴리오용으로도 사용할 수 있을 것같다는 생각도 있어서다.

지금은 기획은 넘어가고 대략적인 설계가 끝나서 구현에 들어간 상태다.
아무래도 예전에 만들었던 턴제 전략 게임(마이너버전 택틱스같은 하지만 허접한)과는
다른 수준이 나와야할텐데..

2008년 4월 19일 토요일

[잡담]음.... 이거 카테고리로 나누는건 없나..

아무래도 처음 써봐서 그런건지 카테고리를 설정을 못하겠네..

[기초]분할 정복

음.. 재귀와 함께 알고리즘에서 자주 보이는 분할 정복에 대해서

대충 써보면..

기본적인 컨셉은 큰 하나의 것을 작은 여러개로 분리해서 작은 것들을 전부 끝내고 그것을 합해서 하나로 만드는 것을 말하는 것이다.

이렇게 써 놓으면 뭐 씨뷁하는 생각밖에 들지 않을테고, 알고리즘 책에서도 자주 예를 드는 병합정렬을 예로 들어보면,(여기서는 간단하게 보여주기만 할 것이고, 알고리즘 폴더에 정확한 것을 써 놓을 것이다)

XXXXXXXXXXX 라는 배열을 정렬한다고 했을 때

1.XXXXX 2.XXXXXX 둘로 나누고

1.XX 2.XXX 1.XXX 2.XXX 둘로 나눈 것을 다시 둘로 나누고

1.X 2.X 1.X 2.XX 1.X 2.XX 1.X 2.XX 다시 둘로 나눠서

X X X X X X X X X X X 이렇게 각자 하나가 될 때까지 나누면 하나

의 원소는 정렬된 것이므로 이것들을 합하면서 정렬시키는 것이다.


그래서 저렇게 나눠진 것을 합해서 정렬된 배열이 나타나는데,

이런 식으로 큰 부분을 작게 나누고 작게 나눠진 부분에서 계산이나 실행을 끝내고 합하는 것을 분할 정복이라고 한다.

뭐 잘 이해가 안가는 설명이었는지도 모르겠지만, 나의 설명의 한계는 이정도이므로 여기서 끝낸다..

[기초]재귀

재귀는 말 그대로 자기 자신을 호출하는 것이다.

재귀를 설명할 때의 가장 간단한 프로그램은 역시 피보나치 수열이다.

피보나치 수열은 자기앞의 두 수의 합이 자신의 값이 되는 것이다. 그리고 자기 앞이 존재하지 않는 1, 2번째의 경우 1로 설정된다. 따라서 수열의 모양은 아래와 같다

1 1 2 3 5 8 13 21 34 55.....

이것을 함수로 나타낸다면

int fibo(int index)

{

if(index <= 0)

return 0;

if(index == 1 || index == 2)

return 1;

return fibo(index - 1) + fibo(index - 2);

}

같은 형식이 될 것이다.

재귀의 경우 전부 루프로 나타낼 수 있다고 한다.

c++에서 재귀함수의 문제점이라면

1. 함수이므로 스택이 쌓이면서 메모리 사용양이 증가한다.

2. 위와같은 이유로 느려진다.

[알고리즘]힙정렬

힙정렬이다.. 우선 소스를 보자.

// 깊이를 구하기위해서 값이 1이하가 될 때까지 쉬프트 연산을 해

// 주고
// 쉬프트 연산의 회수를 반환
int Lg2(int iVal)
{
int temp = 0;
while(iVal > 1)
{
++temp;
iVal >>= 1;
}
return temp;
}

// root인덱스가 추가되었을 때 힙을 재구성해주는 함수
// 좌우 자식중 큰 값을 부모와 비교하여 부모가 크다면 그대로 두

// 고
// 자식이 크다면 부모와 바꿔준다.
// 만약 부모와 자식을 바꾸었다면, 내려간 부모의 인덱스를 이용해

// 다시 자신을 호출한다.
// 여기서 root는 최대 iVec.size() >> 1 즉 배열 크기의 절반이므

// 로
// 최소한 왼쪽 자식은 존재한다.
void LocalHeapify(vector & iVec, int root)
{
int max; // 두 자식중 큰 값의 인덱스를 저장할 변수
int leftChild = root * 2; // 왼쪽 자식
int rightChild = root * 2 + 1; // 오른족 자식
// 두 자식중 큰값의 인덱스를 max에 저장
if(rightChild != iVec.size()) // 오른쪽 자식이 배열의 크기와 같다

//면
// 오른쪽 자식은 배열의 인덱스를 벗어난 것이다.
{
iVec[leftChild] > iVec[rightChild] ? max = leftChild : max = rightChild;
}else
{
max = leftChild;
}

// 만약 자식이 부모보다 크다면 두 값을 바꿔주고
// 내려간 부모의 인덱스를 이용해 재귀적으로 호출
if(iVec[max] > iVec[root])
{
SwapInt(iVec[max], iVec[root]);
if(max <= (iVec.size() >> 1))
{
LocalHeapify(iVec, max);
}
}
}

// 들어온 배열로 힙을 만들어주는 함수
// 마지막 원소의 인덱스를 2로 나눈 것부터 첫번째 원소까지
// LocalHeapify함수를 호출
// 마지막 원소의 인덱스를 2로 나눈 것이 자식을 가지는 가장 아래

// 의 가장 오른쪽 원소이기때문이다.
void MakeHeap(vector & iVec)
{
int temp = (iVec.size() - 1) >> 1;
for(int i = temp; i > 0; --i)
{
LocalHeapify(iVec, i);
}
}

// 만들어진 힙을 사용해서 힙정렬을 수행하는 함수
// 루트를 마지막원소와 바꿔주는 연산을 계속하면서
// 바꿔준 뒤에 힙을 재구성하는 AcceleratedHeapify함수를 호출
void HSort(vector & iVec)
{
int end = iVec.size() - 1;
while(end > 1)
{
SwapInt(iVec[1], iVec[end]);
AcceleratedHeapify(iVec, --end);
}
}

// 루트의 바뀐 값을 이용해 힙을 재구성 하는 함수
// 깊이의 절반만큼 자식들만 비교해서 내려간뒤
// 들어온 값이 자신의 부모보다 크다면 위로 올라가면서 제자릴 찾

//고 끝내고
// 들오온 값이 자신의 부보보다 작다면 다시 남은 깊이의 절반만큼

//내려간다.
// 만약 리프까지 내려오면 종료한다.
void AcceleratedHeapify(vector & iVec, int end)
{
// 값이 1개도 남지않았다면 종료
if(end < cur =" 1;">

//다.
int treeHeight = Lg2(end); // 정렬되지 않은 트리의 깊이를 구한

//다.
int currentHeight = 0; // 들어온 값이 내려온 깊이를 저장한다.
// 리프까지 내려갈때까지 루프를 돈다.
while(currentHeight <= treeHeight) { int move = (treeHeight - currentHeight) / 2 + 1; // 한번에 내려

//갈 깊이
for(int i = 0; i <>

//내려간다.
{
int leftChild = cur * 2;
int rightChild = cur * 2 + 1;
int max;
if(leftChild > end)
{
break;
}else if(rightChild > end)
{
max = leftChild;
}else if(iVec[leftChild] > iVec[rightChild])
{
max = leftChild;
}else
{
max = rightChild;
}
SwapInt(iVec[cur], iVec[max]);
cur = max;
}
int parent = cur / 2;
if(cur > 1 && iVec[cur] > iVec[parent]) // 만약 내려간 위치에

//서 부모가 자신보다 작다면
{
while(cur > 1 && iVec[cur] > iVec[parent]) // 정확한 위치를

//찾을 때까지 거슬러 올라간다.
{
SwapInt(iVec[cur], iVec[parent]);
cur = parent;
parent = cur / 2;
}
return; // 정확한 위치를 찾았으니 종료
}
currentHeight += move; // 내려간 위치의 깊이를 저장
}
}


주석때문에 보기가 엉망이다... 거기다 힙정렬의 변화형을 사용했기때문에 소스가 길어졌다.

이 소스도 아래의 퀵정렬과 마찬가지로 전에 만들었던 소스를 그냥 올린 것이다.

[알고리즘]퀵 정렬

아.. 간만에 쓴다.. 솔직히 버블이나 삽입같은거야 그냥 쉽게 쉽게 설명이 되는데 이분부터는 재귀씨가 들어가셔서 애로사항이 꽃필수도 있다.

우선 코드를 보면

void QuickSort(vector & iVec, int first, int last)
{
if(first >= last) // 값이 1개만 들어오거나 안들어왔을 경우를 위한

//문장
return;
if((last - first) <>

//를 사용
InsertSort(iVec, first, last);
SwapInt(iVec[first], iVec[last]); // 처음 인덱스의 값을 마지막으

//로 보냄
// 굳이 보낼 필요는 없지만, 보내고 싶어서 보냄
int pbot = iVec[last]; // 처음 값을 인덱스로 결정
--last;
int f = first; // 피봇보다 작은 값의 범위를 나타내줄 변수
int l = last; // " 큰 "
while(f <= l) { while(iVec[f] <>= pbot) // 피봇보다 작은 값이 나올때까지 이동
{
--l;
}
if(f <>= l이면 파티션이 제 자리를 찾았으므로 swap하지않

//는다.
SwapInt(iVec[f], iVec[l]);
}
SwapInt(iVec[++last], iVec[f]); // 피봇값을 제자리로 위치 시킴
QuickSort(iVec,first, f - 1); // 피봇보다 작은 쪽 파티션을 다시 재

//귀적으로 호출
QuickSort(iVec,f + 1, last); // " 큰 "
}


아.. 예전에 만든 코드를 가져다 붙였더니 엉망이다..

가장먼저 보이는 것은 vector로 배열을 사용하지 않고 벡터를 썼다. 배열을 써도 무관하다. 알고리즘과는 전혀 상관없다.

알고리즘을 설명하면 정렬하려는 범위내에서 피봇을 하나 선택한 후 그 피봇보다 작은 것은 앞쪽에 크거나 같은 것은 뒤쪽에 놓는다. 이 과정이 끝나면 피봇값은 정확한 위치에 놓이게된다.

그 다음 자신보다 작은부분과 큰부분에 다시 위의 것을 적용한다.

이것이 기본적인 컨셉이다.

이것을 구현하는 방식이 책이나 문서마다 조금씩 다른 경우가 있는데, 큰 차이는 없다. 위의 코드에서 사용한 방식을 보면

3 5 6 1 6 8 9 // 시작값

9 5 6 1 6 8 3 // 처음 값을 피봇으로 선택후 맨 뒤와 교체

f l p //p는 피봇값 f,l은 인덱스를 가리키는것으로 뒤에설명

9 5 6 1 6 8 3 // 앞쪽부터 피봇값보다 크거나 같은값이 올때까지 f를

f l p //이동

// 이동이 없다.

9 5 6 1 6 8 3 // 뒤쪽부터 피봇값보다 작은 값이 올 때까지 l을 이동

f l p// 1까지 이동

1 5 6 9 6 8 3 // f <>

f l p // 교체

// f > l이라면 끝낸다

1 5 6 9 6 8 3 // 다시 f를 이동

f l p // 5까지 이동

1 5 6 9 6 8 3 // l을 이동

l f // 1까지 이동

// f > l 이므로 현재 단계를 끝낸다.

1 3 6 9 6 8 5 // 피봇값과 f를 교체

l p f // 교체

// 피봇값의 앞 뒤로 다시 알고리즘을 실행한다.

// 앞쪽은 1 하나로 종료

// 위에 설명했으므로 바뀌는 순서만 표시

6 9 6 8 5

5 9 6 8 6

5 6 6 8 9 // 피봇값은 두번째

// 앞쪽은 5 하나로 종료

6 8 9

9 8 6

6 8 9 // 피봇값은 첫번째

8 9

8 9

// 결과

1 3 5 6 6 8 9

알고리즘은 이런 식 이지만, 자료가 일정 수 이하일 경우

퀵정렬이 삽입정렬보다 정렬 시간이 더 걸리게 되므로

현재 정렬해야하는 원소의 수를 세어서 위의 코드의 경우 10개 미만이라면 삽입 정렬을 사용한다.

위의 예에서는 단지 퀵정렬이 이루어지는 방식을 보여주는 것으로

저정도 숫자라면 삽입 정렬을 사용한다

[알고리즘]버블 정렬

이번에도 기초적인 것으로 버블 정렬이다.

우선 소스를 보면


bubbleSort(int array[], int arrayNum)

{

for(int i = arrayNum - 2; i >=0; --i)

{

for(int j = 0; j <= i; ++j)

{

if(array[j] > array[j+1])

{

array[j] += array[j+1];

array[j+1] = array[j] - array[j+1];

array[j] = array[j] - array[j+1];

}

}

}

}


알고리즘을 설명하면

버블 정렬은 배열의 끝으로 최대값을 보내고

최대값이 들어간 부분은 제외하고 다시 최대값을 끝으로

보내는 것을 반복하는 것이다.


예를 들면,

4 10 3 6 2 라는 배열이 주어진다면

4& 10 3 6 2 // 초기값

// &앞과 뒤의 값을 비교해서 큰 수를 뒤로보냄

4 10& 3 6 2 // 먼저 나온 for문의 첫번째 루프

4 3 10& 6 2

4 3 6 10& 2

4 &3 6 2 *10 // 별표 이후는 고정값

3 4 &6 2 *10 // 두번째 루프

3 4 6 &2 *10

3 &4 2 *6 10

3 4 &2 *6 10 // 세번째 루프

3 &2 *4 6 10

2 *3 4 6 10 // 네번재 루프

이번에는 예가 긴데, 버블정렬은 삽입정렬과는 달리 항상 n(n-1)/2

번의 연산을 해야하기 때문이다.

버블정렬은 가장 큰 수가 맨 뒤로 가는 구조로 마치 물방울이 떠오르는 것처럼 보여서 '버블' 정렬이라고 부른다

[알고리즘]삽입정렬

우선 알고리즘의 기초라고 할 수 있는 삽입정렬

insertSort(int array[], int arrayNum)

{

int temp;

for(int i = 1; i <>

{

temp = i;

while(array[temp] <>= 0)

{

array[temp] += array[temp-1];

array[temp-1] = array[temp] - array[temp-1];

array[temp] = array[temp] - array[temp-1];

--temp;

}

}

}


이건 슈도코드가 아니라 c++ 코드로 만든 것으로

돌아가는지는 확인해봤음


알고리즘에 관한 간단한 설명이라면

우선 while문 부터 설명하면

정렬할 숫자(array[i])의 앞부분은 정렬이 되어있다는 가정하에

바로 앞의 숫자와 비교해봐서 자신이 작다면 교환한뒤

다시 앞의 숫자와 비교하는 것을

맨 앞까지 가거나 앞의 숫자가 자신보다 작거나 같다면

끝나는 구조로 되어있다.

for문이 1부터 시작하는 것은 1개의 값은

항상 정렬되어있기 때문이다.


나의 특유의 이해하기 힘든 설명으로

위의 글은 거의 알아먹기 힘들테니 예를 들어보면,

입력이 10, 4, 5, 2, 8 이라면

우선 i = 1이니 4부터 시작

10* 4 5 2 8 // 시작부분

4 10* 5 2 8 // i = 1

4 5 10* 2 8 // i = 2

4 5 2 10 8 // i = 3

4 2 5 10 8 // i = 3

2 4 5 10* 8 // i = 3

2 4 5 8 10* // i = 4 끝


위에서 별표를 한 곳 앞쪽은 정렬이 되어있다.

바로 뒤의 것을 정렬이 되어있는 부분에 '삽입' 하기때문에

삽입정렬이라고 하는 것이다.


어쨋든 설명을 잘 하지는 않았지만 나로서는 이것이 한계로

더 이상의 설명은 관두기로..

[OGRE]오거 설정

음.. 내가 대충 직역으로 해석한 것을 올리는데,

내가 보려고 한 것이니, 쓸데없는 딴지는 하지말고

해석이 잘못된 것이 있다면 댓글로..

뭐 누군가 들어올 사람도 없겠지만...

혹시라도 가져다 쓰는 것은 좋지만

가져다 쓴다는 말 정도는 해놓고 썼으면..

원본: http://www.ogre3d.org/wiki/index.php/SettingUpAnApplication

어플리케이션 설정

이 페이지는 너의 첫 번째 어플리케이션을 설정하는 가이드이다. SDK를 인스톨했거나 소스로부터 빌드한 OGRE 엔진이 준비되어 있어야한다. 초보자라면 가능하면 첫 번째를 추천한다.


전제조건

지금쯤은 너는 SDK의 인스톨이나 소스를 빌드를 끝내놓았을 것이다. 아니라면, 적당한 페이지로 돌아가서 너의 OGRE 설정을 끝내라.

너의 어플리케이션을 실행하기 위해서는 여러 가지 파일들이 너의 시스템에 자리 잡고 있어야한다. 그 목록은 아래에 여러 파일들이 명시되어 있다. _d는 디버그 라이브러리에서 추가참조를 나타낸다.(예를 들어 OgreMain_d.dll로 OgreMain.dll을 대신 사용된다) 이 파일들은 너의 작업 디렉터리나 접근 가능한 적당한 패스에 존재해야만 한다.

설정된 모든 것을 사용하는 가장 간단한 방법은 OGRE 샘플과 media 디렉터리를 너의 작업 디렉터리로 복사하는 것이다. 만약 윈도우를 사용한다면 모든 필요한 런타임 dll을 이 디렉터리로 복사해라. 새로운 디렉터리에 맞도록 plugins.cfg와 resources.cfg 파일에 저장된 파일 위치 값을 고쳐라.


OGRE 라이브러리와 파일

▪ OGRE 라이브러리들(윈도우에서는 OgreMain[_d].dll, OgrePlatform[_d].dll , 리눅스라면libOgreMain.so, libOgrePlatform.so)

▪ plugins.cfg - Ogre에 사용가능한 렌더링 라이브러리를 명세 하는 텍스트 파일

▪ 모든 플러그인 라이브러리들은 plugin.cfg에 명시되어 있다.(네가 사용하고 싶지 않은 파일은 plugin.cfg에서 지울 수 있다)

▪ resources.cfg - 만약 ExampleApplication을 사용한다면, 매질, 텍스쳐, 모델 등의 패스를 명세 하는 텍스트 파일이다.

▪ OgreCore.zip - 네가 OGRE 디버그 패널에나 프로파일러를 사용하기로 계획했다면, 이들 파일의 적당한 패스를 가지고 있는 resource.cfg 파일을 보호하는 파일이다.

▪ 너의 프로그램에서 사용되는 다른 자료들(*.zip; *.png; *.particle; *.mesh;..)


서드파티 라이브러리

SDK를 사용하지 않고 소스로부터 빌드했다면 추가적인 패키지 또한 설치가 필요하다. 라이브러리들(.lib, .a) 그리고 헤더파일들(.h) 는 링크시 필요할 것이고, 런타임 라이브러리들(win32.dll, linux.so)는 실행시 필요할 것이다. 만약 윈도우에서 라면, 미리 컴파일된 부가물들을 강력히 추천한다. 이것들은 www.ogre3d.org -> More Downloads -> Source: Windows에서 받을 수 있다. 너의 컴파일러에 맞는 패키지를 받아라.


아래의 것들은 필수사항이다.

▪ Zlib: zlib1.dll; libz.so(debian: zlib1g, zlib1g-dev)

▪ DevIL: devil.dll, ilu.dll, ilut.dll; libIL.so, libILU.so(debian: libdevil1, libdevil-dev)



아래의 것들은 옵션이다.

▪ CEGUI: OgreGUIRenderer[_d].dll, CEGUIBase[_d].dll, CEGUITaharezLook[_d].dll, CEGUIWindowsLook[_d].dll, xerces-c_2_5_0.dll

▪ CEGUI: libCEGUIBase.so. libCEGUIOgreRenderer.so, libxerces-c.so(debian: libcegui-mk2-0, libcegui-mk2-dev, libxerces26, libxerces26-dev)

▪ Cg: cg.dll; libCg.so(debian: nvidia-cg-toolkit)

▪ OpenEXR: openexr.dll ??;(debian: libopenexr-dev libopenexr2)

▪ ReferenceApp: ReferenceAppLayer.dll


MSVC++6(SP3+)에서의 추가사항

▪ stlport_vc6[_stldebug]46.dll

▪ msvcp60[D].dll

▪ msvcrt[D].dll


MSVC++.net 2002에서의 추가사항

▪ stlport_vc7[_stldebug]46.dll

▪ msvcp70[d].dll

▪ msvcr70[d].dll


MSVC++.net 2003에서의 추가사항

▪ msvcp71[d].dll

▪ msvcr71[d].dll


Mingw + STLPort에서의 추가사항

▪ libstlport[stlg].5.0.dll

▪ mingwm10.dll


환경 설정

너는 OGRE설치경로의 루트를 너의 환경변수가 가리키도록 등록함으로서 너는 그것과 관계있는 모든 너의 경로를 표현할 수 있는 것을 원할지도 모른다. 네가 만약 주변의 것들을 이동시켜봤거나 다른 머신으로 옮겨봤다면, 더욱 쉬울 수 있다. 환경변수들의 점검과 갱신 정보를 알아내기 위해서는 너의 운영체제의 문서를 봐라.

(윈도우:http://www.microsoft.com/resources/documentation/windows/xp/all/proddocs/en-us/environment_variables.mspx 리눅스: http://www.tldp.org/LDP/gs/node5.html 맥 OSX: http://developer.apple.com/documentation/MacOSX/Conceptual/BPRuntimeConfig/index.html)

▪ 만약 네가 미리컴파일된 OGRE SDK를 받아서 설치했다면, 너는 이미 네가 설치한 폴더를 가리키고 있는 ‘OGRE_HOME'라는 환경변수를 가지고 있을 것이다. 만약 존재하지 않는다면, 너는 아마도 다른 유저의 권한아래 설치한 것일 것이다. 그렇다면 OGRE_HOME을 수동으로 정의해라.


▪ 만약 네가 소스를 다운받았다면 너는 OGRE 소스로부터 만들어진 'ogrenew'를 가리키는 OGRE_SRC라는 새로운 환경변수를 등록해야할 것이다.


새로운 프로젝트 생성

이 섹션은 확장 컴파일러/IDE 설정을 알려주는 것이 아니다. 단지 새로운 프로젝트를 시작하는데 굉장히 짧은 단계를 말해주는 것이다. 이것은 어떤 IDE에서도 매우 쉽게 될 것이다. 프로젝트에 들어갈 소스코드는 아래쪽에 있다. 너의 소스코드를 담을 작업 디렉터리를 만들어라. 표준 디렉터리구조는 헤더와 소스파일, 프로젝트 파일을 아래처럼 분리한다.

work_dir

include

*.h

src

*.cpp

scripts

*.vcproj


MSVC++6(SP3+)

OGRE는 VC6을 위한 지원을 하지 않는다. 그것은 1998년부터 있었고, 정확히는 더 오래되었다. ISO C++도 지원하지 않는다. 그것은 너에게 고통만을 만들어낼 것이다.

대신에 MSVC++2005를 권한다.

만약 네가 그냥 쓰고 싶다면 네 스스로 계속해라(VC6.0용 설정 링크: http://www.ogre3d.org/wiki/index.php/Setting_up_VC6). 너는 어떠한 지원도 받지 못할 것이고, 다른 사람들이 업그레이드하라고 말할 것이다.


MSVC++.net

노트: 만약 네가 2003이나 2005를 사용한다면, 너는 Ogre Application Wizard를 사용할 수 있고, OGRE 어플리케이션을 만들 준비가 된 것이다. - 편안한 마음으로 코드 부분으로 넘어가라. 어플리케이션 위자드가 너를 위해 설정해줄 것이다. 또한 The Complete Blanks Guide To Using The OGRE SDK AppWizard 항목을 봐라.

반대로 IDE 설정을 수동으로 하고 싶다면, 다음 순서를 따라라.

1. Visual C++ Projects / Win32 / Win32 Project 타입으로 새 프로젝트를 만들어라.

2. 너의 프로젝트 이름을 입력하고, 작업 디렉터리를 가리키는 위치를 변경해라.(런타임 디렉터리로부터 분리해라)

3. 생성을 위한 프로젝트 타입 설정에서 윈도우 응용프로그램과 빈 프로젝트를 선택해라.

4. 프로젝트-> 새 아이템추가를 이용해 새로운 소스파일을 만들어라. 파일이 작업 디렉터리에 있는지 확인해라. 이 단계는 프로젝트 속성을 고치기전에 실행되어야한다.(그렇지 않으면 'C/C++' 페이지는 접근할 수 없을 것이다.)

5. 프로젝트를 저장해라.



만약 네가 너의 프로젝트의 이름을 ‘Testproject'라고 했다면 그리고 위치를 c:\Work같은 곳을 위치로 잡았고, 체크박스에서 솔루션을 위한 디렉터리 생성을 Testsolution이라는 이름으로 체크했다면, 디렉터리 구조는 C:\Work\Testsolution\Testproject 일 것이다. 만약 솔루션 디렉터리를 만들지 않았다면, 구조는 단순하게 C:\Work\Testproject가 될 것이다.

DLL파일이 있는 곳을 알기 쉽게 하는 쉬운 한가지 방법은 OGRE 인스톨 디렉터리의 \bin 폴더(\debug와 \release를 포함하는)와 \media 폴더를 너의 Testproject폴더로 복사하는 것이다.(note: 이 경우 너는 원치 않는 DLL파일들도 복사할지도 모른다. 하지만 이것은 머리 아프지 않은 방법이다.) 위에 써놓은 것을 따른다면 너는 헤더와 스크립트, 소스파일을 위한 폴더를 \Testproject 폴더의 하위폴더로 'bin', 'include', 'media', 'testsolution', 'scripts', 'src'라는 이름으로 만들어야 할 것이다.


만약 네가 다음의 몇 개의 단계를 조심해서 따라한다면, 너의 프로젝트는 에러 없이 돌아갈 것이다.


너의 프로젝트를 아래와 같이 설정해라. 이것들은 전부 디버그 설정이다. 릴리즈 설정을 위해서는 단순히 디렉터리를 \Debug에서 \Release로 바꿔라.

프로젝트에서 속성을 선택한 다음 아래처럼 써 넣어라.

디버깅 -> 작업 디렉터리 = ..\bin\Debug

c/c++ -> 전처리기 -> 전처리기 정의 += _STLP_DEBUG (디버그 모드에서만, .net 2003

과 2005에서는 불필요함)

c/c++ -> 코드 생성 -> 런타임 라이브러리 = 다중 스레드 디버그 DLL

(릴리즈 시 다중 스레드 DLL)

링커 -> 일반 -> 출력 파일 = ..\bin\Debug\[appname].exe

링커 -> 입력 -> 추가 종속성 += OgreMain_d.lib (릴리즈 시 OgreMain.lib)


그리고 SDK에서 이들을 사용하기 위해서

c/c++ -> 일반 -> 추가 포함 디렉터리 = ..\include;$(OGRE_HOME)\include;

$(OGRE_HOME)\samples\include

링커 -> 일반 -> 추가 라이브러리 디렉터리 = $(OGRE_HOME)\lib


아니면 소스 릴리즈를 사용하기 위해서

c/c++ -> 일반 -> 추가 포함 디렉터리 = ..\include;$(OGRE_SRC)\OgreMain\include;

$(OGRE_SRC)\Samples\Common\include

링커 -> 일반 -> 추가 라이브러리 디렉터리 = $(OGRE_SRC)\OgreMain\lib\Debug


뒤에 다른 ide나 다른 컴파일러의 경우는 생략.... 그냥 오거 홈페이지에 가서 찾아보는 게 좋을 듯