OpenGL做一个坐标系指示方位

我们试着用OpengGL来画一个坐标系,方便我们知道我们的模型当前的位置和方向。做好的坐标系类似下面的效果(中间的停顿效果是因为绘图程序是用主程序的空余时间来画的,如果鼠标按住标题栏,标题栏重绘的时候,就不会处理绘图程序了)。

OpenGL除了能画3D模型,渲染外,也可以画线。下面是一段画坐标箭头的代码,供参考。

首先要加载数据到缓存区

//箭头数据,每两个点为一组,画一条线段    
glm::vec3 box[34] = {
		{ 0, 0, 0.f },
		{ 1, 0, 0.f },
		{ 1, 0, 0.f },
		{ 0.7, 0.1, 0.f },
		{ 1, 0, 0.f },
		{ 0.7, -0.1, 0.f },
        { 1.2, 0.1, 0.f },
        { 1.3, -0.1, 0.f },
        { 1.2, -0.1, 0.f },
        { 1.3, 0.1, 0.f },

		{ 0, 0, 0.f },
		{ 0, 1, 0.f },
		{ 0, 1, 0.f },
		{ 0.1, 0.7, 0.f },
		{ 0, 1, 0.f },
		{ -0.1, 0.7, 0.f },
		{ 0.05, 1.3, 0.f },
        { 0, 1.2, 0.f },
        { -0.05, 1.3, 0.f },
        { 0, 1.2, 0.f },
        { 0, 1.2, 0.f },
        { 0, 1.1, 0.f },

        { 0, 0, 0.0f },
		{ 0, 0, 1.0f },
		{ 0, 0, 1.0f },
		{ 0.1, 0.0, 0.7f },
		{ 0, 0, 1.0f },
		{ -0.1, 0.0, 0.7f },
		{ -0.05, 0, 1.2f },
		{ 0.05, 0, 1.2f },
		{ 0.05, 0, 1.2f },
		{ -0.05, 0.0, 1.1f },
		{ -0.05, 0, 1.1f },
		{ 0.05, 0.0, 1.1f }
	};
	std::vector<float> pvalues;
     for(int i=0;i<sizeof(box);i++)
    {
        pvalues.push_back(box[i][0]);
        pvalues.push_back(box[i][1]);
        pvalues.push_back(box[i][2]);
    }

    glGenVertexArrays(1,vao);
    glGenBuffers(1,vbo);
    //绑定到vao
    glBindVertexArray(vao[0]);
    glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);
    //缓存数据
    glBufferData(GL_ARRAY_BUFFER,pvalues.size()*4,&pvalues[0],GL_STATIC_DRAW);
    //指定数据格式
    glVertexAttribPointer(0,3,GL_FLOAT,GL_FALSE,0,0);
    glEnableVertexAttribArray(0);
    //松绑
    glBindVertexArray(0);

绘图代码如下:

glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
glDepthFunc(GL_LEQUAL);
/获取统一变量地址
scene.mvLoc=glGetUniformLocation(renderingProgram,"mv_matrix");

    scene.vMat=glm::translate(glm::mat4(1.0f),glm::vec3(-camera.camerax,-camera.cameray,-camera.cameraz));               scene.mMat=glm::translate(glm::mat4(1.0f),glm::vec3(mytorus.locx,mytorus.locy,mytorus.locz));
    scene.mMat*= glm::rotate(glm::mat4(1.0f), (float)(mytorus.rotateangle),glm::vec3(1.0f,1.0f,0.0f));
    scene.mvMat=scene.vMat*scene.mMat;
glUniformMatrix4fv(scene.mvLoc,1,GL_FALSE,glm::value_ptr(scene.mvMat));

glBindVertexArray(vao[0]);
glDisable(GL_LIGHTING);
glDisable(GL_DEPTH_TEST);
glColor3f(0.f, 1.f, 1.f);
glLineWidth(5.0f);

glDrawArrays(GL_LINES, 0, 34);

glEnable(GL_LIGHTING);
glEnable(GL_DEPTH_TEST);
glBindVertexArray(0);

效果图如下

