text:
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======//
//
// Purpose:
//
// $Revision: $
// $NoKeywords: $
//
// This file contains code to allow us to associate client data with bsp leaves.
//===========================================================================//

#include "cbase.h"
#include "ClientLeafSystem.h"
#include "UtlBidirectionalSet.h"
#include "BSPTreeData.h"
#include "model_types.h"
#include "IVRenderView.h"
#include "tier0/vprof.h"
#include "DetailObjectSystem.h"
#include "engine/IStaticPropMgr.h"
#include "engine/IVDebugOverlay.h"

// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"

class VMatrix;  // forward decl

static ConVar cl_drawleaf("cl_drawleaf", "-1", FCVAR_CHEAT );
static ConVar r_PortalTestEnts( "r_PortalTestEnts", "1", FCVAR_CHEAT, "Clip entities against portal frustums." );
static ConVar r_portalsopenall( "r_portalsopenall", "1", FCVAR_CHEAT, "Open all portals" );

//-----------------------------------------------------------------------------
// The client leaf system
//-----------------------------------------------------------------------------
class CClientLeafSystem : public IClientLeafSystem, public ISpatialLeafEnumerator
{
public:
	virtual char const *Name() { return "CClientLeafSystem"; }

	// constructor, destructor
	CClientLeafSystem();
	virtual ~CClientLeafSystem();

	// Methods of IClientSystem
	bool Init() { return true; }
	void Shutdown() {}

	virtual bool IsPerFrame() { return true; }

	void PreRender();
	void PostRender() { }
	void Update( float frametime ) { }

	void LevelInitPreEntity();
	void LevelInitPostEntity() {}
	void LevelShutdownPreEntity();
	void LevelShutdownPostEntity();

	virtual void OnSave() {}
	virtual void OnRestore() {}
	virtual void SafeRemoveIfDesired() {}

// Methods of IClientLeafSystem
public:

	virtual void AddRenderable( IClientRenderable* pRenderable, RenderGroup_t group );
	virtual bool IsRenderableInPVS( IClientRenderable *pRenderable );
	virtual void CreateRenderableHandle( IClientRenderable* pRenderable, bool bIsStaticProp );
	virtual void RemoveRenderable( ClientRenderHandle_t handle );
	// FIXME: There's an incestuous relationship between DetailObjectSystem
	// and the ClientLeafSystem. Maybe they should be the same system?
	virtual void GetDetailObjectsInLeaf( int leaf, int& firstDetailObject, int& detailObjectCount );
 	virtual void SetDetailObjectsInLeaf( int leaf, int firstDetailObject, int detailObjectCount );
	virtual void DrawDetailObjectsInLeaf( int leaf, int frameNumber, int& nFirstDetailObject, int& nDetailObjectCount );
	virtual bool ShouldDrawDetailObjectsInLeaf( int leaf, int frameNumber );
	virtual void RenderableChanged( ClientRenderHandle_t handle );
	virtual void SetRenderGroup( ClientRenderHandle_t handle, RenderGroup_t group );
	virtual void ComputeTranslucentRenderLeaf( int count, LeafIndex_t *pLeafList, LeafFogVolume_t *pLeafFogVolumeList, int frameNumber );
	virtual void CollateViewModelRenderables( CUtlVector< IClientRenderable * >& opaque, CUtlVector< IClientRenderable * >& translucent );
	virtual void CollateRenderablesInLeaf( int leaf, int worldListLeafIndex, SetupRenderInfo_t &info );
	virtual void DrawStaticProps( bool enable );
	virtual void DrawSmallEntities( bool enable );
	virtual void EnableAlternateSorting( ClientRenderHandle_t handle, bool bEnable );

	// Adds a renderable to a set of leaves
	virtual void AddRenderableToLeaves( ClientRenderHandle_t handle, int nLeafCount, unsigned short *pLeaves );

	// The following methods are related to shadows...
	virtual ClientLeafShadowHandle_t AddShadow( unsigned short userId, unsigned short flags );
	virtual void RemoveShadow( ClientLeafShadowHandle_t h );

	virtual void ProjectShadow( ClientLeafShadowHandle_t handle, const Vector& origin,
					const Vector& dir, const Vector2D& size, float maxDist );
	virtual void ProjectFlashlight( ClientLeafShadowHandle_t handle, const VMatrix &worldToShadow );

	// Find all shadow casters in a set of leaves
	virtual void EnumerateShadowsInLeaves( int leafCount, LeafIndex_t* pLeaves, IClientLeafShadowEnum* pEnum );

	// methods of ISpatialLeafEnumerator
public:

	bool EnumerateLeaf( int leaf, int context );

	// Adds a shadow to a leaf
	void AddShadowToLeaf( int leaf, ClientLeafShadowHandle_t handle );

	// Fill in a list of the leaves this renderable is in.
	// Returns -1 if the handle is invalid.
	int GetRenderableLeaves( ClientRenderHandle_t handle, int leaves[128] );

	// Get leaves this renderable is in
	virtual bool GetRenderableLeaf ( ClientRenderHandle_t handle, int* pOutLeaf, const int* pInIterator = 0, int* pOutIterator = 0 );

	// Singleton instance...
	static CClientLeafSystem s_ClientLeafSystem;

private:
	// Creates a new renderable
	void NewRenderable( IClientRenderable* pRenderable, RenderGroup_t type, int flags = 0 );

	// Adds a renderable to the list of renderables
	void AddRenderableToLeaf( int leaf, ClientRenderHandle_t handle );

	// Returns -1 if the renderable spans more than one area. If it's totally in one area, then this returns the leaf.
	short GetRenderableArea( ClientRenderHandle_t handle );

	// insert, remove renderables from leaves
	void InsertIntoTree( ClientRenderHandle_t handle );
	void RemoveFromTree( ClientRenderHandle_t handle );

	// Returns if it's a view model render group
	inline bool IsViewModelRenderGroup( RenderGroup_t group ) const;

	// Adds, removes renderables from view model list
	void AddToViewModelList( ClientRenderHandle_t handle );
	void RemoveFromViewModelList( ClientRenderHandle_t handle );

	// Insert translucent renderables into list of translucent objects
	void InsertTranslucentRenderable( IClientRenderable* pRenderable,
		int& count, IClientRenderable** pList, float* pDist );

	// Used to change renderables from translucent to opaque
	// Only really used by the static prop fading...
	void ChangeRenderableRenderGroup( ClientRenderHandle_t handle, RenderGroup_t group );

	// Adds a shadow to a leaf/removes shadow from renderable
	void AddShadowToRenderable( ClientRenderHandle_t renderHandle, ClientLeafShadowHandle_t shadowHandle );
	void RemoveShadowFromRenderables( ClientLeafShadowHandle_t handle );

	// Adds a shadow to a leaf/removes shadow from renderable
	bool ShouldRenderableReceiveShadow( ClientRenderHandle_t renderHandle, int nShadowFlags );

	// Adds a shadow to a leaf/removes shadow from leaf
	void RemoveShadowFromLeaves( ClientLeafShadowHandle_t handle );

	// Methods associated with the various bi-directional sets
	static unsigned short& FirstRenderableInLeaf( int leaf )
	{
		return s_ClientLeafSystem.m_Leaf[leaf].m_FirstElement;
	}

	static unsigned short& FirstLeafInRenderable( unsigned short renderable )
	{
		return s_ClientLeafSystem.m_Renderables[renderable].m_LeafList;
	}

	static unsigned short& FirstShadowInLeaf( int leaf )
	{
		return s_ClientLeafSystem.m_Leaf[leaf].m_FirstShadow;
	}

	static unsigned short& FirstLeafInShadow( ClientLeafShadowHandle_t shadow )
	{
		return s_ClientLeafSystem.m_Shadows[shadow].m_FirstLeaf;
	}

	static unsigned short& FirstShadowOnRenderable( unsigned short renderable )
	{
		return s_ClientLeafSystem.m_Renderables[renderable].m_FirstShadow;
	}

	static unsigned short& FirstRenderableInShadow( ClientLeafShadowHandle_t shadow )
	{
		return s_ClientLeafSystem.m_Shadows[shadow].m_FirstRenderable;
	}

private:
	enum
	{
		RENDER_FLAGS_TWOPASS		= 0x01,
		RENDER_FLAGS_STATIC_PROP	= 0x02,
		RENDER_FLAGS_BRUSH_MODEL	= 0x04,
		RENDER_FLAGS_STUDIO_MODEL	= 0x08,
		RENDER_FLAGS_HASCHANGED		= 0x10,
		RENDER_FLAGS_ALTERNATE_SORTING = 0x20,
	};

	// All the information associated with a particular handle
	struct RenderableInfo_t
	{
		IClientRenderable*	m_pRenderable;
		int					m_RenderFrame;	// which frame did I render it in?
		int					m_RenderFrame2;
		int					m_EnumCount;	// Have I been added to a particular shadow yet?
		unsigned short		m_LeafList;		// What leafs is it in?
		unsigned short		m_RenderLeaf;	// What leaf do I render in?
		unsigned char		m_Flags;		// rendering flags
		unsigned char		m_RenderGroup;	// RenderGroup_t type
		unsigned short		m_FirstShadow;	// The first shadow caster that cast on it
		short m_Area;	// -1 if the renderable spans multiple areas.
	};

	// The leaf contains an index into a list of renderables
	struct ClientLeaf_t
	{
		unsigned short	m_FirstElement;
		unsigned short	m_FirstShadow;

		// An optimization for detail objects since there are tens
		// of thousands of them, and since we're assuming they lie in
		// exactly one leaf (a bogus assumption, but too bad)
		unsigned short	m_FirstDetailProp;
		unsigned short	m_DetailPropCount;
		int				m_DetailPropRenderFrame;
	};

	// Shadow information
	struct ShadowInfo_t
	{
		unsigned short	m_FirstLeaf;
		unsigned short	m_FirstRenderable;
		int				m_EnumCount;
		unsigned short	m_Shadow;
		unsigned short	m_Flags;
	};

	// Stores data associated with each leaf.
	CUtlVector< ClientLeaf_t >	m_Leaf;

	// Stores all unique non-detail renderables
	CUtlLinkedList< RenderableInfo_t, ClientRenderHandle_t >	m_Renderables;

	// Information associated with shadows registered with the client leaf system
	CUtlLinkedList< ShadowInfo_t, ClientLeafShadowHandle_t >	m_Shadows;

	// Maintains the list of all renderables in a particular leaf
	CBidirectionalSet< int, ClientRenderHandle_t, unsigned short >	m_RenderablesInLeaf;

	// Maintains a list of all shadows in a particular leaf
	CBidirectionalSet< int, ClientLeafShadowHandle_t, unsigned short >	m_ShadowsInLeaf;

	// Maintains a list of all shadows cast on a particular renderable
	CBidirectionalSet< ClientRenderHandle_t, ClientLeafShadowHandle_t, unsigned short >	m_ShadowsOnRenderable;

	// Dirty list of renderables
	CUtlVector< ClientRenderHandle_t >	m_DirtyRenderables;

	// List of renderables in view model render groups
	CUtlVector< ClientRenderHandle_t >	m_ViewModels;

	// Should I draw static props?
	bool m_DrawStaticProps;
	bool m_DrawSmallObjects;

	// A little enumerator to help us when adding shadows to renderables
	int	m_ShadowEnum;
};

//-----------------------------------------------------------------------------
// Expose IClientLeafSystem to the client dll.
//-----------------------------------------------------------------------------
CClientLeafSystem CClientLeafSystem::s_ClientLeafSystem;
IClientLeafSystem *g_pClientLeafSystem = &CClientLeafSystem::s_ClientLeafSystem;
EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CClientLeafSystem, IClientLeafSystem, CLIENTLEAFSYSTEM_INTERFACE_VERSION, CClientLeafSystem::s_ClientLeafSystem );

void CalcRenderableWorldSpaceAABB_Fast( IClientRenderable *pRenderable, Vector &absMin, Vector &absMax );

