Beispiel #1
0
////////////////////////////////////////////////////////////////////////////////
// splitNode
void MaBSPTree::splitNode( MaBSPNode* pNode )
{
	MaBSPNode* pSwappedNode = NULL;

	BcBSPNodeList FList_;			// Front list.
	BcBSPNodeList BList_;			// Back list.

	// Move non coinciding node to the front.
	putNonCoincidingNodeAtTheFront( pNode->WorkingList_ );

	// Split up this nodes list into a front and back list.
	for( BcBSPNodeList::iterator It( pNode->WorkingList_.begin() ); It != pNode->WorkingList_.end(); )
	{
		MaPlane::eClassify Classify = classifyNode( (*It), pNode->Plane_ );

		// If it's coinciding use normal to determine facing.
		if( Classify == MaPlane::bcPC_COINCIDING )
		{
			/*
			if( pNode->Plane_.normal().dot( (*It)->Plane_.normal() ) < 0.0f )
			{
				Classify = MaPlane::bcPC_FRONT;
			}
			else
			{
				Classify = MaPlane::bcPC_FRONT;
			}
			*/
			// HACK, seems to work...just:
			Classify = MaPlane::bcPC_FRONT;
		}

		// Classify the node.
		switch( Classify )
		{
		case MaPlane::bcPC_FRONT:
			{
				// Node is entirely infront.
				pSwappedNode = (*It);				
				It = pNode->WorkingList_.erase( It );
				FList_.push_back( pSwappedNode );
				BcAssert( pSwappedNode->Vertices_.size() >= 2 );
			}
			break;

		case MaPlane::bcPC_BACK:
			{
				// Node is entirely behind.
				pSwappedNode = (*It);
				It = pNode->WorkingList_.erase( It );
				BList_.push_back( pSwappedNode );
				BcAssert( pSwappedNode->Vertices_.size() >= 2 );
			}
			break;

		case MaPlane::bcPC_SPANNING:
			{
				// Node spans the plane. Must be clipped.
				MaBSPNode* pFront = clipNode( (*It), MaPlane( pNode->Plane_.normal().x(), pNode->Plane_.normal().y(), pNode->Plane_.normal().z(), pNode->Plane_.d() ) );
				MaBSPNode* pBack = clipNode( (*It), MaPlane( -pNode->Plane_.normal().x(), -pNode->Plane_.normal().y(), -pNode->Plane_.normal().z(), -pNode->Plane_.d() ) );

				// Original node can be dropped.
				pSwappedNode = (*It);
				It = pNode->WorkingList_.erase( It );			
				
				// Add new nodes to lists.
				FList_.push_back( pFront );
				BcAssert( pFront->Vertices_.size() >= 2 );

				BList_.push_back( pBack );
				BcAssert( pBack->Vertices_.size() >= 2 );
			}
			break;

		default:
			//Bc_AssertFailMsg( "Duplicate plane in tree." );
			BcBreakpoint;
			break;
		}
	}
	
	// Select a front and back node for each list.
	if( FList_.size() > 0 )
	{
		pNode->pFront_ = (*FList_.begin());
		FList_.erase( FList_.begin() );

		MaBSPNode* pSwappedNode = NULL;
		for( BcBSPNodeList::iterator It( FList_.begin() ); It != FList_.end(); )
		{
			pSwappedNode = (*It);
			It = FList_.erase( It );
			pNode->pFront_->WorkingList_.push_back( pSwappedNode );
			BcAssert( pSwappedNode->Vertices_.size() >= 2 );
		}

		splitNode( pNode->pFront_ );
	}

	if( BList_.size() > 0 )
	{
		pNode->pBack_ = (*BList_.begin());
		BList_.erase( BList_.begin() );

		MaBSPNode* pSwappedNode = NULL;
		for( BcBSPNodeList::iterator It( BList_.begin() ); It != BList_.end(); )
		{
			pSwappedNode = (*It);
			It = BList_.erase( It );
			pNode->pBack_->WorkingList_.push_back( pSwappedNode );
			BcAssert( pSwappedNode->Vertices_.size() >= 2 );
		}

		splitNode( pNode->pBack_ );
	}


}
Beispiel #2
0
void ScnViewComponent::bind( RsFrame* pFrame, RsRenderSort Sort )
{
	RsContext* pContext = pFrame->getContext();

	// Calculate the viewport.
	BcF32 Width = static_cast< BcF32 >( pContext->getWidth() );
	BcF32 Height = static_cast< BcF32 >( pContext->getHeight() );

	// If we're using a render target, we want to use it for dimensions.
	if( RenderTarget_.isValid() )
	{
		Width = static_cast< BcF32 >( RenderTarget_->getWidth() );
		Height = static_cast< BcF32 >( RenderTarget_->getHeight() );
	}

	const BcF32 ViewWidth = Width_ * Width;
	const BcF32 ViewHeight = Height_ * Height;
	const BcF32 Aspect = ViewWidth / ViewHeight;

	// Setup the viewport.
	Viewport_.viewport( static_cast< BcU32 >( X_ * Width ),
	                    static_cast< BcU32 >( Y_ * Height ),
	                    static_cast< BcU32 >( ViewWidth ),
	                    static_cast< BcU32 >( ViewHeight ),
	                    Near_,
	                    Far_ );
	
	// Create appropriate projection matrix.
	if( HorizontalFOV_ > 0.0f )
	{
		ViewUniformBlock_.ProjectionTransform_.perspProjectionHorizontal( HorizontalFOV_, Aspect, Near_, Far_ );
	}
	else
	{
		ViewUniformBlock_.ProjectionTransform_.perspProjectionVertical( VerticalFOV_, 1.0f / Aspect, Near_, Far_ );
	}

	ViewUniformBlock_.InverseProjectionTransform_ = ViewUniformBlock_.ProjectionTransform_;
	ViewUniformBlock_.InverseProjectionTransform_.inverse();

	// Setup view matrix.
	ViewUniformBlock_.InverseViewTransform_ = getParentEntity()->getWorldMatrix();
	ViewUniformBlock_.ViewTransform_ = ViewUniformBlock_.InverseViewTransform_;
	ViewUniformBlock_.ViewTransform_.inverse();

	// Clip transform.
	ViewUniformBlock_.ClipTransform_ = ViewUniformBlock_.ViewTransform_ * ViewUniformBlock_.ProjectionTransform_;

	// Upload uniforms.
	RsCore::pImpl()->updateBuffer( 
		ViewUniformBuffer_,
		0, sizeof( ViewUniformBlock_ ),
		RsResourceUpdateFlags::ASYNC,
		[ this ]( RsBuffer* Buffer, const RsBufferLock& Lock )
		{
			BcMemCopy( Lock.Buffer_, &ViewUniformBlock_, sizeof( ViewUniformBlock_ ) );
		} );

	// Build frustum planes.
	// TODO: revisit this later as we don't need to do it I don't think.
	FrustumPlanes_[ 0 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][0]) );

	FrustumPlanes_[ 1 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][0] ) );

	FrustumPlanes_[ 2 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][1] ) );

	FrustumPlanes_[ 3 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][1] ) );

	FrustumPlanes_[ 4 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][2] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][2] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][2] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][2] ) );
	
	FrustumPlanes_[ 5 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] ) );

	// Normalise frustum planes.
	for ( BcU32 i = 0; i < 6; ++i )
	{
		MaVec3d Normal = FrustumPlanes_[ i ].normal();
		BcF32 Scale = 1.0f / -Normal.magnitude();
		FrustumPlanes_[ i ] = MaPlane( FrustumPlanes_[ i ].normal().x() * Scale,
		                               FrustumPlanes_[ i ].normal().y() * Scale,
		                               FrustumPlanes_[ i ].normal().z() * Scale,
		                               FrustumPlanes_[ i ].d() * Scale );
	}

	// Setup render node to set the frame buffer, viewport, and clear colour.
	// TODO: Pass this in with the draw commands down the line.
	ScnViewComponentViewport* pRenderNode = pFrame->newObject< ScnViewComponentViewport >();
	pRenderNode->Sort_ = Sort;
	pRenderNode->FrameBuffer_ = FrameBuffer_.get();
	pRenderNode->Viewport_ = Viewport_;
	pRenderNode->ClearColour_ = ClearColour_;
	pRenderNode->EnableClearColour_ = EnableClearColour_;
	pRenderNode->EnableClearDepth_ = EnableClearDepth_;
	pRenderNode->EnableClearStencil_ = EnableClearStencil_;
	pFrame->addRenderNode( pRenderNode );
}
Beispiel #3
0
//////////////////////////////////////////////////////////////////////////
// bind
void ScnViewComponent::bind( RsFrame* pFrame, RsRenderSort Sort )
{
	RsContext* pContext = pFrame->getContext();

	// Calculate the viewport.
	BcF32 Width = static_cast< BcF32 >( pContext->getWidth() );
	BcF32 Height = static_cast< BcF32 >( pContext->getHeight() );

	// If we're using a render target, we want to use it for dimensions.
	if( RenderTarget_.isValid() )
	{
		Width = static_cast< BcF32 >( RenderTarget_->getWidth() );
		Height = static_cast< BcF32 >( RenderTarget_->getHeight() );
	}

	const BcF32 ViewWidth = Width_ * Width;
	const BcF32 ViewHeight = Height_ * Height;
	const BcF32 Aspect = ViewWidth / ViewHeight;

	// Setup the viewport.
	Viewport_.viewport( static_cast< BcU32 >( X_ * Width ),
	                    static_cast< BcU32 >( Y_ * Height ),
	                    static_cast< BcU32 >( ViewWidth ),
	                    static_cast< BcU32 >( ViewHeight ),
	                    Near_,
	                    Far_ );
	
	// Setup matrices in view uniform block.
	if( ViewUniformBuffer_->lock() )
	{
		// Create appropriate projection matrix.
		if( HorizontalFOV_ > 0.0f )
		{
			ViewUniformBlock_.ProjectionTransform_.perspProjectionHorizontal( HorizontalFOV_, Aspect, Near_, Far_ );
		}
		else
		{
			ViewUniformBlock_.ProjectionTransform_.perspProjectionVertical( VerticalFOV_, 1.0f / Aspect, Near_, Far_ );
		}

		ViewUniformBlock_.InverseProjectionTransform_ = ViewUniformBlock_.ProjectionTransform_;
		ViewUniformBlock_.InverseProjectionTransform_.inverse();

		// Setup view matrix.
		ViewUniformBlock_.InverseViewTransform_ = getParentEntity()->getWorldMatrix();
		ViewUniformBlock_.ViewTransform_ = ViewUniformBlock_.InverseViewTransform_;
		ViewUniformBlock_.ViewTransform_.inverse();

		// Clip transform.
		ViewUniformBlock_.ClipTransform_ = ViewUniformBlock_.ViewTransform_ * ViewUniformBlock_.ProjectionTransform_;

		ViewUniformBuffer_->unlock();
	}

	// Build frustum planes.
	// TODO: revisit this later as we don't need to do it I don't think.
	FrustumPlanes_[ 0 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][0]) );

	FrustumPlanes_[ 1 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][0] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][0] ) );

	FrustumPlanes_[ 2 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] + ViewUniformBlock_.ClipTransform_[0][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] + ViewUniformBlock_.ClipTransform_[1][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] + ViewUniformBlock_.ClipTransform_[2][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] + ViewUniformBlock_.ClipTransform_[3][1] ) );

	FrustumPlanes_[ 3 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][1] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][1] ) );

	FrustumPlanes_[ 4 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] - ViewUniformBlock_.ClipTransform_[0][2] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] - ViewUniformBlock_.ClipTransform_[1][2] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] - ViewUniformBlock_.ClipTransform_[2][2] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] - ViewUniformBlock_.ClipTransform_[3][2] ) );
	
	FrustumPlanes_[ 5 ] = MaPlane( ( ViewUniformBlock_.ClipTransform_[0][3] ),
	                               ( ViewUniformBlock_.ClipTransform_[1][3] ),
	                               ( ViewUniformBlock_.ClipTransform_[2][3] ),
	                               ( ViewUniformBlock_.ClipTransform_[3][3] ) );

	// Normalise frustum planes.
	for ( BcU32 i = 0; i < 6; ++i )
	{
		MaVec3d Normal = FrustumPlanes_[ i ].normal();
		BcF32 Scale = 1.0f / -Normal.magnitude();
		FrustumPlanes_[ i ] = MaPlane( FrustumPlanes_[ i ].normal().x() * Scale,
		                               FrustumPlanes_[ i ].normal().y() * Scale,
		                               FrustumPlanes_[ i ].normal().z() * Scale,
		                               FrustumPlanes_[ i ].d() * Scale );
	}

	// Set render target.
	if( RenderTarget_.isValid() )
	{
		RenderTarget_->bind( pFrame );
	}
	else
	{
		pFrame->setRenderTarget( NULL );
	}
	
	// Set viewport.
	pFrame->setViewport( Viewport_ );
}