也可以添加线条做成网格

结合圆环的绘制和变换矩阵,可以得到下面的动画效果:

熟悉GLSL的可以通过增加一个变量,将纹理颜色和普通颜色区分出来,就可以得到下面的结果。

 顶点着色器代码:

#version 430

layout (location = 0) in vec3 position;
layout (location = 1) in vec2 tex_coord;
layout (location = 2) in vec4 dcolor;
out vec2 tc;
out vec4 dc;
uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
layout (binding=0) uniform sampler2D s;

void main(void)
{	gl_Position = proj_matrix * mv_matrix * vec4(position,1.0);
	tc = tex_coord;
	dc=dcolor;
}

片段着色器代码:

#version 430

in vec2 tc;
in vec4 dc;
out vec4 color;

uniform mat4 mv_matrix;
uniform mat4 proj_matrix;
layout (binding=0) uniform sampler2D s;

void main(void)
{
	if(dc[3]==1.0f)
    {
        color=dc;
    }else
    {
        color = texture(s,tc);
    }
}

最后贴出整个主程序的代码(绘图代码有点啰嗦,懂vao的自己简化下):

#include <windows.h>
#define STB_IMAGE_IMPLEMENTATION
#include "stb_image.h"
#include <gl/gl.h>

#include "Globalv.h"

using namespace std;

void LoadAxle(void)
{
    glm::vec3 box[54] = {
        //x轴
		{ 0.0f, 0.0f, 0.0f },
		{ 5.0f, 0.0f, 0.0f },
		{ 5.0f, 0.0f, 0.0f },
		{ 4.7f, 0.1f, 0.0f },
		{ 5.0f, 0.0f, 0.0f },
		{ 4.7f, -0.1f, 0.0f },
        { 5.2f, 0.1f, 0.0f },
        { 5.3f, -0.1f, 0.0f },
        { 5.2f, -0.1f, 0.0f },
        { 5.3f, 0.1f, 0.0f },
        //y轴
		{ 0.0f, 0.0f, 0.0f },   //10
		{ 0.0f, 5.0f, 0.0f },
		{ 0.0f, 5.0f, 0.0f },
		{ 0.1f, 4.7f, 0.0f },
		{ 0.0f, 5.0f, 0.0f },
		{ -0.1f, 4.7f, 0.0f },
		{ 0.05f, 5.3f, 0.0f },
        { 0.0f, 5.2f, 0.0f },
        { -0.05f, 5.3f, 0.0f },
        { 0.0f, 5.2f, 0.0f },
        { 0.0f, 5.2f, 0.0f },
        { 0.0f, 5.1f, 0.0f },
        //z轴
        { 0.0f, 0.0f, 0.0f },   //22
		{ 0.0f, 0.0f, 5.0f },
		{ 0.0f, 0.0f, 5.0f },
		{ 0.1f, 0.0f, 4.7f },
		{ 0.0f, 0.0f, 5.0f },
		{ -0.1f, 0.0f, 4.7f },
		{ -0.05f, 0.0f, 5.2f },
		{ 0.05f, 0.0f, 5.2f },
		{ 0.05f, 0.0f, 5.2f },
		{ -0.05f, 0.0f, 5.1f },
		{ -0.05f, 0.0f, 5.1f },
		{ 0.05f, 0.0f, 5.1f },

        //网格横线
		{ 0.0f, 0.0f, 0.0f },   //34
		{ 0.0f, 4.0f, 0.0f },
		{ 1.0f, 0.0f, 0.0f },
		{ 1.0f, 4.0f, 0.0f },
		{ 2.0f, 0.0f, 0.0f },
		{ 2.0f, 4.0f, 0.0f },
		{ 3.0f, 0.0f, 0.0f },
		{ 3.0f, 4.0f, 0.0f },
		{ 4.0f, 0.0f, 0.0f },
		{ 4.0f, 4.0f, 0.0f },
        //网格竖线
        { 0.0f, 0.0f, 0.0f },   //44
		{ 4.0f, 0.0f, 0.0f },
		{ 0.0f, 1.0f, 0.0f },
		{ 4.0f, 1.0f, 0.0f },
		{ 0.0f, 2.0f, 0.0f },
		{ 4.0f, 2.0f, 0.0f },
		{ 0.0f, 3.0f, 0.0f },
		{ 4.0f, 3.0f, 0.0f },
		{ 0.0f, 4.0f, 0.0f },
		{ 4.0f, 4.0f, 0.0f }

	};
	std::vector<float> pvalues;
	std::vector<float> dvalues;
	glm::vec4 dcolor={0.0f,0.0f,1.0f,1.0f};
	glm::vec4 ecolor={1.0f,0.0f,0.0f,1.0f};
	glm::vec4 fcolor={0.0f,1.0f,0.0f,1.0f};
	glm::vec4 gcolor={1.0f,1.0f,0.0f,1.0f};
    for(int i=0;i<sizeof(box);i++)
    {
        pvalues.push_back(box[i][0]);
        pvalues.push_back(box[i][1]);
        pvalues.push_back(box[i][2]);
        if(i<=9 or i==44 or i==45)
        {
            dvalues.push_back(dcolor[0]);
            dvalues.push_back(dcolor[1]);
            dvalues.push_back(dcolor[2]);
            dvalues.push_back(dcolor[3]);
        }else if(i<=21 or i==34 or i==35)
        {
            dvalues.push_back(ecolor[0]);
            dvalues.push_back(ecolor[1]);
            dvalues.push_back(ecolor[2]);
            dvalues.push_back(ecolor[3]);
        }else if(i<=33)
        {
            dvalues.push_back(fcolor[0]);
            dvalues.push_back(fcolor[1]);
            dvalues.push_back(fcolor[2]);
            dvalues.push_back(fcolor[3]);
        }else
        {
            dvalues.push_back(gcolor[0]);
            dvalues.push_back(gcolor[1]);
            dvalues.push_back(gcolor[2]);
            dvalues.push_back(gcolor[3]);
        }

    }
    glBindVertexArray(vao[0]);
    glBindBuffer(GL_ARRAY_BUFFER,vbo[0]);
    glBufferData(GL_ARRAY_BUFFER,pvalues.size()*4,&pvalues[0],GL_STATIC_DRAW);
    glBindBuffer(GL_ARRAY_BUFFER,vbo[1]);
    glBufferData(GL_ARRAY_BUFFER,dvalues.size()*4,&dvalues[0],GL_STATIC_DRAW);
    glBindVertexArray(0);
}