//-----------------------------------------------------------------------------
// Helper functions.
//-----------------------------------------------------------------------------
void DefaultRenderBoundsWorldspace( IClientRenderable *pRenderable, Vector &absMins, Vector &absMaxs )
{
	// Tracker 37433:  This fixes a bug where if the stunstick is being wielded by a combine soldier, the fact that the stick was
	//  attached to the soldier's hand would move it such that it would get frustum culled near the edge of the screen.
	C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity();
	if ( pEnt && pEnt->IsFollowingEntity() )
	{
		C_BaseEntity *pParent = pEnt->GetFollowedEntity();
		if ( pParent )
		{
			// Get the parent's abs space world bounds.
			CalcRenderableWorldSpaceAABB_Fast( pParent, absMins, absMaxs );

			// Add the maximum of our local render bounds. This is making the assumption that we can be at any
			// point and at any angle within the parent's world space bounds.
			Vector vAddMins, vAddMaxs;
			pEnt->GetRenderBounds( vAddMins, vAddMaxs );
			// if our origin is actually farther away than that, expand again
			float radius = pEnt->GetLocalOrigin().Length();

			float flBloatSize = max( vAddMins.Length(), vAddMaxs.Length() );
			flBloatSize = max(flBloatSize, radius);
			absMins -= Vector( flBloatSize, flBloatSize, flBloatSize );
			absMaxs += Vector( flBloatSize, flBloatSize, flBloatSize );
			return;
		}
	}

	Vector mins, maxs;
	pRenderable->GetRenderBounds( mins, maxs );

	// FIXME: Should I just use a sphere here?
	// Another option is to pass the OBB down the tree; makes for a better fit
	// Generate a world-aligned AABB
	const QAngle& angles = pRenderable->GetRenderAngles();
	const Vector& origin = pRenderable->GetRenderOrigin();
	if (angles == vec3_angle)
	{
		VectorAdd( mins, origin, absMins );
		VectorAdd( maxs, origin, absMaxs );
	}
	else
	{
		matrix3x4_t	boxToWorld;
		AngleMatrix( angles, origin, boxToWorld );
		TransformAABB( boxToWorld, mins, maxs, absMins, absMaxs );
	}
	Assert( absMins.IsValid() && absMaxs.IsValid() );
}

// Figure out a world space bounding box that encloses the entity's local render bounds in world space.
inline void CalcRenderableWorldSpaceAABB(
	IClientRenderable *pRenderable,
	Vector &absMins,
	Vector &absMaxs )
{
	pRenderable->GetRenderBoundsWorldspace( absMins, absMaxs );
}

// This gets an AABB for the renderable, but it doesn't cause a parent's bones to be setup.
// This is used for placement in the leaves, but the more expensive version is used for culling.
void CalcRenderableWorldSpaceAABB_Fast( IClientRenderable *pRenderable, Vector &absMin, Vector &absMax )
{
	C_BaseEntity *pEnt = pRenderable->GetIClientUnknown()->GetBaseEntity();
	if ( pEnt && pEnt->IsFollowingEntity() )
	{
		C_BaseEntity *pParent = pEnt->GetMoveParent();
		Assert( pParent );

		// Get the parent's abs space world bounds.
		CalcRenderableWorldSpaceAABB_Fast( pParent, absMin, absMax );

		// Add the maximum of our local render bounds. This is making the assumption that we can be at any
		// point and at any angle within the parent's world space bounds.
		Vector vAddMins, vAddMaxs;
		pEnt->GetRenderBounds( vAddMins, vAddMaxs );
		// if our origin is actually farther away than that, expand again
		float radius = pEnt->GetLocalOrigin().Length();

		float flBloatSize = max( vAddMins.Length(), vAddMaxs.Length() );
		flBloatSize = max(flBloatSize, radius);
		absMin -= Vector( flBloatSize, flBloatSize, flBloatSize );
		absMax += Vector( flBloatSize, flBloatSize, flBloatSize );
	}
	else
	{
		// Start out with our own render bounds. Since we don't have a parent, this won't incur any nasty
		CalcRenderableWorldSpaceAABB( pRenderable, absMin, absMax );
	}
}

//-----------------------------------------------------------------------------
// constructor, destructor
//-----------------------------------------------------------------------------
CClientLeafSystem::CClientLeafSystem() : m_DrawStaticProps(true), m_DrawSmallObjects(true)
{
	// Set up the bi-directional lists...
	m_RenderablesInLeaf.Init( FirstRenderableInLeaf, FirstLeafInRenderable );
	m_ShadowsInLeaf.Init( FirstShadowInLeaf, FirstLeafInShadow );
	m_ShadowsOnRenderable.Init( FirstShadowOnRenderable, FirstRenderableInShadow );
}

CClientLeafSystem::~CClientLeafSystem()
{
}

//-----------------------------------------------------------------------------
// Activate, deactivate static props
//-----------------------------------------------------------------------------
void CClientLeafSystem::DrawStaticProps( bool enable )
{
	m_DrawStaticProps = enable;
}

void CClientLeafSystem::DrawSmallEntities( bool enable )
{
	m_DrawSmallObjects = enable;
}

//-----------------------------------------------------------------------------
// Level init, shutdown
//-----------------------------------------------------------------------------
void CClientLeafSystem::LevelInitPreEntity()
{
	MEM_ALLOC_CREDIT();

	m_Renderables.EnsureCapacity( 1024 );
	m_RenderablesInLeaf.EnsureCapacity( 1024 );
	m_ShadowsInLeaf.EnsureCapacity( 256 );
	m_ShadowsOnRenderable.EnsureCapacity( 256 );
	m_DirtyRenderables.EnsureCapacity( 256 );

	// Add all the leaves we'll need
	int leafCount = engine->LevelLeafCount();
	m_Leaf.EnsureCapacity( leafCount );

	ClientLeaf_t newLeaf;
	newLeaf.m_FirstElement = m_RenderablesInLeaf.InvalidIndex();
	newLeaf.m_FirstShadow = m_ShadowsInLeaf.InvalidIndex();
	newLeaf.m_FirstDetailProp = 0;
	newLeaf.m_DetailPropCount = 0;
	newLeaf.m_DetailPropRenderFrame = -1;
	while ( --leafCount >= 0 )
	{
		m_Leaf.AddToTail( newLeaf );
	}
}

void CClientLeafSystem::LevelShutdownPreEntity()
{
}

void CClientLeafSystem::LevelShutdownPostEntity()
{
	m_ViewModels.Purge();
	m_Renderables.Purge();
	m_RenderablesInLeaf.Purge();
	m_Shadows.Purge();
	m_Leaf.Purge();
	m_ShadowsInLeaf.Purge();
	m_ShadowsOnRenderable.Purge();
	m_DirtyRenderables.Purge();
}

//-----------------------------------------------------------------------------
// This is what happens before rendering a particular view
//-----------------------------------------------------------------------------
void CClientLeafSystem::PreRender()
{
	VPROF( "CClientLeafSystem::PreRender" );

	// Iterate through all renderables and tell them to compute their FX blend
	for ( int i = m_DirtyRenderables.Count(); --i >= 0; )
	{
		ClientRenderHandle_t handle = m_DirtyRenderables[i];
		RenderableInfo_t& renderable = m_Renderables[ handle ];

		Assert( renderable.m_Flags & RENDER_FLAGS_HASCHANGED );

		// Update position in leaf system
		RemoveFromTree( handle );
		InsertIntoTree( handle );
		renderable.m_Flags &= ~RENDER_FLAGS_HASCHANGED;
	}
	m_DirtyRenderables.RemoveAll();
}

//-----------------------------------------------------------------------------
// Creates a new renderable
//-----------------------------------------------------------------------------
void CClientLeafSystem::NewRenderable( IClientRenderable* pRenderable, RenderGroup_t type, int flags )
{
	Assert( pRenderable );
	Assert( pRenderable->RenderHandle() == INVALID_CLIENT_RENDER_HANDLE );

	ClientRenderHandle_t handle = m_Renderables.AddToTail();
	RenderableInfo_t &info = m_Renderables[handle];

	// We need to know if it's a brush model for shadows
	int modelType = modelinfo->GetModelType( pRenderable->GetModel() );
	if (modelType == mod_brush)
	{
		flags |= RENDER_FLAGS_BRUSH_MODEL;
	}
	else if ( modelType == mod_studio )
	{
		flags |= RENDER_FLAGS_STUDIO_MODEL;
	}

	info.m_pRenderable = pRenderable;
	info.m_RenderFrame = -1;
	info.m_RenderFrame2 = -1;
	info.m_FirstShadow = m_ShadowsOnRenderable.InvalidIndex();
	info.m_LeafList = m_RenderablesInLeaf.InvalidIndex();
	info.m_Flags = flags;
	info.m_RenderGroup = (unsigned char)type;
	info.m_EnumCount = 0;
	info.m_RenderLeaf = 0xFFFF;
	if ( IsViewModelRenderGroup( (RenderGroup_t)info.m_RenderGroup ) )
	{
		AddToViewModelList( handle );
	}

	pRenderable->RenderHandle() = handle;
}

void CClientLeafSystem::CreateRenderableHandle( IClientRenderable* pRenderable, bool bIsStaticProp )
{
	// FIXME: The argument is unnecessary if we could get this next line to work
	// the reason why we can't is because currently there are IClientRenderables
	// which don't correctly implement GetRefEHandle.

	//bool bIsStaticProp = staticpropmgr->IsStaticProp( pRenderable->GetIClientUnknown() );

	// Add the prop to all the leaves it lies in
	RenderGroup_t group = pRenderable->IsTransparent() ? RENDER_GROUP_TRANSLUCENT_ENTITY : RENDER_GROUP_OPAQUE_ENTITY;

	bool bTwoPass = false;
	if (group == RENDER_GROUP_TRANSLUCENT_ENTITY)
		bTwoPass = modelinfo->IsTranslucentTwoPass( pRenderable->GetModel() );

	int flags = 0;
	if ( bIsStaticProp )
	{
		flags = RENDER_FLAGS_STATIC_PROP;
		if ( group == RENDER_GROUP_OPAQUE_ENTITY )
			group = RENDER_GROUP_OPAQUE_STATIC;
	}

	if (bTwoPass)
		flags |= RENDER_FLAGS_TWOPASS;

	NewRenderable( pRenderable, group, flags );
}

//-----------------------------------------------------------------------------
// Used to change renderables from translucent to opaque
//-----------------------------------------------------------------------------
void CClientLeafSystem::ChangeRenderableRenderGroup( ClientRenderHandle_t handle, RenderGroup_t group )
{
	RenderableInfo_t &info = m_Renderables[handle];
	info.m_RenderGroup = (unsigned char)group;
}

//-----------------------------------------------------------------------------
// Use alternate translucent sorting algorithm (draw translucent objects in the furthest leaf they lie in)
//-----------------------------------------------------------------------------
void CClientLeafSystem::EnableAlternateSorting( ClientRenderHandle_t handle, bool bEnable )
{
	RenderableInfo_t &info = m_Renderables[handle];
	if ( bEnable )
	{
		info.m_Flags |= RENDER_FLAGS_ALTERNATE_SORTING;
	}
	else
	{
		info.m_Flags &= ~RENDER_FLAGS_ALTERNATE_SORTING;
	}
}

//-----------------------------------------------------------------------------
// Add/remove renderable
//-----------------------------------------------------------------------------
void CClientLeafSystem::AddRenderable( IClientRenderable* pRenderable, RenderGroup_t group )
{
	// force a relink we we try to draw it for the first time
	int flags = RENDER_FLAGS_HASCHANGED;

	if ( group == RENDER_GROUP_TWOPASS )
	{
		group = RENDER_GROUP_TRANSLUCENT_ENTITY;
		flags |= RENDER_FLAGS_TWOPASS;
	}

	NewRenderable( pRenderable, group, flags );
	ClientRenderHandle_t handle = pRenderable->RenderHandle();
	m_DirtyRenderables.AddToTail( handle );
}

