[OpenGL] ์ค‘๋ ฅ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๊ณต ์šด๋™ ํ•˜๊ธฐ

2024. 6. 7. 00:05

 

 

OpenGL๊ณผ GLFW๋ฅผ ์ด์šฉํ•ด์„œ ๊ฐ„๋‹จํ•œ ๋ฌผ๋ฆฌ ๊ธฐ๋ฐ˜์˜ ๊ณต ์šด๋™ ์‹œ๋ฎฌ๋ ˆ์ด์…˜์„ ํ•ด๋ดค๋‹ค.

๊ณต๋ถ€ํ•œ ๊น€์— ๊ฒธ์‚ฌ๊ฒธ์‚ฌ~

์ค‘๋ ฅ ์˜ํ–ฅ์„ ๋ฐ›์•„์„œ ๋ฐ”๋‹ฅ์œผ๋กœ ๋–จ์–ด์ง€๊ณ  ๋ฐ”๋‹ฅ์— ๋‹ฟ์œผ๋ฉด ๋ฐ˜๋™ ํšจ๊ณผ๋ฅผ ์ ์šฉํ•ด ๋‹ค์‹œ ์œ„๋กœ ํŠ•๊ฒจ ์˜ค๋ฅด๋Š” ๋‘ ๊ฐœ์˜ ๊ณต์„ ํ™”๋ฉด์œผ๋กœ ์ถœ๋ ฅํ•˜๋Š” ๊ฐ„๋‹จํ•œ ์˜ˆ์ œ์ด๋‹ค.

 

๊ธฐ๋ณธ ์„ค์ •

๊ทธ๋ƒฅ ํ˜น์‹œ๋‚˜ ๋”ฐ๋ผํ•˜๋Š” ์‚ฌ๋žŒ์ด ์žˆ์„๊นŒ ํ•ด์„œ ์ถ”๊ฐ€ํ•ด๋ณธ ์œˆ๋„์šฐ ์ดˆ๊ธฐํ™” ๊ด€๋ จ ๋‚ด์šฉ์ด๋‹ค.

์œˆ๋„์šฐ์˜ ํฌ๊ธฐ๋ฅผ ์„ค์ •ํ•˜๊ณ  GLFW๋ฅผ ์ด์šฉํ•ด ์œˆ๋„์šฐ๋ฅผ ์ƒ์„ฑํ•œ๋‹ค

GLFWwindow* window = glfwCreateWindow(WIDTH, HEIGHT, "ball simulation", NULL, NULL);
glfwMakeContextCurrent(window);

 

OpenGL์˜ ๋ทฐํฌํŠธ๋ฅผ ์„ค์ •ํ•˜๊ณ , ํˆฌ์˜ ํ–‰๋ ฌ์„ ์ •์˜ํ•œ๋‹ค.

์ด ์˜ˆ์ œ์—์„œ๋Š” 2D ํˆฌ์˜์„ ์‚ฌ์šฉํ•ด์„œ -1์—์„œ 1๊นŒ์ง€์˜ ์ขŒํ‘œ๊ณ„๋ฅผ ์„ค์ •ํ•œ๋‹ค.

glViewport(0, 0, WIDTH, HEIGHT);
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(-1.0, 1.0, -1.0, 1.0, -1.0, 1.0);
glMatrixMode(GL_MODELVIEW);

 

 

๋ฌผ๋ฆฌ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ ๊ตฌํ˜„

๊ณต์˜ ์›€์ง์ž„์„ ์‹œ๋ฎฌ๋ ˆ์ด์…˜ํ•˜๊ธฐ!

๊ณต์€ ์ค‘๋ ฅ์˜ ์˜ํ–ฅ์„ ๋ฐ›์•„์„œ ์•„๋ž˜๋กœ ๋–จ์–ด์ง€๊ณ  ๋ฐ”๋‹ฅ์— ๋‹ฟ์œผ๋ฉด ๋ฐ˜๋™ ํšจ๊ณผ๋ฅผ ์ ์šฉํ•ด ํŠ€์–ด ์˜ค๋ฅด๊ฒŒ ๋œ๋‹ค.

const float GRAVITY = -9.81f;
const float BOUNCE_DAMPING = 0.7f;
const float FLOOR_Y = -0.9f;

struct Ball 
{
    float x, y;
    float radius;
    float velocityY;
};

Ball ball1 = { -0.3f, 0.5f, 0.1f, 0.0f };
Ball ball2 = { 0.3f, 0.7f, 0.1f, 0.0f };

 