void LoadBuffer(void)
{
    std::vector<int> ind=mytorus.getIndices();
    std::vector<glm::vec3> vert =mytorus.getVertices();
    std::vector<glm::vec2> tex=mytorus.getTexCoords();
    std::vector<glm::vec3> norm=mytorus.getNormals();

    std::vector<float> pvalues;
    std::vector<float> tvalues;
    std::vector<float> nvalues;
    std::vector<float> dvalues;

    int numVertices=mytorus.getNumVertices();
    for(int i=0;i<numVertices;i++)
    {
        pvalues.push_back(vert[i].x);
        pvalues.push_back(vert[i].y);
        pvalues.push_back(vert[i].z);

        tvalues.push_back(tex[i].s);
        tvalues.push_back(tex[i].t);

        nvalues.push_back(norm[i].x);
        nvalues.push_back(norm[i].y);
        nvalues.push_back(norm[i].z);
        dvalues.push_back(0.0f);
        dvalues.push_back(0.0f);
        dvalues.push_back(0.0f);
        dvalues.push_back(0.0f);
    }
    glBindVertexArray(vao[1]);

    glBindBuffer(GL_ARRAY_BUFFER,vbo[2]);
    glBufferData(GL_ARRAY_BUFFER,pvalues.size()*4,&pvalues[0],GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER,vbo[3]);
    glBufferData(GL_ARRAY_BUFFER,tvalues.size()*4,&tvalues[0],GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER,vbo[4]);
    glBufferData(GL_ARRAY_BUFFER,nvalues.size()*4,&nvalues[0],GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER,vbo[5]);
    glBufferData(GL_ARRAY_BUFFER,dvalues.size()*4,&dvalues[0],GL_STATIC_DRAW);

    glBindBuffer(GL_ARRAY_BUFFER,ebo);
    glBufferData(GL_ARRAY_BUFFER,ind.size()*4,&ind[0],GL_STATIC_DRAW);
    glBindVertexArray(0);
}