void CClientLeafSystem::RemoveRenderable( ClientRenderHandle_t handle )
{
	// This can happen upon level shutdown
	if (!m_Renderables.IsValidIndex(handle))
		return;

	// Reset the render handle in the entity.
	IClientRenderable *pRenderable = m_Renderables[handle].m_pRenderable;
	Assert( handle == pRenderable->RenderHandle() );
	pRenderable->RenderHandle() = INVALID_CLIENT_RENDER_HANDLE;

	// Reemove the renderable from the dirty list
	if ( m_Renderables[handle].m_Flags & RENDER_FLAGS_HASCHANGED )
	{
		// NOTE: This isn't particularly fast (linear search),
		// but I'm assuming it's an unusual case where we remove
		// renderables that are changing or that m_DirtyRenderables usually
		// only has a couple entries
		int i = m_DirtyRenderables.Find( handle );
		Assert( i != m_DirtyRenderables.InvalidIndex() );
		m_DirtyRenderables.FastRemove( i );
	}

	if ( IsViewModelRenderGroup( (RenderGroup_t)m_Renderables[handle].m_RenderGroup ) )
	{
		RemoveFromViewModelList( handle );
	}

	RemoveFromTree( handle );
	m_Renderables.Remove( handle );
}

int CClientLeafSystem::GetRenderableLeaves( ClientRenderHandle_t handle, int leaves[128] )
{
	if ( !m_Renderables.IsValidIndex( handle ) )
		return -1;

	RenderableInfo_t *pRenderable = &m_Renderables[handle];
	if ( pRenderable->m_LeafList == m_RenderablesInLeaf.InvalidIndex() )
		return -1;

	int nLeaves = 0;
	for ( int i=m_RenderablesInLeaf.FirstBucket( handle ); i != m_RenderablesInLeaf.InvalidIndex(); i = m_RenderablesInLeaf.NextBucket( i ) )
	{
		leaves[nLeaves++] = m_RenderablesInLeaf.Bucket( i );
		if ( nLeaves >= 128 )
			break;
	}
	return nLeaves;
}

//-----------------------------------------------------------------------------
// Retrieve leaf handles to leaves a renderable is in
// the pOutLeaf parameter is filled with the leaf the renderable is in.
// If pInIterator is not specified, pOutLeaf is the first leaf in the list.
// if pInIterator is specified, that iterator is used to return the next leaf
// in the list in pOutLeaf.
// the pOutIterator parameter is filled with the iterater which index to the pOutLeaf returned.
//
// Returns false on failure cases where pOutLeaf will be invalid. CHECK THE RETURN!
//-----------------------------------------------------------------------------
bool CClientLeafSystem::GetRenderableLeaf(ClientRenderHandle_t handle, int* pOutLeaf, const int* pInIterator /* = 0 */, int* pOutIterator /* = 0  */)
{
	// bail on invalid handle
	if ( !m_Renderables.IsValidIndex( handle ) )
		return false;

	// bail on no output value pointer
	if ( !pOutLeaf )
		return false;

	// an iterator was specified
	if ( pInIterator )
	{
		int iter = *pInIterator;

		// test for invalid iterator
		if ( iter == m_RenderablesInLeaf.InvalidIndex() )
			return false;

		int iterNext =  m_RenderablesInLeaf.NextBucket( iter );

		// test for end of list
		if ( iterNext == m_RenderablesInLeaf.InvalidIndex() )
			return false;

		// Give the caller the iterator used
		if ( pOutIterator )
		{
			*pOutIterator = iterNext;
		}

		// set output value to the next leaf
		*pOutLeaf = m_RenderablesInLeaf.Bucket( iterNext );

	}
	else // no iter param, give them the first bucket in the renderable's list
	{
		int iter = m_RenderablesInLeaf.FirstBucket( handle );

		if ( iter == m_RenderablesInLeaf.InvalidIndex() )
			return false;

		// Set output value to this leaf
		*pOutLeaf = m_RenderablesInLeaf.Bucket( iter );

		// give this iterator to caller
		if ( pOutIterator )
		{
			*pOutIterator = iter;
		}

	}

	return true;
}

bool CClientLeafSystem::IsRenderableInPVS( IClientRenderable *pRenderable )
{
	ClientRenderHandle_t handle = pRenderable->RenderHandle();
	int leaves[128];
	int nLeaves = GetRenderableLeaves( handle, leaves );
	if ( nLeaves == -1 )
		return false;

	// Ask the engine if this guy is visible.
	return render->AreAnyLeavesVisible( leaves, nLeaves );
}

short CClientLeafSystem::GetRenderableArea( ClientRenderHandle_t handle )
{
	int leaves[128];
	int nLeaves = GetRenderableLeaves( handle, leaves );
	if ( nLeaves == -1 )
		return 0;

	// Now ask the
	return engine->GetLeavesArea( leaves, nLeaves );
}

//-----------------------------------------------------------------------------
// Indicates which leaves detail objects are in
//-----------------------------------------------------------------------------
void CClientLeafSystem::SetDetailObjectsInLeaf( int leaf, int firstDetailObject,
											    int detailObjectCount )
{
	m_Leaf[leaf].m_FirstDetailProp = firstDetailObject;
	m_Leaf[leaf].m_DetailPropCount = detailObjectCount;
}

//-----------------------------------------------------------------------------
// Returns the detail objects in a leaf
//-----------------------------------------------------------------------------
void CClientLeafSystem::GetDetailObjectsInLeaf( int leaf, int& firstDetailObject,
											    int& detailObjectCount )
{
	firstDetailObject = m_Leaf[leaf].m_FirstDetailProp;
	detailObjectCount = m_Leaf[leaf].m_DetailPropCount;
}

//-----------------------------------------------------------------------------
// Create/destroy shadows...
//-----------------------------------------------------------------------------
ClientLeafShadowHandle_t CClientLeafSystem::AddShadow( unsigned short userId, unsigned short flags )
{
	ClientLeafShadowHandle_t idx = m_Shadows.AddToTail();
	m_Shadows[idx].m_Shadow = userId;
	m_Shadows[idx].m_FirstLeaf = m_ShadowsInLeaf.InvalidIndex();
	m_Shadows[idx].m_FirstRenderable = m_ShadowsOnRenderable.InvalidIndex();
	m_Shadows[idx].m_EnumCount = 0;
	m_Shadows[idx].m_Flags = flags;
	return idx;
}

void CClientLeafSystem::RemoveShadow( ClientLeafShadowHandle_t handle )
{
	// Remove the shadow from all leaves + renderables...
	RemoveShadowFromLeaves( handle );
	RemoveShadowFromRenderables( handle );

	// Blow away the handle
	m_Shadows.Remove( handle );
}

//-----------------------------------------------------------------------------
// Adds a shadow to a leaf/removes shadow from renderable
//-----------------------------------------------------------------------------
inline bool CClientLeafSystem::ShouldRenderableReceiveShadow( ClientRenderHandle_t renderHandle, int nShadowFlags )
{
	RenderableInfo_t &renderable = m_Renderables[renderHandle];
	if( !( renderable.m_Flags & ( RENDER_FLAGS_BRUSH_MODEL | RENDER_FLAGS_STATIC_PROP | RENDER_FLAGS_STUDIO_MODEL ) ) )
		return false;

	return renderable.m_pRenderable->ShouldReceiveProjectedTextures( nShadowFlags );
}

//-----------------------------------------------------------------------------
// Adds a shadow to a leaf/removes shadow from renderable
//-----------------------------------------------------------------------------
void CClientLeafSystem::AddShadowToRenderable( ClientRenderHandle_t renderHandle,
										ClientLeafShadowHandle_t shadowHandle )
{
	// Check if this renderable receives the type of projected texture that shadowHandle refers to.
	int nShadowFlags = m_Shadows[shadowHandle].m_Flags;
	if ( !ShouldRenderableReceiveShadow( renderHandle, nShadowFlags ) )
		return;

	m_ShadowsOnRenderable.AddElementToBucket( renderHandle, shadowHandle );

	// Also, do some stuff specific to the particular types of renderables

	// If the renderable is a brush model, then add this shadow to it
	if (m_Renderables[renderHandle].m_Flags & RENDER_FLAGS_BRUSH_MODEL)
	{
		IClientRenderable* pRenderable = m_Renderables[renderHandle].m_pRenderable;
		g_pClientShadowMgr->AddShadowToReceiver( m_Shadows[shadowHandle].m_Shadow,
			pRenderable, SHADOW_RECEIVER_BRUSH_MODEL );
	}
	else if( m_Renderables[renderHandle].m_Flags & RENDER_FLAGS_STATIC_PROP )
	{
		IClientRenderable* pRenderable = m_Renderables[renderHandle].m_pRenderable;
		g_pClientShadowMgr->AddShadowToReceiver( m_Shadows[shadowHandle].m_Shadow,
			pRenderable, SHADOW_RECEIVER_STATIC_PROP );
	}
	else if( m_Renderables[renderHandle].m_Flags & RENDER_FLAGS_STUDIO_MODEL )
	{
		IClientRenderable* pRenderable = m_Renderables[renderHandle].m_pRenderable;
		g_pClientShadowMgr->AddShadowToReceiver( m_Shadows[shadowHandle].m_Shadow,
			pRenderable, SHADOW_RECEIVER_STUDIO_MODEL );
	}
}

void CClientLeafSystem::RemoveShadowFromRenderables( ClientLeafShadowHandle_t handle )
{
	m_ShadowsOnRenderable.RemoveElement( handle );
}

//-----------------------------------------------------------------------------
// Adds a shadow to a leaf/removes shadow from leaf
//-----------------------------------------------------------------------------
void CClientLeafSystem::AddShadowToLeaf( int leaf, ClientLeafShadowHandle_t shadow )
{
	m_ShadowsInLeaf.AddElementToBucket( leaf, shadow );

	// Add the shadow exactly once to all renderables in the leaf
	unsigned short i = m_RenderablesInLeaf.FirstElement( leaf );
	while ( i != m_RenderablesInLeaf.InvalidIndex() )
	{
		ClientRenderHandle_t renderable = m_RenderablesInLeaf.Element(i);
		RenderableInfo_t& info = m_Renderables[renderable];

		// Add each shadow exactly once to each renderable
		if (info.m_EnumCount != m_ShadowEnum)
		{
			AddShadowToRenderable( renderable, shadow );
			info.m_EnumCount = m_ShadowEnum;
		}

		i = m_RenderablesInLeaf.NextElement(i);
	}
}

void CClientLeafSystem::RemoveShadowFromLeaves( ClientLeafShadowHandle_t handle )
{
	m_ShadowsInLeaf.RemoveElement( handle );
}

//-----------------------------------------------------------------------------
// Adds a shadow to all leaves along a ray
//-----------------------------------------------------------------------------
class CShadowLeafEnum : public ISpatialLeafEnumerator
{
public:
	bool EnumerateLeaf( int leaf, int context )
	{
		CClientLeafSystem::s_ClientLeafSystem.AddShadowToLeaf( leaf, (ClientLeafShadowHandle_t)context );
		return true;
	}
};

void CClientLeafSystem::ProjectShadow( ClientLeafShadowHandle_t handle, const Vector& origin,
					const Vector& dir, const Vector2D& size, float maxDist )
{
	// Remove the shadow from any leaves it current exists in
	RemoveShadowFromLeaves( handle );
	RemoveShadowFromRenderables( handle );

	Assert( ( m_Shadows[handle].m_Flags & SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK ) == SHADOW_FLAGS_SHADOW );

	// This will help us to avoid adding the shadow multiple times to a renderable
	++m_ShadowEnum;

	// Create a ray starting at the origin, with a boxsize == to the
	// maximum size, and cast it along the direction of the shadow
	// Then mark each leaf that the ray hits with the shadow
	Ray_t ray;
	VectorCopy( origin, ray.m_Start );
	VectorMultiply( dir, maxDist, ray.m_Delta );
	ray.m_StartOffset.Init( 0, 0, 0 );

	float maxsize = max( size.x, size.y ) * 0.5f;
	ray.m_Extents.Init( maxsize, maxsize, maxsize );
	ray.m_IsRay = false;
	ray.m_IsSwept = true;

	CShadowLeafEnum leafEnum;
	ISpatialQuery* pQuery = engine->GetBSPTreeQuery();
	pQuery->EnumerateLeavesAlongRay( ray, &leafEnum, handle );
}

