[7th week] cg_practice_compose_and_render_scene

Download Report

Transcript [7th week] cg_practice_compose_and_render_scene

Compose and render the
scene
Hanyang University
Jungsik Park
모델의 배치
 장면에 모델을 구성하는 기본적인 코드 순서는 다음과
같다.







1. 모델뷰 행렬 초기화(glIdentity)
2. 시점이동(gluLookat 혹은 glTranslate,glRotate)
3. 현재의 모델뷰행렬 스택에 저장(glPushMatrix)
4. 모델 배치(glTranslate,glRotate)
5. 모델 그리기
6. 모델뷰행렬 스택으로부터 모델을 배치해기 이전의
모델뷰행렬 복원 (glPopMatrix)
3~6 반복
Division of Electrical and Computer Engineering, Hanyang University
모델의 배치
void RenderScene(void)
{
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, 1.0f, 1.0f, 1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
gluLookAt(0.0, 200.0, 200.0,
0.0f, 0.0f, 0.0f, 0.0f, 1.0f, 0.0f);
glViewport(0, 0, windowWidth, windowHeight);
void DrawModels(void)
{
// Draw plane that the objects rest on
glColor3f(0.0f, 0.0f, 0.90f); // Blue
glNormal3f(0.0f, 1.0f, 0.0f);
glBegin(GL_QUADS);
glVertex3f(-100.0f, -25.0f, -100.0f);
glVertex3f(-100.0f, -25.0f, 100.0f);
glVertex3f(100.0f, -25.0f, 100.0f);
glVertex3f(100.0f, -25.0f, -100.0f);
glEnd();
// Draw red cube
glColor3f(1.0f, 0.0f, 0.0f);
glutSolidCube(48.0f);
// Draw green sphere
glColor3f(0.0f, 1.0f, 0.0f);
glPushMatrix();
glTranslatef(-60.0f, 0.0f, 0.0f);
glutSolidSphere(25.0f, 50, 50);
glPopMatrix();
// Clear the window with current clearing color
glClear(GL_COLOR_BUFFER_BIT |
GL_DEPTH_BUFFER_BIT);
// Draw yellow cone
glColor3f(1.0f, 1.0f, 0.0f);
glPushMatrix();
glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
glTranslatef(60.0f, 0.0f, -24.0f);
glutSolidCone(25.0f, 50.0f, 50, 50);
glPopMatrix();
// Draw objects in the scene
DrawModels();
// Draw magenta torus
glColor3f(1.0f, 0.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0f, 0.0f, 60.0f);
glutSolidTorus(8.0f, 16.0f, 50, 50);
glPopMatrix();
// Flush drawing commands
glutSwapBuffers();
// Draw cyan octahedron
glColor3f(0.0f, 1.0f, 1.0f);
glPushMatrix();
glTranslatef(0.0f, 0.0f, -60.0f);
glScalef(25.0f, 25.0f, 25.0f);
glutSolidOctahedron();
glPopMatrix();
}
}
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University
복잡한 모델의 렌더링을 위한 빠른
처리 방법
Division of Electrical and Computer Engineering, Hanyang University
OpenGL의 렌더링 방식
 Immediate mode
 Display List
 Vertex array
Division of Electrical and Computer Engineering, Hanyang University
Immediate mode
 glBegin() ~ glEnd() 를 이용하는 방법
 glVertex*() 등의 함수를 한 번 호출할 때마다 하나의
버텍스 정보와 명령을 그래픽 하드웨어에 전달하므로
다음과 같은 단점이 있다.
 함수 호출 횟수가 많다.
 전송 대역폭을 제대로 활용하지 못한다.


• 그래픽 하드웨어에 작은 데이터를 여러 번 보내기
때문
그래픽 하드웨어의 병렬 처리능력을 제대로 활용하지
못한다.
• 기하 요소를 그리기 위한 버텍스 정보가 모일 때까지
기다려야 한다.
적은 수의 폴리곤을 갖는 간단한 모델을 그리는 경우엔
문제가 되지 않지만, 수많은 폴리곤으로 구성되는
복잡한 모델을 그리는 경우엔 상당한 속도 저하 발생.
Division of Electrical and Computer Engineering, Hanyang University
Display List
 렌더링 명령 및 버텍스 정보를 미리 low-level
하드웨어 명령으로 컴파일하여 사용하는 방법.



