OpenGL实验一

OpenGL简介:
(英语:Open Graphics Library,译名:开放图形库或者“开放式图形库”)是用于渲染2D、3D矢量图形的跨语言、跨平台的应用程序编程接口(API)。这个接口由近350个不同的函数调用组成,用来绘制从简单的图形比特到复杂的三维景象。而另一种程序接口系统是仅用于Microsoft Windows上的Direct3D。OpenGL常用于CAD、虚拟现实、科学可视化程序和电子游戏开发。

开发环境:win10 ,VS-2015

一、预先准备

1.1 安装VS2015

1.2 创建工程目录并复制GLIB至工程目录下


GLIB内文件如下:



二、创建工程

2.1 创建命令行程序

打开vs,点击:文件->新建->项目
打开对话框选择:模板->VC+±>Win32->Win32控制台应用程序
点击确定,进入命令行程序向导

2.2 Win32应用程序向导

点击下一步,打开应用程序设置
应用程序类型:选择“控制台应用程序”
附加选项:全部不选
点击“完成”,生成项目

2.3 指定OpenGL头文件路径

2.4 加入OpenGL静态库、动态库


2.5 包含头文件:在main.cpp中,添加并改写main函数:

2.6 点击:VS->生成->重新生成解决方案,若编译成功,说明编译连接配置是正确的

2.7 调试运行 点击F5运行程序调试成功

三、绘制二维图形

3.1 改写main.cpp

// exp_1.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include<windows.h>
#define GLUT_DISABLE_ATEXIT_HACK
#include "GL/glut.h"
void myDisplay();
void myInit();
int main(int argc,char **argv)
{glutInit(&argc, argv);   //Initialize GLUT function callings//Set window size (width,height)in number of pixelsglutInitWindowSize(400, 400);//Set window position,form the left and top of the screenglutInitWindowPosition(200, 100);//in numbers of pixels//Specify a window creation eventglutCreateWindow("Green Triangle");//Specify the drawing function that is called when the window is created or re-drewglutDisplayFunc(myDisplay);   myInit();  //Invoke this function for initializationglutMainLoop();  //Enter the event processing loopreturn 0; //Indicate normal termination
}
void myDisplay() {glClear(GL_COLOR_BUFFER_BIT); //Clear the frame bufferglColor3f(0.0, 1.0, 0.0);  //Set current color to greenglBegin(GL_POLYGON);   //Draw the triangleglVertex2f(-0.7, -0.7);glVertex2f(0.7, -0.7);glVertex2f(0, 0.7);glEnd();glFlush();   //Force to display the new drawings immediately
}
void myInit() {glClearColor(0.0, 0.0, 0.0, 0.0);  //Set the clear color to black//Specify the boundaries of the view windowglMatrixMode(GL_PROJECTION);glLoadIdentity();//恢复初始坐标gluOrtho2D(-1.0, 1.0, -1.0, 1.0);  //指定世界窗口glMatrixMode(GL_MODELVIEW);
}

3.2 编译运行

四、绘制3D图形

4.1 改写main.cpp

