2021SC@SDUSC ClayGL Camera类分析(一)
Camera类主要定义了视角、物体、世界矩阵向相机矩阵的变换以及在相机进行变换后的坐标更新,也具有定义光线向量的函数,该光线是从相机开始定义的发射的。
该函数包含Camera节点扩展及实例对象函数定义。
成员 | 类型 |
---|---|
projectionMatrix | Matrix4() |
invProjectionMatrix | Matrix4() |
viewMatrix | Matrix4() |
frustum | Frustum() |
代码如下:
var Camera = Node.extend(function () {
return {
projectionMatrix: new Matrix4(),
invProjectionMatrix: new Matrix4(),
viewMatrix: new Matrix4(),
frustum: new Frustum()
};
}, function () {
this.update(true);
},
从源码中可以看出,projectionMatrix、invProjectionMatrix 、viewMatrix的类型均为返回一个4维矩阵的函数的结果,frustum 的类型为返回Frustum() 函数的结果。
调用对象采用call方法,将一个函数的对象上下文从初始的上下文改变为force指定的新对象;
在Matrix4函数中用世界坐标变换求视角矩阵,并更新投影矩阵;
在Matrix4函数中根据投影矩阵转换求逆投影矩阵;
根据投影矩阵定义视野锥体。
源码如下:
{
update: function (force) {
Node.prototype.update.call(this, force);
Matrix4.invert(this.viewMatrix, this.worldTransform);
this.updateProjectionMatrix();
Matrix4.invert(this.invProjectionMatrix, this.projectionMatrix);
this.frustum.setFromProjection(this.projectionMatrix);
},
复制投影矩阵;
根据投影矩阵求得逆投影矩阵;
{
setViewMatrix: function (viewMatrix) {
Matrix4.copy(this.viewMatrix, viewMatrix);
Matrix4.invert(this.worldTransform, viewMatrix);
this.decomposeWorldTransform();
},
分解投影矩阵;
设置投影矩阵:
复制投影矩阵;
根据投影矩阵求得逆投影矩阵;
更新投影矩阵;
decomposeProjectionMatrix: function () {},
setProjectionMatrix: function (projectionMatrix) {
Matrix4.copy(this.projectionMatrix, projectionMatrix);
Matrix4.invert(this.invProjectionMatrix, projectionMatrix);
this.decomposeProjectionMatrix();
},
updateProjectionMatrix: function () {},
将光线从近平面的相机投射到远平面
castRay函数中参数origin(光束起点)是世界坐标系下相机的位置;参数direction也就是光束的方向向量,并对方向向量归一化,返回的光束ray是世界坐标系下的坐标表达。
castRay: (function () {
var v4 = vec4.create();
return function (ndc, out) {
var ray = out !== undefined ? out : new Ray();
var x = ndc.array[0];
var y = ndc.array[1];
vec4.set(v4, x, y, -1, 1);
vec4.transformMat4(v4, v4, this.invProjectionMatrix.array);
vec4.transformMat4(v4, v4, this.worldTransform.array);
vec3.scale(ray.origin.array, v4, 1 / v4[3]);
vec4.set(v4, x, y, 1, 1);
vec4.transformMat4(v4, v4, this.invProjectionMatrix.array);
vec4.transformMat4(v4, v4, this.worldTransform.array);
vec3.scale(v4, v4, 1 / v4[3]);
vec3.sub(ray.direction.array, v4, ray.origin.array);
vec3.normalize(ray.direction.array, ray.direction.array);
ray.direction._dirty = true;
ray.origin._dirty = true;
return ray;
};
})(),
});