/*-
 * Copyright (c) 1999,2000 Qube Software, Ltd.
 * All rights reserved.
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 * 
 * 1. Redistributions of the source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 
 * 2. Any redistribution solely in binary form must conspicuously
 *    reproduce the following disclaimer in documentation provided with the
 *    binary redistribution.
 * 
 * THIS SOFTWARE IS PROVIDED ``AS IS'', WITHOUT ANY WARRANTIES, EXPRESS
 * OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, WARRANTIES OF
 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  LICENSOR SHALL
 * NOT BE LIABLE FOR ANY LOSS OR DAMAGES RESULTING FROM THE USE OF THIS
 * SOFTWARE, EITHER ALONE OR IN COMBINATION WITH ANY OTHER SOFTWARE.
 * 
 * 	$Id: matrix3.h,v 1.13 2000/04/20 16:21:57 n_hibma Exp $
 */

#ifndef __matrix3_h__
#define __matrix3_h__

MATHS_BEGIN

struct EXPORT_QMATHS Matrix3f
{
    Matrix3f() {}
    Matrix3f(const Quat4f&);
    Matrix3f(const Matrix4f&);
    
private:
    struct Vec3x3
    {
	float		varray_[3][3];
	inline operator Vec3f*()
	    { return (Vec3f*) varray_; }
	inline operator const Vec3f*() const
	    { return (const Vec3f*) varray_; }
    };
#if 0
    struct OffsetCheck
    {
	// Generate compile error if offsets in union don't match
	int x_[(sizeof(Vec3x3) == sizeof(float) * 9) ? 1 : -1];
    };
#endif

public:
    // Allow access using subscripts as well as by name
#if 0
    union {
	struct {
	    float       xx, xy, xz;
	    float       yx, yy, yz;
	    float       zx, zy, zz;
	} u;
	Vec3x3 m;
    };
#else
    Vec3x3 m;
#endif

    // Accessors
    Vec3f&		operator[](unsigned int i)       { return m[i]; }
    const Vec3f&	operator[](unsigned int i) const { return m[i]; }

    const Vec3f&	up() const          { return (const Vec3f&)m[1]; }
    const Vec3f&	direction() const   { return (const Vec3f&)m[2]; }
    const Vec3f&	side() const        { return (const Vec3f&)m[0]; }

    // Modifiers
    void		setIdentity();
    void		setRotation(const Vec3f&, const Vec3f&);
    void		setRotation(const Vec3f&, float);
    void		setQuaternion(const Quat4f&);
    Vec3f&		up() { return (Vec3f&)m[1]; }
    Vec3f&		direction() { return (Vec3f&)m[2]; }

    // Arithmetic base methods
    void                invert(const Matrix3f &from);
    void                transpose(const Matrix3f &from);
    void                product(const Matrix3f& m1, const Matrix3f& m2);
    void                negate(const Matrix3f &src);
    void                sub(const Matrix3f &m1, const Matrix3f &m2);
    void                add(const Matrix3f &m1, const Matrix3f &m2);


    // C++ operator Aritmetic
    Matrix3f		invert() const
                            { Matrix3f temp; temp.invert(*this); return(temp); }

    Matrix3f		transpose() const
                            { Matrix3f temp; temp.transpose(*this); return(temp); }

    Matrix3f &operator*=(const Matrix3f &a)
                            { product(Matrix3f(*this),a); return(*this); }

    friend Matrix3f operator-(const Matrix3f &from)
                            { Matrix3f temp; temp.negate(from); return(temp); }

    friend Matrix3f operator-(const Matrix3f &a, const Matrix3f &b)
                            { Matrix3f temp; temp.sub(a,b); return(temp); }

    friend Matrix3f operator+(const Matrix3f &a, const Matrix3f &b)
                            { Matrix3f temp; temp.add(a,b); return(temp); }

    friend Matrix3f operator *(const Matrix3f &a, const Matrix3f &b)
                            { Matrix3f temp;  temp.product(a,b); return(temp); }
   
};

MATHS_END

#endif

// Local Variables:
// mode: c++
// End:
