• 博客园logo
  • 会员
  • 众包
  • 新闻
  • 博问
  • 闪存
  • 赞助商
  • HarmonyOS
  • Chat2DB
    • 搜索
      所有博客
    • 搜索
      当前博客
  • 写随笔 我的博客 短消息 简洁模式
    用户头像
    我的博客 我的园子 账号设置 会员中心 简洁模式 ... 退出登录
    注册 登录
lizhengjin
博客园    首页    新随笔    联系   管理    订阅  订阅
对相机的理解及使用多相机绘制只旋转的坐标系

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矩阵有不同的拆分方法,每种拆分方法可以拆分出不同的T和R,所以相机的位置和放置的方向可以有很多种方法。 如下图:

 

 

 

  投影矩阵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的含义上面已经讲过),  还可以从坐标变换的角度去理解,每乘以一个矩阵就相当于进行了一次坐标变换,Model,R, T, N, M, 就相当于进行了一系列变换后生成了新的坐标,这个左边的Z轴最终变成了0和1之间,也就是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

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

posted on 2016-09-30 13:55  lizhengjin  阅读(1280)  评论(0)    收藏  举报
刷新页面返回顶部
博客园  ©  2004-2025
浙公网安备 33010602011771号 浙ICP备2021040463号-3