0.1. 资料

泡沫机器人

github
example

opengl中视频机的地方,观看标大势

gluLookAt函数

澳门金沙国际 1

0.1. 资料

泡沫机器人

github
example

opengl中摄像机的地点,旁观的大方向

gluLookAt函数

澳门金沙国际 2

刚发轫学习opengl,做的首先个实验,就是显得圆柱体

澳门金沙国际 3

0.2. 行使表明

应用这一个gluLookAt矩阵坐标观察矩阵可以很便捷地把具备世界坐标变换为洞察坐标LookAt矩阵

find_package(Pangolin REQUIRED)
include_directories(${Pangolin_INCLUDE_DIRS})

target_link_libraries(pangolin_test ${Pangolin_LIBRARIES})

Github 下有个example有一部分例子,不难的参考着写,复杂的推断须要查opengl.

0.2. 拔取验证

接纳那么些gluLookAt矩阵坐标观看矩阵可以很迅猛地把全部世界坐标变换为考察坐标LookAt矩阵

find_package(Pangolin REQUIRED)
include_directories(${Pangolin_INCLUDE_DIRS})

target_link_libraries(pangolin_test ${Pangolin_LIBRARIES})

Github 下有个example有一对事例,不难的参照着写,复杂的估价须要查opengl.

其一通过opengl库中的api函数gluCylinder()就可以来得出来,不过最为蛋疼的是,完全看不出它是一个圆柱啊

timg.jpeg

0.3. HelloPangolin

#include <iostream>
#include <pangolin/pangolin.h>

int main(int argc, char **argv)
{
    //创建一个窗口
    pangolin::CreateWindowAndBind("Main",640,480);
    //启动深度测试
    glEnable(GL_DEPTH_TEST);

    // Define Projection and initial ModelView matrix
    pangolin::OpenGlRenderState s_cam(
            pangolin::ProjectionMatrix(640,480,420,420,320,240,0.2,100),
            //对应的是gluLookAt,摄像机位置,参考点位置,up vector(上向量)
            pangolin::ModelViewLookAt(0,-10,0.1,0,0,0,pangolin::AxisNegY)
    );

    // Create Interactive View in window
    pangolin::Handler3D handler(s_cam);
    //setBounds 跟opengl的viewport 有关
    //看SimpleDisplay中边界的设置就知道
    pangolin::View &d_cam = pangolin::CreateDisplay().SetBounds(0.0,1.0,0.0,1.0,-640.0f/480.0f)
                            .SetHandler(&handler);

    while(!pangolin::ShouldQuit())
    {
        // Clear screen and activate view to render into
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        d_cam.Activate(s_cam);

        // Render OpenGL Cube
//        pangolin::glDrawColouredCube();\
        //坐标轴的创建
        pangolin::glDrawAxis(3);

        //点的创建
        glPointSize(10.0f);
        glBegin(GL_POINTS);
        glColor3f(1.0,1.0,1.0);
        glVertex3f(0.0f,0.0f,0.0f);
        glVertex3f(1,0,0);
        glVertex3f(0,2,0);
        glEnd();

        //把下面的点都做一次旋转变换
        glPushMatrix();
        //col major
        std::vector<GLfloat > Twc = {1,0,0,0, 0,1,0,0 , 0,0,1,0 ,0,0,5,1};
        glMultMatrixf(Twc.data());

        //直线的创建
        const float w = 2;
        const float h = w*0.75;
        const float z = w*0.6;
        glLineWidth(2);
        glColor3f(1.0,0,0);
        glBegin(GL_LINES);

        glVertex3f(0,0,0);
        glVertex3f(w,h,z);
        glVertex3f(0,0,0);
        glVertex3f(w,-h,z);
        glVertex3f(0,0,0);
        glVertex3f(-w,-h,z);
        glVertex3f(0,0,0);
        glVertex3f(-w,h,z);
        glVertex3f(w,h,z);
        glVertex3f(-w,h,z);
        glVertex3f(-w,h,z);
        glVertex3f(-w,-h,z);
        glVertex3f(-w,-h,z);
        glVertex3f(w,-h,z);
        glVertex3f(w,-h,z);
        glVertex3f(w,h,z);
        glEnd();

        glPopMatrix();

        // Swap frames and Process Events
        pangolin::FinishFrame();
    }

    return 0;

}

