프로그래밍/C/C++2013.08.19 17:02

cocos2dx 3.0.0 이 kick start 되었습니다.


기존 2.x.x에서 3.x.x로 바뀌었단 얘기는 많은것이 바뀌었단 얘기죠.


가장 큰 변화점은 C++11 을 정식으로 지원한단 얘깁니다.


C++10 또는 C++0x 은 기존 C++의 불편한 점을 개선하고 최근 트렌드 (java, phython등) 를 따라가려고 노력합니다.


앞으로 이 부분에 대해 간략하게 소개할까 합니다.


따..딱히 할일이 없어서 그러는건 아니라능!


cocos2dx 3.0.0 (이하 cocos3.0) 에서는 다음과 같은 재료를 필요로합니다.


- Xcode 4.6 (for iOS or Mac)

- gcc 4.7 for Linux or Android. For Android ndk-r8e or newer is required.


업데이트 해주세요 :)

참고로 ios7에서 앱을 만들고 업로드하려면 xcode5 가 필요합니다. 그리고 xcode5 는 마운틴라이언부터 지원하고요. -_-;;;


cocos3.0 에서 c++11 을 지원하는 부분은 크게 4가지입니다.


- std::function, including lambda objects for callbacks

- strongly typed enums, for most of the cocos2d-x enums and constants

- std::thread for threading

- override context keyword, for overriden methods


오늘은 std::function, lambda object 에 대해 설명하겠습니다.


위에서도 말했듯이 c++0x부터 최신 트렌드를 따라가기 위한 많은 노력이 있었는데


예를들어 java에서


{

    this.callback(new callback(){ Log.d(TAG, "CALLBACK!"); });

}


같은 코드를 자주 쓰셨을겁니다.


함수안에서 함수의 내용을 선언해서 사용하는 부분인데 c++에서는 해당 기능을 지원해주지 않아서 쓸데없이 header가 길어졌죠.


c++0x에서는 이걸 이렇게 지원해줍니다.


{

    this->callback([]{ Log.d(TAG, "CALLBACK!"); });

}


만세! 이제 .h 는 좀 더 깔끔해질겁니다!


기본적인 사용법은 [introducer]->return type(parameter){statement} 입니다.


parameter, statement 야 다들 아실테고 introducer 를 설명드리자면


이 람다에 외부 변수들을 어떻게 연결시켜줄지 선언하는 부분입니다.


1) 아무것도 넣지 않으면 외부 변수들을 쓰지 않겠다.


2) [=] 는 외부의 변수를 값(const)으로 사용하겠다


3) [&] 는 외부의 변수를 참조(*)해서 사용하겠다.


4) [this] 는 외부와 직접적으로 연결하겠다.


introducer는 좀 더 복잡하게 사용 가능합니다.


만약 


{

    int a, b;

    [=, &a](){ };

}


라면 외부의 변수의 값을 전부 가져오되, a만 참조하겠다. 라는 뜻입니다.


[&, b](){ }; 처럼 쓸 수도 있습니다.


return type 은 해당 람다가 값을 리턴할때 그 형을 명시해줄 수 있습니다.


(어떠한 형인지 확정할 수 없을때 java 에서 Object 를 쓰듯이, objective-c 에서 id 를 쓰듯이, c++0x에선 auto 를 쓸 수 있습니다.)


또한 람다 자체를 객체로서 보관할 수 도 있습니다.


function<void (int)> func = [](int n) { cout << n * n * n << " "; };


다음에는 threading 에 대해 알아보겠습니다.


참고자료 : http://scor7910.tistory.com/55

Posted by Yria

댓글을 달아 주세요

프로그래밍/C/C++2010.03.27 12:53


#include 

