Summer of Code 2007: High level animation control plugin (including IK support)

Student: Jaroslaw Kochanowicz (jarek108)

Mentor: Paul Cheyrou-lagreze (tuan kuranes)

Status: Failed at Midterm

Introduction (taken from proposal)


Based on ogre3d forum discussions and project ideas:

http://www.ogre3d.org/phpBB2/viewtopic.php?p=211812#211812
http://www.ogre3d.org/wiki/index.php?title=HelpRequested&#Animation_Enhancements

I’d like to build a high level animation control plug-in for ogre. It would enable user to blend together multiple animations in a way similar to proposed here by ogre mentor tuan kuranes:

http://www.ogre3d.org/phpBB2/viewtopic.php?t=28812&postdays=0&postorder=asc&start=50
and to apply procedural animation controllers(eg apply IK and physics) blending them all together.

Features:


-supply users with interfaces allowing them to define on a high (by scripts?) authored animations to be blended and the way that should be blended(like in example in post above)
- provide abstract interface for animation controllers influencing the actor to build later user defined controllers(IK algorithms etc)
- allow user to easily attach external physics engine that will influence the actor.
-implement of CCD IK algorithm using the abstract interface
-if time allows work monitor mentors/users for any feature that will be expected and possible to implement

Fast remarks on interface with current ogre code.

  1. Project will replace and expand current implementation of animation blender.
  2. The bottom level of the system will directly use ogre classes: Bone, Skeleton, NodeAnimationTrack etc to allow programmer define how animations should be blended together.
  3. Higher levels will allow to have easy controll over complex animation proceses with few lines of code.


this point will be expanded later.

Some of the artifices/www pages that are a source of inspiration for the project. Good introduction.

  1. mechwarior animation blending system: http://www.gamasutra.com/features/20030704/edsall_pfv.htm. this is a main source of inspiration for my system. describes system of animation blending used in commercial game addresses many pitfalls and gives solutions proven to be useful.
  2. CCD algorithm description http://number-none.com/product/IK%20with%20Quaternion%20Joint%20Limits/index.html
  3. Ogre animation blender: http://www.ogre3d.org/wiki/index.php/AnimationBlender. Old simple system that will be replaced and expanded by the lowest pars of my system.
  4. . proposal + basic interface from tuan kuranes: http://www.ogre3d.org/phpBB2/viewtopic.php?t=28812&postdays=0&postorder=asc&start=50. General idea of what high level user interface could look like.
  5. articles on IK and procedural controllers for human-like characters:

Some articles that provide ideas of what kind of expansions are possible to the system.
All kinds of procedural vs data driven(artist created) animation interactions are described.

Introduction. Use case.


Animation blender.
Ok. how could you use a system like that? i`ll try to make it possible to do that in many ways, according to your needs. there are increasing levels on witch you can use the system. so let`s start from the buttom.

First, imagine you have shooting and walking animations. want to combine them. normally in ogre you can do that, but the effect will not be nice. because in shooting your legs are still, after you blend the animations the poor guy will start to walk slow, like an old men. also the hands may not behave so nice - swinging from walking can be too big...

Second. you have running. you have walking. why not jog? with any given speed between walk and run? sounds easy: just set weights like: 50/50 for something exactly in between, or 10/90 for almost full run. but there is a problem - the run/walk periods are very different. this will cause random behaviour like changing speed, stopping, even walking back.

To deal with the first problem, the system will allow you to define for example that lower body(or any set of joints) will not be taken into consideration in shooting. in fact it can take a neutral position and propose the joints that are not used in the animation as the ones to be weighted with zero.

To solve the other problem we will go step further. we will use a concept of an animation tree.

JOG(speed)
   WALK
   RUN
this means that jog is a combination of RUN and WALK animations. speed variable is controlling the process. the animations will be synchronised. if the period of walking is longer, they will be scaled according to the weights of the animations. now you can just tell the system to set the variable to the desired value and... it is done. you can even tell it to go over time from walking to running in let`s say 1.5 second if you want realistic acceleration.


This is some basic "pictorial" explanation. Below Later you will find more technical info on how exacly the system will work and what will it be able to do.

Some other use cases:

Low level.

...just altering that...

Middle level.


Let us say that we want to have a ninja running, sneaking and fighing a bit.

This is to present how simple variables can be used to alter the behaviour of the character.
so far i use: registerVar, varSetTo, varGoTo methods. i agree they are not nice. will change them as soon as someone proposes in ogre forum: how they want to perform this control alternatively.

We assume that "a" was provided with animations used as a base for blending(running etc).
n is game data representing ninja. holds some variables describing his state.

a.registerVar("speed",n.speed); //we can watch/change external variables to control animation behaviour
   a.registerVar("IK Parameter 1", x) // x will represent variable used in some IK animations
   
   n.speed = 0;                //we can now control animation directly through n.speed: ninja starts standing
                               //this is for example purpose. we could also use a.varSetTo("speed", 0); with the same result.
                               
                               
   a.varSetTo("crouch", 2);    //another way of setting variable, we start in full stand
   ...// lazy ninja just stands around...
   
   a.varGoTo("speed", 1);     // we can also use "a" to control n.speed. Here "a" takes care of smooth transition from stand to walk
                              //and than plays walking animation in loop.  when varGoTo used, change from current value to goal occurs
                              //every frame with a default (if user will not change it) 
                                                          
   ...//"Stand To Walk" animation is played, than we continue with looped "Walking"
   ...//ofcourse we should also make sure animation direction and velocity of object are correct, we only focus on animations
   
   
   a.varGoTo("speed", 2);     //our ninja accelerates going from walk to run animation smoothly then mainteining runing
   .....//our ninja sees an enemy who is turned back so...
   
   a.varGoTo("crouch", 1);    //ninja starts sneaking (still at full running speed!);
   .....//we are getting close...
   
   a.varGoTo("speed", 1)    //ninja goes really sneaking (crouch + walk)
   .....//target in reach...
   
   x = target.getPosition();           //we set some variable responsible for ik procedure
   a.varSetTo("attack phase", 1);      // and we tell "a" to start the attack animation
                                       //(goes to 0 with default speed, representing animation progress)
                                       
   ......        //ninja preforms attack sequance WHILE walking and WHILE sneaking, target is silenced
   
   a.varGoTo("croach", 2);    // no need to hide any more
   a.varGoTo("speed", 2);    // ninja runs once again
   .....
   
   x = weapon.getPosition();
   a.varSetTo("grab", 1); //ninja sees nicer sword, and grabs it in full run
   ....
   
   a.varSetTo("small hit", 1);    // but... takes a hit from a small gun while grabing and runnung. ouch.
   a.varSetTo("damaged", 1);       // from now on his motion is going to be a bit less cat-like
   .... //ninja runs for the guy with the gun
   
   
   a.varSetTo("dodge", 1);       //a bit of matrix-like bullet avoiding
   ...
   
   x = target.getPosition();
   a.varSetTo("attack", 1);      // attack the guy not waiting for the dodge to finish...
   ...
   
   a.varSetTo("big hit", 1);     // but unfortunately there was another guy with a shootgun that ninja just did not notice
   ...
   
   a.varSetTo("attack", 0);  //ninja does not feel like continuing the attack
   a.varGoTo("speed", 0);    //also the missing head is to much to run, he stops smoothly
   a.varGoTo("croach", 0);   //and takes his time to rest
   ...
   
   a.varGoTo("die", 1);    //....forever

Again. This is just to illustrate the type of operations one can expect from this level of the system. I`m preety sure specific
classes/methods, default variable names etc will change.

High level.


Will come... hopefully after some nice interaction/ideas from community.

System basic structure(more technical stuff...)

Core blending system itself:

remarks for entire system

