// ObjectChild.cpp: implementation of the CObjectChild class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "ObjectChild.h"

#include "MainFrm.h"
#include "MapEditor.h"
#include "MapEditorDoc.h"
#include "MapEditorView.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

extern LPDIRECT3DDEVICE8	g_pD3dDev;

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CObjectChild::CObjectChild(int objType,  D3DXVECTOR3 vPos,BOOL bCheckTick)
{
	CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
	CMapEditorView* pView = (CMapEditorView*)pFrame->GetActiveView();

	m_pCharacterInfo = NULL;
	memset(&m_info,0x00,sizeof(MAPOBJECTINFODETAIL));
	m_pRenderer = pView->m_pObject;
	m_vPos = vPos;
	m_vUp = D3DXVECTOR3(0,1,0);
	D3DXVECTOR3 vVel;
	vVel.x = (float)(rand()%1000 - 500);
	vVel.y = 0;
	vVel.z = (float)(rand()%1000 - 500);
	D3DXVec3Normalize(&m_vVel, &vVel);
	if(objType < pView->m_nObjectNormalCont)
		m_dwPartType = objType;
	else
		m_dwPartType = 10000 + (objType - pView->m_nObjectNormalCont);
//	m_bRenderType = pView->m_checkAlphaBlending;
	m_fCurrentTime = 0.0f;
	m_bCheckTick = bCheckTick;		// Tick 걸며 고저 자동조절 변수
	m_bCheckChoose = FALSE;		// 오브젝트 에디터에서 선택여부 변수
	m_bCheckRender = TRUE;
	if(pView->m_checkObjectNormal)
	{
		float fDist,fBary1,fBary2;
		int x = m_vPos.x/40.0f;
		int z = m_vPos.z/40.0f;
		D3DXVECTOR3 vDir = D3DXVECTOR3(0,-1,0);
		D3DXVECTOR3 vPos = m_vPos-vDir;
		D3DXVECTOR3 vUp = m_vUp;
		if(pView->m_pBackground->IntersectTriangle(vPos,vDir,pView->m_pBackground->m_pTileVertexArray[(x)*(pView->m_pBackground->m_sYSize+1)+z].pos,
			pView->m_pBackground->m_pTileVertexArray[(x)*(pView->m_pBackground->m_sYSize+1)+(z+1)].pos,pView->m_pBackground->m_pTileVertexArray[(x+1)*(pView->m_pBackground->m_sYSize+1)+(z+1)].pos,
			&fDist, &fBary1, &fBary2 ))
		{
			// 맵 타일 바꾸기
			D3DXVec3Cross(&m_vUp,&(pView->m_pBackground->m_pTileVertexArray[(x)*(pView->m_pBackground->m_sYSize+1)+(z+1)].pos-pView->m_pBackground->m_pTileVertexArray[(x)*(pView->m_pBackground->m_sYSize+1)+z].pos)
				,&(pView->m_pBackground->m_pTileVertexArray[(x+1)*(pView->m_pBackground->m_sYSize+1)+(z+1)].pos-pView->m_pBackground->m_pTileVertexArray[(x)*(pView->m_pBackground->m_sYSize+1)+(z+1)].pos));
			D3DXVec3Normalize(&m_vUp,&m_vUp);
			if(D3DXVec3Length(&(m_vUp + vUp)) < 2.0f)
				D3DXVec3Cross(&m_vVel,&vUp,&m_vUp);
		}
		else if(pView->m_pBackground->IntersectTriangle(vPos,vDir,pView->m_pBackground->m_pTileVertexArray[(x)*(pView->m_pBackground->m_sYSize+1)+z].pos,
			pView->m_pBackground->m_pTileVertexArray[(x+1)*(pView->m_pBackground->m_sYSize+1)+(z+1)].pos,pView->m_pBackground->m_pTileVertexArray[(x+1)*(pView->m_pBackground->m_sYSize+1)+z].pos,
			&fDist, &fBary1, &fBary2 ))
		{
			D3DXVec3Cross(&m_vUp,&(pView->m_pBackground->m_pTileVertexArray[(x+1)*(pView->m_pBackground->m_sYSize+1)+(z+1)].pos-pView->m_pBackground->m_pTileVertexArray[(x)*(pView->m_pBackground->m_sYSize+1)+z].pos)
				,&(pView->m_pBackground->m_pTileVertexArray[(x+1)*(pView->m_pBackground->m_sYSize+1)+(z)].pos-pView->m_pBackground->m_pTileVertexArray[(x+1)*(pView->m_pBackground->m_sYSize+1)+(z+1)].pos));
			D3DXVec3Normalize(&m_vUp,&m_vUp);
			if(D3DXVec3Length(&(m_vUp + vUp)) < 2.0f)
				D3DXVec3Cross(&m_vVel,&vUp,&m_vUp);
		}
	}
	
	D3DXMatrixLookAtLH( &m_mMatrix, &m_vPos, &(m_vPos+m_vVel), &m_vUp);
	D3DXMatrixInverse( &m_mMatrix, NULL, &m_mMatrix );

	CString strObjectname;
	char bufError[256];
	if(objType < pView->m_comboObjectSelect.GetCount())
		pView->m_comboObjectSelect.GetLBText(objType,strObjectname);
	else
	{
		wsprintf(bufError,"Object doesn't exist. [%d]",m_dwPartType);
		AfxMessageBox(bufError,MB_OK);
		m_bUsing = FALSE;
	}

//	int nObjNum;
	if(strlen(strObjectname))
	{
		m_nObjectNum = atoi(strObjectname);
		map<INT, MAPOBJECTINFO*>::iterator it = pView->m_mapObjectInfo.find(m_nObjectNum);
		if(it != pView->m_mapObjectInfo.end())
			m_bRenderType = it->second->Alpha;
		else
			m_bRenderType = FALSE;

		char buf[256];
		wsprintf(buf,"%08d",m_nObjectNum);
		LoadCharacterEffect(buf);
		if(!m_info.bBodyCondition)
		{
			m_bodyCondition = BODYCON_LANDED_MASK;
			m_info.bBodyCondition = 2;
		}
		else
		{
			LONGLONG bBodyCon = 1;
			bBodyCon <<= m_info.bBodyCondition;
			m_bodyCondition = bBodyCon;
		}
		if(m_pCharacterInfo)
		{
			m_pCharacterInfo->SetAllBodyConditionMatrix(m_mMatrix);
			m_pCharacterInfo->ChangeBodyCondition(m_bodyCondition);
		}
	}
	if(m_info.dwObjectType == 0)
		m_info.dwObjectType = m_nObjectNum;
//	if(m_info.fObjectScale == 0.0f)
//		m_info.fObjectScale = 1.0f;
//	if(m_info.bObjectTexIndex == 0)
//		m_info.bObjectTexIndex = 1;
//	if(m_info.nObjectSrcIndex == 0)
//		m_info.nObjectSrcIndex = m_nObjectNum;
}