복잡한 모델을 그리기 위한 일련의 명령과 계산을
컴파일해 둠으로써 렌더링 시 빠르게 일괄 처리할 수
있다.
컴파일된 명령의 재사용이 가능하므로 불필요한 반복
작업을 피할 수 있다.
정적인 모델에 대해서만 적용이 가능하다.
Division of Electrical and Computer Engineering, Hanyang University
Display List
 void glNewList (GLuint list, GLenum mode)
 glNewList() ~ glEndList() 사이의 OpenGL 명령들을 묶
어 컴파일하여 display list로 만든다.
 list : display list의 이름
 mode
 GL_COMPILE : 컴파일만 수행
 GL_COMPILE_AND_EXECUTE : 컴파일 후 한 번 그
리기 수행
Division of Electrical and Computer Engineering, Hanyang University
Display List
 Gluint glGenLists (GLsizei range)
 현재 사용가능한 display list 이름의 범위를 예약하고 시작 값을 리턴
 a = glGenLists(b); 를 실행할 경우

a ~ a+b-1 의 display list 이름이 예약되고 범위 내의 값으로 display
list를 만들어 사용할 수 있다.
 void glDeleteLists (GLuint list, GLsizei range)
 사용중이거나 예약되어 있는 display list 이름을 반납한다.
 glDeleteLists(a, b); 를 실행한 경우

a ~ a+b-1 의 display list 이름을 반납한다.
 void glCallList (GLuint list)
 list를 이름으로 갖는 display list를 실행한다.
 void glCallLists (GLsizei n, GLenum type, const GLvoid *lists)
 display list 이름을 배열로 관리할 경우 여러 개의 display list를 한 번에
실행.
 n : 배열에 담긴 display list의 개수
 type : display list 이름의 타입(GL_UNSIGNED_INT,
GL_UNSIGNED_BYTE)
 lists : 배열의 시작 주소
Division of Electrical and Computer Engineering, Hanyang University
Vertex array
 한 버텍스 단위로 버텍스 정보를 전송하는 immediate
mode와 달리 배열을 이용하여 많은 수의 버텍스
정보를 한 번에 전송한 뒤, 렌더링하는 방법.


데이터 전송 대역폭과 그래픽 하드웨어의 병렬 처리
능력을 활용
정적인 모델 뿐만 아니라 동적인 모델에도 적용 가능
 vertex array 관련 함수에 대해서는 modeling
hierarchy 에서 설명.
Division of Electrical and Computer Engineering, Hanyang University
OBJ 형식 모델 파일의 추출 및
OPENGL에서의 사용
Division of Electrical and Computer Engineering, Hanyang University
Obj format
 Wavefront OBJ (object) files are used by Wavefront's
Advanced Visualizer application to store geometric
objects composed of lines, polygons, and free-form
curves and surfaces.



http://www.fileformat.info/format/wavefrontobj/egff.htm
버텍스 좌표, 법선 벡터, 텍스처 좌표, 삼각형을
구성하는 버텍스의 인덱스, 재질 속성 파일이름(.mtl)
등이 저장됨.
3DS Max, Maya 등의 3D 모델링 툴에서 모델을 만든
후, obj 파일 형식으로 내보내어 OpenGL
어플리케이션에서 로드한다.
Division of Electrical and Computer Engineering, Hanyang University
3ds max에서 obj 파일 추출
Division of Electrical and Computer Engineering, Hanyang University
 재질 속성
Division of Electrical and Computer Engineering, Hanyang University
 색상 변경(diffuse), material editor 상단의 변경된
색상의 원을 클릭하여 모델로 드래그하면 모델 색상이
변경된다.
Division of Electrical and Computer Engineering, Hanyang University
 색상이 변경되었다.
Division of Electrical and Computer Engineering, Hanyang University
 이미지 텍스처 매핑
Division of Electrical and Computer Engineering, Hanyang University
 마찬가지로 변경된 원을 클릭 후 모델에 드래그하면
모델의 재질속성이 변경된다.(Show Standart Map in
Viewport가 활성화되어야 확인 가능)
Division of Electrical and Computer Engineering, Hanyang University
 menu->file->export 혹은 export selected
Division of Electrical and Computer Engineering, Hanyang University
 경로 및 파일 형식(Wavefront Object, *.obj) 선택
Division of Electrical and Computer Engineering, Hanyang University
 재질 속성을
사용하지 않을 경우
 재질속성을 사용할
