// 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.EqCoordSystems.CoordSystem_Camera;
import static net.cellcomputing.himawari.library.EqCoordSystems.CoordSystem_Current;
import static net.cellcomputing.himawari.library.EqCoordSystems.CoordSystem_Last;
import static net.cellcomputing.himawari.library.EqCoordSystems.CoordSystem_NDC;
import static net.cellcomputing.himawari.library.EqCoordSystems.CoordSystem_Raster;
import static net.cellcomputing.himawari.library.EqCoordSystems.CoordSystem_Screen;
import static net.cellcomputing.himawari.library.EqCoordSystems.CoordSystem_World;
import static net.cellcomputing.himawari.library.EqModeBlock.Attribute;
import static net.cellcomputing.himawari.library.EqModeBlock.BeginEnd;
import static net.cellcomputing.himawari.library.EqModeBlock.Frame;
import static net.cellcomputing.himawari.library.EqModeBlock.Motion;
import static net.cellcomputing.himawari.library.EqModeBlock.Object;
import static net.cellcomputing.himawari.library.EqModeBlock.Solid;
import static net.cellcomputing.himawari.library.EqModeBlock.Transform;
import static net.cellcomputing.himawari.library.EqModeBlock.World;
import static net.cellcomputing.himawari.library.EqRenderMode.RenderMode_Image;
import static net.cellcomputing.himawari.library.EqShaderType.Type_Surface;
import static net.cellcomputing.himawari.library.EqVariableClass.class_constant;
import static net.cellcomputing.himawari.library.EqVariableClass.class_facevarying;
import static net.cellcomputing.himawari.library.EqVariableClass.class_invalid;
import static net.cellcomputing.himawari.library.EqVariableClass.class_uniform;
import static net.cellcomputing.himawari.library.EqVariableClass.class_varying;
import static net.cellcomputing.himawari.library.EqVariableClass.class_vertex;
import static net.cellcomputing.himawari.library.EqVariableType.type_color;
import static net.cellcomputing.himawari.library.EqVariableType.type_float;
import static net.cellcomputing.himawari.library.EqVariableType.type_hpoint;
import static net.cellcomputing.himawari.library.EqVariableType.type_integer;
import static net.cellcomputing.himawari.library.EqVariableType.type_invalid;
import static net.cellcomputing.himawari.library.EqVariableType.type_matrix;
import static net.cellcomputing.himawari.library.EqVariableType.type_normal;
import static net.cellcomputing.himawari.library.EqVariableType.type_point;
import static net.cellcomputing.himawari.library.EqVariableType.type_string;
import static net.cellcomputing.himawari.library.EqVariableType.type_vector;
import static net.cellcomputing.himawari.library.Float_h.FLT_MAX;
import static net.cellcomputing.himawari.library.RiGlobal.CreateDisplayDriverManager;
import static net.cellcomputing.himawari.library.RiGlobal.CreateRaytracer;
import static net.cellcomputing.himawari.library.RiGlobal.QGetRenderContext;
import static net.cellcomputing.himawari.library.RiGlobal.RI_SHADER_EXTENSION;
import static net.cellcomputing.himawari.library.RiGlobal.chash;
import static net.cellcomputing.himawari.library.RiGlobal.cuhash;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsConstant;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsConstantArray;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsFaceVarying;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsFaceVaryingArray;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsUniform;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsUniformArray;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsVarying;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsVaryingArray;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsVertex;
import static net.cellcomputing.himawari.library.RiGlobal.gVariableCreateFuncsVertexArray;
import static net.cellcomputing.himawari.library.RiGlobal.ohash;
import static net.cellcomputing.himawari.library.RiGlobal.oldkey;
import static net.cellcomputing.himawari.library.RiGlobal.oldresult;
import static net.cellcomputing.himawari.library.RiGlobal.shash;
import static net.cellcomputing.himawari.shaderexecenv.GlobalShaderExecEnv.gShaderTypeNames;

import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.Reader;
import java.io.StreamTokenizer;
import java.lang.reflect.Method;
import java.util.HashMap;

import net.cellcomputing.himawari.accessory.STLVector;
import net.cellcomputing.himawari.accessory.primitive.p_String;
import net.cellcomputing.himawari.accessory.primitive.p_float;
import net.cellcomputing.himawari.accessory.primitive.p_int;
import net.cellcomputing.himawari.exception.DisplayNotFoundException;
import net.cellcomputing.himawari.exception.XqException;
import net.cellcomputing.himawari.library.types.CqColor;
import net.cellcomputing.himawari.library.types.CqMatrix;
import net.cellcomputing.himawari.library.types.CqVector2D;
import net.cellcomputing.himawari.library.types.CqVector3D;
import net.cellcomputing.himawari.main.Globalmain;
import net.cellcomputing.himawari.shadervm.CqShaderVM;
import net.cellcomputing.himawari.util.CellCipher;
import net.cellcomputing.himawari.util.HimawariLogger;

/**
 * 
 * レンダリング中に保存しておくデータの全てを管理するクラス。
 * 
 * @author NTT DATA Corporation
 */