0.3. HelloPangolin

#include <iostream>
#include <pangolin/pangolin.h>

int main(int argc, char **argv)
{
    //创建一个窗口
    pangolin::CreateWindowAndBind("Main",640,480);
    //启动深度测试
    glEnable(GL_DEPTH_TEST);

    // Define Projection and initial ModelView matrix
    pangolin::OpenGlRenderState s_cam(
            pangolin::ProjectionMatrix(640,480,420,420,320,240,0.2,100),
            //对应的是gluLookAt,摄像机位置,参考点位置,up vector(上向量)
            pangolin::ModelViewLookAt(0,-10,0.1,0,0,0,pangolin::AxisNegY)
    );

    // Create Interactive View in window
    pangolin::Handler3D handler(s_cam);
    //setBounds 跟opengl的viewport 有关
    //看SimpleDisplay中边界的设置就知道
    pangolin::View &d_cam = pangolin::CreateDisplay().SetBounds(0.0,1.0,0.0,1.0,-640.0f/480.0f)
                            .SetHandler(&handler);

    while(!pangolin::ShouldQuit())
    {
        // Clear screen and activate view to render into
        glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
        d_cam.Activate(s_cam);

        // Render OpenGL Cube
//        pangolin::glDrawColouredCube();\
        //坐标轴的创建
        pangolin::glDrawAxis(3);

        //点的创建
        glPointSize(10.0f);
        glBegin(GL_POINTS);
        glColor3f(1.0,1.0,1.0);
        glVertex3f(0.0f,0.0f,0.0f);
        glVertex3f(1,0,0);
        glVertex3f(0,2,0);
        glEnd();

        //把下面的点都做一次旋转变换
        glPushMatrix();
        //col major
        std::vector<GLfloat > Twc = {1,0,0,0, 0,1,0,0 , 0,0,1,0 ,0,0,5,1};
        glMultMatrixf(Twc.data());

        //直线的创建
        const float w = 2;
        const float h = w*0.75;
        const float z = w*0.6;
        glLineWidth(2);
        glColor3f(1.0,0,0);
        glBegin(GL_LINES);

        glVertex3f(0,0,0);
        glVertex3f(w,h,z);
        glVertex3f(0,0,0);
        glVertex3f(w,-h,z);
        glVertex3f(0,0,0);
        glVertex3f(-w,-h,z);
        glVertex3f(0,0,0);
        glVertex3f(-w,h,z);
        glVertex3f(w,h,z);
        glVertex3f(-w,h,z);
        glVertex3f(-w,h,z);
        glVertex3f(-w,-h,z);
        glVertex3f(-w,-h,z);
        glVertex3f(w,-h,z);
        glVertex3f(w,-h,z);
        glVertex3f(w,h,z);
        glEnd();

        glPopMatrix();

        // Swap frames and Process Events
        pangolin::FinishFrame();
    }

    return 0;

}

即使如此可以因而reshape()来再度定视角,可是每便运行程序,只好展现2个理念,多麻烦啊。

名词解释

pipleline:管线
Pangolin学习。opengl applocation: geometry(几何图形) + texture(纹理贴图)
vertex data(顶点数据):lighting(光照) transform(变换) scale(缩放)
geometry: rasterization(光栅) clipping(剪裁)
fragment(段): fog(雾) + texture
framebuffer(帧缓冲区): stecil(蒙版) z-test:深度测试 阿尔法:透明
blending(混合)
eyeball(眼球)

近平面
远平面
frustum:平截头体,视景体(远近平面之间的台式)
伪变换
GLSurfaceView:GL表层视图输出openGL画面的控件
render: 渲染器,绘制openGL 的类
viewPort : 视口,输出画面的区域
matrix:矩阵

投影:
透视投影:有深度,越远越小(站在铁轨,远处线相交 )
正投影:没有深度概念,相同大小
状态机