- low level flat list animation blending(elimination of low weighted animations)
- middle level graph structure(heart of the system): leafs = animations, nodes = blend controllers or procedural operators
- high level:  
                    *play("x") using lower levels for all the dirt work,
                    *logical animation states, possible transitions for character
            - some animation assumptions:
                    *some animations will have to be synchronized(egz. "walk" and "run" both start with the same leg in front and have one
                    full walk cycle)
                    *if we decide to process character`s velocity in this system we assume that animations(and procedural controllers)
                    return velocities for further calculations

some info on low level "flat" blender


-extension of ogre animation blender
        -cheap animation blending(at least i hope so:)), because of skeleton level approach
        -flat list for blending created from middle level graph
        -flat list only refreshed when weights change(and only in a sub tree where the change appeared)
        -when procedural controllers are used as internal nodes, for each a flat blend has to be locally applied to children animations

basic features and structure description of middle level graph


GENERAL REMARKS
- blending multiple skeletal animations
            - allowing to blend IK and other user defined procedural skeletal animations
            - easy, intuitive high level access to blending parameters, including:
                    *automatic blending transition between given animations with defined time/runDegree, both cyclic and single shoot animations
                    *external variable monitoring as blending control (egz. runDegree controls stand/walk/run blends)
                    *support for using artist animations as transitions(egz. "walk to run", "crouch to lay" will not be effects of a blend)
            - underneath: hierarchical animation tree holding animation priorities, blending weights and logical structure

DETAILS ON TREE STRUCTURE AND BLENDING CONTROLLERS(INNER TREE NODES)


- named blending controllers(inner tree nodes)
                        *allow high level controlled automatic weight transitions(egz go smooth from "run" after user calls "walk" animation)
                        *internal nodes map input parameters into children animation weights
                        (hold animation weight distribution in control parameter space)
                        *different blending weight control types:
                                -direct input parameters(observe external variables to adjust blend weight)
                                -indirect, binary like - controller gets order to go to bound state using defined transition speed to produce
                                 smooth result, use tree managed variable to keep transition progress
                                -indirect, with special animation for transition(when starting to walk from stand, walk+stand blend could produce awkward solution)
                                -inner nodes do not care about the type of control: tree menages variables for binary controllers allow uniform interface
                        *faze synchronisation of blended animations
                                        -faze synchronization is required for blending animations of the same nature(egz. walk + run) to achive appropriate "between" animations
                                        (we cannot blend them when one is startin and the other is in the middle of cycle)
                                -synchronized animations monitor external variable that sets their faze instead of perform time based updates
            -tree variable management
                      *used for controlling automatic transitions between requred states and
                      *used for synchronizing animation fazes(instead of using local animation faze control)
                      *other purposes?
                      *monitored by the control nodes like external variables
                      *altered by user requests and time update in a way dependent on the variable type
                      *will require some logic to determine behaviours egz. cyclic for walkFaze var, single transition for walk to run control
                      *decide interface for higher levels, i think tree should make no logical decisions about how to react on play("x") when
                      currently running, how when standing), this should be left to higher level layers
                      *do we send notification about finalisation of transition to higher levels so they know that some state is reached?
            - procedural(egz. IK) animation controllers as internal nodes
                        *if they are not leafs they require separate flat list blend, to produce input start pose for procedural altering
                        *if char. velocity is determined in the tree, procedural controllers have to return it also
                        *will be implemented:
                                -CCD (see below(in the future:)) for details)
                                -abstract interfaces for other, user defined controllers
            - configurable default settings on appropriate levels all over the system, example:
                        *animation(=managed variable) transition runDegree
                        *play type for animation - cyclic or single
                        *default tree for humanoid(others can be created, used, reused and modified for special needs),

EXAMPLE ANIMATION TREE


LEGEND:
            y(x)        - animation y monitors x variable as a parameter
            xTRANS     - control node plays Transition animations(named T01, T10) to go between extremes, instead of blending border animation
            0/1 x         - indicates that x animation is a border animation either for 0 or 1 parameter value for the father node
            T01/T10 x - x is an artist created Transition animation used by the father node to go between border animations
            xIK        -  x animation uses IK to modify skeleton according to external variables(steepens of terrain or direction of walk),
                                could be simulated by blending extreme states: Walk(X,Y) = X*WalkUp + Y*WalkRight + Walk*(2-X-Y) but more work for
                                artist + not that good result?
            xPart        - partial animation only modifies certain bones.
                                        
            Remark:     sons of a node represent animations whitch weights are controled by father. leafs are artist created animations.
                        0 and 1 in the picture just mean "border animation" not actual value of a parameter for witch this border is achieved
                            in a particular node.            
             
                            
 FullMotion
    Hit(CroachDegree)
         LieHit(hitSize)
                        SmallLieHit
                        BigLieHit
         StandHit(hitSize)
                        SmallStandHit
                        BigStandHit
                            
    DamagedMotion(damageDegree)
         Damage(croachDegree)
                 WalkDamaged(walkFaze)            <-------holds damage motion features sheared for all walk like animations                                                                        
                 CrawlDamaged(walkFaze)        <-----------------"""""----------------- but lie down
                 
         Motion(croachlDegree)
              0 LieMotion(runDegree)        
                      Crawl/Roll(direction, steepnes, walkFaze)
                      Lie    (steepnes)                
                              
              T01 LieToCroach
              T10 CroachToLie
                                  
              1 StandMotion(startWalkDegree)
                          0     StandCtrl(croachDegree)
                                       0 Stand
                                       1 Croach                        
                          T01 StandToWalk(croachDegree)
                                       0 StandToWalkIK(steapness, direction)
                                       1 CroachToSneakIK(steapness, direction)
                          T10 WalkToStand(croachDegree)
                                       WalkToStandIK(steapness, direction)
                                       SneakToCroachIK(steapness, direction)
                          1     WalkCtrl(croachDegree)
                                       0 Jog(runDegree)        
                                               WalkIK(steapness, direction, walkFaze)    
                                               RunIK(steapness, direction, walkFaze)
                                       1 Sneak(runDegree)     
                                               SneakIK(steapness, direction, walkFaze)
                                               SneakRunIK(steapness, direction, walkFaze)(perhaps this is not needed, just RunIK for running efects?)
                                     
                                                            
    external/tree menaged variables:
            croachDegree  - single transition. controlls transition between croach and stand, walk/run and sneek. When it is 
                           menaged it represents a system where character either stands or croaches and tree just provides 
                           transition, if it is an external variable all kinds of behaviours are posible(all staten between sneak 
                           and walk, etc.) programmer would be responsible for variable control, tree would provide blending 
                           acordingly. This example goes also for other variables like runDegree (walk/run just transition or 
                           all states between possible?) etc. Example scale: 0 - lie down, 0.5 - croach, 1 stand
            runDegree                - single transition. stand/walkrun controll.
            startWalkDegree - single transition. starting and stoping walking.
            walkFaze            - cyclic. synchronization of walk like animations
            steapness            - external. angle of terrian
            direction            - external. front, back, left, right?.
            damageDegree    - external. 0 - not wounded, 1 - maximal damage
            hitSize                -  static, zero after hit animation finished. 0 - no hit right now, 0.5 - small hit, 1 big hit

When smome simple interpretations(changing parameter values) for animation calls would be provided,
adressing that tree by calls like: play("run") (makes runDegree goes to 1 with default speed), play("croach"/"lie")
(croachDegree goes to 0.5/1.0) or by changing monitored variables, user could quite easily controll the animation.
Still because much care has to be taken when creating tree to avoid strange situations like go from lie to jump, and for
ease of definition of how play("x") influences tree depending on current animation state, we will provide another abstraction
layer for state and transition based definition of character`s legal animation blendings.

This could also provide easy, powerful tool to modify not only the parameters but also tree structure without going into rather
complicated manual tree constructing.

high level controll system

This will be some kind of graph representing legal character states, transitions between them and actions modifying blending tree
when a state in entered or transition is made.

CCD and other algorithms.

later...

AnimationPhisics - IK interaction

later...

IV. Interseting community propositions, questions etc...


<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.