#include "stdafx.h"
#include <windows.h>   //Header File For Windows
#include <GL\GL.h>     //Header File For The OpenGL32 Library
#include <GL\GLU.h>     //Header File For The GLu32 Library
#include <GL\GLAUX.H>   //Header File For the Glaux Library
#define GLUT_DISABLE_ATEXIT_HACK
#include "GL\GLUT.H"
GLfloat rtri;   //Angle For The Triangle (NEW)
GLfloat rquad;  //Angle for the Quad (NEW)
void InitGL(int width, int height);
GLvoid DrawGLScene(GLvoid);
void myReshape(int w, int h);
void myKeyboard(int key, int x, int y);
void myMovedMouse(int x, int y);
int main(int argc, char **argv) {glutInit(&argc, argv);   //Intialize GLUT function callingsglutInitWindowSize(800, 600); //Set widow size (width,height)in number of pixels//Set window positio, from the left and top of the screen,glutInitWindowPosition(200, 100);  //in numbers of pixels//Specify a window creation eventglutCreateWindow("3D Graph");//Specify the drawing function that is called when the windowglutDisplayFunc(DrawGLScene);glutReshapeFunc(myReshape);glutMotionFunc(myMovedMouse);glutSpecialFunc(myKeyboard); //新增键盘响应InitGL(800, 600);   //Invoke this function for initializationglutMainLoop();     // Enter the event processing loopreturn 0;           //Indicate normal termination
}
void InitGL(int width, int height) {myReshape(width, height);glShadeModel(GL_SMOOTH);   //Enable Smooth ShadingglClearColor(0.0f, 0.0f, 0.0f, 0.5f); //BlackBackgroundglClearDepth(1.0f);//Depth Buffer SetupglEnable(GL_DEPTH_TEST); //Enables Depth TestingglDepthFunc(GL_LEQUAL);  //The Type of Depth Testing To DoglHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);  //Really Nice Perspective Calculations
}
void myReshape(int width, int height) {if (height == 0)//Prevent A Divide By Zero By{height = 1;//Making Height Equal One}glViewport(0, 0, width, height);    //Reset the Cuurent ViewportglMatrixMode(GL_PROJECTION); //Select the Projection MatrixglLoadIdentity();            //Resetthe Projection Matrix//Calculate the Aspect Ratio of the windowgluPerspective(45.0f, (GLfloat)width / (GLfloat)height, 0.1f, 100.0f);glMatrixMode(GL_MODELVIEW);        //Select The Modelview MatrixglLoadIdentity();                  //Reset the Modelview Matrix
}
GLvoid DrawGLScene(GLvoid)
//Here's where we do all the drawing
{glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);    //Clear Screen And Depth BufferglLoadIdentity(); //Reset The cuurent Modelview MatrixglTranslatef(-1.5f, 0.0f, -6.0f); //Move Left 1.5 Units And Into The Screen 6.0glRotatef(rtri, 0.0f, 1.0f, 0.0f); //Rotate The Triangle On the Y axis(NEW)glBegin(GL_TRIANGLES);          //Start Drawing A TriangleglColor3f(1.0f, 0.0f, 0.0f);    //RedglVertex3f(0.0f, 1.0f, 0.0f);   //Top of Triangle (Front)glColor3f(0.0f, 1.0, 0.0f);     //GreenglVertex3f(-1.0f, -1.0f, 1.0f); //Left of Triangle (Front)glColor3f(0.0f, 0.0f, 1.0f);    //BlueglVertex3f(1.0f, -1.0f, 1.0f);  //Right of Triangle (Front)glColor3f(1.0f, 0.0f, 0.0f);    //RedglVertex3f(0.0f, 1.0f,0.0f);   //Top of Triangle (Right)glColor3f(0.0f, 0.0f, 1.0f);    //BlueglVertex3f(1.0f, -1.0f, 1.0f); //Left of Triangle (Right)glColor3f(0.0f, 1.0f, 0.0f);    //GreenglVertex3f(1.0f, -1.0f, -1.0f);  //Right of Triangle (Right)glColor3f(1.0f, 0.0f, 0.0f);  //RedglVertex3f(0.0f, 1.0f, 0.0f);   //Top of Triangle  (Back)glColor3f(0.0f, 1.0f, 0.0f);    //GreenglVertex3f(1.0f, -1.0f, -1.0f);//Left of Triangle(Back)glColor3f(0.0f, 0.0f, 1.0f);    //BlueglVertex3f(-1.0f, -1.0f, -1.0f); //Left of Triangle (Back)glColor3f(1.0f, 0.0f, 0.0f);    //RedglVertex3f(0.0f, 1.0f, 0.0f);   //Top of Triangle  (Left)glColor3f(0.0f, 0.0f, 1.0f);    //BlueglVertex3f(-1.0f, -1.0f, -1.0f);//Left of Triangle (Left)glColor3f(0.0f, 1.0f, 0.0f);    //GreenglVertex3f(-1.0f, -1.0f, 1.0f); //Right of Triangle(Left)glEnd();//Done Drawing the PyramidglLoadIdentity();  //Reset the Current Modelview MatrixglTranslatef(1.5f, 0.0f, -7.0f); //Move Right 1.5 Units And Intothe screen 7.0glRotatef(rquad, 1.0f, 1.0f, 1.0f); //Rotate The Quad On the X axis(NEW)glBegin(GL_QUADS);//Draw A QuadglColor3f(0.0f, 1.0f, 0.0f);   // Set The Color to GreenglVertex3f(1.0f, 1.0f, -1.0f); //Top Right of The Quad (Top)glVertex3f(-1.0f, 1.0f, -1.0f);//Top Left of The Quad (Top)glVertex3f(-1.0f, 1.0f, 1.0f); //Bottom Left of the Quad(Top)glVertex3f(1.0f, 1.0f, 1.0f);  //Bottom Right of the Quad(Top)glColor3f(1.0f, 0.5f, 0.0f);   //Set The Color to OrangeglVertex3f(1.0f, -1.0f, 1.0f); //Top Right of the Quad(Bottom)glVertex3f(-1.0f, -1.0f, 1.0f);//Top Left of the Quad (Bottom)glVertex3f(-1.0f, -1.0f, -1.0f);//Bottom Left of the Quad(Bottom)glVertex3f(1.0f, -1.0f, -1.0f);//Bottom Right of the QuadglColor3f(1.0f, 0.0f, 0.0f);   //Set the Color to RedglVertex3f(1.0f, 1.0f, 1.0f);  //Top Right of the Quad (Front)glVertex3f(-1.0f, 1.0f, 1.0f); //Top Left of the Quad (Front)glVertex3f(-1.0f, -1.0f, 1.0f);//Bottom Left of the Quad(Front)glVertex3f(1.0f, -1.0f, 1.0f); //Bottom Right of the Quad(Front)glColor3f(1.0f, 1.0f, 0.0f);   //Set the Color to Yellow glVertex3f(1.0f, -1.0f, -1.0f);//Top Right of the Quad(back)glVertex3f(-1.0f, -1.0f, -1.0f);//Top Left of the Quad(back)glVertex3f(-1.0f, 1.0f, -1.0f);//Bottom Left of the Quad (back)glVertex3f(1.0f, 1.0f, -1.0f); //Bottom Right of the Quad (back)glColor3f(0.0f, 0.0f, 1.0f);//Set the Color to BlueglVertex3f(-1.0f, 1.0f, 1.0f);//Top Right of the Quad(Left)glVertex3f(-1.0f, 1.0f, -1.0f);//Top Left of the Quad(Left)glVertex3f(-1.0f, -1.0f, -1.0f);//Bottom Left of the Quad (Left)glVertex3f(-1.0f, -1.0f, 1.0f);//Bottom Right of the Quad (Left)glColor3f(1.0f, 0.0f, 1.0f);   //Set the Color to VioletglVertex3f(1.0f, 1.0f, -1.0f); //Top right of the Quad(Right)glVertex3f(1.0f, 1.0f, 1.0f); //Top Left of the Quad(Right)glVertex3f(1.0f, -1.0f, 1.0f); //Bottom Left of the Quad(Right)glVertex3f(1.0f, -1.0f, -1.0f); //Bottom Right of the Quad(Right)glEnd();//Done Drawing the quadglFlush();  //Force to display the new drawings immediately
}
void myKeyboard(int key, int x, int y) {switch (key) {case GLUT_KEY_LEFT:case GLUT_KEY_UP:rtri -= 0.5f;   //Decrese the Roatation Variable For The Triangle (New)rquad += 0.5f;  //Increse The Rotation Variable For The QuadDrawGLScene();break;case GLUT_KEY_RIGHT:case GLUT_KEY_DOWN:rtri += 0.5f;   //Increse the Roatation Variable For The Triangle (New)rquad -= 0.85f;  //Decrese The Rotation Variable For The QuadDrawGLScene();break;}
}
void myMovedMouse(int x, int y) {
}

4.2 运行成功的截图

4.3 控制3D物体旋转平移

上述代码中的myKeyboard便实现了通过键盘而操纵图像旋转,注意在主函数中,用glutSpecialFunc()才能调用。

void myKeyboard(int key, int x, int y) {switch (key) {case GLUT_KEY_LEFT:case GLUT_KEY_UP:rtri -= 0.5f;   //Decrese the Roatation Variable For The Triangle (New)rquad += 0.5f;  //Increse The Rotation Variable For The QuadDrawGLScene();break;case GLUT_KEY_RIGHT:case GLUT_KEY_DOWN:rtri += 0.5f;   //Increse the Roatation Variable For The Triangle (New)rquad -= 0.85f;  //Decrese The Rotation Variable For The QuadDrawGLScene();break;}
}

五、心得体会

本次实验中需要在写代码时仔细比对各个参数,不可粗心大意,比如针对颜色,glColor3f函数中的3个参数取不同的值就会导致不同的效果。头文件的导入也需要注意,再比如"stdafx.h"文件必须放在其他库文件之前。
观察代码结构可以发现,绘制图形的思路大致如下:

  1. 绘制窗口
  2. 初始化GL函数
  3. 编写重新载入图像的函数
  4. 绘制图形的函数
  5. 键盘or鼠标操纵图形的函数

相关函数列举:

  1. 上述源程序中的主函数:
    glutInit() 初始化函数
    glutInitWindowSize() 设置窗口大小
    glutInitWindowPosition() 设置窗口位置
    glutCreateWindow() 创建窗口
    glutDisplayFunc(DrawGLScene) 指定显示函数
    glutReshapeFunc(myReshape) 改变显示区域
    glutMotionFunc(myMovedMouse) 这个函数是处理当鼠标键摁下时,鼠标拖动的事件。当鼠标拖动时,将每一帧都调用一次这个函数。
    glutSpecialFunc(myKeyboard) 这个函数是用来处理一些特殊键(如:F1,F2,etc)摁下的事件。本实验中主要是方向键。
    glutMainLoop() 进行过程循环
  2. myReshape函数
    glViewport(width,height) 表示这个视口矩形的宽度和高度,根据窗口的实时变化重绘窗口。
    glMatrixMode() 选择投影矩阵 这个函数其实就是对接下来要做什么进行一下声明,也就是在要做下一步之前告诉计算机我要对“什么”进行操作了,这个“什么”在glMatrixMode的“()”里的选项(参数)有3种模式: GL_PROJECTION 投影, GL_MODELVIEW 模型视图, GL_TEXTURE 纹理。
    如果参数是GL_PROJECTION,这个是投影的意思,就是要对投影相关进行操作,也就是把物体投影到一个平面上,就像我们照相一样,把3维物体投到2维的平面上。这样,接下来的语句可以是跟透视相关的函数,比如glFrustum()或gluPerspective();
    在操作投影矩阵以前,需要调用函数:glMatrixMode(GL_PROJECTION); //将当前矩阵指定为投影矩阵
    然后把矩阵设为单位矩阵:glLoadIdentity();再度调用glFrustum()或gluPerspective(),它们生成的矩阵会与当前的矩阵相乘,生成透视的效果;
    参考资料:https://blog.csdn.net/jiangdf/article/details/8460012
    glLoadIdentity() 恢复初始坐标系
    该命令是一个无参的无值函数,其功能是用一个4×4的单位矩阵来替换当前矩阵,实际上就是对当前矩阵进行初始化。也就是说,无论以前进行了多少次矩阵变换,在该命令执行后,当前矩阵均恢复成一个单位矩阵,即相当于没有进行任何矩阵变换状态。
    注意:由于某些原因可能使得当前矩阵中的元素有一些不确定的值,这将导致程序对图形对象进行几何变形时得到一个非预期的结果。因此有必要将当前矩阵初始成 一个单位矩阵,即对图形对象不做任何变换。这就是为什么在调用过glMatrixMode()命令后,总是要调用该命令的原因。由于glMatrixMode()命令本身也是一种矩阵变换,它将当前矩阵变成命令参数所规定的形式,若不用单位矩阵来替换它,在此矩阵下绘制出的图形将是难以预计的。
    关于这个函数的详细解释请看以下博文:
    https://blog.csdn.net/shuaihj/article/details/7228265

    (个人感觉这一篇讲得很清楚~)
    glViewport() 在默认情况下,视口被设置为占据窗口的整个像素矩形,窗口大小和视口大小相同。如果选择一个更小的绘图区域,可以用glviewport函数实现这一变换,在窗口中定义一个像素矩形,将图像映射到这个矩形中。
    gluPerspective(GLdouble fovy,GLdouble aspect,GLdouble zNear,GLdouble zFar)
    fovy,这个最难理解,我的理解是,眼睛睁开的角度,即,视角的大小,如果设置为0,相当你闭上眼睛了,所以什么也看不到,如果为180,那么可以认为你的视界很广阔
    aspect,这个好理解,就是实际窗口的纵横比,即x/y
    zNear,这个呢,表示你近处,的裁面,
    zFar表示远处的裁面

    参考资料:https://blog.csdn.net/dcrmg/article/details/53106457
  3. InitGL中的函数
    glShadeModel() 设置着色模式,即控制绘制自定两点间其他点颜色的过渡模式,参数一般为GL_SMOOTH(默认)如果两点颜色不同,GL_SMOOTH会出现过渡效果。采用恒定着色时(即GL_FLAT),使用图元中某个顶点的颜色来渲染整个图元。
    在使用光滑着色时(即GL_SMOOTH),独立的处理图元中各个顶点的颜色。对于线段图元,线段上各点的颜色将根据两个顶点的颜色通过差值得到。对于多边形图元,多边形内部区域的颜色将根据所有顶点的颜色差值得到。
    参考原文链接:https://blog.csdn.net/deniece1/article/details/102133394
    glClearColor() 搭配glClearDepth使用
    参数:GL_COLOR_BUFFER_BIT,颜色缓冲
    GL_DEPTH_BUFFER_BIT,深度缓冲
    GL_STENCIL_BUFFER_BIT,模板缓冲
    值的预制主要通过glclearcolor,glcleardepth,glclearstencil来完成,它提前设置好值,OpenGL是一个状态机,它就相当于设置好了context的一个状态值。
    参考:https://blog.csdn.net/qq_36383623/article/details/85115585
    因此我运行的程序窗口的背景是黑色的~
    glEnable() 用于启用各种功能。功能由参数决定。
    程序中的参数GL_DEPTH_TEST 启用深度测试,根据坐标的远近自动隐藏被遮住的图形(材料)
    glDepthFunc() 指定目标像素与当前像素在z方向上值大小比较的函数。
    GL_LEQUAL,如果输入的深度值小于或等于参考值,则通过
    glHint() 应用:glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); 如果OpenGL不能有效的支持透视修正参数差值,那么GL_DONT_CARE 和 GL_FASTEST可以执行颜色、纹理坐标的简单线性差值计算。
    GL_PERSPECTIVE_CORRECTION_HINT:指定颜色和纹理坐标的差值质量。如果OpenGL不能有效的支持透视修正参数差值,那么GL_DONT_CARE 和 GL_FASTEST可以执行颜色、纹理坐标的简单线性差值计算。
    GL_NICEST在光栅化期间可以生成更多的像素段。选择最高质量选项。
    参考资料:https://blog.csdn.net/blues1021/article/details/48769797
  4. DrawGLScene()
    glTranslatef() 沿X轴正方向平移x个单位(x是有符号数) 沿Y轴正方向平移y个单位(y是有符号数)沿Z轴正方向平移z个单位(z是有符号数)
    glRotatef() 先解释一下旋转方向,做(0,0,0)到(x,y,z)的向量,用右手握住这条向量,大拇指指向向量的正方向,四指环绕的方向就是旋转的方向;
    函数功能:以点(0,0,0)到点(x,y,z)为轴,旋转angle角度;
    glBegin() mode:创建元素的类型.
    glBegin和glEnd函数限定了一组或多组图元的定点定义。
    GL_TRIANGLES 把每个顶点作为一个独立的三角形,顶点3n-2,3n-1和3n定义了第n个三角形,绘制了N/3个三角形。
    glColor3f() 需要注意的是,如果在glBegin()与glEnd()函数之间多次连续调用颜色函数,那么,只会显示出最后一次的颜色。它的参数应该有三个,类型是float型的。另外一点是它的参数值的范围是[0.0,1.0]"background-color: rgb(255, 255, 255); 。

本次实验圆满结束O(∩_∩)O哈哈~,欢迎分享交流。

OpenGL 实验一 绘制简单图形相关推荐

  1. Android openGl开发详解(一)——绘制简单图形

    1. What? openGl是什么?openGl ES又是什么? 2. How? Android中的openGL 如何使用? 3. GlSurfaceView是什么? GLSurfaceView的作 ...

  2. SurfaceView简单理解,Android混淆,Android openGl开发详解简单图形的绘制,

    SurfaceView允许你在非ui线程中去绘制. SurfaceView的帧率可以操作60FPS 在要求实时性比较高的游戏开发中,显然,view的ondraw是满足不了你的,这时候只能是用Surfa ...

  3. OpenGL实验:绘制彩色五角星

    OpenGL实验:绘制彩色五角星 第二次编程作业内容 用配置好的OpenGL环境实现彩色五角星效果,以及把五角星作为3D对象绘制出来,通过按键能够调整角度(用J.K.L三个键分别控制三个互相正交方向上 ...

  4. [Qt教程] 第11篇 2D绘图(一)绘制简单图形

    [Qt教程] 第11篇 2D绘图(一)绘制简单图形 楼主  发表于 2013-4-23 12:52:35 | 查看: 1398| 回复: 5 绘制简单图形 版权声明 该文章原创于Qter开源社区,作者 ...

  5. java 绘制长方形_Java入门:绘制简单图形

    在上一节,我们学习了如何使用swing和awt工具创建一个空的窗口,本节学习如何绘制简单图形. 基本绘图介绍 Java中绘制基本图形,可以使用Java类库中的Graphics类,此类位于java.aw ...

  6. python opencv 绘制简单图形

    09-python opencv 绘制简单图形 09-python opencv 绘制简单图形 概述 实现过程 引用与创建空图 绘制直线 绘制矩形 绘制圆 绘制椭圆 添加文字 显示图像 源代码 运行结 ...

  7. Python之Turtle库绘制简单图形

    Python之Turtle库绘制简单图形 来绘制正方形.三角形.五边形.五角形 import turtle #引入turtle库pen=turtle.Turtle() #创建turtle类型的画笔 # ...

  8. plotly绘制简单图形4--饼形图

    plotly绘制简单图形<1>--散点图折线图 plotly绘制简单图形<2>--条形图 plotly绘制简单图形<3>--设置按钮 本次说一下饼形图: 目录 1. ...

  9. plotly绘制简单图形5--饼形图附加

    plotly绘制简单图形<4>--饼形图里说了饼形图的基本设置, 这里补充一个怎样设置两个饼图的方法(数据是爬取京东手机和电脑价格数据分析结果) import plotly.plotly ...

最新文章

  1. C语言中常用的数学公式
  2. BZOJ 1176([Balkan2007]Mokia-CDQ分治-分治询问)
  3. 超级计算机 26010,全球最强超级计算机搭载的SW26010处理器解析
  4. 超好看的科学科普书,孩子大人都可以看!
  5. CMU本科计算机科学,CMU计算机科学学院本科难录吗?
  6. opencv_python使用cv2.imread()读取中文路径报错问题(转)
  7. Canny边缘检测算法原理及其VC实现详解(一)
  8. SpringMVC工作原理的介绍
  9. Unity项目中的资源管理
  10. 2020 CUMCM全国大学生数学建模竞赛 B题 Notes
  11. [Telink][TLSR8251] [泰凌微]入门上手教程(IDE+SDK+烧录)
  12. Excel堆积柱形图制作过程
  13. 四六级得分技巧备考和心态
  14. Python+Vue计算机毕业设计教师教学质量评价管理2lbw7(程序+LW+源码+部署)
  15. 基于Echarts实现可视化数据大屏大数据平台车辆监控系统HTML模板
  16. “ORA-28007: the password cannot be reused”解决
  17. MATLAB 输入和输出参数
  18. 票据识别android代码,Android 百度AI开放平台-文字识别-财务票据文字识别
  19. LABVIEW以及各种驱动(VDM/VAS等)的安装教程
  20. 【python操作word和pdf】

热门文章

  1. 面试又被问高并发,哑口无言?一份高并发核心文档助你吊打面试官
  2. 骨传导耳机会伤害耳朵吗?骨传导耳机优点是什么
  3. 面向对象概念及对象、抽象、类的解释
  4. S型加减速程序,C++,PLC,AGV
  5. java从数据库读取zip文件的字节数组byte[]直接解压
  6. 网上经常听到的“终端”指的什么?
  7. C语言基础---3.格式化输出总结---%d ,%s,%f %.3f,%m.ns 以及sprintf函数
  8. mp3音频转换,合并方法?-QVE音频剪辑
  9. 泛知识+社交搜索,快手平台内容生态知识普惠价值凸显
  10. Android Studio入学1-3:通过okhttp连接服务器