■ XML: A fundamental concept
XML(eXtensible Markup Language): 확장 가능한 마크업 언어(Markup Language)라고 한다.
Markup Language: 문서의 논리적 구조와 배치 양식에 대한 정보를 표현하는 언어라고 한다.
- 이러한 정보들은 Meta Language로 구성되어진다.
Meta Language: 메타 데이터(Meta Data)로 구성된 언어라고 볼 수 있음
- Meta Data: 속성 정보라고도 함 (일정한 규칙 따름)
- 규칙을 알면 해당 데이터에 효율적으로 접근할 수 있음
XML - Markup Language - Meta Language
즉 속성 정보를 논리적 구조로 배치한 언어를 Markup Language라고 하며, 이것을 확장가능하도록 한 언어를 XML이라고 정의할 수 있다.
XML을 사용해야 하는 이유는 다음 사이트에 잘 나와 있다.
http://office.microsoft.com/ko-kr/training/RZ001130477.aspx?section=2
현재 우리는 HTML(Hypertext Markup Language)로 짜여진 문서를 웹브라우저를 통해 보고 있다. 현재 보고 있는 글도 HTML로 짜여져서 각종 웹브라우저에서 볼 수 있는 것이다. 즉 하나의 표준으로 다른 기기간 동일한 화면을 표현하는 것이다.
표준은 다른 기기 다른 프로그램에서 동일한 입력과 출력을 가지는 것을 목표로 한다. 즉 XML 또한 표준이다. 오늘날 기업에서는 다양한 프로그램, 데이터베이스에서 수 많은 데이터를 받고 처리 한다. 이 과정에서 시스템간 기기간 다른 데이터 형식으로 인해 데이터의 관리가 어려워 졌다. 이러한 점은 XML이 등장하게 된 배경 중 하나이다.
즉 우리는 데이터의 입출력을 하나의 표준을 사용함으로써 다른 프로그램과 시스템간 동일한 자료 구조를 공유할 수 있다. 이와 같은 특징은 효과적인 데이터 관리를 할 수 있는 장점을 가지게 된다.
XML의 원래 용도
- World Wide Web를 통해 데이터를 전송하기 위해(www)
XML의 기본구성
- XML 데이터 파일, XML 스키마 및 XML 변환
■ OpenGL: 2D Scatter Plot(Demo Video)
흠냐 우여곡절 끝에 간단한 2D Scatter Plot 그래프를 완성하였다. 미흡하지만 만족한다.
다차원의 패턴을 저차원으로 매핑하는 결과들은 대부분 2-3 차원으로 축소된다. 때문에 2-3차원 scatter, line, bar 그래프가 필요하다. 예전에는 오픈된 라이브러리를 가져다 쓰니 내 맘에 맞게 못고치는 부분이 있었다. 초심으로 돌아가 하나씩 만들어가고자 한다.
- font : FreeType library
- using vertex array for drawing geometrics
- useing gluPerspective()
- based on MFC(MDI)
Sample Data: Result of SAMANN(Sammon Artificial Neural Network): not De-Normalized Data
화질이 좀 안좋게 나오네... 저렇게 나쁘지 않음..
'OpenGL' 카테고리의 다른 글
OpenGL: Tutorial on using FreeType Fonts in OpenGL (1) | 2014.05.21 |
---|---|
OpenGL: Modern OpenGL Tutorial Text Rendering 02 (0) | 2014.05.20 |
OpenGL: Very Simple Textured Text (1) | 2014.05.18 |
Visual Studio: Setting FreeType Library (0) | 2014.05.16 |
OpenGL: Modern OpenGL Tutorial Text Rendering 01 (0) | 2014.05.15 |
■ Scaling a range of numbers with a known min and max value
Let's say you want to scale a range [min,max]
to [a,b]
. You're looking for a (continuous) function that satisfies
f(min) = a
f(max) = b
In your case, a
would be 1 and b
would be 30, but let's start with something simpler and try to map [min,max]
into the range [0,1]
.
Putting min
into a function and getting out 0 could be accomplished with
f(x) = x - min ===> f(min) = min - min = 0
So that's almost what we want. But putting in max
would give us max - min
when we actually want 1. So we'll have to scale it:
x - min max - min
f(x) = --------- ===> f(min) = 0; f(max) = --------- = 1
max - min max - min
which is what we want. So we need to do a translation and a scaling. Now if instead we want to get arbitrary values of a
and b
, we need something a little more complicated:
(b-a)(x - min)
f(x) = -------------- + a
max - min
You can verify that putting in min
for x
now gives a
, and putting in max
gives b
.
You might also notice that (b-a)/(max-min)
is a scaling factor between the size of the new range and the size of the original range. So really we are first translating x
by -min
, scaling it to the correct factor, and then translating it back up to the new minimum value of a
.
Hope this helps.
http://stackoverflow.com/questions/5294955/how-to-scale-down-a-range-of-numbers-with-a-known-min-and-max-value
'Tips' 카테고리의 다른 글
Generate distinctly different RGB colors in graphs (0) | 2014.07.29 |
---|
■ OpenGL: Tutorial on using FreeType Fonts in OpenGL[1]
네헤 라는 곳!!! 여기에 좋은 글들이 많네 .. 자 이 내용을 중심으로 이 사람은 어떻게 FreeType library를 활용했는지 보자.
1. MSVC(Microsoft Visual C++) 새 프로젝트 생성
- FreeType Library - Include folder 포함
- 라이브러리 설정(OpenGL.dlls, FreeType.dlls)
2. FreeType 설정 및 빌드를 위한 파일 복사
참고 사이트 하단에 가면 "DOWNLOAD visual C++ code for This Lesson"
- 클릭해서 다운로드
- 폴더 내에 "freetype.cpp" and "freetype.h" 파일을 생성한 프로젝트에 복사
- *.dll 파일도 생성한 프로젝트에 복사
3. FreeType 헤더파일 분석
-#include <xxxx.h> 파일들은 핸들링 및 보다 쉬운 디버깅을 위해 선언
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | #ifndef FREE_NEHE_H #define FREE_NEHE_H // FreeType Headers #include <ft2build.h> #include <freetype/freetype.h> #include <freetype/ftglyph.h> #include <freetype/ftoutln.h> #include <freetype/fttrigon.h> // OpenGL Headers #include <windows.h> // (The GL Headers Need It) #include <GL/gl.h> #include <GL/glu.h> // Some STL Headers #include <vector> #include <string> // Using The STL Exception Library Increases The // Chances That Someone Else Using Our Code Will Correctly // Catch Any Exceptions That We Throw. #include <stdexcept> // MSVC Will Spit Out All Sorts Of Useless Warnings If // You Create Vectors Of Strings, This Pragma Gets Rid Of Them. #pragma warning(disable: 4786) |
- WGL(Window OpenGL)
- 폰트 저장을 위해 구조체 선언 및 네임스페이스로 욘속이 freetype 이라고 이름 지어줌 낭낭
- 머 13장에서 배웠던 내용이라는데 난 그냥 이글만 봐서... 느낌상 위 구조체를 사용함으로써 하나의 명령 glCAllLists 를 사용하여 문자열을 출력할 수 있는 좋은 능력을 보여준다고 하넹 +_+ 흣(대단한 녀석이군)
- 128ASCII 코드를 사용하기 때문에 128개의 텍스쳐를 만들어야 함. 마지막 비트는 폰트의 픽셀 높이 정보라는군.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | ///Wrap everything in a namespace, that we can use common ///function names like "print" without worrying about ///overlapping with anyone else's code. namespace freetype { //Inside of this namespace, give ourselves the ability //to write just "vector" instead of "std::vector" using std::vector; //Ditto for string. using std::string; //This holds all of the information related to any //freetype font that we want to create. struct font_data { float h; ///< Holds the height of the font. GLuint * textures; ///< Holds the texture id's GLuint list_base; ///< Holds the first display list id //The init function will create a font of //of the height h from the file fname. void init(const char * fname, unsigned int h); //Free all the resources assosiated with the font. void clean(); }; //The flagship function of the library - this thing will print //out text at window coordinates x,y, using the font ft_font. //The current modelview matrix will also be applied to the text. void print(const font_data &ft_font, float x, float y, const char *fmt, ...) ; } #endif |
마지막으로 우리는 문자열을 출력할 수 있는 프로토타입(prototype)가 필요하다고 하는군. 위 코드 마지막 줄에 프린트 욘속을 말함.
4. FreeType.cpp 파일 분석
- 각 문자를 찍기 위해 텍스쳐를 사용함.
- OpenGL 텍스쳐들은 2의 제곱을 가지는 차원수를 가져야 한다고 함.
1 2 3 4 5 6 7 8 9 | // This Function Gets The First Power Of 2 >= The // Int That We Pass It. inline int next_p2 (int a ) { int rval=1; // rval<<=1 Is A Prettier Way Of Writing rval*=2; while(rval<a) rval<<=1; return rval; } |
해서 위와 같은 소스로 2제곱을 해서 리턴함
다음 함수가 제일 중요함 각 폰트의 Glyph 정보를 읽고 bitmap 저장
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | // Create A Display List Corresponding To The Given Character. void make_dlist ( FT_Face face, char ch, GLuint list_base, GLuint * tex_base ) { // The First Thing We Do Is Get FreeType To Render Our Character // Into A Bitmap. This Actually Requires A Couple Of FreeType Commands: // Load The Glyph For Our Character. if(FT_Load_Glyph( face, FT_Get_Char_Index( face, ch ), FT_LOAD_DEFAULT )) throw std::runtime_error("FT_Load_Glyph failed"); // Move The Face's Glyph Into A Glyph Object. FT_Glyph glyph; if(FT_Get_Glyph( face->glyph, &glyph )) throw std::runtime_error("FT_Get_Glyph failed"); // Convert The Glyph To A Bitmap. FT_Glyph_To_Bitmap( &glyph, ft_render_mode_normal, 0, 1 ); FT_BitmapGlyph bitmap_glyph = (FT_BitmapGlyph)glyph; // This Reference Will Make Accessing The Bitmap Easier. FT_Bitmap& bitmap=bitmap_glyph->bitmap; |
이제 OpenGL Texture를 위한 legal source를 만들기 위해 빈공간에 저장된 bitmap 정보를 저장함
- OpenGL에서 bitmap는 픽셀당 8bit 정보 저장
- grays를 저장할 수 있음(anti-aliased text를 만드는데 필요한 정보임)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | // Use Our Helper Function To Get The Widths Of // The Bitmap Data That We Will Need In Order To Create // Our Texture. int width = next_p2( bitmap.width ); int height = next_p2( bitmap.rows ); // Allocate Memory For The Texture Data. GLubyte* expanded_data = new GLubyte[ 2 * width * height]; // Here We Fill In The Data For The Expanded Bitmap. // Notice That We Are Using A Two Channel Bitmap (One For // Channel Luminosity And One For Alpha), But We Assign // Both Luminosity And Alpha To The Value That We // Find In The FreeType Bitmap. // We Use The ?: Operator To Say That Value Which We Use // Will Be 0 If We Are In The Padding Zone, And Whatever // Is The FreeType Bitmap Otherwise. for(int j=0; j <height;j++) { for(int i=0; i < width; i++){ expanded_data[2*(i+j*width)]= expanded_data[2*(i+j*width)+1] = (i>=bitmap.width || j>=bitmap.rows) ? 0 : bitmap.buffer[i + bitmap.width*j]; } } |
위 작업 후 OpenGL Texture 를 만들어야 함.
- 알파 값을 통해 투명도 설정 가능하게 해놨음
1 2 3 4 5 6 7 8 9 10 11 12 13 | // Now We Just Setup Some Texture Parameters. glBindTexture( GL_TEXTURE_2D, tex_base[ch]); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); // Here We Actually Create The Texture Itself, Notice // That We Are Using GL_LUMINANCE_ALPHA To Indicate That // We Are Using 2 Channel Data. glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, expanded_data ); // With The Texture Created, We Don't Need The Expanded Data Anymore. delete [] expanded_data; |
이제 우리는 텍스트를 그리기 위해 텍스쳐가 맵핑된 quads를 사용할 거얌!
- quads를 이용함으로써 장점: 회전, 크기 변경, 문자열 사용 가능, 색상 적용 가능
흣 +_+
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 | // Now We Create The Display List glNewList(list_base+ch,GL_COMPILE); glBindTexture(GL_TEXTURE_2D,tex_base[ch]); glPushMatrix(); // First We Need To Move Over A Little So That // The Character Has The Right Amount Of Space // Between It And The One Before It. glTranslatef(bitmap_glyph->left,0,0); // Now We Move Down A Little In The Case That The // Bitmap Extends Past The Bottom Of The Line // This Is Only True For Characters Like 'g' Or 'y'. glTranslatef(0,bitmap_glyph->top-bitmap.rows,0); // Now We Need To Account For The Fact That Many Of // Our Textures Are Filled With Empty Padding Space. // We Figure What Portion Of The Texture Is Used By // The Actual Character And Store That Information In // The x And y Variables, Then When We Draw The // Quad, We Will Only Reference The Parts Of The Texture // That Contains The Character Itself. float x=(float)bitmap.width / (float)width, y=(float)bitmap.rows / (float)height; // Here We Draw The Texturemapped Quads. // The Bitmap That We Got From FreeType Was Not // Oriented Quite Like We Would Like It To Be, // But We Link The Texture To The Quad // In Such A Way That The Result Will Be Properly Aligned. glBegin(GL_QUADS); glTexCoord2d(0,0); glVertex2f(0,bitmap.rows); glTexCoord2d(0,y); glVertex2f(0,0); glTexCoord2d(x,y); glVertex2f(bitmap.width,0); glTexCoord2d(x,0); glVertex2f(bitmap.width,bitmap.rows); glEnd(); glPopMatrix(); glTranslatef(face->glyph->advance.x >> 6 ,0,0); // Increment The Raster Position As If We Were A Bitmap Font. // (Only Needed If You Want To Calculate Text Length) // glBitmap(0,0,0,0,face->glyph->advance.x >> 6,0,NULL); // Finish The Display List glEndList(); } |
다음 init함수는 FreeType Font 라이브러리를 초기화 하고 주어진 폰트 파일을 읽은 다음 폰트 사이즈를 설정한 후 해당 갯수의 텍스쳐를 생성하여 정보를 저장하는 작업
준비 작업임
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | void font_data::init(const char * fname, unsigned int h) { // Allocate Some Memory To Store The Texture Ids. textures = new GLuint[128]; this->h=h; // Create And Initilize A FreeType Font Library. FT_Library library; if (FT_Init_FreeType( &library )) throw std::runtime_error("FT_Init_FreeType failed"); // The Object In Which FreeType Holds Information On A Given // Font Is Called A "face". FT_Face face; // This Is Where We Load In The Font Information From The File. // Of All The Places Where The Code Might Die, This Is The Most Likely, // As FT_New_Face Will Fail If The Font File Does Not Exist Or Is Somehow Broken. if (FT_New_Face( library, fname, 0, &face )) throw std::runtime_error("FT_New_Face failed (there is probably a problem with your font file)"); // For Some Twisted Reason, FreeType Measures Font Size // In Terms Of 1/64ths Of Pixels. Thus, To Make A Font // h Pixels High, We Need To Request A Size Of h*64. // (h << 6 Is Just A Prettier Way Of Writing h*64) FT_Set_Char_Size( face, h << 6, h << 6, 96, 96); // Here We Ask OpenGL To Allocate Resources For // All The Textures And Display Lists Which We // Are About To Create. list_base=glGenLists(128); glGenTextures( 128, textures ); // This Is Where We Actually Create Each Of The Fonts Display Lists. for(unsigned char i=0;i<128;i++) make_dlist(face,i,list_base,textures); // We Don't Need The Face Information Now That The Display // Lists Have Been Created, So We Free The Assosiated Resources. FT_Done_Face(face); // Ditto For The Font Library. FT_Done_FreeType(library); } |
폰트와 관련된 텍스쳐와 displaylist를 초기화 시키는 함수
1 2 3 4 5 | void font_data::clean() { glDeleteLists(list_base,128); glDeleteTextures(128,textures); delete [] textures; } |
자원을 썼으니 반납하시오!!!!
윈도우 화면 투영 함수
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | // A Fairly Straightforward Function That Pushes // A Projection Matrix That Will Make Object World // Coordinates Identical To Window Coordinates. inline void pushScreenCoordinateMatrix() { glPushAttrib(GL_TRANSFORM_BIT); GLint viewport[4]; glGetIntegerv(GL_VIEWPORT, viewport); glMatrixMode(GL_PROJECTION); glPushMatrix(); glLoadIdentity(); gluOrtho2D(viewport[0],viewport[2],viewport[1],viewport[3]); glPopAttrib(); } // Pops The Projection Matrix Without Changing The Current // MatrixMode. inline void pop_projection_matrix() { glPushAttrib(GL_TRANSFORM_BIT); glMatrixMode(GL_PROJECTION); glPopMatrix(); glPopAttrib(); } |
폰트 출력함수
출력함수는 lesson13과 매우 흡사하나 두가지 중요한 점이 다르다.
- 비트멥들 대신 2채널의 텍스쳐를 사용하기 위해 OpenGL 활성화 flags 설정
- 새로운 라인을 다루기 위해 추가적인 기능을 넣었음.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 | ///Much like Nehe's glPrint function, but modified to work ///with freetype fonts. void print(const font_data &ft_font, float x, float y, const char *fmt, ...) { // We want a coordinate system where things coresponding to window pixels. pushScreenCoordinateMatrix(); GLuint font=ft_font.list_base; float h=ft_font.h/.63f; //We make the height about 1.5* that of char text[256]; // Holds Our String va_list ap; // Pointer To List Of Arguments if (fmt == NULL) // If There's No Text *text=0; // Do Nothing else { va_start(ap, fmt); // Parses The String For Variables vsprintf(text, fmt, ap); // And Converts Symbols To Actual Numbers va_end(ap); // Results Are Stored In Text } //Here is some code to split the text that we have been //given into a set of lines. //This could be made much neater by using //a regular expression library such as the one avliable from //boost.org (I've only done it out by hand to avoid complicating //this tutorial with unnecessary library dependencies). const char *start_line=text; vector<string> lines; for(const char *c=text;*c;c++) { if(*c=='\n') { string line; for(const char *n=start_line;n<c;n++) line.append(1,*n); lines.push_back(line); start_line=c+1; } } /* if(start_line) { string line; for(const char *n=start_line;n<c;n++) line.append(1,*n); lines.push_back(line); } */ glPushAttrib(GL_LIST_BIT | GL_CURRENT_BIT | GL_ENABLE_BIT | GL_TRANSFORM_BIT); glMatrixMode(GL_MODELVIEW); glDisable(GL_LIGHTING); glEnable(GL_TEXTURE_2D); glDisable(GL_DEPTH_TEST); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glListBase(font); float modelview_matrix[16]; glGetFloatv(GL_MODELVIEW_MATRIX, modelview_matrix); //This is where the text display actually happens. //For each line of text we reset the modelview matrix //so that the line's text will start in the correct position. //Notice that we need to reset the matrix, rather than just translating //down by h. This is because when each character is //draw it modifies the current matrix so that the next character //will be drawn immediatly after it. for(int i=0;i<lines.size();i++) { glPushMatrix(); glLoadIdentity(); glTranslatef(x,y-h*i,0); glMultMatrixf(modelview_matrix); // The commented out raster position stuff can be useful if you need to // know the length of the text that you are creating. // If you decide to use it make sure to also uncomment the glBitmap command // in make_dlist(). // glRasterPos2f(0,0); glCallLists(lines[i].length(), GL_UNSIGNED_BYTE, lines[i].c_str()); // float rpos[4]; // glGetFloatv(GL_CURRENT_RASTER_POSITION ,rpos); // float len=x-rpos[0]; glPopMatrix(); } glPopAttrib(); pop_projection_matrix(); } |
5. 사용방법
step 1: 헤더파일 선언
1 | #include "freetype.h" // Header for our little font library. |
step 2: 전역 font_data object 생성
1 2 | // This holds all the information for the font that we are going to create. freetype::font_data our_font; |
step 3: 폰트 자원의 메모리 할당 및 해제
1 | our_font.init("test.TTF", 16); //Build the freetype font |
종료 함수에 삽입
1 | our_font.clean(); |
step 4: 폰트 드로웅~~~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 | int DrawGLScene(GLvoid) // Here's Where We Do All The Drawing { glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); // Clear Screen And Depth Buffer glLoadIdentity(); // Reset The Current Modelview Matrix glTranslatef(0.0f,0.0f,-1.0f); // Move One Unit Into The Screen // Blue text glColor3ub(0,0,0xff); // Position the WGL Text On The Screen glRasterPos2f(-0.40f, 0.35f); glPrint("Active WGL Bitmap Text With NeHe - %7.2f", cnt1); // Print GL Text To The Screen // Here We Print Some Text Using Our Freetype Font // The Only Really Important Command Is The Actual Print() Call, // But For The Sake Of Making The Results A Bit More Interesting // I Have Put In Some Code To Rotate And Scale The Text. // Red Text glColor3ub(0xff,0,0); glPushMatrix(); glLoadIdentity(); glRotatef(cnt1,0,0,1); glScalef(1,.8+.3*cos(cnt1/5),1); glTranslatef(-180,0,0); freetype::print(our_font, 320, 200, "Active FreeType Text - %7.2f", cnt1); glPopMatrix(); // Uncomment This To Test Out Print's Ability To Handle Newlines. // freetype::print(our_font, 320, 200, "Here\nthere\nbe\n\nnewlines\n.", cnt1); cnt1+=0.051f; // Increase The First Counter cnt2+=0.005f; // Increase The First Counter return TRUE; // Everything Went OK } |
step 5: 예외처리 함수 삽입(+____+;;;)
1 2 3 4 | MSG msg; // Windows Message Structure BOOL done=FALSE; // Bool Variable To Exit Loop try { |
1 2 3 4 5 6 7 8 9 10 | // Shutdown KillGLWindow(); // Kill The Window // Catch Any Exceptions That Were Thrown } catch (std::exception &e) { MessageBox(NULL,e.what(),"CAUGHT AN EXCEPTION",MB_OK | MB_ICONINFORMATION); } return (msg.wParam); // Exit The Program } |
Now if we ever hit an exception, we will get a little message box telling us what happened. Note that exception handling can slow down your code, so when you are compiling a release version of your program, you may want to go to Project->Settings->C/C++, switch to the "C++ Language" category, and turn off exception handling.
So that's it! Compile the program and you should see some nice FreeType rendered text moving around underneath the original bitmapped text from lesson 13.
마지막 글
약간의 버그가 있다고 하넹
http://nehe.gamedev.net/data/lessons/http://www.cs.northwestern.edu/~sco590/fonts_tutorial.html
위 사이트 가서 버그를 샤샤삭~~~
뚜둥 실행화면
자 이렇게 나온단다.
나는 MFC 기반의 프로젝트를 만들고 있기 때문에 아마 좀 다르게 나오겠지 적용방법도 다르고 한번 해보자구웃!
역시나 제대로 출력이 안되넹
glPrint("FreeType using multi texture!!"); 요렇게 해서 찍어 봤지..
뒤에 g라는 욘속이 들어 가네 왜 그러징.. ㅋㅋ
흣... 이거 제대로 찍을라면 소스를 좀 수정해야 함.
아놔운서!!!(-_ㅡ;;)
수정해야 하는 소스는 다음과 같다.
위치: FreeType.cpp : void print(const font_data &ft_font, float x, float y, const char *fmt, ...)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | const char *start_line=text; vector<string> lines; for(const char *c=text;*c;c++) { if(*c=='\n') { string line; for(const char *n=start_line;n<c;n++) line.append(1,*n); lines.push_back(line); start_line=c+1; } } if(start_line) { string line; for(const char *n=start_line;n<c;n++) line.append(1,*n); lines.push_back(line); } |
위와 같이 되어 있는데.. 우선 데이터가 잘 넘어오는지 다 확인하고 나중에 lines 의 값을 찍어 보니 맹탕 알고 보니 위 소스를 보면 아하하고 아놔운서를 불렀더랬지
- 위 소스의 의도는 여러 줄을 찍는 것을 가능하게 해 주는 소스이다. 즉 넘거 받은 문자열 중에 개행문자를 만나면 줄을 바꾸고 저장.. 요런식으로 여러 줄을 찍을라고 한 작업이다.
1 2 3 4 5 6 7 8 | const char *start_line=text; vector<string> lines; string line; for (const char *c = text; *c; c++) { if (*c != '\n') line.append(1, *c); }lines.push_back(line); |
수정된 소스라오. 난 한줄만 찍어도 충분하다.
본인은 폰트를 찍어서 회전시켜야 하는 일이 생겼다. 대부분의 그래픽 응용에서 폰트에 회전을 줄 필요는 없는 듯 보였다. 그래서 몇일 작업했더랬지.. 그래서 결국에는 회전 성공.. 하 지금은 텍스쳐를 여러개 만들어서 하는 방법이다. 이 방법보다 좋은것은 텍스쳐 아틀라스로 하나의 텍스쳐에서 좌표를 가져와 버텍스 매핑하는 방법이 되겠지 우선 여기까지만 해도 괜찮을듯 하다. 여러번해보고 버그 생기면 다시 고쳐야겠지 아뵤 힘내세요.
[1]http://nehe.gamedev.net/tutorial/freetype_fonts_in_opengl/24001/
'OpenGL' 카테고리의 다른 글
OpenGL: 2D Scatter Plot(Demo Video) (1) | 2014.05.25 |
---|---|
OpenGL: Modern OpenGL Tutorial Text Rendering 02 (0) | 2014.05.20 |
OpenGL: Very Simple Textured Text (1) | 2014.05.18 |
Visual Studio: Setting FreeType Library (0) | 2014.05.16 |
OpenGL: Modern OpenGL Tutorial Text Rendering 01 (0) | 2014.05.15 |
■ OpenGL: Modern OpenGL Tutorial Text Rendering 02[1]
FreeType 라이브러리로 폰트를 그리는 두번째 파트
1. Introduction
이전 파트에서 우리는 각 폰트를 그리기 위한 텍스처를 만들어 그래픽 카드에 옵로딩 하였다.
- 요러한 방식이 비효율적이라고 한다.
- 새롭게 계속 텍스쳐를 그래픽 카드에 올리는 것 보다는 전체 폰트를 그래픽 카드에 옵로드 했다가 쓰는 것이 더 효율적이라고 함.
method 1:
- 간단한 방법으로 각 폰트에 대한 많은 텍스처를 가지는 것.
- 즉 각 폰트에 대한 텍스처를 가지고 있다가 quad를 그릴때 텍스처만 바꾸어 주는 방식으로 간다.
- 하지만 이와 같은 방법은 여러 폰트를 그릴때 엄청나게 많이 반복해서 quad를 그려줘야 함
method 2:
- 덜 복잡한 방법은 왕 큰 하나의 텍스처에 모든 폰트의 값을 저장하고 있는 거지,
- 그래서 각 폰트에 대한 텍스처 좌표와 quad의 버텍스를 매핑시키는 거야
- 이 방법에서는 " texture atlas" 개념을 알고 있어야 한다고 함
texture atlas: 텍스처 아틀라스(atlas:지도책)
여러 이미지를 하나의 파일에 모아놓은 텍스처를 Atlas Texture라고하며, 일반적으로 툴없이
포토샵으로 하게 될 경우 수정 및 텍스처 공간활용, 좌표 추출 등에서 많은 애를 먹게 된다.
2. texture atlas만들기
텍스처 아틀라스는 여러 꼬맹이 이미지들이 하나의 패키지처럼 모여 있는 엄마 텍스처라고 생각하면 됨
- 꼬맹이 이미지들이 동일한 사이즈면 만들기 쉽다넹.
- 하지만 뚜둥 폰트 사이즈는 각각 달라!!!
- 텍스처 아틀라스를 만드는 많은 방법이 있지만 여기서는 간단한 방법을 사용한다고 함(휴 *_*)
- 텍스처 아틀라스를 만들기 전에 미리 폰트의 가로 세로 사이즈 등을 미리 알고 있어야 함
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | FT_GlyphSlot g = face->glyph; int w = 0; int h = 0; for(int i = 32; i < 128; i++) { if(FT_Load_Char(face, i, FT_LOAD_RENDER)) { fprintf(stderr, "Loading character %c failed!\n", i); continue; } w += g->bitmap.width; h = std::max(h, g->bitmap.rows); /* you might as well save this value as it is needed later on */ int atlas_width = w; } |
텍스처 아틀라스를 만드는 코드당. FT_GlyphSlot g 변수를 통해 한 폰트에 대한 정보를 가져옴 이 폰트의 사이즈를 미리 알고 ASCII 코드 32번째 부터 쭈우우욱 값을 읽어드림
- 또한 g에 대한 정보로 아틀라스 사이즈 w, h를 구함
다음으로는 이 아틀라스 사이즈를 가지고 하나의 빈 텍스처를 만듬(하나씩 찍기 위함이지)
1 2 3 4 5 6 7 | GLuint tex; glActiveTexture(GL_TEXTURE0); glGenTextures(1, &tex); glBindTexture(GL_TEXTURE_2D, tex); glPixelStorei(GL_UNPACK_ALIGNMENT, 1); glTexImage2D(GL_TEXTURE_2D, 0, GL_ALPHA, w, h, 0, GL_ALPHA, GL_UNSIGNED_BYTE, 0); |
이제 텍스처 아틀라스에 glyph images를 붙여 넣은 준비가 됬고 우리는 glTexSubImage2D()함수로 글립 이미지를 간단하게 텍스처 아틀라스에 넣을 수 있음등!!
1 2 3 4 5 6 7 8 9 10 | int x = 0; for(int i = 32; i < 128; i++) { if(FT_Load_Char(face, i, FT_LOAD_RENDER)) continue; glTexSubImage2D(GL_TEXTURE_2D, 0, x, 0, g->bitmap.width, g->bitmap.rows, GL_ALPHA, GL_UNSIGNED_BYTE, g->bitmap.buffer); x += g->bitmap.width; } |
3. Caching glyph metrics and texture offsets
자 그럼 폰트를 아틀라스 텍스쳐에서 어떻게 가져와야 함!!!
정확한 위치에 폰트를 가지고 올라면 좌표(x,y) 그리고 x offset 그러니깐 몇행인지 그리고 폰트의 정보가 필요함
이 정보를 기억하기 위해 다음과 같은 구조체를 만듬, 이 구조체에 위 필요한 정보를 기억하여 캐쉬메모리로 사용해서 필요할때 마다 찾아 갈꺼얌
1 2 3 4 5 6 7 8 9 10 11 12 | struct character_info { float ax; // advance.x float ay; // advance.y float bw; // bitmap.width; float bh; // bitmap.rows; float bl; // bitmap_left; float bt; // bitmap_top; float tx; // x offset of glyph in texture coordinates } c[128]; |
텍스처에 glyph images를 넣는 루프에서 다음과 같이 수행해서 구조체에 정보를 쏘옥~
1 2 3 4 5 6 7 8 9 10 | c[*p].ax = g->advance.x >> 6; c[*p].ay = g->advance.y >> 6; c[*p].bw = g->bitmap.width; c[*p].bh = g->bitmap.rows; c[*p].bl = g->bitmap_left; c[*p].bt = g->bitmap_top; c[*p].tx = (float)x / w; |
4. Rendering lines of text using the atlas
실제 텍스쳐 그리는 소스는 다음과 같다구웃!
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 | void render_text(const char *text, atlas * a, float x, float y, float sx, float sy) { const uint8_t *p; /* Use the texture containing the atlas */ glBindTexture(GL_TEXTURE_2D, a->tex); glUniform1i(uniform_tex, 0); /* Set up the VBO for our vertex data */ glEnableVertexAttribArray(attribute_coord); glBindBuffer(GL_ARRAY_BUFFER, vbo); glVertexAttribPointer(attribute_coord, 4, GL_FLOAT, GL_FALSE, 0, 0); point coords[6 * strlen(text)]; int c = 0; /* Loop through all characters */ for (p = (const uint8_t *)text; *p; p++) { /* Calculate the vertex and texture coordinates */ float x2 = x + a->c[*p].bl * sx; float y2 = -y - a->c[*p].bt * sy; float w = a->c[*p].bw * sx; float h = a->c[*p].bh * sy; /* Advance the cursor to the start of the next character */ x += a->c[*p].ax * sx; y += a->c[*p].ay * sy; /* Skip glyphs that have no pixels */ if (!w || !h) continue; coords[c++] = (point) { x2, -y2, a->c[*p].tx, a->c[*p].ty}; coords[c++] = (point) { x2 + w, -y2, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty}; coords[c++] = (point) { x2, -y2 - h, a->c[*p].tx, a->c[*p].ty + a->c[*p].bh / a->h}; coords[c++] = (point) { x2 + w, -y2, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty}; coords[c++] = (point) { x2, -y2 - h, a->c[*p].tx, a->c[*p].ty + a->c[*p].bh / a->h}; coords[c++] = (point) { x2 + w, -y2 - h, a->c[*p].tx + a->c[*p].bw / a->w, a->c[*p].ty + a->c[*p].bh / a->h}; } /* Draw all the character on the screen in one go */ glBufferData(GL_ARRAY_BUFFER, sizeof coords, coords, GL_DYNAMIC_DRAW); glDrawArrays(GL_TRIANGLES, 0, c); glDisableVertexAttribArray(attribute_coord); } |
................\wikibooks-opengl-modern-tutorials\text02_atlas
위 폴더에서 text.cpp 파일을 실행시키면 되는데
point coords[6 * strlen(text)]; 아이에서 배열 상수식 선언 에러 나올꺼야. 또
coords[c++] 요라인도
고칠라면 point coords 배열을 동적배열로 사용하고
구조체 접근 또한 coords[c].x = x2; 요러한 형식으로 진행해야 하지
최종 실행 결과
2번째 싸이트 방문해 보면 텍스쳐 아틀라스를 만들어 사용하는 것을 확인할 수 있다.
3번째 싸이트 가면 텍스쳐를 여러개 만들어서 사용하는 방법이다.
2번째 싸이트 보니 하... 그래서 3번째 싸이트 내용을 가지고 또 연습해 보자.
[1] http://en.wikibooks.org/wiki/OpenGL_Programming/Modern_OpenGL_Tutorial_Text_Rendering_02
[2] http://lazyfoo.net/tutorials/OpenGL/23_freetype_fonts/index.php
[3] http://www.sccs.swarthmore.edu/users/03/sven/freetype_tut/
'OpenGL' 카테고리의 다른 글
OpenGL: 2D Scatter Plot(Demo Video) (1) | 2014.05.25 |
---|---|
OpenGL: Tutorial on using FreeType Fonts in OpenGL (1) | 2014.05.21 |
OpenGL: Very Simple Textured Text (1) | 2014.05.18 |
Visual Studio: Setting FreeType Library (0) | 2014.05.16 |
OpenGL: Modern OpenGL Tutorial Text Rendering 01 (0) | 2014.05.15 |