void CClientLeafSystem::ProjectFlashlight( ClientLeafShadowHandle_t handle, const VMatrix &worldToShadow )
{
	// Remove the shadow from any leaves it current exists in
	RemoveShadowFromLeaves( handle );
	RemoveShadowFromRenderables( handle );

	Assert( ( m_Shadows[handle].m_Flags & SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK ) == SHADOW_FLAGS_FLASHLIGHT );

	// This will help us to avoid adding the shadow multiple times to a renderable
	++m_ShadowEnum;

	// Use an AABB around the frustum to enumerate leaves.
	Vector mins, maxs;
	CalculateAABBFromProjectionMatrix( worldToShadow, &mins, &maxs );

	CShadowLeafEnum leafEnum;
	ISpatialQuery* pQuery = engine->GetBSPTreeQuery();
	pQuery->EnumerateLeavesInBox( mins, maxs, &leafEnum, handle );
}

//-----------------------------------------------------------------------------
// Find all shadow casters in a set of leaves
//-----------------------------------------------------------------------------
void CClientLeafSystem::EnumerateShadowsInLeaves( int leafCount, LeafIndex_t* pLeaves, IClientLeafShadowEnum* pEnum )
{
	if (leafCount == 0)
		return;

	// This will help us to avoid enumerating the shadow multiple times
	++m_ShadowEnum;

	for (int i = 0; i < leafCount; ++i)
	{
		int leaf = pLeaves[i];

		unsigned short j = m_ShadowsInLeaf.FirstElement( leaf );
		while ( j != m_ShadowsInLeaf.InvalidIndex() )
		{
			ClientLeafShadowHandle_t shadow = m_ShadowsInLeaf.Element(j);
			ShadowInfo_t& info = m_Shadows[shadow];

			if (info.m_EnumCount != m_ShadowEnum)
			{
				pEnum->EnumShadow(info.m_Shadow);
				info.m_EnumCount = m_ShadowEnum;
			}

			j = m_ShadowsInLeaf.NextElement(j);
		}
	}
}

//-----------------------------------------------------------------------------
// Adds a renderable to a leaf
//-----------------------------------------------------------------------------
void CClientLeafSystem::AddRenderableToLeaf( int leaf, ClientRenderHandle_t renderable )
{
	m_RenderablesInLeaf.AddElementToBucket( leaf, renderable );

	if ( !ShouldRenderableReceiveShadow( renderable, SHADOW_FLAGS_PROJECTED_TEXTURE_TYPE_MASK ) )
		return;

	// Add all shadows in the leaf to the renderable...
	unsigned short i = m_ShadowsInLeaf.FirstElement( leaf );
	while (i != m_ShadowsInLeaf.InvalidIndex() )
	{
		ClientLeafShadowHandle_t shadow = m_ShadowsInLeaf.Element(i);
		ShadowInfo_t& info = m_Shadows[shadow];

		// Add each shadow exactly once to each renderable
		if (info.m_EnumCount != m_ShadowEnum)
		{
			AddShadowToRenderable( renderable, shadow );
			info.m_EnumCount = m_ShadowEnum;
		}

		i = m_ShadowsInLeaf.NextElement(i);
	}
}

//-----------------------------------------------------------------------------
// Adds a renderable to a set of leaves
//-----------------------------------------------------------------------------
void CClientLeafSystem::AddRenderableToLeaves( ClientRenderHandle_t handle, int nLeafCount, unsigned short *pLeaves )
{
	for (int j = 0; j < nLeafCount; ++j)
	{
		AddRenderableToLeaf( pLeaves[j], handle );
	}
	m_Renderables[handle].m_Area = GetRenderableArea( handle );
}

//-----------------------------------------------------------------------------
// Inserts an element into the tree
//-----------------------------------------------------------------------------
bool CClientLeafSystem::EnumerateLeaf( int leaf, int context )
{
	ClientRenderHandle_t handle = (ClientRenderHandle_t)context;
	AddRenderableToLeaf( leaf, handle );
	return true;
}

void CClientLeafSystem::InsertIntoTree( ClientRenderHandle_t handle )
{
	// When we insert into the tree, increase the shadow enumerator
	// to make sure each shadow is added exactly once to each renderable
	++m_ShadowEnum;

	// NOTE: The render bounds here are relative to the renderable's coordinate system
	IClientRenderable* pRenderable = m_Renderables[handle].m_pRenderable;
	Vector absMins, absMaxs;

	CalcRenderableWorldSpaceAABB_Fast( pRenderable, absMins, absMaxs );
	Assert( absMins.IsValid() && absMaxs.IsValid() );

	ISpatialQuery* pQuery = engine->GetBSPTreeQuery();
	pQuery->EnumerateLeavesInBox( absMins, absMaxs, this, handle );

	// Cache off the area it's sitting in.
	m_Renderables[handle].m_Area = GetRenderableArea( handle );
}

//-----------------------------------------------------------------------------
// Removes an element from the tree
//-----------------------------------------------------------------------------
void CClientLeafSystem::RemoveFromTree( ClientRenderHandle_t handle )
{
	m_RenderablesInLeaf.RemoveElement( handle );

	// Remove all shadows cast onto the object
	m_ShadowsOnRenderable.RemoveBucket( handle );

	// If the renderable is a brush model, then remove all shadows from it
	if (m_Renderables[handle].m_Flags & RENDER_FLAGS_BRUSH_MODEL)
	{
		g_pClientShadowMgr->RemoveAllShadowsFromReceiver(
			m_Renderables[handle].m_pRenderable, SHADOW_RECEIVER_BRUSH_MODEL );
	}
	else if( m_Renderables[handle].m_Flags & RENDER_FLAGS_STUDIO_MODEL )
	{
		g_pClientShadowMgr->RemoveAllShadowsFromReceiver(
			m_Renderables[handle].m_pRenderable, SHADOW_RECEIVER_STUDIO_MODEL );
	}
}

//-----------------------------------------------------------------------------
// Call this when the renderable moves
//-----------------------------------------------------------------------------
void CClientLeafSystem::RenderableChanged( ClientRenderHandle_t handle )
{
	Assert ( handle != INVALID_CLIENT_RENDER_HANDLE );
	Assert( m_Renderables.IsValidIndex( handle ) );
	if ( !m_Renderables.IsValidIndex( handle ) )
		return;

	if ( (m_Renderables[handle].m_Flags & RENDER_FLAGS_HASCHANGED ) == 0 )
	{
		m_Renderables[handle].m_Flags |= RENDER_FLAGS_HASCHANGED;
		m_DirtyRenderables.AddToTail( handle );
	}
#if _DEBUG
	else
	{
		// It had better be in the list
		Assert( m_DirtyRenderables.Find( handle ) != m_DirtyRenderables.InvalidIndex() );
	}
#endif
}

//-----------------------------------------------------------------------------
// Returns if it's a view model render group
//-----------------------------------------------------------------------------
inline bool CClientLeafSystem::IsViewModelRenderGroup( RenderGroup_t group ) const
{
	return (group == RENDER_GROUP_VIEW_MODEL_TRANSLUCENT) || (group == RENDER_GROUP_VIEW_MODEL_OPAQUE);
}

//-----------------------------------------------------------------------------
// Adds, removes renderables from view model list
//-----------------------------------------------------------------------------
void CClientLeafSystem::AddToViewModelList( ClientRenderHandle_t handle )
{
	MEM_ALLOC_CREDIT();
	Assert( m_ViewModels.Find( handle ) == m_ViewModels.InvalidIndex() );
	m_ViewModels.AddToTail( handle );
}

void CClientLeafSystem::RemoveFromViewModelList( ClientRenderHandle_t handle )
{
	int i = m_ViewModels.Find( handle );
	Assert( i != m_ViewModels.InvalidIndex() );
	m_ViewModels.FastRemove( i );
}

//-----------------------------------------------------------------------------
// Call this to change the render group
//-----------------------------------------------------------------------------
void CClientLeafSystem::SetRenderGroup( ClientRenderHandle_t handle, RenderGroup_t group )
{
	RenderableInfo_t *pInfo = &m_Renderables[handle];

	bool twoPass = false;
	if ( group == RENDER_GROUP_TWOPASS )
	{
		twoPass = true;
		group = RENDER_GROUP_TRANSLUCENT_ENTITY;
	}

	if ( twoPass )
	{
		pInfo->m_Flags |= RENDER_FLAGS_TWOPASS;
	}
	else
	{
		pInfo->m_Flags &= ~RENDER_FLAGS_TWOPASS;
	}

	bool bOldViewModelRenderGroup = IsViewModelRenderGroup( (RenderGroup_t)pInfo->m_RenderGroup );
	bool bNewViewModelRenderGroup = IsViewModelRenderGroup( group );
	if ( bOldViewModelRenderGroup != bNewViewModelRenderGroup )
	{
		if ( bOldViewModelRenderGroup )
		{
			RemoveFromViewModelList( handle );
		}
		else
		{
			AddToViewModelList( handle );
		}
	}

	pInfo->m_RenderGroup = group;

}

//-----------------------------------------------------------------------------
// Detail system marks
//-----------------------------------------------------------------------------
void CClientLeafSystem::DrawDetailObjectsInLeaf( int leaf, int nFrameNumber, int& nFirstDetailObject, int& nDetailObjectCount )
{
	ClientLeaf_t &leafInfo = m_Leaf[leaf];
	leafInfo.m_DetailPropRenderFrame = nFrameNumber;
	nFirstDetailObject = leafInfo.m_FirstDetailProp;
	nDetailObjectCount = leafInfo.m_DetailPropCount;
}

//-----------------------------------------------------------------------------
// Are we close enough to this leaf to draw detail props *and* are there any props in the leaf?
//-----------------------------------------------------------------------------
bool CClientLeafSystem::ShouldDrawDetailObjectsInLeaf( int leaf, int frameNumber )
{
	ClientLeaf_t &leafInfo = m_Leaf[leaf];
	return ( (leafInfo.m_DetailPropRenderFrame == frameNumber ) && ( leafInfo.m_DetailPropCount != 0 ) );
}

//-----------------------------------------------------------------------------
// Compute which leaf the translucent renderables should render in
//-----------------------------------------------------------------------------
void CClientLeafSystem::ComputeTranslucentRenderLeaf( int count, LeafIndex_t *pLeafList, LeafFogVolume_t *pLeafFogVolumeList, int frameNumber )
{
	VPROF( "CClientLeafSystem::ComputeTranslucentRenderLeaf" );

	// For better sorting, we're gonna choose the leaf that is closest to
	// the camera. The leaf list passed in here is sorted front to back
	for (int i = 0; i < count; ++i )
	{
		int leaf = pLeafList[i];

		// iterate over all elements in this leaf
		unsigned short idx = m_RenderablesInLeaf.FirstElement(leaf);
		while (idx != m_RenderablesInLeaf.InvalidIndex())
		{
			RenderableInfo_t& info = m_Renderables[m_RenderablesInLeaf.Element(idx)];
			if( info.m_RenderFrame != frameNumber )
			{
				// Compute translucency
				info.m_pRenderable->ComputeFxBlend();

				if( info.m_RenderGroup == RENDER_GROUP_TRANSLUCENT_ENTITY )
				{
					info.m_RenderLeaf = leaf;
				}
				info.m_RenderFrame = frameNumber;
			}
			else if ( info.m_Flags & RENDER_FLAGS_ALTERNATE_SORTING )
			{
				if( info.m_RenderGroup == RENDER_GROUP_TRANSLUCENT_ENTITY )
				{
					info.m_RenderLeaf = leaf;
				}
			}
			idx = m_RenderablesInLeaf.NextElement(idx);
		}
	}
}

