Esempio n. 1
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;
	}
}
Esempio n. 2
0
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 );
		}
	}
}
Esempio n. 3
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;
}
Esempio n. 4
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();
}