Exemple #1
0
sF32 sBSpline::Evaluate(sF32 time) const
{
    sInt deg = Degree;
    sF32 *weights = (sF32 *) _alloca(sizeof(sF32) * (deg + 1));
    sInt first;

    CalcBasis(time,first,weights);

    sF32 value = 0.0f;
    for(sInt i=0; i<=deg; i++)
        value += weights[i] * Values[first+i];

    return value;
}
void CGlowOverlay::Draw( bool bCacheFullSceneState )
{
	extern ConVar	r_drawsprites;
	if( !r_drawsprites.GetBool() )
		return;
	
	// Get the vector to the sun.
	Vector vToGlow;
	
	if( m_bDirectional )
		vToGlow = m_vDirection;
	else
		vToGlow = m_vPos - CurrentViewOrigin();

	VectorNormalize( vToGlow );

	float flDot = vToGlow.Dot( CurrentViewForward() );

	UpdateGlowObstruction( vToGlow, bCacheFullSceneState );
	if( m_flGlowObstructionScale == 0 )
		return;
	
	bool bWireframe = ShouldDrawInWireFrameMode() || (r_drawsprites.GetInt() == 2);
	
	CMatRenderContextPtr pRenderContext( materials );

	for( int iSprite=0; iSprite < m_nSprites; iSprite++ )
	{
		CGlowSprite *pSprite = &m_Sprites[iSprite];
 
		// Figure out the color and size to draw it.
		float flHorzSize, flVertSize;
		Vector vColor;
		CalcSpriteColorAndSize( flDot, pSprite, &flHorzSize, &flVertSize, &vColor );
	
		// If we're alpha'd out, then don't bother
		if ( vColor.LengthSqr() < 0.00001f )
			continue;
		
		// Setup the basis to draw the sprite.
		Vector vBasePt, vUp, vRight;
		CalcBasis( vToGlow, flHorzSize, flVertSize, vBasePt, vUp, vRight );

		//Get our diagonal radius
		float radius = (vRight+vUp).Length();
		if ( R_CullSphere( view->GetFrustum(), 5, &vBasePt, radius ) )
			continue;

		// Get our material (deferred default load)
		if ( m_Sprites[iSprite].m_pMaterial == NULL )
		{
			m_Sprites[iSprite].m_pMaterial = materials->FindMaterial( "sprites/light_glow02_add_noz", TEXTURE_GROUP_CLIENT_EFFECTS );
		}

		Assert( m_Sprites[iSprite].m_pMaterial );
		static unsigned int		nHDRColorScaleCache = 0;
		IMaterialVar *pHDRColorScaleVar = m_Sprites[iSprite].m_pMaterial->FindVarFast( "$hdrcolorscale", &nHDRColorScaleCache );
		if( pHDRColorScaleVar )
		{
			pHDRColorScaleVar->SetFloatValue( m_flHDRColorScale );
		}

		// Draw the sprite.
		IMesh *pMesh = pRenderContext->GetDynamicMesh( false, 0, 0, m_Sprites[iSprite].m_pMaterial );

		CMeshBuilder builder;
		builder.Begin( pMesh, MATERIAL_QUADS, 1 );
		
		Vector vPt;
		
		vPt = vBasePt - vRight + vUp;
		builder.Position3fv( vPt.Base() );
		builder.Color4f( VectorExpand(vColor), 1 );
		builder.TexCoord2f( 0, 0, 1 );
		builder.AdvanceVertex();
		
		vPt = vBasePt + vRight + vUp;
		builder.Position3fv( vPt.Base() );
		builder.Color4f( VectorExpand(vColor), 1 );
		builder.TexCoord2f( 0, 1, 1 );
		builder.AdvanceVertex();
		
		vPt = vBasePt + vRight - vUp;
		builder.Position3fv( vPt.Base() );
		builder.Color4f( VectorExpand(vColor), 1 );
		builder.TexCoord2f( 0, 1, 0 );
		builder.AdvanceVertex();
		
		vPt = vBasePt - vRight - vUp;
		builder.Position3fv( vPt.Base() );
		builder.Color4f( VectorExpand(vColor), 1 );
		builder.TexCoord2f( 0, 0, 0 );
		builder.AdvanceVertex();
		
		builder.End( false, true );

		if( bWireframe )
		{
			IMaterial *pWireframeMaterial = materials->FindMaterial( "debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER );
			pRenderContext->Bind( pWireframeMaterial );
			
			// Draw the sprite.
			IMesh *pMesh = pRenderContext->GetDynamicMesh( false, 0, 0, pWireframeMaterial );
			
			CMeshBuilder builder;
			builder.Begin( pMesh, MATERIAL_QUADS, 1 );
			
			Vector vPt;
			
			vPt = vBasePt - vRight + vUp;
			builder.Position3fv( vPt.Base() );
			builder.Color3f( 1.0f, 0.0f, 0.0f );
			builder.AdvanceVertex();
			
			vPt = vBasePt + vRight + vUp;
			builder.Position3fv( vPt.Base() );
			builder.Color3f( 1.0f, 0.0f, 0.0f );
			builder.AdvanceVertex();
			
			vPt = vBasePt + vRight - vUp;
			builder.Position3fv( vPt.Base() );
			builder.Color3f( 1.0f, 0.0f, 0.0f );
			builder.AdvanceVertex();
			
			vPt = vBasePt - vRight - vUp;
			builder.Position3fv( vPt.Base() );
			builder.Color3f( 1.0f, 0.0f, 0.0f );
			builder.AdvanceVertex();
			
			builder.End( false, true );
		}
	}
}
//-----------------------------------------------------------------------------
// Purpose: Special draw for the warped overlay
//-----------------------------------------------------------------------------
void CWarpOverlay::Draw( bool bCacheFullSceneState )
{
	// Get the vector to the sun.
	Vector vToGlow;
	
	if( m_bDirectional )
		vToGlow = m_vDirection;
	else
		vToGlow = m_vPos - CurrentViewOrigin();

	VectorNormalize( vToGlow );

	float flDot = vToGlow.Dot( CurrentViewForward() );

	if( flDot <= g_flOverlayRange )
		return;

	UpdateGlowObstruction( vToGlow, bCacheFullSceneState );
	if( m_flGlowObstructionScale == 0 )
		return;
	
	CMatRenderContextPtr pRenderContext( materials );
	
	//FIXME: Allow multiple?
	for( int iSprite=0; iSprite < m_nSprites; iSprite++ )
	{
		CGlowSprite *pSprite = &m_Sprites[iSprite];

		// Figure out the color and size to draw it.
		float flHorzSize, flVertSize;
		Vector vColor;
		CalcSpriteColorAndSize( flDot, pSprite, &flHorzSize, &flVertSize, &vColor );
	
		// Setup the basis to draw the sprite.
		Vector vBasePt, vUp, vRight;
		CalcBasis( vToGlow, flHorzSize, flVertSize, vBasePt, vUp, vRight );

		// Draw the sprite.
		IMaterial *pMaterial = materials->FindMaterial( "sun/overlay", TEXTURE_GROUP_CLIENT_EFFECTS );
		IMesh *pMesh = pRenderContext->GetDynamicMesh( false, 0, 0, pMaterial );

		CMeshBuilder builder;
		builder.Begin( pMesh, MATERIAL_QUADS, 1 );
		
		Vector vPt;

		vPt = vBasePt - vRight + vUp;
		builder.Position3fv( vPt.Base() );
		builder.Color4f( VectorExpand(vColor), 1 );
		builder.TexCoord2f( 0, 0, 1 );
		builder.AdvanceVertex();

		vPt = vBasePt + vRight + vUp;
		builder.Position3fv( vPt.Base() );
		builder.Color4f( VectorExpand(vColor), 1 );
		builder.TexCoord2f( 0, 1, 1 );
		builder.AdvanceVertex();

		vPt = vBasePt + vRight - vUp;
		builder.Position3fv( vPt.Base() );
		builder.Color4f( VectorExpand(vColor), 1 );
		builder.TexCoord2f( 0, 1, 0 );
		builder.AdvanceVertex();

		vPt = vBasePt - vRight - vUp;
		builder.Position3fv( vPt.Base() );
		builder.Color4f( VectorExpand(vColor), 1 );
		builder.TexCoord2f( 0, 0, 0 );
		builder.AdvanceVertex();
		
		builder.End( false, true );
	}
}
Exemple #4
0
void sBSpline::LeastSquaresFit(const Sample *samples,sInt nSamples)
{
    // The input dataset is assumed to be on [0,1)
    // Now do a least-squares fit via normal equations, that is solve
    //   (A^T A) x = A^T b
    // for x.
    //
    // To do this, first compute the weights of the B-Spline at
    // sample points to determine A
    sInt deg = Degree,order = Degree + 1;
    sInt nKnots = Knots.Count;

    sF32 *A = new sF32[nSamples * order];
    sInt *start = new sInt[nSamples];

    for(sInt i=0; i<nSamples; i++)
        if(samples[i].Type == 0) // normal function value
            CalcBasis(samples[i].Time,start[i],A + i*order);
        else // derivative
            CalcBasisDeriv(samples[i].Time,start[i],A + i*order);

    // Next, calculate the matrix A^T A. This is always symmetrical and
    // positive semidefinite, and in this case also a banded matrix, so we
    // only need order * nKnots floats to store it
    sF32 *ATA = new sF32[nKnots * order];

    for(sInt i=0; i<nKnots; i++)
    {
        // samples for knot i
        sInt start1 = lowerBound(start,i-deg,nSamples);
        sInt end1 = lowerBound(start,i+1,nSamples);

        for(sInt j=0; j<order; j++)
        {
            // samples for knot i+j-deg
            sInt start2 = lowerBound(start,i+j-2*deg,nSamples);
            sInt end2 = lowerBound(start,i+j-deg+1,nSamples);

            // calculate overlap
            sInt commonStart = sMax(start1,start2);
            sInt commonEnd = sMin(end1,end2);

            // perform summation
            sF64 sum = 0.0f;
            for(sInt k=commonStart; k<commonEnd; k++)
            {
                sF32 *pos = &A[k*order + i-start[k]];
                sum += pos[0] * pos[j-deg];
            }

            ATA[i*order+j] = sum;
        }
    }

    // Compute a LDL^T decomposition of A^T A (in-place)
    sF32 *scale = new sF32[nKnots];
    for(sInt i=0; i<nKnots; i++)
    {
        // Solve for diagonal element
        sF64 d = ATA[i*order+deg];
        for(sInt j=sMax(i-deg,0); j<i; j++)
            d -= sSquare(ATA[i*order+(j-i)+deg])*ATA[j*order+deg];

        // Calculate inverse d, store back
        d = (sFAbs(d) > 1e-10f) ? d : 0.0f;
        sF64 id = d ? 1.0f / d : 0.0f;
        ATA[i*order+deg] = d;
        scale[i] = id;

        // Solve for rest
        for(sInt j=1; j<order; j++)
        {
            sInt row = i+j;

            if(row < nKnots)
            {
                sF64 sum = ATA[row*order+deg-j];
                for(sInt k=sMax(row-deg,0); k<i; k++)
                    sum -= ATA[row*order+(k-row)+deg] * ATA[i*order+(k-i)+deg] * ATA[k*order+deg];

                ATA[row*order+deg-j] = id * sum;
            }
        }
    }

    // Now, actually solve the system. Anything before this only needs to be
    // done once per knot vector.
    // Compute A^T b
    for(sInt i=0; i<nKnots; i++)
    {
        sInt startw = lowerBound(start,i-deg,nSamples);
        sInt endw = lowerBound(start,i+1,nSamples);

        sF64 c = 0.0f;
        for(sInt j=startw; j<endw; j++)
            c += A[j*order + i-start[j]] * samples[j].Value;

        Values[i] = c;
    }

    // Solve Lx
    for(sInt i=0; i<nKnots; i++)
    {
        sF64 sum = Values[i];
        for(sInt j=sMax(i-deg,0); j<i; j++)
            sum -= ATA[i*order+(j-i)+deg] * Values[j];

        Values[i] = sum;
    }

    // Solve Dx
    for(sInt i=0; i<nKnots; i++)
        Values[i] *= scale[i];

    // Solve L^Tx (backwards substitution)
    for(sInt i=nKnots-2; i>=0; i--)
    {
        sF64 sum = Values[i];
        for(sInt j=i+1; j<sMin(i+order,nKnots); j++)
            sum -= ATA[j*order+(i-j)+deg] * Values[j];

        Values[i] = sum;
    }

    // Cleanup
    delete[] A;
    delete[] start;
    delete[] ATA;
    delete[] scale;
}