摄像机

learn opengl


本节讨论如何在OpenGL中配置一个FPS风格的摄像机,让你能够在3D场景中自由移动。

摄像机/观察空间(Camera/View Space)

摄像机/观察空间(Camera/View Space)是指以摄像机的视角作为场景原点时场景中的所有顶点坐标:观察矩阵把所有的世界坐标变换为相对于摄像机位置与方向的观察坐标。要定义一个摄像机,我们需要它在世界空间中的位置、观察的方向、一个指向它右测的向量以及一个指向它上方的向量。注意,我们实际上创建了一个三个单位轴相互垂直的、以摄像机的位置为原点的坐标系。

1. 摄像机位置

获取摄像机位置很简单。摄像机位置简单来说就是世界空间中一个指向摄像机位置的向量。

不要忘记正z轴是从屏幕指向你的,如果我们希望摄像机向后移动,我们就沿着z轴的正方向移动。
glm::vec3 cameraPos = glm::vec3(0.0f, 0.0f, 3.0f);

2. 摄像机方向

摄像机的方向是它指向哪个方向。现在我们让摄像机指向场景原点:(0, 0, 0)。

“方向向量”是指向z轴正方向的,而不是摄像机所注视的那个方向.
glm::vec3 cameraTarget = glm::vec3(0.0f, 0.0f, 0.0f);
glm::vec3 cameraDirection = glm::normalize(cameraPos - cameraTarget);

3. 右轴

右向量(Right Vector),它代表摄像机空间的x轴的正方向。为获取右向量我们需要先使用一个小技巧:先定义一个上向量(Up Vector)。接下来把上向量和第二步得到的方向向量进行叉乘。两个向量叉乘的结果会同时垂直于两向量,因此我们会得到指向x轴正方向的那个向量

glm::vec3 up = glm::vec3(0.0f, 1.0f, 0.0f); 
glm::vec3 cameraRight = glm::normalize(glm::cross(up, cameraDirection));

4. 上轴

现在我们已经有了x轴向量和z轴向量,获取一个指向摄像机的正y轴向量就相对简单了:我们把右向量和方向向量进行叉乘:

glm::vec3 cameraUp = glm::cross(cameraDirection, cameraRight);

Look At 矩阵

你可以用这3个轴外加一个平移向量来创建一个矩阵,并且你可以用这个矩阵乘以任何向量来将其变换到那个坐标空间。这正是LookAt矩阵所做的,现在我们有了3个相互垂直的轴和一个定义摄像机空间的位置坐标,我们可以创建我们自己的LookAt矩阵了:



其中 R 是右向量, U 是上向量, D 是方向向量 P 是摄像机位置向量。注意,位置向量是相反的,因为我们最终希望把世界平移到与我们自身移动的相反方向。把这个LookAt矩阵作为观察矩阵可以很高效地把所有世界坐标变换到刚刚定义的观察空间。LookAt矩阵就像它的名字表达的那样:它会创建一个看着(Look at)给定目标的观察矩阵。

以下我们来做些有意思的事,把我们的摄像机在场景中旋转。我们会将摄像机的注视点保持在(0, 0, 0)。

我们需要用到一点三角学的知识来在每一帧创建一个x和z坐标,它会代表圆上的一点,我们将会使用它作为摄像机的位置。通过重新计算x和y坐标,我们会遍历圆上的所有点,这样摄像机就会绕着场景旋转了。


    //(1)摄像机旋转
    camAngle++;
    float radius = 10;
    float camX = sinf(CC_DEGREES_TO_RADIANS(camAngle)) * radius;
    float camZ = cosf(CC_DEGREES_TO_RADIANS(camAngle)) * radius;
    Mat4::createLookAt(Vec3(camX, 0, camZ), Vec3::ZERO, Vec3(0, 1, 0), myCamera);
摄像机矩阵传入 vertex shader:

    //摄像机矩阵传入 vertex shader
    GLuint viewLoc = glGetUniformLocation(glprogram->getProgram(), "view");
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, myCamera->m);

摄像机自由移动

    camPos = Vec3(0, 0, 3);
    camFront = Vec3(0, 0, -1);
    camUp = Vec3(0, 1, 0);
    Mat4::createLookAt(camPos, camPos + camFront, camUp, myCamera);
首先将摄像机位置设置为之前定义的 cameraPos 。方向是当前的位置加上我们刚刚定义的方向向量。这样能保证无论我们怎么移动,摄像机都会注视着目标方向。让我们摆弄一下这些向量,在按下某些按钮时更新 cameraPos 向量。

void OpenGLCamera::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *evt)
{
    Vec2 curpos = touch->getLocationInView();
    Vec2 prepos = touch->getPreviousLocationInView();
    GLfloat dx = curpos.x - prepos.x;
    GLfloat dy = curpos.y - prepos.y;
    
    //移动摄像机
    GLfloat camspeed = 0.05f;
    if (curpos.y - prepos.y > 0) { //w
        camPos += camspeed * camFront;
    }else if (curpos.y - prepos.y < 0){ //s
        camPos -= camspeed * camFront;
    }
     if (curpos.x - prepos.x < 0){ //a
         Vec3 right = Vec3::ZERO;
        Vec3::cross(camFront, camUp, &right);
        right.normalize();
        camPos -= right * camspeed;
    }else if (curpos.x - prepos.x > 0){ //d
        Vec3 right = Vec3::ZERO;
        Vec3::cross(camFront, camUp, &right);
        right.normalize();
        camPos += right * camspeed;
    }
    
}


视角移动

欧拉角

欧拉角(Euler Angle)是可以表示3D空间中任何旋转的3个值,由莱昂哈德·欧拉(Leonhard Euler)在18世纪提出。一共有3种欧拉角:俯仰角(Pitch)、偏航角(Yaw)和滚转角(Roll),下面的图片展示了它们的含义:

俯仰角是描述我们如何往上或往下看的角,可以在第一张图中看到。第二张图展示了偏航角,偏航角表示我们往左和往右看的程度。滚转角代表我们如何翻滚摄像机,通常在太空飞船的摄像机中使用。每个欧拉角都有一个值来表示,把三个角结合起来我们就能够计算3D空间中任何的旋转向量了。

给定一个俯仰角和偏航角,我们可以把它们转换为一个代表新的方向向量的3D向量。俯仰角和偏航角转换为方向向量的处理需要一些三角学知识,我们先从最基本的情况开始:

如果我们把斜边边长定义为1,我们就能知道邻边的长度是 cos x/h=cos x/1=cos x ,它的对边是 sin y/h=sin y/1=sin y 。这样我们获得了能够得到x和y方向长度的通用公式,它们取决于所给的角度。我们使用它来计算方向向量的分量:

这个三角形看起来和前面的三角形很像,所以如果我们想象自己在xz平面上,看向y轴,我们可以基于第一个三角形计算来计算它的长度/y方向的强度(Strength)(我们往上或往下看多少)。从图中我们可以看到对于一个给定俯仰角的y值等于 sin θ

direction.y = sin(glm::radians(pitch)); // 注意我们先把角度转为弧度
这里我们只更新了y值,仔细观察x和z分量也被影响了。从三角形中我们可以看到它们的值等于:
direction.x = cos(glm::radians(pitch));
direction.z = cos(glm::radians(pitch));

为偏航角找到需要的分量:

就像俯仰角的三角形一样,我们可以看到x分量取决于cos(yaw)的值,z值同样取决于偏航角的正弦值。把这个加到前面的值中,会得到基于俯仰角和偏航角的方向向量:

direction.x = cos(glm::radians(pitch)) * cos(glm::radians(yaw)); // 译注:direction代表摄像机的前轴(Front),这个前轴是和本文第一幅图片的第二个摄像机的方向向量是相反的
direction.y = sin(glm::radians(pitch));
direction.z = cos(glm::radians(pitch)) * sin(glm::radians(yaw));