#define WINDOW_WIDTH 800
#define WINDOW_HEIGHT 600
GLdouble aspectW;
GLdouble aspectH;
static int rotate = 0;
void reshape(int width, int height){
	aspectW = (GLdouble)width / (GLdouble)WINDOW_WIDTH;
	aspectH = (GLdouble)height / (GLdouble)WINDOW_HEIGHT;
}void DrawScene()
{	
	glColor3f(1.0, 1.0, 1.0);
	glPushMatrix();		
	glRotatef((GLfloat)rotate, 0.0, 1.0, 0.0);	
	glTranslatef(0.0, 0.0, 0.0);	
	glutWireTeapot(1.0);
	glPopMatrix();
}
void display()
{	
	glClear (GL_COLOR_BUFFER_BIT);
	glColor3f (1.0, 1.0, 1.0);
	glViewport(0, 0, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);	
	// 좌하	glPushMatrix();	
	gluLookAt(0.0, 0.0, 1.0,   0.0, 0.0, 0.0,   0.0, 1.0, 0.0);
	DrawScene();
	glPopMatrix();
	glViewport(WINDOW_WIDTH/2, 0, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);		
	// 우하	glPushMatrix();	
	gluLookAt(1.0, 0.0, 0.0,   0.0, 0.0, 0.0,   0.0, 1.0, 0.0);	
	DrawScene();	
	glPopMatrix();
	glViewport(0, WINDOW_HEIGHT/2, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);
	// 좌상	glPushMatrix();	
	gluLookAt(0.0, 1.0, 0.0,   0.0, 0.0, 0.0,   0.0, 0.0, 1.0);	
	DrawScene();	
	glPopMatrix();
	glViewport(WINDOW_WIDTH/2, WINDOW_HEIGHT/2, WINDOW_WIDTH/2, WINDOW_HEIGHT/2);	
	// 우상	glMatrixMode(GL_PROJECTION);
	glPushMatrix();	
	glLoadIdentity();		
	gluPerspective(30, 1.0, 8.0, 100.0);		
	glMatrixMode(GL_MODELVIEW);		
	glPushMatrix();		
	gluLookAt(6.0, 6.0, 6.0,   0.0, 0.0, 0.0,   0.0, 1.0, 0.0);	
	DrawScene();	
	glPopMatrix();
	glMatrixMode(GL_PROJECTION);
	glPopMatrix();	
	glFlush();
	glutSwapBuffers();
}
void Init() {
	glClearColor (0.0, 0.0, 0.0, 0.0);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();	
	glOrtho(-2.0, 2.0, -2.0, 2.0, 0.5, 5.0);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}
void idle(){
	rotate++;
	glutPostRedisplay();
}

int main(int argc, char** argv){
	glutInit(&argc, argv);
	glutInitDisplayMode (GLUT_DOUBLE | GLUT_RGB);	
	glutInitWindowSize (WINDOW_WIDTH, WINDOW_HEIGHT);
	glutInitWindowPosition (100, 100);
	glutCreateWindow ("4Viewport - teapot");
	Init();
	glutDisplayFunc(display);
	glutReshapeFunc(reshape);	
	glutIdleFunc(idle);
	glutMainLoop();
	return 0;
}


 뷰포트란 윈도우 안에 설정한 작은 창을 말한다. MFC에서 자식윈도우를 생각해도 좋으나 3DMAX나 기타 툴을 보면 화면이 분활되어 각각 다른 시점으로 물체를 보는걸 본 적이 있을것이다.


void glViewport(GLint X, GLint Y, GLsizei width, GLsizei height); // 31 line


 앞의 X, Y는 glViewport를 그려주는 왼쪽 아래 좌표를 말하며, 뒤의 width, height는 뷰포트의 크기를 지정해준다.

 GLUT함수는 화면 좌표계의 기준을 좌상단으로 잡지만 GL함수는 윈도우의 좌하단을 (0,0)으로 기준한다는 점에 유의해야한다.


 콜백 함수는 윈도우에 어떤 동작을 할때 일어난다. 예를 들어 디스플레이 콜백 함수는


1. 처음 윈도우를 열때
2. 윈도위 위치를 옮길때
3. 윈도우 크기를 조절할 때
4. 앞 윈도우에 가려저 안보이던 뒤 윈도우가 활성화되어 앞으로 드러날 때
5. glutPostRedisplay(); 함수에 의해 이벤트 큐에 Flag이 게시될 


 일때 자동으로 호출한다. 그 외 키보드 콜백, 마우스 콜백, 메뉴 콜백, 아이들Idle 콜백 등이 있다.


 다른 여러가지는 이름을 들으면 대충 어떤건지 머리속에 떠오르지만 아이들Idle 콜백은 좀 애매할것이다. glutMainLoop() 을 이용해 프로그램을 무한 이벤트 루프로 가져간다.


