1 /****************************************************************************
  2  Copyright (c) 2010-2012 cocos2d-x.org
  3  Copyright (c) 2008-2010 Ricardo Quesada
  4  Copyright (c) 2011      Zynga Inc.
  5 
  6  http://www.cocos2d-x.org
  7 
  8  Permission is hereby granted, free of charge, to any person obtaining a copy
  9  of this software and associated documentation files (the "Software"), to deal
 10  in the Software without restriction, including without limitation the rights
 11  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 12  copies of the Software, and to permit persons to whom the Software is
 13  furnished to do so, subject to the following conditions:
 14 
 15  The above copyright notice and this permission notice shall be included in
 16  all copies or substantial portions of the Software.
 17 
 18  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 19  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 20  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 21  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 22  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 23  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 24  THE SOFTWARE.
 25  ****************************************************************************/
 26 
 27 var cc = cc = cc || {};
 28 
 29 /**
 30  @brief Base class for cc.Camera actions
 31  */
 32 cc.ActionCamera = cc.ActionInterval.extend({
 33     centerXOrig:0,
 34     centerYOrig:0,
 35     centerZOrig:0,
 36     eyeXOrig:0,
 37     eyeYOrig:0,
 38     eyeZOrig:0,
 39     upXOrig:0,
 40     upYOrig:0,
 41     upZOrig:0,
 42     // super methods
 43     startWithTarget:function (target) {
 44         this._super(target);
 45 
 46         var camera = target.getCamera();
 47         camera.getCenterXYZ(this.centerXOrig, this.centerYOrig, this.centerZOrig);
 48         camera.getEyeXYZ(this.eyeXOrig, this.eyeYOrig, this.eyeZOrig);
 49         camera.getUpXYZ(this.upXOrig, this.upYOrig, this.upZOrig);
 50     },
 51     reverse:function () {
 52         return cc.ReverseTime.create(this);
 53     }
 54 });
 55 
 56 /**
 57  @brief cc.OrbitCamera action
 58  Orbits the camera around the center of the screen using spherical coordinates
 59  */
 60 cc.OrbitCamera = cc.ActionCamera.extend({
 61     radius:0.0,
 62     deltaRadius:0.0,
 63     angleZ:0.0,
 64     deltaAngleZ:0.0,
 65     angleX:0.0,
 66     deltaAngleX:0.0,
 67     radZ:0.0,
 68     radDeltaZ:0.0,
 69     radX:0.0,
 70     radDeltaX:0.0,
 71 
 72     /** initializes a cc.OrbitCamera action with radius, delta-radius,  z, deltaZ, x, deltaX */
 73     initWithDuration:function (t, radius, deltaRadius, angleZ, deltaAngleZ, angleX, deltaAngleX) {
 74         if (this._super(t)) {
 75             this.radius = radius;
 76             this.deltaRadius = deltaRadius;
 77             this.angleZ = angleZ;
 78             this.deltaAngleZ = deltaAngleZ;
 79             this.angleX = angleX;
 80             this.deltaAngleX = deltaAngleX;
 81 
 82             this.radDeltaZ = cc.DEGREES_TO_RADIANS(deltaAngleZ);
 83             this.radDeltaX = cc.DEGREES_TO_RADIANS(deltaAngleX);
 84             return true;
 85         }
 86         return false;
 87     },
 88     /** positions the camera according to spherical coordinates */
 89     sphericalRadius:function (newRadius, zenith, azimuth) {
 90         var ex, ey, ez, cx, cy, cz, x, y, z;
 91         var r; // radius
 92         var s;
 93 
 94         var camera = this._target.getCamera();
 95         camera.getEyeXYZ(ex, ey, ez);
 96         camera.getCenterXYZ(cx, cy, cz);
 97 
 98         x = ex - cx;
 99         y = ey - cy;
100         z = ez - cz;
101 
102         r = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2));
103         s = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2));
104         if (s == 0.0)
105             s = cc.FLT_EPSILON;
106         if (r == 0.0)
107             r = cc.FLT_EPSILON;
108 
109         zenith = Math.acos(z / r);
110         if (x < 0)
111             azimuth = Math.PI - Math.asin(y / s);
112         else
113             azimuth = Math.asin(y / s);
114 
115         newRadius = r / cc.Camera.getZEye();
116     },
117     // super methods
118     copyWithZone:function (zone) {
119         var newZone = null;
120         var ret = null;
121         if (zone && zone.copyObject) //in case of being called at sub class
122             ret = zone.copyObject;
123         else {
124             ret = new cc.OrbitCamera();
125             zone = newZone = new cc.Zone(ret);
126         }
127 
128         cc.ActionInterval.copyWithZone(zone);
129 
130         ret.initWithDuration(this._duration, this.radius, this.deltaRadius, this.angleZ, this.deltaAngleZ, this.angleX, this.deltaAngleX);
131 
132         return ret;
133     },
134     startWithTarget:function (target) {
135         this._super(target);
136         var r, zenith, azimuth;
137         this.sphericalRadius(r, zenith, azimuth);
138         if (isNaN(this.radius)) {
139             this.radius = r;
140         }
141         if (isNaN(this.angleZ)) {
142             this.angleZ = cc.RADIANS_TO_DEGREES(zenith);
143         }
144         if (isNaN(this.angleX)) {
145             this.angleX = cc.RADIANS_TO_DEGREES(azimuth);
146         }
147 
148         this.radZ = cc.DEGREES_TO_RADIANS(this.angleZ);
149         this.radX = cc.DEGREES_TO_RADIANS(this.angleX);
150     },
151     update:function (dt) {
152         var r = (this.radius + this.deltaRadius * dt) * cc.Camera.getZEye();
153         var za = this.radZ + this.radDeltaZ * dt;
154         var xa = this.radX + this.radDeltaX * dt;
155 
156         var i = Math.sin(za) * Math.cos(xa) * r + this.centerXOrig;
157         var j = Math.sin(za) * Math.sin(xa) * r + this.centerYOrig;
158         var k = Math.cos(za) * r + this.centerZOrig;
159 
160         this._target.getCamera().setEyeXYZ(i, j, k);
161     }
162 });
163 
164 /** creates a cc.OrbitCamera action with radius, delta-radius,  z, deltaZ, x, deltaX */
165 cc.OrbitCamera.create = function (t, radius, deltaRadius, angleZ, deltaAngleZ, angleX, deltaAngleX) {
166     var ret = new cc.OrbitCamera();
167     if (ret.initWithDuration(t, radius, deltaRadius, angleZ, deltaAngleZ, angleX, deltaAngleX)) {
168         return ret;
169     }
170     return null;
171 };
172