void InitOpenGL(void)
{

    //1.0 初始化数据
    camera.camerax=2.0f;camera.cameray=1.0f;camera.cameraz=8.5f;
    camera.rotateangle=0.1f;
    mytorus.locx=0.0f;mytorus.locy=0.0f;mytorus.locz=0.0f;
    mytorus.rotateangle=0.1f;

    //1.1B 编译并使用纹理可编程管线
    renderingProgram =mycorelib.createShaderProgram("vert.glsl", "frag.glsl");
    //1.2B 选择指定的管线
    glUseProgram(renderingProgram);
    //1.3B  透视矩阵设置
    scene.projLoc=glGetUniformLocation(renderingProgram,"proj_matrix");
    scene.aspect=(float)scene.screenWidth/(float)scene.screenHeight;
    scene.pMat=glm::perspective(1.0472f,scene.aspect,0.1f,1000.0f);                 
    //1.0472radians=60degree
    glUniformMatrix4fv(scene.projLoc,1,GL_FALSE,glm::value_ptr(scene.pMat));

    glGenVertexArrays(2,vao);
    glGenBuffers(6,vbo);
    glGenBuffers(1, &ebo);
    LoadAxle();
    //1.4B
    LoadBuffer();


    //加载图片,制作纹理,贴图;除了这里加载图片外,还要在下面计算出贴图坐标,将其传到着色器里
    int width,height,nrChannels;
    glGenTextures(1, &texture);
    unsigned char *data1=stbi_load("brick.jpg",&width,&height,&nrChannels,0);
    glBindTexture(GL_TEXTURE_2D, texture);
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data1);
    glGenerateMipmap(GL_TEXTURE_2D);
    stbi_image_free(data1);
}

void DrawModel(float theta)
{

    glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
    glClear(GL_COLOR_BUFFER_BIT| GL_DEPTH_BUFFER_BIT);
    glDepthFunc(GL_LEQUAL);

    scene.mvLoc=glGetUniformLocation(renderingProgram,"mv_matrix");
    scene.vMat=glm::translate(glm::mat4(1.0f),glm::vec3(-camera.camerax,-camera.cameray,-camera.cameraz));
    glUniformMatrix4fv(scene.mvLoc,1,GL_FALSE,glm::value_ptr(scene.vMat));

    glDisable(GL_LIGHTING);
	glDisable(GL_DEPTH_TEST);
	glColor3f(0.0f, 1.0f, 1.0f);
	glLineWidth(2.0f);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
    glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(2);
    glDrawArrays(GL_LINES, 0, 54);
    glEnable(GL_LIGHTING);
	glEnable(GL_DEPTH_TEST);
    glBindVertexArray(0);

    scene.mMat=glm::translate(glm::mat4(1.0f),glm::vec3(mytorus.locx,mytorus.locy,mytorus.locz));
    scene.mMat*=glm::rotate(glm::mat4(1.0f), (float)(mytorus.rotateangle),glm::vec3(1.0f,0.0f,0.0f));
    scene.mvMat=scene.vMat*scene.mMat;
    glUniformMatrix4fv(scene.mvLoc,1,GL_FALSE,glm::value_ptr(scene.mvMat));

    //第一步,先保存原始位置到栈里
    mvStack.push(scene.mvMat);
    int mvsize=mvStack.size();

    glBindBuffer(GL_ARRAY_BUFFER, vbo[2]);
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(0);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[3]);
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(1);

    glBindBuffer(GL_ARRAY_BUFFER, vbo[5]);
    glVertexAttribPointer(2, 4, GL_FLOAT, GL_FALSE, 0, 0);
    glEnableVertexAttribArray(2);

    glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ebo);
    glDrawElements(GL_TRIANGLES, mytorus.getNumIndices(), GL_UNSIGNED_INT, 0);
    //在前面旋转的圆环的基础上,平移一个距离
    mvStack.top()*=glm::translate(glm::mat4(1.0f), glm::vec3(0.0f,1.0f,0.0f));

    glUniformMatrix4fv(scene.mvLoc,1,GL_FALSE,glm::value_ptr(mvStack.top()));
    glDrawElements(GL_TRIANGLES, mytorus.getNumIndices(), GL_UNSIGNED_INT, 0);

    mvStack.pop();
    mvsize=mvStack.size();
}

