Overview

Ogre internally uses Quaternions for orientation. There are many advantages to this, but there is one main disadvantage: quaternions are usually confusing to beginners. An alternative method of orientation is Euler angles (commonly called yaw, pitch and roll). Euler angles have many disadvantages, but they are also easy to understand. The code in this article provides a Euler class, capable of operating on Euler angles and generating ogre quaternions. It is possible to give a Euler object directly to any Ogre function which normally takes a quaternion, the conversion is automatic.

Euler angles consist of 3 rotations, often known as Yaw, Pitch and Roll. Each of these rotations is around a specific axis.

Yaw is a rotation around the Y axis.Pitch is a rotation around the X axis.Roll is a rotation around the Z axis.
Example of yawing an object with euler angles. Example of pitching an object with euler angles. Example of rolling an object with euler angles.

Euler angles are best suited to situations with restricted orientations. For example, game cameras can usually yaw (rotate around the Y axis, like a person looking left or right) and pitch (rotate around the X axis, like a person looking up or down), but not roll (rotate around the Z axis, like a person tilting their head to either side).

The Euler class allows you to directly set/get absolute pitch, yaw or roll values without affecting each other, for example setting the orientation to face east while preserving the pitch and roll.

Ogre provides methods to use euler angles with matrices and quaternions, however there are problems that make this inconvenient. The primary problem is that multiple combinations of euler angles can produce the same quaternion or matrix. This means that converting eulers into a quaternion then back to euler can give different (but equivilant) results than what you started with. This is often a problem when attempting to apply constraints to an orientation (such as limiting a camera's pitch).

Euler angles are non commutative. This means that the order you apply the rotations matters. Different applications use different orderings. The code provided here uses the YXZ (Yaw Pitch Roll) order. This means that the object performs local yaw, then local pitch, then local roll. This is the same as performing world roll, then world pitch, then world yaw.
This code also follows ogre's coordinate system standard: right handed cartesian coordinates with U axis up and -Z axis forward, and right handed rotations. A positive yaw, pitch or roll operates in the direction shown in the animated images above. Positive yaw is anticlockwise, positive pitch looks up and positive roll is anticlockwise (when looking along -Z). Setting all three angles to 0 gives the same orientation as an identity quaternion or matrix, in other words a model facing -Z will remain facing that direction (-Z is the ogre standard for forwards).

All three euler angles are unlimited in range. This means you can have a yaw of 10000 degrees, or a pitch of -400 degrees. This is impossible in quaternions and matrices, they can only represent the final orientation, not how many rotations took place to get there. Methods are provided to either clamp each angle to a +/-limit range, or normalise the euler object so all angles are wrapped around to the +/-180 degree range.

It is possible to treat the euler class as either absolute or relative. This works like a Vector3, which can represent either an absolute position in space or an offset from a position. For example, subtracting one euler from another gives a euler containing the angular offset between the initial two.

The three angles which make up a euler orientation are stored separately. It is possible to set or get the value of the yaw, pitch or roll without affecting the other angles.

To increase performance, the Euler class stores a cached copy of the last generated quaternion. Any time an angle is changed, a flag is set to indicate the cached copy is out of date. Next time a conversion to quaternion is requested, a full calculation will be done, with the result cached for future reuse. This means the class memory footprint is larger than needed (7 floats and a bool, rather than 3 floats), but quaternion generation involves several sin/cos operations (for a full euler it is typically 3 sin, 3 cos and a bunch of algebra).

Many methods of the euler class return a self reference, allowing you to chain multiple methods together.

Behaviour video

Kojack created a video to show the general Ogre behaviour and the EulerAngleClass one.

Here's a video showing the issue:

The right sinbad uses a euler object with keyboard control (he also has head tracking on, but that's not important here). The euler object is used to set his orientation quaternion.
The middle sinbad reads the right sinbad's orientation (as a quaternion), calls getYaw, getPitch and getRoll on it, puts them into a second euler object and uses it as the orientation.
The left sinbad reads the right sinbad's orientation as well, but it converts the orientation quaternion into a matrix, then uses the matrix ToEulerAnglesYXZ to get the yaw, pitch and roll and puts them in a third euler object and then use that for orientation.

As you can see, the left and right ones are identical. The problem is that the rotation order for getYaw, getPitch and getRoll doesn't match my euler code. But matrices let you choose, so I just picked the correct one.
Different combinations can be chosen based on coordinate system (does yaw go around the y or z axis?) and gimbal lock. When the second angle is 90 or -90 degrees, the first and third angles gimbal lock. So in mine if you look up (pitch), the yaw and roll gimbal lock. If looking up is common, a different ordering would move the gimbal lock to a less important angle.

Basic API Info

getYaw(), getPitch(), getRoll() Retrieve the current yaw, pitch or roll values.
getForward(), getRight(), getUp() Retrieve a Vector3 which points in the specified direction relative to the euler angles.
getRotationTo(dir, setYaw, setPitch, shortest) Return the relative rotation needed to make the euler face dir. If shortest is true, angles are wrapped.
setYaw(angle), setPitch(angle), setRoll(angle) Change the current yaw, pitch or roll values.
setDirection(dir, setYaw, setPitch) Sets the euler to face dir. If setYaw or setPitch are false, the matching angle isn't modified. Roll is always preserved.
setRotation(yaw, pitch, roll) Change the current yaw, pitch or roll values.
yaw(angle), pitch(angle), roll(angle) Add the angle to the current yaw, pitch or roll.
rotate(yaw, pitch, roll) Add all three angles to the current angles.
limitYaw(angle), limitPitch(angle), limitRoll(angle) Clamp to a range of +/-angle.
normalise(normYaw, normPitch, normRoll) Wrap the angles around to be +/-180 degrees. The three parameters control which angles are wrapped.
toQuaternion() Convert the euler to a quaternion.
(Euler = Euler + Euler) Add angles. For example, (90y,0p,0r) added to (20y,0p,0r) will give (110y,0p,0r).
(Euler = Euler - Euler) Subtract angles.
(Euler = Euler * Real) or (Euler = Real * Euler) Interpolation of the euler angles by Real.
(Quaternion = Euler * Euler) Rotate one euler object by another, returning a quaternion.
(Vector3 = Euler * Vector3) Rotate a vector by the euler object.

Euler class

For a Mogre compatible C# port, go to Euler Angle Class Mogre

/**
    @file Euler.h
    @brief %Euler class for %Ogre
    @details License: Do whatever you want with it.
    @version 2.3
    @author Kojack 
    @author Transporter
    @author Klaim

Extracted From: http://www.ogre3d.org/tikiwiki/tiki-ind ... e=Cookbook
*/
#ifndef HGUARD_OGRE_MATHS_EULER_H
#define HGUARD_OGRE_MATHS_EULER_H
 
#include "OgreMaths.h"
#include "OgreVector3.h"
#include "OgreQuaternion.h"
#include "OgreMatrix3.h"
 
namespace Ogre {
 
    /**
    @class Euler
    @brief Class for %Euler rotations
 
    <table><tr><td>Yaw is a rotation around the Y axis.</td><td>Pitch is a rotation around the X axis.</td><td>Roll is a rotation around the Z axis.</td></tr>
    <tr><td><img src="http://www.ogre3d.org/tikiwiki/tiki-download_file.php?fileId=2112" /></td><td><img src="http://www.ogre3d.org/tikiwiki/tiki-download_file.php?fileId=2113" /></td><td><img src="http://www.ogre3d.org/tikiwiki/tiki-download_file.php?fileId=2114" /></td></tr></table>
    */
    class Euler
    {
    public:
       /// Default constructor.
       Euler()
          : mYaw(Radian(0.0f)), mPitch(Radian(0.0f)), mRoll(Radian(0.0f)), mChanged(true) 
       {
       }
 
       /**
       @brief Constructor which takes yaw, pitch and roll values.   
       @param y Starting value for yaw
       @param p Starting value for pitch
       @param r Starting value for roll
       */
       Euler(const Radian &y, const Radian &p = Radian(0.0f), const Radian &r = Radian(0.0f))
          : mYaw(y), mPitch(p), mRoll(r), mChanged(true) 
       {
       }
 
        /**
       @brief Constructor which takes yaw, pitch and roll values as reals (radians).
       @param y Starting value for yaw [radian]
       @param p Starting value for pitch [radian]
       @param r Starting value for roll [radian]
       */
       Euler(Real y, Real p = 0.0f, Real r = 0.0f)
          : mYaw(Radian(y)), mPitch(Radian(p)), mRoll(Radian(r)), mChanged(true) 
       {
       }
 
       /**
       @brief Default constructor with presets.
       @param quaternion Calculate starting values from this quaternion
       */
       explicit Euler(const Quaternion &quaternion)
       {
          fromQuaternion(quaternion);
       }
 
       explicit Euler(const Matrix3 &matrix)
       {
          fromMatrix3(matrix);
       }
 
       /// Get the Yaw angle.
       inline Radian yaw() const { return mYaw; }
 
       /// Get the Pitch angle.
       inline Radian pitch() const { return mPitch; }
 
       /// Get the Roll angle.
       inline Radian roll() const { return mRoll; }
 
       /**
       @brief Set the yaw.
       @param y New value for yaw
       */
       inline Euler &setYaw(Radian y)
       {
          mYaw = y; 
          mChanged = true; 
          return *this;
       }
 
       /**
       @brief Set the pitch.
       @param p New value for pitch
       */
       inline Euler &setPitch(Radian p) 
       {
          mPitch = p; 
          mChanged = true; 
          return *this;
       }
 
       /**
       @brief Set the roll.
       @param r New value for roll
       */
       inline Euler &setRoll(Radian r) 
       {
          mRoll = r; 
          mChanged = true; 
          return *this;
       }
 
       /**
       @brief Set all rotations at once.
       @param y New value for yaw
       @param p New value for pitch
       @param r New value for roll
       */
       inline Euler &orientation(const Radian &y, const Radian &p, const Radian &r)
       {
          mYaw = y;
          mPitch = p;
          mRoll = r; 
          mChanged = true; 
          return *this;
       }
 
       /**
       @brief Apply a relative yaw.
       @param y Angle to add on current yaw
       */
       inline Euler &yaw(const Radian &y) 
       {
          mYaw += y; 
          mChanged = true; 
          return *this;
       }
 
       /**
       @brief Apply a relative pitch.
       @param p Angle to add on current pitch
       */
       inline Euler &pitch(const Radian &p) 
       {
          mPitch += p; 
          mChanged = true; 
          return *this;
       }
 
       /**
       @brief Apply a relative roll.
       @param r Angle to add on current roll
       */
       inline Euler &roll(const Radian &r) 
       {
          mRoll += r; 
          mChanged = true; 
          return *this;
       }
 
       /**
       @brief Apply all relative rotations at once.
       @param y Angle to add on current yaw
       @param p Angle to add on current pitch
       @param r Angle to add on current roll
       */
       inline Euler &rotate(const Radian &y, const Radian &p, const Radian &r)
       {
          mYaw += y;
          mPitch += p;
          mRoll += r; 
          mChanged = true; 
          return *this;
       }
 
       /// Get a vector pointing forwards.
       inline Vector3 forward() const { return toQuaternion() * Vector3::NEGATIVE_UNIT_Z; }
 
       /// Get a vector pointing to the right.
       inline Vector3 right() const { return toQuaternion() * Vector3::UNIT_X; }
 
       /// Get a vector pointing up.
       inline Vector3 up() const { return toQuaternion() * Vector3::UNIT_Y; }
 
       /**
       @brief Calculate the quaternion of the euler object.
       @details The result is cached, it is only recalculated when the component euler angles are changed.
       */
       inline Quaternion toQuaternion() const
       {
          if(mChanged) 
          {
             mCachedQuaternion = Quaternion(mYaw, Vector3::UNIT_Y) * Quaternion(mPitch, Vector3::UNIT_X) * Quaternion(mRoll, Vector3::UNIT_Z); 
             mChanged = false;
          }
          return mCachedQuaternion;
       }
 
       /// Casting operator. This allows any ogre function that wants a Quaternion to accept a Euler instead.
       inline operator Quaternion() const
       {
          return toQuaternion();
       }
 
       /**
       @brief Calculate the current euler angles of a given quaternion object.
       @param quaternion Quaternion which is used to calculate current euler angles.
       */
       inline Euler &fromQuaternion(const Quaternion &quaternion)
       {
          Matrix3 rotmat;
          quaternion.ToRotationMatrix(rotmat);
          fromMatrix3(rotmat);
          return *this;
       }
 
       /**
       @brief Calculate the current euler angles of a given matrix object.
       @param matrix Matrix3 which is used to calculate current euler angles.
       */
       inline Euler &fromMatrix3(const Matrix3 &matrix)
       {
          matrix.ToEulerAnglesYXZ(mYaw,mPitch,mRoll);
          mChanged = true;
          return *this;
       }
 
       /**
       @brief Set the yaw and pitch to face in the given direction.
       @details The direction doesn't need to be normalised. Roll is always unaffected.
       @param setYaw If false, the yaw isn't changed.
       @param setPitch If false, the pitch isn't changed.
       */
       inline Euler &direction(const Vector3 &v, bool setYaw = true, bool setPitch = true)
       {
          Vector3 d(v.normalisedCopy());
          if(setPitch)
             mPitch = Math::ASin(d.y);
          if(setYaw)
             mYaw = Math::ATan2(-d.x, -d.z);
          mChanged = setYaw||setPitch;
           return *this;
       }
 
       /**
       @brief Normalise the selected rotations to be within the +/-180 degree range.
       @details The normalise uses a wrap around, so for example a yaw of 360 degrees becomes 0 degrees, and -190 degrees becomes 170.
       @param normYaw If false, the yaw isn't normalized.
       @param normPitch If false, the pitch isn't normalized.
       @param normRoll If false, the roll isn't normalized.
       */
       inline Euler &normalise(bool normYaw = true, bool normPitch = true, bool normRoll = true)
       {
            if(normYaw)
              wrapAngle( mYaw );

          if(normPitch)
              wrapAngle( mPitch );

          if(normRoll)
              wrapAngle( mRoll );

          return *this;
       }
 
       /**
       @brief Return the relative euler angles required to rotate from the current forward direction to the specified dir vector.
       @details The result euler can then be added to the current euler to immediately face dir.
       The rotation won't flip upside down then roll instead of a 180 degree yaw.
       @param setYaw If false, the angle is set to 0. If true, the angle is calculated.
       @param setPitch If false, the angle is set to 0. If true, the angle is calculated.
       @param shortest If false, the full value of each angle is used. If true, the angles are normalised and the shortest
       rotation is found to face the correct direction. For example, when false a yaw of 1000 degrees and a dir of
       (0,0,-1) will return a -1000 degree yaw. When true, the same yaw and dir would give 80 degrees (1080 degrees faces
       the same way as (0,0,-1).
       */
       inline Euler rotationTo(const Vector3 &dir, bool setYaw = true, bool setPitch = true, bool shortest = true) const
       {
          Euler t1;
          Euler t2;
          t1.direction(dir, setYaw, setPitch);
          t2 = t1 - *this;
          if(shortest && setYaw)
          {
             t2.normalise();
          }
          return t2;
       }
 
       /// Clamp the yaw angle to a range of +/-limit.
       inline Euler &limitYaw(const Radian &limit)
       {
          limitAngle( mYaw, limit );
          return *this;
       }
 
       /// Clamp the pitch angle to a range of +/-limit.
       inline Euler &limitPitch(const Radian &limit)
       {
          limitAngle( mPitch, limit );
          return *this;
       }
 
       /// Clamp the roll angle to a range of +/-limit.
       inline Euler &limitRoll(const Radian &limit)
       {
          limitAngle( mRoll, limit );
          return *this;
       }
 
       /// Stream operator, for printing the euler component angles to a stream
       inline friend std::ostream &operator<<(std::ostream &o, const Euler &e)
       {
          o << "<Y:" << e.mYaw << ", P:" << e.mPitch << ", R:" << e.mRoll << ">";
          return o;
       }
 
       /// Add two euler objects.
       inline Euler operator+(const Euler &rhs) const 
       {
          return Euler(mYaw + rhs.mYaw, mPitch + rhs.mPitch, mRoll + rhs.mRoll); 
       }
 
       /**
       @brief Subtract two euler objects.
       @details This finds the difference as relative angles.
       */
        inline Euler operator-(const Euler &rhs) const 
       { 
          return Euler(mYaw - rhs.mYaw, mPitch - rhs.mPitch, mRoll - rhs.mRoll); 
       }
 
       /// Interpolate the euler angles by rhs.
       inline Euler operator*(Real rhs) const 
       { 
          return Euler(mYaw * rhs, mPitch * rhs, mRoll * rhs); 
       }
 
       /// Interpolate the euler angle by lhs.
       inline friend Euler operator*(Real lhs, const Euler &rhs)
       { 
          return Euler(lhs * rhs.mYaw, lhs * rhs.mPitch, lhs * rhs.mRoll); 
       }
 
       /**
       @brief Multiply two eulers.
       @details This has the same effect as multiplying quaternions.
       @returns The result is a quaternion.
       */
       inline Quaternion operator*( Euler rhs) const
       {
          Euler e1(*this), e2(rhs);
          return e1.toQuaternion()*e2.toQuaternion();
       }

 
       /// Apply the euler rotation to the vector rhs.
       inline Vector3 operator*(const Vector3 &rhs) const
       { 
          return toQuaternion() * rhs; 
       }
        
        
       /// Copy assignment operator (Euler)
       inline Euler& operator=(const Euler& src)
       {
          orientation(src.yaw(), src.pitch(), src.roll());
          return *this;
       }
 
       /// Copy assignment operator (Quaternion)
       inline Euler& operator=(const Quaternion &quaternion)
       {
          fromQuaternion(quaternion);
          return *this;
       }
 
       /// Copy assignment operator (Matrix3)
       inline Euler& operator=(const Matrix3 &matrix)
       {
          fromMatrix3(matrix);
          return *this;
       }

        inline friend bool operator==( const Euler& left, const Euler& right )
        {
            return left.mYaw   == right.mYaw
                && left.mPitch == right.mPitch
                && left.mRoll  == right.mRoll
            ;
        }

        inline friend bool operator!=( const Euler& left, const Euler& right )
        {
            return !( left == right );
        }

        inline friend bool sameOrientation( const Euler& left, const Euler& right )
        {
            // I'm comparing resulting vectors to avoid having to compare angles that are the same but in different values.
            // Only the resulting oriented vectors really have any meaning in the end.
            return left.forward().positionEquals( right.forward() )
                && left.up().positionEquals( right.up() )
                ;
        }
 
    protected:
       Radian mYaw;                           //!< Rotation around the Y axis.
       Radian mPitch;                            //!< Rotation around the X axis.
       Radian mRoll;                           //!< Rotation around the Z axis.
       mutable Quaternion mCachedQuaternion;       //!< Cached quaternion equivalent of this euler object.
       mutable bool mChanged;                  //!< Is the cached quaternion out of date?

        inline void wrapAngle( Radian& angle )
        {
            Real rangle = angle.valueRadians();
         if(rangle < -Math::PI)
         {
            rangle = fmod(rangle, -Math::TWO_PI);
            if(rangle < -Math::PI)
            {
               rangle += Math::TWO_PI;
            }
            angle = rangle;
            mChanged = true;
         }
         else if(rangle > Math::PI)
         {
            rangle = fmod(rangle, Math::TWO_PI);
            if(rangle > Math::PI)
            {
               rangle -= Math::TWO_PI;
            }
            angle = rangle;
            mChanged = true;
         }

        }

        inline void limitAngle( Radian& angle, const Radian& limit )
        {
             if(angle > limit)
          {
             angle = limit;
             mChanged = true;
          }
          else if(angle < -limit)
          {
             angle = -limit;
             mChanged = true;
          }
        }
    };
 
}
 
#endif

Examples

Making and using a euler object:

Euler euler;
sceneNode->setOrientation(euler);   // Euler auto converts to a quaternion if you pass it to any Ogre function which expects a quaternion.


Make a scene node face the camera (both yaw and pitch):

Euler euler;
euler.setDirection(camera->getPosition() - sceneNode->getPosition());   // setDirection normalises the vector
sceneNode->setOrientation(euler);


Make a scene node face the camera using only the yaw (good for character controllers):

Euler euler;
euler.setDirection(camera->getPosition() - sceneNode->getPosition(), true, false);   // the bools control whether the yaw or pitch are changed
sceneNode->setOrientation(euler);


Make a scene node face the camera with a limit of +/-45 degrees on the pitch and unlimited yaw:

Euler euler;
euler.setDirection(camera->getPosition() - sceneNode->getPosition());
euler.limitPitch(Degree(45));
sceneNode->setOrientation(euler);


Perform a corkscrew motion (move vertical as the yaw increases:

sceneNode->setOrientation(euler);
Vector3 pos = sceneNode->getPosition();
pos.y = euler.getYaw();
sceneNode->setPosition(pos);


Chain together several methods (in this case apply OIS mouse input to yaw and pitch the node, plus set it's roll to zero).

const MouseState &ms = mMouse->getMouseState();
// add mouse x to yaw, add mouse y to pitch, and reset roll to 0.
euler.yaw(Radian(ms.X.rel)).pitch(Radian(ms.Y.rel)).setRoll(Degree(0));
sceneNode->setOrientation(euler);


Move forward using the euler direction:

sceneNode->setPosition(sceneNode->getPosition + euler.getForward());


Cancel out excess rotations (return all angles to the +-180 degree range):

euler.normalise();


Rotate the head of the Sinbad mesh to face the camera, with slow head turning and pitch/yaw constraints:
(This is using a modified version of the Sinbad mesh which is 2m tall and faces -Z)

//In the initialisation:
Bone *bone = entity->getSkeleton()->getBone("Head");
bone->setManuallyControlled(true);
Euler headFacing;


// In the update logic:
Vector3 lookat = m_nodes[0]->convertWorldToLocalPosition(m_camera->getPosition()) - Vector3(0, 1.9, 0);
Euler temp = headFacing.getRotationTo(lookat);   // temp is how much you need to rotate to get from the current orientation to the new orientation
temp.limitYaw(Ogre::Radian(deltaT*3.0));   // limit the offset so the head turns at a maximum of 3.0 radians per second
temp.limitPitch(Ogre::Radian(deltaT*3.0));

headFacing = headFacing + temp;   // add the offset to the current orientation
e2.limitYaw(Ogre::Degree(60));   // make sure the head doesn't turn too far. Clamp it to +/- 60 degrees of yaw and pitch.
e2.limitPitch(Ogre::Degree(60));
node->setOrientation(headFacing);

Sinbad's current orientation is taken into account by the convertWorldToLocalPosition call, so you can rotate him in any direction and he will still try to turn his head to the camera (if the limits allow).


Alias: Euler_Angle_Class

<HR>
Creative Commons Copyright -- Some rights reserved.


THE WORK (AS DEFINED BELOW) IS PROVIDED UNDER THE TERMS OF THIS CREATIVE COMMONS PUBLIC LICENSE ("CCPL" OR "LICENSE"). THE WORK IS PROTECTED BY COPYRIGHT AND/OR OTHER APPLICABLE LAW. ANY USE OF THE WORK OTHER THAN AS AUTHORIZED UNDER THIS LICENSE OR COPYRIGHT LAW IS PROHIBITED.

BY EXERCISING ANY RIGHTS TO THE WORK PROVIDED HERE, YOU ACCEPT AND AGREE TO BE BOUND BY THE TERMS OF THIS LICENSE. THE LICENSOR GRANTS YOU THE RIGHTS CONTAINED HERE IN CONSIDERATION OF YOUR ACCEPTANCE OF SUCH TERMS AND CONDITIONS.

1. Definitions

  • "Collective Work" means a work, such as a periodical issue, anthology or encyclopedia, in which the Work in its entirety in unmodified form, along with a number of other contributions, constituting separate and independent works in themselves, are assembled into a collective whole. A work that constitutes a Collective Work will not be considered a Derivative Work (as defined below) for the purposes of this License.
  • "Derivative Work" means a work based upon the Work or upon the Work and other pre-existing works, such as a translation, musical arrangement, dramatization, fictionalization, motion picture version, sound recording, art reproduction, abridgment, condensation, or any other form in which the Work may be recast, transformed, or adapted, except that a work that constitutes a Collective Work will not be considered a Derivative Work for the purpose of this License. For the avoidance of doubt, where the Work is a musical composition or sound recording, the synchronization of the Work in timed-relation with a moving image ("synching") will be considered a Derivative Work for the purpose of this License.
  • "Licensor" means the individual or entity that offers the Work under the terms of this License.
  • "Original Author" means the individual or entity who created the Work.
  • "Work" means the copyrightable work of authorship offered under the terms of this License.
  • "You" means an individual or entity exercising rights under this License who has not previously violated the terms of this License with respect to the Work, or who has received express permission from the Licensor to exercise rights under this License despite a previous violation.
  • "License Elements" means the following high-level license attributes as selected by Licensor and indicated in the title of this License: Attribution, ShareAlike.

2. Fair Use Rights

Nothing in this license is intended to reduce, limit, or restrict any rights arising from fair use, first sale or other limitations on the exclusive rights of the copyright owner under copyright law or other applicable laws.

3. License Grant

Subject to the terms and conditions of this License, Licensor hereby grants You a worldwide, royalty-free, non-exclusive, perpetual (for the duration of the applicable copyright) license to exercise the rights in the Work as stated below:

  • to reproduce the Work, to incorporate the Work into one or more Collective Works, and to reproduce the Work as incorporated in the Collective Works;
  • to create and reproduce Derivative Works;
  • to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission the Work including as incorporated in Collective Works;
  • to distribute copies or phonorecords of, display publicly, perform publicly, and perform publicly by means of a digital audio transmission Derivative Works.
  • For the avoidance of doubt, where the work is a musical composition:
    • Performance Royalties Under Blanket Licenses. Licensor waives the exclusive right to collect, whether individually or via a performance rights society (e.g. ASCAP, BMI, SESAC), royalties for the public performance or public digital performance (e.g. webcast) of the Work.
    • Mechanical Rights and Statutory Royalties. Licensor waives the exclusive right to collect, whether individually or via a music rights society or designated agent (e.g. Harry Fox Agency), royalties for any phonorecord You create from the Work ("cover version") and distribute, subject to the compulsory license created by 17 USC Section 115 of the US Copyright Act (or the equivalent in other jurisdictions).
    • Webcasting Rights and Statutory Royalties. For the avoidance of doubt, where the Work is a sound recording, Licensor waives the exclusive right to collect, whether individually or via a performance-rights society (e.g. SoundExchange), royalties for the public digital performance (e.g. webcast) of the Work, subject to the compulsory license created by 17 USC Section 114 of the US Copyright Act (or the equivalent in other jurisdictions).


The above rights may be exercised in all media and formats whether now known or hereafter devised. The above rights include the right to make such modifications as are technically necessary to exercise the rights in other media and formats. All rights not expressly granted by Licensor are hereby reserved.

4. Restrictions

The license granted in Section 3 above is expressly made subject to and limited by the following restrictions:

  • You may distribute, publicly display, publicly perform, or publicly digitally perform the Work only under the terms of this License, and You must include a copy of, or the Uniform Resource Identifier for, this License with every copy or phonorecord of the Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Work that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder. You may not sublicense the Work. You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Work itself to be made subject to the terms of this License. If You create a Collective Work, upon notice from any Licensor You must, to the extent practicable, remove from the Collective Work any credit as required by clause 4(c), as requested. If You create a Derivative Work, upon notice from any Licensor You must, to the extent practicable, remove from the Derivative Work any credit as required by clause 4(c), as requested.
  • You may distribute, publicly display, publicly perform, or publicly digitally perform a Derivative Work only under the terms of this License, a later version of this License with the same License Elements as this License, or a Creative Commons iCommons license that contains the same License Elements as this License (e.g. Attribution-ShareAlike 2.5 Japan). You must include a copy of, or the Uniform Resource Identifier for, this License or other license specified in the previous sentence with every copy or phonorecord of each Derivative Work You distribute, publicly display, publicly perform, or publicly digitally perform. You may not offer or impose any terms on the Derivative Works that alter or restrict the terms of this License or the recipients' exercise of the rights granted hereunder, and You must keep intact all notices that refer to this License and to the disclaimer of warranties. You may not distribute, publicly display, publicly perform, or publicly digitally perform the Derivative Work with any technological measures that control access or use of the Work in a manner inconsistent with the terms of this License Agreement. The above applies to the Derivative Work as incorporated in a Collective Work, but this does not require the Collective Work apart from the Derivative Work itself to be made subject to the terms of this License.
  • If you distribute, publicly display, publicly perform, or publicly digitally perform the Work or any Derivative Works or Collective Works, You must keep intact all copyright notices for the Work and provide, reasonable to the medium or means You are utilizing: (i) the name of the Original Author (or pseudonym, if applicable) if supplied, and/or (ii) if the Original Author and/or Licensor designate another party or parties (e.g. a sponsor institute, publishing entity, journal) for attribution in Licensor's copyright notice, terms of service or by other reasonable means, the name of such party or parties; the title of the Work if supplied; to the extent reasonably practicable, the Uniform Resource Identifier, if any, that Licensor specifies to be associated with the Work, unless such URI does not refer to the copyright notice or licensing information for the Work; and in the case of a Derivative Work, a credit identifying the use of the Work in the Derivative Work (e.g., "French translation of the Work by Original Author," or "Screenplay based on original Work by Original Author"). Such credit may be implemented in any reasonable manner; provided, however, that in the case of a Derivative Work or Collective Work, at a minimum such credit will appear where any other comparable authorship credit appears and in a manner at least as prominent as such other comparable authorship credit.

5. Representations, Warranties and Disclaimer

UNLESS OTHERWISE AGREED TO BY THE PARTIES IN WRITING, LICENSOR OFFERS THE WORK AS-IS AND MAKES NO REPRESENTATIONS OR WARRANTIES OF ANY KIND CONCERNING THE MATERIALS, EXPRESS, IMPLIED, STATUTORY OR OTHERWISE, INCLUDING, WITHOUT LIMITATION, WARRANTIES OF TITLE, MERCHANTIBILITY, FITNESS FOR A PARTICULAR PURPOSE, NONINFRINGEMENT, OR THE ABSENCE OF LATENT OR OTHER DEFECTS, ACCURACY, OR THE PRESENCE OF ABSENCE OF ERRORS, WHETHER OR NOT DISCOVERABLE. SOME JURISDICTIONS DO NOT ALLOW THE EXCLUSION OF IMPLIED WARRANTIES, SO SUCH EXCLUSION MAY NOT APPLY TO YOU.

6. Limitation on Liability.

EXCEPT TO THE EXTENT REQUIRED BY APPLICABLE LAW, IN NO EVENT WILL LICENSOR BE LIABLE TO YOU ON ANY LEGAL THEORY FOR ANY SPECIAL, INCIDENTAL, CONSEQUENTIAL, PUNITIVE OR EXEMPLARY DAMAGES ARISING OUT OF THIS LICENSE OR THE USE OF THE WORK, EVEN IF LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.

7. Termination

  • This License and the rights granted hereunder will terminate automatically upon any breach by You of the terms of this License. Individuals or entities who have received Derivative Works or Collective Works from You under this License, however, will not have their licenses terminated provided such individuals or entities remain in full compliance with those licenses. Sections 1, 2, 5, 6, 7, and 8 will survive any termination of this License.
  • Subject to the above terms and conditions, the license granted here is perpetual (for the duration of the applicable copyright in the Work). Notwithstanding the above, Licensor reserves the right to release the Work under different license terms or to stop distributing the Work at any time; provided, however that any such election will not serve to withdraw this License (or any other license that has been, or is required to be, granted under the terms of this License), and this License will continue in full force and effect unless terminated as stated above.

8. Miscellaneous

  • Each time You distribute or publicly digitally perform the Work or a Collective Work, the Licensor offers to the recipient a license to the Work on the same terms and conditions as the license granted to You under this License.
  • Each time You distribute or publicly digitally perform a Derivative Work, Licensor offers to the recipient a license to the original Work on the same terms and conditions as the license granted to You under this License.
  • If any provision of this License is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this License, and without further action by the parties to this agreement, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
  • No term or provision of this License shall be deemed waived and no breach consented to unless such waiver or consent shall be in writing and signed by the party to be charged with such waiver or consent.
  • This License constitutes the entire agreement between the parties with respect to the Work licensed here. There are no understandings, agreements or representations with respect to the Work not specified here. Licensor shall not be bound by any additional provisions that may appear in any communication from You. This License may not be modified without the mutual written agreement of the Licensor and You.