본문 바로가기
College Computer Science/Computer Graphics

[컴퓨터그래픽스] openGL 사용하지 않고 culling 수행하기

by 2den 2021. 4. 3.
728x90
#include <glut.h>
#include <glm/glm.hpp>
#include <stdio.h>
#define PI 3.141592
#define CCW 0
#define CW  1

using namespace glm;

vec3 my_triangle1[3] = { vec3(-10.f, 0.f, 0.f), vec3(10.f, 0.f, 0.f), vec3(0.f, 10.f, 0.f) }; // CCW
vec3 my_triangle2[3] = { vec3(10.f, 0.f, 0.f), vec3(-10.f, 0.f, 0.f), vec3(0.f, 10.f, 0.f) }; // CW
vec3 faceNorm[2];
vec3 eyeVec;
GLfloat angle[2];
GLint culling = CW;
GLint isTriangle1 = 0;
GLint isTriangle2 = 0;

void RenderScene(void)
{
	glClear(GL_COLOR_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);

	glLoadIdentity();
	gluLookAt(0.f, 0.f, 80.0f, 0.f, 0.f, 0.f, 0.f, 1.f, 0.f);
	
	faceNorm[0] = cross(my_triangle1[1] - my_triangle1[0], my_triangle1[2] - my_triangle1[0]);
	faceNorm[1] = cross(my_triangle2[1] - my_triangle2[0], my_triangle2[2] - my_triangle2[0]);
	eyeVec = vec3(0.f, 0.f, 0.f) - vec3(0.f, 0.f, 80.0f);

	angle[0] = acos(
		dot(faceNorm[0], eyeVec) /
		dot(sqrt(faceNorm[0].x * faceNorm[0].x + faceNorm[0].y * faceNorm[0].y + faceNorm[0].z * faceNorm[0].z),
			sqrt(eyeVec.x * eyeVec.x + eyeVec.y * eyeVec.y + eyeVec.z * eyeVec.z))
	);

	angle[1] = acos(
		dot(faceNorm[1], eyeVec) /
		dot(sqrt(faceNorm[1].x * faceNorm[1].x + faceNorm[1].y * faceNorm[1].y + faceNorm[1].z * faceNorm[1].z),
			sqrt(eyeVec.x * eyeVec.x + eyeVec.y * eyeVec.y + eyeVec.z * eyeVec.z))
	);

	if (angle[0] > PI/2.) isTriangle1 = CW;
	else isTriangle1 = CCW;

	if (angle[1] > PI/2.) isTriangle2 = CW;
	else isTriangle2 = CCW;

	if (culling == isTriangle1)
	{ 
		glColor3f(1.0f, 0.0f, 0.0f);
		glPushMatrix();
		glTranslatef(25.f, 0.f, 0.f);
		glScaled(2.f, 2.f, 2.f);
		glBegin(GL_TRIANGLES);
		glVertex3f(-10.f, 0.f, 0.f);
		glVertex3f(10.f, 0.f, 0.f);
		glVertex3f(0.f, 10.f, 0.f);
		glEnd();
		glPopMatrix();
	}

	if (culling == isTriangle2)
	{
		glColor3f(0.0f, 1.0f, 0.0f);
		glPushMatrix();
		glTranslatef(-25.f, 0.f, 0.f);
		glScaled(2.f, 2.f, 2.f);
		glBegin(GL_TRIANGLES);
		glVertex3f(-10.f, 0.f, 0.f);
		glVertex3f(10.f, 0.f, 0.f);
		glVertex3f(0.f, 10.f, 0.f);
		glEnd();
		glPopMatrix();	}
		glFlush();
}

void SetupRC(void)
{
	glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
}

void ChangeSize(GLsizei w, GLsizei h)
{
	if (h == 0)
		h = 1;

	glViewport(0, 0, w, h);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	GLfloat aspectRatio = (GLfloat)w / (GLfloat)h;
	gluPerspective(90.f, aspectRatio, 10.f, 200.f);
}