//CObjectChild::CObjectChild(int objType,BOOL bRenderType,  D3DXVECTOR3 vPos, D3DXVECTOR3 vVel,D3DXVECTOR3 vUp,BOOL bCheckTick)
CObjectChild::CObjectChild(OBJECTINFO info1,MAPOBJECTINFODETAIL info2)
{
	CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
	CMapEditorView* pView = (CMapEditorView*)pFrame->GetActiveView();

	m_pCharacterInfo = NULL;

	memset(&m_info,0x00,sizeof(MAPOBJECTINFODETAIL));
	memcpy(&m_info,&info2,sizeof(MAPOBJECTINFODETAIL));

	int type;	
	if(info1.m_dwObjType < 10000 && info1.m_dwObjType >= pView->m_nObjectNormalCont)
		type = info1.m_dwObjType - pView->m_nObjectNormalCont + 10000;
	else
		type = info1.m_dwObjType;
	
	
	m_pRenderer = pView->m_pObject;
	m_vPos = info1.vPos;
	D3DXVec3Normalize(&m_vUp,&info1.vUp);
	m_vVel = info1.vVel;
/*	if(objType < pView->m_nObjectNormalCont)
		m_dwPartType = objType;
	else
		m_dwPartType = 10000 + (objType - pView->m_nObjectNormalCont);
*/
	m_dwPartType = type;
//	m_bRenderType = bRenderType;
	m_fCurrentTime = 0.0f;
	m_bCheckTick = info1.bCheckTick;		// Tick 걸며 고저 자동조절 변수
	m_bCheckChoose = FALSE;		// 오브젝트 에디터에서 선택여부 변수
	m_bCheckRender = TRUE;

	D3DXMatrixLookAtLH( &m_mMatrix, &m_vPos, &(m_vPos+m_vVel), &m_vUp);
	D3DXMatrixInverse( &m_mMatrix, NULL, &m_mMatrix );

	CString strObjectname;
	char bufError[256];
	if(m_dwPartType < 10000)
	{
		if(m_dwPartType < pView->m_comboObjectSelect.GetCount())
			pView->m_comboObjectSelect.GetLBText(m_dwPartType,strObjectname);
		else
		{
			wsprintf(bufError,"Object doesn't exist. [%d]",m_dwPartType);
			AfxMessageBox(bufError,MB_OK);
			m_bUsing = FALSE;
		}
	}
	else
	{
		if(m_dwPartType-10000 + pView->m_nObjectNormalCont < pView->m_comboObjectSelect.GetCount())
			pView->m_comboObjectSelect.GetLBText(m_dwPartType-10000 + pView->m_nObjectNormalCont,strObjectname);
		else
		{
			wsprintf(bufError,"Object doesn't exist. [%d]",m_dwPartType);
			AfxMessageBox(bufError,MB_OK);
			m_bUsing = FALSE;
		}
	}
	if(strlen(strObjectname))
	{
		m_nObjectNum = atoi(strObjectname);
		map<INT, MAPOBJECTINFO*>::iterator it = pView->m_mapObjectInfo.find(m_nObjectNum);
		if(it != pView->m_mapObjectInfo.end())
			m_bRenderType = it->second->Alpha;
		else
			m_bRenderType = FALSE;
		char buf[256];
		wsprintf(buf,"%08d",m_nObjectNum);
		LoadCharacterEffect(buf);
		if(!m_info.bBodyCondition)
		{
			m_bodyCondition = BODYCON_LANDED_MASK;
			m_info.bBodyCondition = 2;
		}
		else
		{
			LONGLONG bBodyCon = 1;
			bBodyCon <<= m_info.bBodyCondition;
			m_bodyCondition = bBodyCon;
		}
		if(m_pCharacterInfo)
		{
			m_pCharacterInfo->SetAllBodyConditionMatrix(m_mMatrix);
			m_pCharacterInfo->ChangeBodyCondition(m_bodyCondition);
		}
	}
	if(m_info.dwObjectType == 0)
		m_info.dwObjectType = m_nObjectNum;
//	if(m_info.fObjectScale == 0.0f)
//		m_info.fObjectScale = 1.0f;
//	if(m_info.bObjectTexIndex == 0)
//		m_info.bObjectTexIndex = 1;
//	if(m_info.nObjectSrcIndex == 0)
//		m_info.nObjectSrcIndex = m_nObjectNum;

}