//-----------------------------------------------------------------------------
// Adds a renderable to the list of renderables to render this frame
//-----------------------------------------------------------------------------
inline void AddRenderableToRenderList( CRenderList &renderList, IClientRenderable *pRenderable,
	int iLeaf, RenderGroup_t group,	ClientRenderHandle_t renderHandle, bool bTwoPass = false )
{
#ifdef _DEBUG
	if (cl_drawleaf.GetInt() >= 0)
	{
		if (iLeaf != cl_drawleaf.GetInt())
			return;
	}
#endif

	Assert( group >= 0 && group < RENDER_GROUP_COUNT );

	int &curCount = renderList.m_RenderGroupCounts[group];
	if ( curCount < CRenderList::MAX_GROUP_ENTITIES )
	{
		Assert( (iLeaf >= 0) && (iLeaf <= 65535) );

		CRenderList::CEntry *pEntry = &renderList.m_RenderGroups[group][curCount];
		pEntry->m_pRenderable = pRenderable;
		pEntry->m_iWorldListInfoLeaf = iLeaf;
		pEntry->m_TwoPass = bTwoPass;
		pEntry->m_RenderHandle = renderHandle;
		curCount++;
	}
	else
	{
		engine->Con_NPrintf( 10, "Warning: overflowed CRenderList group %d", group );
	}
}

//-----------------------------------------------------------------------------
// Purpose:
// Input  : renderList -
//			renderGroup -
//-----------------------------------------------------------------------------
void CClientLeafSystem::CollateViewModelRenderables( CUtlVector< IClientRenderable * >& opaque, CUtlVector< IClientRenderable * >& translucent )
{
	for ( int i = m_ViewModels.Count()-1; i >= 0; --i )
	{
		ClientRenderHandle_t handle = m_ViewModels[i];
		RenderableInfo_t& renderable = m_Renderables[handle];

		// NOTE: In some cases, this removes the entity from the view model list
		renderable.m_pRenderable->ComputeFxBlend();

		// That's why we need to test RENDER_GROUP_OPAQUE_ENTITY - it may have changed in ComputeFXBlend()
		if ( renderable.m_RenderGroup == RENDER_GROUP_VIEW_MODEL_OPAQUE || renderable.m_RenderGroup == RENDER_GROUP_OPAQUE_ENTITY )
		{
			opaque.AddToTail( renderable.m_pRenderable );
		}
		else
		{
			translucent.AddToTail( renderable.m_pRenderable );
		}
	}
}

void CClientLeafSystem::CollateRenderablesInLeaf( int leaf, int worldListLeafIndex,	SetupRenderInfo_t &info )
{
	bool portalTestEnts = r_PortalTestEnts.GetBool() && !r_portalsopenall.GetBool();

	// Collate everything.
	unsigned short idx = m_RenderablesInLeaf.FirstElement(leaf);
	for ( ;idx != m_RenderablesInLeaf.InvalidIndex(); idx = m_RenderablesInLeaf.NextElement(idx) )
	{
		ClientRenderHandle_t handle = m_RenderablesInLeaf.Element(idx);
		RenderableInfo_t& renderable = m_Renderables[handle];

		// Early out on static props if we don't want to render them
		if ((!m_DrawStaticProps) && (renderable.m_Flags & RENDER_FLAGS_STATIC_PROP))
			continue;

		// Early out if we're told to not draw small objects (top view only,
		/* that's why we don't check the z component).
		if (!m_DrawSmallObjects)
		{
			CCachedRenderInfo& cachedInfo =  m_CachedRenderInfos[renderable.m_CachedRenderInfo];
			float sizeX = cachedInfo.m_Maxs.x - cachedInfo.m_Mins.x;
			float sizeY = cachedInfo.m_Maxs.y - cachedInfo.m_Mins.y;
			if ((sizeX < 50.f) && (sizeY < 50.f))
				continue;
		}*/

		Assert( m_DrawSmallObjects ); // MOTODO

		// Don't hit the same ent in multiple leaves twice.
		if ( renderable.m_RenderGroup != RENDER_GROUP_TRANSLUCENT_ENTITY )
		{
			if ( renderable.m_RenderFrame2 == info.m_nRenderFrame )
				continue;

			renderable.m_RenderFrame2 = info.m_nRenderFrame;
		}
		else
		{
			// Translucent entities already have had ComputeTranslucentRenderLeaf called on them
			// so m_RenderLeaf should be set to the nearest leaf, so that's what we want here.
			if ( renderable.m_RenderLeaf != leaf )
				continue;
		}

		// Prevent culling if the renderable is invisible
		// NOTE: OPAQUE objects can have alpha == 0.
		// They are made to be opaque because they don't have to be sorted.
		unsigned char nAlpha = renderable.m_pRenderable->GetFxBlend();
		if ( nAlpha == 0 )
			continue;

		Vector absMins, absMaxs;
		CalcRenderableWorldSpaceAABB( renderable.m_pRenderable, absMins, absMaxs );
		// If the renderable is inside an area, cull it using the frustum for that area.
		if ( portalTestEnts && renderable.m_Area != -1 )
		{
			VPROF( "r_PortalTestEnts" );
			if ( !engine->DoesBoxTouchAreaFrustum( absMins, absMaxs, renderable.m_Area ) )
				continue;
		}
		else
		{
			// cull with main frustum
			if ( engine->CullBox( absMins, absMaxs ) )
				continue;
		}

		// UNDONE: Investigate speed tradeoffs of occlusion culling brush models too?
		if ( renderable.m_Flags & RENDER_FLAGS_STUDIO_MODEL )
		{
			// test to see if this renderable is occluded by the engine's occlusion system
			if ( engine->IsOccluded( absMins, absMaxs ) )
				continue;
		}

		if( renderable.m_RenderGroup != RENDER_GROUP_TRANSLUCENT_ENTITY )
		{
			RenderGroup_t group = (RenderGroup_t)renderable.m_RenderGroup;
			AddRenderableToRenderList( *info.m_pRenderList, renderable.m_pRenderable,
				worldListLeafIndex, group, handle);
		}
		else
		{
			bool bTwoPass = ((renderable.m_Flags & RENDER_FLAGS_TWOPASS) != 0) && ( nAlpha == 255 );

			AddRenderableToRenderList( *info.m_pRenderList, renderable.m_pRenderable,
				worldListLeafIndex, (RenderGroup_t)renderable.m_RenderGroup, handle, bTwoPass );

			// Add to both lists if it's a two-pass model...
			if (bTwoPass)
			{
				AddRenderableToRenderList( *info.m_pRenderList, renderable.m_pRenderable,
					worldListLeafIndex, RENDER_GROUP_OPAQUE_ENTITY, handle, bTwoPass );
			}
		}
	}

	// Do detail objects.
	// These don't have render handles!
	if ( IsPC() && info.m_bDrawDetailObjects && ShouldDrawDetailObjectsInLeaf( leaf, info.m_nDetailBuildFrame ) )
	{
		idx = m_Leaf[leaf].m_FirstDetailProp;
		int count = m_Leaf[leaf].m_DetailPropCount;
		while( --count >= 0 )
		{
			IClientRenderable* pRenderable = DetailObjectSystem()->GetDetailModel(idx);

			// FIXME: This if check here is necessary because the detail object system also maintains
			// lists of sprites...
			if (pRenderable)
			{
				if( pRenderable->IsTransparent() )
				{
					// Lots of the detail entities are invsible so avoid sorting them and all that.
					if( pRenderable->GetFxBlend() > 0 )
					{
						AddRenderableToRenderList( *info.m_pRenderList, pRenderable,
							worldListLeafIndex, RENDER_GROUP_TRANSLUCENT_ENTITY, DETAIL_PROP_RENDER_HANDLE );
					}
				}
				else
				{
					AddRenderableToRenderList( *info.m_pRenderList, pRenderable,
						worldListLeafIndex, RENDER_GROUP_OPAQUE_ENTITY, DETAIL_PROP_RENDER_HANDLE );
				}
			}
			++idx;
		}
	}
}


Is that the twang of guitar abuse chiming over What A Drag's opening minutes, or the sound of something rummaging through a box of crockery? Both perhaps? It's one of many noises on the tape that rustle and creak beyond the ease of sonic categorisation, and as the band moniker aptly suggests, the record comprises of eroded shapes and mysterious implication; sound as fossil, just barely resisting time's attempts to eradicate its character and shape.
Even if it was without the ugly dents and decay that come with the record's crumbling low fidelity, What A Drag would be an ugly work. About 11-minutes into the first side, the record begins to sound like some rusting metal watermill, with rippling static sloshing across a hideous, rotary turbine squeak; elsewhere, the music comes to resemble the broken wail of submarine sonar, or the sound of thrown pebbles clattering into the side of a flimsy metallic shed. It's a catalogue of unwanted audial bi-products – polluting sonic processes rendered even more toxic by the abrasive method of monophonic capture, writhing through the creases of garbled magnetic tape.
Things change suddenly ten minutes into the second half – the noise cuts dead, re-emerging in greater clarity as a vaster, brighter live recording. The underbelly of distortion becomes tempered by bubbling synthesisers that dance in rather dainty patterns over the top, before the whole thing transforms into some sort of ominous funeral train for the final five minutes, trundling laboriously through monster groans and malformed, processed pop music. Regardless of these abrupt shifts in shape, the band's persistent will to unsettle – while trampling over traditionally held production values – renders the whole tape coherent enough.


