/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield 
 *
 * This library is open source and may be redistributed and/or modified under  
 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or 
 * (at your option) any later version.  The full license is in LICENSE file
 * included with this distribution, and on the openscenegraph.org website.
 * 
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 * OpenSceneGraph Public License for more details.
*/

#ifndef OSGUTIL_CONVERTVEC
#define OSGUTIL_CONVERTVEC 1

namespace osgUtil {

template <typename InType, typename OutType, 
          unsigned int InSize = InType::num_components, 
          unsigned int OutSize = OutType::num_components>
struct ConvertVec
{
    static void convert(InType & in, OutType & out)
    {}
};



template <typename InType, typename OutType>
struct ConvertVec<InType, OutType, 2, 2>
{
    static void convert(InType & in, OutType & out)
    { 
        out.set(static_cast<typename OutType::value_type>(in.x()), 
                static_cast<typename OutType::value_type>(in.y())); 
    }
};

template <typename InType, typename OutType>
struct ConvertVec<InType, OutType, 2, 3>
{
    static void convert(InType & in, OutType & out)
    { 
        out.set(static_cast<typename OutType::value_type>(in.x()), 
                static_cast<typename OutType::value_type>(in.y()), 
                static_cast<typename OutType::value_type>(0.0)); 
    }
};

template <typename InType, typename OutType>
struct ConvertVec<InType, OutType, 2, 4>
{
    static void convert(InType & in, OutType & out)
    { 
        out.set(static_cast<typename OutType::value_type>(in.x()), 
                static_cast<typename OutType::value_type>(in.y()), 
                static_cast<typename OutType::value_type>(0.0), 
                static_cast<typename OutType::value_type>(1.0)); 
    }
};





template <typename InType, typename OutType>
struct ConvertVec<InType, OutType, 3, 2>
{
    static void convert(InType & in, OutType & out)
    { 
        out.set(static_cast<typename OutType::value_type>(in.x()), 
                static_cast<typename OutType::value_type>(in.y())); 
    }
};

template <typename InType, typename OutType>
struct ConvertVec<InType, OutType, 3, 3>
{
    static void convert(InType & in, OutType & out)
    { 
        out.set(static_cast<typename OutType::value_type>(in.x()), 
                static_cast<typename OutType::value_type>(in.y()), 
                static_cast<typename OutType::value_type>(in.z())); 
    }
};

template <typename InType, typename OutType>
struct ConvertVec<InType, OutType, 3, 4>
{
    static void convert(InType & in, OutType & out)
    { 
        out.set(static_cast<typename OutType::value_type>(in.x()), 
                static_cast<typename OutType::value_type>(in.y()), 
                static_cast<typename OutType::value_type>(in.z()), 
                static_cast<typename OutType::value_type>(1.0)); 
    }
};





template <typename InType, typename OutType>
struct ConvertVec<InType, OutType, 4, 2>
{
    static void convert(InType & in, OutType & out)
    { 
        out.set(static_cast<typename OutType::value_type>(in.x()/in.w()), 
                static_cast<typename OutType::value_type>(in.y()/in.w())); 
    }
};

template <typename InType, typename OutType>
struct ConvertVec<InType, OutType, 4, 3>
{
    static void convert(InType & in, OutType & out)
    { 
        out.set(static_cast<typename OutType::value_type>(in.x()/in.w()), 
                static_cast<typename OutType::value_type>(in.y()/in.w()), 
                static_cast<typename OutType::value_type>(in.z()/in.w())); 
    }
};

template <typename InType, typename OutType>
struct ConvertVec<InType, OutType, 4, 4>
{
    static void convert(InType & in, OutType & out)
    { 
        out.set(static_cast<typename OutType::value_type>(in.x()), 
                static_cast<typename OutType::value_type>(in.y()), 
                static_cast<typename OutType::value_type>(in.z()), 
                static_cast<typename OutType::value_type>(in.w())); 
    }
};

} // end of osg namespace

#endif // ** OSG_CONVERTVEC ** //