zoukankan      html  css  js  c++  java
  • 对相机的理解及使用多相机绘制只旋转的坐标系

    1. 对相机的理解

    1.1. 点是怎么转到屏幕上

    假设一个A点在世界坐标系内的坐标是A(x, y, z), 视口矩阵,投影矩阵,模型视图矩阵为M, N, P,则 M* N * P * A = A1,  A1就是点A在屏幕上的坐标。有此可见,在这个过程中只有三个矩阵M,N,P,而没有相机的概念,所谓相机的概念其实是对矩阵M, N, P的一种解释方式,只不过这种解释方式比较形象,容易理解,容易使用。但是除了用相机去解释这三个矩阵,其实还有其它很多解释方式,就像一种颜色在正常人的眼里和色盲的眼里是不一样的。它是什么不重要,也无意义,重要的是你怎么观察它,谁观察它的,怎么解释它。

    1.2. 使用相机去解释M,N,P

    矩阵P是模型视图矩阵,P又可以拆分出两个矩阵,一个是模型矩阵Model,一个是视图矩阵View, 模型矩阵只作用某一个模型上,而View矩阵是作用到所有的模型上,View又可以拆分出平移矩阵T,和旋转矩阵R,(一般来说不能拆分出缩放矩阵)因此R矩阵就可以理解为视点坐标系,R矩阵的三个列向量就是视点坐标系的X轴,Y轴,Z轴,T矩阵是一个向量,也是视点坐标系的原点,也可以理解为相机的位置,由于对P矩阵有不同的拆分方法,每种拆分方法可以拆分出不同的TR,所以相机的位置和放置的方向可以有很多种方法。 如下图:

     

      投影矩阵N本来的作用就是把模型变换到一个边长为2的立方体内,方便剪裁,可以把投影矩阵解释为八个顶点形成的棱柱体,这个棱柱可以是正棱柱或者斜棱柱,这个棱柱的八个顶点为参数可以合成一个矩阵,这个矩阵就是N,这个棱柱体的八个顶点的坐标乘以N后,就为变成边长为2的立方体的顶点。如下图:

     

    1.3. 使用坐标变换去解释M,N,P

    除了M, N解释为相机外, M* N * P * A = A1又可以理解为 M * N * T * R * Model * A = A1, (T, R, Model的含义上面已经讲过),  还可以从坐标变换的角度去理解,每乘以一个矩阵就相当于进行了一次坐标变换,ModelR, T, N, M, 就相当于进行了一系列变换后生成了新的坐标,这个左边的Z轴最终变成了01之间,也就是opengl中深度坐标的范围。最终按照变换后的坐标,使用绘制点的函数绘制到屏幕上。

    2. 多相机的使用

    既然知道了 M* N * P * A = A1, 也就是一个点变换到屏幕上的过程,并且相机就是指的N, N, 这两个矩阵,那么在什么情况下会用到多相机呢?就是绘制多个模型,但是这几个模型的M,N值不一样的时候,比如说你绘制了一个球,再绘制了一个公告板(就是一个模型的永远朝向相机),在这种情况下,就需要两个相机,一个相机绘制球,一个相机绘制公告板。或者说,你在绘制模型的同时,还想在屏幕的左下角绘制一个坐标系,这个坐标系只能旋转,不能平移缩放,只起个指示模型的方向的作用,在这种情况下,可以单独使用一个相机绘制这个坐标系,其它的模型要使用另一个相机。

    3. THREE.JS使用多相机绘制坐标系

    THREE.JS中实现左下角一个坐标轴,只旋转,不平移不缩放,仅仅起指示作用。如下图:

     

     

    代码如下:

    //立即执行函数,绘制坐标轴

    //绘制Y

    (function (){

     var sourcePos = new THREE.Vector3(0, 0, 0);

    var targetPos = new THREE.Vector3(0, 100, 0);

    var direction = new THREE.Vector3().sub(targetPos, sourcePos);

    var arrow = new THREE.ArrowHelper(direction.clone().normalize(), sourcePos, direction.length(), 0xff0000, 15, 15);

    AxisScene.add(arrow);

          })();

     

    //绘制X

    (function (){

    var sourcePos = new THREE.Vector3(0, 0, 0);

    var targetPos = new THREE.Vector3(100, 0, 0);

    var direction = new THREE.Vector3().sub(targetPos, sourcePos);

    var arrow = new THREE.ArrowHelper(direction.clone().normalize(), sourcePos, direction.length(), 0x00ff00, 15, 15);

     AxisScene.add(arrow);

               })();

     

    //绘制Z

     (function (){

    var sourcePos = new THREE.Vector3(0, 0, 0);

    var targetPos = new THREE.Vector3(0, 0, 100);

    var direction = new THREE.Vector3().sub(targetPos, sourcePos);

    var arrow = new THREE.ArrowHelper(direction.clone().normalize(), sourcePos, direction.length(), 0x0000ff, 15, 15);

    AxisScene.add(arrow);

                })();

     

    //专门为绘制坐标轴设置一个相机

     AxisCamera = new THREE.Plot3DCamera(-100, 100, 100, -100, -500, 500);

     renderer.setViewport(0, 0, window.innerWidth, window.innerHeight);

    //scene, camera原来的场景节点和相机,绘制场景

    renderer.render(scene, camera);

    renderer.autoClearColor = false;

    //坐标系绘制到左下角

    renderer.setViewport(window.innerWidth - 100, window.innerHeight - 100, 100, 100);

    //绘制坐标系

    renderer.render(CADscene, CADcamera);

    交流图形学的一切,每天有原创文章

    qq群: 52391108

    将近两百篇图形学相关的技术文章,经常更

  • 相关阅读:
    eWebEditor在ie9下按钮功能失效的解决办法
    FLV视频播放代码
    笔记 PHP常用 语句
    jquery 无刷新加载执行,显示数据
    常用的PHP与SQL语句
    PHP常用语句
    Ajax+php 无刷新更新数据.并将数据库操作改写成类.
    js下拉框联动代码
    PHP 更新功能 笔记
    MyEclipse8.5开发环境配置中SVN插件安装重点解析
  • 原文地址:https://www.cnblogs.com/lizhengjin/p/5923598.html
Copyright © 2011-2022 走看看