//===========================================================================//
// File:	lattice.cc                                                          //
// Project: MUNGA           Brick: lattice Manager	                          //
// Contents: 																					  //
//---------------------------------------------------------------------------//
//   Date    Who  Modification                                               //
// --------  ---  ---------------------------------------------------------- //
// 12/20/94  ECH  Initial coding.                                            //
//---------------------------------------------------------------------------//
// Copyright (C) 1994-1995, Virtual World Entertainment, Inc.                //
// All Rights reserved worldwide                                             //
// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL               //
//===========================================================================//

#include <munga.hpp>
#pragma hdrstop

#if !defined(BOXSOLID_HPP)
#	include <boxsolid.hpp>
#endif

#if !defined(COLLORGN_HPP)
#	include <collorgn.hpp>
#endif

#if !defined(APP_HPP)
	#include <app.hpp>
#endif

#if !defined(NOTATION_HPP)
	#include <notation.hpp>
#endif

//#############################################################################
//###########################    LatticeZone    ###############################
//#############################################################################

LatticeZone::LatticeZone(const ExtentBox &extents):
	boundingBox(extents, this)
{
}

LatticeZone::~LatticeZone()
{
}

//#############################################################################
//#########################    EnvironmentZone    #############################
//#############################################################################

EnvironmentZone::EnvironmentZone(
	const ExtentBox &extents,
   const Environment &the_environment
):
	LatticeZone(extents)
{
   environment = the_environment;
}

EnvironmentZone::~EnvironmentZone()
{
}

Logical
	EnvironmentZone::TestInstance() const
{
	LatticeZone::TestInstance();
   Check(&environment);
	return True;
}

//#############################################################################
//###########################    InterestZone    ##############################
//#############################################################################

InterestZone::InterestZone(
   const ExtentBox &extents,
   InterestZoneID interest_zone_id,
   BoxedSolidTree *collision_root,
	EnvironmentZone *environment_zone,
	BoundingBoxTree *existance_root
):
	LatticeZone(extents)
{
	Verify(interest_zone_id != NullInterestZoneID);
	Check(collision_root);
	Check(environment_zone);
	Check(existance_root);

	interestZoneID = interest_zone_id;
	collisionRoot = collision_root;
	environmentZone = environment_zone;
	collisionOrigin = NULL;
	existanceRoot = existance_root;
}

InterestZone::~InterestZone()
{
	//
   // HACK - delete collision tree
   //
   Unregister_Object(collisionRoot);
   delete collisionRoot;
   collisionRoot = NULL;

	//
	// HACK - delete environment zone
	//
	Unregister_Object(environmentZone);
	delete environmentZone;
   environmentZone = NULL;

	//
	// HACK - delete existance tree
	//
	Unregister_Object(existanceRoot);
	delete existanceRoot;
   existanceRoot = NULL;

	//
	// HACK - delete collision origin
	//
	if (collisionOrigin != NULL)
	{
		Check(application);
		Check(application->GetInterestManager());
		application->GetInterestManager()->OrphanInterestOrigin(collisionOrigin);
		CollisionOrigin *col_origin = collisionOrigin;
		collisionOrigin = NULL;
		Unregister_Object(col_origin);
		delete col_origin;
	}
}

Logical
	InterestZone::TestInstance() const
{
	LatticeZone::TestInstance();

   Verify(interestZoneID != NullInterestZoneID);

	if (collisionOrigin != NULL)
	{
		Check(collisionOrigin);
	}
	if (collisionRoot != NULL)
	{
		Check(collisionRoot);
	}
	if (environmentZone != NULL)
	{
		Check(environmentZone);
	}
	if (existanceRoot != NULL)
	{
		Check(existanceRoot);
	}

	return True;
}

//#############################################################################
//###########################    InterestArena    #############################
//#############################################################################

InterestArena::InterestArena(InterestZone *interest_zone):
	interestZoneSocket(NULL)
{
   Check(interest_zone);
	Check(&interestZoneSocket);
   interestZoneSocket.Add(interest_zone);
}

