1
# ----------------------------------------------------------------------------
3
# Copyright (c) 2008 Daniel Moisset, Ricardo Quesada, Rayentray Tappa, Lucio Torre
6
# Redistribution and use in source and binary forms, with or without
7
# modification, are permitted provided that the following conditions are met:
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
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
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
# ----------------------------------------------------------------------------
35
Actions that moves the OpenGL camera.
38
__docformat__ = 'restructuredtext'
40
from cocos.director import director
41
from cocos.euclid import *
42
from base_actions import *
46
__all__ = [ 'CameraException', # Camera Exceptions
52
class CameraException( Exception ):
55
class Camera3DAction( IntervalAction ):
56
def init( self, duration=2):
57
"""Initialize the Camera Action
61
Number of seconds that the action will last
63
self.duration = duration
66
super(Camera3DAction, self).start()
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
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
78
def __reversed__( self ):
79
return _ReverseTime( self )
82
class OrbitCamera( Camera3DAction ):
83
'''Orbits the camera around the center of the screen using spherical coordinates
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
90
Radius of the orbit. Default: current radius
91
`delta_radius` : float
92
Delta movement of the radius. Default: 0
94
The zenith angle of the spherical coordinate in degrees. Default: current
96
Relative movement of the zenith angle. Default: 0
98
The azimuth angle of the spherical coordinate in degrees. Default: 0
100
Relative movement of the azimuth angle. Default: 0
103
For more information regarding spherical coordinates, read this:
104
http://en.wikipedia.org/wiki/Spherical_coordinates
107
super( OrbitCamera, self ).init( *args, **kw )
109
width, height = director.get_window_size()
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 )
119
super(OrbitCamera,self).start()
121
radius, zenith, azimuth = self.get_spherical_coords()
123
if self.radius is None:
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)
130
self.rad_x = math.radians( self.angle_x )
131
self.rad_z = math.radians( self.angle_z )
133
def get_spherical_coords( self ):
134
'''returns the spherical coordinates from a cartesian coordinates
138
- http://www.math.montana.edu/frankw/ccp/multiworld/multipleIVP/spherical/body.htm#converting
140
:rtype: ( radius, zenith, azimuth )
142
eye = self.target.camera.eye - self.target.camera.center
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) )
152
angle_z = math.acos( eye.z / float(r) )
154
angle_x = math.pi - math.asin( eye.y / s )
156
angle_x = math.asin( eye.y / s )
158
radius = radius / self.target.camera.get_z_eye()
159
return radius, angle_z, angle_x
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
166
# using spherical coordinates
167
p = Point3( math.sin(z_angle) * math.cos(x_angle),
168
math.sin(z_angle) * math.sin(x_angle),
172
d = p + self.camera_center_orig
173
self.target.camera.eye = d