text:
The U.S. Naval Academy's Offshore Sail Training Squadron program brings out the leadership potential in every participant and can be pivotal in the development of junior officers. Here, the squadron prepares to moor in Mystic, Connecticut, as part of its sail to Newport, Rhode Island, in summer 2010.
U.S. Navy (Steven Myers)
Professional Notes
By Lieutenant (j.g.) Jessica Fuller andCommander James Lowell, U.S. NavyOn 11 March 2011, Japan experienced the
Vol. 139/2/1,320
Operating in a RADCON Environment
fifth-largest earthquake in recorded history. The resulting tsunami caused immeasurable damage including crippling cooling systems at the Fukushima Daiichi reactor complex near Sendai, Japan. In efforts to prevent a catastrophic meltdown, reactors were vented to release increasing internal pressure. Several fission products were sent skyward in a radioactive plume carried easterly into the western Pacific. In addition to the airborne threat, water drawn from the ocean to cool the reactors drained back into the ocean carrying a contaminated ocean-plume eastward.
Besides damaging the plants at Fukushima, the tsunami devastated the coast, leaving 4 million Japanese citizens without electricity, 1.5 million without water, and 27,000 missing. In response to the government of Japan's request for assistance, Japan-based U.S. Navy ships sortied to Honshu's northeast coast in Operation Tomodachi. En route to the affected area, the USS Essex (LHD-2) damage-control experts reviewed FM 3-11.5, Multiservice Tactics, Techniques, and Procedures for Chemical, Biological, Radiological, and Nuclear Decontamination. Although expeditionary missions are common for the Navy's amphibious fleet, operating and conducting humanitarian assistance and disaster relief (HA/DR) in a radiologically contaminated (RADCON) environment required adaptability, flexibility, dynamic planning—and writing the book along the way.
The Navy trained and operated in a Cold War environment for decades. Procedures were published and practiced, and protective equipment was set aside for nuclear, biological, and chemical warfare. With the waning threat of global nuclear war, priorities shifted to chemical, biological, and radiological (CBR) warfare, with an addendum as nuclear proliferation expanded—CBR-N. References prescribed how the Essex should avoid and recover from a thermonuclear blast, but not how to sustain operations in a RADCON environment.
With the adapted Cold War checklist complete, new questions arose. What does contamination mean? What level of contamination is hazardous? What happens when that level is reached? Can helicopters fly in a plume? Will aircraft and landing craft bring back high levels of contamination to a "clean" ship? The procedures outlined in the Cold War manuals were proving impractical and insufficient for unfettered support of Operation Tomodachi. With her mission unchanged, Essex leaders no longer questioned if they would do it, but how.
The Greatest Threat
Contamination—not radiation—was the long-term threat to sustained HA/DR operations. Radiation was strongest at the Fukushima plant, and the Essex's distance from the reactors exponentially minimized exposure to that radiation. But fissionable material did not remain at the plant. To reduce heat-generated pressure from the uncooled reactor vessels, plant workers vented radiological contaminates into the atmosphere, creating airborne plumes. The plumes' paths followed prevailing winds and weather and tracked toward the Essex. Any shipboard system that could collect or concentrate fissionable products such as air handlers, ventilation filters, gunwales, deck-drains, greases, oils, or low spots in the flight deck quickly became the focus of newly trained radiation-control surveyors. A survey program was quickly developed for aircraft and landing craft making contact with contaminated soil ashore.
Once the threat to sustained HA/DR operations was identified, mitigation methods were codified with three goals:
• Limit ship and crew exposure to contamination.
• Limit contamination to the ship's exterior.
• Sustain continuous HA/DR operations in support of Operation Tomodachi.
Using emerging Navy guidance and expert assistance from on-board Navy radiation specialists from Norfolk Naval Shipyard, the Essex tightly controlled exposure to radiological hazards through organizational adaptations and alterations to flight-deck and well-deck operating procedures.
Changes to routine duties were implemented to track and monitor contamination levels and to advise the commanding officer and embarked leadership on the operational impacts of survey readings and decontamination efforts.
First, a radiation-control watch was established. Teams worked around the clock, monitoring radio messages and logging dozens of survey forms generated by radiation-survey teams stationed on the flight deck or in the well deck.
Next, the Essex's damage-control assistant was assigned as decontamination coordinator. Added responsibilities included issuing and controlling Mission-Oriented Protective Posture (MOPP) gear—rubber suits, masks, and gloves—dosimeters, and decontamination supplies to survey and flight-deck-decontamination teams. The coordinator also liaised with all radiological players to ensure surveys and decontaminations were handled efficiently and systematically.
Finally, because of changes and updates from both the Fukushima plants and refined radiation health guidance, radiation-control policies were amended daily. To keep sailors and Marines informed and to emphasize the importance of upholding these policies, a radiation-control liaison officer was assigned to work closely with embarked radiation specialists to develop policies, analyze shipboard impacts, and train a cadre of radiation surveyors.
Damage controlmen were trained as radiation health technicians, performing surveys in addition to assisting in decontaminating gear and aircraft. Aerographer's mates located and modeled radiation plumes and informed the Essex's command and embarked leadership. The supply department determined how to handle and store radiological waste. All embarked sailors and Marines were trained on the hazards of radiological contamination and to remain vigilant and patient with amended policies.
On the Flight Deck
During Operation Tomodachi, up to 100 sailors and Marines and more than 25 aircraft operated on the flight deck. Each day, approximately five aircraft and 30 individuals went ashore inside the radiological "warm zone." Aircraft and personnel routinely returned with a measurable level of radiological contamination. To remain flying and keep contamination from entering the skin of the ship, several modifications to flight-deck operations were required:
• All but one entrance and one exit to the flight deck were secured.
• MOPP overboots were worn on the flight deck. They were issued at the access and collected for decontamination at the exit. If they could be decontaminated below 100 corrected counts per minute (CCPM), they were reissued. Any boots failing decontamination were stored for disposal.
• Radiation specialists conducted surveys of every person entering the skin of the ship. No one was exempt from the survey, which averaged five minutes per person. Any gear found above 100 CCPM was decontaminated prior to return.
• Helicopters were surveyed and decontaminated inside and out.
Although implementing new procedures was challenging, necessity demanded a steep learning curve. New processes quickly became routine to maintain unhindered flight operations.
In the Well Deck
Waterborne operations landed hundreds of Marines to the radiological warm zone. Survey procedures used on the flight deck were adapted and refined for larger scale operations in the ocean environment. One of the challenges to surveying wetted gear is the radiological shielding effect of even a thin film of water.
Landing craft utility (LCU) boats were decontaminated at sea prior to entering the well deck using a saltwater wash-down by trained Marines and embarked radiation specialists. Marine boots were surveyed before disembarking the LCU to eliminate contamination spread. Rucksacks were removed before Marines proceeded to a full-body scan, and contaminated uniforms and gear were tagged for decontamination and/or disposal. Some Marines lost contaminated gear exceeding 100 CCPM, for a total of 150 pounds.
Final Decontamination
After completing 32 days of HA/DR in and out of the warm zone, the final question was how effective containment policies and practices had been. During the four-day transit to Okinawa, surveyors needed to prove the Essex was free from contamination by meeting the following criteria:
• Establish that all internal spaces were free from contamination.
• Establish that all external surfaces were free from contamination.
• Segregate, contain, and store all low-level radioactive waste.
The Essex has more than 1,400 internal spaces. Certifying that each was clean in four days was no small task. Embarked radiation specialists and newly trained surveyors swept areas within the ship, averaging 10 minutes per space and 60 minutes for messing and berthing spaces.
External areas, including the flight deck, well deck, aircraft, and Marine vehicles, were extensively surveyed and results mapped. Any area of elevated contamination was decontaminated and closely monitored. The flight deck and all external surfaces were rinsed with the ship's countermeasure wash-down system and scrubbed with soap and water. After a thorough and extensive survey was completed and documented for future research, the Essex was certified free and clear.
Personal articles that could not be decontaminated were placed in an airtight container, marked as low-level radioactive waste, and stored by the Essex's hazardous materials organization for future disposal.
Lack of existing guidance was the major obstacle to sustaining operations in a radiological environment. In that absence, the Essex took charge of educating her sailors and Marines and developed effective policies with the assistance of radiation health experts. While the learning curve was steep, the ship's sailors and Marines mastered the keys to operating in a radiological environment and sustaining humanitarian assistance and disaster relief operations in support of the people of Japan.
Lieutenant (j.g.) Fuller is in the nuclear-power training pipeline and served as electrical and radiation-control liaison officer in the Essex.
Commander Lowell is a senior officer ship-maintenance-and-repair course instructor at the Surface Warfare Officers School in Newport, Rhode Island. He has commanded three crews in six ships and was temporarily assigned as the Essex's executive officer.
Joint Air: Don't Let Knowledge Slip Away
By Commander Tom Pieluszczak, U.S. Navy (Retired)
Nine years after the start of Operation Iraqi Freedom, the Navy stands at the edge of losing capital it has slowly accumulated over the years. Strike groups are trained to integrate into the joint air command and control (C2) environment throughout the Fleet Response Plan from the classroom through joint task force exercise. Yet when they enter the theater, they may as well be speaking a foreign language.
It seems as though we continually let knowledge slip away too easily when it will be very difficult to recover as combat operations commence in the next major theater operation. The Navy needs to clarify its course and game-plan.
Is joint air C2 a core mission? It is unclear whether or not we have prioritized giving the joint force maritime component commander (JFMCC) and strike groups the capability to collaboratively plan and execute at the joint operational and tactical levels. Critical parts of Theater Battle Management Core System (TBMCS) funding have been and continue to be targeted across the Future Years Defense Programs. This may be because of budgetary expediency, and yet Headquarters Marine Corps for Aviation has made air C2 a core priority. Is naval aviation leadership willing to do the same?
The concept and doctrine for JFMCC/maritime operations center/maritime headquarters have been documented. The numbered fleet commanders need to adapt and execute. The service must apply the composite warfare commander concept and define JFMCC relationship(s) with other components more in terms of C2 nodes with full C2 capabilities.
Our Joint Background
It has been more than 20 years since Operation Desert Storm when, by necessity, the air tasking order (ATO) was flown out by carrier-based antisubmarine warfare aircraft—Lockheed S-3 Vikings—from the combined air operations center (CAOC) to the carrier strike group. Since then our service has slowly but surely come into the world of distributive planning and real-time collaborative execution with respect to joint air operations. We have migrated to the joint system of record for air C2; we have created classes at the Fleet concentration centers, establishing a joint working relationship with the Air Force's C2 Warrior School to ensure that selected Fleet air C2 billet holders get a critical basic understanding of joint air operations interrelationships. Finally, we now understand that manning the air operations center is a process that requires thought and preparation. We cannot show up on day one of the war saying, "Here are my targeting priorities Joint Force Air Component Commander."
Our high-water mark occurred in the latter stages of major combat operations during Operation Iraqi Freedom. Over the course of that campaign, the Navy had a plan to fully integrate personnel into the combined air operations center ashore as augmentees and liaisons. Afloat, our aircraft carrier strike operations planning teams built planning shells for strike group direct support missions, forwarding them to CAOC combat plans where those sorties would appear on the ATO along with common use Navy missions planned by multiservice planners at the combined air operations center. Carrier air wing personnel stood the current operations watch-reporting air tasking order execution to CAOC combat ops. The process worked, though it wasn't easy; and we came to realize that it was complex. The resultant product was a near-real-time status of missions available for reference laterally and vertically by all C2 levels, from Commander, Joint Task Force, to unit level.
Some think the Navy does not need to be an active planning participant in the joint air C2 process, but that is incorrect. As the combined air operations center shrinks in size, the components will be required to pick up more of the planning burden for both common-use and direct-support missions. The tools that enable collaboration and interoperability across these lines must be preserved and improved.
Preserve and Improve Tools
Service leadership must assess and formulate a recommendation for Fleet approval as to the scalability in level of effort required to execute and manage air C2 within the Navy based on the nature of operations. The capability to meet this requirement must take into account the number of organizations that possess an ability to execute C2 of air operations and those organizations' capacity to function for any given level of operational intensity.
The Bureau of Personnel must ensure all identified Fleet air C2 billets are funded and filled with personnel who are properly trained to assume the roles and responsibilities in the process. En route, permanent change-of-station to schools is essential and must be funded.
United States Fleet Forces Command and commanders, Strike Force Training, Atlantic and Pacific, must ensure there remains a naval command and control of air operations (NC2AO) staff billet to deal with service and joint air C2 issues. The Fleet Forces Command NC2AO community manager must be empowered by leadership to represent the service and carry out air C2 requirements for the Navy. Under the NC2AO community manager, a comprehensive list of air C2 specialists must be available for contingency planning. This available manpower pool would be sent forward to the CAOC, maritime operations center, or ship to augment and relieve functional and manning burdens.
Commander Naval Strike Air Warfare Center, as the Navy's lead on strike issues, should be designated Deputy–Combined/Joint Force Air Component Commander in the event of emerging theater contingencies. During Operation Iraqi Freedom, the Naval Strike Air Warfare Center commander served as Deputy Combined Force Air Component Commander, bringing forward many staff strike experts and overseeing a significant Navy augmentation/liaison presence at the Prince Sultan Air Base (Saudi Arabia) combined air operations center. This lesson cannot be lost in the shuffle of passing time.
The Theater Battle Management Core System (TBMCS) is the only capability we field that enables true joint planning, collaboration, and execution monitoring. The capability must be preserved to plan, collaborate, monitor, and execute within the joint air C2 command structure, ensured by the Naval Network Warfare Command as the command, control, communications, computers, intelligence, surveillance, and reconnaissance (C4ISR)/force-net type commander; and by Space Warfare Systems Command as the technical implementer. Distributive and collaborative strike/fires planning and execution management among C2 nodes is a tenet of Sea Strike and would be a naturally assumed capability within a net-centric environment. Space Warfare Systems Command must ensure strike groups have all the tools (all software service packs and maintenance releases) that will enable interoperability with the combined air operations center. The Fleet must have significant operational support to answer the call when needed.
The lack of a cohesive C4ISR/information-technology development and fielding strategy is crippling the service. As maintenance releases are fielded in the Theater Battle Management Core System, the Fleet falls further behind in implementing much-needed technology and capabilities. It may come to a point where there will be no targeting capabilities fielded afloat, with all Fleet targeting being done in the maritime operations center (ashore or on the afloat command ship). Where does this leave the joint partners?
TBMCS is an Air Force program, but joint partners use it extensively. The Air Force has unilaterally made acquisition decisions placing it into sustainment, lowering priorities for a program used by the joint partners in favor of the light blue air operations center weapon system. The Air Force must stay attuned to the joint perspective and not be allowed to wander astray. Independent service testing (recurring events) of new technologies/functionality through the air operations center weapons system test team/force rather than the TBMCS team (where the Navy and Marine Corps are signatories) cannot continue. Air Combat Command and the TBMCS systems program office cannot make unilateral program decisions that will affect fielding within the Navy and Marine Corps. TBMCS supposedly is the "engine" of the air operations center weapon system. It should not lag behind the joint partners in fielding capability.
Adhere to Doctrine
"If it flies in the area of responsibility, it will be on the ATO." These are words lost in translation over the years. Currently joint-partner direct-support sorties are not included on the ATO in an area of responsibility not to be named. Instead, all flights and alerts need to be on the ATO because you never know when a shooting war may begin, and you don't want to be the one at the end of a long table explaining why we didn't follow doctrine and ended up shooting down friendlies.
The Navy's future in the air C2 arena must be shaped by commitment to a clear strategy and a willingness to execute when directed. There can be no shortcuts, no looking down the road as to what future systems capabilities could bring. This is the path to success.
The Air Force cannot leave the service and alliance partners behind to chase technology for its own sake. Version 1.1.3, with a large portion of functionality web-enabled, was the first logical step in moving to net-centric functionality across components. If a C2 air operation suite is indeed the path to service-oriented architecture, we must declare that intention and work toward that goal rather than through a series of TBMCS 1.1.3 maintenance releases that complicate the air C2 architecture and impose a series of ridiculous interoperability requirements that makes the technical system views look like spaghetti.
Commander Pieluszczak is a retired F-14 radar intercept officer qualified with an air C2 subspecialty. He supports Commander Operational Test and Evaluation Force as a senior engineer analyst for air C2 systems operational test. Previously he served as the deputy air operations officer, 2d Fleet and strike module lead, air C2 officer at Tactical Training Group Atlantic, Dam Neck, Virginia.
Offshore Sail Training: A View from West Point
By First Lieutenant Rhys A. Hearn, U.S. Army
I walked onto the Army sailing team in 2008 without ever having set foot on a sailboat. Never would I have guessed that my team and the connections I made would define my 47-month experience at West Point. My very first race was the invitational Shield's Cup Regatta held at the U.S. Naval Academy. Army sailing took last place that year, a dismal finish that many on my team would rather forget. However, with that brief taste of sailing Navy 44s—the Navy 44 Mark II Sail Training Craft is the latest of four generations of one-design offshore cruiser/racers to be authorized and funded by Congress for training midshipmen—I got hooked. I started to dedicate my free time to learning, practicing, and perfecting the craft of sailing. With the help of my coach, I also made significant connections with the sailing program at the Naval Academy that helped me develop as a sailor and cadet-coach.
When I arrived at the Naval Academy in January 2010 on an academy exchange, I somehow convinced them to let a West Pointer teach a group of midshipmen how to sail. Shortly thereafter, I was assigned to the Offshore Sail Training Squadron (OSTS) program: a three-week sail to Newport, Rhode Island, along with eight midshipmen. A month before I returned to West Point, I confidently gave the last command to make down the lines on board the Tenacious (NA-25). In retrospect, I am able to identify four major facets of leadership that were developed and strengthened though the OSTS program: mentorship, experience, new knowledge, and the ability to reflect. These, combined with the challenging environment of life at sea, provide midshipmen a real-time command laboratory that strengthens the foundation for lifelong leaders.
This is the first and most influential aspect of the OSTS experience. From the beginning of the program until the last stern line is set, there are numerous opportunities to adopt a mentor. Throughout my time in the program, my mentor was retired Army Colonel Dick Lunsford, a former West Point instructor. Although he is a sailing favorite at the Naval Academy, he has always been supportive of the Army sailing team and often dedicated his weekends to help coach and train our crew. Mentors such as he help support the Academy's mission to develop midshipmen morally, mentally, and physically. He helped me synthesize my conclusions about leadership challenges I encountered and made certain I came away from each experience with a lesson learned.
One of the most significant lessons Colonel Lunsford taught me was the concept of "the loneliness of command." This refers to the second- and third-order effects of decisions. At sea or on land, leaders are charged with the duty of making responsible and educated decisions that are not always comfortable for the crew or the leader. It is there, in the area between doing what is needed and what is wanted, that the leader will feel that loneliness.
These lessons can only be understood through shared personal experience. Mentors like Colonel Lunsford are an invaluable element of the OSTS program because they reflect what it means to be a leader in our current operating environment and promote mentorship to those they guide. With a cycle of great mentors developing future mentors, generations of leaders will continue to be inspired.
This is the second most important aspect of leader development. Over the course of our 15-day sail, my crew and I were tested a number of times by the sea and the weather. One trial occurred about seven miles off the eastern coast of Block Island, Rhode Island. A weather system began to move in just as I was relieved from my nightly watch. I retired to my bunk and had barely shut my eyes before I was wakened by a crew member yelling, "Rhys, Nick is on the bow and he needs your help!" Instinctively I grabbed my foul-weather gear and ran onto the deck.
The wind was howling, and the skies had opened up as I quickly surveyed the scene and spotted Nick's headlamp on the bow. He was lying on the deck on top of a jib sail, struggling to stay in control of the situation—and on the boat, for that matter. The force of the wind, peaking at about 45 knots, caused the bow of the boat to round up into the breaking swells. I had to react immediately to secure the safety of my crew. With little time to think, I relied heavily on my training and let muscle memory take over. I quickly moved to release the jib halyard and fetch the sail ties to secure the flailing sail to the deck. After the sail was down and the crew was accounted for, the reality of the situation sank in.
Months later, I learned that I had executed "recognition-primed decision making." I recognized the situation from hours of training and classroom exercises and was able to make a quick decision based on the circumstances. This validated the OSTS training program for me. From that point forward, I was confident that my training would get me through any situation at sea. While the program could not possibly teach you how to react in every instance, it does instruct you how to approach a situation calmly and objectively, troubleshoot, and develop an appropriate course of action. Although not officially, the OSTS teaching method inculcates a deliberate problem-solving process that is valuable in many circumstances for any military leader.
The OSTS program's training philosophy is derived from military decision-making and training programs that are in operational use. It provides a basis of knowledge for midshipmen that will underlie their military careers. This knowledge extends beyond traditional skills such as plotting, engineering, and watch standing. It delves into the core values of leadership by placing the individuals, especially the midshipman skipper and executive officers, at the center of all training. It is based on standards and oriented around performance.
The offshore program gives the skipper and XO responsibility for training their crew by allowing them to determine the training schedule during the first week of local-area sailing. The skipper then takes the crew and trains them to a proficient level, which includes everything from running the galley to reefing sails and man-overboard drills. The schedule helps develop and enhance the technical proficiency of skippers and XOs. During their first overnight at the end of the first week, the skipper/executive officer team train the crew to adapt to a variety of situations that may arise while at sea. These rehearsals, or sea trials, are the best way for the leadership team to recognize the individual and collective tasks that still need improvement while also identifying the members of the crew to fill watch-captain positions. Finally, the program allows the leadership to identify and recommend members of their crew to return the following year as XOs. This helps sustain the training program while fostering an environment of continued proficiency and dedicated leadership.
When I returned to West Point in August 2010, I brought back knowledge and experience to the Army Offshore Sailing Section. I rejoined my coach, Dr. Lee Harrell (a fellow OSTS skipper and volunteer) and other members of the sailing team to develop a training schedule similar to the OSTS program. Dr. Harrell and I were determined to develop the team into a more competitive sailing program that was on par with the skill and resolve of its members. This determination was instilled in me by the OSTS program where I not only became a better sailor but also developed professionally and gained confidence in my leadership abilities.
Through reflection on my experiences at the Naval Academy and the incredible opportunity I was given, I became better suited for a prominent role on the sailing team. Although the technical skills I learned through the OSTS program may not be applicable for an Army officer, the chance I had to make substantial real-time and real-world decisions will remain with me indefinitely.
Mentorship, experience, new knowledge, and the ability to reflect are key elements in professional development. These are brought to the forefront in the OSTS program through real-life consequences of decisions made at sea. As author Herman Melville surmised, "at sea a fellow comes out."
The OSTS program brings out the leadership potential in every midshipman. It puts young men and women into challenging situations, forcing them to face whatever fears they have to make quality, educated decisions for their crew. The program inspires its participants to take ownership of their professional development, a notion that will serve leaders well throughout their career. To me, the OSTS program is one of the most defining moments of my development as a junior officer and leader. I am grateful to the Naval Academy for providing me with this opportunity and I hope that I may one day return to the program.
First Lieutenant Hearn reported to Fort Bragg, North Carolina, after graduating from the U.S. Military Academy in 2011. He serves in the 27th Engineer Battalion (Combat) (Airborne) as an airborne engineer.
In the wake of the 2011 earthquake and tsunami in Japan, damage included the Fukushima Daiichi reactor complex near Sendai. As the world responded, the USS Essex updated procedures for humanitarian and disaster-relief operations in a radiologically contaminated environment. These members of the 31st Marine Expeditionary Unit prepare potable water for transport to Japan as part of Operation Tomodachi.
U.S. Navy (Casey H. Kyhl)
The Navy has made great progress in planning and executing combined air operations both ashore and afloat, the author observes, but is now in danger of losing the benefits of that experience. Joint air-defense interoperability exercises such as those shown here, of the Harry S. Truman (CVN-75) with the Winston S. Churchill (DDG-81) and French navy frigate Jean Bart, are invaluable.
U.S. Navy (Kiho Park)