touch 输入


void OpenGLCamera::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *evt)
{
    Vec2 curpos = touch->getLocationInView();
    Vec2 prepos = touch->getPreviousLocationInView();
    GLfloat dx = curpos.x - prepos.x;
    GLfloat dy = curpos.y - prepos.y;
    
   
    //(3)旋转摄像机
    
    pitch += dy * camspeed; //绕x轴,俯仰角
    if(pitch > 89.0f){
        pitch =  89.0f;
    }
    if(pitch < -89.0f){
        pitch = -89.0f;
    }
    yaw += dx * camspeed; //绕y轴,偏航角
    GLfloat pitch_radian = CC_DEGREES_TO_RADIANS(pitch);
    GLfloat yaw_radian = CC_DEGREES_TO_RADIANS(yaw);
    Vec3 dir = Vec3(cosf(pitch_radian) * cosf(yaw_radian), sinf(pitch_radian), cosf(pitch_radian) * sinf(yaw_radian));
    dir.normalize();
    camFront = dir;
   
}

我们需要给摄像机添加一些限制,这样摄像机就不会发生奇怪的移动了(这样也会避免一些奇怪的问题)。对于俯仰角,要让用户不能看向高于89度的地方(在90度时视角会发生逆转,所以我们把89度作为极限),同样也不允许小于-89度。这样能够保证用户只能看到天空或脚下,但是不能超越这个限制。

缩放(Zoom)

视野(Field of View)或fov定义了我们可以看到场景中多大的范围。当视野变小时,场景投影出来的空间就会减小,产生放大(Zoom In)了的感觉。
void OpenGLCamera::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *evt)
{
    Vec2 curpos = touch->getLocationInView();
    Vec2 prepos = touch->getPreviousLocationInView();
    GLfloat dx = curpos.x - prepos.x;
    GLfloat dy = curpos.y - prepos.y;
    
   
    GLfloat camspeed = 0.05f;

    //(4)缩放
    if(fov >= 1.0f && fov <= 45.0f){
        fov -= dx * camspeed;
    }
    if(fov <= 1.0f){
        fov = 1.0f;
    }
    if(fov >= 45.0f){
        fov = 45.0f;
    }
}
现在在每一帧都必须把透视投影矩阵上传到GPU,但现在使用 fov 变量作为它的视野:
Mat4::createPerspective(fov, viewsize.width/viewsize.height, 0.1, 200, projection);

全部代码如下:
//
//  Triangle.cpp
//  shaderTest
//
//  Created by MacSBL on 2016/12/15.
//
//

#include "OpenGLCamera.h"