CObjectChild::CObjectChild(D3DXVECTOR3 vPos)
{
	CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
	CMapEditorView* pView = (CMapEditorView*)pFrame->GetActiveView();

	m_pCharacterInfo = NULL;

	memset(&m_info,0x00,sizeof(MAPOBJECTINFODETAIL));
	m_pRenderer = pView->m_pObject;
	m_vPos = vPos;
	m_vUp = D3DXVECTOR3(0,1,0);
	if(pView->m_bObjectDir == 0)
		m_vVel = D3DXVECTOR3(1,0,0);
	else if(pView->m_bObjectDir == 1)
		m_vVel = D3DXVECTOR3(0,0,1);
	else if(pView->m_bObjectDir == 2)
		m_vVel = D3DXVECTOR3(-1,0,0);
	else
		m_vVel = D3DXVECTOR3(0,0,-1);

	if(pView->m_dwObjectType < pView->m_nObjectNormalCont)
		m_dwPartType = pView->m_dwObjectType;
	else
		m_dwPartType = 10000 + (pView->m_dwObjectType - pView->m_nObjectNormalCont);
//	m_bRenderType = pView->m_checkAlphaBlending;
	m_fCurrentTime = 0.0f;
	m_bCheckTick = FALSE;		// Tick 걸며 고저 자동조절 변수
	m_bCheckChoose = FALSE;		// 오브젝트 에디터에서 선택여부 변수
	m_bCheckRender = TRUE;

	D3DXMatrixLookAtLH( &m_mMatrix, &m_vPos, &(m_vPos+m_vVel), &m_vUp);
	D3DXMatrixInverse( &m_mMatrix, NULL, &m_mMatrix );
		
	CString strObjectname;
	char bufError[256];
	if(pView->m_dwObjectType < pView->m_comboObjectSelect.GetCount())
		pView->m_comboObjectSelect.GetLBText(pView->m_dwObjectType,strObjectname);
	else
	{
		wsprintf(bufError,"Object doesn't exist. [%d]",m_dwPartType);
		AfxMessageBox(bufError,MB_OK);
		m_bUsing = FALSE;
	}
	if(strlen(strObjectname))
	{
		m_nObjectNum = atoi(strObjectname);
		map<INT, MAPOBJECTINFO*>::iterator it = pView->m_mapObjectInfo.find(m_nObjectNum);
		if(it != pView->m_mapObjectInfo.end())
			m_bRenderType = it->second->Alpha;
		else
			m_bRenderType = FALSE;

		char buf[256];
		wsprintf(buf,"%08d",m_nObjectNum);
		LoadCharacterEffect(buf);
		if(!m_info.bBodyCondition)
		{
			m_bodyCondition = BODYCON_LANDED_MASK;
			m_info.bBodyCondition = 2;
		}
		else
		{
			LONGLONG bBodyCon = 1;
			bBodyCon <<= m_info.bBodyCondition;
			m_bodyCondition = bBodyCon;
		}
		if(m_pCharacterInfo)
		{
			m_pCharacterInfo->SetAllBodyConditionMatrix(m_mMatrix);
			m_pCharacterInfo->ChangeBodyCondition(m_bodyCondition);
		}
	}
	if(m_info.dwObjectType == 0)
		m_info.dwObjectType = m_nObjectNum;
//	if(m_info.fObjectScale == 0.0f)
//		m_info.fObjectScale = 1.0f;
//	if(m_info.bObjectTexIndex == 0)
//		m_info.bObjectTexIndex = 1;
//	if(m_info.nObjectSrcIndex == 0)
//		m_info.nObjectSrcIndex = m_nObjectNum;
}