InterestArena::~InterestArena()
{
	//
   // deconnect from interest zone
   //
	Check(&interestZoneSocket);
	#if DEBUG_LEVEL>0
		InterestZone *interest_zone = interestZoneSocket.GetCurrent();
		Check(interest_zone);
	#endif
	interestZoneSocket.Remove();

   #if 0
	//
   // If the interest zone is not in any interest arenas then delete
   //
   PlugIterator iterator(interest_zone);
   Check(&iterator);
   if (iterator.GetSize() == 0)
   {
   	Unregister_Object(interest_zone);
      delete interest_zone;
   }
	#endif
}

Logical
	InterestArena::TestInstance() const
{
	Node::TestInstance();
	Check(&interestZoneSocket);
	return True;
}

//#############################################################################
//###########################    LatticeManager    ############################
//#############################################################################

LatticeManager::LatticeManager()
{
}

LatticeManager::~LatticeManager()
{
}

//#############################################################################
//#######################    InterestLatticeManager    ########################
//#############################################################################

//
//#############################################################################
//#############################################################################
//
InterestLatticeManager::InterestLatticeManager():
	interestZoneSocket(NULL)
{
}

//
//#############################################################################
//#############################################################################
//
InterestLatticeManager::~InterestLatticeManager()
{
	InterestZone *interest_zone;

	Check(&interestZoneSocket);
	if ((interest_zone = interestZoneSocket.GetCurrent()) != NULL)
   {
      Unregister_Object(interest_zone);
      delete interest_zone;
   }
}

//
//#############################################################################
//#############################################################################
//
Logical
	InterestLatticeManager::TestInstance() const
{
	Node::TestInstance();
	Check(&interestZoneSocket);
	return True;
}

