opengl
YeeKal
•
•
"#"
g++ opengl_demo.cpp -o opengl_demo -lGL -lglut -lGLU
数据
全局: - 位置 - 大小 - 背景色 - look at - perspective
局部个体
- 颜色
- size
- 数据
图元类型
线段 多边形 四边形
- 全局静态变量实现opengl回调到类内部
- 每一个功能包装成函数对象,存储到列表里
- 链表存储函数对象,集合根据名称快速定位是否存在
viewer
drawer: scale, color, pose viewer: global mutux util: default color
- 2d
- points: size, color, pose
- path: line-width, color, pose
- lines (connect between two points), line-width, color, pose
- pologon
- circle
- triangle: size, color, pose, fill
- rectangle: size, color, pose, fill
- 3d
- 3d points
- 3d lines
- 3d path
- polyhedron
- sphere
- cube
- 3d model
- stl
- ply
drawer: inner data update / pose update
environment:
2dmap: - robot: D2Robot - pointRobot - CircleRobot - linkRobot - obstacle: - rectangle - circle
glDrawElements, glDrawArrays
定点数组
//指定需要启动的数组(GL_VERTEX_ARRAY,GL_COLOR_ARRAY,GL_INDEX_ARRAY等8个可用数组)
void glEnableClientState(GLenum array);
void drawCube()
{
// enable and specify pointers to vertex arrays
//指定需要启动的数组(GL_VERTEX_ARRAY,GL_COLOR_ARRAY,GL_INDEX_ARRAY等8个可用数组)
glEnableClientState(GL_NORMAL_ARRAY);
glEnableClientState(GL_COLOR_ARRAY);
glEnableClientState(GL_VERTEX_ARRAY);
// 指定数组数据
glNormalPointer(GL_FLOAT, 0, normals);
glColorPointer(3, GL_FLOAT, 0, colors);
glVertexPointer(3, GL_FLOAT, 0, vertices);
glDrawElements(GL_TRIANGLES, // 绘图模式
36, // 每次读出的点的个数
GL_UNSIGNED_BYTE,
indices); // 索引数组
glDisableClientState(GL_VERTEX_ARRAY); // disable vertex arrays
glDisableClientState(GL_COLOR_ARRAY);
glDisableClientState(GL_NORMAL_ARRAY);
}
//获取当前所哟启用的数组第ith个顶点数据(从0开始算)
void glArrayElement(GLint ith);
//mode指定要创建图元的类型(和glBegin参数相同),count为顶点数量,type为顶点数据类型,indices表示索引数组首地址
//glDrawElements的作用相当于多条glArrayElement(indices[i])
void glDrawElements(GLenum mode,GLsize count,GLenum type,const GLvoid* indices);
//相当于primcount条glDrawElements(mode,count[i],type,indices[i])语句
void glMultiDrawElements(GLenum mode,GLsize* count,GLenum type,const GLvoid** indices,GLsizei primcount);
//相当于有范围的glDrawElements,范围为[start,end]
void glDrawRangeElements(GLenum mode,GLuint start,GLuint end,GLsize count,GLenum type,const GLvoid* indices);
//创建一个图元序列,从每个被启用的数组,范围为[first,first + count - 1]
void glDrawArrays(GLenum mode,GLint first,GLsizei count);
//相当于primcount条glDrawArrays(mode,first[i],count[i])
void glMultiDrawArrays(GLenum mode,GLint* first,GLsizei* count,GLsizei primcount);
光照和材质
- 光照模型
- 全局环境光
- 环境光:环境光是一种无处不在的光。环境光源放出的光线被认为来自任何方向。因此,当你仅为场景指定环境光时,所有的物体无论法向量如何,都将表现为同样的明暗程度
- 镜面光:反射到某一个方向
- 散射光:
-
光源
-
环境光:环境光是一种无处不在的光。环境光源放出的光线被认为来自任何方向。因此,当你仅为场景指定环境光时,所有的物体无论法向量如何,都将表现为同样的明暗程度
- 点光源:来自同一点
- 平行光:反射到某一个方向
- 聚光灯:锥体光源,像手电筒
// set light
void glLightfv (GLenum light, GLenum pname, const GLfloat *params);
// 位置在(0,0,0),没有环境光,镜面反射光和漫反射光都为白光的光源
GLfloat light_position[] = { 0.0, 0.0, 0.0, 0.0 }; // -1 表示无限远
GLfloat light_ambient [] = { 0.0, 0.0, 0.0, 1.0 };
GLfloat light_diffuse [] = { 1.0, 1.0, 1.0, 1.0 };
GLfloat light_specular[] = { 1.0, 1.0, 1.0, 1.0 };
glLightfv(GL_LIGHT0, GL_POSITION, light_position);
glLightfv(GL_LIGHT0, GL_AMBIENT , light_ambient ); // 环境光
glLightfv(GL_LIGHT0, GL_DIFFUSE , light_diffuse ); // 漫反射
glLightfv(GL_LIGHT0, GL_SPECULAR, light_specular); // 镜面光
// open light
glEnable(GL_LIGHTING)
glEnable(GL_LIGHTX)
// depth
display: glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
init: glEnable(GL_DEPTH_TEST);
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH);
```、
材质:
```cpp
// set material
void glMaterialfv (GLenum face, GLenum pname, const GLfloat *params);
/**
face: 表明当前材质应该应用到物体的哪一个面上
GL_FRONT、GL_BACK、GL_FRONT_AND_BACK
pname:
GL_SHINESS
**/
坐标系
右手坐标系
^ y
|
|
|
-------------> x
/
/
/
z
void ViewerManager::getGlobalTrans(){
Eigen::Vector3f gtrans={x_trans_, y_trans_,z_trans_};
Eigen::Isometry3f t_n =Eigen::Isometry3f::Identity();
t_n.pretranslate(gtrans);
model_view_ = cam_view_ * t_n.inverse() * cam_view_.inverse() * model_view_;
}
void ViewerManager::getGlobalRot(){
Eigen::Vector3f axis={ -y_angle_,x_angle_,0};
float scale = axis.norm();
Eigen::Vector3f axis_n=axis.normalized();
Eigen::Vector3f gtrans={x_trans_, y_trans_,z_trans_};
std::cout<<"gangle:\n"<<axis.transpose()<<std::endl;
std::cout<<"gtrans:\n"<<gtrans.transpose()<<std::endl;
Eigen::Matrix3f rot;
rot=Eigen::AngleAxisf(scale, axis_n);
Eigen::Isometry3f t_n =Eigen::Isometry3f::Identity();
t_n.prerotate(rot);
t_n.pretranslate(gtrans);
// 按照屏幕坐标旋转,容易转过视野
// model_view_ = cam_view_ * t_n.inverse() * cam_view_.inverse() * model_view_;
// 按照视觉中心点旋转
// model_view_ = model_view_ *t_n;
// 按照自身坐标系旋转
// model_view_ = t_n * model_view_;
// 按照视觉中心点的位置和屏幕坐标的方向
Eigen::Isometry3f c_c=cam_view_;
c_c(0,3) = 0;
c_c(1,3) = 0;
c_c(2,3) = 0;
Eigen::Vector3f axis_origin=c_c * axis_n;
Eigen::Matrix3f rot2;
rot2=Eigen::AngleAxisf(scale, axis_origin);
Eigen::Isometry3f t_n2 =Eigen::Isometry3f::Identity();
t_n2.prerotate(rot2);
model_view_ = t_n2 * model_view_;
}
观察矩阵变换关系
- $T_c$: camera transformation relative to world
- $T_m$: model global transformation relative to world
- $T_n$: new camera transformation
鼠标与观察矩阵变换关系:
# 鼠标屏幕坐标 opengl 画面坐标
-----------> x | y
| |
| |
| y ------------> x
鼠标右移 mx增大 相机相反 相机x减小 dx = - (x -last_x) rot_y =(x-last_x)
鼠标上移 my减小 画面y增大 相机y减小 dy = (y -last_y) rot_x = (y-last_y)
- model transformation(model matrix): 物体在世界坐标中的位置变换
- view transformation(view matrix): 视图变换,观察者从哪个视角观察
- projection transformation: 投影变换,观察的结果以那种投影方式呈现
- viewport: 视口变换,对观察空间的裁剪
视图变换必须出现在模型变换之前,但可以在绘图之前的任何时候执行投影变换和视口变换。
// 对矩阵进行选择
glMatrixMode(mode);
/*
mode: GL_MODELVIEW, GL_PROJECTION, and GL_TEXTURE
模型视图变换(GL_MODELVIEW):从“相对移动”的观点来看,改变观察点的位置与方向和改变物体本身的位置与方向具有等效性。
透视投影变换(GL_PROJECTION):定义一个可视空间,可视空间以外的物体不会被绘制到屏幕上。
视图变换(glViewPort):通常情况下,程序默认像素填充整个窗口,通过视口变换设置像素在窗口上的填充情况。
视口变换(glViewPort):通常情况下,程序默认像素填充整个窗口,通过视口变换设置像素在窗口上的填充情况。
*/
void glPushMatrix(void);
void glPopMatrix(void);
/**
每一次push都把当前变换矩阵存入栈中,接下来操作都在当前矩阵上改变。因此push可以看作是一次镜像拷贝。当前矩阵操作完成之后,调用pop,移出栈,矩阵回退到矩阵拷贝之前的状态。
**/
anti-aliasing
glutInitDisplayMode(GLUT_DOUBLE | GLUT_RGBA | GLUT_DEPTH | GLUT_MULTISAMPLE);
glEnable(GL_MULTISAMPLE);
变换方式
/*************** 视图变换 ****************/
// 默认 照相机位于原点,指向z轴负方向,朝上向量为(0,1,0)
// creates a viewing matrix
void gluLookAt(
GLdouble eyeX, GLdouble eyeY, GLdouble eyeZ, // position of the eye point
GLdouble centerX, GLdouble centerY, GLdouble centerZ, // position to look at
GLdouble upX, GLdouble upY, GLdouble upZ // the up vector
);
/*************** 视口变换 ****************/
// set the viewport
// 设定图像最终显示在屏幕哪个区域,默认为整个屏幕
void glViewport( GLint x,
GLint y,
GLsizei width,
GLsizei height);
/*************** 空间变换 ****************/
glMatrixMode(GL_MODELVIEW);
// 以某一向量进行旋转
void glRotatef( GLfloat angle,
GLfloat x,
GLfloat y,
GLfloat z);
void glTranslatef( GLfloat x,
GLfloat y,
GLfloat z);
void glScalef( GLfloat x,
GLfloat y,
GLfloat z);
/*************** 投影变换 ****************/
// 0. prepare
glMatrixMode(GL_PROJECTION); // declare a projection matrix
glLoadIdentity(); // set it ot identity
// 1. 正投影变换
glOrtho(左,右,下,上,近,远);
void gluOrtho2D( GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top);
// 2. 透视投影
// glFrustum — multiply the current matrix by a perspective matrix
void glFrustum( GLdouble left,
GLdouble right,
GLdouble bottom,
GLdouble top,
GLdouble nearVal,
GLdouble farVal);
// 3. 透视投影的另一种方式
// gluPerspective — set up a perspective projection matrix
/*
fovy
Specifies the field of view angle, in degrees, in the y direction.
aspect
Specifies the aspect ratio that determines the field of view in the x direction. The aspect ratio is the ratio of x (width) to y (height).
zNear
Specifies the distance from the viewer to the near clipping plane (always positive).
zFar
Specifies the distance from the viewer to the far clipping plane (always positive).
*/
void gluPerspective( GLdouble fovy,
GLdouble aspect,
GLdouble zNear,
GLdouble zFar);
几何图元
2D
GL_POINTS、GL_LINES、GL_LINE_STRIP、GL_LINE_LOOP、GL_TRIANGLES、GL_TRIANGLE_STRIP、GL_TRIANGLE_FAN、GL_QUADS、GL_QUAD_STRIP和GL_POLYGON
3D
glutWireCube(1); // 正方体线框
glutSolidSphere(re(GLdouble radius, GLint slices, GLint stacks);
// ref: https://www.opengl.org/resources/libraries/glut/spec3/node80.html#SECTION000120000000000000000
11.1 glutSolidSphere, glutWireSphere
11.2 glutSolidCube, glutWireCube
11.3 glutSolidCone, glutWireCone
11.4 glutSolidTorus, glutWireTorus
11.5 glutSolidDodecahedron, glutWireDodecahedron
11.6 glutSolidOctahedron, glutWireOctahedron
11.7 glutSolidTetrahedron, glutWireTetrahedron
11.8 glutSolidIcosahedron, glutWireIcosahedron
11.9 glutSolidTeapot, glutWireTeapot
鼠标旋转平移缩放
// 方案1 改变视图
// 方案2 改变全局物体变换(常用)
glRotatef(x_angle, 0.0f, 1.0f, 0.0f); // 旋转 x
glRotatef(y_angle, 1.0f, 0.0f, 0.0f); // 旋转 y
glTranslatef(x_trans,y_trans, m_scale); // 平移 + 缩放 (缩放通过z轴移动来实现)
2d demo
#include <GL/glut.h>
#include <stdio.h>
void displayCB(void){
glClear(GL_COLOR_BUFFER_BIT); /* clear the display */
glColor3f(0.5, 0.8, 0.5); /* set current color to white */
glBegin(GL_POLYGON); /* draw filled triangle */
glVertex2i(200,125); /* specify each vertex of triangle */
glVertex2i(100,375);
glVertex2i(300,375);
glEnd(); /* OpenGL draws the filled triangle */
glFlush(); /* Complete any pending operations */
}
void keyCB(unsigned char key, int x , int y){
if(key == 'q' || key =='Q') exit(0);
}
int main(int argc, char ** argv){
glutInit(&argc, argv);
glutInitDisplayMode(GLUT_RGB);
glutInitWindowPosition(400,300);
glutInitWindowSize(640,480);
glutCreateWindow("simple 2d");
glClearColor(1.0,1.0,1.0, 1.0); // set background to black
gluOrtho2D(0, 400, 0, 500); // set display range: x~[0-400], y~[0-500]
glutDisplayFunc(displayCB);
glutKeyboardFunc(keyCB);
glutMainLoop();
return 0;
}
ref
- blog
- code
- project
- paper