~facundo/enjuewemela/trunk

« back to all changes in this revision

Viewing changes to cocos/actions/camera_actions.py

  • Committer: facundo at com
  • Date: 2010-11-20 01:41:24 UTC
  • mto: This revision was merged to the branch mainline in revision 63.
  • Revision ID: facundo@taniquetil.com.ar-20101120014124-zjyxkchmvili5m2u
Project reorder!

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# ----------------------------------------------------------------------------
 
2
# cocos2d
 
3
# Copyright (c) 2008 Daniel Moisset, Ricardo Quesada, Rayentray Tappa, Lucio Torre
 
4
# All rights reserved.
 
5
#
 
6
# Redistribution and use in source and binary forms, with or without
 
7
# modification, are permitted provided that the following conditions are met:
 
8
#
 
9
#   * Redistributions of source code must retain the above copyright
 
10
#     notice, this list of conditions and the following disclaimer.
 
11
#   * Redistributions in binary form must reproduce the above copyright 
 
12
#     notice, this list of conditions and the following disclaimer in
 
13
#     the documentation and/or other materials provided with the
 
14
#     distribution.
 
15
#   * Neither the name of cocos2d nor the names of its
 
16
#     contributors may be used to endorse or promote products
 
17
#     derived from this software without specific prior written
 
18
#     permission.
 
19
#
 
20
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 
21
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 
22
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 
23
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 
24
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
 
25
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
 
26
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
 
27
# LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
 
28
# CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 
29
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
 
30
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 
31
# POSSIBILITY OF SUCH DAMAGE.
 
32
# ----------------------------------------------------------------------------
 
33
'''Camera Actions
 
34
 
 
35
Actions that moves the OpenGL camera.
 
36
'''
 
37
 
 
38
__docformat__ = 'restructuredtext'
 
39
 
 
40
from cocos.director import director
 
41
from cocos.euclid import *
 
42
from base_actions import *
 
43
 
 
44
import math
 
45
 
 
46
__all__ = [ 'CameraException',            # Camera Exceptions
 
47
           
 
48
            'Camera3DAction',
 
49
            'OrbitCamera',
 
50
            ]
 
51
 
 
52
class CameraException( Exception ):
 
53
    pass
 
54
 
 
55
class Camera3DAction( IntervalAction ):
 
56
    def init( self,  duration=2):
 
57
        """Initialize the Camera Action
 
58
 
 
59
        :Parameters:
 
60
            `duration` : int 
 
61
                Number of seconds that the action will last
 
62
        """
 
63
        self.duration = duration
 
64
 
 
65
    def start( self ):        
 
66
        super(Camera3DAction, self).start()
 
67
 
 
68
        self.camera_eye_orig =  self.target.camera.eye
 
69
        self.camera_center_orig = self.target.camera.center
 
70
        self.camera_up_orig = self.target.camera.up_vector
 
71
 
 
72
#    def stop( self ):
 
73
#        super(Camera3DAction, self).stop()
 
74
#        self.target.camera.eye = self.camera_eye_orig
 
75
#        self.target.camera.center = self.camera_center_orig
 
76
#        self.target.camera.up_vector = self.camera_up_orig
 
77
 
 
78
    def __reversed__( self ):
 
79
        return _ReverseTime( self )
 
80
 
 
81
 
 
82
class OrbitCamera( Camera3DAction ):
 
83
    '''Orbits the camera around the center of the screen using spherical coordinates
 
84
    '''
 
85
    def init( self, radius=None, delta_radius=0, angle_z=None, delta_z=0, angle_x=None, delta_x=0, *args, **kw ):
 
86
        '''Initialize the camera with spherical coordinates
 
87
 
 
88
        :Parameters:
 
89
            `radius` : float
 
90
                Radius of the orbit. Default: current radius
 
91
            `delta_radius` : float
 
92
                Delta movement of the radius. Default: 0
 
93
            `angle_z` : float
 
94
                The zenith angle of the spherical coordinate in degrees. Default: current
 
95
            `delta_z` : float
 
96
                Relative movement of the zenith angle. Default: 0
 
97
            `angle_x` : float
 
98
                The azimuth angle of the spherical coordinate in degrees. Default: 0
 
99
            `delta_x` : float
 
100
                Relative movement of the azimuth angle. Default: 0
 
101
                
 
102
 
 
103
        For more information regarding spherical coordinates, read this:
 
104
            http://en.wikipedia.org/wiki/Spherical_coordinates
 
105
 
 
106
        '''
 
107
        super( OrbitCamera, self ).init( *args, **kw )
 
108
 
 
109
        width, height = director.get_window_size()
 
110
 
 
111
        self.radius = radius
 
112
        self.delta_radius = delta_radius
 
113
        self.angle_x = angle_x
 
114
        self.rad_delta_x= math.radians( delta_x )
 
115
        self.angle_z = angle_z 
 
116
        self.rad_delta_z = math.radians( delta_z )
 
117
 
 
118
    def start( self ):
 
119
        super(OrbitCamera,self).start()
 
120
 
 
121
        radius, zenith, azimuth = self.get_spherical_coords()
 
122
 
 
123
        if self.radius is None:
 
124
            self.radius = radius
 
125
        if self.angle_z is None:
 
126
            self.angle_z= math.degrees(zenith)
 
127
        if self.angle_x is None:
 
128
            self.angle_x= math.degrees(azimuth)
 
129
 
 
130
        self.rad_x = math.radians( self.angle_x )
 
131
        self.rad_z = math.radians( self.angle_z )
 
132
 
 
133
    def get_spherical_coords( self ):
 
134
        '''returns the spherical coordinates from a cartesian coordinates
 
135
 
 
136
        using this formula:
 
137
 
 
138
            - http://www.math.montana.edu/frankw/ccp/multiworld/multipleIVP/spherical/body.htm#converting
 
139
 
 
140
        :rtype: ( radius, zenith, azimuth )
 
141
        '''
 
142
        eye = self.target.camera.eye - self.target.camera.center
 
143
 
 
144
        radius = math.sqrt( pow(eye.x,2) + pow(eye.y,2) + pow(eye.z,2) )
 
145
        s = math.sqrt( pow(eye.x,2) + pow(eye.y,2) )
 
146
        if s == 0:
 
147
            s = 0.000000001
 
148
        r = radius
 
149
        if r == 0:
 
150
            r = 0.000000001
 
151
 
 
152
        angle_z = math.acos( eye.z / float(r) )
 
153
        if eye.x < 0:
 
154
            angle_x = math.pi - math.asin( eye.y / s )
 
155
        else:
 
156
            angle_x = math.asin( eye.y / s )
 
157
 
 
158
        radius = radius / self.target.camera.get_z_eye()
 
159
        return radius, angle_z, angle_x
 
160
 
 
161
    def update( self, t ):
 
162
        r = (self.radius + self.delta_radius * t) * self.target.camera.get_z_eye()
 
163
        z_angle = self.rad_z + self.rad_delta_z * t
 
164
        x_angle = self.rad_x + self.rad_delta_x * t
 
165
 
 
166
        # using spherical coordinates
 
167
        p = Point3( math.sin(z_angle) * math.cos(x_angle),
 
168
                    math.sin(z_angle) * math.sin(x_angle),
 
169
                    math.cos(z_angle) )
 
170
 
 
171
        p = p * r
 
172
        d = p + self.camera_center_orig
 
173
        self.target.camera.eye = d