From 2e925286d87aa2ceb70e23afae7ecb26025f4935 Mon Sep 17 00:00:00 2001 From: Heng_Xin_666 <282000500@qq.com> Date: Tue, 5 Aug 2025 15:17:39 +0800 Subject: [PATCH] =?UTF-8?q?=E5=AE=8C=E6=88=90=E7=AC=AC=E4=BA=8C=E6=AC=A1?= =?UTF-8?q?=E5=9B=9E=E5=AE=B6=E4=BD=9C=E4=B8=9A(=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E8=AF=BE:=20=E7=BB=98=E5=88=B63D=20OpenCV=20=E5=9B=BE=E6=A0=87?= =?UTF-8?q?)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/Game.cpp | 111 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 91 insertions(+), 20 deletions(-) diff --git a/src/Game.cpp b/src/Game.cpp index 7229bd9..5df5db3 100644 --- a/src/Game.cpp +++ b/src/Game.cpp @@ -37,6 +37,11 @@ void Game::initialize() { CHECK_GL(glCullFace(GL_BACK)); CHECK_GL(glFrontFace(GL_CCW)); + CHECK_GL(glEnable(GL_LIGHTING)); // 启用固定管线光照 (古代特性) + CHECK_GL(glEnable(GL_LIGHT0)); // 启用 0 号光源 (古代特性) + CHECK_GL(glEnable(GL_COLOR_MATERIAL)); // 启用材质颜色追踪 (古代特性) + CHECK_GL(glEnable(GL_NORMALIZE)); // 法线归一化 + // glm::vec4 lightPos(-1, 1, 1, 0); // 等会用更现代的方式指定光源方向 auto program = GLProgram().make(); @@ -52,30 +57,96 @@ void Game::initialize() { CHECK_GL(glLinkProgram(program)); m_private->program = std::move(program); - m_private->obj.load_obj(OPENGLTUTOR_HOME "assets/monkey.obj"); + m_private->obj.load_obj(OPENGLTUTOR_HOME "assets/opencvpart.obj"); m_private->obj.draw_obj(m_private->drawableObj, /*dynamic=*/false); } -void Game::render() { - int width, height; - glfwGetWindowSize(m_window, &width, &height); - CHECK_GL(glViewport(0, 0, width, height)); - - CHECK_GL(glClearColor(0.0f, 0.0f, 0.0f, 0.0f)); - CHECK_GL(glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT)); +// 手动计算法线 asin 系数 +static glm::vec3 compute_normal_biased(glm::vec3 a, glm::vec3 b, glm::vec3 c) noexcept { + auto ab = b - a; + auto ac = c - a; + auto n = glm::cross(ab, ac); + auto nLen = glm::length(n); + if (nLen != 0) { + n *= glm::asin(nLen / (glm::length(ab) * glm::length(ac))) / nLen; + } + return n; +} +void Game::render() { + CHECK_GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); // 清空画布 + + // 存储各个角度 + static auto models = [] { + float k = 0.618f; + float xDown = k * std::sqrt(3.f); + float hOpencv = k * 1.f; + std::vector res; + glm::mat4x4 model{1.f}; + model = glm::translate(model, glm::vec3{hOpencv * 2, 0, 0}); + model = glm::rotate(model, glm::radians(60.f), glm::vec3{0, 1, 0}); + res.push_back(model); + + model = glm::mat4x4{1.f}; + model = glm::translate(model, glm::vec3{-hOpencv, 0, -xDown}); + model = glm::rotate(model, glm::radians(180.f), glm::vec3{0, 1, 0}); + res.push_back(model); + + model = glm::mat4x4{1.f}; + model = glm::translate(model, glm::vec3{-hOpencv, 0, xDown}); + model = glm::rotate(model, glm::radians(240.f), glm::vec3{0, 1, 0}); + res.push_back(model); + return res; + }(); + + auto& vertices = m_private->obj.vertices; + auto& faces = m_private->obj.faces; + + // 计算平滑渲染需要的法线 + static auto normals = [&] { + std::vector res; + res.resize(faces.size()); + for (auto const& v : faces) { + auto a = vertices[v[0]].position, + b = vertices[v[1]].position, + c = vertices[v[2]].position; + for (std::size_t i = 0; i < 3; ++i) + res[v[i]] += compute_normal_biased(a, b, c); + } + for (auto& it : res) + it = glm::normalize(it); + return res; + }(); + + std::size_t i = 1; auto projection = m_inputCtl.get_projection_matrix(); auto view = m_inputCtl.get_view_matrix(); - glm::mat4x4 model(1.0f); - - CHECK_GL(glUseProgram(m_private->program)); - CHECK_GL(glUniformMatrix4fv(glGetUniformLocation(m_private->program, "uniModel"), 1, GL_FALSE, glm::value_ptr(model))); - CHECK_GL(glUniformMatrix4fv(glGetUniformLocation(m_private->program, "uniView"), 1, GL_FALSE, glm::value_ptr(view))); - CHECK_GL(glUniformMatrix4fv(glGetUniformLocation(m_private->program, "uniProjection"), 1, GL_FALSE, glm::value_ptr(projection))); - - glm::vec2 mousePos = m_inputCtl.get_cursor_pos(); - glm::vec3 lightDir = glm::normalize(glm::vec3(mousePos.x, mousePos.y, 1)); - int location = glGetUniformLocation(m_private->program, "uniLightDir"); - CHECK_GL(glUniform3fv(location, 1, glm::value_ptr(lightDir))); - m_private->drawableObj.draw(); + for (auto model : models) { + glm::mat4x4 viewModel = view * model; // ModelView + + // 加载投影矩阵 + glMatrixMode(GL_PROJECTION); + glLoadMatrixf(glm::value_ptr(projection)); + + // 加载模型视图矩阵 + glMatrixMode(GL_MODELVIEW); + glLoadMatrixf(glm::value_ptr(viewModel)); + + glColor3f(i & 1, (i & 2) >> 1, (i & 4) >> 2); // RGB, 对应 opencv 颜色 + glBegin(GL_TRIANGLES); + for (auto const& v : faces) { + auto a = vertices[v.x].position, + b = vertices[v.y].position, + c = vertices[v.z].position; + + glNormal3fv(glm::value_ptr(normals[v[0]])); + glVertex3fv(glm::value_ptr(a)); + glNormal3fv(glm::value_ptr(normals[v[1]])); + glVertex3fv(glm::value_ptr(b)); + glNormal3fv(glm::value_ptr(normals[v[2]])); + glVertex3fv(glm::value_ptr(c)); + } + CHECK_GL(glEnd()); + i <<= 1; + } }