gl.glMatrixModel(int
n):矩阵形式,openGL基于状态的,操纵很多矩阵,通过该函数内定使用哪个矩阵
如:GL10.GL_PROJECTION 投影矩阵
GL10.GL_MODELVIEW 模态视图矩阵
钦赐哪个矩阵之后,需求先加载单位矩阵(gl.glLoadIdentity() 类似于矩阵清零)

gl.glFrustumf(,,,,,,)
//参数
left:左侧距离
right:
bottom
top
zNear:近平面距离
zFar:远平面距离

设置眼睛的职位
//眼球的坐标,观望的点,向上的向量
//操作的是模型视图矩阵,须要先安装gl.glMatrixMode(GL10.GL_MODELVIEW);
gluLookAt(GL10 gl, float eyeX, float eyeY, float eyeZ, float centerX,
float centerY, float centerZ, float upX, float upY, float upZ)

首先组eyex, eyey,eyez 相机在世界坐标的地方
其次组centerx,centery,centerz 相机镜头对准的物体在世界坐标的职位
其三组upx,upy,upz 相机向上的倾向在世界坐标中的方向
您把相机想象变为你协调的脑壳:
首先组数据就是底部的地点
其次组数据就是双眼看的物体的职位
其三组就是尾部朝向的自由化(因为您可以歪着头看同一个物体)
参考:http://www.cnblogs.com/jiangu66/archive/2013/04/06/3003122.html
1.末尾的七个参数(0.0,1.0,0.0),y轴为1,其他为0,表示脑袋朝上,就是健康的情形

澳门金沙国际 4

timg.jpeg

如此表示脑袋向下,即人眼倒着看

澳门金沙国际 5

timg.jpeg

即人的头颅像右歪90度来看,即顺时针转90度(换个角度考虑就是壶逆时针转90度)

澳门金沙国际 6

timg.jpeg

0.4. Plot data with ros

参照SimplePlot, !pangolin::ShouldQuit()换成ros::ok(),就可以

参照SimpleDisplay, 可以做出抉择配置

0.4. Plot data with ros

参照SimplePlot, !pangolin::ShouldQuit()换成ros::ok(),就可以

参照SimpleDisplay, 可以做出抉择配置

率先个想做的就是消除录像机难题,让我们得以由此鼠标键盘交互,完毕360度旋转和拓宽减弱。

使用OpenGL步骤

  • 1.创建GLSurfaceView对象
  • 2.创建GLSurfaceView.render实现类
  • 3.设置activity的contentview,以及安装view的render对象
  • 4.兑现render类的长河
    a.onSurfaceCreated()方法
    1.装置清屏的颜色和启用顶点缓冲区
    b.onSurfaceChanged()方法
    1.设置viewPort(视口)
    2.操作投影矩阵,设置平截头体(比例一般和视口比例相同,否则输出画面会走样)
    c.onDrawFrame()方法
    1.革除颜色缓冲区
    gl.glClearColor(0,0,0,1);
    2.操作模型视图矩阵,设置眼球的参数
    gl.glMatrixMode(GL10.GL_MODELVIEW);
    gl.glLoadIdentity();
    GLU.gluLookAt(gl,0,0,0,0,0,5,0,1,0);
    3.定义图形顶点坐标值数组
    4.将顶点坐标转换来缓冲区数据
    5.装置绘图颜色
    6.点名顶点缓冲区指针
    //3.意味3维点,使用八个坐标值表示一个点
    //type:GL10.GL_FLOAT 每种点的数据类型
    //stride:0,跨度
    gl.glVertexPointer(3,GL10.GL_FLOAT,0,ibb);
    7.绘图
    //3. 点的数量
    //0. 起始点
    gl.glDrawArrays(GL10.GL_TRIANGLES,0,3);

 

opengl中的投影有二种,贰个是(平行投影),三个是(透视投影)

(透视投影)符合人们思想习惯,近大远小

就此以下的证实都以基于(透视投影)的。 ps:其实本人还不懂平行投影

 

  1. 行使透视投影

第①main函数中添加

    glutReshapeFunc(reshape);

参数reshape()是函数名,接下去是reshape()函数

