mirror of
https://github.com/smallmain/cocos-enhance-kit.git
synced 2025-10-09 11:25:23 +00:00
初始化
This commit is contained in:
904
engine/cocos2d/core/camera/CCCamera.js
Normal file
904
engine/cocos2d/core/camera/CCCamera.js
Normal file
@@ -0,0 +1,904 @@
|
||||
/****************************************************************************
|
||||
Copyright (c) 2013-2016 Chukong Technologies Inc.
|
||||
Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd.
|
||||
|
||||
https://www.cocos.com/
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated engine source code (the "Software"), a limited,
|
||||
worldwide, royalty-free, non-assignable, revocable and non-exclusive license
|
||||
to use Cocos Creator solely to develop games on your target platforms. You shall
|
||||
not use Cocos Creator software for developing other software or tools that's
|
||||
used for developing games. You are not granted to publish, distribute,
|
||||
sublicense, and/or sell copies of Cocos Creator.
|
||||
|
||||
The software or tools in this License Agreement are licensed, not sold.
|
||||
Xiamen Yaji Software Co., Ltd. reserves all rights not expressly granted to you.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
****************************************************************************/
|
||||
|
||||
import { Mat4, Vec2, Vec3 } from '../value-types';
|
||||
import { Ray } from '../geom-utils';
|
||||
|
||||
const AffineTrans = require('../utils/affine-transform');
|
||||
const renderer = require('../renderer/index');
|
||||
const RenderFlow = require('../renderer/render-flow');
|
||||
const game = require('../CCGame');
|
||||
|
||||
let RendererCamera = null;
|
||||
if (CC_JSB && CC_NATIVERENDERER) {
|
||||
RendererCamera = window.renderer.Camera;
|
||||
} else {
|
||||
RendererCamera = require('../../renderer/scene/camera');
|
||||
}
|
||||
|
||||
let _mat4_temp_1 = cc.mat4();
|
||||
let _mat4_temp_2 = cc.mat4();
|
||||
|
||||
let _v3_temp_1 = cc.v3();
|
||||
let _v3_temp_2 = cc.v3();
|
||||
let _v3_temp_3 = cc.v3();
|
||||
|
||||
let _cameras = []; // unstable array
|
||||
|
||||
function updateMainCamera () {
|
||||
for (let i = 0, minDepth = Number.MAX_VALUE; i < _cameras.length; i++) {
|
||||
let camera = _cameras[i];
|
||||
if (camera._depth < minDepth) {
|
||||
Camera.main = camera;
|
||||
minDepth = camera._depth;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let _debugCamera = null;
|
||||
|
||||
function repositionDebugCamera () {
|
||||
if (!_debugCamera) return;
|
||||
|
||||
let node = _debugCamera.getNode();
|
||||
let canvas = cc.game.canvas;
|
||||
node.z = canvas.height / 1.1566;
|
||||
node.x = canvas.width / 2;
|
||||
node.y = canvas.height / 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* !#en Values for Camera.clearFlags, determining what to clear when rendering a Camera.
|
||||
* !#zh 摄像机清除标记位,决定摄像机渲染时会清除哪些状态
|
||||
* @enum Camera.ClearFlags
|
||||
*/
|
||||
let ClearFlags = cc.Enum({
|
||||
/**
|
||||
* !#en
|
||||
* Clear the background color.
|
||||
* !#zh
|
||||
* 清除背景颜色
|
||||
* @property COLOR
|
||||
*/
|
||||
COLOR: 1,
|
||||
/**
|
||||
* !#en
|
||||
* Clear the depth buffer.
|
||||
* !#zh
|
||||
* 清除深度缓冲区
|
||||
* @property DEPTH
|
||||
*/
|
||||
DEPTH: 2,
|
||||
/**
|
||||
* !#en
|
||||
* Clear the stencil.
|
||||
* !#zh
|
||||
* 清除模板缓冲区
|
||||
* @property STENCIL
|
||||
*/
|
||||
STENCIL: 4,
|
||||
});
|
||||
|
||||
let StageFlags = cc.Enum({
|
||||
OPAQUE: 1,
|
||||
TRANSPARENT: 2
|
||||
});
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Camera is usefull when making reel game or other games which need scroll screen.
|
||||
* Using camera will be more efficient than moving node to scroll screen.
|
||||
* Camera
|
||||
* !#zh
|
||||
* 摄像机在制作卷轴或是其他需要移动屏幕的游戏时比较有用,使用摄像机将会比移动节点来移动屏幕更加高效。
|
||||
* @class Camera
|
||||
* @extends Component
|
||||
*/
|
||||
let Camera = cc.Class({
|
||||
name: 'cc.Camera',
|
||||
extends: cc.Component,
|
||||
|
||||
ctor () {
|
||||
if (game.renderType !== game.RENDER_TYPE_CANVAS) {
|
||||
let camera = new RendererCamera();
|
||||
|
||||
camera.setStages([
|
||||
'opaque',
|
||||
]);
|
||||
|
||||
camera.dirty = true;
|
||||
|
||||
this._inited = false;
|
||||
this._camera = camera;
|
||||
}
|
||||
else {
|
||||
this._inited = true;
|
||||
}
|
||||
},
|
||||
|
||||
editor: CC_EDITOR && {
|
||||
menu: 'i18n:MAIN_MENU.component.others/Camera',
|
||||
inspector: 'packages://inspector/inspectors/comps/camera.js',
|
||||
executeInEditMode: true
|
||||
},
|
||||
|
||||
properties: {
|
||||
_cullingMask: 0xffffffff,
|
||||
_clearFlags: ClearFlags.DEPTH | ClearFlags.STENCIL,
|
||||
_backgroundColor: cc.color(0, 0, 0, 255),
|
||||
_depth: 0,
|
||||
_zoomRatio: 1,
|
||||
_targetTexture: null,
|
||||
_fov: 60,
|
||||
_orthoSize: 10,
|
||||
_nearClip: 1,
|
||||
_farClip: 4096,
|
||||
_ortho: true,
|
||||
_rect: cc.rect(0, 0, 1, 1),
|
||||
_renderStages: 1,
|
||||
_alignWithScreen: true,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The camera zoom ratio, only support 2D camera.
|
||||
* !#zh
|
||||
* 摄像机缩放比率, 只支持 2D camera。
|
||||
* @property {Number} zoomRatio
|
||||
*/
|
||||
zoomRatio: {
|
||||
get () {
|
||||
return this._zoomRatio;
|
||||
},
|
||||
set (value) {
|
||||
this._zoomRatio = value;
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.zoomRatio',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Field of view. The width of the Camera’s view angle, measured in degrees along the local Y axis.
|
||||
* !#zh
|
||||
* 决定摄像机视角的宽度,当摄像机处于透视投影模式下这个属性才会生效。
|
||||
* @property {Number} fov
|
||||
* @default 60
|
||||
*/
|
||||
fov: {
|
||||
get () {
|
||||
return this._fov;
|
||||
},
|
||||
set (v) {
|
||||
this._fov = v;
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.fov',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The viewport size of the Camera when set to orthographic projection.
|
||||
* !#zh
|
||||
* 摄像机在正交投影模式下的视窗大小。
|
||||
* @property {Number} orthoSize
|
||||
* @default 10
|
||||
*/
|
||||
orthoSize: {
|
||||
get () {
|
||||
return this._orthoSize;
|
||||
},
|
||||
set (v) {
|
||||
this._orthoSize = v;
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.orthoSize',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The near clipping plane.
|
||||
* !#zh
|
||||
* 摄像机的近剪裁面。
|
||||
* @property {Number} nearClip
|
||||
* @default 0.1
|
||||
*/
|
||||
nearClip: {
|
||||
get () {
|
||||
return this._nearClip;
|
||||
},
|
||||
set (v) {
|
||||
this._nearClip = v;
|
||||
this._updateClippingpPlanes();
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.nearClip',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The far clipping plane.
|
||||
* !#zh
|
||||
* 摄像机的远剪裁面。
|
||||
* @property {Number} farClip
|
||||
* @default 4096
|
||||
*/
|
||||
farClip: {
|
||||
get () {
|
||||
return this._farClip;
|
||||
},
|
||||
set (v) {
|
||||
this._farClip = v;
|
||||
this._updateClippingpPlanes();
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.farClip',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Is the camera orthographic (true) or perspective (false)?
|
||||
* !#zh
|
||||
* 设置摄像机的投影模式是正交还是透视模式。
|
||||
* @property {Boolean} ortho
|
||||
* @default false
|
||||
*/
|
||||
ortho: {
|
||||
get () {
|
||||
return this._ortho;
|
||||
},
|
||||
set (v) {
|
||||
this._ortho = v;
|
||||
this._updateProjection();
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.ortho',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Four values (0 ~ 1) that indicate where on the screen this camera view will be drawn.
|
||||
* !#zh
|
||||
* 决定摄像机绘制在屏幕上哪个位置,值为(0 ~ 1)。
|
||||
* @property {Rect} rect
|
||||
* @default cc.rect(0,0,1,1)
|
||||
*/
|
||||
rect: {
|
||||
get () {
|
||||
return this._rect;
|
||||
},
|
||||
set (v) {
|
||||
this._rect = v;
|
||||
this._updateRect();
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.rect',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* This is used to render parts of the scene selectively.
|
||||
* !#zh
|
||||
* 决定摄像机会渲染场景的哪一部分。
|
||||
* @property {Number} cullingMask
|
||||
*/
|
||||
cullingMask: {
|
||||
get () {
|
||||
return this._cullingMask;
|
||||
},
|
||||
set (value) {
|
||||
this._cullingMask = value;
|
||||
this._updateCameraMask();
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.cullingMask',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Determining what to clear when camera rendering.
|
||||
* !#zh
|
||||
* 决定摄像机渲染时会清除哪些状态。
|
||||
* @property {Camera.ClearFlags} clearFlags
|
||||
*/
|
||||
clearFlags: {
|
||||
get () {
|
||||
return this._clearFlags;
|
||||
},
|
||||
set (value) {
|
||||
this._clearFlags = value;
|
||||
if (this._camera) {
|
||||
this._camera.setClearFlags(value);
|
||||
}
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.clearFlags',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* The color with which the screen will be cleared.
|
||||
* !#zh
|
||||
* 摄像机用于清除屏幕的背景色。
|
||||
* @property {Color} backgroundColor
|
||||
*/
|
||||
backgroundColor: {
|
||||
get () {
|
||||
return this._backgroundColor;
|
||||
},
|
||||
set (value) {
|
||||
if (!this._backgroundColor.equals(value)) {
|
||||
this._backgroundColor.set(value);
|
||||
this._updateBackgroundColor();
|
||||
}
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.backgroundColor',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Camera's depth in the camera rendering order. Cameras with higher depth are rendered after cameras with lower depth.
|
||||
* !#zh
|
||||
* 摄像机深度。用于决定摄像机的渲染顺序,值越大渲染在越上层。
|
||||
* @property {Number} depth
|
||||
*/
|
||||
depth: {
|
||||
get () {
|
||||
return this._depth;
|
||||
},
|
||||
set (value) {
|
||||
if (Camera.main === this) {
|
||||
if (this._depth < value) {
|
||||
updateMainCamera();
|
||||
}
|
||||
}
|
||||
else if (Camera.main && value < Camera.main._depth && _cameras.includes(this)) {
|
||||
Camera.main = this;
|
||||
}
|
||||
|
||||
this._depth = value;
|
||||
if (this._camera) {
|
||||
this._camera.setPriority(value);
|
||||
}
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.depth',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Destination render texture.
|
||||
* Usually cameras render directly to screen, but for some effects it is useful to make a camera render into a texture.
|
||||
* !#zh
|
||||
* 摄像机渲染的目标 RenderTexture。
|
||||
* 一般摄像机会直接渲染到屏幕上,但是有一些效果可以使用摄像机渲染到 RenderTexture 上再对 RenderTexture 进行处理来实现。
|
||||
* @property {RenderTexture} targetTexture
|
||||
*/
|
||||
targetTexture: {
|
||||
get () {
|
||||
return this._targetTexture;
|
||||
},
|
||||
set (value) {
|
||||
this._targetTexture = value;
|
||||
this._updateTargetTexture();
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.targetTexture',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Sets the camera's render stages.
|
||||
* !#zh
|
||||
* 设置摄像机渲染的阶段
|
||||
* @property {Number} renderStages
|
||||
*/
|
||||
renderStages: {
|
||||
get () {
|
||||
return this._renderStages;
|
||||
},
|
||||
set (val) {
|
||||
this._renderStages = val;
|
||||
this._updateStages();
|
||||
},
|
||||
tooltip: CC_DEV && 'i18n:COMPONENT.camera.renderStages',
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en Whether auto align camera viewport to screen
|
||||
* !#zh 是否自动将摄像机的视口对准屏幕
|
||||
* @property {Boolean} alignWithScreen
|
||||
*/
|
||||
alignWithScreen: {
|
||||
get () {
|
||||
return this._alignWithScreen;
|
||||
},
|
||||
set (v) {
|
||||
this._alignWithScreen = v;
|
||||
}
|
||||
},
|
||||
|
||||
_is3D: {
|
||||
get () {
|
||||
return this.node && this.node._is3DNode;
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
statics: {
|
||||
/**
|
||||
* !#en
|
||||
* The primary camera in the scene. Returns the rear most rendered camera, which is the camera with the lowest depth.
|
||||
* !#zh
|
||||
* 当前场景中激活的主摄像机。将会返回渲染在屏幕最底层,也就是 depth 最小的摄像机。
|
||||
* @property {Camera} main
|
||||
* @static
|
||||
*/
|
||||
main: null,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* All enabled cameras.
|
||||
* !#zh
|
||||
* 当前激活的所有摄像机。
|
||||
* @property {[Camera]} cameras
|
||||
* @static
|
||||
*/
|
||||
cameras: _cameras,
|
||||
|
||||
ClearFlags: ClearFlags,
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get the first camera which the node belong to.
|
||||
* !#zh
|
||||
* 获取节点所在的第一个摄像机。
|
||||
* @method findCamera
|
||||
* @param {Node} node
|
||||
* @return {Camera}
|
||||
* @static
|
||||
*/
|
||||
findCamera (node) {
|
||||
for (let i = 0, l = _cameras.length; i < l; i++) {
|
||||
let camera = _cameras[i];
|
||||
if (camera.containsNode(node)) {
|
||||
return camera;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
},
|
||||
|
||||
_findRendererCamera (node) {
|
||||
let cameras = renderer.scene._cameras;
|
||||
for (let i = 0; i < cameras._count; i++) {
|
||||
if (cameras._data[i]._cullingMask & node._cullingMask) {
|
||||
return cameras._data[i];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
},
|
||||
|
||||
_setupDebugCamera () {
|
||||
if (_debugCamera) return;
|
||||
if (game.renderType === game.RENDER_TYPE_CANVAS) return;
|
||||
let camera = new RendererCamera();
|
||||
_debugCamera = camera;
|
||||
|
||||
camera.setStages([
|
||||
'opaque',
|
||||
]);
|
||||
|
||||
camera.setFov(Math.PI * 60 / 180);
|
||||
camera.setNear(0.1);
|
||||
camera.setFar(4096);
|
||||
|
||||
camera.dirty = true;
|
||||
|
||||
camera.cullingMask = 1 << cc.Node.BuiltinGroupIndex.DEBUG;
|
||||
camera.setPriority(cc.macro.MAX_ZINDEX);
|
||||
camera.setClearFlags(0);
|
||||
camera.setColor(0, 0, 0, 0);
|
||||
|
||||
let node = new cc.Node();
|
||||
camera.setNode(node);
|
||||
|
||||
repositionDebugCamera();
|
||||
cc.view.on('design-resolution-changed', repositionDebugCamera);
|
||||
|
||||
renderer.scene.addCamera(camera);
|
||||
}
|
||||
},
|
||||
|
||||
_updateCameraMask () {
|
||||
if (this._camera) {
|
||||
let mask = this._cullingMask & (~(1 << cc.Node.BuiltinGroupIndex.DEBUG));
|
||||
this._camera.cullingMask = mask;
|
||||
}
|
||||
},
|
||||
|
||||
_updateBackgroundColor () {
|
||||
if (!this._camera) return;
|
||||
|
||||
let color = this._backgroundColor;
|
||||
this._camera.setColor(
|
||||
color.r / 255,
|
||||
color.g / 255,
|
||||
color.b / 255,
|
||||
color.a / 255,
|
||||
);
|
||||
},
|
||||
|
||||
_updateTargetTexture () {
|
||||
if (!this._camera) return;
|
||||
|
||||
let texture = this._targetTexture;
|
||||
this._camera.setFrameBuffer(texture ? texture._framebuffer : null);
|
||||
},
|
||||
|
||||
_updateClippingpPlanes () {
|
||||
if (!this._camera) return;
|
||||
this._camera.setNear(this._nearClip);
|
||||
this._camera.setFar(this._farClip);
|
||||
},
|
||||
|
||||
_updateProjection () {
|
||||
if (!this._camera) return;
|
||||
let type = this._ortho ? 1 : 0;
|
||||
this._camera.setType(type);
|
||||
},
|
||||
|
||||
_updateRect () {
|
||||
if (!this._camera) return;
|
||||
let rect = this._rect;
|
||||
this._camera.setRect(rect.x, rect.y, rect.width, rect.height);
|
||||
},
|
||||
|
||||
_updateStages () {
|
||||
let flags = this._renderStages;
|
||||
let stages = [];
|
||||
if (flags & StageFlags.OPAQUE) {
|
||||
stages.push('opaque');
|
||||
}
|
||||
if (flags & StageFlags.TRANSPARENT) {
|
||||
stages.push('transparent');
|
||||
}
|
||||
this._camera.setStages(stages);
|
||||
},
|
||||
|
||||
_init () {
|
||||
if (this._inited) return;
|
||||
this._inited = true;
|
||||
|
||||
let camera = this._camera;
|
||||
if (!camera) return;
|
||||
camera.setNode(this.node);
|
||||
camera.setClearFlags(this._clearFlags);
|
||||
camera.setPriority(this._depth);
|
||||
this._updateBackgroundColor();
|
||||
this._updateCameraMask();
|
||||
this._updateTargetTexture();
|
||||
this._updateClippingpPlanes();
|
||||
this._updateProjection();
|
||||
this._updateStages();
|
||||
this._updateRect();
|
||||
|
||||
if (!CC_EDITOR) {
|
||||
this.beforeDraw();
|
||||
}
|
||||
},
|
||||
|
||||
__preload () {
|
||||
this._init();
|
||||
},
|
||||
|
||||
onEnable () {
|
||||
if (!CC_EDITOR && game.renderType !== game.RENDER_TYPE_CANVAS) {
|
||||
cc.director.on(cc.Director.EVENT_BEFORE_DRAW, this.beforeDraw, this);
|
||||
renderer.scene.addCamera(this._camera);
|
||||
}
|
||||
_cameras.push(this);
|
||||
if (!Camera.main || (this._depth < Camera.main._depth)) {
|
||||
Camera.main = this;
|
||||
}
|
||||
},
|
||||
|
||||
onDisable () {
|
||||
if (!CC_EDITOR && game.renderType !== game.RENDER_TYPE_CANVAS) {
|
||||
cc.director.off(cc.Director.EVENT_BEFORE_DRAW, this.beforeDraw, this);
|
||||
renderer.scene.removeCamera(this._camera);
|
||||
}
|
||||
cc.js.array.fastRemove(_cameras, this);
|
||||
if (Camera.main === this) {
|
||||
Camera.main = null;
|
||||
updateMainCamera();
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get the screen to world matrix, only support 2D camera which alignWithScreen is true.
|
||||
* !#zh
|
||||
* 获取屏幕坐标系到世界坐标系的矩阵,只适用于 alignWithScreen 为 true 的 2D 摄像机。
|
||||
* @method getScreenToWorldMatrix2D
|
||||
* @param {Mat4} out - the matrix to receive the result
|
||||
* @return {Mat4} out
|
||||
*/
|
||||
getScreenToWorldMatrix2D (out) {
|
||||
this.getWorldToScreenMatrix2D(out);
|
||||
Mat4.invert(out, out);
|
||||
return out;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get the world to camera matrix, only support 2D camera which alignWithScreen is true.
|
||||
* !#zh
|
||||
* 获取世界坐标系到摄像机坐标系的矩阵,只适用于 alignWithScreen 为 true 的 2D 摄像机。
|
||||
* @method getWorldToScreenMatrix2D
|
||||
* @param {Mat4} out - the matrix to receive the result
|
||||
* @return {Mat4} out
|
||||
*/
|
||||
getWorldToScreenMatrix2D (out) {
|
||||
this.node.getWorldRT(_mat4_temp_1);
|
||||
|
||||
let zoomRatio = this.zoomRatio;
|
||||
let _mat4_temp_1m = _mat4_temp_1.m;
|
||||
_mat4_temp_1m[0] *= zoomRatio;
|
||||
_mat4_temp_1m[1] *= zoomRatio;
|
||||
_mat4_temp_1m[4] *= zoomRatio;
|
||||
_mat4_temp_1m[5] *= zoomRatio;
|
||||
|
||||
let m12 = _mat4_temp_1m[12];
|
||||
let m13 = _mat4_temp_1m[13];
|
||||
|
||||
let center = cc.visibleRect.center;
|
||||
_mat4_temp_1m[12] = center.x - (_mat4_temp_1m[0] * m12 + _mat4_temp_1m[4] * m13);
|
||||
_mat4_temp_1m[13] = center.y - (_mat4_temp_1m[1] * m12 + _mat4_temp_1m[5] * m13);
|
||||
|
||||
if (out !== _mat4_temp_1) {
|
||||
Mat4.copy(out, _mat4_temp_1);
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Convert point from screen to world.
|
||||
* !#zh
|
||||
* 将坐标从屏幕坐标系转换到世界坐标系。
|
||||
* @method getScreenToWorldPoint
|
||||
* @param {Vec3|Vec2} screenPosition
|
||||
* @param {Vec3|Vec2} [out]
|
||||
* @return {Vec3|Vec2} out
|
||||
*/
|
||||
getScreenToWorldPoint (screenPosition, out) {
|
||||
if (this.node.is3DNode) {
|
||||
out = out || new cc.Vec3();
|
||||
this._camera.screenToWorld(out, screenPosition, cc.visibleRect.width, cc.visibleRect.height);
|
||||
}
|
||||
else {
|
||||
out = out || new cc.Vec2();
|
||||
this.getScreenToWorldMatrix2D(_mat4_temp_1);
|
||||
Vec2.transformMat4(out, screenPosition, _mat4_temp_1);
|
||||
}
|
||||
return out;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Convert point from world to screen.
|
||||
* !#zh
|
||||
* 将坐标从世界坐标系转化到屏幕坐标系。
|
||||
* @method getWorldToScreenPoint
|
||||
* @param {Vec3|Vec2} worldPosition
|
||||
* @param {Vec3|Vec2} [out]
|
||||
* @return {Vec3|Vec2} out
|
||||
*/
|
||||
getWorldToScreenPoint (worldPosition, out) {
|
||||
if (this.node.is3DNode) {
|
||||
out = out || new cc.Vec3();
|
||||
this._camera.worldToScreen(out, worldPosition, cc.visibleRect.width, cc.visibleRect.height);
|
||||
}
|
||||
else {
|
||||
out = out || new cc.Vec2();
|
||||
this.getWorldToScreenMatrix2D(_mat4_temp_1);
|
||||
Vec2.transformMat4(out, worldPosition, _mat4_temp_1);
|
||||
}
|
||||
|
||||
return out;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get a ray from screen position
|
||||
* !#zh
|
||||
* 从屏幕坐标获取一条射线
|
||||
* @method getRay
|
||||
* @param {Vec2} screenPos
|
||||
* @return {Ray}
|
||||
*/
|
||||
getRay (screenPos) {
|
||||
if (!cc.geomUtils) return screenPos;
|
||||
|
||||
Vec3.set(_v3_temp_3, screenPos.x, screenPos.y, 1);
|
||||
this._camera.screenToWorld(_v3_temp_2, _v3_temp_3, cc.visibleRect.width, cc.visibleRect.height);
|
||||
|
||||
if (this.ortho) {
|
||||
Vec3.set(_v3_temp_3, screenPos.x, screenPos.y, -1);
|
||||
this._camera.screenToWorld(_v3_temp_1, _v3_temp_3, cc.visibleRect.width, cc.visibleRect.height);
|
||||
}
|
||||
else {
|
||||
this.node.getWorldPosition(_v3_temp_1);
|
||||
}
|
||||
|
||||
return Ray.fromPoints(new Ray(), _v3_temp_1, _v3_temp_2);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Check whether the node is in the camera.
|
||||
* !#zh
|
||||
* 检测节点是否被此摄像机影响
|
||||
* @method containsNode
|
||||
* @param {Node} node - the node which need to check
|
||||
* @return {Boolean}
|
||||
*/
|
||||
containsNode (node) {
|
||||
return (node._cullingMask & this.cullingMask) > 0;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Render the camera manually.
|
||||
* !#zh
|
||||
* 手动渲染摄像机。
|
||||
* @method render
|
||||
* @param {Node} [rootNode]
|
||||
*/
|
||||
render (rootNode) {
|
||||
rootNode = rootNode || cc.director.getScene();
|
||||
if (!rootNode) return null;
|
||||
|
||||
// force update node world matrix
|
||||
this.node.getWorldMatrix(_mat4_temp_1);
|
||||
this.beforeDraw();
|
||||
|
||||
RenderFlow.renderCamera(this._camera, rootNode);
|
||||
},
|
||||
|
||||
_onAlignWithScreen () {
|
||||
let height = cc.game.canvas.height / cc.view._scaleY;
|
||||
|
||||
let targetTexture = this._targetTexture;
|
||||
if (targetTexture) {
|
||||
if (CC_EDITOR) {
|
||||
height = cc.engine.getDesignResolutionSize().height;
|
||||
}
|
||||
else {
|
||||
height = cc.visibleRect.height;
|
||||
}
|
||||
}
|
||||
|
||||
let fov = this._fov * cc.macro.RAD;
|
||||
this.node.z = height / (Math.tan(fov / 2) * 2);
|
||||
|
||||
fov = Math.atan(Math.tan(fov / 2) / this.zoomRatio) * 2;
|
||||
this._camera.setFov(fov);
|
||||
this._camera.setOrthoHeight(height / 2 / this.zoomRatio);
|
||||
this.node.setRotation(0, 0, 0, 1);
|
||||
},
|
||||
|
||||
beforeDraw () {
|
||||
if (!this._camera) return;
|
||||
|
||||
if (this._alignWithScreen) {
|
||||
this._onAlignWithScreen();
|
||||
}
|
||||
else {
|
||||
let fov = this._fov * cc.macro.RAD;
|
||||
fov = Math.atan(Math.tan(fov / 2) / this.zoomRatio) * 2;
|
||||
this._camera.setFov(fov);
|
||||
|
||||
this._camera.setOrthoHeight(this._orthoSize / this.zoomRatio);
|
||||
}
|
||||
|
||||
this._camera.dirty = true;
|
||||
}
|
||||
});
|
||||
|
||||
// deprecated
|
||||
cc.js.mixin(Camera.prototype, {
|
||||
/**
|
||||
* !#en
|
||||
* Returns the matrix that transform the node's (local) space coordinates into the camera's space coordinates.
|
||||
* !#zh
|
||||
* 返回一个将节点坐标系转换到摄像机坐标系下的矩阵
|
||||
* @method getNodeToCameraTransform
|
||||
* @deprecated since v2.0.0
|
||||
* @param {Node} node - the node which should transform
|
||||
* @return {AffineTransform}
|
||||
*/
|
||||
getNodeToCameraTransform (node) {
|
||||
let out = AffineTrans.identity();
|
||||
node.getWorldMatrix(_mat4_temp_2);
|
||||
if (this.containsNode(node)) {
|
||||
this.getWorldToCameraMatrix(_mat4_temp_1);
|
||||
Mat4.mul(_mat4_temp_2, _mat4_temp_2, _mat4_temp_1);
|
||||
}
|
||||
AffineTrans.fromMat4(out, _mat4_temp_2);
|
||||
return out;
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Conver a camera coordinates point to world coordinates.
|
||||
* !#zh
|
||||
* 将一个摄像机坐标系下的点转换到世界坐标系下。
|
||||
* @method getCameraToWorldPoint
|
||||
* @deprecated since v2.1.3
|
||||
* @param {Vec2} point - the point which should transform
|
||||
* @param {Vec2} [out] - the point to receive the result
|
||||
* @return {Vec2} out
|
||||
*/
|
||||
getCameraToWorldPoint (point, out) {
|
||||
return this.getScreenToWorldPoint(point, out);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Conver a world coordinates point to camera coordinates.
|
||||
* !#zh
|
||||
* 将一个世界坐标系下的点转换到摄像机坐标系下。
|
||||
* @method getWorldToCameraPoint
|
||||
* @deprecated since v2.1.3
|
||||
* @param {Vec2} point
|
||||
* @param {Vec2} [out] - the point to receive the result
|
||||
* @return {Vec2} out
|
||||
*/
|
||||
getWorldToCameraPoint (point, out) {
|
||||
return this.getWorldToScreenPoint(point, out);
|
||||
},
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get the camera to world matrix
|
||||
* !#zh
|
||||
* 获取摄像机坐标系到世界坐标系的矩阵
|
||||
* @method getCameraToWorldMatrix
|
||||
* @deprecated since v2.1.3
|
||||
* @param {Mat4} out - the matrix to receive the result
|
||||
* @return {Mat4} out
|
||||
*/
|
||||
getCameraToWorldMatrix (out) {
|
||||
return this.getScreenToWorldMatrix2D(out);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* !#en
|
||||
* Get the world to camera matrix
|
||||
* !#zh
|
||||
* 获取世界坐标系到摄像机坐标系的矩阵
|
||||
* @method getWorldToCameraMatrix
|
||||
* @deprecated since v2.1.3
|
||||
* @param {Mat4} out - the matrix to receive the result
|
||||
* @return {Mat4} out
|
||||
*/
|
||||
getWorldToCameraMatrix (out) {
|
||||
return this.getWorldToScreenMatrix2D(out);
|
||||
},
|
||||
});
|
||||
|
||||
module.exports = cc.Camera = Camera;
|
Reference in New Issue
Block a user