CObjectChild::CObjectChild( D3DXVECTOR3 vPos, D3DXVECTOR3 vVel, D3DXVECTOR3 vUp, int nObjType )
{
	CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
	CMapEditorView* pView = (CMapEditorView*)pFrame->GetActiveView();

	m_pCharacterInfo = NULL;

	memset(&m_info,0x00,sizeof(MAPOBJECTINFODETAIL));
	m_pRenderer = pView->m_pObject;
	m_vPos = vPos;
	m_vUp = vUp;
	m_vVel = vVel;

	if(nObjType < pView->m_nObjectNormalCont)
		m_dwPartType = nObjType;
	else
		m_dwPartType = 10000 + (nObjType - pView->m_nObjectNormalCont);

	m_fCurrentTime = 0.0f;
	m_bCheckTick = FALSE;		// Tick 걸며 고저 자동조절 변수
	m_bCheckChoose = FALSE;		// 오브젝트 에디터에서 선택여부 변수
	m_bCheckRender = TRUE;

	D3DXMatrixLookAtLH( &m_mMatrix, &m_vPos, &(m_vPos+m_vVel), &m_vUp);
	D3DXMatrixInverse( &m_mMatrix, NULL, &m_mMatrix );
		
	map<INT, MAPOBJECTINFO*>::iterator it = pView->m_mapObjectInfo.find(nObjType);
	if(it != pView->m_mapObjectInfo.end())
		m_bRenderType = it->second->Alpha;
	else
		m_bRenderType = FALSE;

	char buf[256];
	wsprintf(buf,"%08d",nObjType);
	LoadCharacterEffect(buf);
	if(!m_info.bBodyCondition)
	{
		m_bodyCondition = BODYCON_LANDED_MASK;
		m_info.bBodyCondition = 2;
	}
	else
	{
		LONGLONG bBodyCon = 1;
		bBodyCon <<= m_info.bBodyCondition;
		m_bodyCondition = bBodyCon;
	}
	
	if(m_pCharacterInfo)
	{
		m_pCharacterInfo->SetAllBodyConditionMatrix(m_mMatrix);
		m_pCharacterInfo->ChangeBodyCondition(m_bodyCondition);
	}
	if(m_info.dwObjectType == 0)
		m_info.dwObjectType = nObjType;
//	if(m_info.fObjectScale == 0.0f)
//		m_info.fObjectScale = 1.0f;
//	if(m_info.bObjectTexIndex == 0)
//		m_info.bObjectTexIndex = 1;
//	if(m_info.nObjectSrcIndex == 0)
//		m_info.nObjectSrcIndex = nObjType;
}