//
//#############################################################################
//#############################################################################
//
InterestArena*
	InterestLatticeManager::MakeInterestArena(
      InterestZoneID,
		InterestType,
      InterestDepth
	)
{
	Check(this);

	//
   //---------------------------------------------------------------------
   // HACK - See if the one interest zone has been created
   //---------------------------------------------------------------------
   //
	InterestZone *interest_zone;

	if ((interest_zone = interestZoneSocket.GetCurrent()) == NULL)
	{
		//
		//---------------------------------------------------------------------
		// Create the one environment
		//---------------------------------------------------------------------
		//
		EnvironmentZone *environment_zone;

		//
		// Make the memory stream
		//
		Check(application);
		ResourceFile *res_file = application->GetResourceFile();
		Check(res_file);

		ResourceDescription *resource_description =
			res_file->FindResourceDescription(
				"EnvironmentZone",
				ResourceDescription::EnvironmentZoneResourceType
			);
		if (resource_description)
		{
			Check(resource_description);
			resource_description->Lock();

			MemoryStream
				memory_stream(
					resource_description->resourceAddress,
					resource_description->resourceSize
				);

			//
			// Get the construction arguments
			//
			ExtentBox extent_box;
			Environment environment;

			memory_stream >> extent_box >> environment;

			resource_description->Unlock();

			//
			// Make the environment zone
			//
			environment_zone = new EnvironmentZone(extent_box, environment);
			Register_Object(environment_zone);
		}

		//
		//---------------------------------------------------------------------
		// Create the one interest zone
		//---------------------------------------------------------------------
		//
		resource_description =
			res_file->FindResourceDescription(
				"InterestZone",
				ResourceDescription::InterestZoneResourceType
			);
		if (resource_description)
		{
			Check(resource_description);
			resource_description->Lock();

			MemoryStream
				memory_stream(
					resource_description->resourceAddress,
					resource_description->resourceSize
				);

			//
			// Get the construction arguments
			//
			ExtentBox extent_box;
			InterestZoneID interest_zone_ID;
			CString map_resource_name;

			memory_stream >> extent_box >> interest_zone_ID >> map_resource_name;

			resource_description->Unlock();

			//
			// Make the collision tree root
			//
			BoxedSolidTree *collision_root = new BoxedSolidTree;
			Register_Object(collision_root);

			//
			// Make the existance tree root
			//
			BoundingBoxTree *existance_root = new BoundingBoxTree;
			Register_Object(existance_root);

			//
			// Make the interest zone
			//
			interest_zone =
				new InterestZone(
					extent_box,
					interest_zone_ID,
					collision_root,
					environment_zone,
					existance_root
				);
			Register_Object(interest_zone);
		}

		interestZoneSocket.Add(interest_zone);
		Verify(interest_zone == interestZoneSocket.GetCurrent());
	}
	Check(interest_zone);

	//
	//---------------------------------------------------------------------
	// Create an interest arena pointing at this zone
   //---------------------------------------------------------------------
   //
	return new InterestArena(interest_zone);
}
#if 0
InterestArena*
	InterestLatticeManager::MakeInterestArena(
      InterestZoneID,
		InterestType,
      InterestDepth
	)
{
	Check(this);

	//
   //---------------------------------------------------------------------
   // HACK - Create one interest zone
   //---------------------------------------------------------------------
   //
   InterestZone *interest_zone;

   if ((interest_zone = interestZoneSocket.GetCurrent()) == NULL)
   {
      const Scalar min_dimension = -100000.0f;
      const Scalar max_dimension = 100000.0f;

		Vector3D min_vector(min_dimension, min_dimension, min_dimension);
		Vector3D max_vector(max_dimension, max_dimension, max_dimension);
      ExtentBox big_extent(min_vector, max_vector);

      //
      // Pick one interest zone id
      //
      InterestZoneID interest_zone_ID = NullInterestZoneID + 1;

      //
      // Set up one environment
      //
      Environment environment;
      EnvironmentZone *environment_zone;

      environment.gravityConstant = 6.5f;
      environment.airDensity = 1.0f;
		environment.windVelocity = Vector3D::Identity;
		environment.ambientTemperature = 294.26f;   // Seventy degrees farenheit

		environment_zone = new EnvironmentZone(big_extent, environment);
		Register_Object(environment_zone);

		//
		// Load entire collision tree
		//
		BoxedSolidTree *collision_root = new BoxedSolidTree;
		Register_Object(collision_root);

		//
		// Make one interest zone for everything
		//
		interest_zone =
			new InterestZone(
				big_extent,
				interest_zone_ID,
				collision_root,
				environment_zone
			);
		Register_Object(interest_zone);

		interestZoneSocket.Add(interest_zone);
		Verify(interest_zone == interestZoneSocket.GetCurrent());
	}
	Check(interest_zone);

	//
	//---------------------------------------------------------------------
	// Create an interest arena pointing at this zone
	//---------------------------------------------------------------------
	//
	return new InterestArena(interest_zone);
}
#endif

#if 0
//
//#############################################################################
//#############################################################################
//
void
	InterestLatticeManager::DestroyInterestArena(InterestArena *interest_arena)
{
	Check(this);
   Check(interest_arena);

	//
   //---------------------------------------------------------------------
   // Delete the interest arena
   //---------------------------------------------------------------------
   //
   Unregister_Object(interest_arena);
   delete interest_arena;
}
#endif

//
//#############################################################################
//#############################################################################
//
InterestZoneID
	InterestLatticeManager::SearchForEntityInterestZone(
		InterestZoneID,
		const EntityID&
	)
{
	Check(this);
   Check(interestZoneSocket.GetCurrent());
	return interestZoneSocket.GetCurrent()->GetInterestZoneID();
}

//
//#############################################################################
//#############################################################################
//
InterestZone*
   InterestLatticeManager::GetInterestZone(InterestZoneID)
{
	Check(this);
	return interestZoneSocket.GetCurrent();
}

