nuclear@0: /* nuclear@0: Open Asset Import Library (assimp) nuclear@0: ---------------------------------------------------------------------- nuclear@0: nuclear@0: Copyright (c) 2006-2012, assimp team nuclear@0: All rights reserved. nuclear@0: nuclear@0: Redistribution and use of this software in source and binary forms, nuclear@0: with or without modification, are permitted provided that the nuclear@0: following conditions are met: nuclear@0: nuclear@0: * Redistributions of source code must retain the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer. nuclear@0: nuclear@0: * Redistributions in binary form must reproduce the above nuclear@0: copyright notice, this list of conditions and the nuclear@0: following disclaimer in the documentation and/or other nuclear@0: materials provided with the distribution. nuclear@0: nuclear@0: * Neither the name of the assimp team, nor the names of its nuclear@0: contributors may be used to endorse or promote products nuclear@0: derived from this software without specific prior nuclear@0: written permission of the assimp team. nuclear@0: nuclear@0: THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS nuclear@0: "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT nuclear@0: LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR nuclear@0: A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT nuclear@0: OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, nuclear@0: SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT nuclear@0: LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, nuclear@0: DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY nuclear@0: THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT nuclear@0: (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE nuclear@0: OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. nuclear@0: nuclear@0: ---------------------------------------------------------------------- nuclear@0: */ nuclear@0: nuclear@0: /** @file LWOAnimation.h nuclear@0: * @brief LWOAnimationResolver utility class nuclear@0: * nuclear@0: * This is for all lightwave-related file format, not only LWO. nuclear@0: * LWS isthe main purpose. nuclear@0: */ nuclear@0: #ifndef AI_LWO_ANIMATION_INCLUDED nuclear@0: #define AI_LWO_ANIMATION_INCLUDED nuclear@0: nuclear@0: namespace Assimp { nuclear@0: namespace LWO { nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** \brief List of recognized LWO envelopes nuclear@0: */ nuclear@0: enum EnvelopeType nuclear@0: { nuclear@0: EnvelopeType_Position_X = 0x1, nuclear@0: EnvelopeType_Position_Y = 0x2, nuclear@0: EnvelopeType_Position_Z = 0x3, nuclear@0: nuclear@0: EnvelopeType_Rotation_Heading = 0x4, nuclear@0: EnvelopeType_Rotation_Pitch = 0x5, nuclear@0: EnvelopeType_Rotation_Bank = 0x6, nuclear@0: nuclear@0: EnvelopeType_Scaling_X = 0x7, nuclear@0: EnvelopeType_Scaling_Y = 0x8, nuclear@0: EnvelopeType_Scaling_Z = 0x9, nuclear@0: nuclear@0: // -- currently not yet handled nuclear@0: EnvelopeType_Color_R = 0xa, nuclear@0: EnvelopeType_Color_G = 0xb, nuclear@0: EnvelopeType_Color_B = 0xc, nuclear@0: nuclear@0: EnvelopeType_Falloff_X = 0xd, nuclear@0: EnvelopeType_Falloff_Y = 0xe, nuclear@0: EnvelopeType_Falloff_Z = 0xf, nuclear@0: nuclear@0: EnvelopeType_Unknown nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** \brief List of recognized LWO interpolation modes nuclear@0: */ nuclear@0: enum InterpolationType nuclear@0: { nuclear@0: IT_STEP, IT_LINE, IT_TCB, IT_HERM, IT_BEZI, IT_BEZ2 nuclear@0: }; nuclear@0: nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** \brief List of recognized LWO pre or post range behaviours nuclear@0: */ nuclear@0: enum PrePostBehaviour nuclear@0: { nuclear@0: PrePostBehaviour_Reset = 0x0, nuclear@0: PrePostBehaviour_Constant = 0x1, nuclear@0: PrePostBehaviour_Repeat = 0x2, nuclear@0: PrePostBehaviour_Oscillate = 0x3, nuclear@0: PrePostBehaviour_OffsetRepeat = 0x4, nuclear@0: PrePostBehaviour_Linear = 0x5 nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** \brief Data structure for a LWO animation keyframe nuclear@0: */ nuclear@0: struct Key nuclear@0: { nuclear@0: Key() nuclear@0: : inter (IT_LINE) nuclear@0: {} nuclear@0: nuclear@0: //! Current time nuclear@0: double time; nuclear@0: nuclear@0: //! Current value nuclear@0: float value; nuclear@0: nuclear@0: //! How to interpolate this key with previous key? nuclear@0: InterpolationType inter; nuclear@0: nuclear@0: //! Interpolation parameters nuclear@0: float params[5]; nuclear@0: nuclear@0: nuclear@0: // for std::find() nuclear@0: operator double () { nuclear@0: return time; nuclear@0: } nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** \brief Data structure for a LWO animation envelope nuclear@0: */ nuclear@0: struct Envelope nuclear@0: { nuclear@0: Envelope() nuclear@0: : type (EnvelopeType_Unknown) nuclear@0: , pre (PrePostBehaviour_Constant) nuclear@0: , post (PrePostBehaviour_Constant) nuclear@0: nuclear@0: , old_first (0) nuclear@0: , old_last (0) nuclear@0: {} nuclear@0: nuclear@0: //! Index of this envelope nuclear@0: unsigned int index; nuclear@0: nuclear@0: //! Type of envelope nuclear@0: EnvelopeType type; nuclear@0: nuclear@0: //! Pre and post-behaviour nuclear@0: PrePostBehaviour pre,post; nuclear@0: nuclear@0: //! Keyframes for this envelope nuclear@0: std::vector keys; nuclear@0: nuclear@0: nuclear@0: // temporary data for AnimResolver nuclear@0: size_t old_first,old_last; nuclear@0: }; nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: //! @def AI_LWO_ANIM_FLAG_SAMPLE_ANIMS nuclear@0: //! Flag for AnimResolver, subsamples the input data with the rate specified nuclear@0: //! by AnimResolver::SetSampleRate(). nuclear@0: #define AI_LWO_ANIM_FLAG_SAMPLE_ANIMS 0x1 nuclear@0: nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: //! @def AI_LWO_ANIM_FLAG_START_AT_ZERO nuclear@0: //! Flag for AnimResolver, ensures that the animations starts at zero. nuclear@0: #define AI_LWO_ANIM_FLAG_START_AT_ZERO 0x2 nuclear@0: nuclear@0: // --------------------------------------------------------------------------- nuclear@0: /** @brief Utility class to build Assimp animations from LWO envelopes. nuclear@0: * nuclear@0: * Used for both LWO and LWS (MOT also). nuclear@0: */ nuclear@0: class AnimResolver nuclear@0: { nuclear@0: public: nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Construct an AnimResolver from a given list of envelopes nuclear@0: * @param envelopes Input envelopes. May be empty. nuclear@0: * @param Output tick rate, per second nuclear@0: * @note The input envelopes are possibly modified. nuclear@0: */ nuclear@0: AnimResolver(std::list& envelopes, nuclear@0: double tick); nuclear@0: nuclear@0: public: nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Extract the bind-pose transformation matrix. nuclear@0: * @param out Receives bind-pose transformation matrix nuclear@0: */ nuclear@0: void ExtractBindPose(aiMatrix4x4& out); nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Extract a node animation channel nuclear@0: * @param out Receives a pointer to a newly allocated node anim. nuclear@0: * If there's just one keyframe defined, *out is set to NULL and nuclear@0: * no animation channel is computed. nuclear@0: * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. nuclear@0: */ nuclear@0: void ExtractAnimChannel(aiNodeAnim** out, unsigned int flags = 0); nuclear@0: nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Set the sampling rate for ExtractAnimChannel(). nuclear@0: * nuclear@0: * Non-linear interpolations are subsampled with this rate (keys nuclear@0: * per second). Closer sampling positions, if existent, are kept. nuclear@0: * The sampling rate defaults to 0, if this value is not changed and nuclear@0: * AI_LWO_ANIM_FLAG_SAMPLE_ANIMS is specified for ExtractAnimChannel(), nuclear@0: * the class finds a suitable sample rate by itself. nuclear@0: */ nuclear@0: void SetSampleRate(double sr) { nuclear@0: sample_rate = sr; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Getter for SetSampleRate() nuclear@0: */ nuclear@0: double GetSampleRate() const { nuclear@0: return sample_rate; nuclear@0: } nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Set the animation time range nuclear@0: * nuclear@0: * @param first Time where the animation starts, in ticks nuclear@0: * @param last Time where the animation ends, in ticks nuclear@0: */ nuclear@0: void SetAnimationRange(double _first, double _last) { nuclear@0: first = _first; nuclear@0: last = _last; nuclear@0: nuclear@0: ClearAnimRangeSetup(); nuclear@0: UpdateAnimRangeSetup(); nuclear@0: } nuclear@0: nuclear@0: protected: nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Build linearly subsampled keys from 3 single envelopes nuclear@0: * @param out Receives output keys nuclear@0: * @param envl_x X-component envelope nuclear@0: * @param envl_y Y-component envelope nuclear@0: * @param envl_z Z-component envelope nuclear@0: * @param flags Any combination of the AI_LWO_ANIM_FLAG_XXX flags. nuclear@0: * @note Up to two input envelopes may be NULL nuclear@0: */ nuclear@0: void GetKeys(std::vector& out, nuclear@0: LWO::Envelope* envl_x, nuclear@0: LWO::Envelope* envl_y, nuclear@0: LWO::Envelope* envl_z, nuclear@0: unsigned int flags); nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Resolve a single animation key by applying the right nuclear@0: * interpolation to it. nuclear@0: * @param cur Current key nuclear@0: * @param envl Envelope working on nuclear@0: * @param time time to be interpolated nuclear@0: * @param fill Receives the interpolated output value. nuclear@0: */ nuclear@0: void DoInterpolation(std::vector::const_iterator cur, nuclear@0: LWO::Envelope* envl,double time, float& fill); nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Almost the same, except we won't handle pre/post nuclear@0: * conditions here. nuclear@0: * @see DoInterpolation nuclear@0: */ nuclear@0: void DoInterpolation2(std::vector::const_iterator beg, nuclear@0: std::vector::const_iterator end,double time, float& fill); nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Interpolate 2 tracks if one is given nuclear@0: * nuclear@0: * @param out Receives extra output keys nuclear@0: * @param key_out Primary output key nuclear@0: * @param time Time to interpolate for nuclear@0: */ nuclear@0: void InterpolateTrack(std::vector& out, nuclear@0: aiVectorKey& key_out,double time); nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Subsample an animation track by a given sampling rate nuclear@0: * nuclear@0: * @param out Receives output keys. Last key at input defines the nuclear@0: * time where subsampling starts. nuclear@0: * @param time Time to end subsampling at nuclear@0: * @param sample_delta Time delta between two samples nuclear@0: */ nuclear@0: void SubsampleAnimTrack(std::vector& out, nuclear@0: double time,double sample_delta); nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Delete all keys which we inserted to match anim setup nuclear@0: */ nuclear@0: void ClearAnimRangeSetup(); nuclear@0: nuclear@0: // ------------------------------------------------------------------ nuclear@0: /** @brief Insert extra keys to match LWO's pre and post behaviours nuclear@0: * in a given time range [first...last] nuclear@0: */ nuclear@0: void UpdateAnimRangeSetup(); nuclear@0: nuclear@0: private: nuclear@0: std::list& envelopes; nuclear@0: double sample_rate; nuclear@0: nuclear@0: LWO::Envelope* trans_x, *trans_y, *trans_z; nuclear@0: LWO::Envelope* rotat_x, *rotat_y, *rotat_z; nuclear@0: LWO::Envelope* scale_x, *scale_y, *scale_z; nuclear@0: nuclear@0: double first, last; nuclear@0: bool need_to_setup; nuclear@0: nuclear@0: // temporary storage nuclear@0: LWO::Envelope* envl_x, * envl_y, * envl_z; nuclear@0: std::vector::const_iterator cur_x,cur_y,cur_z; nuclear@0: bool end_x, end_y, end_z; nuclear@0: nuclear@0: unsigned int flags; nuclear@0: double sample_delta; nuclear@0: }; nuclear@0: nuclear@0: } // end namespace LWO nuclear@0: } // end namespace Assimp nuclear@0: nuclear@0: #endif // !! AI_LWO_ANIMATION_INCLUDED