int WINAPI WinMain(HINSTANCE hInstance,
                   HINSTANCE hPrevInstance,
                   LPSTR lpCmdLine,
                   int nCmdShow)
{

    HWND hwnd;
    HDC hDC;
    HGLRC hRC;
    MSG msg;
    BOOL bQuit = FALSE;

    if(myform.RegistWinform(hInstance)==0)
        return 0;

    /* create main window */
    hwnd = CreateWindowEx(0,"GLSample","OpenGL Sample",
                          WS_OVERLAPPEDWINDOW,
                          360,200,683,384,
                          NULL,NULL,hInstance,NULL);

    ShowWindow(hwnd, nCmdShow);

    /* enable OpenGL for the window */
    mycorelib.EnableOpenGL(hwnd, &hDC, &hRC);

    InitOpenGL();
    /* program main loop */
    while (!bQuit)
    {
        /* check for messages */
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
        {
            myform.WatchMessage(msg,&bQuit);
        }
        else
        {
            DrawModel(mytorus.rotateangle);
            SwapBuffers(hDC);
            mytorus.rotateangle += 0.01f;
            Sleep (20);
        }
    }

    /* shutdown OpenGL */
    mycorelib.DisableOpenGL(hwnd, hDC, hRC);

    /* destroy the window explicitly */
    DestroyWindow(hwnd);

    return msg.wParam;
}

上传文件用于测试效果,附件链接:

GLSL画坐标系用于显示模型位置-其他文档类资源-CSDN下载

  • 5
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
要使用OpenGL绘制三维坐标系,需要进行以下步骤: 1. 首先,需要设置OpenGL的视口和投影矩阵,以确保正确的视角和透视效果。这可以通过glViewport和gluPerspective函数来实现。 2. 接下来,需要定义三个向量表示坐标系的三个轴,通常是X轴,Y轴和Z轴。 3. 然后,可以使用OpenGL的绘图函数(如glBegin和glEnd)来绘制每个轴线。对于每个轴线,需要先设置颜色,然后使用glVertex3f指定起点和终点。 以下是一个基本的OpenGL代码示例,用于绘制一个简单的三维坐标系: ``` void drawAxes() { // 设置视口和投影矩阵 glViewport(0, 0, windowWidth, windowHeight); glMatrixMode(GL_PROJECTION); glLoadIdentity(); gluPerspective(45.0, (double)windowWidth / (double)windowHeight, 0.1, 100.0); // 定义坐标系三个轴的向量 vec3 xAxis = vec3(1, 0, 0); vec3 yAxis = vec3(0, 1, 0); vec3 zAxis = vec3(0, 0, 1); // 绘制X轴 glColor3f(1.0, 0.0, 0.0); glBegin(GL_LINES); glVertex3f(0.0, 0.0, 0.0); glVertex3f(1.0, 0.0, 0.0); glEnd(); // 绘制Y轴 glColor3f(0.0, 1.0, 0.0); glBegin(GL_LINES); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 1.0, 0.0); glEnd(); // 绘制Z轴 glColor3f(0.0, 0.0, 1.0); glBegin(GL_LINES); glVertex3f(0.0, 0.0, 0.0); glVertex3f(0.0, 0.0, 1.0); glEnd(); } ``` 这段代码包含一个名为“drawAxes”的函数,该函数在OpenGL窗口中绘制了一个三维坐标系。注意,这只是一个基本示例,您可以根据需要自定义颜色,坐标轴的长度和粗细等参数。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

水滴与鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值