경우(재질속성은 mtl
파일로 추출)
Division of Electrical and Computer Engineering, Hanyang University
Obj format parser
 nVidia OpenGL SDK의 nvModel 라이브러리 이용
 OpenGL SDK 다운로드
 http://developer.nvidia.com/object/sdk_home.html
Division of Electrical and Computer Engineering, Hanyang University
 visual studio에서 obj parser에 필요한 각 헤더 파일과 라이브러리
파일 폴더 경로를 지정 및 dll 파일 복사

헤더파일 경로





라이브러리 파일 경로




C:\Program Files\NVIDIA Corporation\NVIDIA OpenGL SDK
10\common\include
C:\Program Files\NVIDIA Corporation\NVIDIA OpenGL SDK
10\common\GLEW\include
C:\Program Files\NVIDIA Corporation\NVIDIA OpenGL SDK
10\common\nvImage\include
C:\Program Files\NVIDIA Corporation\NVIDIA OpenGL SDK
10\common\nvModel\include
C:\Program Files\NVIDIA Corporation\NVIDIA OpenGL SDK
10\common\GLEW\lib
C:\Program Files\NVIDIA Corporation\NVIDIA OpenGL SDK
10\common\nvImage\lib
C:\Program Files\NVIDIA Corporation\NVIDIA OpenGL SDK
10\common\nvModel\lib
dll 파일


C:\Program Files\NVIDIA Corporation\NVIDIA OpenGL SDK 10\bin
에서 glew32.dll, nvModel.dll, nvImage.dll을 C:\Windows\system32
폴더에 복사
Division of Electrical and Computer Engineering, Hanyang University
nvModel
 obj 파일에서 버텍스 좌표, 법선 벡터, 텍스처 좌표
등을 로드하여 배열 형태로 메모리에 저장.
 렌더링할 때 버텍스 정보가 저장된 배열 주소를
이용하여 vertex array 방식으로 렌더링
 nvModel은 obj 파일만 읽어들일 뿐, 재질속성
파일(.mtl) 및 텍스처 이미지 파일은 읽어들이지 않음



조명에 대한 반사도(색상)이 필요하면 mtl 파일
parser를 따로 작성해야 함.
혹은, mtl 파일을 생성하지 않고, 모델을 렌더링할 때
glColor*로 직접 색상 지정.
텍스처의 경우 nvImage를 이용하여 이미지 파일을
따로 로드하여 텍스처 객체를 생성해 주어야 함.
Division of Electrical and Computer Engineering, Hanyang University
nvModel
 모델 로드 방법
nv::Model *model = new nv::Model;
// 모델 로드
model->loadModelFromFile(model_filename);
// 중복된 버텍스 인덱스를 제거
model->removeDegeneratePrims();
// 법선 벡터 계산
model->computeNormals();
// 삼각형 메쉬로 렌더링할 수 있도록 vertex arrays 생성
model->compileModel( nv::Model::eptAll);
Division of Electrical and Computer Engineering, Hanyang University
nvModel
 모델 렌더링 방법
