1 /** 2 * Hilo 3 * Copyright 2015 alibaba.com 4 * Licensed under the MIT License 5 */ 6 7 /** 8 * @class Camera3d is a pseudo-3d camera. 9 * @module hilo/game/Camera3d 10 * @requires hilo/core/Class 11 * @requires hilo/util/util 12 * @property {Number} fv The distance of the fov(The distance between eyes and the Z plane,it determines the scale ratio of the 3d object). 13 * @property {Number} fx The x position of the screen viewpoint(The distance between the screen viewpoint and the screen left top corner on the x axis). 14 * @property {Number} fy The y position of the screen viewpoint(The distance between the screen viewpoint and the screen left top corner on the y axis). 15 * @property {Object} stage The 3d object's container, it can be stage or container.It is required if you need to sort the 3d object by z axis. 16 * @property {Number} x The x position. 17 * @property {Number} y The y position. 18 * @property {Number} z The z position. 19 * @property {Number} rotationX The x rotation. 20 * @property {Number} rotationY The y rotation. 21 * @property {Number} rotationZ The z rotation. 22 */ 23 var Camera3d = (function(){ 24 25 var degtorad = Math.PI / 180; 26 27 //Rotate the axis. 28 function rotateX(x, y, z, ca, sa) {//rotate x 29 return { 30 x: x, 31 y: y * ca - z * sa, 32 z: y * sa + z * ca 33 }; 34 } 35 function rotateY(x, y, z, ca, sa) {//rotate y 36 return { 37 x: x * ca - z * sa, 38 y: y, 39 z: x * sa + z * ca 40 }; 41 } 42 function rotateZ(x, y, z, ca, sa) {//rotate z 43 return { 44 x: x * ca - y * sa, 45 y: x * sa + y * ca, 46 z: z 47 }; 48 } 49 50 var Camera3d = Class.create(/** @lends Camera3d.prototype */{ 51 52 constructor: function(properties){ 53 properties.x = properties.x || 0; 54 properties.y = properties.y || 0; 55 properties.z = properties.z || 0; 56 properties.rotationX = properties.rotationX || 0; 57 properties.rotationY = properties.rotationY || 0; 58 properties.rotationZ = properties.rotationZ || 0; 59 60 util.copy(this, properties); 61 }, 62 63 /** 64 * Translate the camera,used for Zoomin/out feature. 65 * @param {Number} x The x position. 66 * @param {Number} y The y position. 67 * @param {Number} z The z position. 68 */ 69 translate : function(x,y,z){ 70 this.tx = x; 71 this.ty = y; 72 this.tz = z; 73 }, 74 75 /** 76 * Rotate by the x axis. 77 * @param {Number} angle The rotate degree. 78 */ 79 rotateX : function(angle){ 80 this.rotationX = angle; 81 }, 82 83 /** 84 * Rotate by the y axis. 85 * @param {Number} angle The rotate degree. 86 */ 87 rotateY : function(angle){ 88 this.rotationY = angle; 89 }, 90 91 /** 92 * Rotate by the z axis. 93 * @param {Number} angle The rotate degree. 94 */ 95 rotateZ : function(angle){ 96 this.rotationZ = angle; 97 }, 98 99 /** 100 * Project the 3d point to 2d point. 101 * @param {object} vector3D The 3d position, it must have x, y and z properties. 102 * @param {View} view The view related to the 3d position.It'll be auto translated by the 3d position. 103 * @returns {Object} The 2d object include z and scale properties, e.g.:{x:x, y:y, z:z, scale} 104 */ 105 project : function(vector3D, view){ 106 107 var rx = this.rotationX * degtorad, 108 ry = this.rotationY * degtorad, 109 rz = this.rotationZ * degtorad, 110 111 cosX = Math.cos(rx), sinX = Math.sin(rx), 112 cosY = Math.cos(ry), sinY = Math.sin(ry), 113 cosZ = Math.cos(rz), sinZ = Math.sin(rz), 114 115 // 旋转变换前的 仿射矩阵位移, 116 dx = vector3D.x - this.x, 117 dy = vector3D.y - this.y, 118 dz = vector3D.z - this.z; 119 120 // 旋转矩阵变换 121 var vector = rotateZ(dx, dy, dz, cosZ, sinZ); 122 vector = rotateY(vector.x, vector.y, vector.z, cosY, sinY); 123 vector = rotateX(vector.x, vector.y, vector.z, cosX, sinX); 124 125 // 最后的仿射矩阵变换 126 if(this.tx) vector.x -= this.tx; 127 if(this.ty) vector.y -= this.ty; 128 if(this.tz) vector.z -= this.tz; 129 130 var perspective = this.fv / (this.fv + vector.z), 131 _x = vector.x * perspective, 132 _y = -vector.y * perspective; 133 134 var result = { 135 x : _x + this.fx, 136 y : _y + this.fy, 137 z : -vector.z, 138 scale : perspective 139 }; 140 141 if(view){ 142 view.x = result.x; 143 view.y = result.y; 144 view.z = result.z; 145 view.scaleX = result.scale; 146 view.scaleY = result.scale; 147 } 148 149 return result; 150 }, 151 152 /** 153 * Sort by z axis. 154 */ 155 sortZ : function(){ 156 this.stage.children.sort(function(view_a, view_b){ 157 return view_a.z > view_b.z; 158 }); 159 }, 160 161 /** 162 * Used for the ticker. 163 */ 164 tick : function(){ 165 this.sortZ(); 166 } 167 168 }); 169 170 return Camera3d; 171 172 })();