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