void Sphere::MakeBound( Bound &out_bound ) const
{
	float	tuMin = mThetamaxRad * mURange[0];
	float	tuMax = mThetamaxRad * mURange[1];

	float	alphaMin = DASin( mZMin / mRadius );
	float	alphaMax = DASin( mZMax / mRadius );

	float	aVMin = DMix( alphaMin, alphaMax, mVRange[0] );
	float	aVMax = DMix( alphaMin, alphaMax, mVRange[1] );

	float	rVMin = DCos( aVMin ) * mRadius;
	float	rVMax = DCos( aVMax ) * mRadius;
	float	rMin = DMIN( rVMin, rVMax );
	
	float	rMax;
	
	if ( aVMin < 0 && aVMax > 0 )
		rMax = mRadius;
	else
		rMax = DMAX( rVMin, rVMax );
	
	out_bound.Reset();
	bounds2DSweepL( out_bound, rMin, rMax, tuMin, tuMax );

	out_bound.mBox[0].z() = DSin( aVMin ) * mRadius;
	out_bound.mBox[1].z() = DSin( aVMax ) * mRadius;
}
//==================================================================
void Cylinder::MakeBound( Bound &out_bound ) const
{
	float	tuMin = mThetamaxRad * mURange[0];
	float	tuMax = mThetamaxRad * mURange[1];
	out_bound.Reset();
	bounds2DSweepL( out_bound, mRadius, mRadius, tuMin, tuMax );
	out_bound.mBox[0].z() = DMix( mZMin, mZMax, mVRange[0] );
	out_bound.mBox[1].z() = DMix( mZMin, mZMax, mVRange[1] );
}
void Torus::MakeBound( Bound &out_bound ) const
{
	float	tuMin = mThetamaxRad * mURange[0];
	float	tuMax = mThetamaxRad * mURange[1];

	float	phiVMin = DMix( mPhiminRad, mPhimaxRad, mVRange[0] );
	float	phiVMax = DMix( mPhiminRad, mPhimaxRad, mVRange[1] );

	Bound	a;
	a.Reset();
	bounds2DSweepR( a, mMinRadius, phiVMin, phiVMax );
	float	rMin = a.mBox[0].x() + mMaxRadius;
	float	rMax = a.mBox[1].x() + mMaxRadius;

	out_bound.Reset();
	bounds2DSweepL( out_bound, rMin, rMax, tuMin, tuMax );
	out_bound.mBox[0].z() = a.mBox[0].y();
	out_bound.mBox[1].z() = a.mBox[1].y();
}
void Cone::MakeBound( Bound &out_bound ) const
{
	float	tuMin = mThetamaxRad * mURange[0];
	float	tuMax = mThetamaxRad * mURange[1];

	float	rMin = mRadius * (1 - mVRange[1]);
	float	rMax = mRadius * (1 - mVRange[0]);
	out_bound.Reset();
	bounds2DSweepL( out_bound, rMin, rMax, tuMin, tuMax );
	out_bound.mBox[0].z() = mVRange[0] * mHeight;
	out_bound.mBox[1].z() = mVRange[1] * mHeight;
}
void Paraboloid::MakeBound( Bound &out_bound ) const
{
	float	scale = mRmax / DSqrt( mZmax );

	float	tuMin = mThetamaxRad * mURange[0];
	float	tuMax = mThetamaxRad * mURange[1];
	float	zVMin = mZmin + mVRange[0] * (mZmax-mZmin);
	float	zVMax = mZmin + mVRange[1] * (mZmax-mZmin);
	float	rMin = DSqrt( zVMin ) * scale;
	float	rMax = DSqrt( zVMax ) * scale;
	out_bound.Reset();
	bounds2DSweepL( out_bound, rMin, rMax, tuMin, tuMax );
	out_bound.mBox[0].z() = zVMin;
	out_bound.mBox[1].z() = zVMax;
}
void Hyperboloid::MakeBound( Bound &out_bound ) const
{
	float	tuMin = mThetamaxRad * mURange[0];
	float	tuMax = mThetamaxRad * mURange[1];

	Float2_	uvMin( 0.f, mVRange[0] );
	Float2_	uvMax( 0.f, mVRange[1] );
	Float3_	pMin; EvalP( uvMin, pMin );
	Float3_	pMax; EvalP( uvMax, pMax );

	out_bound.Reset();
	bounds2DSweepP( out_bound, pMin.x()[0], pMin.y()[0], tuMin, tuMax );
	bounds2DSweepP( out_bound, pMax.x()[0], pMax.y()[0], tuMin, tuMax );
	
	out_bound.mBox[0].z() = DMIN( pMin.z()[0], pMax.z()[0] );
	out_bound.mBox[1].z() = DMAX( pMin.z()[0], pMax.z()[0] );
}
Beispiel #7
0
//==================================================================
SimplePrimitiveBase::CheckSplitRes
	SimplePrimitiveBase::CheckForSplit(
							const Hider &hider,
							int			out_bound2d[4],
							bool		&out_uSplit,
							bool		&out_vSplit )
{
	const Matrix44 &mtxLocalWorld = mpTransform->GetMatrix();

	DASSERT( mDiceGridWd == -1 && mDiceGridHe == -1 );

	Float3_	testDicePo[ MAX_MAKE_BOUND_OUT_SIZE ];

	Bound	bound;
	bound.Reset();

	MakeBound( bound, testDicePo );

	float pixelArea = hider.RasterEstimate( bound, mtxLocalWorld, out_bound2d );
	
	if ( pixelArea <= MP_GRID_MAX_SIZE )
	{
		if ( pixelArea < RI_EPSILON )
		{
			return CHECKSPLITRES_CULL;
		}

		float	dim = DSqrt( pixelArea );

		mDiceGridWd = DMT_SIMD_PADSIZE( (int)ceilf( dim ) );
		mDiceGridHe = (int)ceilf( dim );

		out_uSplit = false;
		out_vSplit = false;

		return CHECKSPLITRES_DICE;	// will dice
	}
	else
	{
#if 0
		SlVec2	locUV[ TEST_DICE_SIMD_BLOCKS ];
		// set last item to 0 to be safe when using the AddReduce() later on
		locUV[ TEST_DICE_SIMD_BLOCKS - 1 ] = SlVec2( 0.f, 0.f );

		fillUVsArray(
				locUV,
				1.0f / (TEST_DICE_LEN - 1),
				1.0f / (TEST_DICE_LEN - 1),
				TEST_DICE_LEN,
				TEST_DICE_LEN );

		//Float3_	avg_dPdu( 0.f, 0.f, 0.f );
		//Float3_	avg_dPdv( 0.f, 0.f, 0.f );
		SlScalar	avg_dPdu( 0.f );
		SlScalar	avg_dPdv( 0.f );
		for (u_int i=0; i < TEST_DICE_SIMD_BLOCKS; ++i)
		{
			SlVec3	posLS;
			SlVec3	dPdu;
			SlVec3	dPdv;

			Eval_dPdu_dPdv( locUV[ i ], posLS, &dPdu, &dPdv );

			avg_dPdu += dPdu.GetLengthSqr();
			avg_dPdv += dPdv.GetLengthSqr();
		}

		// divide by the total number of elements 
		//avg_dPdu /= (float)TEST_DICE_SIMD_BLOCKS * DMT_SIMD_FLEN;
		//avg_dPdv /= (float)TEST_DICE_SIMD_BLOCKS * DMT_SIMD_FLEN;
/*

		Float3 avg_dPdu_s(
				avg_dPdu.x().AddReduce(),	// avg_dPdu.x()[0] + avg_dPdu.x()[1] ...
				avg_dPdu.y().AddReduce(),
				avg_dPdu.z().AddReduce() );

		Float3 avg_dPdv_s(
				avg_dPdv.x().AddReduce(),	// avg_dPdv.x()[0] + avg_dPdv.x()[1] ...
				avg_dPdv.y().AddReduce(),
				avg_dPdv.z().AddReduce() );
*/

		float lenU = avg_dPdu.AddReduce();
		float lenV = avg_dPdv.AddReduce();

		if ( lenU < lenV )
		{
			out_uSplit = false;
			out_vSplit = true;
		}
		else
		{
			out_uSplit = true;
			out_vSplit = false;
		}

#else
		out_uSplit = true;
		out_vSplit = true;

#endif

		return CHECKSPLITRES_SPLIT;	// will split
	}
}