๊ณต์˜ ์œ„์น˜์™€ ๋ฐ˜์ง€๋ฆ„, ์†๋„ ๋“ฑ์„ ํฌํ•จํ•œ 'Ball' ๊ตฌ์กฐ์ฒด๋ฅผ ํ•˜๋‚˜ ์ถ”๊ฐ€ํ•ด ์ค€๋‹ค.

 

์‹œ๊ฐ„์— ๋”ฐ๋ผ ๊ณต์˜ ์†๋„๋ž‘ ์œ„์น˜๋ฅผ ์—…๋ฐ์ดํŠธ ํ•˜๋Š” 'updateBall' ํ•จ์ˆ˜๋กœ ๋ฌผ๋ฆฌ ์„ค์ •์ด ์‹œ๋ฎฌ๋ ˆ์ด์…˜๋œ๋‹ค.

์ค‘๋ ฅ ๊ฐ€์†๋„๋ฅผ ์†๋„์— ๋”ํ•˜๊ณ , ์†๋„๋ฅผ ์ด์šฉํ•ด์„œ ๊ณต์˜ ์œ„์น˜๋ฅผ ์—…๋ฐ์ดํŠธํ•œ๋‹ค.

๋งŒ์•ฝ ๊ณต์ด ๋ฐ”๋‹ฅ์— ๋‹ฟ์œผ๋ฉด ๋ฐ˜๋™ ๊ณ„์ˆ˜๋ฅผ ์ ์šฉํ•ด ๊ณต์˜ ์†๋„๋ฅผ ๋ฐ˜์ „์‹œํ‚จ๋‹ค.

void updateBall(Ball &ball, float deltaTime) 
{
    ball.velocityY += GRAVITY * deltaTime;
    ball.y += ball.velocityY * deltaTime;

    if (ball.y - ball.radius <= FLOOR_Y) 
    {
        ball.y = FLOOR_Y + ball.radius;
        ball.velocityY = -ball.velocityY * BOUNCE_DAMPING;
    }
}

 

 

๊ณต ๊ทธ๋ฆฌ๊ธฐ

'drawBall' ํ•จ์ˆ˜๋Š” ๊ณต์˜ ์ค‘์‹ฌ์ ์—์„œ ์‹œ์ž‘ํ•ด์„œ ๋ฐ˜์ง€๋ฆ„์„ ๊ธฐ์ค€์œผ๋กœ ์›์„ ๊ทธ๋ฆฐ๋‹ค.

void drawBall(Ball ball) 
{
    glBegin(GL_TRIANGLE_FAN);
    glVertex2f(ball.x, ball.y);
    for (int i = 0; i <= 100; i++) 
    {
        float theta = (float)i / 100.0f * 2.0f * 3.14159f;
        float dx = ball.radius * cosf(theta);
        float dy = ball.radius * sinf(theta);
        glVertex2f(ball.x + dx, ball.y + dy);
    }
    glEnd();
}

 

 

๋ฉ”์ธ ๋ฃจํ”„

๋งˆ์ง€๋ง‰์œผ๋กœ ๋ฃจํ”„์—์„œ ๊ณต์˜ ์›€์ง์ž„์„ ์—…๋ฐ์ดํŠธํ•˜๊ณ  ํ™”๋ฉด์— ๊ทธ๋ฆฌ๋Š” ์ž‘์—…์„ ๋ฐ˜๋ณตํ•œ๋‹ค.

ํ™”๋ฉด์€ ๋งค ํ”„๋ ˆ์ž„๋งˆ๋‹ค ์ง€์›Œ์ง€๊ณ  ๋‘ ๊ฐœ์˜ ๊ณต์ด ๊ฐ๊ฐ ๋นจ๊ฐ„์ƒ‰๊ณผ ํŒŒ๋ž€์ƒ‰์œผ๋กœ ๊ทธ๋ ค์ง„๋‹ค.

while (!glfwWindowShouldClose(window)) 
{
    float currentTime = glfwGetTime();
    static float lastTime = 0.0f;
    float deltaTime = currentTime - lastTime;
    lastTime = currentTime;

    updateBall(ball1, deltaTime);
    updateBall(ball2, deltaTime);

    glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
    glClear(GL_COLOR_BUFFER_BIT);

    glLoadIdentity();
    glColor3f(1.0f, 0.0f, 0.0f);
    drawBall(ball1);
    glColor3f(0.0f, 0.0f, 1.0f);
    drawBall(ball2);

    glfwSwapBuffers(window);
    glfwPollEvents();
}