void glutIdleFunc(idle); // 95 line


 idle 함수 안에선 rotate변수를 계속 증가시켰고, 이는 glRotatef((GLfloat)rotate, 0.0, 1.0, 0.0); 에서 증가된 rotate값 덕분에 회전 할 수 있게 된다. 참고로,


void glRotatef(GLfloat angle, GLfloat x, GLfloat y, GLfloat z); // 20 line


에서 y가 1이기 때문에 y축을 기준으로 회전하고 있다.


 여기 까지 하면 회전하는 주전자를 4개의 시점으로 볼 수 있을것이다. 그런데 모델의 애니메이션에 가장 중요한 한 가지가 빠져 있다. 바로 버퍼이다. 쉽게 말해서 그림을 그려준후 이를 화면에 뿌리는데 두 작업간의 속도에 차이가 나서 화면에 잔상이 남게 된다.  다시 말해서 GPU가 프레임 버퍼에 쓰는 작업은 비디오 컨트롤러가 프레임 버퍼를 읽어가는 속도에 비해 훨씬 느리다. 화면에 이미지를 뿌릴때는 왼쪽 위부터 한줄씩 채워가기 때문에 애니메이션이 마치 물결치는 모습으로 보이게 될 것이다.


 이를 해결하기 위해 더블 버퍼를 사용한다. 즉, 버퍼를 두개 만들어서 A버퍼가 화면을 뿌릴때 다음 장면을 B버퍼에 저장하는 것이다.


void glutInitDisplayMode(unsigned int mode); // 88 line
void glutSwapBuffers(void); // 63 line


 전자의 함수에서 (GLUT_SINGLE | ..) 로 되 있는것을, (GLUT_DOUBLE | ..) 로 바꾸어 주면 되고 후자의 함수는 glFlush(); 이후에 사용하면 된다.

Posted by Yria

댓글을 달아 주세요

프로그래밍/C/C++2010.03.05 11:24

#include ;

void display()
{
	glClear (GL_COLOR_BUFFER_BIT);

	glColor3f (0.0, 1.0, 1.0);
	glBegin(GL_POLYGON);
	glVertex3f (0.25, 0.25, 0.0);
	glVertex3f (0.45, 0.25, 0.0);
	glVertex3f (0.45, 0.45, 0.0);
	glVertex3f (0.25, 0.45, 0.0);
	glEnd();

	glColor3f (1.0, 0.0, 1.0);
	glBegin(GL_POLYGON);
	glVertex3f (0.75, 0.75, 0.0);
	glVertex3f (0.85, 0.85, 0.0);
	glVertex3f (0.85, 0.65, 0.0);
	glEnd();

	
	glColor3f (1.0, 1.0, 0.0);
	glBegin(GL_POLYGON);
	glVertex3f (0.25, 0.75, 0.0);
	glVertex3f (0.35, 0.55, 0.0);
	glVertex3f (0.55, 0.55, 0.0);
	glVertex3f (0.65, 0.75, 0.0);
	glVertex3f (0.45, 0.95, 0.0);
	glEnd();

	glFlush ();
}

void rectangle()
{
	glClear(GL_COLOR_BUFFER_BIT);
	
	glColor3f (1.0, 0.0, 1.0);
	glBegin(GL_POLYGON);
	glVertex3f (0.55, 0.55, 0.0);
	glVertex3f (0.65, 0.65, 0.0);
	glVertex3f (0.45, 0.45, 0.0);
	glEnd();

	glFlush();
}


void init() 
{
	glClearColor (0.0, 0.0, 0.0, 0.0);

	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	glOrtho(0.0, 1.0, 0.0, 1.0, -1.0, 1.0);
}

int main(int argc, char** argv)
{	
	glutInit(&argc, argv);
	glutInitDisplayMode (GLUT_SINGLE | GLUT_RGB);
	glutInitWindowSize (500, 500); 
	glutInitWindowPosition (100, 100);
	glutCreateWindow ("hello");
	init();
	glutDisplayFunc(display); 
	glutMainLoop();
	return 0;
}




openGL의 기초 프로그래밍이다.

화면은 오픈소스이자 연습용으로 가장 적당한 GLUT를 이용해 그렸다.