CObjectChild::~CObjectChild()
{
	if(m_pCharacterInfo)//추가
	{
		m_pCharacterInfo->InvalidateDeviceObjects();
		m_pCharacterInfo->DeleteDeviceObjects();
		SAFE_DELETE(m_pCharacterInfo);
	}
}
void CObjectChild::SetObjectMatrix( D3DXMATRIX mat )
{
	D3DXMATRIX m = mat;
	m._41 = 0; m._42 = 0; m._43 = 0;m._44 = 0;
	m_vPos = D3DXVECTOR3(mat._41, mat._42, mat._43);
	m_vUp = D3DXVECTOR3(0,1,0);
	m_vVel = D3DXVECTOR3(0,0,1);
	D3DXVec3TransformCoord( &m_vUp, &m_vUp, &m );
	D3DXVec3TransformCoord( &m_vVel, &m_vVel, &m );
}

void CObjectChild::Tick()
{
	CMainFrame* pFrame = (CMainFrame*)AfxGetMainWnd();
	CMapEditorView* pView = (CMapEditorView*)pFrame->GetActiveView();

	D3DXMatrixIdentity(&m_mMatrix);
	m_fCurrentTime += 20.0f*pView->GetElapsedTime();//0.0f;

	static float fCheckTime = 0.5f;
	if(m_bCheckChoose)
	{
		if(fCheckTime > -0.3f)
			fCheckTime -= pView->GetElapsedTime();
		if(fCheckTime < -0.3f)
			fCheckTime = 0.5f;
		if(fCheckTime<0.0f)
			m_bCheckRender = FALSE;
		else
			m_bCheckRender = TRUE;
	}
	if(m_bCheckTick)
	{
		FLOAT fBary1, fBary2;
		FLOAT fDist;
		int i,j;
		i = (int)(m_vPos.x/40.0f);
		j = (int)(m_vPos.z/40.0f);
		D3DXVECTOR3 v,orig,dir;//,v2;
		orig = m_vPos;
		dir = D3DXVECTOR3(0,-1,0);

		if(i>=0 && i<pView->m_pBackground->m_projectInfo.m_sXSize && j>=0 && j<pView->m_pBackground->m_projectInfo.m_sYSize)
		{
			if(IntersectTriangle(orig,dir,pView->m_pBackground->m_pTileVertexArray[i*(pView->m_pBackground->m_sYSize+1)+j].pos,
				pView->m_pBackground->m_pTileVertexArray[i*(pView->m_pBackground->m_sYSize+1)+(j+1)].pos,
				pView->m_pBackground->m_pTileVertexArray[(i+1)*(pView->m_pBackground->m_sYSize+1)+(j+1)].pos,
				&fDist, &fBary1, &fBary2 ))
			{
				// 맵 타일 바꾸기
				v = orig + dir*fDist;
				m_vPos = v;
	//			return;
			}
			if(IntersectTriangle(orig,dir,pView->m_pBackground->m_pTileVertexArray[i*(pView->m_pBackground->m_sYSize+1)+j].pos,
				pView->m_pBackground->m_pTileVertexArray[(i+1)*(pView->m_pBackground->m_sYSize+1)+(j+1)].pos,
				pView->m_pBackground->m_pTileVertexArray[(i+1)*(pView->m_pBackground->m_sYSize+1)+j].pos,
				&fDist, &fBary1, &fBary2 ))
			{
				v = orig + dir*fDist;
				m_vPos = v;
	//			return;
			}
		}
	}
// 2004-04-24 by dhkwon	
	D3DXMatrixLookAtLH( &m_mMatrix, &m_vPos, &(m_vPos+m_vVel), &m_vUp);
	D3DXMatrixInverse( &m_mMatrix, NULL, &m_mMatrix );
//	D3DXMatrixTranslation(&m_mMatrix, m_vPos.x, m_vPos.y, m_vPos.z );
//	D3DXMatrixIdentity( &m_mMatrix );
	// effect matrix & ticking
	if(m_pCharacterInfo)
	{
		m_pCharacterInfo->SetAllBodyConditionMatrix(m_mMatrix );
		m_pCharacterInfo->Tick(pView->GetElapsedTime());
	}

	// 스크린상의 좌표
	pView->CalcObjectSourceScreenCoords(m_vPos, pView->GetBackBufferDesc().Width, pView->GetBackBufferDesc().Height, 
		m_nObjScreenX, m_nObjScreenY, m_nObjScreenW );
}

