Пример #1
0
//----------------------------------------------------------------------------
void NodeBillboard::UpdateWorldData(Double appTime, Bool updateControllers)
{
    // Compute billboard's world transforms based on its parent's world
    // transform and its local transforms. Notice that you should not call
    // Node::UpdateWorldData since that function updates its children. The
    // children of a NodeBillboard cannot be updated until the billboard is
    // aligned with the camera.
    Spatial::UpdateWorldData(appTime, updateControllers);

    if (mspCamera)
    {
        // Inverse-transform the camera to the model space of the billboard.
        Vector3F camLocation = World.ApplyInverse(mspCamera->GetLocation());

        // To align the billboard, the projection of the camera to the
        // xz-plane of the billboard's model space determines the angle of
        // rotation about the billboard's model y-axis. If the projected
        // camera is on the model axis (x = 0 and z = 0), ATan2 returns zero
        // (rather than NaN), so there is no need to trap this degenerate
        // case and handle it separately.
        Float angle = MathF::ATan2(camLocation.X(), camLocation.Z());
        Matrix34F orientation(Vector3F::UNIT_Y, angle);
        World.SetRotate(World.GetMatrix() * orientation);
    }

    // update the children now that the billboard orientation is known
    for (UInt i = 0; i < mChildren.GetQuantity(); i++)
    {
        Spatial* pChild = mChildren[i];
        if (pChild)
        {
            pChild->UpdateGS(appTime, false, updateControllers);
        }
    }
}
Пример #2
0
float grinliz::PointBetweenPoints( const Vector3F& p0, const Vector3F& p1, const Vector3F& pi )
{
	float validCount = 0.0f;
	float t = 0.0f;

	// p0.x + t*(p1.x-p0.x) = pi.x
	for( int i=0; i<3; ++i ) {
		float denom = p1.X(i) - p0.X(i);
		if ( !Equal( denom, 0.0f, 0.001f ) ) {
			float t0 = ( pi.X(i) - p0.X(i) ) / denom;
			GLASSERT( t0 >= 0.0f && t0 <= 1.0f );
			t += t0;
			validCount += 1.0f;
		}
	}
	t /= validCount;
	GLASSERT( t >= 0.0f && t <= 1.0f );
	return t;
}
Пример #3
0
//----------------------------------------------------------------------------
void Game::DrawWarning(Double time)
{
	GetRenderer()->DisableLighting();
	Float f = (MathF::Sin(MathF::FMod(static_cast<Float>(time*5),
		MathF::TWO_PI)) + 1) * 0.5F;
	ColorRGB color(1, f, f);
	mspWarningText->Clear(color);
	mspWarningText->Append("Aim at the screen!");
	mspWarningText->Update(GetRenderer());

	Vector3F center = mspWarningText->GetMesh()->GetModelBound()->GetCenter();
	center.Y() -= static_cast<Float>(mpRenderer->GetHeight()) * 0.5F;
	center.X() -= static_cast<Float>(mpRenderer->GetWidth()) * 0.5F;
	Transformation translate;
	translate.SetTranslate(-center);

	GetRenderer()->Draw(mspWarningText, translate);
}
Пример #4
0
int grinliz::IntersectRayPlane(	const Vector3F& origin, const Vector3F& dir,
                                int plane, float x,
                                Vector3F* intersect )
{
    GLASSERT( plane >=0 && plane < 3 );

    if ( dir.X(plane) > -EPSILON && dir.X(plane) < EPSILON )
        return REJECT;
    if ( dir.X(plane) > 0.0f && origin.X(plane) >= x )
        return REJECT;
    if ( dir.X(plane) < 0.0f && origin.X(plane) <= x )
        return REJECT;

    float t = ( x - origin.X(plane) ) / dir.X(plane);

    if ( intersect ) {
        intersect->x = origin.x + dir.x * t;
        intersect->y = origin.y + dir.y * t;
        intersect->z = origin.z + dir.z * t;
    }
    return INTERSECT;
}
Пример #5
0
int grinliz::IntersectionRayAABB(	const Ray& ray,
									const Rectangle3F& aabb,
									Rectangle3F* result )
{
	bool hasStart = false;
	bool hasEnd = false;
	Vector3F start, end;

	GLASSERT( Equal( ray.direction.Length(), 1.0f, 0.001f ) );

	if ( aabb.Contains( ray.origin ) )
	{
		hasStart = true;
		start = ray.origin;
	}

	// Check for an intersection with each face. If t>0 and it is a 
	// positive dot then it is an 'end'. If t>0 and it is a negative
	// dot, then it is a 'start'.

	Vector3F at;
	float t;			

	for( int k=0; k<=1; ++k )
	{
		Vector3F originToPlane;
		if ( k == 0 ) {
			// min
			originToPlane.Set(	aabb.min.x - ray.origin.x,
								aabb.min.y - ray.origin.y,
								aabb.min.z - ray.origin.z );
		}
		else {
			// max
			originToPlane.Set(	aabb.max.x - ray.origin.x,
								aabb.max.y - ray.origin.y,
								aabb.max.z - ray.origin.z );
		}

		for ( int i=0; i<3 && !(hasEnd && hasStart); ++i ) {
			int i1 = (i + 1)%3;
			int i2 = (i + 2)%3;

			Vector3F planeNormal = { 0.0f, 0.0f, 0.0f };
			planeNormal.X(i) = ( k == 0 ) ? -1.0f : 1.0f;
			float dot = DotProduct( originToPlane, planeNormal );

			int hit = IntersectRayAAPlane(	ray.origin, ray.direction,
											i, 
											(k==0) ? aabb.min.X(i) : aabb.max.X(i),
											&at, &t );
			if (    hit == INTERSECT 
				 && t > 0.0f
				 && InRange( at.X(i1), aabb.min.X(i1), aabb.max.X(i1) )
				 && InRange( at.X(i2), aabb.min.X(i2), aabb.max.X(i2) ) )
			{
				// We have hit a face of the AABB
				if ( dot > 0.0f ) {
					GLASSERT( !hasEnd );
					hasEnd = true;
					if ( t > ray.length )
						end = ray.origin + ray.direction*t;
					else
						end = at;
				}
				else if ( dot < 0.0f ) {
					GLASSERT( !hasStart );
					hasStart = true;
					if ( t > ray.length ) {
						return REJECT;	// the start never gets to the AABB
					}
					start = at;
				}
			}
		}
	}
	if( !hasStart || !hasEnd ) {
		return REJECT;
	}
	for( int i=0; i<3; ++i ) {
		result->min.X(i) = Min( start.X(i), end.X(i) );
		result->max.X(i) = Max( start.X(i), end.X(i) );
	}
	return INTERSECT;
}