public strictfp class CqRenderer implements IqRenderer{
	
	/** CqRenderer()
	 * コンストラクタ
	 *　基本的なものの初期化
	 * */
	public CqRenderer()
	{		
		// 各変数の初期化
		
		m_pImageBuffer 			= null ;
		m_Mode.setValue(RenderMode_Image);
//		m_fSaveGPrims 			= false ;
		m_OutputDataOffset 		= 9;		// Cs, Os, z, coverage, a
		m_OutputDataTotalSize 	= 9;		// Cs, Os, z, coverage, a
		m_FrameNo 				= 0 ;
		m_bObjectOpen 			= false;
		try {
			m_pErrorHandler 		= RendermanInterface.class.getMethod("RiErrorPrint", int.class,int.class,String.class);
		} catch (Exception e) {
			HimawariLogger.outputException( e );
		} 
		m_pProgressHandler 		= null;
		m_pPreRenderFunction	= null;
		m_pPreWorldFunction		= null;
		m_pRaytracer			= null;
		
		
		m_pImageBuffer = new CqImageBuffer();
		
		// デフォルト CqOptions　の初期化　Initialize the default options
		m_pOptDefault = new CqOptions();
		
		m_pAttrDefault  = new CqAttributes();
		m_pAttrDefault.AddRef();
		//C言語オリジナル　ADDREF( m_pAttrDefault );
		
		m_pTransDefault =  new CqTransform();
		m_pTransCamera  =  new CqTransform();
		m_pTransDefObj  =  new CqTransform();
		m_fWorldBegin = false;
		
		// coordinate systems　の配列の初期化　Initialise the array of coordinate systems.

		m_aCoordSystems.resize( CoordSystem_Last );
		
		SqCoordSys[] SqCoordSystmp = new SqCoordSys[CoordSystem_Last];
		SqCoordSystmp[CoordSystem_Camera] = new SqCoordSys();
		SqCoordSystmp[CoordSystem_Current] = new SqCoordSys();
		SqCoordSystmp[CoordSystem_World] = new SqCoordSys();
		SqCoordSystmp[CoordSystem_Screen] = new SqCoordSys();
		SqCoordSystmp[CoordSystem_NDC] = new SqCoordSys();
		SqCoordSystmp[CoordSystem_Raster] = new SqCoordSys();
		
		SqCoordSystmp[CoordSystem_Camera].m_strName = "__camera__";
		SqCoordSystmp[CoordSystem_Current].m_strName = "__current__";
		SqCoordSystmp[CoordSystem_World].m_strName = "world";
		SqCoordSystmp[CoordSystem_Screen].m_strName = "screen";
		SqCoordSystmp[CoordSystem_NDC].m_strName = "NDC";
		SqCoordSystmp[CoordSystem_Raster].m_strName = "raster";
		
		SqCoordSystmp[CoordSystem_Camera].m_hash = "__camera__".hashCode();
		SqCoordSystmp[CoordSystem_Current].m_hash = "__current__".hashCode();
		SqCoordSystmp[CoordSystem_World].m_hash = "world".hashCode();
		SqCoordSystmp[CoordSystem_Screen].m_hash = "screen".hashCode();
		SqCoordSystmp[CoordSystem_NDC].m_hash = "NDC".hashCode();
		SqCoordSystmp[CoordSystem_Raster].m_hash = "raster".hashCode();
		
		m_aCoordSystems.setElementAt(SqCoordSystmp[CoordSystem_Camera],CoordSystem_Camera);
		m_aCoordSystems.setElementAt(SqCoordSystmp[CoordSystem_Current],CoordSystem_Current);
		m_aCoordSystems.setElementAt(SqCoordSystmp[CoordSystem_World],CoordSystem_World);
		m_aCoordSystems.setElementAt(SqCoordSystmp[CoordSystem_Screen],CoordSystem_Screen);
		m_aCoordSystems.setElementAt(SqCoordSystmp[CoordSystem_NDC],CoordSystem_NDC);
		m_aCoordSystems.setElementAt(SqCoordSystmp[CoordSystem_Raster],CoordSystem_Raster);
		
		/*C言語オリジナルソース
		 m_aCoordSystems[ CoordSystem_Camera ].m_strName = "__camera__";
		 m_aCoordSystems[ CoordSystem_Current ].m_strName = "__current__";
		 m_aCoordSystems[ CoordSystem_World ].m_strName = "world";
		 m_aCoordSystems[ CoordSystem_Screen ].m_strName = "screen";
		 m_aCoordSystems[ CoordSystem_NDC ].m_strName = "NDC";
		 m_aCoordSystems[ CoordSystem_Raster ].m_strName = "raster";
		 
		 m_aCoordSystems[ CoordSystem_Camera ].m_hash = "__camera__".hashCode();
		 m_aCoordSystems[ CoordSystem_Current ].m_hash = "__current__".hashCode();
		 m_aCoordSystems[ CoordSystem_World ].m_hash = "world".hashCode();
		 m_aCoordSystems[ CoordSystem_Screen ].m_hash = "screen".hashCode();
		 m_aCoordSystems[ CoordSystem_NDC ].m_hash = "NDC".hashCode();
		 m_aCoordSystems[ CoordSystem_Raster ].m_hash = "raster".hashCode();
		 */
		
		//ディスプレイドライバの初期化
		m_pDDManager = CreateDisplayDriverManager();
		m_pDDManager.Initialise();
//		
//		//レイトレースエンジンの初期化
		m_pRaytracer = CreateRaytracer();
		m_pRaytracer.Initialise();
		
		// ピンホールレンズのための被写界深度の設定　Set up DoF stuff for pinhole lens ( i.e. no DoF )
		m_UsingDepthOfField = false;
		
		// Get the hash keys for object, shader, camera keywords.
		
		// Set the TIFF Error/Warn handler
//		TIFFSetErrorHandler( &TIFF_ErrorHandler );
//		TIFFSetWarningHandler( &TIFF_WarnHandler );
	}
	
	public void destruct()
	{
		// ImageBufferのクリア
		if ( m_pImageBuffer != null)
		{
			m_pImageBuffer.Release();
			m_pImageBuffer = null;
		}
		FlushShaders();
		
		// Shutdown the shaderVM.
		CqShaderVM.ShutdownShaderEngine();
		
		// Close down the Display device manager.
		m_pDDManager.Shutdown();
		m_pDDManager = null;
//		delete(m_pDDManager);
		
		// Delete the default options
		if ( m_pOptDefault != null)
		{
//			delete m_pOptDefault;
			m_pOptDefault = null;
		}
		
		// Delete the default attributes, transform and camera transform
		if ( m_pAttrDefault != null)
		{
			m_pAttrDefault.Release();
			//C言語RELEASEREF( m_pAttrDefault );
			m_pAttrDefault = null;
		}
		
		if( m_pRaytracer != null)	// MGC: MEMLEAK_FIX
		{
//			delete m_pRaytracer;
			m_pRaytracer = null;	// MGC: or better NULL?
		}
		// Clear up the MicroPolygon memory pool.
//必要なし		CqMicroPolygon.Flush();					 
//必要なし		CqMovingMicroPolygonKeyPoints.Flush();	 
//必要なし		CqLath.Flush();							 
		
		// Clear the ObjectInstance buffer
//		std::vector<CqObjectInstance*>::iterator i;
//		for(i=m_ObjectInstances.begin(); i!=m_ObjectInstances.end(); i++)
//			delete((*i));
//		m_ObjectInstances.clear();
		
		m_ObjectInstances.clear();
		m_ObjectInstances = null;
	}
	
//	---------------------------------------------------------------------
	/** Create a new main context, called from within RiBegin(), error if not first
	 * context created.  If first, create with this as the parent.
	 * 新しいメインのコンテキストを作成します。
	 * RiBegein（）から呼ばれています。
	 * 最初のコンテキストの作成でなければエラーになります。
	 * 最初に、親としてこれで作成します。
	 */
	public CqModeBlock	BeginMainModeBlock()
	{
		//XXX: Error checking may eventually be unnecessary.  - ajb
		if ( m_pconCurrent == null)
		{
			m_pconCurrent =  new CqMainModeBlock( m_pconCurrent ) ;
			return ( m_pconCurrent );
		}
		else
			return null ;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
	}
	
//	---------------------------------------------------------------------
	/** Create a new Frame context, should only be called when the current
	 * context is a Main context, but the internal context handling deals
	 * with it so I don't need to worry.
	 *  新しいフレームのコンテキストを作成します。
	 *  現在のコンテキストがメインの時だけ呼ばれます。
	 *  しかし、内部のコンテキストハンドリングはそのような形で扱われるので、私は注意しています。
	 */
	public CqModeBlock	BeginFrameModeBlock()
	{
		//XXX: Error checking may eventually be unnecessary.  - ajb
		if ( m_pconCurrent != null)
		{
			CqModeBlock pconNew = m_pconCurrent.BeginFrameModeBlock();
			if ( pconNew  != null)
			{
				m_pconCurrent = pconNew;
				return ( pconNew );
			}
			else
				return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
		}
		else
			return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
	}
	
//	---------------------------------------------------------------------
	/** Create a new world context, again the internal context handling deals
	 * with invalid calls.
	 * 新しいワールドのコンテキストを作成します。
	 * 再び内部のコンテキストハンドリングで無効の呼び出しとして扱われます。
	 */
	
	public CqModeBlock	BeginWorldModeBlock()
	{
		//XXX: Error checking may eventually be unnecessary.  - ajb
		if ( m_pconCurrent != null)
		{
			CqModeBlock pconNew = m_pconCurrent.BeginWorldModeBlock();
			if ( pconNew != null)
			{
				m_pconCurrent = pconNew;
				return ( pconNew );
			}
			else
				return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
		}
		else
			return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
	}
	
//	---------------------------------------------------------------------
	/** Create a new attribute context.
	 * 新しいアトリビュートのコンテキストを作成します。
	 */
	
	public CqModeBlock BeginAttributeModeBlock()
	{
		//XXX: Error checking may eventually be unnecessary.  - ajb
		if ( m_pconCurrent != null)
		{
			CqModeBlock pconNew = m_pconCurrent.BeginAttributeModeBlock();
			if ( pconNew != null)
			{
				m_pconCurrent = pconNew;
				return ( pconNew );
			}
			else
				return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
		}
		else
			return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
	}
	
//	---------------------------------------------------------------------
	/** Create a new transform context.
	 * 新しいトランスフォームのコンテキストを作成する。
	 */
	public CqModeBlock	BeginTransformModeBlock()
	{
		//XXX: Error checking may eventually be unnecessary.  - ajb
		if ( m_pconCurrent != null)
		{
			CqModeBlock pconNew = m_pconCurrent.BeginTransformModeBlock();
			if ( pconNew != null)
			{
				m_pconCurrent = pconNew;
				return ( pconNew );
			}
			else
				return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
		}
		else
			return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
	}
	
//	---------------------------------------------------------------------
	/** Create a new solid context.
	 * 新しいソリッドのコンテキストを作成する。
	 */ 
	public CqModeBlock	BeginSolidModeBlock( String type )
	{
		//XXX: Error checking may eventually be unnecessary.  - ajb
		if ( m_pconCurrent != null)
		{
			CqModeBlock pconNew = m_pconCurrent.BeginSolidModeBlock( type );
			if ( pconNew != null)
			{
				m_pconCurrent = pconNew;
				return ( pconNew );
			}
			else
				return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
		}
		else
			return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
	}
	
//	---------------------------------------------------------------------
	/** Create a new object context.
	 * 新しいオブジェクトのコンテキストを作成する。
	 */
	public CqModeBlock	BeginObjectModeBlock()
	{
		//XXX: Error checking may eventually be unnecessary.  - ajb
		if ( m_pconCurrent != null)
		{
			CqModeBlock pconNew = m_pconCurrent.BeginObjectModeBlock();
			if ( pconNew != null)
			{
				m_pconCurrent = pconNew;
				return ( pconNew );
			}
			else
				return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
		}
		else
			return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
	}
	
//	---------------------------------------------------------------------
	/** Create a new motion context.
	 *  新しいモーションコンテキストを作成する。
	 */
	public CqModeBlock BeginMotionModeBlock( int N, float times[] )
	{
		// XXX: Error checking may eventually be unnecessary.  - ajb
		if ( m_pconCurrent != null)
		{
			CqModeBlock pconNew = m_pconCurrent.BeginMotionModeBlock( N, times );
			if ( pconNew != null)
			{
				m_pconCurrent = pconNew;
				return ( pconNew );
			}
			else
				return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
		}
		else
			return null;//boost::shared_ptr<CqModeBlock>( );とリターンしているが適当な値っぽいのでnull
	}
	
//	----------------------------------------------------------------------
	/** Delete the current context presuming it is a main context.
	 * 　メインのコンテキストと推測した、コンテキストを消去してください。
	 */
	
	public void	EndMainModeBlock()
	{
		if ( (m_pconCurrent != null) && (m_pconCurrent.Type().getValue() == BeginEnd))
		{
			m_pconCurrent.EndMainModeBlock();
			m_pconCurrent = m_pconCurrent.pconParent();
		}
	}
	
//	----------------------------------------------------------------------
	/** Delete the current context presuming it is a frame context.
	 * フレームのコンテキストと推測した、コンテキストを消去してください。
	 */
	public void	EndFrameModeBlock()
	{
		if ( (m_pconCurrent != null) && (m_pconCurrent.Type().getValue() == Frame ))
		{
			m_pconCurrent.EndFrameModeBlock();
			m_pconCurrent = m_pconCurrent.pconParent();
		}
	}
	
//	----------------------------------------------------------------------
	/** Delete the current context presuming it is a world context.
	 * ワールドのコンテキストと推測した、コンテキストを消去してください。
	 */
	public void	EndWorldModeBlock()
	{
		if ( (m_pconCurrent != null) && (m_pconCurrent.Type().getValue() == World))
		{
			m_pconCurrent.EndWorldModeBlock();
			m_pconCurrent = m_pconCurrent.pconParent();
		}
	}
	
//	----------------------------------------------------------------------
	/** Delete the current context presuming it is a attribute context.
	 * アトリビュートのコンテキストと推測した、コンテキストを消去してください。
	 */
	public void	EndAttributeModeBlock()
	{
		if ( (m_pconCurrent != null) && (m_pconCurrent.Type().getValue() == Attribute))
		{
			m_pconCurrent.EndAttributeModeBlock();
			m_pconCurrent = m_pconCurrent.pconParent();
		}
	}
	
//	----------------------------------------------------------------------
	/** Delete the current context presuming it is a transform context.
	 * トランスフォームのコンテキストと推測した、コンテキストを消去してください。
	 */
	public void	EndTransformModeBlock()
	{
		if ( (m_pconCurrent != null) && (m_pconCurrent.Type().getValue() == Transform))
		{
			// Copy the current state of the attributes UP the stack as a TransformBegin/End doesn't store them
			m_pconCurrent.pconParent().m_pattrCurrent = m_pconCurrent.m_pattrCurrent;
			m_pconCurrent.EndTransformModeBlock();
			m_pconCurrent = m_pconCurrent.pconParent();
		}
	}
	
//	----------------------------------------------------------------------
	/** Delete the current context presuming it is a solid context.
	 * ソリッドのコンテキストと推測した、コンテキストを消去してください。
	 */
	public void	EndSolidModeBlock()
	{
		if ( (m_pconCurrent != null) && (m_pconCurrent.Type().getValue() == Solid ) )
		{
			m_pconCurrent.EndSolidModeBlock();
			m_pconCurrent = m_pconCurrent.pconParent();
		}
	}
	
//	----------------------------------------------------------------------
	/** Delete the current context presuming it is a object context.
	 * オブジェクトのコンテキストと推測した、コンテキストを消去してください。
	 */
	
	public void	EndObjectModeBlock()
	{
		if ( (m_pconCurrent != null) && (m_pconCurrent.Type().getValue() == Object ) )
		{
			m_pconCurrent.EndObjectModeBlock();
			m_pconCurrent = m_pconCurrent.pconParent();
		}
	}
	
//	----------------------------------------------------------------------
	/** Delete the current context presuming it is a motion context.
	 * モーションのコンテキストと推測した、コンテキストを消去してください。
	 */
	public void	EndMotionModeBlock()
	{
		if ( (m_pconCurrent != null) && (m_pconCurrent.Type().getValue() == Motion) )
		{
			CqModeBlock pconParent = m_pconCurrent.pconParent();
			// Copy the current state of the attributes UP the stack as a TransformBegin/End doesn't store them
			pconParent.m_pattrCurrent = m_pconCurrent.m_pattrCurrent;
			pconParent.m_ptransCurrent = m_pconCurrent.m_ptransCurrent;
			m_pconCurrent.EndMotionModeBlock();
			m_pconCurrent = pconParent;
		}
	}
	
//	----------------------------------------------------------------------
	/** Return a reference to the current options.
	 * 現在のオプションの参照を返す
	 */
	public	CqOptions	optCurrent()
	{
		if ( m_pconCurrent != null)
			return ( m_pconCurrent.optCurrent() );
		else
		{
			assert( m_pOptDefault != null );
			return ( m_pOptDefault );
		}
	}
	
//	----------------------------------------------------------------------
	/** Return a pointer to the current attributes.
	 * 　現在のアトリビュートの参照を返す
	 */
	public CqAttributes	pattrCurrent()
	{
		if ( m_pconCurrent != null)
			return ( m_pconCurrent.pattrCurrent() );
		else
			return ( m_pAttrDefault );
	}
	
//	----------------------------------------------------------------------
	/** Return a writable pointer to the current attributes.
	 * 現在の書き込むことができるアトリビュートのポインタを返す
	 */
	
	public	CqAttributes	pattrWriteCurrent()
	{
		if ( m_pconCurrent != null)
			return ( m_pconCurrent.pattrWriteCurrent() );
		else
			return ( m_pAttrDefault );
	}
	
//	----------------------------------------------------------------------
	/** Return a pointer to the current transform.
	 * 　現在のトランスフォームのポインタを返す
	 */
	public 	CqTransform		ptransCurrent()
	{
		if ( m_pconCurrent != null)
			return ( m_pconCurrent.ptransCurrent() );
		else
			return ( m_pTransDefault );
	}
	
	
	public void	ptransSetTime( final CqMatrix matTrans )
	{
		if ( m_pconCurrent == null)
		{
			throw null;
		}
		CqTransform.Set set = null; //型によって呼び出すコンストラクタを変えたいためにここでダミーを宣言する。
		CqTransform newTrans = new CqTransform( m_pconCurrent.ptransCurrent(), Time(), matTrans, set );
		m_pconCurrent.ptransSetCurrent( newTrans );
	}
	
	public void	ptransSetCurrentTime( final CqMatrix matTrans )
	{
		if ( m_pconCurrent == null)
		{
			throw null;
		}
		CqTransform.SetCurrent setCurrent = null; //型によって呼び出すコンストラクタを変えたいためにここでダミーを宣言する。
		CqTransform newTrans =  new CqTransform( m_pconCurrent.ptransCurrent(), Time(), matTrans, setCurrent );
		m_pconCurrent.ptransSetCurrent( newTrans );
	}
	
	public void	ptransConcatCurrentTime( final CqMatrix matTrans )
	{
		if ( m_pconCurrent == null)
		{
			throw null;
		}
		CqTransform.ConcatCurrent concatcurrent = null; //型によって呼び出すコンストラクタを変えたいためにここでダミーを宣言する。
		CqTransform newTrans = new CqTransform( m_pconCurrent.ptransCurrent(), Time(), matTrans, concatcurrent );
		m_pconCurrent.ptransSetCurrent( newTrans );
	}
	
//	----------------------------------------------------------------------
	/** Get the current shutter time, always returns 0.0 unless within a motion block,
	 * when it returns the appropriate shutter time.
	 * 現在のシャッタータイムを取得する。
	 * 適切なシャッター時間を返すとき、モーションブロックの中でなければ常に０．０を返す。
	 */
	
	public	float	Time()
	{
		if ( (m_pconCurrent != null)&& m_pconCurrent.Type().getValue() == Motion)
			return ( m_pconCurrent.Time() );
		else
			//nttdata 高速化
			//return ( QGetRenderContext().optCurrent().GetFloatOptionWrite( "System", "Shutter" )[ 0 ].value );
			return ( QGetRenderContext().optCurrent().GetFloatOptionWriteIndex( "System", "Shutter",0 ).value );
	}
	
//	----------------------------------------------------------------------
	/** Advance the current shutter time, only valid within motion blocks.
	 * 現在のシャッタータイムのアドバンス版
	 * モーションブロックが有効な時のみ
	 */
	public	void	AdvanceTime()
	{
		if ( m_pconCurrent != null)
			m_pconCurrent.AdvanceTime();
	}
	
	/**
	 * バケットのカウント数を返す
	 */
	public	int		bucketCount()
	{
		return(pImage().cXBuckets() * pImage().cYBuckets() );
	}
	
	/** Set a pointer to the current context.
	 * Primarily for Procedural objects
	 * 現在のコンテキストのポインタを設定する。
	 * 主としてProceduralオブジェクトのために
	 * @return Pointer to a previous CqModeBlock.<br>前のCqModeBlockへのポインタ。
	 *  
	 */
	public CqModeBlock	pconCurrent(final CqModeBlock pcon )
	{
		CqModeBlock prev = m_pconCurrent;
		m_pconCurrent = pcon;
		return ( prev );
	}
	/** Get a pointer to the current context.
	 * 現在のコンテキストのポインタを設定する。
	 * @return Pointer to a CqModeBlock derived class.<br>CqModeBlockへの指針はクラスを引き出しました。
	 * 
	 */
	public CqModeBlock	pconCurrent()
	{
		return ( m_pconCurrent );
	}
	
	/** Get a pointer to the current image buffer.
	 * 現在のイメージバッファーのポインタを取得する
	 * @return A CqImageBuffer pointer.<BR>イメージバッファーのポインタ
	 * 
	 */
	public CqImageBuffer pImage()
	{
		return ( m_pImageBuffer );
	}
	/** Set the pointer to the current image buffer.
	 * 現在のイメージバッファーを設定する。
	 */
	public	void	SetImage( CqImageBuffer pImage )
	{
		m_pImageBuffer = pImage;
	}
	
	// Handle various coordinate system transformation requirements.
	
//	----------------------------------------------------------------------
	/** Get the matrix to convert between the specified coordinate systems.
	 * 指定された座標系の間でマトリクスを変換させてください。
	 */
	
	public	CqMatrix	matSpaceToSpace		( final String strFrom, final String strTo, final CqMatrix matShaderToWorld, final CqMatrix matObjectToWorld, float time )
	{
		CqMatrix	matResult = new CqMatrix();
		CqMatrix 	matA;// = new CqMatrix();
		CqMatrix	matB;// = new CqMatrix();
		long fhash, thash;
		
		
		// Get the hash keys for From,To spaces
		// 元と先の空間のハッシュキーを取得する
		fhash = strFrom.hashCode();
		thash = strTo.hashCode();
		
		// Get the two component matrices.
		// First check for special cases.
		if ( fhash == ohash ) matA = matObjectToWorld;
		else if ( fhash == shash ) matA = matShaderToWorld;
		else if ( ( fhash == chash ) || ( fhash == cuhash ) )
//			matA = m_pTransCamera->GetMotionObjectInterpolated( time ).Inverse();
			matA = m_pTransCamera.matObjectToWorld( time ).Inverse();
		else
		{
			matA = new CqMatrix();
			WhichMatToWorld( matA, fhash );//matAは参照渡し
		}
		
		
		if ( thash == ohash ) matB = matObjectToWorld.Inverse();
		else if ( thash == shash ) matB = matShaderToWorld.Inverse();
		else if ( ( thash == chash ) || ( thash == cuhash ) )
//			matB = m_pTransCamera->GetMotionObjectInterpolated( time );
			matB = m_pTransCamera.matObjectToWorld( time );
		else
		{
			matB = new CqMatrix();
			WhichMatWorldTo( matB, thash );//matBは参照渡し
		}
		
//		matResult = matB * matA;
		matResult.assignment( matB.multiply(matA) );
		
		return ( matResult );
	}
	
//	----------------------------------------------------------------------
	/** Get the matrix to convert vectors between the specified coordinate systems.
	 * マトリクスに指定された座標系の間のベクトルを変換させてください。
	 */
	public	CqMatrix	matVSpaceToSpace	( final String strFrom, final String strTo, final CqMatrix matShaderToWorld, final CqMatrix matObjectToWorld, float time )
	{
		CqMatrix	matResult = new CqMatrix();
		CqMatrix 	matA;// = new CqMatrix();
		CqMatrix	matB;// = new CqMatrix();
		
		long fhash, thash;
		
		// Get the hash keys for From,To spaces
		fhash = strFrom.hashCode();
		thash = strTo.hashCode();
		
		// Get the two component matrices.
		// First check for special cases.
		if ( fhash == ohash ) matA = matObjectToWorld;
		else if ( fhash == shash ) matA = matShaderToWorld;
		else if ( ( fhash == chash ) || ( fhash == cuhash ) )
//			matA = m_pTransCamera->GetMotionObjectInterpolated( time ).Inverse();
			matA = m_pTransCamera.matObjectToWorld( time ).Inverse();
		else
		{
			matA = new CqMatrix();
			WhichMatToWorld ( matA, fhash );
		}
		
		if ( thash == ohash ) matB = matObjectToWorld.Inverse();
		else if ( thash == shash ) matB = matShaderToWorld.Inverse();
		else if ( ( thash == chash ) || ( thash == cuhash ) )
//			matB = m_pTransCamera->GetMotionObjectInterpolated( time );
			matB = m_pTransCamera.matObjectToWorld( time );
		else
		{
			matB = new CqMatrix();
			WhichMatWorldTo ( matB, thash );
		}
		
//		matResult = matB * matA;
		matResult = matB.multiply(matA);
		
		
//		if (memcmp((void) oldkey[0].mpElements(), (void) matResult.pElements(), sizeof(Tqfloat) * 16) != 0)
		if (!oldkey[0].equals(matResult))
		{
			oldkey[0] = matResult;
//			matResult[ 3 ][ 0 ] = matResult[ 3 ][ 1 ] = matResult[ 3 ][ 2 ] = matResult[ 0 ][ 3 ] = matResult[ 1 ][ 3 ] = matResult[ 2 ][ 3 ] = 0.0;
//			matResult[ 3 ][ 3 ] = 1.0;
			matResult.m_aaElement[3][0] = matResult.m_aaElement[3][1] = matResult.m_aaElement[3][2] = matResult.m_aaElement[0][3] = matResult.m_aaElement[1][3] = matResult.m_aaElement[2][3] = 0.0f;
			matResult.m_aaElement[3][3] = 1.0f;
			
			oldresult[0] = matResult;
			
		} else
		{
			return oldresult[0];
		}
		return ( matResult );
	}
	
	//	  ----------------------------------------------------------------------
	/** Get the matrix to convert normals between the specified coordinate systems.
	 * マトリクスに指定された座標系の間の標準を変換させてください。
	 */
	public	CqMatrix	matNSpaceToSpace	( final String strFrom, final String strTo, final CqMatrix matShaderToWorld, final CqMatrix matObjectToWorld, float time )
	{
		CqMatrix	matResult = new CqMatrix();
		CqMatrix	matA ;//= new CqMatrix();
		CqMatrix	matB ;//= new CqMatrix();
		
		long fhash, thash;
		
		// Get the hash keys for From,To spaces
		fhash = strFrom.hashCode();
		thash = strTo.hashCode();
		
		// Get the two component matrices.
		// First check for special cases.
		if ( fhash == ohash ) matA = matObjectToWorld;
		else if ( fhash == shash ) matA = matShaderToWorld;
		else if ( ( fhash == chash ) || ( fhash == cuhash ) )
//			matA = m_pTransCamera->GetMotionObjectInterpolated( time ).Inverse();
			matA = m_pTransCamera.matObjectToWorld( time ).Inverse();
		else
		{
			matA = new CqMatrix();
			WhichMatToWorld ( matA, fhash );
		}
		
		if ( thash == ohash ) matB = matObjectToWorld.Inverse();
		else if ( thash == shash ) matB = matShaderToWorld.Inverse();
		else if ( ( thash == chash ) || ( thash == cuhash ) )
//			matB = m_pTransCamera->GetMotionObjectInterpolated( time );
			matB = m_pTransCamera.matObjectToWorld( time );
		else
		{
			matB = new CqMatrix();
			WhichMatWorldTo ( matB, thash );
		}
		
		
		
		matResult = matB.multiply(matA);
		
		//	        if (memcmp((void ) oldkey[1].pElements(), (void ) matResult.pElements(), sizeof(TqFloat) * 16) != 0)
		if ( !oldkey[1].equals(matResult))
		{
			oldkey[1] = matResult;
			matResult.m_aaElement[3][0] = matResult.m_aaElement[3][1] = matResult.m_aaElement[3][2] = matResult.m_aaElement[0][3] = matResult.m_aaElement[1][3] = matResult.m_aaElement[2][3] = 0.0f;
			matResult.m_aaElement[3][3]= 1.0f;
			matResult = matResult.Inverse().Transpose();
			oldresult[1] = matResult;
			
		} else
		{
			return oldresult[1];
		}
		
		return ( matResult );
	}
	
	
	
	public float[]	GetFloatOption( String strName, String strParam )
	{
		return ( optCurrent().GetFloatOption( strName, strParam ) );
	}

	public int[]	GetIntegerOption( String strName, String strParam )
	{
		return ( optCurrent().GetIntegerOption( strName, strParam ) );
	}

	public String[] GetStringOption( String strName, String strParam )
	{
		return ( optCurrent().GetStringOption( strName, strParam ) );
	}

	public CqVector3D[]	GetPointOption( String strName, String strParam )
	{
		return ( optCurrent().GetPointOption( strName, strParam ) );
	}

	public CqColor[]	GetColorOption( String strName, String strParam )
	{
		return ( optCurrent().GetColorOption( strName, strParam ) );
	}

	public	p_float[]	GetFloatOptionWrite( String strName, String strParam )
	{
		return ( optCurrent().GetFloatOptionWrite( strName, strParam ) );
	}

	public	p_int[]	GetIntegerOptionWrite( String strName, String strParam )
	{
		return ( optCurrent().GetIntegerOptionWrite( strName, strParam ) );
	}

	public	p_String[] GetStringOptionWrite( String strName, String strParam )
	{
		return ( optCurrent().GetStringOptionWrite( strName, strParam ) );
	}

	public	CqVector3D[]	GetPointOptionWrite( String strName, String strParam )
	{
		return ( optCurrent().GetPointOptionWrite( strName, strParam ) );
	}

	public	CqColor[]	GetColorOptionWrite( String strName, String strParam )
	{
		return ( optCurrent().GetColorOptionWrite( strName, strParam ) );
	}
	
	public	void	PrintString( String str )
	{
//		std::cout << str;
		System.out.print(str);
	}
	
	public	IqTextureMap GetTextureMap( final String strFileName )
	{
		return ( CqTextureMap.GetTextureMap( strFileName ) );
	}
	public	IqTextureMap GetEnvironmentMap( final String strFileName )
	{
		return ( CqTextureMap.GetEnvironmentMap( strFileName ) );
	}
	public	IqTextureMap GetShadowMap( final String strFileName )
	{
		return ( CqTextureMap.GetShadowMap( strFileName ) );
	}
	public	IqTextureMap GetLatLongMap( final String strFileName )
	{
		return ( CqTextureMap.GetLatLongMap( strFileName ) );
	}
	
	public	boolean	GetBasisMatrix( CqMatrix matBasis, final String name )
	{
		//RtBasis basis;
		float basis[][] = new float[4][4];
		
		if ( RendermanInterface.BasisFromName( basis, name ) )
		{
			matBasis.assignment( basis ) ;
			
			return ( true );
		}
		else
			return ( false );
	}
	
	/** Get a read only reference to the current transformation matrix.
	 * トランスフォームマトリクスの書き込み禁止の参照を得てください。
	 * @return A constant reference to a CqMatrix.<Br>
	 * CqMatrixの一定の参照。 
	 */
	public CqMatrix	matCurrent( float time )
	{
		return ( pconCurrent().matCurrent( time ) );
	}
	
//	----------------------------------------------------------------------
	/** Store the named coordinate system in the array of named coordinate systems, overwrite any existing
	 * with the same name. Returns TqTrue if system already exists.
	 * 命名された座標系の配列で命名された座標系を保存してください。
	 * 同じ名前であらゆる存在を上書きしてください。 
	 * システムが既に存在しているなら、trueを返します。
	 */
	
	public boolean	SetCoordSystem( final String strName, final CqMatrix matToWorld )
	{
//		Search for the same named system in the current list.
		long hash = strName.hashCode();
		for ( int i = 0; i < m_aCoordSystems.size(); i++ )
		{
			if ( m_aCoordSystems.get(i).m_hash == hash )
			{
				m_aCoordSystems.get(i).m_matToWorld = matToWorld;
				m_aCoordSystems.get(i).m_matWorldTo = matToWorld.Inverse();
				return ( true );
			}
		}
		
		// If we got here, it didn't exists.
		m_aCoordSystems.add(new SqCoordSys( strName, matToWorld, matToWorld.Inverse() ) );
		return ( false );
	}
	
	// Function which can be overridden by the derived class.
	// 派生しているクラスからオーバライドすることのできるクラス
	
//	----------------------------------------------------------------------
	/** Initialise the renderer.
	 * レンダラーを初期化する
	 */
	public	void	Initialise()
	{
		ClearSymbolTable();
		FlushShaders();
		
		// Truncate the array of named coordinate systems to just the standard ones.
		m_aCoordSystems.setSize( CoordSystem_Last );
		
		// Clear the output data entries
		m_OutputDataEntries.clear();
		m_OutputDataOffset = 9;		// Cs, Os, depth, coverage, a
		m_OutputDataTotalSize = 9;	// Cs, Os, depth, coverage, a
	}
	
//	----------------------------------------------------------------------
	/** Render all surface in the current list to the image buffer.
	 * イメージバッファーのリストの中にある全てのサーフェースをレンダリングしてください
	 */
	public	void	RenderWorld()
	{
		// Check we have a valid Image buffer
		if ( pImage() == null )
		{
			SetImage( new CqImageBuffer() );
			
		}
		m_pDDManager.OpenDisplays();
		
		pImage().RenderImage();
		
		m_pDDManager.CloseDisplays();
	}
	
//	---------------------------------------------------------------------
	/** Add a new requested display driver to the list.
	 * 新しい要求されたディスプレイドライバをリストに追加してください
	 */
	public	void	AddDisplayRequest( final String name, final String type, final String mode, int modeID, int dataOffset, int dataSize, HashMap<String, Object> mapOfArguments )
	{
		try{
			m_pDDManager.AddDisplay( name, type, mode, modeID, dataOffset, dataSize, mapOfArguments );
		}catch(DisplayNotFoundException dnfe){

			HimawariLogger.outputException( dnfe );
	    	logger.error( dnfe.getMessage() );
		}
	}
	
//	---------------------------------------------------------------------
	/** Clear the list of requested display drivers.
	 *  要求されたディスプレイドライバをリストから取り除いてください。
	 */
	public	void	ClearDisplayRequests()
	{
		m_pDDManager.ClearDisplays();
	}
	
	public	IqDDManager	pDDmanager()
	{
		return ( m_pDDManager );
	}
	
//	----------------------------------------------------------------------
	/** 
	 * イメージバッファーのレンダリングを継続するかを判定するフラグを落とす。
	 */
	public	void	Quit()
	{
		if ( m_pImageBuffer != null)
		{
			// Ask the image buffer to quit.
			m_pImageBuffer.Quit();
		}
	}
	
	public	void UpdateStatus()
	{
		// Aqsis1.0では未実装
	}
	
	/** Get the global statistics class.
	 * グローバルな統計のクラスを手に入れてください。
	 * \return A reference to the CqStats class on this renderer.<br>
	 * このレンダラーのCqStatsのクラスの参照。
	 * 
	 */
	public CqStats	Stats()
	{
		return ( m_Stats );
	}
	
	// Contect change callbacks
	
//	----------------------------------------------------------------------
	/** Find a parameter type declaration and return it.
	 * パラメタ型の宣言を見つけてください、そして、それを返してください。
	 * @param strDecl Character pointer to the name of the declaration to find.
	 * <br> strDecl キャラクターポインタは見つかった宣言の名前を返す。
	 * 
	 */
	public	SqParameterDeclaration FindParameterDecl( final String strDecl ) throws XqException
	{
		CqInlineParse parser = new CqInlineParse();
		String __strDecl = strDecl;
		parser.parse( __strDecl );
		
		
		if( parser.isInline() )
		{
			SqParameterDeclaration Decl = new SqParameterDeclaration();
			Decl.m_strName = parser.getIdentifier();
			Decl.m_Count = parser.getQuantity();
			Decl.m_Type = parser.getType();
			Decl.m_Class = parser.GetClass();
			Decl.m_strSpace = "";	
			// Get the creation function.
			switch ( Decl.m_Class.getValue() )
			{
				case class_constant:
				{
					if ( Decl.m_Count > 1 )
						Decl.m_pCreate = gVariableCreateFuncsConstantArray[ Decl.m_Type.getValue() ];
					else
						Decl.m_pCreate = gVariableCreateFuncsConstant[ Decl.m_Type.getValue() ];
				}
				break;
				
				case class_uniform:
				{
					if ( Decl.m_Count > 1 )
						Decl.m_pCreate = gVariableCreateFuncsUniformArray[ Decl.m_Type.getValue() ];
					else
						Decl.m_pCreate = gVariableCreateFuncsUniform[ Decl.m_Type.getValue() ];
				}
				break;
				
				case class_varying:
				{
					if ( Decl.m_Count > 1 )
						Decl.m_pCreate = gVariableCreateFuncsVaryingArray[ Decl.m_Type.getValue() ];
					else
						Decl.m_pCreate = gVariableCreateFuncsVarying[ Decl.m_Type.getValue() ];
				}
				break;
				
				case class_vertex:
				{
					if ( Decl.m_Count > 1 )
						Decl.m_pCreate = gVariableCreateFuncsVertexArray[ Decl.m_Type.getValue() ];
					else
						Decl.m_pCreate = gVariableCreateFuncsVertex[ Decl.m_Type.getValue() ];
				}
				break;
				
				case class_facevarying:
				{
					if ( Decl.m_Count > 1 )
						Decl.m_pCreate = gVariableCreateFuncsFaceVaryingArray[ Decl.m_Type.getValue() ];
					else
						Decl.m_pCreate = gVariableCreateFuncsFaceVarying[ Decl.m_Type.getValue() ];
				}
				break;
				
				default:
				{
					// left blank to avoid compiler warnings about unhandled types
					break;	                    
				}
			}
			return ( Decl );
		}
		
//		String strName = strDecl;
		
		long hash = strDecl.hashCode() ;
		for( SqParameterDeclaration spd : m_Symbols ) //java ではm_Symbolsをコピーしなくてもスピードは変わらないのでメモリの節約
		{
			long hash2 = spd.m_strName.hashCode();
			if ( hash == hash2 )
				return ( spd );
			
		}
		
		return ( new SqParameterDeclaration( "", new EqVariableType(type_invalid),new EqVariableClass(class_invalid), 0, null, "" ) );
	}
	
	/** 
	 * Add a parameter type declaration to the local declarations.
	 * 局所宣言にパラメタ型の宣言を加えてください。
	 * 
	 * @param strName Character pointer to parameter name.
	 * @param strType Character pointer to string containing the type identifier.
	 */
	public	void	AddParameterDecl( final String strName, final String strType )
	{
		String strDecl = strType;
		strDecl += " ";
		strDecl += strName;
		SqParameterDeclaration Decl;
		try{
			Decl = FindParameterDecl( strDecl );
		}catch( XqException e ){
			logger.error( e.strReason() + "\n" );
			return;
		}
		
		// Put new declaration at the top to make it take priority over pervious
		// 透した状態で優先権を引き継がせる先端の新しい宣言を置いてください。
//		m_Symbols.insert( m_Symbols.begin(), Decl );
		m_Symbols.add( 0, Decl );
	}
	
	public	void	ClearSymbolTable()
	{
		m_Symbols.clear();
	}
	
	/** Get the list of currently registered shaders.
	 * @return A reference to a list of CqShaderRegister classes.
	 */
	
//	---------------------------------------------------------------------
	/** Find a shader of the specified type with the specified name.
	 * If not found, try to load one.
	 */    
	public IqShader CreateShader( final String strName, EqShaderType type )
	{
//		construct the key which is used to index the shader
		CqShaderKey key = new CqShaderKey( strName, type );
		
		// first, look for the shader of the appropriate type and name in the
		//  map of shader "templates"
		if ( m_Shaders.get( key.getkey() ) != null )
		{
		// the shader template is present, so return its clone
			return m_Shaders.get( key.getkey() ).Clone() ;
		}
		
		// we now create the shader...
		// 私たちはシェーダを作ります
		
		// search in the current directory first
		String strFilename = strName;
		strFilename += RI_SHADER_EXTENSION;
		CqRiFile SLXFile = new CqRiFile( strFilename, "shader" );
		if ( SLXFile.IsValid() )
		{
			IqShader pRet = new CqShaderVM();
			
			CqShaderVM pShader = (CqShaderVM)( pRet );
			final String[] poptDSOPath = QGetRenderContext().optCurrent().GetStringOption( "searchpath", "dsolibs" );
			
			logger.info("DSO lib path set to \"" + poptDSOPath + "\"\n");
			
			//pShader.SetDSOPath( poptDSOPath );
			
			String strRealName =  SLXFile.strRealName() ;
			
			
			try {
//				FileReader fr;
//				fr = new FileReader( strRealName);
				Reader fr;
		    	if(Globalmain.g_enc_flag.value){
		    		fr = CellCipher.getReader(strRealName);
		    	}
		    	else{
		    		fr = new FileReader(strRealName);
		    	}
		    	
				StreamTokenizer SLXst = new StreamTokenizer(new BufferedReader(fr));
				logger.info("Loading shader \"" + strName + "\" from file \"" + strRealName + "\"\n");
				
				pShader.SetstrName( strName );
				pShader.LoadProgram( SLXst );
				
				//2006.08.31 nttdata add
				fr.close();
				SLXFile.Close();
				
				// check shader type
				if( pShader.Type().getValue() != type.getValue() )
				{
					String typeName = "unkown";
					for( int i=0; i<gShaderTypeNames.length; i++ ){
						if( gShaderTypeNames[i].type.getValue() == type.getValue() ){
							typeName = gShaderTypeNames[i].name;
						}
					}
						
					logger.error( "Shader Type Mismatch [" +strName+ "] ExpectedType[" +typeName+ "] \n" );
					return null;
				}
				
			} catch (FileNotFoundException e) {
				HimawariLogger.outputException( e );
			} catch (IOException e) {
				HimawariLogger.outputException( e );
			}
			
			// add the shader to the map as a template and return its 
			//  clone
			m_Shaders.put(key.getkey(), pRet);
			return pRet.Clone();
		}
		else
		{
			if ( ( strName.compareTo( "null" ) != 0 ) && ( strName.compareTo("_def_" ) != 0) )
			{
				String strError = new String("Shader \"" + strName + "\" not found\n");
				logger.error( strError );
			}
			if ( type.getValue() == Type_Surface )
			{
				IqShader pRet = new CqShaderVM() ;
				
				CqShaderVM pShader = (CqShaderVM)( pRet );
				pShader.SetstrName( "null" );
				pShader.DefaultSurface();
				
				// add the shader to the map and return its clone
				m_Shaders.put(key.getkey(), pRet);
				return pRet.Clone();
			}
			else
			{
			// the boost::shared_ptr analogue of return NULL:
				return null;
			}
		}
	}
	
	/** Flush any registered shaders.
	 * あらゆる登録されたシェーダを洗い流してください。
	 */
	void	FlushShaders()
	{
		//while ( m_Shaders.pFirst() != 0 )
		//    delete( m_Shaders.pFirst() );
		m_Shaders.clear();
	}
	
	/** Set the world to screen matrix.
	 *  ワールドスクリーンのマトリックスを設定する
	 * @param mat The new matrix to use as the world to screen transformation.
	 * <br>　matはワールドスクリーントランスフォームとして使われる、新しいマトリックス
	 */
	public void	SetmatScreen( final CqMatrix mat )
	{
		m_aCoordSystems.get(CoordSystem_Screen).m_matWorldTo = mat;
	}
	
	/** Set the world to NDC matrix.
	 * NDCマトリックスでのワールドの設定
	 * @param mat The new matrix to use as the world to NDC transformation.
	 * ワールドとしてNDCトランスフォームに使用する新しいマトリクスをもつれさせてください。
	 */
	public void	SetmatNDC( final CqMatrix mat )
	{
		m_aCoordSystems.get(CoordSystem_NDC).m_matWorldTo = mat;
	}
	/** Set the world to raster matrix.
	 * ラスタマトリックスでのワールドの設定
	 * @param mat The new matrix to use as the world to raster transformation.
	 * ワールドとしてラスタトランスフォームに使用する新しいマトリクスをもつれさせてください。
	 */
	public void	SetmatRaster( final CqMatrix mat )
	{
		m_aCoordSystems.get(CoordSystem_Raster).m_matWorldTo = mat;
	}
	/** Set the world to camera transform.
	 * カメラトランスフォームにワールドに設定してください。
	 * @param ptrans A pointer to the transformation object which represents the world to camera transform.
	 * カメラ変換に世界を代表する変化物へのptrans Aポインタ。
	 */
	public void	SetCameraTransform( final CqTransform ptrans )
	{
		m_pTransCamera = ptrans;
	}
	/** Get the world to camera tramsform.
	 * 世界をカメラtramsformに手に入れてください。
	 * @return A pointer to the transformation object which represents the world to camera transform.
	 * カメラ変換に世界を代表する変化物へのポインタ。
	 */
	public CqTransform	GetCameraTransform( )
	{
		return( m_pTransCamera );
	}
	/** Set the initial object transformation, this transform takes into account motion imparted by the camera.
	 *  This is used when resetting the object transform in prepareation for a RiTransform.
	 *  初期の物のトランスフォームを設定してください、そして、このトランスフォームはカメラによって伝えられたアカウント動きを連れていきます。
	 *  RiTransformのためにprepareationに物の変換をリセットするとき、これは使用されています。
	 * @param ptrans A pointer to the transformation object which represents the initial object space transform.
	 * 初期のオブジェクト宇宙変換を表す変換オブジェクトへのptrans A指針。
	 */
	public	void	SetDefObjTransform( final CqTransform ptrans )
	{
		m_pTransDefObj = ptrans;
	}
	/** Get initial object transformation.
	 * 初期のオブジェクト変換を得てください。
	 * @return A pointer to the transformation object which represents the initial object space transform.
	 * 初期のオブジェクト宇宙変換を表す変換オブジェクトへの指針。
	 */
	public	CqTransform	GetDefObjTransform( )
	{
		return( m_pTransDefObj );
	}
	
	/** Set the lens data associated with depth of field effects.
	 * 被写界深度効果に関連しているレンズデータを設定してください。
	 * @param fstop The f-stop of the lens.
	 * @param focalLength The size of the lens.
	 * @param focalDistance The distance at which everything is in focus.
	 */
	public void	SetDepthOfFieldData( float fstop, float focalLength, float focalDistance )
	{
		m_UsingDepthOfField = (fstop < FLT_MAX);
		if (fstop < FLT_MAX)
		{
			float lensDiameter = focalLength / fstop;
			m_DofMultiplier = (float) (0.5 * lensDiameter * focalDistance / (focalDistance + lensDiameter));
			m_OneOverFocalDistance = (float) (1.0 / focalDistance);
		}
	}
	
	/** Find out if we are using depth of field or not.
	 * 私たちが被写界深度を使用しているかどうか調べてください。
	 * @return TqTrue if depth of field is turned on.
	 * trueは被写界深度であるならつけられています。
	 */
	public boolean	UsingDepthOfField( )
	{
		return m_UsingDepthOfField;
	}
	
	/** Set the scale for dof to transform the coc from camera to raster space
	 * cocをカメラからラスタ空間に変えるdofにスケールを設定してください。
	 * @param x the scale in x
	 * @param y the scale in y
	 */
	public void SetDepthOfFieldScale( float x, float y )
	{
		m_DepthOfFieldScale.x( x );
		m_DepthOfFieldScale.y( y );
	}
	
	/** Get the circle of confusion at the specified depth
	 * 指定された深さにおける錯乱円を得てください。
	 * @param depth The depth in camera space
	 * 深さはカメラスペースの深さです。
	 * @return A 2d vector with the radius of the coc in raster space along x and y.
	 * xとyに沿ったラスタ空間における、cocの半径に従った2dベクトル。 
	 */
	public CqVector2D GetCircleOfConfusion( float depth )
	{
		assert(m_UsingDepthOfField);
		float c = m_DofMultiplier * Math.abs(1.0f / depth - m_OneOverFocalDistance);
//		return new CqVector2D( m_DepthOfFieldScale * c );
		return m_DepthOfFieldScale.mul(c);
	}
	//nttdata 高速化
	public void GetCircleOfConfusion( float depth ,CqVector2D vec2)
	{
		assert(m_UsingDepthOfField);
		float c = m_DofMultiplier * Math.abs(1.0f / depth - m_OneOverFocalDistance);
//		return new CqVector2D( m_DepthOfFieldScale * c );
		vec2.x = m_DepthOfFieldScale.x * c ;
		vec2.y = m_DepthOfFieldScale.y * c ;
	}
	
	//void	RegisterShader( const char* strName, EqShaderType type, IqShader* pShader );
	//CqShaderRegister* FindShader( const char* strName, EqShaderType type );
	
//	---------------------------------------------------------------------
	/** Returns a pointer to the default surface.
	 * デフォルトサーフェースを返す。
	 */
	public IqShader getDefaultSurfaceShader()
	{
		// construct a key to index the default surface
		CqShaderKey key = new CqShaderKey( "_def_", new EqShaderType( Type_Surface ) );
		
		// check for the shader in the existing map
		IqShader pMapCheck = CreateShader( "_def_", new EqShaderType( Type_Surface ) );
		if (pMapCheck != null)
			return pMapCheck;
		
		// insert the default surface template into the map
		IqShader pRet = new CqShaderVM();
		CqShaderVM pShader = (CqShaderVM)( pRet );
		pShader.SetstrName( "_def_" );
		pShader.DefaultSurface();
		pShader.matCurrent().assignment( matCurrent(Time()));
		pShader.PrepareDefArgs();
//		m_Shaders[key] = pRet;
		m_Shaders.put( key.getkey(), pRet );
		
		// return a clone of the default surface template
		return pRet.Clone();
	}
	
	public class SqOutputDataEntry
	{
		int	m_Offset;
		int	m_NumSamples;
		int	m_Type;
	}
	
	public int	RegisterOutputData( final String name) throws XqException
	{
		int offset;
		if( ( offset = OutputDataIndex( name ) ) != -1 )
			return(offset);
		
		SqParameterDeclaration Decl;
		try
		{
			Decl = FindParameterDecl( name );
		}
		catch( XqException e )
		{
			HimawariLogger.outputException( e );
			return(-1);
		}
		if( Decl.m_Type.getValue() != type_invalid )
		{
			if( Decl.m_Count != 1 )
				throw new XqException("Error: Cannot use array as an output type");
			
			SqOutputDataEntry DataEntry = new SqOutputDataEntry();
			int NumSamples = 0;
			switch( Decl.m_Type.getValue() )
			{
			case type_float:
			case type_integer:
				NumSamples = 1;
				break;
			case type_point:
			case type_normal:
			case type_vector:
			case type_hpoint:
				NumSamples = 3;
				break;
			case type_color:
				// \note: Color is handled separately in case we ever support RiColorSamples
				NumSamples = 3;
				break;
			case type_matrix:
				NumSamples = 16;
				break;
			case type_string:
				throw new XqException("Error: String not valid as an output type");
//				break;
			default:
				break;	// left blank to avoid compiler warnings about unhandled types
			}
			
			DataEntry.m_Offset = m_OutputDataOffset;
			DataEntry.m_NumSamples = NumSamples;
			DataEntry.m_Type = Decl.m_Type.getValue();
			m_OutputDataOffset += NumSamples;
			m_OutputDataTotalSize += NumSamples;
			
			// Add the new entry to the map, using the Decl name as the key.
			// 新しいエントリーをマップに追加します、Declの名前とそのキーを使用します。
//			m_OutputDataEntries[Decl.m_strName] = DataEntry;
			m_OutputDataEntries.put(Decl.m_strName,DataEntry);
			
			return( DataEntry.m_Offset );
		}
		
		return( -1 );
	}
	public int	OutputDataIndex( final String name )
	{
		SqParameterDeclaration Decl = new SqParameterDeclaration();
		try
		{
			Decl = FindParameterDecl( name );
		}
		catch( XqException e )
		{
			HimawariLogger.outputException( e );
			return(-1);
		}
		if( Decl.m_Type.getValue() != type_invalid )
		{
			SqOutputDataEntry entry = m_OutputDataEntries.get(Decl.m_strName);
			if( entry != null )
				return( entry.m_Offset);
		}
		return( -1 );
	}
	
	public int	OutputDataSamples( final String name )
	{
		SqParameterDeclaration Decl = new SqParameterDeclaration();
		try
		{
			Decl = FindParameterDecl( name );
		}
		catch( XqException e )
		{
			HimawariLogger.outputException( e );
			return(-1);
		}
		if( Decl.m_Type.getValue() != type_invalid )
		{
			SqOutputDataEntry entry = m_OutputDataEntries.get(Decl.m_strName);
			if( entry != null )
				return( entry.m_NumSamples);
		}
		return( 0 );
	}
	
	public int	OutputDataType(final String name )
	{
		SqParameterDeclaration Decl = new SqParameterDeclaration();
		try
		{
			Decl = FindParameterDecl( name );
			
		}
		catch( XqException e )
		{
			HimawariLogger.outputException( e );
			return(-1);
		}
		if( Decl.m_Type.getValue() != type_invalid )
		{
			SqOutputDataEntry entry = m_OutputDataEntries.get(Decl.m_strName);
			if( entry != null )
				return( entry.m_Type);
		}
		return( 0 );
	}
	
	public HashMap<String, SqOutputDataEntry> GetMapOfOutputDataEntries()
	{
		return( m_OutputDataEntries );
	}
	
	/** Get the number if samples needed to fulfil the display requests.
	 */
	public int	GetOutputDataTotalSize()
	{
		return( m_OutputDataTotalSize );
	}
	
	public	void	SetCurrentFrame( int FrameNo )
	{
		m_FrameNo = FrameNo;
	}
	public int	CurrentFrame()
	{
		return( m_FrameNo );
	}
	
	public CqObjectInstance	pCurrentObject()
	{
		if( m_bObjectOpen )
//			return(m_ObjectInstances.back());
			return (m_ObjectInstances.get( m_ObjectInstances.size()-1 ));
		else
			return( null );
	}
	
	public CqObjectInstance OpenNewObjectInstance()
	{
		assert( !m_bObjectOpen );
		m_bObjectOpen = true;
		CqObjectInstance pNew = new CqObjectInstance();
		m_ObjectInstances.add(pNew);
		
		return( pNew );
	}
	public void InstantiateObject( CqObjectInstance handle )
	{
//		Ensure that the object passed in is valid.
//		if( std::find(m_ObjectInstances.begin(), m_ObjectInstances.end(), handle ) != m_ObjectInstances.end() )
		if(m_ObjectInstances.indexOf(handle) != -1)
			handle.RecallInstance(); 
	}
	
	public void CloseObjectInstance()
	{
		m_bObjectOpen = false;
	}
	
	/** Get a pointer to the error handler function.
	 */
	public Method	pErrorHandler()
	{
		return ( m_pErrorHandler );
	}
	/** Set the error handler function to use.
	 * @param perrorhandler A pointer to a function which conforms to RtErrorFunc.
	 */
	public void	SetpErrorHandler( Method perrorhandler )
	{
		m_pErrorHandler = perrorhandler;
	}
	
	/** Get a pointer to the progress handler function.
	 */
	public Method	pProgressHandler()
	{
		return ( m_pProgressHandler );
	}
	/** Set the progress handler function to use.
	 * @param pprogresshandler A pointer to a function which conforms to RtProgressFunc.
	 */
	public void	SetpProgressHandler( Method pprogresshandler )
	{
		m_pProgressHandler = pprogresshandler;
	}
	
	public Method	pPreRenderFunction()
//	public RtFunc	pPreRenderFunction()
	{
		return ( m_pPreRenderFunction );
	}
	/** Set a function to call just before initiating the render.
	 *  This function will be called during the RiWorldEnd command, the state will be World.
	 * @param pfunction A pointer to a function which conforms to RtFunc.
	 */
	public void	SetpPreRenderFunction( Method pfunction )
//	public void	SetpPreRenderFunction( RtFunc pfunction )
	{
		m_pPreRenderFunction = pfunction;
	}
	
	public Method	pPreWorldFunction()
//	public RtFunc	pPreWorldFunction()
	{
		return ( m_pPreWorldFunction );
	}
	/** Set a function to call just before starting the world definition.
	 *  This function will be called during the RiWorldBegin command, the state will be Begin/End or Frame.
	 * \param pfunction A pointer to a function which conforms to RtFunc.
	 * ワールドの定義が始まる以前に機能を設定してください。
	 * この機能はRiWorldBeginこまのどの中で呼ばれるでしょう。その状態はbegin/endかフレームになるでしょう。
	 * RtFuncに従う機能へのpfunction Aポインタ。
	 */
	
	public void	SetpPreWorldFunction( Method pfunction )
//	public void	SetpPreWorldFunction( RtFunc pfunction )
	{
		m_pPreWorldFunction = pfunction;
	}
	
	/** Get a pointer to the raytracing subsystem
	 * レイトレーサーのサブシステムのポインタを取得
	 */
	public IqRaytrace	pRaytracer()
	{
		return( m_pRaytracer );
	}
	
	public boolean	IsWorldBegin()
	{
		return(m_fWorldBegin);
	}
	
	public void SetWorldBegin()
	{
		m_fWorldBegin = true;
	}
	
	public void SetWorldBegin(boolean begin)
	{
		m_fWorldBegin = begin;
	}
	
	private	CqModeBlock		m_pconCurrent ;					///< 現在のカレントコンテキストへのポインタ	Pointer to the current context.
	private	CqStats			m_Stats = new CqStats();						///< グローバルステータス　	Global statistics.
	private   	CqAttributes	m_pAttrDefault ;					///< デフォルトのアトリビュート	Default attributes.
	private   	CqTransform		m_pTransDefault ;				///< デフォルトのトランスフォーム		Default transformation.
	private   	CqImageBuffer	m_pImageBuffer ;					///<　現在のイメージバッファへのポインタ Pointer to the current image buffer.
	
	private   	IqDDManager		m_pDDManager ;
	
	private   	EqRenderMode	m_Mode = new EqRenderMode();
	//CqList<CqShaderRegister> m_Shaders;				///< List of registered shaders.
	// JSM:
	private    	HashMap< Long, IqShader > m_Shaders = new HashMap< Long , IqShader >();
	
//	private    	boolean		m_fSaveGPrims;
	private    	CqTransform		m_pTransCamera ;					///< カメラのトランスフォーム	The camera transform.
	private		CqTransform		m_pTransDefObj ;					///< オブジェクトのトランスフォーム	The initial transformation for objects.
	private		boolean			m_fWorldBegin;
	private    	STLVector<SqParameterDeclaration>	m_Symbols = new STLVector<SqParameterDeclaration>(SqParameterDeclaration.class);	///< Symbol table.
	
	private    	float			m_DofMultiplier;
	private    	float			m_OneOverFocalDistance;
	private    	boolean			m_UsingDepthOfField;
	private    	CqVector2D		m_DepthOfFieldScale = new CqVector2D();
	
//	---------------------------------------------------------------------
	/** Which matrix will be used in ToWorld
	 * どのマトリクスがToWorldで使用されるでしょうか。
	 */
	private int awhich = 0;
	private		void WhichMatToWorld(CqMatrix matA, long thash )
	{
//		static int awhich = 0;
		int tmp = awhich;
		
		
		for ( ; awhich >= 0; awhich-- )
		{
			if ( m_aCoordSystems.get( awhich ).m_hash == thash )
			{
				matA.assignment( m_aCoordSystems.get( awhich ).m_matToWorld );
				return ;
			}
		}
		
		int size = m_aCoordSystems.size() - 1;
		for ( awhich = size; awhich > tmp; awhich-- )
		{
			if ( m_aCoordSystems.get( awhich ).m_hash == thash )
			{
				matA.assignment( m_aCoordSystems.get( awhich ).m_matToWorld );
				break;
				
			}
		}
	}
	
	
//	---------------------------------------------------------------------
	/** Which matrix will be used in WorldTo
	 * どのマトリクスがWorldToで使用されるでしょうか。
	 */
	private int bwhich = 0;
	private void WhichMatWorldTo(CqMatrix matB, long thash)
	{
//		static int bwhich = 0;
		int tmp = bwhich;
		
		for ( ; bwhich >= 0; bwhich-- )
		{
			if ( m_aCoordSystems.get( bwhich ).m_hash == thash )
			{
				matB.assignment( m_aCoordSystems.get( bwhich ).m_matWorldTo );
				return ;
			}
		}
		
		int size = m_aCoordSystems.size() - 1;
		for ( bwhich = size; bwhich > tmp; bwhich-- )
		{
			if ( m_aCoordSystems.get( bwhich ).m_hash == thash )
			{
				matB.assignment( m_aCoordSystems.get( bwhich ).m_matWorldTo );
				break;
			}
		}
	}
	
	private     HashMap<String, SqOutputDataEntry>	m_OutputDataEntries = new HashMap<String, SqOutputDataEntry>();
	private    	int		m_OutputDataOffset;
	private   	int		m_OutputDataTotalSize;
	
	private    	CqOptions 		m_pOptDefault = new CqOptions();	///< Pointer to default options.
	private   	int				m_FrameNo;
	private		STLVector<CqObjectInstance>	 m_ObjectInstances = new STLVector<CqObjectInstance>(CqObjectInstance.class);
	private		boolean		m_bObjectOpen;
	
	private		Method			m_pErrorHandler;		///< A pointer to the error hadling function.
	private    	Method			m_pProgressHandler;		///< A pointer to the progress hadling function.
	private    	Method			m_pPreRenderFunction;	///< A pointer to the function called just prior to rendering.
	private    	Method			m_pPreWorldFunction;	///< A pointer to the function called just prior to starting the world.
	
	private		IqRaytrace		m_pRaytracer;			///< Pointer to the raytracing subsystem interface.
	
	public		STLVector<SqCoordSys>	 m_aCoordSystems = new STLVector<SqCoordSys>(SqCoordSys.class);	///< List of reistered coordinate systems.
	private HimawariLogger logger = HimawariLogger.getLogger();

	
}