BOOL CObjectChild::IntersectTriangle( const D3DXVECTOR3& orig,
                                       const D3DXVECTOR3& dir, D3DXVECTOR3& v0,
                                       D3DXVECTOR3& v1, D3DXVECTOR3& v2,
                                       FLOAT* t, FLOAT* u, FLOAT* v )
{
    // Find vectors for two edges sharing vert0
    D3DXVECTOR3 edge1 = v1 - v0;
    D3DXVECTOR3 edge2 = v2 - v0;

    // Begin calculating determinant - also used to calculate U parameter
    D3DXVECTOR3 pvec;
    D3DXVec3Cross( &pvec, &dir, &edge2 );

    // If determinant is near zero, ray lies in plane of triangle
    FLOAT det = D3DXVec3Dot( &edge1, &pvec );

    D3DXVECTOR3 tvec;
    if( det > 0 )
    {
        tvec = orig - v0;
    }
    else
    {
        tvec = v0 - orig;
        det = -det;
    }

    if( det < 0.0001f )
        return FALSE;

    // Calculate U parameter and test bounds
    *u = D3DXVec3Dot( &tvec, &pvec );
    if( *u < 0.0f || *u > det )
        return FALSE;

	// Prepare to test V parameter
	D3DXVECTOR3 qvec;
	D3DXVec3Cross( &qvec, &tvec, &edge1 );

	// Calculate V parameter and test bounds
    *v = D3DXVec3Dot( &dir, &qvec );
    if( *v < 0.0f || *u + *v > det )
        return FALSE;

	// Calculate t, scale parameters, ray intersects triangle
	*t = D3DXVec3Dot( &edge2, &qvec );
	FLOAT fInvDet = 1.0f / det;
	*t *= fInvDet;
	*u *= fInvDet;
	*v *= fInvDet;

    return TRUE;
}

//void CObjectChild::Render(int min_x,int max_x,int min_z,int max_z)
void CObjectChild::Render()
{
/*	int x,z;
	x = (int)(m_vPos.x / 40.0f);
	z = (int)(m_vPos.z / 40.0f);
	if(min_x <= x && x < max_x && min_z <= z && z < max_z)
*/		m_pRenderer->Render(this);
}

void CObjectChild::LoadCharacterEffect(char* strFileName)
{
	if(m_pCharacterInfo)
	{
		m_pCharacterInfo->InvalidateDeviceObjects();
		m_pCharacterInfo->DeleteDeviceObjects();
		m_pCharacterInfo->InitData();
	}
	m_pCharacterInfo = new CCharacterInfo();
	if(m_pCharacterInfo->Load(strFileName))
	{
		m_pCharacterInfo->InitDeviceObjects();
		m_pCharacterInfo->RestoreDeviceObjects();
	}
	else
		SAFE_DELETE(m_pCharacterInfo);

}
