Skip to content
  • 首页
  • 留言
  • 关于

Share the joys of programming and technology

Modern OpenGL绘制圆柱体

Modern OpenGL绘制圆柱体

2021年6月29日 liyanliang Comments 2 comments
阅读次数: 1,607

本文主要介绍如何使用 C++ 生成圆柱几何体以及如何在 OpenGL 中绘制它。

1.绘制方法

由于我们无法绘制一个完美的圆形底面和圆柱体的弯曲侧面,我们只能通过将底面除以扇区(切片)来采样有限数量的点。因此,它在技术上是通过将这些采样点连接在一起来构建棱柱体。随着样本数量的增加,几何形状更接近于圆柱体。

假设一个圆柱体以原点为中心,半径为r,高度为h。圆柱体上的任意点 ( x, y, z ) 可以从具有相应扇形角θ的圆方程计算出来:

扇形角的范围是从 0 到 360 度。每个步骤的扇形角可以通过以下方式计算:

2.创建存放顶点向量和法向量的结构体:

struct TVertex {
	// position
	glm::vec3 Position;
	// normal
	glm::vec3 Normal;
};

​3.计算圆周上的点

const int sectorCount = 36; 
const float pierRadius = 2.0f;
const float pierHeight = 5.0f;
// 圆周顶点
std::vector<TVertex> getUnitCircleVertices()
{
    const float PI = 3.1415926f;
    float sectorStep = 2 * PI / sectorCount;
    float sectorAngle = 0.0f;
​
    glm::vec3 position;
    glm::vec3 normal;
    TVertex tVertex;
​
    std::vector<TVertex> unitCircleVertices;
    for (int i = 0; i <= sectorCount; ++i)
    {
        sectorAngle = i * sectorStep;
        position.x = pierRadius * cos(sectorAngle);
        position.y = 0.0f;
        position.z = pierRadius * sin(sectorAngle);
​
        normal.x = cos(sectorAngle);
        normal.y = 0.0f;
        normal.z = sin(sectorAngle);
​
        tVertex.Position = position;
        tVertex.Normal = normal;
​
        unitCircleVertices.push_back(tVertex);
    }
​
    return unitCircleVertices;
}

4.获取圆柱体侧面、顶面、底面的顶点和法向量

// generate vertices for a cylinder
void buildCylinderVertices(std::vector<TVertex>& vertices)
{
    std::vector<TVertex> unitVertices = getUnitCircleVertices();
​
    // 获取上、下圆周点数组
    std::vector<TVertex> vctTop;
    std::vector<TVertex> vctBot;
​
    TVertex tVertex;
    for(int i = 0; i < unitVertices.size(); ++i)
    {
        tVertex.Position = unitVertices[i].Position;
        tVertex.Position.y = pierHeight;
        tVertex.Normal = unitVertices[i].Normal;
        vctTop.push_back(tVertex);  
​
        tVertex.Position.y = 0.0f;
        vctBot.push_back(tVertex);     
    }
​
    assert(vctTop.size() >= 2);
    assert(vctBot.size() >= 2);
​
    // 圆柱侧面
    for(int i = 0; i < vctTop.size() - 1; ++i)
    {
        // 左三角形
        vertices.push_back(vctTop[i]);
        vertices.push_back(vctBot[i]);
        vertices.push_back(vctBot[i+1]);
        
        // 右三角形
        vertices.push_back(vctTop[i]);
        vertices.push_back(vctTop[i+1]);
        vertices.push_back(vctBot[i+1]);
    }
    
    // 顶部圆形
    glm::vec3 position;
    for (int i = 0; i < vctTop.size() - 1; ++i)
    {
        glm::vec3 position(0.0f, pierHeight, 0.0f);
        glm::vec3 normal(0.0f, 1.0f, 0.0f);
        tVertex.Position = position;
        tVertex.Normal = normal;
        vertices.push_back(tVertex);
​
        tVertex.Position = vctTop[i].Position;
        vertices.push_back(tVertex);
​
        tVertex.Position = vctTop[i+1].Position;
        vertices.push_back(tVertex);
    }
​
    // 底部圆形
    for (int i = 0; i < vctBot.size() - 1; ++i)
    {
        glm::vec3 position(0.0f, 0.0f, 0.0f);
        glm::vec3 normal(0.0f, -1.0f, 0.0f);
        tVertex.Position = position;
        tVertex.Normal = normal;
        vertices.push_back(tVertex);
​
        tVertex.Position = vctBot[i].Position;
        vertices.push_back(tVertex);
​
        tVertex.Position = vctBot[i+1].Position;
        vertices.push_back(tVertex);
    }
}