//
//#############################################################################
//#############################################################################
//
void
   InterestLatticeManager::CreateZoneResources(
   	ResourceFile *resource_file,
      NotationFile *zone_notation_file
   )
{
	Check(zone_notation_file);

   //
   //---------------------------------------------------------------------
   // HACK - Create the one environment zone resource
   //---------------------------------------------------------------------
	//
   {
      //
      // Environment zone construction arguments
      //
      ExtentBox extent_box;
      Environment environment;

      //
      // Get environment zone construction arguments
      //
		const char *contents;

		#if DEBUG_LEVEL>0
			int ret = zone_notation_file->GetEntry(
				"EnvironmentZone",
				"extent_box",
				&contents
			);
			Verify(ret);
		#else
			zone_notation_file->GetEntry(
				"EnvironmentZone",
				"extent_box",
				&contents
			);
		#endif
		Convert_From_Ascii(contents, &extent_box);

		#if DEBUG_LEVEL>0
			ret = zone_notation_file->GetEntry(
				"EnvironmentZone",
				"environment",
				&contents
			);
			Verify(ret);
		#else
			zone_notation_file->GetEntry(
				"EnvironmentZone",
				"environment",
				&contents
			);
		#endif
		Convert_From_Ascii(contents, &environment);

		//
		// Create environment zone memory stream
		//
		DynamicMemoryStream environment_zone_memory_stream;

		environment_zone_memory_stream << extent_box << environment;

		//
		// Add environment zone resource
		//
		CString environment_zone_resource_name("EnvironmentZone");

		#if DEBUG_LEVEL>0
			ResourceDescription *res_description =
				resource_file->AddResourceMemoryStream(
					environment_zone_resource_name,
					ResourceDescription::EnvironmentZoneResourceType,
					1,
					ResourceDescription::Preload,
					&environment_zone_memory_stream
				);
			Check(res_description);
		#else
			resource_file->AddResourceMemoryStream(
				environment_zone_resource_name,
				ResourceDescription::EnvironmentZoneResourceType,
				1,
				ResourceDescription::Preload,
				&environment_zone_memory_stream
			);
		#endif
	}

   //
   //---------------------------------------------------------------------
   // HACK - Create the one interest zone resource
   //---------------------------------------------------------------------
	//
   {
      //
      // Interest zone construction arguments
      //
      ExtentBox extent_box;
      InterestZoneID interest_zone_ID;
      CString map_resource_name;

		//
		// Get interest zone construction arguments
		//
		const char *contents;

		#if DEBUG_LEVEL>0
			int ret = zone_notation_file->GetEntry(
				"InterestZone",
				"extent_box",
				&contents
			);
			Verify(ret);
		#else
			zone_notation_file->GetEntry(
				"InterestZone",
				"extent_box",
				&contents
			);
		#endif
		Convert_From_Ascii(contents, &extent_box);

		#if DEBUG_LEVEL>0
			ret = zone_notation_file->GetEntry(
				"InterestZone",
				"interest_zone_ID",
				&contents
			);
			Verify(ret);
		#else
			zone_notation_file->GetEntry(
				"InterestZone",
				"interest_zone_ID",
				&contents
			);
		#endif
		Convert_From_Ascii(contents, &interest_zone_ID);

		#if DEBUG_LEVEL>0
			ret = zone_notation_file->GetEntry(
				"InterestZone",
				"map_resource_name",
				&contents
			);
			Verify(ret);
		#else
			zone_notation_file->GetEntry(
				"InterestZone",
				"map_resource_name",
				&contents
			);
		#endif
		map_resource_name = contents;

      //
      // Create interest zone memory stream
      //
      DynamicMemoryStream interest_zone_memory_stream;

		interest_zone_memory_stream << extent_box << interest_zone_ID;
		interest_zone_memory_stream << map_resource_name;

      //
      // Add interest zone resource
      //
		CString interest_zone_resource_name("InterestZone");

		#if DEBUG_LEVEL>0
			ResourceDescription *res_description =
				resource_file->AddResourceMemoryStream(
					interest_zone_resource_name,
					ResourceDescription::InterestZoneResourceType,
					1,
					ResourceDescription::Preload,
					&interest_zone_memory_stream
				);
			Check(res_description);
		#else
			resource_file->AddResourceMemoryStream(
				interest_zone_resource_name,
				ResourceDescription::InterestZoneResourceType,
				1,
				ResourceDescription::Preload,
				&interest_zone_memory_stream
			);
		#endif
	}
}

