int CameraComponent::DoTick(U32 delta)
{
	float EASE = 0.2f;

	switch (mode) {

		case PAN:
		{
			Vector3F d = (dest - camera->PosWC());
			Vector3F c = camera->PosWC();

			if (d.Length() < 0.01f) {
				camera->SetPosWC(dest.x, dest.y, dest.z);
				mode = DONE;
			}
			else {
				camera->SetPosWC(c.x + EASE*d.x, c.y + EASE*d.y, c.z + EASE*d.z);
			}
		}
		break;

		case TRACK:
		{
			Chit* chit = Context()->chitBag->GetChit(targetChitID);
			if (chit) {

				Vector3F pos = chit->Position();
				pos.y = 0;

				// Scoot the camera to always focus on the target. Removes
				// errors that occur from rotation, drift, etc.
				const Vector3F* eye3 = camera->EyeDir3();
				Vector3F at;
				int result = IntersectRayPlane(camera->PosWC(), eye3[0], 1, 0.0f, &at);
				if (result == INTERSECT) {
					Vector3F t = (camera->PosWC() - at);

					//camera->SetPosWC( pos + t );
					Vector3F c = camera->PosWC();
					Vector3F d = (pos + t) - c;

					// If grid moving, the EASE contributes to jitter.
					if (GET_SUB_COMPONENT(chit, MoveComponent, GridMoveComponent)) {
						EASE = 1.0f;
					}
					camera->SetPosWC(c.x + EASE*d.x, pos.y + t.y, c.z + EASE*d.z);
				}
			}
		}
		break;

		case DONE:
		break;

		default:
		GLASSERT(0);
	}
	return 0;
}
/*static*/ void Plane::CreatePlane( const Vector3F& normal, const Vector3F& point, Plane* plane )
{
    // n * p + d = 0
    // so: d = -n*p

    GLASSERT( Equal( normal.Length(), 1.0f, 0.001f ) );
    plane->n = normal;
    plane->d = -DotProduct( normal, point );
}
void SphericalXZ::FromCartesion( const Vector3F& in )
{
    theta = rho = 0.0f;
    r = in.Length();

    if ( r != 0.0f ) {
        rho = acosf( in.y / r );
    }
    if ( in.z != 0.0f ) {
        theta = atanf( -in.x / in.z );
    }
}
/// <summary>
/// Sets up a quaternion & position from vector camera components
/// and oriented the camera up
/// </summary>
/// <param name="eye">The camera position</param>
/// <param name="lookAt">The camera's look-at point</param>
/// <param name="up"></param>
void ArcBallCameraController::SetCamera(Vector3F position, Vector3F target, Vector3F up)
{
	m_bRecomputeViewMatrix = true;

	//Create a look at matrix, to simplify matters a bit
	Matrix4 temp;
	temp.LookAt(position, target, up);

	//invert the matrix, since we're determining the
	//orientation from the rotation matrix in RH coords
	temp.Invert();

	//set the position
	m_Target = target;

	//set distance
	m_fDistance = (target - position).Length();

	//create the new aspect from the look-at matrix
	m_ArcBallOrientation.FromMatrix(temp);

	//When setting a new eye-view direction 
	//in one of the gamble-locked modes, the yaw and
	//pitch gimble must be calculated.

	//first, get the direction projected on the x/z plne
	Vector3F dir = Direction();
	dir.y = 0.0f;
	if (dir.Length() == 0.0f)
	{
		dir = Vector3F::Forward();
	}
	dir.Normalize();

	//find the yaw of the direction on the x/z plane
	//and use the sign of the x-component since we have 360 degrees
	//of freedom
	m_fArcBallYaw = (acosf(-dir.z) * Sign(dir.x));

	//Get the pitch from the angle formed by the Up vector and the 
	//the forward direction, then subtracting Pi / 2, since 
	//we pitch is zero at Forward, not Up.
	m_fArcBallPitch = -(acosf(Vector3F::Dot(Vector3F::Up(), Direction())) - MATH_PI_DIV_2);
}
Beispiel #5
0
Bolt* LumosChitBag::NewBolt(	const Vector3F& pos,
								const Vector3F& _dir,
								int effectFlags,
								int chitID,
								float damage,
								float speed,
								bool trail )
{
	GLASSERT(pos.y > 0);
	GLASSERT(pos.y < 4);

	Bolt* bolt = ChitBag::NewBolt();

	Vector3F dir = _dir;
	dir.Normalize();
	GLASSERT(Equal(dir.Length(), 1.0f));

	bolt->head = pos + dir * 0.5f;
	bolt->len = 0.5f;
	bolt->dir = dir;

	const Game::Palette* palette = Game::GetMainPalette();

	switch( effectFlags & (GameItem::EFFECT_FIRE | GameItem::EFFECT_SHOCK) ) {
	case 0:													bolt->color = palette->Get4F( 1, PAL_GREEN );	break;
	case GameItem::EFFECT_FIRE:								bolt->color = palette->Get4F( 1, PAL_RED );		break;
	case GameItem::EFFECT_SHOCK:							bolt->color = palette->Get4F( 1, PAL_BLUE );	break;
	case GameItem::EFFECT_FIRE | GameItem::EFFECT_SHOCK:	bolt->color = palette->Get4F( 1, PAL_PURPLE );	break;
	default:
		GLASSERT( 0 );
		break;
	}

	bolt->chitID = chitID;
	bolt->damage = damage;
	bolt->effect = effectFlags;
	bolt->particle  = trail;
	bolt->speed = speed;
	bolt->frameCount = 0;

	return bolt;
}
Beispiel #6
0
void XenoAudio::SetChannelPos(int i)
{
	if (!audioOn) return;

	if (sounds[i].pos.IsZero()) {
		Mix_SetPosition(i, 0, 0);
	}
	else {
		Vector3F delta = sounds[i].pos - listenerPos;
		float len = delta.Length();
		float df = len / MAX_DISTANCE;
		int d = LRintf(df*255.0f);
		d = Clamp(d, 0, 255);

		if (delta.LengthSquared() > 0.001f) {
			delta.Normalize();
		}
		else {
			delta.Set(0, 0, -1);
		}

		static const Vector3F UP = { 0, 1, 0 };
		Vector3F listenerRight = CrossProduct(listenerDir, UP);

		float dotFront = DotProduct(delta, listenerDir);
		float dotRight = DotProduct(delta, listenerRight);

		// 0 is north, 90 is east, etc. WTF.
		float rad = atan2(dotRight, dotFront);
		float deg = rad * 180.0f / PI;
		int degi = int(deg);
		if (degi < 0) degi += 360;

		int result = Mix_SetPosition(i, degi, d);
		GLASSERT(result != 0);
		(void)result;
	}
}
void FireWidget::Place( BattleScene* battle,
						const Unit* shooterUnit,
						const Unit* targetUnit, 
						const grinliz::Vector2I& targetPos )
{
	GLASSERT( targetUnit || targetPos.x >= 0 );

	const Model* targetModel = 0;
	const Model* targetWeapon = 0;
	
	Vector3F target;
	BulletTarget bulletTarget;

	if ( targetPos.x >= 0 ) {
		target.Set( (float)targetPos.x+0.5f, 1.0f, (float)targetPos.y+0.5f );
	}
	else {
		targetModel = battle->GetModel( targetUnit );
		targetWeapon = battle->GetWeaponModel( targetUnit );
		GLASSERT( targetModel );
		targetModel->CalcTarget( &target );
		targetModel->CalcTargetSize( &bulletTarget.width, &bulletTarget.height );
	}

	Vector3F distVector = target - shooterUnit->Pos();
	bulletTarget.distance = distVector.Length();

	const Inventory* inventory = shooterUnit->GetInventory();
	const WeaponItemDef* wid = shooterUnit->GetWeaponDef();

	float snapTU=0, autoTU=0, altTU=0;
	if ( wid ) {
		shooterUnit->AllFireTimeUnits( &snapTU, &autoTU, &altTU );
	}

	int numButtons = 0;
	if ( wid )
	{
		for( int i=0; i<WeaponItemDef::MAX_MODE && wid->HasWeapon(i); ++i ) 
		{
			float fraction, anyFraction, dptu, tu;

			shooterUnit->FireStatistics( i, bulletTarget, &fraction, &anyFraction, &tu, &dptu );
			int nRounds = inventory->CalcClipRoundsTotal( wid->GetClipItemDef( i) );

			anyFraction = Clamp( anyFraction, 0.0f, 0.95f );

			char buffer0[32];
			char buffer1[32];
			SNPrintf( buffer0, 32, "%s %d%%", wid->weapon[i]->desc, (int)LRintf( anyFraction*100.0f ) );
			SNPrintf( buffer1, 32, "%d/%d", wid->RoundsNeeded( i ), nRounds );

			fireButton[i].SetEnabled( true );
			fireButton[i].SetVisible( true );
			fireButton[i].SetText( buffer0 );
			fireButton[i].SetText2( buffer1 );

			if ( shooterUnit->CanFire(  i )) {
				// Reflect the TU left.
				float tuAfter = shooterUnit->TU() - tu;
				int tuIndicator = ICON_ORANGE_WALK_MARK;

				if ( tuAfter >= autoTU ) {
					tuIndicator = ICON_GREEN_WALK_MARK;
				}
				else if ( tuAfter >= snapTU ) {
					tuIndicator = ICON_YELLOW_WALK_MARK;
				}
				else if ( tuAfter < snapTU ) {
					tuIndicator = ICON_ORANGE_WALK_MARK;
				}
				fireButton[i].SetDeco( Game::CalcIconAtom( tuIndicator, true ), Game::CalcIconAtom( tuIndicator, false ) );
			}
			else {
				fireButton[i].SetEnabled( false );
				RenderAtom nullAtom;
				fireButton[i].SetDeco( nullAtom, nullAtom );
			}
			numButtons = i+1;
		}
	}
	else {
		fireButton[0].SetVisible( true );
		fireButton[0].SetEnabled( false );
		fireButton[0].SetText( "[none]" );
		fireButton[0].SetText2( "" );
		RenderAtom nullAtom;
		fireButton[0].SetDeco( nullAtom, nullAtom );
		numButtons = 1;
	}
	for( int i=numButtons; i<WeaponItemDef::MAX_MODE; ++i ) {
		fireButton[i].SetVisible( false );
	}

	Vector2F view, ui;
	const Screenport& port = battle->GetEngine()->GetScreenport();
	port.WorldToView( target, &view );
	port.ViewToUI( view, &ui );

	const int DX = 10;

	// Make sure it fits on the screen.
	UIRenderer::LayoutListOnScreen( fireButton, numButtons, sizeof(fireButton[0]), ui.x+DX, ui.y, FIRE_BUTTON_SPACING, port );

	ParticleSystem* ps = ParticleSystem::Instance();
	Game* game = battle->GetGame();
	Color4F color0 = Convert_4U8_4F( game->MainPaletteColor( 0, 5 ));
	Color4F color1 = Convert_4U8_4F( game->MainPaletteColor( 0, 4 ));

	const Model* model = battle->GetModel( shooterUnit );
	if ( model ) {
		Vector3F trigger;

		Vector2I t2 = { (int)target.x, (int)target.z };
		float fireRotation  = shooterUnit->AngleBetween( t2, false );
		model->CalcTrigger( &trigger, &fireRotation );

		Ray ray = { trigger, target-trigger };
		const Model* ignore[] = { model, battle->GetWeaponModel( shooterUnit ), 0 };
		Vector3F intersection;

		Model* m = battle->GetEngine()->IntersectModel( ray, TEST_TRI, 0, 0, ignore, &intersection );
		
		if ( !m || m == targetModel || m == targetWeapon ) {
			ps->EmitBeam( trigger, target, color0 );
		}
		else {
			ps->EmitBeam( trigger, intersection, color0 );
			ps->EmitBeam( intersection, target, color1 );
		}
	}
}
Beispiel #8
0
void ProcessAC3D( ACObject* ob, ModelBuilder* builder, const Matrix4& parent, const char* groupFilter )
{
    Matrix4 m, matrix;
    m.SetTranslation( ob->loc.x, ob->loc.y, ob->loc.z );

    MultMatrix4( parent, m, &matrix );
    builder->SetMatrix( matrix );

    const char* texname = ob->textureName;
    if ( texname ) {
        // Textures just use names, not paths.
        if ( strrchr( texname, '/' )) {
            texname = strrchr( texname, '/' )+1;
        }
    }

    builder->SetTexture( texname ? texname : "" );
    builder->PushObjectName( ob->name );

    Vertex vertex[16];
    memset(vertex, 0, sizeof(Vertex)* 16);

    for( int i = 0; i < ob->num_surf; ++i )
    {
        ACSurface *surf = &ob->surfaces[i];
        Vector3F normal = { surf->normal.x, surf->normal.y, surf->normal.z };
        if ( normal.Length() == 0.f ) {

            GLASSERT( 0 );
            normal.Set( 0.0f, 1.0f, 0.0f );
        }

        int st = surf->flags & 0xf;
        if ( st == SURFACE_TYPE_POLYGON && surf->num_vertref<16 )		// hopefully convex and simple
        {
            for( int j=0; j<surf->num_vertref; ++j )
            {
                ACVertex *v = &ob->vertices[surf->vertref[j]];
                float tx = 0, ty = 0;

                if (ob->texture )
                {
                    float tu = surf->uvs[j].u;
                    float tv = surf->uvs[j].v;

                    tx = ob->texture_offset_x + tu * ob->texture_repeat_x;
                    ty = ob->texture_offset_y + tv * ob->texture_repeat_y;
                }
                GLASSERT( j<16 );
                vertex[j].pos.Set( v->x, v->y, v->z );
                vertex[j].normal = normal;
                vertex[j].tex.Set( tx, ty );
            }
            int numTri = surf->num_vertref-2;
            for( int j=0; j<numTri; ++j ) {
                builder->AddTri( vertex[0], vertex[j+1], vertex[j+2] );
            }
        }
        else
        {
            GLOUTPUT(( "Input polygon or type not supported.\n" ));
            GLASSERT( 0 );
        }
    }
    for ( int n = 0; n < ob->num_kids; n++) {
        if ( groupFilter ) {
            // Sleazy trick to only look at the top node. Set to node
            // after we find the top.
            if ( StrEqual( ob->kids[n]->name, groupFilter ) )
                ProcessAC3D(ob->kids[n], builder, matrix, 0 );
        }
        else {
            ProcessAC3D(ob->kids[n], builder, matrix, 0 );
        }
    }
    builder->PopObjectName();
}