Ejemplo n.º 1
0
internal void
DrawRectangle(	game_offscreen_buffer *Buffer, 
				v2 vMin, v2 vMax,
				real32 R, real32 G, real32 B )
{	
	int32 MinX = RoundReal32ToInt32( vMin.X );
	int32 MinY = RoundReal32ToInt32( vMin.Y );
	int32 MaxX = RoundReal32ToInt32( vMax.X );
	int32 MaxY = RoundReal32ToInt32( vMax.Y );

	if( MinX < 0 ) MinX = 0;
	if( MinY < 0 ) MinY = 0;
	if ( MaxX > Buffer->Width ) MaxX = Buffer->Width;
	if ( MaxY > Buffer->Height ) MaxY = Buffer->Height;

	// BIT PATTERN: 0x AA RR GG BB
	uint32 Color =	(RoundReal32ToUInt32( R * 255.0f ) << 16) |
					(RoundReal32ToUInt32( G * 255.0f ) << 8 ) |
					 RoundReal32ToUInt32( B * 255.0f );

	// Starting pointer. Top-left of rectangle
	uint8 *Row = (uint8*)Buffer->Memory
		+ MinY * Buffer->Pitch
		+ MinX * Buffer->BytesPerPixel;

	for ( int Y = MinY; Y < MaxY; ++Y ) {	
		uint32 *Pixel = (uint32*)Row;
		for ( int X = MinX; X < MaxX; ++X ) {
			*Pixel++ = Color;
		}
		Row += Buffer->Pitch;
	}
}
Ejemplo n.º 2
0
inline void
RecanonicalizeCoord(tile_map *TileMap, uint32 *Tile, real32 *TileRel)
{
	
	int32 Offset = RoundReal32ToInt32(*TileRel / TileMap->TileSideInMeters);
	*Tile += Offset; 
	*TileRel -= (Offset)*TileMap->TileSideInMeters;
}
Ejemplo n.º 3
0
internal void
DrawRectangle(game_offscreen_buffer *Buffer, real32 RealMinX, real32 RealMinY,
              real32 RealMaxX, real32 RealMaxY, uint32 Color)
{
   int32 MinX = (int32)(RoundReal32ToInt32(RealMinX));
   int32 MinY = (int32)(RoundReal32ToInt32(RealMinY));
   int32 MaxX = (int32)(RoundReal32ToInt32(RealMaxX));
   int32 MaxY = (int32)(RoundReal32ToInt32(RealMaxY));

   if(MinX < 0)
   {
      MinX = 0;
   }
   if(MinY < 0)
   {
      MinY = 0;
   }
   if(MaxX > Buffer->Width)
   {
      MaxX = Buffer->Width;
   }
   if(MaxY > Buffer->Height)
   {
      MaxY = Buffer->Height;
   }

   uint8 *Row = ((uint8 *)Buffer->Memory + 
                   MinX * Buffer->BytesPerPixel + 
                   MinY * Buffer->Pitch);
   
   for(int Y = MinY;
       Y < MaxY;
       ++Y)
   {
      uint32 *Pixel = (uint32 *)Row;
      for(int X = MinX;
          X < MaxX;
          ++X)
      {
         *Pixel++ = Color;
      }
      Row += Buffer->Pitch;
   }

}
Ejemplo n.º 4
0
internal void
DrawRectangle(game_offscreen_buffer* Buffer, real32 RealMinX, real32 RealMinY, real32 Width, real32 Height, 
				real32 R, real32 G, real32 B)
{
	int32 MinX = RoundReal32ToInt32(RealMinX);
	int32 MinY = RoundReal32ToInt32(RealMinY);
	int32 MaxX = RoundReal32ToInt32(RealMinX+Width);
	int32 MaxY = RoundReal32ToInt32(RealMinY+Height);

//	int32 iR =(int32) R*255;
//	int32 iG =(int32) G*255;
//	int32 iB =(int32) B*255;

	if(MinX < 0)
	{
		MinX = 0;
	}
	if(MinY < 0)
	{
		MinY = 0;
	}
	if(MaxX > Buffer->Width)
	{
		MaxX =  Buffer->Width;
	}
	if(MaxY > Buffer->Height)
	{
		MaxY = Buffer->Height;
	}

	uint8* Row = ( (uint8*) Buffer->Memory  + MinX * Buffer->BytesPerPixel + 
											  MinY * Buffer->Pitch);
	for(int Y = MinY; Y<MaxY; ++Y)
	{
		uint32* Pixel = (uint32*)Row;
		for(int X = MinX; X<MaxX; ++X)
		{
			*Pixel++ = ((TruncateReal32ToInt32(R*255.f) << 16) |
					   (TruncateReal32ToInt32(G*255.f) << 8) 	|
					   (TruncateReal32ToInt32(B*255.f) << 0));
		}
		Row += Buffer->Pitch;
	}
}
Ejemplo n.º 5
0
inline
void RecanonicalizeCoord(TileMap* tileMap, uint32* tile, float* tileRel)
{
    int32 offset = RoundReal32ToInt32(*tileRel / tileMap->tileSideInMeters);
    *tile += static_cast<uint32>(offset);
    *tileRel -= offset * tileMap->tileSideInMeters;

    ASSERT(*tileRel >= -0.5f * tileMap->tileSideInMeters);
    ASSERT(*tileRel <= 0.5f * tileMap->tileSideInMeters);
}
Ejemplo n.º 6
0
internal void
DrawBitmap( game_offscreen_buffer *Buffer, loaded_bitmap *Bitmap, 
			real32 RealX, real32 RealY,	real32 CAlpha = 1.0f)
{
	int32 MinX = RoundReal32ToInt32( RealX );
	int32 MinY = RoundReal32ToInt32( RealY );
	int32 MaxX = MinX + Bitmap->Width;
	int32 MaxY = MinY + Bitmap->Height;

	int32 SourceOffsetX = 0;
	if ( MinX < 0 ) {
		SourceOffsetX = -MinX;
		MinX = 0;
	}
	int32 SourceOffsetY = 0;
	if ( MinY < 0 ) {
		SourceOffsetY = -MinY;
		MinY = 0;
	}
	if ( MaxX > Buffer->Width ) MaxX = Buffer->Width;
	if ( MaxY > Buffer->Height ) MaxY = Buffer->Height;

	uint32 *SourceRow = Bitmap->Pixels + Bitmap->Width * ( Bitmap->Height - 1 );
	SourceRow += -Bitmap->Width * SourceOffsetY + SourceOffsetX; // top and left clipping
	uint8 *DestRow = (uint8*)Buffer->Memory + 
					MinY * Buffer->Pitch +
					MinX * Buffer->BytesPerPixel;

	for ( int32 Y = MinY; Y < MaxY; ++Y )
	{
		uint32 *Source = SourceRow;
		uint32 *Dest = (uint32*)DestRow;
		for ( int32 X = MinX; X < MaxX; ++X )
		{
			real32 A = (real32)( ( *Source >> 24 ) & 0xFF ) / 255.0f;
			A *= CAlpha;

			real32 SR = (real32)( ( *Source >> 16 ) & 0xFF );
			real32 SG = (real32)( ( *Source >> 8 ) & 0xFF );
			real32 SB = (real32)( ( *Source >> 0 ) & 0xFF );

			real32 DR = (real32)( ( *Dest >> 16 ) & 0xFF );
			real32 DG = (real32)( ( *Dest >> 8 ) & 0xFF );
			real32 DB = (real32)( ( *Dest >> 0 ) & 0xFF );

			real32 R = ( 1.0f - A ) * DR + A * SR;
			real32 G = ( 1.0f - A ) * DG + A * SG;
			real32 B = ( 1.0f - A ) * DB + A * SB;

			// truncate
			*Dest = (((uint32)( R + 0.5f ) << 16 ) |
					 ((uint32)( G + 0.5f ) << 8  ) |
					 ((uint32)( B + 0.5f )) );
			
			++Dest;
			++Source;
		}

		SourceRow -= Bitmap->Width; // bottom to top
		DestRow += Buffer->Pitch;
	}

#if 0
	// Clear screen
	DrawRectangle( Buffer, 0.0f, 0.0f, (real32)Buffer->Width, (real32)Buffer->Height, 1.0f, 0.0f, 1.0f );
#endif
}
Ejemplo n.º 7
0
internal void MixSounds(SoundMixer *mixer, uint32 sampleFrequency, __m128 *realChannel0, __m128 *realChannel1, int32 sampleCount)
{
    i32 sampleCount4 = sampleCount / 4;
    
    // simd globals
    __m128 zero = _mm_set1_ps(0.0f);
    __m128 one  = _mm_set1_ps(1.0f);

    // get number of samples per second
    r32 secondsPerSample = 1.0f / (r32)sampleFrequency;
    
    // NOTE(Joey): clean channels with 0.0f before mixing
    for(int32 sampleIndex = 0; sampleIndex < sampleCount4; ++sampleIndex)
    {
        _mm_store_ps((float*)(realChannel0 + sampleIndex), zero);
        _mm_store_ps((float*)(realChannel1 + sampleIndex), zero);
    }
    
    // NOTE(Joey): loop over all playing sounds and mix into both real floating point channels
    for(PlayingSound **playingSoundPtr = &mixer->FirstPlayingSound;
        *playingSoundPtr;
        )
    {
        PlayingSound *playingSound = *playingSoundPtr;
        bool32 soundFinished = false;
        
        Sound* sound = playingSound->Source;
        if(sound)
        {            
            r32 volume0 = playingSound->CurrentVolume[0];
            r32 volume1 = playingSound->CurrentVolume[1];
            r32 dVolume0 = secondsPerSample*playingSound->dVolume[0];
            r32 dVolume1 = secondsPerSample*playingSound->dVolume[1];
            r32 dSample = playingSound->Pitch;
            
            __m128 *channel0 = realChannel0;
            __m128 *channel1 = realChannel1;            
            __m128 masterVolume4 = _mm_set1_ps(mixer->MasterVolume);
            __m128 volume4_0 = _mm_setr_ps(volume0 + 0.0f*dVolume0,
                                           volume0 + 1.0f*dVolume0,
                                           volume0 + 2.0f*dVolume0,
                                           volume0 + 3.0f*dVolume0);
            __m128 volume4_1 = _mm_setr_ps(volume1 + 0.0f*dVolume1,
                                           volume1 + 1.0f*dVolume1,
                                           volume1 + 2.0f*dVolume1,
                                           volume1 + 3.0f*dVolume1);
            __m128 dVolume4_0 = _mm_set1_ps(4.0f*dVolume0);
            __m128 dVolume4_1 = _mm_set1_ps(4.0f*dVolume1);
            
            Assert(playingSound->SamplesPlayed >= 0);
                        
            // NOTE(Joey): determine the maximum number of samples to mix this frame
            i32 nrSamplesToMix = sampleCount;
            // NOTE(Joey): deltaSampleRates can get negative (likely due to floating point precision)
            // this is accounted for in loop condition.
            i32 deltaSampleRates = (sound->SampleCount - RoundReal32ToInt32(playingSound->SamplesPlayed));
            r32 realSamplesRemainingInSound = (r32)deltaSampleRates / (1.0f*dSample);
            i32 samplesRemainingInSound = RoundReal32ToInt32(realSamplesRemainingInSound);
            if(!playingSound->Loop && samplesRemainingInSound <= (i32)nrSamplesToMix)
            {
                nrSamplesToMix = samplesRemainingInSound;
            }
            
            
            
            // NOTE(Joey): determine if we need to break out of the loop early due to volume
            // attenuation reaching 0.0f volume per channel.
            bool32 volumeEnded[2] = {};
            // TODO(Joey): make logic independent of nummer of channels
            // NOTE(Joey): could have a bug here where the volumeEnded (should) get triggered
            // for both volumes at the same time; which due to this logic will only work on one
            // volume item. I don't think this is a problem, but if so - this is likely it.
            if(dVolume0 != 0.0f)
            {
                r32 deltaVolume = playingSound->TargetVolume[0] - playingSound->CurrentVolume[0];
                i32 volumeSampleCount = (i32)((deltaVolume / (1.0f*dVolume0)) + 0.5f);
                if(volumeSampleCount <= nrSamplesToMix)
                {
                    nrSamplesToMix = volumeSampleCount;
                    volumeEnded[0] = true;
                }
            }
            if(dVolume1 != 0.0f)
            {
                r32 deltaVolume = playingSound->TargetVolume[1] - playingSound->CurrentVolume[1];
                i32 volumeSampleCount = (u32)((deltaVolume / (1.0f*dVolume1)) + 0.5f);
                if(volumeSampleCount <= nrSamplesToMix)
                {
                    nrSamplesToMix = volumeSampleCount;
                    volumeEnded[1] = true;
                }
            }
            
            // NOTE(Joey): we get into float precision issues; take expected begin/end sample 
            // position and set playingSound->SamplePosition to expected end sample position.
            // then get next sample position in the loop loop index and start sample position.
            r32 beginSamplePosition = playingSound->SamplesPlayed;
            r32 endSamplePosition = beginSamplePosition + nrSamplesToMix*dSample;
            r32 loopIndexC = (endSamplePosition - beginSamplePosition) / (r32)nrSamplesToMix;
            // r32 samplePosition = playingSound->SamplesPlayed;
            // NOTE(Joey): clamp nrSamplesToMix loop condition to SIMD width of 4
            for(i32 i = 0; i < nrSamplesToMix - (nrSamplesToMix & 3); i += 4)
            {                   
                r32 samplePosition = beginSamplePosition + loopIndexC*(r32)i;
#if 0 // linear filtering // NOTE(Joey): disabled for now as it doesn't seem to make an 'audible' difference
                __m128 samplePos = _mm_setr_ps(samplePosition + 0.0f*dSample,
                                               samplePosition + 1.0f*dSample,
                                               samplePosition + 2.0f*dSample,
                                               samplePosition + 3.0f*dSample);
                __m128i sampleIndex = _mm_cvttps_epi32(samplePos);
                __m128 frac = _mm_sub_ps(samplePos, _mm_cvtepi32_ps(sampleIndex));                     
                
                __m128 sampleValue0 = _mm_setr_ps(sound->Samples[0][((int32*)&sampleIndex)[0] % sound->SampleCount],
                                                  sound->Samples[0][((int32*)&sampleIndex)[1] % sound->SampleCount],
                                                  sound->Samples[0][((int32*)&sampleIndex)[2] % sound->SampleCount],
                                                  sound->Samples[0][((int32*)&sampleIndex)[3] % sound->SampleCount]);
                __m128 sampleValue1 = _mm_setr_ps(sound->Samples[0][(((int32*)&sampleIndex)[0] + 1) % sound->SampleCount],
                                                  sound->Samples[0][(((int32*)&sampleIndex)[1] + 1) % sound->SampleCount],
                                                  sound->Samples[0][(((int32*)&sampleIndex)[2] + 1) % sound->SampleCount],
                                                  sound->Samples[0][(((int32*)&sampleIndex)[3] + 1) % sound->SampleCount]);
                                                  
                __m128 sampleValue = _mm_add_ps(_mm_mul_ps(_mm_sub_ps(one, frac), sampleValue0), _mm_mul_ps(frac, sampleValue1));
#else // nearest-neighbor filtering
                __m128i sampleIndex = _mm_setr_epi32(RoundReal32ToInt32(samplePosition + 0.0f*dSample) % sound->SampleCount,
                                                     RoundReal32ToInt32(samplePosition + 1.0f*dSample) % sound->SampleCount,
                                                     RoundReal32ToInt32(samplePosition + 2.0f*dSample) % sound->SampleCount,
                                                     RoundReal32ToInt32(samplePosition + 3.0f*dSample) % sound->SampleCount);

                __m128 sampleValue = _mm_setr_ps(sound->Samples[0][((i32*)&sampleIndex)[0]],
                                                 sound->Samples[0][((i32*)&sampleIndex)[1]],
                                                 sound->Samples[0][((i32*)&sampleIndex)[2]],
                                                 sound->Samples[0][((i32*)&sampleIndex)[3]]);
#endif 
                
                // NOTE(Joey): write 4 SIMD wide 
                __m128 d0 = _mm_load_ps((float*)&channel0[0]);
                __m128 d1 = _mm_load_ps((float*)&channel1[0]); 
                
                d0 = _mm_add_ps(d0, _mm_mul_ps(_mm_mul_ps(masterVolume4, volume4_0), sampleValue));
                d1 = _mm_add_ps(d1, _mm_mul_ps(_mm_mul_ps(masterVolume4, volume4_1), sampleValue));
                                
                _mm_store_ps((float*)&channel0[0], d0);
                _mm_store_ps((float*)&channel1[0], d1);
                
                ++channel0;
                ++channel1;
              
                volume4_0 = _mm_add_ps(volume4_0, dVolume4_0);
                volume4_1 = _mm_add_ps(volume4_1, dVolume4_1);
                             
                // samplePosition += 4.0f*dSample;
            }
            
            // playingSound->SamplesPlayed = samplePosition;
            playingSound->SamplesPlayed = endSamplePosition;
            playingSound->CurrentVolume[0] = ((real32*)&volume4_0)[0];
            playingSound->CurrentVolume[1] = ((real32*)&volume4_1)[0];
            
            // NOTE(Joey): if volume 0.0f is reached due to attenuation, reset delta volume
            for(int32 i = 0; i < ArrayCount(volumeEnded); ++i)
            {
                if(volumeEnded[i])
                {
                    playingSound->CurrentVolume[i] = playingSound->TargetVolume[i];
                    playingSound->dVolume[i] = 0.0f;
                }
            }
            
            // if loop, re-position SamplesPlayed to start of sound sample0
            if(playingSound->Loop && playingSound->SamplesPlayed >= (r32)sound->SampleCount)
               playingSound->SamplesPlayed = playingSound->SamplesPlayed - (r32)sound->SampleCount;
          
            
            soundFinished = !playingSound->Loop && (uint32)playingSound->SamplesPlayed >= sound->SampleCount; 
            if(soundFinished)
                dSample = 0.0f;
        }
        else
        {
            // NOTE(Joey): Load sound here? or when retrieving from Asset manager; I'd say load sound when
            // not available in asset manager, much better path to take
        }
        
        if(soundFinished)
        {
            *playingSoundPtr = playingSound->Next;
            playingSound->Next = mixer->FirstFreePlayingSound;
            mixer->FirstFreePlayingSound = playingSound;
        }
        else
        {
            playingSoundPtr = &playingSound->Next;
        }
    }
}