int main(int argc, char* argv[])
{
	glutInit(&argc, argv);

	glutInitDisplayMode(GLUT_SINGLE | GLUT_RGBA);
	glutCreateWindow("Assignment6");

	glutDisplayFunc(RenderScene);
	glutReshapeFunc(ChangeSize);

	SetupRC();
	glutMainLoop();
	return 0;
}

 

설명

 

* 기본적인 수학 연산(dot, cross product, square root)과 vec3 자료형 사용을 위해 glm 라이브러리를 사용하였습니다.

 

faceNorm [ 0 ] = cross ( my_triangle1 [ 1 ] - my_triangle1 [ 0 ],
	my_triangle1 [ 2 ] - my_triangle1 [ 0 ]);
faceNorm [ 1 ] = cross ( my_triangle2 [ 1 ] - my_triangle2 [ 0 ],
	my_triangle2 [ 2 ] - my_triangle2 [ 0 ]);
eyeVec = vec3 ( 0. f , 0. f , 0. f ) - vec3 ( 0. f , 0. f , 80.0 f );

faceNorm의 첫번째 요소에는 my_triangle1의 normal vector를, faceNorm의 두번째 요소에는 my_triangle의 normal vector를, eyeVec에는 눈이 바라보는 시선의 벡터를 저장한다. normal vector는 삼각형(PQR이라고 가정)의 두면 PQ 와 PR의 cross product로 구한다. 벡터는 벡터가 향하는 좌표 - 벡터의 시작점으로 구한다. (glm의 vec3자료형은 벡터형이 아닌 3차원 좌표를 나타내기 위해 쓰이기도 한다.)

 

angle [ 0 ] = acos (
	dot (faceNorm [ 0 ], eyeVec) /
	dot (sqrt (faceNorm [ 0 ]. x * faceNorm [ 0 ]. x
		+ faceNorm [ 0 ]. y * faceNorm [ 0 ]. y
		+ faceNorm [ 0 ]. z * faceNorm [ 0 ]. z),
	sqrt (eyeVec . x * eyeVec . x + eyeVec . y * eyeVec . y + eyeVec . z * eyeVec . z))
	);

두 벡터 사이의 각도는

 

 

 

 

와 같이 구한다.

 

if ( angle [ 0 ] > PI / 2. ) isTriangle1 = CW ;
else isTriangle1 = CCW ;

if ( angle [ 1 ] > PI / 2. ) isTriangle2 = CW ;
else isTriangle2 = CCW ;

눈과 삼각형의 normal vector가 이루는 각도가 90도 초과면 Clockwise, 90도 이하면 Counter-clockwise로 설정한다.

 

GLint culling = CW ;
…
if (culling == isTriangle1)
{
	glColor3f ( 1.0 f, 0.0 f, 0.0 f);
	glPushMatrix ();
	glTranslatef ( 25. f, 0. f, 0. f);
	glScaled ( 2. f, 2. f, 2. f);
	glBegin ( GL_TRIANGLES );
	glVertex3f ( - 10. f, 0. f, 0. f);
	glVertex3f ( 10. f, 0. f, 0. f);
	glVertex3f ( 0. f, 10. f, 0. f);
	glEnd ();
	glPopMatrix ();
}
	
if (culling == isTriangle2)
{
	glColor3f ( 0.0 f, 1.0 f, 0.0 f);
	glPushMatrix ();
	glTranslatef ( - 25. f, 0. f, 0. f);
	glScaled ( 2. f, 2. f, 2. f);
	glBegin ( GL_TRIANGLES );
	glVertex3f ( - 10. f, 0. f, 0. f);
	glVertex3f ( 10. f, 0. f, 0. f);
	glVertex3f ( 0. f, 10. f, 0. f);
	glEnd ();
	glPopMatrix (); }
	glFlush ();
}

culling 모드와 삼각형의 방향을 비교하여 선택적으로 렌더링한다.

 

728x90

댓글