#include"CLightWaveObject.h"

#include"../../../Auxiliary/CString.h"
#include"../../../Auxiliary/Debug/CTrace.h"
#include"../../../Auxiliary/Debug/CAssert.h"

#include<stdio.h>


namespace Maid
{
	/*!
	 	@class	CLightWaveObject CLightWaveObject.h
	 	@brief	lwo形式のファイルを読み込むクラス
	\n			１モデル１サーフェイス＆テクスチャはＵＶ　でないとうまく読めません
	 */


static	inline unt32 StrLen( const mstring& str )	
	{
		// lw の文字列の長さは'\0'をいれて全て偶数である必要がある
		return (unt32)(str.length()+1+1)&~1;
	}
static	inline unt16 Read_U08( CFileRead& hFile )
	{
		return hFile.Read1ByteBigEndian();
	}
static	inline unt16 Read_U16( CFileRead& hFile )
	{
		return hFile.Read2ByteBigEndian();
	}
static	inline unt32 Read_U32( CFileRead& hFile )
	{
		return hFile.Read4ByteBigEndian();
	}

static	inline float Read_F32( CFileRead& hFile )
	{
		return hFile.ReadfloatBigEndian();

	}
static	inline unt32 Read_VX( CFileRead& hFile )
	{
		unt32 index = Read_U08(hFile);

		if( index == 0xFF )
		{
			index = hFile.Read3ByteBigEndian();
		}else
		{
			index = (index<<8) | hFile.Read1ByteBigEndian();

		}
		return index;
	}

static	inline mstring Read_Str( CFileRead& hFile )
	{
		return hFile.ReadString(2);
	}
static	inline unt32 Read_ID( CFileRead& hFile )
	{
		return hFile.Read4ByteLittleEndian();
	}

static	inline mstring ConvertID( unt32 ID )
	{
		char buf[5]={0};
		sprintf( buf, "%c%c%c%c", ID>>0, ID>>8, ID>>16, ID>>24 );
		return CString::ConvertSJIStoMAID(buf);
	}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! ファイルからメモリへロード
/*!
	@param	[i ]	ファイル名
 */
void CLightWaveObject::Load( const mstring& FileName )
{
	// 読み込んだ内容を各チャンクに分ける

	CFileRead hFile;

	hFile.OpenOnmemory( FileName );

	MySTL::vector<CHUNKDATA> ChunkList;
	{
		const unt32 form = Read_ID(hFile);
		const unt32 len  = Read_U32(hFile);
		const unt32 lwo2 = Read_ID(hFile);

		MAID_ASSERT( form!=Str2Binary32('F','O','R','M'), MAIDTEXT("Formではありません") );
		MAID_ASSERT( lwo2!=Str2Binary32('L','W','O','2'), MAIDTEXT("LWO2ではありません") );

		//	わざわざ解析関数なんて作らなくても
		//	スタック構造を持ったIFFリーダーで十分かも(・ω・)
		Parse( hFile, ChunkList );
	}

	// 分割したらそれぞれのチャンクごとで解析していく
	LAYER* pLayer = NULL;
	for( int i=0; i<(int)ChunkList.size(); ++i )
	{
		const CHUNKDATA& dat = ChunkList[i];

		hFile.SetPosition( dat.Pos );

//		MAID_TRACE( "ID:" << ConvertID(dat.Name) );
		switch( dat.Name )
		{
		case Str2Binary32('T','A','G','S'): { LoadTAGS( hFile, dat, m_Document ); }break;
		case Str2Binary32('L','A','Y','R'): { pLayer = LoadLAYR( hFile, dat, m_Document );}break;
		case Str2Binary32('P','N','T','S'): { LoadPNTS( hFile, dat, *pLayer ); }break;
		case Str2Binary32('B','B','O','X'): { LoadBBOX( hFile, dat, *pLayer ); }break;
		case Str2Binary32('P','O','L','S'): { LoadPOLS( hFile, dat, *pLayer ); }break;
		case Str2Binary32('P','T','A','G'): { LoadPTAG( hFile, dat, *pLayer ); }break;
		case Str2Binary32('V','M','A','P'): { LoadVMAP( hFile, dat, *pLayer ); }break;
		case Str2Binary32('V','M','A','D'): { LoadVMAD( hFile, dat, *pLayer ); }break;
		case Str2Binary32('S','U','R','F'): { LoadSURF( hFile, dat, m_Document ); }break;
		case Str2Binary32('C','L','I','P'): { LoadCLIP( hFile, dat, m_Document ); }break;
		}

	}
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定したデータを同じレベルのチャンクリストに分割する
/*!
 	@param	hFile		[i ] 読み込むファイル
 	@param	ChunkList	[ o] 分割されたチャンクリスト
 */
void CLightWaveObject::Parse( CFileRead& hFile, MySTL::vector<CHUNKDATA>& ChunkList )
{
	ChunkList.clear();

	while( true )
	{
		if( hFile.IsEOF() ) { break; }

		CHUNKDATA dat;

		dat.Name = Read_ID(hFile);
		dat.Size = Read_U32(hFile);
		dat.Pos  = hFile.GetPosition();

//		MAID_TRACE( "ID:" << ConvertID(dat.Name) << " "<< dat.Size << " " << dat.Pos );

		ChunkList.push_back( dat );

		hFile.Seek( dat.Size, IFileRead::POSITION_CURRENT );
	}
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 指定したデータを同じレベルのサブチャンクリストに分割する
/*!
 *	\param	pSource		[i ] 分割するデータ
 *	\param	EndPos		[i ] pSourceの長さ
 *	\param	ChunkList	[ o] 分割されたチャンクリスト
 */
void CLightWaveObject::ParseSub( CFileRead& hFile, int EndPos, MySTL::vector<CHUNKDATA>& ChunkList )
{
	// サブチャンクと普通のチャンクとの違いは
	// データの長さを記録している変数のサイズが違う
	ChunkList.clear();

	while( true )
	{
		if( EndPos <= hFile.GetPosition() ) { break; }

		CHUNKDATA dat;

		dat.Name = Read_ID(hFile);
		dat.Size = Read_U16(hFile);
		dat.Pos  = hFile.GetPosition();

		ChunkList.push_back( dat );

		hFile.Seek( dat.Size, IFileRead::POSITION_CURRENT );
	}
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'TAGS' チャンクの読み取り
/*!
 	@param	hFile	[i ] ファイルポインタ
  	@param	dat		[i ] チャンクデータ
	@param	doc		[ o] 出力先
 */
void CLightWaveObject::LoadTAGS( CFileRead& hFile, const CHUNKDATA& dat, DOCUMENT& doc )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('T','A','G','S'), "TAGS チャンクではありません" );


	const int end = dat.Pos + dat.Size;

	while( true )
	{
		if( end<=hFile.GetPosition() ) { break; }

		doc.TagList.push_back(Read_Str(hFile));
	}
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'LAYR' チャンクの読み取り
/*!
 	@param	hFile	[i ] ファイルポインタ
  	@param	dat		[i ] チャンクデータ
	@param	doc		[ o] 出力先
 
 	@return 新しく作成したこのモデルの番号
 */
CLightWaveObject::LAYER* CLightWaveObject::LoadLAYR( CFileRead& hFile, const CHUNKDATA& dat, DOCUMENT& doc )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('L','A','Y','R'), "LAYR チャンクではありません" );

	LAYER layer;

	layer.Index  = Read_U16(hFile);
	layer.Flag   = Read_U16(hFile);
	layer.Pivot.x= Read_F32(hFile);
	layer.Pivot.y= Read_F32(hFile);
	layer.Pivot.z= Read_F32(hFile);

	layer.Name	= Read_Str(hFile);

	doc.LayerList.push_back( layer );

	return &(doc.LayerList.back());
}



/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'PNTS' チャンクの読み取り ( 頂点配列 ）
/*!
 	@param	hFile	[i ] ファイルポインタ
 	@param	dat		[ o] 出力先
 	@param	Layer	[i ] この関数で読み込んだものの設定先モデル番号
 */
void CLightWaveObject::LoadPNTS( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('P','N','T','S'), "PNTS チャンクではありません" );

	MySTL::vector<POINT3DF>& List = Layer.PointList;
	List.resize( dat.Size / sizeof(POINT3DF) ); // <- 12 == sizeof(Vector3D)

	for( int i=0; i<(int)List.size(); ++i )
	{
		POINT3DF& vec = List[i];

		vec.x= Read_F32(hFile);
		vec.y= Read_F32(hFile);
		vec.z= Read_F32(hFile);
	}
}



/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'BBOX' チャンクの読み取り ( バウンディングボックス ）
/*!
 	@param	hFile	[i ] ファイルポインタ
 	@param	dat		[ o] 出力先
 	@param	Layer	[i ] この関数で読み込んだものの設定先モデル番号
 */
void CLightWaveObject::LoadBBOX( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('B','B','O','X'), "BBOX チャンクではありません" );

	RECT3DF& box = Layer.BoundingBox;

	box.x = Read_F32(hFile);
	box.y = Read_F32(hFile);
	box.z = Read_F32(hFile);
	box.w = Read_F32(hFile) - box.x;
	box.h = Read_F32(hFile) - box.y;
	box.d = Read_F32(hFile) - box.z;
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'POLS' チャンクの読み取り ( インデックス配列 ）
/*!
 	@param	hFile	[i ] ファイルポインタ
 	@param	dat		[ o] 出力先
 	@param	Layer	[i ] この関数で読み込んだものの設定先モデル番号
 */
void CLightWaveObject::LoadPOLS( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('P','O','L','S'), "POLS チャンクではありません" );


	LAYER::POLS pols;

	const unt32 ID = Read_ID(hFile);

	switch( ID )
	{
	case Str2Binary32('F','A','C','E'): { pols.Type = LAYER::POLS::FACE;	}break;
//	case Str2Binary32('C','U','R','V'): { pols.Type = LAYER::POLS::CURV;	}break;
//	case Str2Binary32('P','T','C','H'): { pols.Type = LAYER::POLS::PTCH;	}break;
//	case Str2Binary32('M','B','A','L'): { pols.Type = LAYER::POLS::MBAL;	}break;
	case Str2Binary32('B','O','N','E'): { pols.Type = LAYER::POLS::BONE;	}break;
	default: {	MAID_ASSERT( true, "識別できないタイプです " << ConvertID(ID) ); return ;}break;
	}

	{
		const int end = dat.Pos + dat.Size;

		while( true )
		{
			if( end<=hFile.GetPosition() ) { break; }
			const unt32 count = Read_U16(hFile) & 0x3FF;

			LAYER::POLS::INDEX index;

			for( unt32 i=0; i<count; ++i )
			{
				index.push_back( Read_VX(hFile) );
			}

			pols.Polygon.push_back( index );
		}
	}

	Layer.Polygon.push_back(pols);
}



/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'PTAG' チャンクの読み取り ( ポリゴンタグマッピング ）
/*!
 	@param	hFile	[i ] チャンクデータ
 	@param	dat		[ o] 出力先
 	@param	Layer	[i ] この関数で読み込んだものの設定先モデル
 */
void CLightWaveObject::LoadPTAG( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('P','T','A','G'), "PTAG チャンクではありません" );

	LAYER::PTAG ptag;

	const unt32 ID = Read_ID(hFile);

	switch( ID )
	{
	case Str2Binary32('S','U','R','F'): { ptag.Type = LAYER::PTAG::SURF;	}break;
//	case Str2Binary32('P','A','R','T'): { ptag.Type = LAYER::PTAG::PART;	}break;
//	case Str2Binary32('S','M','G','P'): { ptag.Type = LAYER::PTAG::SMGP;	}break;
	case Str2Binary32('B','O','N','E'): { ptag.Type = LAYER::PTAG::BONE;	}break;
	case Str2Binary32('B','N','W','T'): { ptag.Type = LAYER::PTAG::BNWT;	}break;
	default: { return ; }break;	//	そのほかはスルー
	}


	// 配列サイズを完全に決めることは出来ないがある程度は予測できるので
	// ちょこっと予約

	ptag.MapList.reserve( dat.Size/4 );

	const int end = dat.Pos + dat.Size;

	while( true )
	{
		if( end<=hFile.GetPosition() ) { break; }

		LAYER::PTAG::MAP m;
		m.PolygonNo = Read_VX (hFile);
		m.TypeNo    = Read_U16(hFile);

		ptag.MapList.push_back(m);
	}

	Layer.PolygonTagMapping.push_back(ptag);
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'VMAP' チャンクの読み取り ( サーフェス情報 ）
/*!
 	@param	hFile	[i ] チャンクデータ
 	@param	dat		[ o] 出力先
 	@param	Layer	[i ] この関数で読み込んだものの設定先モデル
 */
void CLightWaveObject::LoadVMAP( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('V','M','A','P'), "VMAP チャンクではありません" );

	LAYER::VMAP vmap;

	switch( Read_ID(hFile) )
	{
//	case Str2Binary32('P','I','C','K'): { vmap.Type = LAYER::VMAP::PICK; }break;
	case Str2Binary32('W','G','H','T'): { vmap.Type = LAYER::VMAP::WGHT; }break;
//	case Str2Binary32('M','N','V','W'): { vmap.Type = LAYER::VMAP::MNVW; }break;
	case Str2Binary32('T','X','U','V'): { vmap.Type = LAYER::VMAP::TXUV; }break;
	case Str2Binary32('R','G','B',' '): { vmap.Type = LAYER::VMAP::RGB;  }break;
	case Str2Binary32('R','G','B','A'): { vmap.Type = LAYER::VMAP::RGBA; }break;
//	case Str2Binary32('M','O','R','F'): { vmap.Type = LAYER::VMAP::MORF; }break;
//	case Str2Binary32('S','P','O','T'): { vmap.Type = LAYER::VMAP::SPOT; }break;
	default: { vmap.Type = LAYER::VMAP::NONE; }
	}

	const int dim = Read_U16(hFile);

	vmap.Name = Read_Str(hFile);

	const int end = dat.Pos + dat.Size;

	while( true )
	{
		if( end<=hFile.GetPosition() ) { break; }

		LAYER::VMAP::DATA m;
		const int VertexNo = Read_VX(hFile);

		for( int i=0; i<dim; ++i ) { m.Value.push_back(Read_F32(hFile)); }

		vmap.Map[VertexNo] = m;
	}

	Layer.VertexMap.push_back(vmap);
}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'VMAD' チャンクの読み取り ( サーフェス情報 ）
/*!
 	@param	hFile	[i ] チャンクデータ
 	@param	dat		[ o] 出力先
 	@param	Layer	[i ] この関数で読み込んだものの設定先モデル
 */
void CLightWaveObject::LoadVMAD( CFileRead& hFile, const CHUNKDATA& dat, LAYER& Layer )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('V','M','A','D'), "VMAD チャンクではありません" );

	LAYER::VMAD vmad;

	switch( Read_ID(hFile) )
	{
//	case Str2Binary32('P','I','C','K'): { vmad.Type = LAYER::VMAD::PICK; }break;
	case Str2Binary32('W','G','H','T'): { vmad.Type = LAYER::VMAD::WGHT; }break;
//	case Str2Binary32('M','N','V','W'): { vmad.Type = LAYER::VMAD::MNVW; }break;
	case Str2Binary32('T','X','U','V'): { vmad.Type = LAYER::VMAD::TXUV; }break;
	case Str2Binary32('R','G','B',' '): { vmad.Type = LAYER::VMAD::RGB;  }break;
	case Str2Binary32('R','G','B','A'): { vmad.Type = LAYER::VMAD::RGBA; }break;
//	case Str2Binary32('M','O','R','F'): { vmad.Type = LAYER::VMAD::MORF; }break;
//	case Str2Binary32('S','P','O','T'): { vmad.Type = LAYER::VMAD::SPOT; }break;
	default: { vmad.Type = LAYER::VMAD::NONE; }
	}

	const int dim = Read_U16(hFile);

	vmad.Name = Read_Str(hFile);

	const int end = dat.Pos + dat.Size;

	while( true )
	{
		if( end<=hFile.GetPosition() ) { break; }

		LAYER::VMAD::DATA m;

		m.VertexNo  = Read_VX(hFile);
		m.PolygonNo = Read_VX(hFile);

		for( int i=0; i<dim; ++i ) { m.Value.push_back(Read_F32(hFile)); }

		vmad.Map.push_back(m);
	}

	Layer.DisVertexMap.push_back(vmad);

}


/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'SURF' チャンクの読み取り ( サーフェス情報 ）
/*!
 	@param	hFile	[i ] ファイル情報
 	@param	dat		[i ] チャンクデータ
 	@param	doc		[ o] 出力先
 */
void CLightWaveObject::LoadSURF( CFileRead& hFile, const CHUNKDATA& dat, DOCUMENT& doc )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('S','U','R','F'), "SURF チャンクではありません" );

	SURFACE surf;

	surf.Name = Read_Str(hFile);
	surf.ParentName = Read_Str(hFile);

	//	とりあえずデフォルト値を設定しておく

	surf.Diffuse.Value		= 1.0f; surf.Diffuse.EnvelopeNo		= 0;
	surf.Ambient.Value		= 0.0f; surf.Ambient.EnvelopeNo		= 0;
	surf.Specular.Value		= 0.0f; surf.Specular.EnvelopeNo	= 0;
	surf.Glossiness.Value	= 0.0f; surf.Glossiness.EnvelopeNo	= 0;
	surf.Trans.Value		= 0.0f; surf.Trans.EnvelopeNo		= 0;


	const unt32 TextLength = StrLen(surf.Name)+StrLen(surf.ParentName);

	if( dat.Size==TextLength ) { return ; }

	MySTL::vector<CHUNKDATA> ChunkList;

	ParseSub( hFile, dat.Pos + dat.Size-TextLength, ChunkList );

	for( int i=0; i<(int)ChunkList.size(); ++i )
	{
		const CHUNKDATA& d = ChunkList[i];

		hFile.SetPosition( d.Pos );

//		MAIDN_TRACE( "---%s", ConvertID(dat.Name).c_str() );

		switch( d.Name )
		{
		case Str2Binary32('C','O','L','R'):
			{
				surf.Color.Value.SetR( Read_F32(hFile) );
				surf.Color.Value.SetG( Read_F32(hFile) );
				surf.Color.Value.SetB( Read_F32(hFile) );

				surf.Color.EnvelopeNo = Read_VX(hFile) ;
			}break;

		case Str2Binary32('D','I','F','F'): { surf.Diffuse.Value	= Read_F32(hFile); surf.Diffuse.EnvelopeNo		= Read_VX(hFile); }break;
		case Str2Binary32('L','U','M','I'): { surf.Ambient.Value    = Read_F32(hFile); surf.Ambient.EnvelopeNo	= Read_VX(hFile); }break;
		case Str2Binary32('S','P','E','C'): { surf.Specular.Value	= Read_F32(hFile); surf.Specular.EnvelopeNo		= Read_VX(hFile); }break;
		case Str2Binary32('G','L','O','S'): { surf.Glossiness.Value = Read_F32(hFile); surf.Glossiness.EnvelopeNo	= Read_VX(hFile); }break;
		case Str2Binary32('T','R','A','N'): { surf.Trans.Value		= Read_F32(hFile); surf.Trans.EnvelopeNo		= Read_VX(hFile); 	}break;

		case Str2Binary32('B','L','O','K'): { LoadSubBLOK( hFile, d, surf ); }break;

		// その他は無視
//		default: { MAID_WARNING( "このタグは対応していません ", ConvertID(dat.Name) ); }break;
		}
	}

	doc.SurfaceList.push_back(surf);
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/
//! 'CLIP' チャンクの読み取り ( サーフェス情報 ）
/*!
 	@param	hFile	[i ] ファイル情報
 	@param	dat		[i ] チャンクデータ
 	@param	doc		[ o] 出力先
 */
void CLightWaveObject::LoadCLIP( CFileRead& hFile, const CHUNKDATA& dat, DOCUMENT& doc )
{
	MAID_ASSERT( dat.Name!=Str2Binary32('C','L','I','P'), "CLIP チャンクではありません" );

	CLIP clip;

	clip.ID = Read_U32(hFile);
/*
	const unt32 t = Read_ID(hFile);

	switch( t )
	{
	case Str2Binary32('S','T','I','L'): { clip.Type	= CLIP::STIL; }break;
//	case Str2Binary32('I','S','E','Q'): { clip.Type	= CLIP::ISEQ; }break;
//	case Str2Binary32('A','N','I','M'): { clip.Type	= CLIP::ANIM; }break;
//	case Str2Binary32('X','R','E','F'): { clip.Type	= CLIP::XREF; }break;
//	case Str2Binary32('S','T','C','C'): { clip.Type	= CLIP::STCC; }break;
	default: { clip.Type = CLIP::NONE; }
	}
*/

	MySTL::vector<CHUNKDATA> ChunkList;
	ParseSub( hFile, dat.Pos + dat.Size-sizeof(unt32), ChunkList );

	for( int i=0; i<(int)ChunkList.size(); ++i )
	{
		const CHUNKDATA& d = ChunkList[i];
		hFile.SetPosition( d.Pos );
//		DEN_TRACE( "---%s", ConvertID(dat.Name).c_str() );

		switch( d.Name )
		{
		case Str2Binary32('S','T','I','L'): 
			{
				clip.Type	= CLIP::STIL;
				clip.StillImage = Read_Str(hFile); 
			}break;
		}
	}

	doc.ClipList.push_back(clip);
//	DEN_TRACE( "------%s", clip.SourceName.c_str() );
}

void  CLightWaveObject::LoadSubBLOK( CFileRead& hFile, const CHUNKDATA& dat, SURFACE& surf )
{
	MySTL::vector<CHUNKDATA> BlockChunk;

	ParseSub( hFile, dat.Pos + dat.Size, BlockChunk );

	SURFACE::BLOCK block;

	//	初期値の設定

	block.Base.IsEnable = true;

	for( int i=0; i<(int)BlockChunk.size(); ++i )
	{
		const CHUNKDATA& c1 = BlockChunk[i];

		hFile.SetPosition( c1.Pos );

	//	MAID_TRACE( "----" << ConvertID(c1.Name) );

		switch( c1.Name )
		{
		case Str2Binary32('I','M','A','P'):
			{
				block.Base.Type = SURFACE::BLOCK::BASE::IMAP;
				block.Base.Priority = Read_Str(hFile);

				MySTL::vector<CHUNKDATA> ImapChunk;
				ParseSub( hFile, c1.Pos+c1.Size-StrLen(block.Base.Priority), ImapChunk );

				for( int j=0; j<(int)ImapChunk.size(); ++j )
				{
					const CHUNKDATA& c2 = ImapChunk[j];
					hFile.SetPosition( c2.Pos );
					switch( c2.Name )
					{
					case Str2Binary32('C','H','A','N'):
						{
							switch( Read_ID(hFile) )
							{
							case Str2Binary32('C','O','L','R'): { block.Base.Channel = SURFACE::BLOCK::BASE::COLR; } break;
							case Str2Binary32('D','I','F','F'): { block.Base.Channel = SURFACE::BLOCK::BASE::DIFF; } break;
							case Str2Binary32('S','P','E','C'): { block.Base.Channel = SURFACE::BLOCK::BASE::SPEC; } break;
							case Str2Binary32('R','E','F','L'): { block.Base.Channel = SURFACE::BLOCK::BASE::REFL; } break;
							case Str2Binary32('T','R','A','N'): { block.Base.Channel = SURFACE::BLOCK::BASE::TRAN; } break;
							case Str2Binary32('R','I','N','D'): { block.Base.Channel = SURFACE::BLOCK::BASE::RIND; } break;
							case Str2Binary32('T','R','N','L'): { block.Base.Channel = SURFACE::BLOCK::BASE::TRNL; } break;
							case Str2Binary32('B','U','M','P'): { block.Base.Channel = SURFACE::BLOCK::BASE::BUMP; } break;
							}
						}break;
					case Str2Binary32('E','N','A','B'):
						{
							block.Base.IsEnable = false; 
						}break;
					case Str2Binary32('O','P','A','C'):
						{
							switch( Read_U16(hFile) )
							{
							case 0: { block.Base.Opacity.Type = SURFACE::BLOCK::BASE::OPAC::NORMAL; } break;
							case 1: { block.Base.Opacity.Type = SURFACE::BLOCK::BASE::OPAC::SUB;	} break;
							case 2: { block.Base.Opacity.Type = SURFACE::BLOCK::BASE::OPAC::ABS;	} break;
							case 3: { block.Base.Opacity.Type = SURFACE::BLOCK::BASE::OPAC::MUL;	} break;
							case 4: { block.Base.Opacity.Type = SURFACE::BLOCK::BASE::OPAC::DIV;	} break;
							case 5: { block.Base.Opacity.Type = SURFACE::BLOCK::BASE::OPAC::ALPHA;	} break;
							case 6: { block.Base.Opacity.Type = SURFACE::BLOCK::BASE::OPAC::TEXURE; } break;
							case 7: { block.Base.Opacity.Type = SURFACE::BLOCK::BASE::OPAC::ADD;	} break;
							default:{ MAID_ASSERT(true,"不明"); } break;
							}
						}break;
					case Str2Binary32('A','X','I','S'):
						{
							switch( Read_U16(hFile) )
							{
							case 0: { block.Base.Axis = SURFACE::BLOCK::BASE::X; } break;
							case 1: { block.Base.Axis = SURFACE::BLOCK::BASE::Y;	} break;
							case 2: { block.Base.Axis = SURFACE::BLOCK::BASE::Z;	} break;
							default:{ MAID_ASSERT(true,"不明"); } break;
							}
						}break;
					}
				}

			}break;
		case Str2Binary32('T','M','A','P'):
			{
				MySTL::vector<CHUNKDATA> TmapChunk;
				ParseSub( hFile, dat.Pos+dat.Size, TmapChunk );

				for( int j=0; j<(int)TmapChunk.size(); ++j )
				{
					const CHUNKDATA& c2 = TmapChunk[j];
					hFile.SetPosition( c2.Pos );
					switch( c2.Name )
					{
					case Str2Binary32('C','N','T','R'):
						{
							block.TextureMap.Center.x = Read_F32(hFile);
							block.TextureMap.Center.y = Read_F32(hFile);
							block.TextureMap.Center.z = Read_F32(hFile);
							block.TextureMap.Center.EnvelopeNo = Read_VX(hFile);
						}break;
					case Str2Binary32('S','I','Z','E'):
						{
							block.TextureMap.Size.x = Read_F32(hFile);
							block.TextureMap.Size.y = Read_F32(hFile);
							block.TextureMap.Size.z = Read_F32(hFile);
							block.TextureMap.Size.EnvelopeNo = Read_VX(hFile);
						}break;
					case Str2Binary32('R','O','T','A'):
						{
							block.TextureMap.Rotate.x = Read_F32(hFile);
							block.TextureMap.Rotate.y = Read_F32(hFile);
							block.TextureMap.Rotate.z = Read_F32(hFile);
							block.TextureMap.Rotate.EnvelopeNo = Read_VX(hFile);
						}break;
					case Str2Binary32('O','R','E','F'):
						{
							block.TextureMap.ObjectName = Read_Str(hFile);
						}break;
					case Str2Binary32('F','A','L','L'):
						{
							block.TextureMap.FallOff.Type = (SURFACE::BLOCK::TMAP::FALL::TYPE)Read_U16(hFile);
							block.TextureMap.Rotate.x = Read_F32(hFile);
							block.TextureMap.Rotate.y = Read_F32(hFile);
							block.TextureMap.Rotate.z = Read_F32(hFile);
							block.TextureMap.Rotate.EnvelopeNo = Read_VX(hFile);
						}break;
					case Str2Binary32('C','S','Y','S'):
						{
							const unt16 v = Read_U16(hFile);
							if( v==0 ) { block.TextureMap.Csys = SURFACE::BLOCK::TMAP::LOCAL; }
							ef( v==1 ) { block.TextureMap.Csys = SURFACE::BLOCK::TMAP::WORLD; }
						}break;
					}
				}

			}break;

		case Str2Binary32('I','M','A','G'):
			{
				block.ImageMap.ImageNo = Read_VX(hFile);
			}break;
		case Str2Binary32('V','M','A','P'):
			{
				block.ImageMap.UVMapName = Read_Str(hFile);
			}break;
		}
	}

	surf.BlockList.push_back(block);
}

}