5.将顶点和法向量存入缓冲区

  std::vector<TVertex> pierVertices;
  buildCylinderVertices(pierVertices);
  
  unsigned int pierVBO, pierVAO;
  glGenVertexArrays(1, &pierVAO);
  glGenBuffers(1, &pierVBO);
​
  glBindVertexArray(pierVAO);
  glBindBuffer(GL_ARRAY_BUFFER, pierVBO);
​
  glBufferData(GL_ARRAY_BUFFER, pierVertices.size() * sizeof(TVertex), &pierVertices[0], GL_STATIC_DRAW);
  
  // position attribute
  glEnableVertexAttribArray(0);
  glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(TVertex), (void*)0);
  // normal attribute
  glEnableVertexAttribArray(1);
  glVertexAttribPointer(1, 3, GL_FLOAT, GL_FALSE, sizeof(TVertex), (void*)offsetof(TVertex, Normal));
​
  glBindVertexArray(0);

6.绘制圆柱体

        glClearColor(0.9f, 0.9f, 0.9f, 1.0f);
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 
​
        // be sure to activate shader when setting uniforms/drawing objects
        lightingShader.use();
        lightingShader.setVec3("lightDirection", -direction); // 平行光方向
        //lightingShader.setVec3("lightPos", lightPos);
        lightingShader.setVec3("lightColor", 1.0f, 1.0f, 1.0f);
        lightingShader.setVec3("viewPos", camera.Position); 
​
        // 正交平行的视景体
        float fRatio = (float)SCR_WIDTH / (float)SCR_HEIGHT;
        float fHeight = 10.0f;
        float fWidth = fHeight*fRatio;
        //glm::mat4 projection = glm::ortho(-fWidth, fWidth, -fHeight, fHeight, -10.f, 100.f);
        glm::mat4 projection = glm::perspective(glm::radians(camera.Zoom), (float)SCR_WIDTH / (float)SCR_HEIGHT, 0.1f, 100.0f); // 透视投影     
        lightingShader.setMat4("projection", projection);
​
        glm::mat4 viewOrigin = camera.GetViewMatrix();
        lightingShader.setMat4("view", viewOrigin);
​
        // 绘制圆柱体
        viewOrigin = glm::rotate(viewOrigin, glm::radians(30.0f), glm::vec3(1.0f, 0.0f, 0.0f));
        viewOrigin = glm::rotate(viewOrigin, glm::radians(15.0f), glm::vec3(0.0f, 0.0f, -1.0f));
        lightingShader.setMat4("view", viewOrigin);
        glm::mat4 modelPier = glm::mat4(1.0f);
        lightingShader.setMat4("model", modelPier);
        lightingShader.setVec3("objectColor", glm::vec3(0.5f, 0.1f,0.3f));
​
        glBindVertexArray(pierVAO);
        glDrawArrays(GL_TRIANGLES, 0, pierVertices.size());

7.删除缓冲区

    glDeleteVertexArrays(1, &pierVAO);
    glDeleteBuffers(1, &pierVBO);

8.效果

9.完整的项目源代码

https://pan.baidu.com/s/1cEUuAmY3JNUbt7sTNvTuyA

提取码:lf5q

相关文章

  • LearnOpenGL脑图汇总LearnOpenGL脑图汇总
  • OpenGL 几何着色器的应用OpenGL 几何着色器的应用
  • OpenGL绘制桥梁模型OpenGL绘制桥梁模型
  • OpenGL绘制旋转立方体OpenGL绘制旋转立方体
  • OpenGL模型加载-附源码OpenGL模型加载-附源码
  • OpenGL实现多光源-附项目源码OpenGL实现多光源-附项目源码

C++
OpenGL

Post navigation

PREVIOUS
WordPress分页插件 – WP-PageNavi的使用(替换现有脚本)
NEXT
OpenGL绘制桥梁模型

2 thoughts on “Modern OpenGL绘制圆柱体”

  1. 匿名说道:
    2021年11月27日 10:01

    棒棒哒

    回复
  2. Pingback: Modern OpenGL绘制圆柱体 – 源码巴士

发表回复 取消回复

您的邮箱地址不会被公开。 必填项已用 * 标注

近期文章

  • ANR崩溃日志查看方法
  • 通过数学方法来计算short类型的变量w的低八位x和高八位
  • 3dTiles数据解析
  • Games101和Games202脑图汇总
  • LearnOpenGL脑图汇总
  • IBL计算总结
  • C++实现一个简单的语言解释器
  • OpenGL-法线贴图(Normal Mapping)
  • OpenGL-卡通着色(Cartoon)
  • OpenGL几何着色器实现贝塞尔曲线
  • WinDbg检查内存泄漏
  • OpenGL雾化效果实现-每像素雾化
  • OpenGL实现billboard效果(CPU)
  • 算法:寻找异常数字
  • OpenGL 几何着色器的应用
  • Midas XD-构件详图开发
  • Midas XD-选筋助手开发
  • Civil Designer开发-检测规范自动生成控制截面
  • Civil Designer开发-公路桥梁承载能力检算评定
  • Midas W-满堂支架快速建模助手开发

全站热点

  • C++编写的情人节小程序 (2,082)
  • 提取最小封闭区域 (1,696)
  • Modern OpenGL绘制圆柱体 (1,607)
  • OpenGL开发环境搭建-GLFW与GLAD配置 超详细 (1,465)
  • 截面特性计算程序-附源码 (1,290)
  • OpenGL绘制旋转立方体 (1,110)
  • 判断一个点是否在闭合区域内 (1,032)
  • WordPress分页插件 – WP-PageNavi的使用(替换现有脚本) (948)
  • OpenGL实现billboard效果(CPU) (865)
  • Midas W-满堂支架快速建模助手开发 (837)
  • 从DLL中动态加载一个函数:LoadLibrary和GetProcAddress的使用 (748)
  • Midas XD [错误] 右侧挡土墙的最下端深度必须小于地基的最下端深度 (709)
  • 两跨连续梁影响线绘制-附源码 (686)
  • 土木想往土木软件开发方向发展,应该如何准备 (680)
  • OpenGL几何着色器实现贝塞尔曲线 (664)
  • 通过Spy++抓取窗口以查询对话框id (613)
  • 使用ODA数据库出现 “ODA_ASSUME”: 找不到标识符的错误 (547)
  • #pragma message 编译时提示信息 (527)
  • OpenGL雾化效果实现-每像素雾化 (508)
  • midas XD2020的开发 (476)

分类

  • C# (3)
  • C++ (19)
  • GIS (1)
  • MFC (3)
  • ObjectARX (2)
  • OpenGL (11)
  • Revit开发 (1)
  • 学习笔记 (2)
  • 岩土 (2)
  • 算法 (1)
  • 结构设计 (7)
  • 职场生涯 (1)
  • 计算几何 (3)

归档

  • 2024 年 12 月 (1)
  • 2024 年 10 月 (1)
  • 2024 年 9 月 (1)
  • 2023 年 3 月 (2)
  • 2022 年 10 月 (1)
  • 2022 年 3 月 (1)
  • 2022 年 2 月 (1)
  • 2022 年 1 月 (5)
  • 2021 年 11 月 (7)
  • 2021 年 6 月 (3)
  • 2021 年 5 月 (2)
  • 2021 年 3 月 (2)
  • 2021 年 2 月 (8)
  • 2021 年 1 月 (18)

标签

3dtiles anr Bezier Curves BillBoard C++ CDN CivilDesigner DLL EasyX fog glTF MFC Midas W Midas XD NormalMapping ObjectARX ODA OpenGL OpenXML Open XML PBR revit WinDbg 基坑设计 影响线 截面特性 桥梁 桥梁检测 桥梁设计 算法 计算几何 设计模式

书签

  • 李燕良的CSDN
  • 崔济东的博客
  • C++爱好者博客
  • 陈学伟的博客
  • 贾苏的博客
  • 陈睦锋的博客
  • 孙勇的博客

统计

  • 2
  • 152
  • 82
  • 388
  • 145
  • 268,855
  • 77,769

实时访问地域

© 2025   liyanliang.net Copyright. All Rights Reserved.