

#include "OsLib.h"
#include "MathLib.h"
#include "Mesh3DC.h"
#include "MeshRefC.h"
#include "GeomListC.h"


using namespace OsTypes;
using namespace MathLib;

/*

note about the undo system and meshref:

Whenever a meshref is modified a clone of the original is made using the
clone() method. Later when user decides to undo, restore() method is called.
The parameter for the restore method is the original (unmodifed) meshref.

*/



MeshRefC::MeshRefC() :
	EditableI( 0 ),
	m_pMesh( 0 ),
	m_rPosition( 0, 0, 0 ),
	m_rScale( 1, 1, 1 ),
	m_rRotation( 0, 0, 0, 0 ),
	m_i32Flags( 0 ),
	m_rMin( 0, 0, 0 ),
	m_rMax( 0, 0, 0 ),
	m_bBBoxEmpty( OS_TRUE )
//	m_pTransCache0( 0 ),
//	m_pTransCache1( 0 ),
//	m_pTransCache2( 0 )
{
	// empty
}

MeshRefC::MeshRefC( const MeshRefC& rMeshRef ) :
	EditableI( 0 ),
	m_pMesh( 0 ),
	m_rPosition( rMeshRef.m_rPosition ),
	m_rScale( rMeshRef.m_rScale ),
	m_rRotation( rMeshRef.m_rRotation ),
	m_i32Flags( rMeshRef.m_i32Flags ),
	m_rMin( rMeshRef.m_rMin ),
	m_rMax( rMeshRef.m_rMax ),
	m_bBBoxEmpty( rMeshRef.m_bBBoxEmpty )
//	m_pTransCache0( 0 ),
//	m_pTransCache1( 0 ),
//	m_pTransCache2( 0 )
{
	// empty
}

MeshRefC::MeshRefC( const MeshRefC& rMeshRef, EditableI* pOriginal ) :
	EditableI( pOriginal ),
	m_pMesh( rMeshRef.m_pMesh ),
	m_rPosition( rMeshRef.m_rPosition ),
	m_rScale( rMeshRef.m_rScale ),
	m_rRotation( rMeshRef.m_rRotation ),
	m_i32Flags( rMeshRef.m_i32Flags ),
	m_rMin( rMeshRef.m_rMin ),
	m_rMax( rMeshRef.m_rMax ),
	m_bBBoxEmpty( OS_TRUE )
//	m_pTransCache0( rMeshRef.m_pTransCache0 ),
//	m_pTransCache1( rMeshRef.m_pTransCache1 ),
//	m_pTransCache2( rMeshRef.m_pTransCache2 )
{
	// empty
}

MeshRefC::~MeshRefC()
{
//	delete m_pTransCache0;
//	delete m_pTransCache1;
//	delete m_pTransCache2;
}

EditableI*
MeshRefC::clone()
{
	return new MeshRefC( *this, this );
}

void
MeshRefC::restore( EditableI* pEdit )
{
	MeshRefC*	pRef = (MeshRefC*)pEdit;
	m_rPosition = pRef->m_rPosition;
	m_rScale = pRef->m_rScale;
	m_rRotation = pRef->m_rRotation;
	m_i32Flags = pRef->m_i32Flags;
	m_bBBoxEmpty = pRef->m_bBBoxEmpty;
	m_rMin = pRef->m_rMin;
	m_rMax = pRef->m_rMax;
	m_pMesh = pRef->m_pMesh;
//	m_pTransCache0 = pRef->m_pTransCache0;
//	m_pTransCache1 = pRef->m_pTransCache1;
//	m_pTransCache2 = pRef->m_pTransCache2;
}

EditableI*
MeshRefC::duplicate()
{
	return new MeshRefC( *this );
}

void
MeshRefC::copy( EditableI* pEdit )
{
	MeshRefC*	pRef = (MeshRefC*)pEdit;
	m_rPosition = pRef->m_rPosition;
	m_rScale = pRef->m_rScale;
	m_rRotation = pRef->m_rRotation;
	m_i32Flags = pRef->m_i32Flags;
	m_bBBoxEmpty = pRef->m_bBBoxEmpty;
	m_rMin = pRef->m_rMin;
	m_rMax = pRef->m_rMax;
	m_pMesh = pRef->m_pMesh;
}


void
MeshRefC::set_mesh( Mesh3DC* pMesh )
{
	m_pMesh = pMesh;

	Boolean		bFirst = OS_TRUE;

	if( m_pMesh )
		m_pMesh->get_bounds( m_rMin, m_rMax );

	m_bBBoxEmpty = OS_FALSE;

	if( m_rMin == m_rMax ) {
		Vector3dC	rSize( 10, 10, 10 );
		m_rMin = Vector3dC( m_rPosition - rSize );
		m_rMax = Vector3dC( m_rPosition + rSize );
		m_bBBoxEmpty = OS_TRUE;
	}

	// invalidate transform cache
//	delete m_pTransCache;
//	m_pTransCache = 0;
}

Mesh3DC*
MeshRefC::get_mesh()
{
	return m_pMesh;
}

void
MeshRefC::set_position( const Vector3dC& rPos )
{
	m_rPosition = rPos;
}

const Vector3dC&
MeshRefC::get_position() const
{
	return m_rPosition;
}


void
MeshRefC::set_scale( const Vector3dC& rScale )
{
	m_rScale = rScale;
}

const Vector3dC&
MeshRefC::get_scale() const
{
	return m_rScale;
}

void
MeshRefC::set_rotation( const QuatC& rRot )
{
	m_rRotation = rRot;
}

const QuatC&
MeshRefC::get_rotation() const
{
	return m_rRotation;
}


int32
MeshRefC::get_flags() const
{
	return m_i32Flags;
}

void
MeshRefC::set_flags( int32 i32Flags )
{
	m_i32Flags = i32Flags;
}

void
MeshRefC::add_flags( int32 i32Flags )
{
	m_i32Flags |= i32Flags;
}

void
MeshRefC::del_flags( int32 i32Flags )
{
	m_i32Flags &= ~i32Flags;
}

void
MeshRefC::toggle_flags( int32 i32Flags )
{
	m_i32Flags ^= i32Flags;
}

void
MeshRefC::set_bounds( Vector3dC& rMin, Vector3dC& rMax )
{
	m_rMin = rMin;
	m_rMax = rMax;

	if( m_rMin == m_rMax )
		m_bBBoxEmpty = OS_TRUE;
	else
		m_bBBoxEmpty = OS_FALSE;
}

bool
MeshRefC::get_bounds( Vector3dC& rMin, Vector3dC& rMax )
{
	rMin = m_rMin;
	rMax = m_rMax;
	return m_bBBoxEmpty;
}

int32
MeshRefC::get_gizmo_count()
{
	return 0;
}

Vector3dC
MeshRefC::get_gizmo_pos( int32 i32Index )
{
	return Vector3dC();
}

int32
MeshRefC::get_type()
{
	return MESHREF_TYPE_NORMAL;
}


/*
void
MeshRefC::make_transform_cache( TransformCacheC** pPtrCache, OsTypes::int32 i32LODLevel );
{

	delete (*pPtrCache);
	(*pPtrCache) = 0;

	if( !m_pMesh )
		return;

	(*pPtrCache) = new TransformCacheC;

	TransformCacheC*	pCache = (*pPtrCache);

	for( uint32 i = 0; i < m_pMesh->get_geomlist_count( i32LODLevel ); i++ ) {
		GeomListC*	pList = m_pMesh->get_geomlist( i );
		pCache->add_list( pList->get_vertex_count() );
	}
}

void
MeshRefC::update_transform_cache( TransformCacheC** pCache, int32 i32LODLevel )
{
	TransformCacheC*	pCache = (*pPtrCache);
}

void
MeshRefC::update_transform_cache( int32 i32LODLevel )
{
	if( !m_pMesh )
		return;

	if( i32LODLevel == MESH_LOD_LEVEL_1 ) {
		if( !m_pTransCache0 )
			make_transform_cache( &m_pTransCache0, i32LODLevel );
		update_cachr
	}
	else if( i32LODLevel == MESH_LOD_LEVEL_2 ) {
		if( !m_pTransCache1 )
			make_transform_cache( &m_pTransCache1, i32LODLevel );
	}
	else if( i32LODLevel == MESH_LOD_LEVEL_3 ) {
		if( !m_pTransCache2 )
			make_transform_cache( &m_pTransCache2, i32LODLevel );
	}

}

TransformCacheC*
MeshRefC::get_transform_cache()
{
	if( !m_pMesh )
		return;
}
*/