// 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.shadervm;

import static net.cellcomputing.himawari.library.EqIntIndex.SHD_Var_varying_init;
import static net.cellcomputing.himawari.library.EqIntIndex.SHD_var_varying_vector;
import net.cellcomputing.himawari.accessory.STLArray;
import net.cellcomputing.himawari.accessory.STLVector;
import net.cellcomputing.himawari.accessory.primitive.p_boolean;
import net.cellcomputing.himawari.library.CqStats;
import net.cellcomputing.himawari.library.EqVariableType;
import net.cellcomputing.himawari.library.IqShaderData;
import net.cellcomputing.himawari.library.types.CqVector3D;

/**
 * CqShaderVariableVaryingクラスをCqVector3Dに特化した
 * 具現クラス
 * @author NTT DATA Corporation
 */
public strictfp class CqShaderVariableVaryingVector extends CqShaderVariableVarying<CqVector3D> {
	
	/**
	 * コンストラクタ。
	 * Vectorの配列を1にセットして、
	 * 統計情報を更新する。
	 */
	public CqShaderVariableVaryingVector( )
	{
		super(new EqVariableType(EqVariableType.type_vector));
		//委譲したものを実装
		//m_aValue = new STLVector<CqVector3D>(CqVector3D.class);
		m_aValue = new STLArray<CqVector3D>(CqVector3D.class);
		m_aValue.resize( 1 );
		
		CqStats.STATS_INC( SHD_var_varying_vector );
	}
	
	/**
	 * コンストラクタ。
	 * Vectorの配列を1にセットして、
	 * 統計情報を更新する。
	 * 
	 * @param strName
	 * @param fParameter
	 */
	public CqShaderVariableVaryingVector( final String strName, boolean fParameter)
	{
		super(strName,fParameter,new EqVariableType(EqVariableType.type_vector));
		//委譲したものを実装
		//m_aValue = new STLVector<CqVector3D>(CqVector3D.class);
		m_aValue = new STLArray<CqVector3D>(CqVector3D.class);
		m_aValue.resize( 1 );
		CqStats.STATS_INC( SHD_var_varying_vector );
	}
	
	/**
	 * コンストラクタ。
	 * Vectorの配列を1にセットして、
	 * 統計情報を更新する。
	 * 
	 * @param strName
	 */
	public CqShaderVariableVaryingVector( final String strName){
		this(strName,false);
	}
	
	/**
	 * コピーコンストラクタ
	 * @param val
	 */
	public CqShaderVariableVaryingVector(CqShaderVariableVaryingVector val){
		super(val,new EqVariableType(EqVariableType.type_vector));
		//m_aValue = new STLVector<CqVector3D>(CqVector3D.class);
		m_aValue = new STLArray<CqVector3D>(CqVector3D.class);
		m_aValue.resize( val.m_aValue.size() );
//		m_aValue.assign( val.m_aValue.begin(), val.m_aValue.begin() );
		//正しいコードに修正した 2005/11/2 nttdata
		for(int i = 0; i < val.m_aValue.size(); i++)
			m_aValue.elementAt(i).assignment(val.m_aValue.elementAt(i));
		
	}
	
	/**
	 * 「=」演算子のオーバーロード
	 *  Vectorの値をコピーする。
	 * @param From
	 */
	public void assignment(CqShaderVariableVarying From) {
		m_aValue.resize(From.m_aValue.size());
		for(int i = 0; i < From.m_aValue.size();i++){
			m_aValue.elementAt(i).assignment((CqVector3D)From.m_aValue.elementAt(i));
		}
		
	}
	
	/**
	 * 親クラスで定義された初期化関数
	 * Vectorのサイズが1以上であれば
	 * 指定された数だけ先頭の値でVectorを埋め尽くす。
	 * Vectorのサイズが0以下であれば、
	 * 初期値で埋め尽くす。
	 * 
	 * 埋め尽くす数は(uGridRes+1) * (vGridRes)。
	 * 
	 * @param uGridRes
	 * @param vGridRes
	 */
	public void Initialise(int uGridRes, int vGridRes) {
		CqVector3D Def = new CqVector3D();
		
		if ( m_aValue.size() > 0 )
			Def.assignment(m_aValue.elementAt(0));
		
		if( Def.x == 0.0f && Def.y == 0.0f && Def.z == 0.0f )
		{
			m_aValue.resize( (( uGridRes + 1 ) * ( vGridRes + 1 )) );
		}
		else
		{
			m_aValue.assign( (( uGridRes + 1 ) * ( vGridRes + 1 )), Def );
		}
		
		//ここまで
		CqStats.STATS_INC( SHD_Var_varying_init );
	}
	
	/**
	 * 指定された場所のShaderDataの値を取得する
	 * @param res 取得した値を格納する変数
	 * @param index 取得する場所
	 */
	public	void	GetPoint( CqVector3D res, int index)
	{
		res.assignment(m_aValue.elementAt( index ));
	}
	
	/**
	 * ShaderDataの持つ、CqVector3D型のポインタを取得する。
	 * 
	 * @param res 結果を格納する。中身を変更するとShaderData内の値も影響を受ける
	 */
	public	void	GetPointPtr( STLVector<CqVector3D> res )
	{
		res.resize(m_aValue.size());
		for(int i=0;i < m_aValue.size();i++){
			res.setElementAt(m_aValue.elementAt(i),i);
		}
	}
	//public STLVector<CqVector3D> GetPointPtr_2()
	public STLArray<CqVector3D> GetPointPtr_2()
	{
		return m_aValue;
	}
	
	/**
	 * ShaderDataの指定された場所の値を変更する。
	 * 
	 * @param p 変更する値
	 * @param index 変更する場所
	 */
	public	void	SetPoint( final CqVector3D p, int index )
	{
		m_aValue.elementAt(index).assignment( p );
	}
	
	/**
	 * ShaderDataの値を変更する。
	 * 引数で指定された値でVectorを埋め尽くす
	 * @param p 変更する値
	 */
	public	void	SetPoint( final CqVector3D p )
	{
		m_aValue.assign( m_aValue.size(), p );
	}
	
	/**
	 * 指定された場所のShaderDataの値を取得する
	 * @param res 取得した値を格納する変数
	 * @param index 取得する場所
	 */
	public	void	GetVector( CqVector3D res, int index )
	{
		GetPoint( res, index );
	}
	
	/**
	 * ShaderDataの持つ、CqVector3D型のポインタを取得する。
	 * 
	 * @param res 結果を格納する。中身を変更するとShaderData内の値も影響を受ける
	 */
	public	void	GetVectorPtr( STLVector<CqVector3D> res )
	{
		res.resize(m_aValue.size());
		for(int i=0;i < m_aValue.size();i++){
			res.setElementAt(m_aValue.elementAt(i),i);
		}
	}
//	public STLVector<CqVector3D> GetPointPtr_2()
	public STLArray<CqVector3D> GetVectorPtr_2()
	{
		return m_aValue;
	}
	/**
	 * ShaderDataの指定された場所の値を変更する。
	 * 
	 * @param p 変更する値
	 * @param index 変更する場所
	 */
	public	void	SetVector( final CqVector3D p, int index )
	{
		SetPoint( p, index );
	}
	
	/**
	 * ShaderDataの値を変更する。
	 * 引数で指定された値でVectorを埋め尽くす
	 * @param p 変更する値
	 */
	public	void	SetVector( final CqVector3D p )
	{
		SetPoint( p );
	}
	
	/**
	 * 指定された場所のShaderDataの値を取得する
	 * @param res 取得した値を格納する変数
	 * @param index 取得する場所
	 */
	public	void	GetNormal( CqVector3D res, int index )
	{
		GetPoint( res, index );
	}
	
	/**
	 * ShaderDataの持つ、CqVector3D型のポインタを取得する。
	 * 
	 * @param res 結果を格納する。中身を変更するとShaderData内の値も影響を受ける
	 */
	public	void	GetNormalPtr( STLVector<CqVector3D> res )
	{
		res.resize(m_aValue.size());
		for(int i=0;i < m_aValue.size();i++){
			res.setElementAt(m_aValue.elementAt(i),i);
		}
	}
	public STLArray<CqVector3D> GetNormalPtr_2()
	{
		return m_aValue;
	}
	
	/**
	 * ShaderDataの指定された場所の値を変更する。
	 * 
	 * @param p 変更する値
	 * @param index 変更する場所
	 */
	public	void	SetNormal( final CqVector3D p, int index )
	{
		SetPoint( p, index );
	}
	
	/**
	 * ShaderDataの値を変更する。
	 * 引数で指定された値でVectorを埋め尽くす
	 * @param p 変更する値
	 */
	public	void	SetNormal( final CqVector3D p )
	{
		SetPoint( p );
	}
	
	/**
	 * 指定された場所の値がすべて0の時にfalseが、
	 * それ以外はtrueが返る。
	 * 
	 * @param res 値を格納する変数
	 * @param index 指定する場所
	 */
	public void	GetBool( p_boolean res, int index )
	{
		res.value = ( ( m_aValue.elementAt( index ).x != 0.0f ) || ( m_aValue.elementAt( index ).y != 0.0f ) || ( m_aValue.elementAt( index ).z != 0.0f ) );
	}
	
	/** Copy the values from the passed variable into this, taking into account any class differences.
	 * 引数で指定された変数が持つ値を、コピーする。
	 * コピー元のサイズが1以下の場合は、その値を
	 * Vectorの長さだけコピーする。
	 *  
	 * ただしコピー元のVectorのサイズが1より大きく
	 * 自分のVectorのサイズより小さい場合はErrorとなる。
	 * @param pVal The variable to copy from.
	 */
	public	void	SetValueFromVariable( final IqShaderData pVal )
	{
		int i;
		if ( pVal.Size() > 1 )
		{
//			STLVector<CqVector3D> pData = new STLVector<CqVector3D>(CqVector3D.class);
//			pVal.GetVectorPtr( pData );
			
			//STLVector<CqVector3D> pData ;
			STLArray<CqVector3D> pData ;
			pData = pVal.GetVectorPtr_2( );
			
			for ( i = 0; i < Size(); i++ )
				m_aValue.elementAt( i ).assignment( pData.elementAt( i ));
		}
		else
		{
			CqVector3D temp = new CqVector3D();
			pVal.GetVector( temp );
			m_aValue.assign( m_aValue.size(), temp );
		}
	}
	
	/** 
	 * Set the all SIMD data ased on a state vector, only indexes whose bit is set are modified.
	 * 引数で指定された変数が持つVectorの指定された場所の値を
	 * 自分自身のVectorの同じ場所にコピーする。
	 * 
	 * ただし、自分自身、またはコピー元の持つVectorの長さ以上の場所を指定すると
	 * エラーが発生する。(C++では特にエラーが起きない)
	 * @param pVal コピー元 The stack entry to assign.
	 * @param index コピーする場所 Integer SIMD index.
	 */
	public	void	SetValueFromVariable( final IqShaderData pVal, int index )
	{
		pVal.GetVector( m_aValue.elementAt( index ), index );
	}
	
	/**
	 * 自分と同じ値を持つインスタンスを返す
	 * 
	 * @return 自分自身のコピー
	 */
	public	IqShaderData Clone()
	{
		CqShaderVariableVaryingVector newVar = new CqShaderVariableVaryingVector( this );
		newVar.SetSize( (int) Size() );
		newVar.SetValueFromVariable( this );
		return ( newVar );
	}
}