void reshape(int w, int h)
{
    glViewport(0, 0, (GLsizei)w, (GLsizei)h);
    glMatrixMode(GL_PROJECTION);
    glLoadIdentity();

    gluPerspective(60.0, (GLfloat)w / (GLfloat)h, 1.0, 20.0);
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();
    gluLookAt(5.0, 5.0, 5.0, 0.0, 0.0, 0.0, 0, 1, 0);
}

而gluLookAt()函数,其实您可以精晓成视频机,

前一个参数是你的眼睛,中间三个参数是您看着的地点,最终一个参数是你的相机的正上方

实际表达可以参照那位大佬的稿子

 

 

民用精晓,gluLookAt()定义了壹个视景矩阵,把(世界坐标系)转换到(视频机坐标系),

下一场由(视频机坐标系)来分解(世界坐标系)中物体的坐标。

现实转换表明,能够参照

以下网址

 恐怕自个儿写的数学基础知识03

 

2.矩阵交替

opengl中资助使用编写的uvn视景矩阵。

创办贰个Point类(点),创造多少个Vector类(向量),创立二个Camera类(视频机)

据悉gluLookAt()的柒个参数,我们一样可以计算出相应的uvn坐标系

先期表达,这些录制机是以世界坐标系(0, 0,
0)为核心来360度移动的,所以只要变换了着力,之后的函数都要做相呼应的改动。

void setCamera(float eyex, float eyey, float eyez,
                   float centerx, float centery, float centerz,
                   float upx, float upy, float upz) 
    {
        eye.set(eyex, eyey, eyez);
        center.set(centerx, centery, centerz);
        up.setV(upx, upy, upz);

        n.setV(center, eye);
        n.normalize();
        u = n.cross(up);
        u.normalize();
        v = u.cross(n);
        v.normalize();

        R = eye.getDist();

        setModeViewMatrix();
    }

center那些点必须是(0, 0, 0);

若果不是(0,0,0),前面旋转函数要做相呼应的修改

参数表达:

eye是世界坐标系的点,坐标系变换涉及到了运动,所以必须保留下去。

GL450是视点主旨到雕塑机的相距,

函数表明:

normalize()是规范化函数,即令向量的模变为1

cross()是叉乘函数,即求出四个不平行向量决定的平面的(法向量)。

末尾目的是使uvn两两垂直。

 

然后是矩阵设置

void setModeViewMatrix() {
        Vector pointV(eye.x, eye.y, eye.z);
        M[0] = u.x; M[1] = v.x; M[2] = -n.x; M[3] = 0;
        M[4] = u.y; M[5] = v.y; M[6] = -n.y; M[7] = 0;
        M[8] = u.z; M[9] = v.z; M[10] = -n.z; M[11] = 0;
        M[12] = -pointV.dot(u);
        M[13] = -pointV.dot(v);
        M[14] = pointV.dot(n);
        M[15] = 1;

        glMatrixMode(GL_MODELVIEW);
        glLoadIdentity();
//        gluLookAt(5.0, 5.0, 5.0, 0.0, 0.0, 0.0, 0, 1, 0);
//        gluLookAt(eye.x, eye.y, eye.z, 0.0, 0.0, 0.0, up.x, up.y, up.z);

        glMultMatrixf(M);  //这句话就是把矩阵M设为视景矩阵
    }

函数表达:

dot()是点乘函数

 

此处的矩阵为何出现负号,和

数学基础知识03

不平等,因为向量是有倾向的,方向有着改变,所以,一定要注意喔。

 

好了,然后大家可以看看效果,可以发现和gluLookAt()没有强烈的差异

 

3.录像机旋转

率先要显然有个别许种旋转格局,

依照查找的素材,可以分为roll,yaw,pitch,具体表达,可以参照大佬的篇章

 

和方面的大佬们的鼠标交互代码达成不相同,本身一直不采纳slide

以下是自己修改后的yaw()函数和pitch()函数

void yaw(float angle) {
        float cs = cos(angle*PI / 180);
        float sn = sin(angle*PI / 180);
        Vector t(n);
        Vector s(u);
        n.setV(cs*t.x - sn*s.x, cs*t.y - sn*s.y, cs*t.z - sn*s.z);
        u.setV(sn*t.x + cs*s.x, sn*t.y + cs*s.y, sn*t.z + cs*s.z);

        eye.set(-R*n.x, -R*n.y, -R*n.z);

        setModeViewMatrix();
    }

void pitch(float angle) {
        float cs = cos(angle*PI / 180);
        float sn = sin(angle*PI / 180);
        Vector t(v);
        Vector s(n);
        v.setV(cs*t.x - sn*s.x, cs*t.y - sn*s.y, cs*t.z - sn*s.z);
        n.setV(sn*t.x + cs*s.x, sn*t.y + cs*s.y, sn*t.z + cs*s.z);

        eye.set(-R*n.x, -R*n.y, -R*n.z);

        setModeViewMatrix();
    }

那三个函数,都添加了修改视频机的点再世界坐标系下的坐标

举个例证,你把视频机往上活动,借使你的眸子不跟上的视频机,你能看见东西吗?

 

鼠标交互函数

    glutMouseFunc(onMouse);
    glutMotionFunc(onMouseMove);

实际函数完结

void onMouse(int button, int state, int x, int y)
{
    if (button == GLUT_LEFT_BUTTON && state == GLUT_DOWN ) {
        LeftMouseOn = true;
        x11 = x;
        y11 = y;
    }
    else if (button == GLUT_RIGHT_BUTTON && state == GLUT_DOWN) {
        RightMouseOn = true;
        x11 = x;
        y11 = y;
    }
    else {
        LeftMouseOn = false;
        RightMouseOn = false;
    }
}

变量表明:

x11,y11是鼠标按下来的时候,从显示屏得到的点坐标

 

接下来是鼠标移动的有关函数

void onMouseMove(int x, int y)
{
    int dx = x - x11;
    int dy = y - y11;
//    int cnt = 10000;
    if (LeftMouseOn == true) {
        RotateX(dx);
        RotateY(dy);
    }
    else if (RightMouseOn == true) {
        RotateRoll(dx);
    }
    x11 = x;
    y11 = y;
    //x11 = x21;
    //y11 = y21;
}

主要表达:

只要鼠标在活动,都要修改当前鼠标的坐标,

举个例子:你从源点出发,向右跑出去了,可是如若你突然向左,你终于向左吗,不会,相对于源点,你照旧向右的。

 

函数表明:

RotateX()是水平方向旋转

RotateY()是竖直方向旋转

此地的档次和竖直指的是显示器的档次和竖直,不是其中物体的

RotateRoll()是视频机自己的团团转,n不变,旋转u和v,即roll

void RotateX(float x_move)
{
    float part_theta = 30;
    float theta = x_move*part_theta*3.14/180;
    cam.yaw(theta);
}

void RotateY(float y_move)
{
    float part_theta = 30;
    float theta = y_move*part_theta*3.14 / 180;
    cam.pitch(theta);
    /*
    theta = theta / cnt;
    for (; cnt != 0; cnt--) {
        cam.pitch(theta);
    }*/
}

void RotateRoll(float x_move)
{
    float part_theta = 30;
    float theta = x_move*part_theta*3.14 / 180;
    cam.roll(theta);
}

数码证实:

part_theta是(旋转角度/每1单位活动距离)

 

4.水墨画机放大减少(伪)

松手减弱的规律,小编是用摄像机和视点距离的远近变化来了然的。

就此自个儿达成的这些函数,与其说视频机放大减少,还不如说是你拿着摄影机向视点走过去。(因为近大远小嘛)

 

先是是键盘交互函数

glutKeyboardFunc(keyboard);

然后是键盘操作函数

void keyboard(unsigned char key, int x, int y)
{
    if (key == 109){
        cam.bsChange(1);
    }
    else if (key == 110){
        cam.bsChange(-1);
    }
}

void bsChange(int d)
    {
        if (d > 0){
            R--;
            eye.set(-R*n.x, -R*n.y, -R*n.z);
        }
        else{
            R++;
            eye.set(-R*n.x, -R*n.y, -R*n.z);
        }

        setModeViewMatrix();
    }

109和110就是某三个按键的码,我们可以通过printf找出别的三个键来使用

澳门金沙国际 ,重复指示:每一回坐标系变换(无论是旋转依旧平移),都要重新设置视景矩阵

 

相关文章