glVertexPointer( model->getPositionSize(), GL_FLOAT, model->getCompiledVertexSize() * sizeof(float), model->getCompiledVertices());
glNormalPointer( GL_FLOAT, model->getCompiledVertexSize() * sizeof(float), model->getCompiledVertices() + model->getCompiledNormalOffset());
glEnableClientState( GL_VERTEX_ARRAY);
glEnableClientState( GL_NORMAL_ARRAY);
if ( model->hasTexCoords())
{
glTexCoordPointer( model->getTexCoordSize(), GL_FLOAT, model->getCompiledVertexSize() * sizeof(float),
model->getCompiledVertices() + model->getCompiledTexCoordOffset());
glEnableClientState( GL_TEXTURE_COORD_ARRAY);
}
glDrawElements( GL_TRIANGLES, model->getCompiledIndexCount( nv::Model::eptTriangles), GL_UNSIGNED_INT,
model->getCompiledIndices( nv::Model::eptTriangles));
glDisableClientState( GL_VERTEX_ARRAY);
glDisableClientState( GL_NORMAL_ARRAY);
glDisableClientState( GL_TEXTURE_COORD_ARRAY);
Division of Electrical and Computer Engineering, Hanyang University
EXAMPLE – 많은 수의 큐브를
그리는 예제
(IMMEDIATE MODE 및
DISPLAY LIST 이용)
Division of Electrical and Computer Engineering, Hanyang University
기본 뼈대 작성
#include <math.h>
#include <time.h>
#include <stdlib.h>
#include <gl/glut.h>
#define PI
//
모델이나상태변수등의초기화함수
void SetupRC()
{
glClearColor(0.0, 0.0, 0.0, 0.0);
glEnable(GL_DEPTH_TEST);
}
3.141592
typedef struct _Vector3D
{
float x;
float y;
float z;
} Vector3D;
void RenderScene(void)
{
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(angle, 0.0f, 1.0f, 0.0f);
glTranslatef(pos.x, pos.y, pos.z);
static GLfloat angle, velocity = 5;
static Vector3D pos = {0.0, -20.0, 0.0};
void DrawCube(CubeData *pData);
void ChangeSize(GLsizei width, GLsizei height)
{
GLfloat fAspect = (GLfloat)width/(GLfloat)height;
GLfloat nRange = height/4.0;
if(height == 0)
height = 1;
glutSwapBuffers();
}
int main(int argc, char *argv[])
{
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGB | GLUT_DEPTH);
glutInitWindowSize(600, 600);
glutCreateWindow("Example");
glutReshapeFunc(ChangeSize);
glutSpecialFunc(SpecialKeys);
glutDisplayFunc(RenderScene);
SetupRC();
glViewport(0, 0, width, height);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective(45.0f, fAspect, 1.0, 4000.0);
glutMainLoop();
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
return 0;
}
}
void SpecialKeys(int key, int x, int y)
{
if(key == GLUT_KEY_UP)
{
pos.x -= (velocity*sin(angle*PI/180.0));
pos.z += (velocity*cos(angle*PI/180.0));
}
if(key == GLUT_KEY_DOWN)
{
pos.x += (velocity*sin(angle*PI/180.0));
pos.z -= (velocity*cos(angle*PI/180.0));
}
if(key == GLUT_KEY_LEFT)
if(key == GLUT_KEY_RIGHT)
키보드 상하키로 전/후진
키보드 좌우키로 회전
angle -= 5.0f;
angle += 5.0f;
angle = (GLfloat)((const int)angle % 360);
glutPostRedisplay();
}
Division of Electrical and Computer Engineering, Hanyang University
큐브의 위치와 색상을 저장할 구조체 선언
및 임의의 위치에 배치
#define MAX_CUBE
10000
typedef struct _CubeData
{
Vector3D pos;
Vector3D angle;
Vector3D color;
} CubeData;
CubeData cData[MAX_CUBE];
모델들을 월드에 배치하기 위한
modelview transformation 에서
사용할 정보
랜덤한 위치로 modelview
transformation 시키기 위한
좌표 및 랜덤 색상 생성
 stdlib.h, time.h 포함하고,
SetupRC() 에서 다음을 추가
srand((unsigned char)time(NULL));
for (int i = 0 ; i < MAX_CUBE ; i++ )
{
cData[i].pos.x = rand() % 8000 4000;
cData[i].pos.z = rand() % 8000 4000;
cData[i].angle.x = rand() % 360;
cData[i].angle.y = rand() % 360;
cData[i].angle.z = rand() % 360;
cData[i].color.x = (float)(rand()
% 101) / 100.0;
cData[i].color.y = (float)(rand()
% 101) / 100.0;
cData[i].color.z = (float)(rand()
% 101) / 100.0;
}
Division of Electrical and Computer Engineering, Hanyang University
큐브 그리는 함수 작성 및 렌더링
void DrawCube(CubeData *pData)
{
glMatrixMode(GL_MODELVIEW);
glTranslatef(pData->pos.x, 0.0, pData->pos.z);
glRotatef(pData->angle.x, 1.0, 0.0, 0.0);
glRotatef(pData->angle.y, 0.0, 1.0, 0.0);
glRotatef(pData->angle.z, 0.0, 0.0, 1.0);
glColor3f(pData->color.x, pData->color.y, pData->color.z);
glBegin(GL_QUADS);
glVertex3f(10.0,10.0,10.0);
glVertex3f(10.0,-10.0,10.0);
glVertex3f(-10.0,-10.0,10.0);
glVertex3f(-10.0,10.0,10.0);
glVertex3f(10.0,10.0,-10.0);
glVertex3f(10.0,-10.0,-10.0);
glVertex3f(-10.0,-10.0,-10.0);
glVertex3f(-10.0,10.0,-10.0);

RenderScene()에서
glutSwapBuffers(); 위에 다음을 추가
for ( int i = 0 ; i < MAX_CUBE ; i++ )
{
glPushMatrix();
DrawCube(cData+i);
glPopMatrix();
}
glVertex3f(10.0,10.0,-10.0);
glVertex3f(10.0,10.0,10.0);
glVertex3f(-10.0,10.0,10.0);
glVertex3f(-10.0,10.0,-10.0);
glVertex3f(10.0,-10.0,-10.0);
glVertex3f(10.0,-10.0,10.0);
glVertex3f(-10.0,-10.0,10.0);
glVertex3f(-10.0,-10.0,-10.0);
오일러 각으로 모델을 3차원 회전시키고
월드 상의 [pos.x, pos.y, pos.z] 위치로
이동시킴으로서 모델의 배치 수행
glVertex3f(10.0,10.0,10.0);
glVertex3f(10.0,10.0,-10.0);
glVertex3f(10.0,-10.0,-10.0);
glVertex3f(10.0,-10.0,10.0);
glVertex3f(-10.0,10.0,10.0);
glVertex3f(-10.0,10.0,-10.0);
glVertex3f(-10.0,-10.0,-10.0);
glVertex3f(-10.0,-10.0,10.0);
glEnd();
}
Division of Electrical and Computer Engineering, Hanyang University
실행화면
 MAX_CUBE의 값을 크게 하면 굉장히 느려진다.