특이한 점은, 좌표의 기준이 기존의 왼쪽위를 (0, 0)으로 잡는 것이 아니고

수학에서 x,y 그래프를 그리듯이, 왼쪽아래를 (0, 0) 기준점으로 잡아서 좌표를 설정한다.

아직 배울것이 너무 많다.
Posted by Yria

댓글을 달아 주세요

프로그래밍/C/C++2010.01.13 20:57

#include 
#include 

void main(){

	int i, j;
	printf("2~200 사이에 있는 모든 소수 출력\n");

	for (i=2; i<=200; ++i){
		for(j=(int)sqrt((double)i); j<=i; ++j){
			if(i==j || i==2 || i==3){
				printf("%d, ",i);
			}
			if(i%j==0){
				break;
			}

		}
	}
	printf("\n"); 
}


코드 자체는 별거 없다. for문이 두개가 돌면서 i는 소수인지 아닌지 확인하려는 숫자, j는 그걸 확인하기 위한 값이다.

소수라 함은 자기자신으로만 나누어 떨어지는 수를 말하며 그렇기 때문에 소수인지 아닌지 확인하는 j값이 i값과 같은 크기일때까지만 커지면 된다.

또한 자기자신외에 다른 숫자로 나누었을시 나누어 떨어지면 이 숫자는 소수가 아니기 때문에 더이상 j값을 증가시킬 필요가 없다.

그런데 여기서, 숫자는 제곱근을 기준으로 대칭형의 곱셈형식으로 나타낼 수 있다.

예를 들어 12의 경우 1*12, 2*6, 3*4, 4*3, 6*2, 12*1 같이 대칭형을 이룸을 알 수 있다.

그렇기 때문에 원하는 숫자의 제곱근까지 확인하면, 그 이상은 확인하지 않아도 알 수 있기 때문에 제곱근함수(sqrt)를 사용하여 더욱 단축할 수 있다.

소스에서는 제곱근부터 시작하여 소수인지 확인하려는 숫자 i와 그걸 확인하기 위한 숫자 j가 같을때 출력하도록 짜보았다.

시간 복잡도 상으로는 O(n^2) 가 되겠지만 실제로 두번째 for는 검사하려는 숫자의 제곱근부터 검사하기 때문에 평군시간복잡도를 구하면 O(n^2)보다 떨어질것이라 추측한다.



이 외에도 에라토스테네스의 체를 이용하는 방법이 있다.

  1. 2부터 소수를 구하고자 하는 구간의 모든 수를 나열한다. 그림에서 회색 사각형으로 두른 수들이 여기에 해당한다.
  2. 2는 소수이므로 오른쪽에 2를 쓴다.
  3. 자기 자신을 제외한 2의 배수를 모두 지운다.
  4. 남아있는 수 가운데 3은 소수이므로 오른쪽에 3을 쓴다.
  5. 자기 자신을 제외한 3의 배수를 모두 지운다.
  6. 남아있는 수 가운데 5는 소수이므로 오른쪽에 5를 쓴다.
  7. 자기 자신을 제외한 5의 배수를 모두 지운다.
  8. 위의 과정을 반복하면 구하는 구간의 모든 소수가 남는다.

출처 : 위키백과


이를 이용하면 더욱 빨리 구할 수 있다.

웹에서 다른사람이 만든 코드를 인용하겠다.

#void eratosthenes(int *iPrimes, long long *lSum)
{
    bool *bNoPrime = new bool[PRIMES];
    lSum = 0;
    iPrimes = 0;
    int iMaxCompare = (int)sqrt((double)PRIMES);

    memset(bNoPrime, 0, sizeof(bool)*PRIMES);

    int i;
    for (i=2; i<=iMaxCompare; i++)
    {
        if (!bNoPrime[i])
        {
            iPrimes++;
            lSum += i;
        }

        for (int j=i*i; j<PRIMES; j+=i) bNoPrime[j] = true;
    }

    for (i=iMaxCompare+1; i<PRIMES; i++)
    {
        if (!bNoPrime[i])
        {
            iPrimes++;
            lSum += i;
        }
    }

    delete bNoPrime;
}
Posted by Yria

댓글을 달아 주세요