redpajama_set_name: RedPajamaCommonCrawl


Can anyone suggest a GOOD creeper! There seems to be a billion types that all claim to be good but who knows until you actually buy one and use it.
I've had 2 pieces of crap that I'm so disgusted with I'm ready to toss them in the garbage. Wheels don't stay tight and don't last long and will barely roll over a small pebble. One has a head rest that'd be great if it would stay up. Having it drop like a rock unexpectedly when your in the middle of working is a real pain (no pun intended). I'd like one with a good head rest that raises up (and stays up when it's supposed to). Side racks for tools etc. are ok but if that drives up the price a lot forget it. I have a nice concrete garage floor so I don't need huge 6" wheels, just decent lasting and properly attached wheels.
I've got $150 to spend on one. I'd think that should get me something decent.
Well then its a snap on for you guaranteded for life top to bottom.
I wish I had a Snap-on guy around me but right now I have no idea where to catch one. Maybe I'll look on their website and see if the shipping isn't too bad.
Whiteside has some Cadillacs......but they ain't cheap.
Here you go.....a lot more reasonable. Made in America too.
IMO, creepers are like shoes. I try to buy the best shoe I can afford. If you have to lay on your back, it's the only back you have. When you start to have back and neck trouble, you'll understand. It's a pain in the neck.
I need a good creeper also. Since I weigh 285, most creepers don't last long before the wheels fold. I watched the video. I wonder what this bad boy cost?
I have had my snap on creeper for over 20 years without problem and while not used so much the last 10 years it was used a ton it's first ten. It is a low profile steel frame, 6 wheel, with adj headrest.
Well then its a snap on for you guaranteed for life top to bottom.
X2 on the Northern tool "King Crawler." Works OK on gravel and rolls over air hoses!!!
If you're cheap, get a typical parts house creeper and then retrofit the biggest stud mount casters you can find at H-F.
I've had a Craftsman "Professional" for a long time, like over 15 years. Its solid. Never had one problem with it.
When I was working as a tech at a dealer, someone always had the latest and greatest off the tool trucks - magnetic this or that, roller bearing, adjustable, LED lighted, coffee maker, nut scratcher, yada yada - they ALL fell apart instantly.
We had an old shop one, a Jeepers Creeper, that was a good one too, heavy duty plastic. Too dirty for me to lay on though, the floor was cleaner than that thing.
I have one of those also. It's actually solid yet but my back can't handle it because it has virtually no padding so with my bone spurs it feels like I'm laying on rocks.
Exactly. That's my problem and why I need something padded good and with a raisable head rest.
Wow! Never saw anything like that. I'm not really bad off enough to warrant one like that and I probably couldn't afford it anyway but it sure is nice. Just out of curiosity sake do you know the price? I didn't see it listed.
Do they have a head rest that's able raised?
Generally anything with the Snap-on name is good. I looked at them on their website last night and found one that's just a little more than I planned on spending. I'm sure I can come up with the rest. Right now it's #1 on my list of choices.
The King crawler looks like a real good creeper, but I don't think it has the adjustable head rest that I really need. If it weren't for that I'd jump on it. I'm not really a cheap person. Most of the time I buy the absolute best I can afford even if it means digging a little deeper to buy the best because I'm old enough now to know that you get what you pay for.
I was thinking about stopping at Sears tomorrow and looking at them there also. Unfortunately Sears has went downhill a lot in the past yrs. on quality so I'm not sure what you'd buy today would be as good as your 15 yr. old one.
I got that in an email bout a year ago and haven't heard about it since..


