// Aqsis
// Copyright (c) 1997 - 2001, Paul C. Gregory
//
// Contact: pgregory@aqsis.com
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU General Public
// License as published by the Free Software Foundation; either
// version 2 of the License, or (at your option) any later version.
//
// 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 GNU
// General Public License for more details.
//
// You should have received a copy of the GNU General Public
// License along with this library; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

/**
 * Copyright (C) 2006-2007  NTT DATA CORPORATION
 * 
 * Version: 1.0.0 2007/04/01
 *  
 */
package net.cellcomputing.himawari.library;

import static net.cellcomputing.himawari.library.Float_h.FLT_MAX;
import net.cellcomputing.himawari.accessory.STLVector;
import net.cellcomputing.himawari.library.types.CqMatrix;

/**
 * 
 * モーションブラーのための特別なサーフェースのモーションステージのシリーズを含む定型化されたクラス。
 * Templatised class containing a series of motion stages of a specific surface type for motion blurring.<br>
 * 
 * @author NTT DATA Corporation
 */
public strictfp class CqDeformingSurface extends CqBasicSurfaceMotionImple {
	
	/**
	 * デフォルトコンストラクタ
	 * @param a	モーションオブジェクトのデフォルトの値。
	 */
	public CqDeformingSurface( CqBasicSurface a ) 
	{
		super();
		CqMotionSpec( a );
	}
	
	/**
	 * コピーコンストラクタ
	 * @param From	コピー元
	 */
	public CqDeformingSurface( CqDeformingSurface From ) 
	{
		super( From );
		CqMotionSpec( (IqMotionSpec<CqBasicSurface>)From );
	}
	
	
	/** 
	 * Get combnied bound for all times
     * @return CqBound representing the geometric boundary of this GPrim over all time slots.
     */
	 public	CqBound	Bound()
    {
        CqBound B = new CqBound( FLT_MAX, FLT_MAX, FLT_MAX, -FLT_MAX, -FLT_MAX, -FLT_MAX );
        int i;
        for ( i = 0; i < iTimes(); i++ )
            B.Encapsulate( GetMotionObject( Time( i ) ).Bound() );

        return ( B );
    }
	 
    /** 
     * Dice this GPrim, creating a CqMotionMicroPolyGrid with all times in.
     */
    public CqMicroPolyGridBase Dice()
    {
        CqMotionMicroPolyGrid pGrid = new CqMotionMicroPolyGrid();
        int i;
        for ( i = 0; i < iTimes(); i++ )
        {
            CqMicroPolyGridBase pGrid2 = GetMotionObject( Time( i ) ).Dice();
            pGrid.AddTimeSlot( Time( i ), pGrid2 );
            pGrid2.AddRef();
			pGrid.SetfTriangular( pGrid2.fTriangular() );
        }
        return ( pGrid );
    }
    
    /** 
     * Split this GPrim, creating a series of CqDeformingSurface with all times in.
     */
    public int	Split( STLVector<CqBasicSurface> aSplits )
    {
        STLVector<STLVector< CqBasicSurface > > aaMotionSplits = new STLVector< STLVector<CqBasicSurface> >(2,CqBasicSurface.class);
        aaMotionSplits.resize( iTimes() );
        int cSplits = 0;
        int i;

        cSplits = GetMotionObject( Time( 0 ) ).Split( aaMotionSplits.get( 0 ) );
        for ( i = 1; i < iTimes(); i++ )
        {
            GetMotionObject( Time( i ) ).Split( aaMotionSplits.get( i ) );
        }
        
        // Now build motion surfaces from the splits and pass them back.
        for ( i = 0; i < cSplits; i++ )
        {
        	CqDeformingSurface pNewMotion = new CqDeformingSurface( (CqBasicSurface)null );
            pNewMotion.m_fDiceable = true;
            pNewMotion.m_EyeSplitCount = m_EyeSplitCount;
            int j;
            for ( j = 0; j < iTimes(); j++ )
                pNewMotion.AddTimeSlot( Time( j ), aaMotionSplits.get( j ).get( i ) );
            aSplits.add( (CqBasicSurface)( pNewMotion ));
        }
        return ( cSplits );
    }
    
    /** 
     * Determine if the prmary time slot is diceable, this is the one that is shaded, so
     * determines the dicing rate, which is then copied to the other times.
     * @return Boolean indicating GPrim is diceable.
     */
    public boolean Diceable()
    {
        boolean f = GetMotionObject( Time( 0 ) ) .Diceable();
        // Copy the split info so that at each time slot, the gprims split the same.
        int i;
        for ( i = 1; i < iTimes(); i++ )
            GetMotionObject( Time( i ) ) .CopySplitInfo( GetMotionObject( Time( 0 ) ) );
        return ( f );
    }

    /** 
     * Determine whether the passed surface is valid to be used as a
     *  frame in motion blur for this surface.
     */
    public boolean IsMotionBlurMatch( CqBasicSurface pSurf )
    {
        return( false );
    }

    /** 
     * Transform all GPrims by the specified transformation matrices.
     * @param matTx Reference to the transformation matrix.
     * @param matITTx Reference to the inverse transpose of the transformation matrix, used to transform normals.
     * @param matRTx Reference to the rotation only transformation matrix, used to transform vectors.
     * @param iTime The frame time at which to apply the transformation.
     */
    public void	Transform( final CqMatrix matTx,final CqMatrix matITTx, final CqMatrix matRTx)
    {
    	Transform(matTx, matITTx,  matRTx,0);
    }
    public void	Transform( final CqMatrix matTx,final CqMatrix matITTx, final CqMatrix matRTx, int iTime  )
    {
        GetMotionObject( iTime ).Transform( matTx, matITTx, matRTx, iTime );
    }

    /** 
     * Set the surface parameters of all GPrims to match those on the spefified one.
     * @param From GPrim to copy parameters from.
     */
    public	void	SetSurfaceParameters( final CqBasicSurface From )
    {
        int i;
        for ( i = 0; i < iTimes(); i++ )
            GetMotionObject( Time( i ) ) .SetSurfaceParameters( From );
    }
    
    /** 
     * Force all GPrims to be undiceable.
     */
    public	void	ForceUndiceable()
    {
        super.ForceUndiceable();
        int i;
        for ( i = 0; i < iTimes(); i++ )
            GetMotionObject( Time( i ) ).ForceUndiceable();
    }

    /** 
     * Mark all GPrims to be discarded.
     */
    public	void	Discard()
    {
        super.Discard();
        int i;
        for ( i = 0; i < iTimes(); i++ )
            GetMotionObject( Time( i ) ).Discard();
    }

    public	int cUniform()
    {
        return ( GetMotionObject( Time( 0 ) ) .cUniform() );
    }
    public	int cVarying()
    {
        return ( GetMotionObject( Time( 0 ) ) .cVarying() );
    }
    public	int cVertex()
    {
        return ( GetMotionObject( Time( 0 ) ) .cVertex() );
    }
    public	int cFaceVarying()
    {
        return ( GetMotionObject( Time( 0 ) ) .cFaceVarying() );
    }
    
    
    // Overrides from CqMotionSpec
    public	void	ClearMotionObject( CqBasicSurface A )
    {}

    public	CqBasicSurface	ConcatMotionObjects( CqBasicSurface A, CqBasicSurface B ) 
    {
        return ( A );
    }
    public	CqBasicSurface	LinearInterpolateMotionObjects( float Fraction, CqBasicSurface A, CqBasicSurface B )
    {
        return ( A );
    }

}