bool OpenGLCamera::init()
{
    if (!Layer::init()) {
        return false;
    }
    
    GLfloat vertices[] = {
        //3维顶点,            //纹理坐标
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
        0.5f, -0.5f, -0.5f,  1.0f, 0.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 0.0f,
        
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 1.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        0.5f, -0.5f, -0.5f,  1.0f, 1.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        0.5f, -0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f, -0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f, -0.5f, -0.5f,  0.0f, 1.0f,
        
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f,
        0.5f,  0.5f, -0.5f,  1.0f, 1.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        0.5f,  0.5f,  0.5f,  1.0f, 0.0f,
        -0.5f,  0.5f,  0.5f,  0.0f, 0.0f,
        -0.5f,  0.5f, -0.5f,  0.0f, 1.0f
    };
    
    //创建并绑定纹理
    //
    //方法1
    auto sprite = Sprite::create("awesomeface.png");
    textureId2 = sprite->getTexture()->getName();
    //
    //方法2
    glGenTextures(1, &textureId);
    glBindTexture(GL_TEXTURE_2D, textureId);
    
    //纹理环绕方式
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
    //纹理过滤
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
    glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
    
    //加载纹理
    Image* img = new Image();
    img->initWithImageFile("wall.jpg");
    int width = img->getWidth();
    int height = img->getHeight();
    unsigned char* imgdata = img->getData();
    glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, imgdata);
    glGenerateMipmap(GL_TEXTURE_2D);
    //释放内存,解绑texture
    CC_SAFE_DELETE(img);
    glBindTexture(GL_TEXTURE_2D, 0);
    ///
    
    //1、绑定vao
    //顶点数组对象(Vertex Array Object)被绑定后,任何随后的顶点属性调用都会储存在这个VAO中。这样的好处就是,当配置顶点属性指针时,你只需要将那些调用执行一次,之后再绘制物体的时候只需要绑定相应的VAO就行了。这使在不同顶点数据和属性配置之间切换变得非常简单,只需要绑定不同的VAO就行了。刚刚设置的所有状态都将存储在VAO中
    glGenVertexArrays(1, &vao);
    glBindVertexArray(vao);
    
    // 2. 把顶点数组复制到缓冲(vbo)中供OpenGL使用
    //使用glGenBuffers函数和一个缓冲ID生成一个VBO对象
    GLuint vbo;
    glGenBuffers(1, &vbo);
    glBindBuffer(GL_ARRAY_BUFFER, vbo);
    //把之前定义的顶点数据复制到缓冲的内存中
    glBufferData(GL_ARRAY_BUFFER, sizeof(vertices), vertices, GL_STATIC_DRAW);
    
    
    //解析顶点数据, 应用到第1个顶点属性上
    glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, 5* sizeof(GLfloat), (GLvoid*)0);
    glEnableVertexAttribArray(0);
    // 纹理坐标,应用到第2个属性上
    glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 5 * sizeof(GLfloat), (GLvoid*)(3 * sizeof(GLfloat)));
    glEnableVertexAttribArray(1);
    
    //解除绑定vao和vbo
    glBindVertexArray(0);
    glBindBuffer(GL_ARRAY_BUFFER, 0);
    
    //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————-
    auto program = new GLProgram;
    program->initWithFilenames("cube.vsh", "cube.fsh");
    program->link();
    this->setGLProgram(program);
    
    //——————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————————-
    //矩阵
    //绕某轴旋转x°
    model = new Mat4();
    model->rotate(Vec3(1, 0, 0), CC_DEGREES_TO_RADIANS(50));
    
    //离我们有一些距离
    view = new Mat4();
    view->translate(0, 0, -3);
    
    //有透视效果(顶点越远,变得越小)
    cocos2d::Size viewsize = Director::getInstance()->getVisibleSize();
    projection = new Mat4();
    Mat4::createPerspective(45, viewsize.width/viewsize.height, 0.1, 200, projection);
    
    
    //摄像机
    //(1), 旋转
    myCamera = new Mat4();
    //(2),自由移动,通过touch methods
    camPos = Vec3(0, 0, 3);
    camFront = Vec3(0, 0, -1);
    camUp = Vec3(0, 1, 0);
    Mat4::createLookAt(camPos, camPos + camFront, camUp, myCamera);
    
    //开启深度测试
    Director::getInstance()->setDepthTest(true);
    
    cubpos[0] = {0, 0, 0};
    cubpos[1] = {2, 5, -15};
    cubpos[2] = {-1, -2, -2};
    cubpos[3] = {1, 0.5, -1.6};
    
    //touch事件
    auto elistener = EventListenerTouchOneByOne::create();
    elistener->onTouchBegan = CC_CALLBACK_2(OpenGLCamera::onTouchBegan, this);
    elistener->onTouchMoved = CC_CALLBACK_2(OpenGLCamera::onTouchMoved, this);
    elistener->onTouchEnded = CC_CALLBACK_2(OpenGLCamera::onTouchEnded, this);
    _eventDispatcher->addEventListenerWithSceneGraphPriority(elistener, this);
    
    return true;
}

void OpenGLCamera::visit(cocos2d::Renderer *renderer, const cocos2d::Mat4 &parentTransform, uint32_t parentFlags)
{
    Layer::visit(renderer, parentTransform, parentFlags);
    _command.init(_globalZOrder);
    _command.func = CC_CALLBACK_0(OpenGLCamera::onDraw, this);
    Director::getInstance()->getRenderer()->addCommand(&_command);
}

void OpenGLCamera::onDraw()
{
    //获取当前node 的shader
    auto glprogram = getGLProgram();
    //需要在init中指定shader才能在这use
    glprogram->use();
    
    //绑定纹理, 它会自动把纹理赋值给片段着色器texture.fsh的采样器u_myTexture.因为一个纹理的默认纹理单元是0,它是默认的激活纹理单元。
//    GL::bindTexture2D(textureId);
    
    /
    //纹理单元, uniform采样器对应纹理单元
    GL::bindTexture2DN(0, textureId);
    glUniform1i(glGetUniformLocation(glprogram->getProgram(), "u_myTexture1"), 0);
    GL::bindTexture2DN(1, textureId2);
    glUniform1i(glGetUniformLocation(glprogram->getProgram(), "u_myTexture2"), 1);
    /
    //矩阵变换,给vertex shader传值
//    model->rotate(Vec3(1, 0, 0), CC_DEGREES_TO_RADIANS(2));
//    GLuint modelLoc = glGetUniformLocation(glprogram->getProgram(), "model");
//    glUniformMatrix4fv(modelLoc, 1, GL_FALSE, model->m);
    
    //(1)摄像机旋转
//    camAngle++;
//    float radius = 10;
//    float camX = sinf(CC_DEGREES_TO_RADIANS(camAngle)) * radius;
//    float camZ = cosf(CC_DEGREES_TO_RADIANS(camAngle)) * radius;
//    Mat4::createLookAt(Vec3(camX, 0, camZ), Vec3::ZERO, Vec3(0, 1, 0), myCamera);
    
    //(2) touch move 摄像机
    Mat4::createLookAt(camPos, camPos + camFront, camUp, myCamera);
    
    //摄像机矩阵传入 vertex shader
    GLuint viewLoc = glGetUniformLocation(glprogram->getProgram(), "view");
    glUniformMatrix4fv(viewLoc, 1, GL_FALSE, myCamera->m);
    
    //(4)摄像机缩放
    cocos2d::Size viewsize = Director::getInstance()->getVisibleSize();
    Mat4::createPerspective(fov, viewsize.width/viewsize.height, 0.1, 200, projection);
    
    GLuint projectionLoc = glGetUniformLocation(glprogram->getProgram(), "projection");
    glUniformMatrix4fv(projectionLoc, 1, GL_FALSE, projection->m);
    
    
    
    glBindVertexArray(vao);
    for (int i=0; i<4; i++) { //画n个立方体
        Mat4* posmodel = new Mat4();
        posmodel->translate(cubpos[i]);
        posmodel->rotate(Vec3(0, 1, 0), CC_DEGREES_TO_RADIANS(50*i));
        GLuint modelLoc = glGetUniformLocation(glprogram->getProgram(), "model");
        glUniformMatrix4fv(modelLoc, 1, GL_FALSE, posmodel->m);
        glDrawArrays(GL_TRIANGLES, 0, 36);
    }
    glBindVertexArray(0);
}

#pragma mark touch

bool OpenGLCamera::onTouchBegan(cocos2d::Touch *touch, cocos2d::Event *evt)
{
    return true;
}