– Member should be nominated by at least 3 WGTF members.
– Involvement in their community. i.e.: junior programs, free clinics, working with handicap individuals, etc.
All nominations are reviewed by the WGTF Advisory Board and President prior to final selection.
Please submit your nominations to Jennifer Russakis, USGTF Member Services at info@usgtf.com or by snail mail at: 1295 SE Port St. Lucie Blvd. Port St. Lucie, FL 34952. All nominations should be received by July 15, 2012.


Below are photos I took at the Day of the Dead celebration last night in Garfield Park.
What feelings or thoughts arise when you look at these altars?
Some of these pieces honored young people, grandparents, pets, or notable people in history. It was amazing to be a part of their story. The altars were seen by hundreds of people in the park last night.. I had to squeeze my way past the crowd just to get out!
I was inspired, moved, and so glad I ventured into town to participate.
I look forward to creating my own altar at our Campa Creatives party next weekend!


Katie Koffman works with Jennifer Bumgarner, Program Director, Southeast Campaigns, to administer grants and develop and deploy program strategies. Katie previously worked at North Carolina State University as Administrative Support Specialist for New Student Programs and the Office of Assessment. Before that, she was a coordinator for the Global Perspectives Certificate at North Carolina State.


text:
Q: Ignore all relative positioned parent divs wrapped arround absolute positioned div? I know it's not possible with css, but I was trying to find some jQuery solution, so far no luck with answers on stack.
Anyway, the HTML order looks like this, and it needs to stay like this:

So the question is how to position div with class "dont-want-parents" to the right-bottom of the wrapper div, ignoring all the relative positioned parents.
Thanks to everyone who tried to help, eventually I figured out a solution:
$(window).on("load resize",function(e){
  var parentoffset = $('.dont-want-parents').parent();
  var elwidth = $('.dont-want-parents').width();
  var offset = parentoffset.offset();
  $('.dont-want-parents').css('right', -offset.left + elwidth);
});

here's a working fiddle

A: You can set them all back to static so that the one with absolute ignores them. Also, top and left are needed, as position:absolute only removes the element from the layout but not from its original position.

$('.wrapper > div, .wrapper > div > div').css('position', 'static');
div{
  padding: 50px;
  background: rgba(255, 0, 0, 0.5);
}

.wrapper{
  position: relative;
  background: green;
}

.dont-want-parents{
  background: blue;
  top: 0;
}

Another way is to just yank out the element from wherever it is and put it somewhere that is safe to be absolute.

$('.dont-want-parents').appendTo('.wrapper');
div{
  padding: 50px;
  background: rgba(255, 0, 0, 0.5);
}

.wrapper{
  position: relative;
  background: green;
}

.dont-want-parents{
  background: blue;
  top: 0;
}

redpajama_set_name: RedPajamaStackExchange


text:
Britney Spears Continues to Put Her Family First Amid Her Father's Health Issues
It's unclear when the pop star will perform her Domination show.
By Alyssa Morin Mar 05, 2019 11:18 PMTags
Celebrity FamiliesBritney SpearsHealthCelebrities
Britney Spears is continuing to focus on her family amid her father's health issues.
Back in January, the pop star announced she was putting her work on hold, including her Britney: Domination concert, in light of Jamie Spears' sudden medical crisis. At the time of Britney's announcement, E! News confirmed his colon spontaneously ruptured and he was immediately admitted into surgery.
We also learned her father was recuperating at home and gained strength after a long recovery. He was reportedly in the hospital for a month.
Now, many outlets are reporting her dad is undergoing a second colon surgery next week. However, the "Womanizer" songstress has yet to address whether or not her dad is having another surgery.
"Jamie is definitely doing better health-wise," a source tells E! News. "He is still recovering in Louisiana and Britney's been coming back and forth to spend time with him. She's doing okay with it all right now and is just trying to be a supportive as possible."
Britney Spears Cancels Her Las Vegas Residency Show
Another insider tells E! News, "Britney has had to step back for a minute and it has not been an easy thing. She has always given so much time and attention to her fans, but she has now turned all her focus and attention on all aspects of her personal life, including her family and her love life."
The 37-year-old star has been dating Sam Asghari for quite some time.
SplashNews.com
The insider continues, "Her dad is very important to her and when he got sick, she knew she needed to take time and keep things more private. She spent many years traveling and being away from her father, and then all the quality time she had with him in Vegas over the last four years made them extra close."
Britney and Jamie's relationship is even more special, our source says, because her dad is "so good with her boys and his grandchildren." Adding, "He's silly and gets on their level. She's a parent now and she appreciates her parents more."
Earlier this year, the superstar broke her silence on her dad's health condition and apologized to her fans for having to cancel her Domination show.
Writing a lengthy, heartfelt post, she said, "It's important to always put your family first… and that's the decision I had to make. A couple of months ago, my father was hospitalized and almost died. We're all so grateful that he came out of it alive, but he still has a long road ahead of him."
Before closing her statement, she wrote, "I had to make the difficult decision to put my full focus and energy on my family at this time. I hope you all can understand."
We're wishing Jamie a speedy recovery.
Kandi Burruss Is Getting Another Bravo Spinoff: Here's Your First Look


Will changing the definition of marriage mean that we will have twice as many people to choose from?
You will always be constrained by who you are attracted to. People don't get married unless they actually like the other person (except in arrange marriages), so it isn't a matter of having more people to choose from. You've always got the same number of people to choose from (even if you can't marry them), but you only choose the gender that you are attracted to, and the person who interests you. Nothing changes as far as personal choice goes, but the opportunity to marry your own gender is opening up in many parts of the world. That's the only difference.
I need a wife, if you interested write down your e-mail or phone number? I have to go out should I let wife roam house alone or put her in her cage? My husband flirts with his younger sister but blames me for doubting. He favors her during confrontation. He wants to keep him in my home.? Why do men get married to ensure that they will never get laid again, and have nothing of value when they exit the marriage? Why do some people stay married even tho unhappy?


This page is used to submit and discuss edits for Cristian Gentile in the sortitoutsi Live Data Update for Football Manager.
Enabled DB 19.3 Cristian Gentile now has a contract of £1k per week until 31st December 2020.
Cristian Gentile is now on loan to C.D. América de Quito until 31st December 2019 paying 100% of wages.
Disabled DB 19.3 Cristian Gentile now has a contract until 31st December 2020.


It is cold, rainy, and desperately depressing here in Boston right now. After a spring-tease in April, we've been treated to nearly nothing but clouds since May started.
Out went the kelly green shorts, coral blouses and peep-toe espadrilles from three weeks ago. Back in came the black cashmere and boots of fall.
And I am SO over fall clothes.
I didn't think anything could jolt me out of my precipitation-induced coma, until I saw the designs of Madcap Cottage today.
Have you seen? They're like visual antidepressants.
John Loecke and Jason Oliver Nixon, the talents behind Madcap Cottage, might as well have their M.D.s, 'cause I feel a whole lot better after an hour in their world.


What is Brown Fat? What is White Fat?
Long term weight loss comes from understanding how your metabolism works.
Brown fat—prevalent in infants but less abundant in adults - generates heat and burns calories when stimulated. We do not want to burn brown fat but our body will in order to survive. Brown fat pads our hands the soles of our feet, cushions all organs, adds the curves to breasts and buttocks. It is possible to lose weight without losing your curves.
stress activates our ID adrenal glands, the stress glands of our body, to secrete hormones in response to this accumulated stress.
When it comes to body fat, most Americans are concerned with losing as much of it as possible. But this is referring to white fat, which is the type that typically accumulates on your belly and thighs.
Another type of fat is called brown fat, and emerging research suggests that many people may be better off increasing this beneficial type of fat. In fact, a new study revealed that one reason you may have trouble staying slim as you get older is because your levels of brown fat generally decrease with age.
A reason for your body's propensity for weight gain as it ages may have to do with decreasing levels of brown fat, which occurs naturally as you get older. Brown fat is a heat-generating type of fat that burns energy instead of storing it, and this may have important implications when it comes to weight loss.
Brown fat has been located in the neck area, around blood vessels (helping to warm your blood), and "marbled" in with white fat in visceral fat tissue. It's now thought that virtually everyone has small amounts of brown fat in their body, although certain groups of people tend to have more brown fat than others. Interestingly, it appears that the more brown fat, or the more activated brown fat, the better, as there are direct correlations between the activation of brown fat and metabolic measures of good health.
Long term weight loss comes from understanding how your metabolism works. It is not just about eating less or doing more exercise. It is about understanding how to get the most out of your body and your metabolic system.
The most simple and effective metaphor to understanding your metabolism is the pot belly stove.
Do you remember what a pot-belly stove is? A small cast-iron stove that is powered by wood to make a fire. It is used to cook or just heat up a room. Starting a fire in a pot belly stove is done in steps, start with small twigs, as the fire grows add more twigs. As the twigs burn off, you add a small piece of wood to get the fire nice and hot. Add another log to the fire and you have it warming the surrounding area and is ready to cook a meal on the stove. As the day goes on, you add another piece of wood to keep the fire burning hot.
Think of this pot-belly stove as your own belly within you. Start off with small meals not snacks. A meal is a balance of carbs, proteins and fats. Yes, fats! After hours of eating these small meals, your pot-belly stove is ready for a larger piece of wood or meal. This is your metabolism working, creating a nice hot fire, maintaining energy and burning up unwanted fats within you.
After jump starting your metabolism and getting your body's much-needed foundation working properly. The foundation is "nutrition", the essential core to better health and fitness. it is time to add exercise into the day.
Building lean muscles helps the pot-belly stove burn regularly and more efficiently.
Obesity is the enemy within all of us.
Many of us are battling with extra pounds and it's hasn't been a successful battle. There's an epidemic of obesity in America. And we have forgotten how to maintain our pot-belly stoves.


text:
Pop Meets Classical in Anne Sofie von Otter's "So Many Things"
music - classic - pop
Concert Hall, Hong Kong City Hall, Central
Until 3 Jun 2019
The renowned mezzo-soprano teams up with cutting-edge string quartet Brooklyn Rider to perform songs by Elvis Costello, Rufus Wainwright, Kate Bush and Björk, as well as string quartets by Philip Glass and Du Yun.
In this Premiere Performances show, the Swedish mezzo-soprano includes songs that blend pop music with works by contemporary classical composers, making for a spectacular evening of music. The singer doesn't see these genres "as two worlds at all, but just plain old good, interesting, attractive music that moves and inspires [her]".
Von Otter's idea of having a wide range of repertoire stemmed from her habit of listening to various genres of music on the radio and on records. Having heard many things she liked and wanted to sing, she worked with people who also function like that. This prompted her to work on something different from the conventional or traditional at the early stage. She explains in a Gramophone interview, "After a long career it's not that I'm tired of earlier music, of older music, but it's certainly quite interesting and always a challenge to see whether new music is going to be interesting and good and how the voice is going to feel when we are talking about classical contemporary. And I've always liked singing pop songs, so that's nothing new."
Photo: Mats Bäcker
When: 3 Jun 2019 - 3 Jun 2019	Where: Concert Hall, Hong Kong City Hall – 5 Edinburgh Place – Central
pphk.org