MAX_CUBE = 10000
32 fps
MAX_CUBE = 50000
7 fps
Division of Electrical and Computer Engineering, Hanyang University
Display list의 사용

Display list 이름으로 사용할 전역 변수 선언.

GLuint cubeDList;

SetupRC()에서 display list 이름을 예약하고 큐브를 그리는 부분을
RenderScene()으로부터 glNewList() ~ glEndList() 사이로 옮긴다.

RenderScene()에서 glCallList()로 Display list를 실행시킨다.
Division of Electrical and Computer Engineering, Hanyang University
실행화면

Display list를 사용할 경우 성능 향상.
Display list 사용
MAX_CUBE = 50000
12 fps
Immediate mode 사용
MAX_CUBE = 50000
7 fps
이 예제에서는 간단한 모델이 많은 scene 전체를 display list로 만들었기
때문에 성능 향상이 크지는 않다.
 복잡한 모델 단위로 display list를 만들어 사용한다면 성능 향상이 클 것이다.

Division of Electrical and Computer Engineering, Hanyang University
EXAMPLE – OBJ 형식의 모델
파일 로드 및 렌더링
Division of Electrical and Computer Engineering, Hanyang University
Obj 파일을 로드하기 위한 함수 작성
nv::Model* LoadModel(const char *filename)
{
nv::Model *model = new nv::Model;
if (model->loadModelFromFile(filename))
{
// remove any primitives with duplicate indices, as they might confuse adjacency
model->removeDegeneratePrims();
// compute normal
model->computeNormals();
// make the model efficient for rendering with vertex arrays
model->compileModel( nv::Model::eptAll);
}
else
{
fprintf(stderr, "Error loading model '%s'\n", filename);
delete model;
model = 0;
}
return model;
}
모델의 로드가 성공하면 모델 정보가 저장된 nv::Model 클래스의 포
인터를 리턴하고, 실패하면 NULL 포인터 리턴
Division of Electrical and Computer Engineering, Hanyang University
텍스처 이미지를 로드하기 위한 함수 작성
GLuint LoadImage(const char *filename)
{
nv::Image img;
GLuint tex;
if(img.loadImageFromFile(texture_filename))
{
//
텍스처객체를생성하고텍스처객체에이미지데이터복사
glGenTextures(1, &tex);
glBindTexture(GL_TEXTURE_2D, tex);
glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_DECAL);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
glTexParameteri( GL_TEXTURE_2D, GL_GENERATE_MIPMAP, GL_TRUE);
glTexImage2D( GL_TEXTURE_2D, 0, img.getInternalFormat(), img.getWidth(), img.getHeight(), 0,
img.getFormat(), img.getType(), img.getLevel(0));
}
else
{
fprintf(stderr, "Error loading model '%s'\n", filename);
tex = 0;
}
return tex;
}
nvImage 라이브러리는 “png”, “dds”, “hdr” 형식의 이미지만 로드할
수 있다.
이미지 파일의 로드가 성공하면 이미지 데이터를 가진 텍스처 객체
의 id를 리턴하고, 실패하면 0을 리턴(id가 0이면 텍스처가 없음을 나
타냄)
텍스처 관련 함수는 Discrete techs 에서 설명한다.
Division of Electrical and Computer Engineering, Hanyang University
로드한 모델을 그리기 위한 함수 작성
void DrawModel(nv::Model *model, GLuint tex, Vector3D color)
{
if (model)
{
//
모델색상지정
glColor3f(color.x, color.y, color.z);
//
텍스처사용on
glEnable(GL_TEXTURE_2D);
glBindTexture(GL_TEXTURE_2D, tex);
//
vertex array로사용할배열지정
glVertexPointer( model->getPositionSize(), GL_FLOAT, model->getCompiledVertexSize() * sizeof(float), model->getCompiledVertices());
glNormalPointer( GL_FLOAT, model->getCompiledVertexSize() * sizeof(float), model->getCompiledVertices()
+ model->getCompiledNormalOffset());
//
vertex array 사용on
glEnableClientState( GL_VERTEX_ARRAY);
glEnableClientState( GL_NORMAL_ARRAY);
//
텍스처좌표가있을경우
if ( model->hasTexCoords()) {
glTexCoordPointer( model->getTexCoordSize(), GL_FLOAT, model->getCompiledVertexSize() * sizeof(float)
, model->getCompiledVertices() + model->getCompiledTexCoordOffset());
glEnableClientState( GL_TEXTURE_COORD_ARRAY);
}
//
vertex array와vertex index를이용하여실제로그리는함수
glDrawElements( GL_TRIANGLES, model->getCompiledIndexCount( nv::Model::eptTriangles), GL_UNSIGNED_INT
, model->getCompiledIndices( nv::Model::eptTriangles));
//
vertex array 사용off
glDisableClientState( GL_VERTEX_ARRAY);
glDisableClientState( GL_NORMAL_ARRAY);
glDisableClientState( GL_TEXTURE_COORD_ARRAY);
//
텍스처사용off
glDisable(GL_TEXTURE_2D);
}
}
전달받은 모델 클래스, 텍스처 객체, 모델 색상을 이용하여 모델을
그린다.
vertex array 관련 함수는 modeling hierarchy 에서 설명한다.
Division of Electrical and Computer Engineering, Hanyang University
모델 및 텍스처 로드 및 렌더링에 사용할
변수 선언
 nvModel.h, nvImage.h를 인클루드하고, 프로젝트