void OpenGLCamera::onTouchMoved(cocos2d::Touch *touch, cocos2d::Event *evt)
{
    Vec2 curpos = touch->getLocationInView();
    Vec2 prepos = touch->getPreviousLocationInView();
    GLfloat dx = curpos.x - prepos.x;
    GLfloat dy = curpos.y - prepos.y;
    
    //移动摄像机
    GLfloat camspeed = 0.05f;
//    if (curpos.y - prepos.y > 0) { //w
//        camPos += camspeed * camFront;
//    }else if (curpos.y - prepos.y < 0){ //s
//        camPos -= camspeed * camFront;
//    }
//     if (curpos.x - prepos.x < 0){ //a
//         Vec3 right = Vec3::ZERO;
//        Vec3::cross(camFront, camUp, &right);
//        right.normalize();
//        camPos -= right * camspeed;
//    }else if (curpos.x - prepos.x > 0){ //d
//        Vec3 right = Vec3::ZERO;
//        Vec3::cross(camFront, camUp, &right);
//        right.normalize();
//        camPos += right * camspeed;
//    }
    //(3)旋转摄像机
    
//    pitch += dy * camspeed; //绕x轴,俯仰角
//    if(pitch > 89.0f){
//        pitch =  89.0f;
//    }
//    if(pitch < -89.0f){
//        pitch = -89.0f;
//    }
//    yaw += dx * camspeed; //绕y轴,偏航角
//    GLfloat pitch_radian = CC_DEGREES_TO_RADIANS(pitch);
//    GLfloat yaw_radian = CC_DEGREES_TO_RADIANS(yaw);
//    Vec3 dir = Vec3(cosf(pitch_radian) * cosf(yaw_radian), sinf(pitch_radian), cosf(pitch_radian) * sinf(yaw_radian));
//    dir.normalize();
//    camFront = dir;
    //(4)缩放
    if(fov >= 1.0f && fov <= 45.0f){
        fov -= dx * camspeed;
    }
    if(fov <= 1.0f){
        fov = 1.0f;
    }
    if(fov >= 45.0f){
        fov = 45.0f;
    }
}

void OpenGLCamera::onTouchEnded(cocos2d::Touch *touch, cocos2d::Event *evt)
{
    
}





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
计算机网络期末复习题 201708-201801计算机网络复习指导发布-校考学生!!下载截止于12.5日晚上9点 2017-12-04 23:07 计算机网络复习指导-校内考试 §1.名词解释: 1. 计算机网络 2.网络体系结构 3.高速以太网 4.静态路由选择 5. 动态路由选择 6.子网掩码 8.动态主机配置协议 9.套接字 10.客户/服务器模型(C/S模型) 11.域名系统(DNS) 12.光纤分布式数据接口FDDI §2.简答题: 1.试谈你对网络安全的威胁和防病毒技术的认识。(线下教学课件) 2.简述物理层的四个特性。(线下教学课件) 3.计算机网络的组成(P2-P3) 4.计算机网络的功能(P3) 5.计算机网络标准化的相关组织(P4+线下教学课件) 6.计算机网络的性能指标(P8+线下教学课件) 7.简述你所知道的网络传输介质(P33-34) 8.物理层的四个特性(P34) 9.简述四种帧边界的划分方法(即组帧方法)。(P52-54+线下教学课件) 10.简述停止-等待流量控制(协议)。(P59+P62-P64+线下教学课件) 11.简述时分多路复用(P69+线下教学课件) 12.简述频分多路复用(P68+线下教学课件) 13.简述IPv4地址的分类(P122-123) 14.UDP数据报与IP分组的区别(P187) §3.论述题: 1.试说明数据链路层原语和协议的转换。(线下教学课件) 2.描述常规释放的过程,并画出其示意图。(线下教学课件) 3.奈奎斯特定理公式和香农定理公式的主要区别是什么? 4.试比较电路交换、报文交换和分组交换等三种数据传输方式。(P27-29) 5.谈谈你对差错控制方法的理解。(P54-58+线下教学课件) 6.谈谈域名解析过程(P225-226) 7.ARP和DNS是否有些相似?它们有何区别?(P227) 8.FTP的工作原理。(P228)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值