속성에서 nvModel.lib, nvImage.lib을 링크시키도록
설정
 아래의 변수들을 전역 변수로 선언한다.
// 모델 파일 및 이미지 파일 이름
const char *model_filename[2] = {"tree.obj", "treeBase.obj"};
const char *texture_filename = "leaf.png";
// 모델, 모델 색상, 텍스처 객체id
nv::Model *treeModel[2];
Vector3D treeBaseColor = {0.4, 0.0, 0.0 };
GLuint treeTex;
Division of Electrical and Computer Engineering, Hanyang University
나무 모델과 텍스처 로드
 SetupRC()에서 다음 코드를 추가
treeModel[0] = LoadModel(model_filename[0]);
treeModel[1] = LoadModel(model_filename[1]);
treeTex = LoadImage(texture_filename);
나무 모델은 나무 기둥(treebase.obj)과
나무 잎사귀부분(tree.obj, leaf.png)의 두
개의 모델로 구성된다.
nvImage 라이브러리는 “png”, “dds”, “hdr”
형식의 이미지만 로드할 수 있다.
Division of Electrical and Computer Engineering, Hanyang University
나무 모델의 렌더링
 RenderScene()에서 다음의 코드를 추가
for ( int i = 0 ; i < 8 ; i++ )
{
glPushMatrix();
glRotatef(i*360.0/8.0, 0.0, 1.0, 0.0);
glTranslatef(500.0, 0.0, 0.0);
DrawModel(treeModel[0], treeTex, treeBaseColor);
DrawModel(treeModel[1], 0, treeBaseColor);
glPopMatrix();
}
월드의 중심으로부터 반경 500 거
리에 8개의 나무를 그린다.
Division of Electrical and Computer Engineering, Hanyang University
Division of Electrical and Computer Engineering, Hanyang University