void fhSimpleVert::SetColor(const idVec3& v) { SetColor(idVec4(v, 1.0f)); }
/* ================ DrawSolidConsole Draws the console with the solid background ================ */ void idConsoleLocal::DrawSolidConsole( float frac ) { int i, x; float y; int rows; short* text_p; int row; int lines; int currentColor; lines = idMath::Ftoi( SCREEN_HEIGHT * frac ); if( lines <= 0 ) { return; } if( lines > SCREEN_HEIGHT ) { lines = SCREEN_HEIGHT; } // draw the background y = frac * SCREEN_HEIGHT - 2; if( y < 1.0f ) { y = 0.0f; } else { renderSystem->DrawFilled( idVec4( 0.0f, 0.0f, 0.0f, 0.75f ), 0, 0, SCREEN_WIDTH, y ); } renderSystem->DrawFilled( colorCyan, 0, y, SCREEN_WIDTH, 2 ); // draw the version number renderSystem->SetColor( idStr::ColorForIndex( C_COLOR_CYAN ) ); idStr version = va( "%s.%i.%i", ENGINE_VERSION, BUILD_NUMBER, BUILD_NUMBER_MINOR ); i = version.Length(); for( x = 0; x < i; x++ ) { renderSystem->DrawSmallChar( LOCALSAFE_WIDTH - ( i - x ) * SMALLCHAR_WIDTH, ( lines - ( SMALLCHAR_HEIGHT + SMALLCHAR_HEIGHT / 4 ) ), version[x] ); } // draw the text vislines = lines; rows = ( lines - SMALLCHAR_WIDTH ) / SMALLCHAR_WIDTH; // rows of text to draw y = lines - ( SMALLCHAR_HEIGHT * 3 ); // draw from the bottom up if( display != current ) { // draw arrows to show the buffer is backscrolled renderSystem->SetColor( idStr::ColorForIndex( C_COLOR_CYAN ) ); for( x = 0; x < LINE_WIDTH; x += 4 ) { renderSystem->DrawSmallChar( LOCALSAFE_LEFT + ( x + 1 )*SMALLCHAR_WIDTH, idMath::Ftoi( y ), '^' ); } y -= SMALLCHAR_HEIGHT; rows--; } row = display; if( x == 0 ) { row--; } currentColor = idStr::ColorIndex( C_COLOR_WHITE ); renderSystem->SetColor( idStr::ColorForIndex( currentColor ) ); for( i = 0; i < rows; i++, y -= SMALLCHAR_HEIGHT, row-- ) { if( row < 0 ) { break; } if( current - row >= TOTAL_LINES ) { // past scrollback wrap point continue; } text_p = text + ( row % TOTAL_LINES ) * LINE_WIDTH; for( x = 0; x < LINE_WIDTH; x++ ) { if( ( text_p[x] & 0xff ) == ' ' ) { continue; } if( idStr::ColorIndex( text_p[x] >> 8 ) != currentColor ) { currentColor = idStr::ColorIndex( text_p[x] >> 8 ); renderSystem->SetColor( idStr::ColorForIndex( currentColor ) ); } renderSystem->DrawSmallChar( LOCALSAFE_LEFT + ( x + 1 )*SMALLCHAR_WIDTH, idMath::Ftoi( y ), text_p[x] & 0xff ); } } // draw the input prompt, user text, and cursor if desired DrawInput(); renderSystem->SetColor( colorCyan ); }
/* ======================== idSoundHardware_XAudio2::Update ======================== */ void idSoundHardware_XAudio2::Update() { if ( pXAudio2 == NULL ) { int nowTime = Sys_Milliseconds(); if ( lastResetTime + 1000 < nowTime ) { lastResetTime = nowTime; Init(); } return; } if ( soundSystem->IsMuted() ) { pMasterVoice->SetVolume( 0.0f, OPERATION_SET ); } else { pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ), OPERATION_SET ); } pXAudio2->CommitChanges( XAUDIO2_COMMIT_ALL ); // IXAudio2SourceVoice::Stop() has been called for every sound on the // zombie list, but it is documented as asyncronous, so we have to wait // until it actually reports that it is no longer playing. for ( int i = 0; i < zombieVoices.Num(); i++ ) { zombieVoices[i]->FlushSourceBuffers(); if ( !zombieVoices[i]->IsPlaying() ) { freeVoices.Append( zombieVoices[i] ); zombieVoices.RemoveIndexFast( i ); i--; } else { static int playingZombies; playingZombies++; } } if ( s_showPerfData.GetBool() ) { XAUDIO2_PERFORMANCE_DATA perfData; pXAudio2->GetPerformanceData( &perfData ); idLib::Printf( "Voices: %d/%d CPU: %.2f%% Mem: %dkb\n", perfData.ActiveSourceVoiceCount, perfData.TotalSourceVoiceCount, perfData.AudioCyclesSinceLastQuery / (float)perfData.TotalCyclesSinceLastQuery, perfData.MemoryUsageInBytes / 1024 ); } if ( vuMeterRMS == NULL ) { // Init probably hasn't been called yet return; } vuMeterRMS->Enable( s_showLevelMeter.GetBool() ); vuMeterPeak->Enable( s_showLevelMeter.GetBool() ); if ( !s_showLevelMeter.GetBool() ) { pMasterVoice->DisableEffect( 0 ); return; } else { pMasterVoice->EnableEffect( 0 ); } float peakLevels[ 8 ]; float rmsLevels[ 8 ]; XAUDIO2FX_VOLUMEMETER_LEVELS levels; levels.ChannelCount = outputChannels; levels.pPeakLevels = peakLevels; levels.pRMSLevels = rmsLevels; if ( levels.ChannelCount > 8 ) { levels.ChannelCount = 8; } pMasterVoice->GetEffectParameters( 0, &levels, sizeof( levels ) ); int currentTime = Sys_Milliseconds(); for ( int i = 0; i < outputChannels; i++ ) { if ( vuMeterPeakTimes[i] < currentTime ) { vuMeterPeak->SetValue( i, vuMeterPeak->GetValue( i ) * 0.9f, colorRed ); } } float width = 20.0f; float height = 200.0f; float left = 100.0f; float top = 100.0f; sscanf( s_meterPosition.GetString(), "%f %f %f %f", &left, &top, &width, &height ); vuMeterRMS->SetPosition( left, top, width * levels.ChannelCount, height ); vuMeterPeak->SetPosition( left, top, width * levels.ChannelCount, height ); for ( uint32 i = 0; i < levels.ChannelCount; i++ ) { vuMeterRMS->SetValue( i, rmsLevels[ i ], idVec4( 0.5f, 1.0f, 0.0f, 1.00f ) ); if ( peakLevels[ i ] >= vuMeterPeak->GetValue( i ) ) { vuMeterPeak->SetValue( i, peakLevels[ i ], colorRed ); vuMeterPeakTimes[i] = currentTime + s_meterTopTime.GetInteger(); } } }
void fhImmediateMode::Sphere(float radius, int rings, int sectors, bool inverse) { assert(!active); assert(radius > 0.0f); assert(rings > 1); assert(sectors > 1); float const R = 1. / (float)(rings - 1); float const S = 1. / (float)(sectors - 1); int vertexNum = 0; for (int r = 0; r < rings; r++) { for (int s = 0; s < sectors; s++) { float const y = sin(-(idMath::PI/2.0f) + idMath::PI * r * R); float const x = cos(2 * idMath::PI * s * S) * sin(idMath::PI * r * R); float const z = sin(2 * idMath::PI * s * S) * sin(idMath::PI * r * R); drawVerts[vertexNum].xyz.x = x * radius; drawVerts[vertexNum].xyz.y = y * radius; drawVerts[vertexNum].xyz.z = z * radius; drawVerts[vertexNum].st.x = s*S; drawVerts[vertexNum].st.y = r*R; drawVerts[vertexNum].color[0] = currentColor[0]; drawVerts[vertexNum].color[1] = currentColor[1]; drawVerts[vertexNum].color[2] = currentColor[2]; drawVerts[vertexNum].color[3] = currentColor[3]; vertexNum += 1; } } int indexNum = 0; for (int r = 0; r < rings - 1; r++) { for (int s = 0; s < sectors - 1; s++) { if(r == 0) { //faces of first ring are single triangles sphereIndices[indexNum + 2] = r * sectors + s; sphereIndices[indexNum + 1] = (r + 1) * sectors + s; sphereIndices[indexNum + 0] = (r + 1) * sectors + (s + 1); indexNum += 3; } else if (r == rings - 2) { //faces of last ring are single triangles sphereIndices[indexNum + 0] = r * sectors + s; sphereIndices[indexNum + 1] = r * sectors + (s + 1); sphereIndices[indexNum + 2] = (r + 1) * sectors + (s + 1); indexNum += 3; } else { //faces of remaining rings are quads (two triangles) sphereIndices[indexNum + 0] = r * sectors + s; sphereIndices[indexNum + 1] = r * sectors + (s + 1); sphereIndices[indexNum + 2] = (r + 1) * sectors + (s + 1); sphereIndices[indexNum + 3] = sphereIndices[indexNum + 2]; sphereIndices[indexNum + 4] = (r + 1) * sectors + s; sphereIndices[indexNum + 5] = sphereIndices[indexNum + 0]; indexNum += 6; } } } if(inverse) { for(int i = 0; i+2 < indexNum; i += 3) { unsigned short tmp = sphereIndices[i]; sphereIndices[i] = sphereIndices[i+2]; sphereIndices[i+2] = tmp; } } GL_UseProgram(vertexColorProgram); auto vert = vertexCache.AllocFrameTemp(drawVerts, vertexNum * sizeof(fhSimpleVert)); int offset = vertexCache.Bind(vert); fhRenderProgram::SetModelViewMatrix(GL_ModelViewMatrix.Top()); fhRenderProgram::SetProjectionMatrix(GL_ProjectionMatrix.Top()); fhRenderProgram::SetDiffuseColor(idVec4::one); fhRenderProgram::SetBumpMatrix(idVec4(1,0,0,0), idVec4(0,1,0,0)); GL_SetupVertexAttributes(fhVertexLayout::Simple, offset); glDrawElements(GL_TRIANGLES, indexNum, GL_UNSIGNED_SHORT, sphereIndices); GL_SetVertexLayout(fhVertexLayout::None); GL_UseProgram(nullptr); }
idSIMD::Shutdown(); // shut down the memory manager Mem_Shutdown(); } /* =============================================================================== Colors =============================================================================== */ idVec4 colorBlack = idVec4( 0.00f, 0.00f, 0.00f, 1.00f ); idVec4 colorWhite = idVec4( 1.00f, 1.00f, 1.00f, 1.00f ); idVec4 colorRed = idVec4( 1.00f, 0.00f, 0.00f, 1.00f ); idVec4 colorGreen = idVec4( 0.00f, 1.00f, 0.00f, 1.00f ); idVec4 colorBlue = idVec4( 0.00f, 0.00f, 1.00f, 1.00f ); idVec4 colorYellow = idVec4( 1.00f, 1.00f, 0.00f, 1.00f ); idVec4 colorMagenta= idVec4( 1.00f, 0.00f, 1.00f, 1.00f ); idVec4 colorCyan = idVec4( 0.00f, 1.00f, 1.00f, 1.00f ); idVec4 colorOrange = idVec4( 1.00f, 0.50f, 0.00f, 1.00f ); idVec4 colorPurple = idVec4( 0.60f, 0.00f, 0.60f, 1.00f ); idVec4 colorPink = idVec4( 0.73f, 0.40f, 0.48f, 1.00f ); idVec4 colorBrown = idVec4( 0.40f, 0.35f, 0.08f, 1.00f ); idVec4 colorLtGrey = idVec4( 0.75f, 0.75f, 0.75f, 1.00f ); idVec4 colorMdGrey = idVec4( 0.50f, 0.50f, 0.50f, 1.00f ); idVec4 colorDkGrey = idVec4( 0.25f, 0.25f, 0.25f, 1.00f );
/* ================= idPlayerView::Flash flashes the player view with the given color ================= */ void idPlayerView::Flash(idVec4 color, int time ) { Fade(idVec4(0, 0, 0, 0), time); fadeFromColor = colorWhite; }
polyhedron make_sv( const polyhedron &oc, idVec4 light ) { static polyhedron lut[64]; int index = 0; for( unsigned int i = 0; i < 6; i++ ) { if( ( oc.p[i].plane * light ) > 0 ) { index |= 1 << i; } } if( lut[index].e.size() == 0 ) { polyhedron &ph = lut[index]; ph = oc; int V = ph.v.size(); for( int j = 0; j < V; j++ ) { idVec3 proj = homogeneous_difference( light, ph.v[j] ); ph.v.push_back( idVec4( proj.x, proj.y, proj.z, 0 ) ); } ph.p.empty(); for( unsigned int i = 0; i < oc.p.size(); i++ ) { if( ( oc.p[i].plane * light ) > 0 ) { ph.p.push_back( oc.p[i] ); } } if( ph.p.size() == 0 ) { return ph = polyhedron(); } ph.compute_neighbors(); MyArrayPoly vpg; int I = ph.p.size(); for( int i = 0; i < I; i++ ) { MyArrayInt &vi = ph.p[i].vi; MyArrayInt &ni = ph.p[i].ni; int S = vi.size(); for( int j = 0; j < S; j++ ) { if( ni[j] == -1 ) { poly pg; int a = vi[( j + 1 ) % S]; int b = vi[j]; pg.vi = four_ints( a, b, b + V, a + V ); pg.ni = four_ints( -1, -1, -1, -1 ); vpg.push_back( pg ); } } } for( unsigned int i = 0; i < vpg.size(); i++ ) { ph.p.push_back( vpg[i] ); } ph.compute_neighbors(); ph.v.empty(); // no need to copy this data since it'll be replaced } polyhedron ph2 = lut[index]; // initalize vertices ph2.v = oc.v; int V = ph2.v.size(); for( int j = 0; j < V; j++ ) { idVec3 proj = homogeneous_difference( light, ph2.v[j] ); ph2.v.push_back( idVec4( proj.x, proj.y, proj.z, 0 ) ); } // need to compute planes for the shadow volume (sv) ph2.recompute_planes(); return ph2; }
/* ======================== idSoundWorldLocal::Update ======================== */ void idSoundWorldLocal::Update() { if ( s_noSound.GetBool() ) { return; } // ------------------ // Update emitters // // Only loop through the list once to avoid extra cache misses // ------------------ // The naming convention is weird here because we reuse the name "channel" // An idSoundChannel is a channel on an emitter, which may have an explicit channel assignment or SND_CHANNEL_ANY // A hardware channel is a channel from the sound file itself (IE: left, right, LFE) // We only allow MAX_HARDWARE_CHANNELS channels, which may wind up being a smaller number of idSoundChannels idStaticList< idActiveChannel, MAX_HARDWARE_VOICES > activeEmitterChannels; int maxEmitterChannels = s_maxEmitterChannels.GetInteger() + 1; // +1 to leave room for insert-before-sort if ( maxEmitterChannels > MAX_HARDWARE_VOICES ) { maxEmitterChannels = MAX_HARDWARE_VOICES; } int activeHardwareChannels = 0; int totalHardwareChannels = 0; int totalEmitterChannels = 0; int currentTime = GetSoundTime(); for ( int e = emitters.Num() - 1; e >= 0; e-- ) { // check for freeing a one-shot emitter that is finished playing if ( emitters[e]->CheckForCompletion( currentTime ) ) { // do a fast list collapse by swapping the last element into // the slot we are deleting emitters[e]->Reset(); emitterAllocator.Free( emitters[e] ); int lastEmitter = emitters.Num() - 1; if ( e != lastEmitter ) { emitters[e] = emitters[lastEmitter]; emitters[e]->index = e; } emitters.SetNum( lastEmitter ); continue; } emitters[e]->Update( currentTime ); totalEmitterChannels += emitters[e]->channels.Num(); // sort the active channels into the hardware list for ( int i = 0; i < emitters[e]->channels.Num(); i++ ) { idSoundChannel * channel = emitters[e]->channels[i]; // check if this channel contributes at all const bool canMute = channel->CanMute(); if ( canMute && channel->volumeDB <= DB_SILENCE ) { channel->Mute(); continue; } // Calculate the sort key. // VO can't be stopped and restarted accurately, so always keep VO channels by adding a large value to the sort key. const int sortKey = idMath::Ftoi( channel->volumeDB * 100.0f + ( canMute ? 0.0f : 100000.0f ) ); // Keep track of the total number of hardware channels. // This is done after calculating the sort key to avoid a load-hit-store that // would occur when using the sort key in the loop below after the Ftoi above. const int sampleChannels = channel->leadinSample->NumChannels(); totalHardwareChannels += sampleChannels; // Find the location to insert this channel based on the sort key. int insertIndex = 0; for ( insertIndex = 0; insertIndex < activeEmitterChannels.Num(); insertIndex++ ) { if ( sortKey > activeEmitterChannels[insertIndex].sortKey ) { break; } } // Only insert at the end if there is room. if ( insertIndex == activeEmitterChannels.Num() ) { // Always leave one spot free in the 'activeEmitterChannels' so there is room to insert sort a potentially louder sound later. if ( activeEmitterChannels.Num() + 1 >= activeEmitterChannels.Max() || activeHardwareChannels + sampleChannels > MAX_HARDWARE_CHANNELS ) { // We don't have enough voices to play this, so mute it if it was playing. channel->Mute(); continue; } } // We want to insert the sound at this point. activeEmitterChannels.Insert( idActiveChannel( channel, sortKey ), insertIndex ); activeHardwareChannels += sampleChannels; // If we are over our voice limit or at our channel limit, mute sounds until it fits. // If activeEmitterChannels is full, always remove the last one so there is room to insert sort a potentially louder sound later. while ( activeEmitterChannels.Num() == maxEmitterChannels || activeHardwareChannels > MAX_HARDWARE_CHANNELS ) { const int indexToRemove = activeEmitterChannels.Num() - 1; idSoundChannel * const channelToMute = activeEmitterChannels[ indexToRemove ].channel; channelToMute->Mute(); activeHardwareChannels -= channelToMute->leadinSample->NumChannels(); activeEmitterChannels.RemoveIndex( indexToRemove ); } } } const float secondsPerFrame = 1.0f / com_engineHz_latched; // ------------------ // In the very common case of having more sounds that would contribute to the // mix than there are available hardware voices, it can be an audible discontinuity // when a channel initially gets a voice or loses a voice. // To avoid this, make sure that the last few hardware voices are mixed with a volume // of zero, so they won't make a difference as they come and go. // It isn't obvious what the exact best volume ramping method should be, just that // it smoothly change frame to frame. // ------------------ const int uncushionedChannels = maxEmitterChannels - s_cushionFadeChannels.GetInteger(); currentCushionDB = AdjustForCushionChannels( activeEmitterChannels, uncushionedChannels, currentCushionDB, s_cushionFadeRate.GetFloat() * secondsPerFrame ); // ------------------ // Update Hardware // ------------------ shakeAmp = 0.0f; idStr showVoiceTable; bool showVoices = s_showVoices.GetBool(); if ( showVoices ) { showVoiceTable.Format( "currentCushionDB: %5.1f freeVoices: %i zombieVoices: %i buffers:%i/%i\n", currentCushionDB, soundSystemLocal.hardware.GetNumFreeVoices(), soundSystemLocal.hardware.GetNumZombieVoices(), soundSystemLocal.activeStreamBufferContexts.Num(), soundSystemLocal.freeStreamBufferContexts.Num() ); } for ( int i = 0; i < activeEmitterChannels.Num(); i++ ) { idSoundChannel * chan = activeEmitterChannels[i].channel; chan->UpdateHardware( 0.0f, currentTime ); if ( showVoices ) { idStr voiceLine; voiceLine.Format( "%5.1f db [%3i:%2i] %s", chan->volumeDB, chan->emitter->index, chan->logicalChannel, chan->CanMute() ? "" : " <CANT MUTE>\n" ); idSoundSample * leadinSample = chan->leadinSample; idSoundSample * loopingSample = chan->loopingSample; if ( loopingSample == NULL ) { voiceLine.Append( va( "%ikhz*%i %s\n", leadinSample->SampleRate()/1000, leadinSample->NumChannels(), leadinSample->GetName() ) ); } else if ( loopingSample == leadinSample ) { voiceLine.Append( va( "%ikhz*%i <LOOPING> %s\n", leadinSample->SampleRate()/1000, leadinSample->NumChannels(), leadinSample->GetName() ) ); } else { voiceLine.Append( va( "%ikhz*%i %s | %ikhz*%i %s\n", leadinSample->SampleRate()/1000, leadinSample->NumChannels(), leadinSample->GetName(), loopingSample->SampleRate()/1000, loopingSample->NumChannels(), loopingSample->GetName() ) ); } showVoiceTable += voiceLine; } // Calculate shakes if ( chan->hardwareVoice == NULL ) { continue; } shakeAmp += chan->parms.shakes * chan->hardwareVoice->GetGain() * chan->currentAmplitude; } if ( showVoices ) { static idOverlayHandle handle; console->PrintOverlay( handle, JUSTIFY_LEFT, showVoiceTable.c_str() ); } if ( s_drawSounds.GetBool() && renderWorld != NULL ) { for ( int e = 0; e < emitters.Num(); e++ ) { idSoundEmitterLocal * emitter = emitters[e]; bool audible = false; float maxGain = 0.0f; for ( int c = 0; c < emitter->channels.Num(); c++ ) { if ( emitter->channels[c]->hardwareVoice != NULL ) { audible = true; maxGain = Max( maxGain, emitter->channels[c]->hardwareVoice->GetGain() ); } } if ( !audible ) { continue; } static const int lifetime = 20; idBounds ref; ref.Clear(); ref.AddPoint( idVec3( -10.0f ) ); ref.AddPoint( idVec3( 10.0f ) ); // draw a box renderWorld->DebugBounds( idVec4( maxGain, maxGain, 1.0f, 1.0f ), ref, emitter->origin, lifetime ); if ( emitter->origin != emitter->spatializedOrigin ) { renderWorld->DebugLine( idVec4( 1.0f, 0.0f, 0.0f, 1.0f ), emitter->origin, emitter->spatializedOrigin, lifetime ); } // draw the index idVec3 textPos = emitter->origin; textPos.z -= 8; renderWorld->DrawText( va("%i", e), textPos, 0.1f, idVec4(1,0,0,1), listener.axis, 1, lifetime ); textPos.z += 8; // run through all the channels for ( int k = 0; k < emitter->channels.Num(); k++ ) { idSoundChannel * chan = emitter->channels[k]; float min = chan->parms.minDistance; float max = chan->parms.maxDistance; const char * defaulted = chan->leadinSample->IsDefault() ? " *DEFAULTED*" : ""; idStr text; text.Format( "%s (%i %i/%i)%s", chan->soundShader->GetName(), idMath::Ftoi( emitter->spatializedDistance ), idMath::Ftoi( min ), idMath::Ftoi( max ), defaulted ); renderWorld->DrawText( text, textPos, 0.1f, idVec4(1,0,0,1), listener.axis, 1, lifetime ); textPos.z += 8; } } } }
/* ============== sdDeployMenu::Update ============== */ void sdDeployMenu::Update( void ) { sdHudModule::Update(); idPlayer* localPlayer = gameLocal.GetLocalPlayer(); if ( !deployableObject || !localPlayer ) { return; } deployResult_t result = localPlayer->GetDeployResult( position, deployableObject ); if ( result != DR_OUT_OF_RANGE ) { if ( deployableRenderEntityHandle < 0 ) { deployableRenderEntityHandle = gameRenderWorld->AddEntityDef( &deployableRenderEntity ); } idVec4 color; switch ( deployableState ) { case DR_CLEAR: color = colorGreen; break; case DR_WARNING: color = colorOrange; break; case DR_CONDITION_FAILED: color = colorWhite; break; default: case DR_FAILED: color = colorDkRed; break; } if ( decalHandle == -1 ) { decalHandle = gameLocal.RegisterLoggedDecal( decalMaterial ); lastExpandedExtents.minx = -1; } if ( decalHandleOuter == -1 ) { decalHandleOuter = gameLocal.RegisterLoggedDecal( decalMaterialOuter ); lastExpandedExtents.minx = -1; } if ( decalHandleArrows == -1 ) { decalHandleArrows = gameLocal.RegisterLoggedDecal( decalMaterialArrows ); } gameLocal.ResetLoggedDecal( decalHandleArrows ); gameDecalInfo_t* decalInfo = gameLocal.GetLoggedDecal( decalHandle ); gameDecalInfo_t* decalInfoOuter = gameLocal.GetLoggedDecal( decalHandleOuter ); gameDecalInfo_t* decalInfoArrows = gameLocal.GetLoggedDecal( decalHandleArrows ); if ( !deployableObject->AllowRotation() ) { rotation = 0.0f; } idMat3 rotationStart; idAngles::YawToMat3( rotation, rotationStart ); const sdPlayZone* playZone = gameLocal.GetPlayZone( position, sdPlayZone::PZF_DEPLOYMENT ); const sdPlayZone* playZoneHeight = gameLocal.GetPlayZone( position, sdPlayZone::PZF_HEIGHTMAP ); const sdHeightMapInstance* heightMap = NULL; if ( playZoneHeight ) { heightMap = &playZoneHeight->GetHeightMap(); } const sdDeployMaskInstance* mask = NULL; if ( playZone ) { mask = playZone->GetMask( deployableObject->GetDeploymentMask() ); } if ( mask && mask->IsValid() && heightMap && heightMap->IsValid() ) { idBounds bounds( position ); bounds.ExpandSelf( deployableObject->GetObjectSize() ); sdDeployMask::extents_t extents; mask->CoordsForBounds( bounds, extents ); idBounds mainBounds; mask->GetBounds( extents, mainBounds, heightMap ); float depth = 512.0f; idVec3 top; idBounds moveArrowBounds = mainBounds; idBounds rotateArrowBounds = mainBounds; // straight arrows moveArrowBounds.GetMaxs().y = moveArrowBounds.GetCenter().y; moveArrowBounds.GetMins().y += 0.25f * ( mainBounds.GetMaxs().y - mainBounds.GetMins().y ); moveArrowBounds.GetMaxs().y += 0.25f * ( mainBounds.GetMaxs().y - mainBounds.GetMins().y ); moveArrowBounds.GetMins().x = moveArrowBounds.GetCenter().x; { idVec3 center = moveArrowBounds.GetCenter(); moveArrowBounds.TranslateSelf( -center ); for ( int index = 0; index < 3; index++ ) { moveArrowBounds.GetMins()[ index ] *= 0.25f; moveArrowBounds.GetMaxs()[ index ] *= 0.25f; } moveArrowBounds.TranslateSelf( center ); } // rotate arrows rotateArrowBounds.GetMins().x = rotateArrowBounds.GetCenter().x; { idVec3 center = rotateArrowBounds.GetCenter(); rotateArrowBounds.TranslateSelf( -center ); for ( int index = 0; index < 3; index++ ) { rotateArrowBounds.GetMins()[ index ] *= 0.2f; rotateArrowBounds.GetMaxs()[ index ] *= 0.2f; } rotateArrowBounds.TranslateSelf( center ); } top = mainBounds.GetCenter(); top[ 2 ] = mainBounds.GetMaxs()[ 2 ]; idList< const idMaterial* > megaTextureMaterials; const idStrList& megaTextureMaterialNames = gameLocal.GetMapInfo().GetMegatextureMaterials(); for ( int i = 0; i < megaTextureMaterialNames.Num(); i++ ) { megaTextureMaterials.Append( declHolder.FindMaterial( megaTextureMaterialNames[ i ] ) ); } idFixedWinding winding; int spawnID = WORLD_SPAWN_ID; if ( GetDeployMode() ) { // rotate mode idMat3 rotationOffset; idAngles::YawToMat3( 120.0f, rotationOffset ); // forward arrow winding += idVec5( idVec3( moveArrowBounds.GetMins().x, moveArrowBounds.GetMins().y, moveArrowBounds.GetMins().z - depth ), idVec2( 0.5f, 0.0f ) ); winding += idVec5( idVec3( moveArrowBounds.GetMins().x, moveArrowBounds.GetMaxs().y, moveArrowBounds.GetMins().z - depth ), idVec2( 0.5f, 0.5f ) ); winding += idVec5( idVec3( moveArrowBounds.GetMaxs().x, moveArrowBounds.GetMaxs().y, moveArrowBounds.GetMins().z - depth ), idVec2( 1.0f, 0.5f ) ); winding += idVec5( idVec3( moveArrowBounds.GetMaxs().x, moveArrowBounds.GetMins().y, moveArrowBounds.GetMins().z - depth ), idVec2( 1.0f, 0.0f ) ); winding.Rotate( mainBounds.GetCenter(), rotationStart ); idVec3 offset = rotationStart[ 0 ] * ( 16.f * idMath::Sin( ( gameLocal.time / 500.f ) ) ); for ( int i = 0; i < winding.GetNumPoints(); i++ ) { winding[ i ].ToVec3() += offset; } gameRenderWorld->AddToProjectedDecal( winding, top + idVec3( 0.0f, 0.0f, 64.0f + depth ), true, idVec4( 0.87f, 0.59f, 0.f, 1.f ), decalInfoArrows->renderEntity.hModel, spawnID, megaTextureMaterials.Begin(), megaTextureMaterials.Num() ); // rotate arrows winding.Clear(); winding += idVec5( idVec3( rotateArrowBounds.GetMins().x, rotateArrowBounds.GetMins().y, rotateArrowBounds.GetMins().z - depth ), idVec2( 0.0f, 0.0f ) ); winding += idVec5( idVec3( rotateArrowBounds.GetMins().x, rotateArrowBounds.GetMaxs().y, rotateArrowBounds.GetMins().z - depth ), idVec2( 0.0f, 1.0f ) ); winding += idVec5( idVec3( rotateArrowBounds.GetMaxs().x, rotateArrowBounds.GetMaxs().y, rotateArrowBounds.GetMins().z - depth ), idVec2( 0.5f, 1.0f ) ); winding += idVec5( idVec3( rotateArrowBounds.GetMaxs().x, rotateArrowBounds.GetMins().y, rotateArrowBounds.GetMins().z - depth ), idVec2( 0.5f, 0.0f ) ); winding.Rotate( mainBounds.GetCenter(), rotationStart * rotationOffset ); gameRenderWorld->AddToProjectedDecal( winding, top + idVec3( 0.0f, 0.0f, 64.0f + depth ), true, colorWhite, decalInfoArrows->renderEntity.hModel, spawnID, megaTextureMaterials.Begin(), megaTextureMaterials.Num() ); winding.Rotate( mainBounds.GetCenter(), rotationOffset ); gameRenderWorld->AddToProjectedDecal( winding, top + idVec3( 0.0f, 0.0f, 64.0f + depth ), true, colorWhite, decalInfoArrows->renderEntity.hModel, spawnID, megaTextureMaterials.Begin(), megaTextureMaterials.Num() ); } else { // move mode idMat3 rotationOffset; idAngles::YawToMat3( 90.0f, rotationOffset ); winding += idVec5( idVec3( moveArrowBounds.GetMins().x, moveArrowBounds.GetMins().y, moveArrowBounds.GetMins().z - depth ), idVec2( 0.5f, 0.0f ) ); winding += idVec5( idVec3( moveArrowBounds.GetMins().x, moveArrowBounds.GetMaxs().y, moveArrowBounds.GetMins().z - depth ), idVec2( 0.5f, 0.5f ) ); winding += idVec5( idVec3( moveArrowBounds.GetMaxs().x, moveArrowBounds.GetMaxs().y, moveArrowBounds.GetMins().z - depth ), idVec2( 1.0f, 0.5f ) ); winding += idVec5( idVec3( moveArrowBounds.GetMaxs().x, moveArrowBounds.GetMins().y, moveArrowBounds.GetMins().z - depth ), idVec2( 1.0f, 0.0f ) ); gameRenderWorld->AddToProjectedDecal( winding, top + idVec3( 0.0f, 0.0f, 64.0f + depth ), true, colorWhite, decalInfoArrows->renderEntity.hModel, spawnID, megaTextureMaterials.Begin(), megaTextureMaterials.Num() ); winding.Rotate( mainBounds.GetCenter(), rotationOffset ); gameRenderWorld->AddToProjectedDecal( winding, top + idVec3( 0.0f, 0.0f, 64.0f + depth ), true, colorWhite, decalInfoArrows->renderEntity.hModel, spawnID, megaTextureMaterials.Begin(), megaTextureMaterials.Num() ); winding.Rotate( mainBounds.GetCenter(), rotationOffset ); gameRenderWorld->AddToProjectedDecal( winding, top + idVec3( 0.0f, 0.0f, 64.0f + depth ), true, colorWhite, decalInfoArrows->renderEntity.hModel, spawnID, megaTextureMaterials.Begin(), megaTextureMaterials.Num() ); winding.Rotate( mainBounds.GetCenter(), rotationOffset ); gameRenderWorld->AddToProjectedDecal( winding, top + idVec3( 0.0f, 0.0f, 64.0f + depth ), true, colorWhite, decalInfoArrows->renderEntity.hModel, spawnID, megaTextureMaterials.Begin(), megaTextureMaterials.Num() ); } // the grid int maxX, maxY; mask->GetDimensions( maxX, maxY ); sdDeployMask::extents_t expandedExtents; expandedExtents.minx = Max( 0, extents.minx - 2 ); expandedExtents.miny = Max( 0, extents.miny - 2 ); expandedExtents.maxx = Min( maxX, extents.maxx + 2 ); expandedExtents.maxy = Min( maxY, extents.maxy + 2 ); int w = expandedExtents.maxx - expandedExtents.minx + 1; int h = expandedExtents.maxx - expandedExtents.minx + 1; int terrIdx = 0; bool regen = false; if ( ( w * h ) > sizeof( lastTerritory ) / sizeof( lastTerritory[0] ) ) { common->Warning( "test territory size too large" ); return; } for ( int i = expandedExtents.minx; i <= expandedExtents.maxx; i++ ) { for ( int j = expandedExtents.miny; j <= expandedExtents.maxy; j++ ) { gameDecalInfo_t* info = ( ( i >= extents.minx ) && ( i <= extents.maxx ) && ( j >= extents.miny ) && ( j <= extents.maxy ) ) ? decalInfo : decalInfoOuter; if ( !info ) { continue; } sdDeployMask::extents_t localExtents; localExtents.minx = i; localExtents.maxx = i; localExtents.miny = j; localExtents.maxy = j; mask->GetBounds( localExtents, bounds, heightMap ); top = bounds.GetCenter(); top[ 2 ] = bounds.GetMaxs()[ 2 ]; deployResult_t localResult = localPlayer->CheckBoundsForDeployment( localExtents, *mask, deployableObject, playZoneHeight ); bool hasTerritory; if ( localResult == DR_CLEAR ) { hasTerritory = gameLocal.TerritoryForPoint( top, localPlayer->GetGameTeam(), true ) != NULL; } else { hasTerritory = false; } if ( hasTerritory != lastTerritory[ terrIdx ] ) { regen = true; } lastTerritory[ terrIdx++ ] = hasTerritory; } } if ( expandedExtents.minx != lastExpandedExtents.minx || expandedExtents.maxx != lastExpandedExtents.maxx || expandedExtents.miny != lastExpandedExtents.miny || expandedExtents.maxy != lastExpandedExtents.maxy || regen ) { gameLocal.ResetLoggedDecal( decalHandle ); gameLocal.ResetLoggedDecal( decalHandleOuter ); lastExpandedExtents = expandedExtents; terrIdx = 0; for ( int i = expandedExtents.minx; i <= expandedExtents.maxx; i++ ) { for ( int j = expandedExtents.miny; j <= expandedExtents.maxy; j++ ) { gameDecalInfo_t* info = ( ( i >= extents.minx ) && ( i <= extents.maxx ) && ( j >= extents.miny ) && ( j <= extents.maxy ) ) ? decalInfo : decalInfoOuter; if ( !info ) { continue; } sdDeployMask::extents_t localExtents; localExtents.minx = i; localExtents.maxx = i; localExtents.miny = j; localExtents.maxy = j; mask->GetBounds( localExtents, bounds, heightMap ); top = bounds.GetCenter(); top[ 2 ] = bounds.GetMaxs()[ 2 ]; //bool hasTerritory = gameLocal.TerritoryForPoint( top, localPlayer->GetGameTeam(), true ) != NULL; deployResult_t localResult = localPlayer->CheckBoundsForDeployment( localExtents, *mask, deployableObject, playZoneHeight ); idVec4 localColor; switch ( localResult ) { case DR_CLEAR: if ( !lastTerritory[ terrIdx ] ) { localColor = colorOrange; } else { localColor = colorGreen; } break; case DR_WARNING: localColor = colorOrange; break; case DR_FAILED: localColor = colorDkRed; break; } winding.Clear(); winding += idVec5( idVec3( bounds.GetMins()[ 0 ], bounds.GetMins()[ 1 ], bounds.GetMins()[ 2 ] - depth ), idVec2( 0.0f, 0.0f ) ); winding += idVec5( idVec3( bounds.GetMins()[ 0 ], bounds.GetMaxs()[ 1 ], bounds.GetMins()[ 2 ] - depth ), idVec2( 0.0f, 1.0f ) ); winding += idVec5( idVec3( bounds.GetMaxs()[ 0 ], bounds.GetMaxs()[ 1 ], bounds.GetMins()[ 2 ] - depth ), idVec2( 1.0f, 1.0f ) ); winding += idVec5( idVec3( bounds.GetMaxs()[ 0 ], bounds.GetMins()[ 1 ], bounds.GetMins()[ 2 ] - depth ), idVec2( 1.0f, 0.0f ) ); // gameRenderWorld->DebugBounds( localColor, bounds ); // gameRenderWorld->DrawText( va( "%i %i", i, j ), top, 0.5, colorWhite, gameLocal.GetLocalPlayer()->GetRenderView()->viewaxis ); gameRenderWorld->AddToProjectedDecal( winding, top + idVec3( 0, 0, 64.f + depth ), true, localColor, info->renderEntity.hModel, spawnID, megaTextureMaterials.Begin(), megaTextureMaterials.Num() ); terrIdx++; } } } } else { gameLocal.ResetLoggedDecal( decalHandle ); gameLocal.ResetLoggedDecal( decalHandleOuter ); lastExpandedExtents.minx = -1; } idVec3 modelPos = position; if ( playZoneHeight ) { const sdHeightMapInstance& heightMap = playZoneHeight->GetHeightMap(); if ( heightMap.IsValid() ) { modelPos.z = heightMap.GetHeight( modelPos ); } } sdDeployRequest::UpdateRenderEntity( deployableRenderEntity, color, modelPos ); deployableRenderEntity.axis = rotationStart; gameRenderWorld->UpdateEntityDef( deployableRenderEntityHandle, &deployableRenderEntity ); } else { if ( deployableRenderEntityHandle >= 0 ) { gameRenderWorld->FreeEntityDef( deployableRenderEntityHandle ); deployableRenderEntityHandle = -1; } FreeDecals(); } }
// make a unit cube polyhedron PolyhedronFromBounds( const idBounds &b ) { // 3----------2 // |\ /| // | \ / | // | 7--6 | // | | | | // | 4--5 | // | / \ | // | / \ | // 0----------1 static polyhedron p; if( p.e.size() == 0 ) { p.v.push_back( idVec4( -1, -1, 1, 1 ) ); p.v.push_back( idVec4( 1, -1, 1, 1 ) ); p.v.push_back( idVec4( 1, 1, 1, 1 ) ); p.v.push_back( idVec4( -1, 1, 1, 1 ) ); p.v.push_back( idVec4( -1, -1, -1, 1 ) ); p.v.push_back( idVec4( 1, -1, -1, 1 ) ); p.v.push_back( idVec4( 1, 1, -1, 1 ) ); p.v.push_back( idVec4( -1, 1, -1, 1 ) ); p.add_quad( 0, 1, 2, 3 ); p.add_quad( 7, 6, 5, 4 ); p.add_quad( 1, 0, 4, 5 ); p.add_quad( 2, 1, 5, 6 ); p.add_quad( 3, 2, 6, 7 ); p.add_quad( 0, 3, 7, 4 ); p.compute_neighbors(); p.recompute_planes(); p.v.empty(); // no need to copy this data since it'll be replaced } polyhedron p2( p ); const idVec3 &min = b[0]; const idVec3 &max = b[1]; p2.v.empty(); p2.v.push_back( idVec4( min.x, min.y, max.z, 1 ) ); p2.v.push_back( idVec4( max.x, min.y, max.z, 1 ) ); p2.v.push_back( idVec4( max.x, max.y, max.z, 1 ) ); p2.v.push_back( idVec4( min.x, max.y, max.z, 1 ) ); p2.v.push_back( idVec4( min.x, min.y, min.z, 1 ) ); p2.v.push_back( idVec4( max.x, min.y, min.z, 1 ) ); p2.v.push_back( idVec4( max.x, max.y, min.z, 1 ) ); p2.v.push_back( idVec4( min.x, max.y, min.z, 1 ) ); p2.recompute_planes(); return p2; }
/* ============= idRenderSystemLocal::DrawStretchPic ============= */ void idRenderSystemLocal::DrawStretchPic( float x, float y, float w, float h, float s1, float t1, float s2, float t2, const idMaterial* material ) { DrawStretchPic( idVec4( x, y, s1, t1 ), idVec4( x + w, y, s2, t1 ), idVec4( x + w, y + h, s2, t2 ), idVec4( x, y + h, s1, t2 ), material ); }
#include "idlib/Heap.h" #include "framework/Common.h" #include "idlib/Str.h" #if !defined( ID_REDIRECT_NEWDELETE ) && !defined( MACOS_X ) #define USE_STRING_DATA_ALLOCATOR #endif #ifdef USE_STRING_DATA_ALLOCATOR static idDynamicBlockAlloc<char, 1<<18, 128> stringDataAllocator; #endif idVec4 g_color_table[16] = { idVec4(0.0f, 0.0f, 0.0f, 1.0f), idVec4(1.0f, 0.0f, 0.0f, 1.0f), // S_COLOR_RED idVec4(0.0f, 1.0f, 0.0f, 1.0f), // S_COLOR_GREEN idVec4(1.0f, 1.0f, 0.0f, 1.0f), // S_COLOR_YELLOW idVec4(0.0f, 0.0f, 1.0f, 1.0f), // S_COLOR_BLUE idVec4(0.0f, 1.0f, 1.0f, 1.0f), // S_COLOR_CYAN idVec4(1.0f, 0.0f, 1.0f, 1.0f), // S_COLOR_MAGENTA idVec4(1.0f, 1.0f, 1.0f, 1.0f), // S_COLOR_WHITE idVec4(0.5f, 0.5f, 0.5f, 1.0f), // S_COLOR_GRAY idVec4(0.0f, 0.0f, 0.0f, 1.0f), // S_COLOR_BLACK idVec4(0.0f, 0.0f, 0.0f, 1.0f), idVec4(0.0f, 0.0f, 0.0f, 1.0f), idVec4(0.0f, 0.0f, 0.0f, 1.0f), idVec4(0.0f, 0.0f, 0.0f, 1.0f), idVec4(0.0f, 0.0f, 0.0f, 1.0f), idVec4(0.0f, 0.0f, 0.0f, 1.0f),
void idWorldManager::Think( void ) { int i; UpdateRecord(); for (i = 0; i < 3; i++) { idVec4 markerColor; idVec3 markerPos; int markerRadius = 24; if (records[i].playing) { UpdatePlay(i); } else { continue; } if (state == OFF && index != -1 /*caser*/) { continue; } if (this->index == i) { continue; } if (!records[i].ghost->IsHidden()) { if ((int)(gameLocal.time * 0.004) % 3 == 0) { markerRadius = 12; } switch (i) { case 0: markerColor = idVec4(.25, .75, 1, 1); break; //blue. case 1: markerColor = idVec4(.74, .9, .26, 1); break; //green. default: markerColor = idVec4(1, .6, 0, 1); break; //orange. } //blue .25, .75, 1 //yellow 1, .8, 0, 1 //red .9, .25, .25 markerPos = records[i].ghost->GetPhysics()->GetOrigin() + idVec3(0,0,85); gameRenderWorld->DebugLine( markerColor, markerPos + idVec3(0,0,-markerRadius), markerPos + idVec3(0,0,markerRadius) ); gameRenderWorld->DebugLine( markerColor, markerPos + idVec3(0,-markerRadius,0), markerPos + idVec3(0,markerRadius,0) ); gameRenderWorld->DebugLine( markerColor, markerPos + idVec3(-markerRadius,0,0), markerPos + idVec3(markerRadius,0,0) ); if (index == -1) { //draw lines. int k; if (recordlines[i].lines.Num() >= 3) { for (k = 0; k < recordlines[i].lines.Num() - 1; k++) { if (k > 2) //BC hack. The initial lines are garbage data. So, just skip them. { gameRenderWorld->DebugLine( markerColor, recordlines[i].lines[k].position1, recordlines[i].lines[k].position2 ); } } //This is the dangly bit that connects the last recordline position to the character model's feet. if (records[i].index < recordlines[i].lines.Num() && i > 1) { gameRenderWorld->DebugLine( markerColor, recordlines[i].lines[records[i].index].position1, records[i].ghost->GetPhysics()->GetOrigin() ); } } } } } }
void idListWindow::Draw(int time, float x, float y) { idVec4 color; idStr work; int count = listItems.Num(); idRectangle rect = textRect; float scale = textScale; float lineHeight = GetMaxCharHeight(); float bottom = textRect.Bottom(); float width = textRect.w; if ( scroller->GetHigh() > 0.0f ) { if ( horizontal ) { bottom -= sizeBias; } else { width -= sizeBias; rect.w = width; } } if ( noEvents || !Contains(gui->CursorX(), gui->CursorY()) ) { hover = false; } for (int i = top; i < count; i++) { if ( IsSelected( i ) ) { rect.h = lineHeight; dc->DrawFilledRect(rect.x, rect.y + pixelOffset, rect.w, rect.h, borderColor); if ( flags & WIN_FOCUS ) { idVec4 color = borderColor; color.w = 1.0f; dc->DrawRect(rect.x, rect.y + pixelOffset, rect.w, rect.h, 1.0f, color ); } } rect.y ++; rect.h = lineHeight - 1; if ( hover && !noEvents && Contains(rect, gui->CursorX(), gui->CursorY()) ) { color = hoverColor; } else { color = foreColor; } rect.h = lineHeight + pixelOffset; rect.y --; if ( tabInfo.Num() > 0 ) { int start = 0; int tab = 0; int stop = listItems[i].Find('\t', 0); while ( start < listItems[i].Length() ) { if ( tab >= tabInfo.Num() ) { common->Warning( "idListWindow::Draw: gui '%s' window '%s' tabInfo.Num() exceeded", gui->GetSourceFile(), name.c_str() ); break; } listItems[i].Mid(start, stop - start, work); rect.x = textRect.x + tabInfo[tab].x; rect.w = (tabInfo[tab].w == -1) ? width - tabInfo[tab].x : tabInfo[tab].w; dc->PushClipRect( rect ); if ( tabInfo[tab].type == TAB_TYPE_TEXT ) { dc->DrawText(work, scale, tabInfo[tab].align, color, rect, false, -1); } else if (tabInfo[tab].type == TAB_TYPE_ICON) { const idMaterial **hashMat; const idMaterial *iconMat; // leaving the icon name empty doesn't draw anything if ( work[0] != '\0' ) { if ( iconMaterials.Get(work, &hashMat) == false ) { iconMat = declManager->FindMaterial("_default"); } else { iconMat = *hashMat; } idRectangle iconRect; iconRect.w = tabInfo[tab].iconSize.x; iconRect.h = tabInfo[tab].iconSize.y; if(tabInfo[tab].align == idDeviceContext::ALIGN_LEFT) { iconRect.x = rect.x; } else if (tabInfo[tab].align == idDeviceContext::ALIGN_CENTER) { iconRect.x = rect.x + rect.w/2.0f - iconRect.w/2.0f; } else if (tabInfo[tab].align == idDeviceContext::ALIGN_RIGHT) { iconRect.x = rect.x + rect.w - iconRect.w; } if(tabInfo[tab].valign == 0) { //Top iconRect.y = rect.y + tabInfo[tab].iconVOffset; } else if(tabInfo[tab].valign == 1) { //Center iconRect.y = rect.y + rect.h/2.0f - iconRect.h/2.0f + tabInfo[tab].iconVOffset; } else if(tabInfo[tab].valign == 2) { //Bottom iconRect.y = rect.y + rect.h - iconRect.h + tabInfo[tab].iconVOffset; } dc->DrawMaterial(iconRect.x, iconRect.y, iconRect.w, iconRect.h, iconMat, idVec4(1.0f,1.0f,1.0f,1.0f), 1.0f, 1.0f); } } dc->PopClipRect(); start = stop + 1; stop = listItems[i].Find('\t', start); if ( stop < 0 ) { stop = listItems[i].Length(); } tab++; } rect.x = textRect.x; rect.w = width; } else { dc->DrawText(listItems[i], scale, 0, color, rect, false, -1); } rect.y += lineHeight; if ( rect.y > bottom ) { break; } } }
idScreenRect R_CalcIntersectionScissor( const idRenderLightLocal *lightDef, const idRenderEntityLocal *entityDef, const viewDef_t *viewDef ) { idMat4 omodel = make_idMat4( entityDef->modelMatrix ); idMat4 lmodel = make_idMat4( lightDef->modelMatrix ); // compute light polyhedron polyhedron lvol = PolyhedronFromBounds( lightDef->frustumTris->bounds ); // debug if( r_useInteractionScissors.GetInteger() == -2 ) { draw_polyhedron( viewDef, lvol, colorRed ); } // compute object polyhedron polyhedron vol = PolyhedronFromBounds( entityDef->referenceBounds ); // transform it into world space vol.transform( omodel ); // debug if( r_useInteractionScissors.GetInteger() == -2 ) { draw_polyhedron( viewDef, vol, colorBlue ); } // transform light position into world space idVec4 lightpos = idVec4( lightDef->globalLightOrigin.x, lightDef->globalLightOrigin.y, lightDef->globalLightOrigin.z, 1.0f ); // generate shadow volume "polyhedron" polyhedron sv = make_sv( vol, lightpos ); // segment light bounds MySegments in_segs, out_segs; // get shadow volume edges polyhedron_edges( sv, in_segs ); // clip them against light bounds planes clip_segments( lvol, in_segs, out_segs ); // get light bounds edges polyhedron_edges( lvol, in_segs ); // clip them by the shadow volume clip_segments( sv, in_segs, out_segs ); // debug if( r_useInteractionScissors.GetInteger() == -2 ) { draw_segments( viewDef, out_segs, colorGreen ); } idBounds outbounds; outbounds.Clear(); for( unsigned int i = 0; i < out_segs.size(); i++ ) { idVec4 v; world_to_hclip( viewDef, out_segs[i], v ); if( v.w <= 0.0f ) { return lightDef->viewLight->scissorRect; } idVec3 rv( v.x, v.y, v.z ); rv /= v.w; outbounds.AddPoint( rv ); } // limit the bounds to avoid an inside out scissor rectangle due to floating point to short conversion if( outbounds[0].x < -1.0f ) { outbounds[0].x = -1.0f; } if( outbounds[1].x > 1.0f ) { outbounds[1].x = 1.0f; } if( outbounds[0].y < -1.0f ) { outbounds[0].y = -1.0f; } if( outbounds[1].y > 1.0f ) { outbounds[1].y = 1.0f; } float w2 = ( viewDef->viewport.x2 - viewDef->viewport.x1 + 1 ) / 2.0f; float x = viewDef->viewport.x1; float h2 = ( viewDef->viewport.y2 - viewDef->viewport.y1 + 1 ) / 2.0f; float y = viewDef->viewport.y1; idScreenRect rect; rect.Clear(); rect.x1 = outbounds[0].x * w2 + w2 + x; rect.x2 = outbounds[1].x * w2 + w2 + x; rect.y1 = outbounds[0].y * h2 + h2 + y; rect.y2 = outbounds[1].y * h2 + h2 + y; rect.Expand(); rect.Intersect( lightDef->viewLight->scissorRect ); // debug if( r_useInteractionScissors.GetInteger() == -2 && !rect.IsEmpty() ) { viewDef->renderWorld->DebugScreenRect( colorYellow, rect, viewDef ); } return rect; }
bool idUserInterfaceLocal::InitFromFile( const char *qpath, bool rebuild, bool cache ) { if ( !( qpath && *qpath ) ) { // FIXME: Memory leak!! return false; } idHashTable<idParser*> sourcePatchMap; InitPatchFiles( qpath, sourcePatchMap ); loading = true; if ( rebuild ) { delete desktop; desktop = new idWindow( this ); } else if ( desktop == NULL ) { desktop = new idWindow( this ); } source = qpath; idParser src( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT ); //Load the timestamp so reload guis will work correctly fileSystem->ReadFile(qpath, NULL, &timeStamp); src.LoadFile( qpath ); if ( src.IsLoaded() ) { idToken token; while( src.ReadToken( &token ) ) { if ( idStr::Icmp( token, "windowDef" ) == 0 ) { idParser* originalSource = NULL; // Read the window identifier idToken windowName; src.ExpectTokenType( TT_NAME, 0, &windowName ); idParser* source = &src; // See if there is a patch for the whole Window idParser** sourcePatch; if ( sourcePatchMap.Get( windowName, &sourcePatch ) ) { // Save the current source originalSource = source; // Replace the current source with the source from the patch. source = *sourcePatch; // We already know this defines an idWindow, so don't bother to validate source->ExpectAnyToken( &token ); // The root Window is hard coded as a windowDef. Make sure the patch is for the same. if ( idStr::Icmp( token, "windowDef" ) == 0 ) { // Skip the rest of this Window and ignore it. // OPTIONAL: We might want to go back later and and parse this for the window names so // we can explicitly include text from some sections. We'll implement this change is it // is demanded. // Original file must be properly formatted. if ( originalSource->SkipBracedSection() ) { // Can't reuse source patches sourcePatchMap.Remove( windowName ); source->ExpectTokenType( TT_NAME, 0, &windowName ); } } else { common->Warning( "The root window must be a windowDef. Ignoring patch for '%s'.", windowName.c_str() ); (*sourcePatch)->UnreadToken( &token ); } } desktop->SetDC( &uiManagerLocal.dc ); if ( desktop->Parse( source, sourcePatchMap, windowName, rebuild ) ) { desktop->SetFlag( WIN_DESKTOP ); desktop->FixupParms(); } // The original source was saved off. Restore it. if ( originalSource != NULL ) { // Can't reuse source patches delete source; source = originalSource; } continue; } } state.Set( "name", qpath ); } else { desktop->SetDC( &uiManagerLocal.dc ); desktop->SetFlag( WIN_DESKTOP ); desktop->name = "Desktop"; desktop->text = va( "Invalid GUI: %s", qpath ); desktop->rect = idRectangle( 0.0f, 0.0f, 640.0f, 480.0f ); desktop->drawRect = desktop->rect; desktop->foreColor = idVec4( 1.0f, 1.0f, 1.0f, 1.0f ); desktop->backColor = idVec4( 0.0f, 0.0f, 0.0f, 1.0f ); desktop->SetupFromState(); common->Warning( "Couldn't load gui: '%s'", qpath ); } interactive = desktop->Interactive(); if ( uiManagerLocal.guis.Find( this ) == NULL ) { uiManagerLocal.guis.Append( this ); } loading = false; DeletePatchData( sourcePatchMap ); return true; }
static idVec3 ToWorld( idVec3 &v ) { return ( glflipMatrix * idVec4( v, 1.0f ) ).ToVec3(); }
static void RB_GLSL_SubmitDrawInteractions(const viewLight_t& vLight, const InteractionList& interactionList) { if (interactionList.IsEmpty()) return; // perform setup here that will be constant for all interactions GL_State( GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE | GLS_DEPTHMASK | backEnd.depthFunc ); GL_UseProgram( interactionProgram ); fhRenderProgram::SetShading( r_shading.GetInteger() ); fhRenderProgram::SetSpecularExp( r_specularExp.GetFloat() ); fhRenderProgram::SetAmbientLight( vLight.lightDef->lightShader->IsAmbientLight() ? 1 : 0 ); if (vLight.lightDef->ShadowMode() == shadowMode_t::ShadowMap) { const idVec4 globalLightOrigin = idVec4( vLight.globalLightOrigin, 1 ); fhRenderProgram::SetGlobalLightOrigin( globalLightOrigin ); const float shadowBrightness = vLight.lightDef->ShadowBrightness(); const float shadowSoftness = vLight.lightDef->ShadowSoftness(); fhRenderProgram::SetShadowParams( idVec4( shadowSoftness, shadowBrightness, vLight.nearClip[0], vLight.farClip[0] ) ); if(vLight.lightDef->parms.parallel) { //parallel light fhRenderProgram::SetShadowMappingMode( 3 ); fhRenderProgram::SetPointLightProjectionMatrices( vLight.viewProjectionMatrices[0].ToFloatPtr() ); fhRenderProgram::SetShadowCoords( vLight.shadowCoords, 6 ); fhRenderProgram::SetCascadeDistances( r_smCascadeDistance0.GetFloat(), r_smCascadeDistance1.GetFloat(), r_smCascadeDistance2.GetFloat(), r_smCascadeDistance3.GetFloat(), r_smCascadeDistance4.GetFloat()); idVec4 shadowmapSizes[6] = { idVec4(vLight.nearClip[0], vLight.farClip[0], vLight.width[0], vLight.height[0]), idVec4(vLight.nearClip[1], vLight.farClip[1], vLight.width[1], vLight.height[1]), idVec4(vLight.nearClip[2], vLight.farClip[2], vLight.width[2], vLight.height[2]), idVec4(vLight.nearClip[3], vLight.farClip[3], vLight.width[3], vLight.height[3]), idVec4(vLight.nearClip[4], vLight.farClip[4], vLight.width[4], vLight.height[4]), idVec4(vLight.nearClip[5], vLight.farClip[5], vLight.width[5], vLight.height[5]) }; fhRenderProgram::SetShadowMapSize(shadowmapSizes, 6); } else if (vLight.lightDef->parms.pointLight) { //point light fhRenderProgram::SetShadowMappingMode( 1 ); fhRenderProgram::SetPointLightProjectionMatrices( vLight.viewProjectionMatrices[0].ToFloatPtr() ); fhRenderProgram::SetShadowCoords(vLight.shadowCoords, 6); { const idMat3 axis = vLight.lightDef->parms.axis; float viewerMatrix[16]; viewerMatrix[0] = axis[0][0]; viewerMatrix[4] = axis[0][1]; viewerMatrix[8] = axis[0][2]; viewerMatrix[12] = 0; viewerMatrix[1] = axis[1][0]; viewerMatrix[5] = axis[1][1]; viewerMatrix[9] = axis[1][2]; viewerMatrix[13] = 0; viewerMatrix[2] = axis[2][0]; viewerMatrix[6] = axis[2][1]; viewerMatrix[10] = axis[2][2]; viewerMatrix[14] = 0; viewerMatrix[3] = 0; viewerMatrix[7] = 0; viewerMatrix[11] = 0; viewerMatrix[15] = 1; fhRenderProgram::SetInverseLightRotation( viewerMatrix ); } } else { //projected light fhRenderProgram::SetShadowMappingMode( 2 ); fhRenderProgram::SetSpotLightProjectionMatrix( vLight.viewProjectionMatrices[0].ToFloatPtr() ); fhRenderProgram::SetShadowCoords(vLight.shadowCoords, 1); } } else { //no shadows fhRenderProgram::SetShadowMappingMode( 0 ); } //make sure depth hacks are disabled //FIXME(johl): why is (sometimes) a depth hack enabled at this point? RB_LeaveDepthHack(); fhRenderProgram::SetProjectionMatrix( backEnd.viewDef->projectionMatrix ); fhRenderProgram::SetPomMaxHeight( -1 ); const viewEntity_t* currentSpace = nullptr; stageVertexColor_t currentVertexColor = (stageVertexColor_t)-1; bool currentPomEnabled = false; idScreenRect currentScissor; bool depthHackActive = false; bool currentHasBumpMatrix = false; bool currentHasDiffuseMatrix = false; bool currentHasSpecularMatrix = false; idVec4 currentDiffuseColor = idVec4( 1, 1, 1, 1 ); idVec4 currentSpecularColor = idVec4( 1, 1, 1, 1 ); fhRenderProgram::SetDiffuseColor( currentDiffuseColor ); fhRenderProgram::SetSpecularColor( currentSpecularColor ); fhRenderProgram::SetBumpMatrix( idVec4::identityS, idVec4::identityT ); fhRenderProgram::SetSpecularMatrix( idVec4::identityS, idVec4::identityT ); fhRenderProgram::SetDiffuseMatrix( idVec4::identityS, idVec4::identityT ); glDepthRange(0, 1); if (r_useScissor.GetBool()) { auto fb = fhFramebuffer::GetCurrentDrawBuffer(); glScissor( 0, 0, fb->GetWidth(), fb->GetHeight() ); currentScissor.x1 = 0; currentScissor.y1 = 0; currentScissor.x2 = fb->GetWidth(); currentScissor.y2 = fb->GetHeight(); } const int num = interactionList.Num(); for (int i = 0; i < num; ++i) { const auto& din = interactionList[i]; const auto offset = vertexCache.Bind( din.surf->geo->ambientCache ); GL_SetupVertexAttributes( fhVertexLayout::Draw, offset ); if (currentSpace != din.surf->space) { fhRenderProgram::SetModelMatrix( din.surf->space->modelMatrix ); fhRenderProgram::SetModelViewMatrix( din.surf->space->modelViewMatrix ); if (din.surf->space->modelDepthHack) { RB_EnterModelDepthHack( din.surf->space->modelDepthHack ); fhRenderProgram::SetProjectionMatrix( GL_ProjectionMatrix.Top() ); depthHackActive = true; } else if (din.surf->space->weaponDepthHack) { RB_EnterWeaponDepthHack(); fhRenderProgram::SetProjectionMatrix( GL_ProjectionMatrix.Top() ); depthHackActive = true; } else if (depthHackActive) { RB_LeaveDepthHack(); fhRenderProgram::SetProjectionMatrix( GL_ProjectionMatrix.Top() ); depthHackActive = false; } // change the scissor if needed if (r_useScissor.GetBool() && !currentScissor.Equals( din.surf->scissorRect )) { currentScissor = din.surf->scissorRect; glScissor( backEnd.viewDef->viewport.x1 + currentScissor.x1, backEnd.viewDef->viewport.y1 + currentScissor.y1, currentScissor.x2 + 1 - currentScissor.x1, currentScissor.y2 + 1 - currentScissor.y1 ); } currentSpace = din.surf->space; } fhRenderProgram::SetLocalLightOrigin( din.localLightOrigin ); fhRenderProgram::SetLocalViewOrigin( din.localViewOrigin ); fhRenderProgram::SetLightProjectionMatrix( din.lightProjection[0], din.lightProjection[1], din.lightProjection[2] ); fhRenderProgram::SetLightFallOff( din.lightProjection[3] ); if (din.hasBumpMatrix) { fhRenderProgram::SetBumpMatrix( din.bumpMatrix[0], din.bumpMatrix[1] ); currentHasBumpMatrix = true; } else if (currentHasBumpMatrix) { fhRenderProgram::SetBumpMatrix( idVec4::identityS, idVec4::identityT ); currentHasBumpMatrix = false; } if (din.hasDiffuseMatrix) { fhRenderProgram::SetDiffuseMatrix( din.diffuseMatrix[0], din.diffuseMatrix[1] ); currentHasDiffuseMatrix = true; } else if (currentHasDiffuseMatrix) { fhRenderProgram::SetDiffuseMatrix( idVec4::identityS, idVec4::identityT ); currentHasDiffuseMatrix = false; } if (din.hasSpecularMatrix) { fhRenderProgram::SetSpecularMatrix( din.specularMatrix[0], din.specularMatrix[1] ); currentHasSpecularMatrix = true; } else if (currentHasSpecularMatrix) { fhRenderProgram::SetSpecularMatrix( idVec4::identityS, idVec4::identityT ); currentHasSpecularMatrix = false; } if (currentVertexColor != din.vertexColor) { switch (din.vertexColor) { case SVC_IGNORE: fhRenderProgram::SetColorModulate( idVec4::zero ); fhRenderProgram::SetColorAdd( idVec4::one ); break; case SVC_MODULATE: fhRenderProgram::SetColorModulate( idVec4::one ); fhRenderProgram::SetColorAdd( idVec4::zero ); break; case SVC_INVERSE_MODULATE: fhRenderProgram::SetColorModulate( idVec4::negOne ); fhRenderProgram::SetColorAdd( idVec4::one ); break; } currentVertexColor = din.vertexColor; } if (din.diffuseColor != currentDiffuseColor) { fhRenderProgram::SetDiffuseColor( din.diffuseColor ); currentDiffuseColor = din.diffuseColor; } if (din.specularColor != currentSpecularColor) { fhRenderProgram::SetSpecularColor( din.specularColor ); currentSpecularColor = din.specularColor; } const bool pomEnabled = r_pomEnabled.GetBool() && din.specularImage->hasAlpha; if (pomEnabled != currentPomEnabled) { if (pomEnabled) { fhRenderProgram::SetPomMaxHeight( r_pomMaxHeight.GetFloat() ); } else { fhRenderProgram::SetPomMaxHeight( -1 ); } } fhRenderProgram::SetNormalMapEncoding( RB_GetNormalEncoding( din.bumpImage ) ); din.bumpImage->Bind( 1 ); din.lightFalloffImage->Bind( 2 ); din.lightImage->Bind( 3 ); din.diffuseImage->Bind( 4 ); din.specularImage->Bind( 5 ); // draw it backEnd.stats.groups[backEndGroup::Interaction].drawcalls += 1; backEnd.stats.groups[backEndGroup::Interaction].tris += din.surf->geo->numIndexes / 3; RB_DrawElementsWithCounters( din.surf->geo ); } if (depthHackActive) { RB_LeaveDepthHack(); fhRenderProgram::SetProjectionMatrix( GL_ProjectionMatrix.Top() ); } if (r_useScissor.GetBool()) { auto fb = fhFramebuffer::GetCurrentDrawBuffer(); glScissor( 0, 0, fb->GetWidth(), fb->GetHeight() ); backEnd.currentScissor.x1 = 0; backEnd.currentScissor.y1 = 0; backEnd.currentScissor.x2 = fb->GetWidth(); backEnd.currentScissor.y2 = fb->GetHeight(); } }
/* ================ idThread::Event_DebugArrow ================ */ void idThread::Event_DebugArrow( const idVec3 &color, const idVec3 &start, const idVec3 &end, const int size, const float lifetime ) { gameRenderWorld->DebugArrow( idVec4( color.x, color.y, color.z, 0.0f ), start, end, size, SEC2MS( lifetime ) ); }
void idGLDrawableView::drawLights( renderView_t *refdef ) { int i; for ( i=0; i < viewLights.Num(); i++ ) { lightInfo_t *vLight = &viewLights[i]; idVec4 lColor; lColor.x = vLight->color.x; lColor.y = vLight->color.y; lColor.z = vLight->color.z; lColor.w = 1.f; idSphere sphere(vLight->renderLight.origin, 4); session->rw->DebugSphere( lColor, sphere, 0, true ); session->rw->DrawText( va( "%d", i+1 ), vLight->renderLight.origin + idVec3(0,0,5), 0.25f, idVec4(1,1,0,1), refdef->viewaxis, 1, 0, true ); } }
/* ================ idThread::Event_DebugCircle ================ */ void idThread::Event_DebugCircle( const idVec3 &color, const idVec3 &origin, const idVec3 &dir, const float radius, const int numSteps, const float lifetime ) { gameRenderWorld->DebugCircle( idVec4( color.x, color.y, color.z, 0.0f ), origin, dir, radius, numSteps, SEC2MS( lifetime ) ); }
/* ======================== idSoundHardware_XAudio2::Init ======================== */ void idSoundHardware_XAudio2::Init() { cmdSystem->AddCommand( "listDevices", listDevices_f, 0, "Lists the connected sound devices", NULL ); DWORD xAudioCreateFlags = 0; // RB: not available on Windows 8 SDK #if !defined(USE_WINRT) && defined(_DEBUG) xAudioCreateFlags |= XAUDIO2_DEBUG_ENGINE; #endif // RB end XAUDIO2_PROCESSOR xAudioProcessor = XAUDIO2_DEFAULT_PROCESSOR; // RB: not available on Windows 8 SDK if ( FAILED( XAudio2Create( &pXAudio2, xAudioCreateFlags, xAudioProcessor ) ) ){ #if !defined(USE_WINRT) && defined(_DEBUG) if ( xAudioCreateFlags & XAUDIO2_DEBUG_ENGINE ) { // in case the debug engine isn't installed xAudioCreateFlags &= ~XAUDIO2_DEBUG_ENGINE; if ( FAILED( XAudio2Create( &pXAudio2, xAudioCreateFlags, xAudioProcessor ) ) ) { idLib::FatalError( "Failed to create XAudio2 engine. Try installing the latest DirectX." ); return; } } else #endif // RB end { idLib::FatalError( "Failed to create XAudio2 engine. Try installing the latest DirectX." ); return; } } #ifdef _DEBUG XAUDIO2_DEBUG_CONFIGURATION debugConfiguration = { 0 }; debugConfiguration.TraceMask = XAUDIO2_LOG_WARNINGS; debugConfiguration.BreakMask = XAUDIO2_LOG_ERRORS; pXAudio2->SetDebugConfiguration( &debugConfiguration ); #endif // Register the sound engine callback pXAudio2->RegisterForCallbacks( &soundEngineCallback ); soundEngineCallback.hardware = this; DWORD outputSampleRate = 44100; // Max( (DWORD)XAUDIO2FX_REVERB_MIN_FRAMERATE, Min( (DWORD)XAUDIO2FX_REVERB_MAX_FRAMERATE, deviceDetails.OutputFormat.Format.nSamplesPerSec ) ); idCmdArgs args; listDevices_f( args ); // RB: not available on Windows 8 SDK #if defined(USE_WINRT) //(_WIN32_WINNT >= 0x0602 /*_WIN32_WINNT_WIN8*/) AudioDevice defaultDevice; std::vector<AudioDevice> vAudioDevices = EnumerateAudioDevices(&defaultDevice); if (!vAudioDevices.empty()) { AudioDevice selectedDevice; int preferredDevice = s_device.GetInteger(); bool validPreference = (preferredDevice >= 0 && preferredDevice < (int)vAudioDevices.size()); // Do we select a device automatically? if (validPreference) { // Use the user's selected device selectedDevice = vAudioDevices[preferredDevice]; } else if (!defaultDevice.id.empty()) { // Fall back to the default device if there is one selectedDevice = defaultDevice; } else { // Fall back to first device selectedDevice = vAudioDevices[0]; } if (SUCCEEDED(pXAudio2->CreateMasteringVoice(&pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, outputSampleRate, 0, selectedDevice.id.c_str(), NULL, AudioCategory_GameEffects))) { XAUDIO2_VOICE_DETAILS deviceDetails; pMasterVoice->GetVoiceDetails(&deviceDetails); pMasterVoice->SetVolume(DBtoLinear(s_volume_dB.GetFloat())); outputChannels = deviceDetails.InputChannels; DWORD win8_channelMask; pMasterVoice->GetChannelMask(&win8_channelMask); channelMask = (unsigned int)win8_channelMask; idLib::Printf( "Using device %S\n", selectedDevice.name ); } else { idLib::Warning("Failed to create master voice"); pXAudio2->Release(); pXAudio2 = NULL; return; } } #else UINT32 deviceCount = 0; if( pXAudio2->GetDeviceCount( &deviceCount ) != S_OK || deviceCount == 0 ) { idLib::Warning( "No audio devices found" ); pXAudio2->Release(); pXAudio2 = NULL; return; } int preferredDevice = s_device.GetInteger(); if( preferredDevice < 0 || preferredDevice >= ( int )deviceCount ) { int preferredChannels = 0; for( unsigned int i = 0; i < deviceCount; i++ ) { XAUDIO2_DEVICE_DETAILS deviceDetails; if( pXAudio2->GetDeviceDetails( i, &deviceDetails ) != S_OK ) { continue; } if( deviceDetails.Role & DefaultGameDevice ) { // if we find a device the user marked as their preferred 'game' device, then always use that preferredDevice = i; preferredChannels = deviceDetails.OutputFormat.Format.nChannels; break; } if( deviceDetails.OutputFormat.Format.nChannels > preferredChannels ) { preferredDevice = i; preferredChannels = deviceDetails.OutputFormat.Format.nChannels; } } } idLib::Printf( "Using device %d\n", preferredDevice ); XAUDIO2_DEVICE_DETAILS deviceDetails; if( pXAudio2->GetDeviceDetails( preferredDevice, &deviceDetails ) != S_OK ) { // One way this could happen is if a device is removed between the loop and this line of code // Highly unlikely but possible idLib::Warning( "Failed to get device details" ); pXAudio2->Release(); pXAudio2 = NULL; return; } if( FAILED( pXAudio2->CreateMasteringVoice( &pMasterVoice, XAUDIO2_DEFAULT_CHANNELS, outputSampleRate, 0, preferredDevice, NULL ) ) ) { idLib::Warning( "Failed to create master voice" ); pXAudio2->Release(); pXAudio2 = NULL; return; } pMasterVoice->SetVolume( DBtoLinear( s_volume_dB.GetFloat() ) ); outputChannels = deviceDetails.OutputFormat.Format.nChannels; channelMask = deviceDetails.OutputFormat.dwChannelMask; #endif // #if (_WIN32_WINNT < 0x0602 /*_WIN32_WINNT_WIN8*/) idSoundVoice::InitSurround( outputChannels, channelMask ); // --------------------- // Initialize the Doom classic sound system. // --------------------- I_InitSoundHardware( outputChannels, channelMask ); // --------------------- // Create VU Meter Effect // --------------------- IUnknown * vuMeter = NULL; XAudio2CreateVolumeMeter( &vuMeter, 0 ); XAUDIO2_EFFECT_DESCRIPTOR descriptor; descriptor.InitialState = true; descriptor.OutputChannels = outputChannels; descriptor.pEffect = vuMeter; XAUDIO2_EFFECT_CHAIN chain; chain.EffectCount = 1; chain.pEffectDescriptors = &descriptor; pMasterVoice->SetEffectChain( &chain ); vuMeter->Release(); // --------------------- // Create VU Meter Graph // --------------------- vuMeterRMS = console->CreateGraph( outputChannels ); vuMeterPeak = console->CreateGraph( outputChannels ); vuMeterRMS->Enable( false ); vuMeterPeak->Enable( false ); memset( vuMeterPeakTimes, 0, sizeof( vuMeterPeakTimes ) ); vuMeterPeak->SetFillMode( idDebugGraph::GRAPH_LINE ); vuMeterPeak->SetBackgroundColor( idVec4( 0.0f, 0.0f, 0.0f, 0.0f ) ); vuMeterRMS->AddGridLine( 0.500f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) ); vuMeterRMS->AddGridLine( 0.250f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) ); vuMeterRMS->AddGridLine( 0.125f, idVec4( 0.5f, 0.5f, 0.5f, 1.0f ) ); const char * channelNames[] = { "L", "R", "C", "S", "Lb", "Rb", "Lf", "Rf", "Cb", "Ls", "Rs" }; for ( int i = 0, ci = 0; ci < sizeof( channelNames ) / sizeof( channelNames[0] ); ci++ ) { if ( ( channelMask & BIT( ci ) ) == 0 ) { continue; } vuMeterRMS->SetLabel( i, channelNames[ ci ] ); i++; } // --------------------- // Create submix buffer // --------------------- if ( FAILED( pXAudio2->CreateSubmixVoice( &pSubmixVoice, 1, outputSampleRate, 0, 0, NULL, NULL ) ) ) { idLib::FatalError( "Failed to create submix voice" ); } // XAudio doesn't really impose a maximum number of voices voices.SetNum( voices.Max() ); freeVoices.SetNum( voices.Max() ); zombieVoices.SetNum( 0 ); for ( int i = 0; i < voices.Num(); i++ ) { freeVoices[i] = &voices[i]; } // RB end }
/* ================ idThread::Event_DebugBounds ================ */ void idThread::Event_DebugBounds( const idVec3 &color, const idVec3 &mins, const idVec3 &maxs, const float lifetime ) { gameRenderWorld->DebugBounds( idVec4( color.x, color.y, color.z, 0.0f ), idBounds( mins, maxs ), vec3_origin, SEC2MS( lifetime ) ); }
bool idUserInterfaceLocal::InitFromFile( const char *qpath, bool rebuild, bool cache ) { if ( !( qpath && *qpath ) ) { // FIXME: Memory leak!! return false; } loading = true; if ( rebuild ) { delete desktop; desktop = new idWindow( this ); } else if ( desktop == NULL ) { desktop = new idWindow( this ); } source = qpath; state.Set( "text", "Test Text!" ); idParser src( LEXFL_NOFATALERRORS | LEXFL_NOSTRINGCONCAT | LEXFL_ALLOWMULTICHARLITERALS | LEXFL_ALLOWBACKSLASHSTRINGCONCAT ); //Load the timestamp so reload guis will work correctly fileSystem->ReadFile(qpath, NULL, &timeStamp); src.LoadFile( qpath ); if ( src.IsLoaded() ) { idToken token; while( src.ReadToken( &token ) ) { if ( idStr::Icmp( token, "windowDef" ) == 0 ) { desktop->SetDC( &uiManagerLocal.dc ); if ( desktop->Parse( &src, rebuild ) ) { desktop->SetFlag( WIN_DESKTOP ); desktop->FixupParms(); } continue; } } state.Set( "name", qpath ); } else { desktop->SetDC( &uiManagerLocal.dc ); desktop->SetFlag( WIN_DESKTOP ); desktop->name = "Desktop"; desktop->text = va( "Invalid GUI: %s", qpath ); desktop->rect = idRectangle( 0.0f, 0.0f, 640.0f, 480.0f ); desktop->drawRect = desktop->rect; desktop->foreColor = idVec4( 1.0f, 1.0f, 1.0f, 1.0f ); desktop->backColor = idVec4( 0.0f, 0.0f, 0.0f, 1.0f ); desktop->SetupFromState(); common->Warning( "Couldn't load gui: '%s'", qpath ); } interactive = desktop->Interactive(); if ( uiManagerLocal.guis.Find( this ) == NULL ) { uiManagerLocal.guis.Append( this ); } loading = false; return true; }
/* ================ idThread::Event_DrawText ================ */ void idThread::Event_DrawText( const char *text, const idVec3 &origin, float scale, const idVec3 &color, const int align, const float lifetime ) { gameRenderWorld->DrawText( text, origin, scale, idVec4( color.x, color.y, color.z, 0.0f ), gameLocal.GetLocalPlayer()->viewAngles.ToMat3(), align, SEC2MS( lifetime ) ); }
void fhLineBuffer::Add(idVec3 from, idVec3 to, idVec3 color) { Add(from, to, idVec4(color.x, color.y, color.z, 1.0f)); }
void MyRenderBase::OnPreRender() { m_eye = idVec4( view.m_pos, 1.0f ); SetupViewMatrix( view ); SetupProjectionMatrix( view ); }
/* ================ idBrittleFracture::UpdateRenderEntity ================ */ bool idBrittleFracture::UpdateRenderEntity( renderEntity_s *renderEntity, const renderView_t *renderView ) const { int i, j, k, n, msec, numTris, numDecalTris; float fade; dword packedColor; srfTriangles_t *tris, *decalTris; modelSurface_t surface; idDrawVert *v; idPlane plane; idMat3 tangents; // this may be triggered by a model trace or other non-view related source, // to which we should look like an empty model if ( !renderView ) { return false; } // don't regenerate it if it is current if ( lastRenderEntityUpdate == gameLocal.time || !changed ) { return false; } lastRenderEntityUpdate = gameLocal.time; changed = false; numTris = 0; numDecalTris = 0; for ( i = 0; i < shards.Num(); i++ ) { n = shards[i]->winding.GetNumPoints(); if ( n > 2 ) { numTris += n - 2; } for ( k = 0; k < shards[i]->decals.Num(); k++ ) { n = shards[i]->decals[k]->GetNumPoints(); if ( n > 2 ) { numDecalTris += n - 2; } } } // FIXME: re-use model surfaces renderEntity->hModel->InitEmpty( brittleFracture_SnapshotName ); // allocate triangle surfaces for the fractures and decals tris = renderEntity->hModel->AllocSurfaceTriangles( numTris * 3, material->ShouldCreateBackSides() ? numTris * 6 : numTris * 3 ); decalTris = renderEntity->hModel->AllocSurfaceTriangles( numDecalTris * 3, decalMaterial->ShouldCreateBackSides() ? numDecalTris * 6 : numDecalTris * 3 ); for ( i = 0; i < shards.Num(); i++ ) { const idVec3 &origin = shards[i]->clipModel->GetOrigin(); const idMat3 &axis = shards[i]->clipModel->GetAxis(); fade = 1.0f; if ( shards[i]->droppedTime >= 0 ) { msec = gameLocal.time - shards[i]->droppedTime - SHARD_FADE_START; if ( msec > 0 ) { fade = 1.0f - (float) msec / ( SHARD_ALIVE_TIME - SHARD_FADE_START ); } } packedColor = PackColor( idVec4( renderEntity->shaderParms[ SHADERPARM_RED ] * fade, renderEntity->shaderParms[ SHADERPARM_GREEN ] * fade, renderEntity->shaderParms[ SHADERPARM_BLUE ] * fade, fade ) ); const idWinding &winding = shards[i]->winding; winding.GetPlane( plane ); tangents = ( plane.Normal() * axis ).ToMat3(); for ( j = 2; j < winding.GetNumPoints(); j++ ) { v = &tris->verts[tris->numVerts++]; v->Clear(); v->xyz = origin + winding[0].ToVec3() * axis; v->st[0] = winding[0].s; v->st[1] = winding[0].t; v->normal = tangents[0]; v->tangents[0] = tangents[1]; v->tangents[1] = tangents[2]; v->SetColor( packedColor ); v = &tris->verts[tris->numVerts++]; v->Clear(); v->xyz = origin + winding[j-1].ToVec3() * axis; v->st[0] = winding[j-1].s; v->st[1] = winding[j-1].t; v->normal = tangents[0]; v->tangents[0] = tangents[1]; v->tangents[1] = tangents[2]; v->SetColor( packedColor ); v = &tris->verts[tris->numVerts++]; v->Clear(); v->xyz = origin + winding[j].ToVec3() * axis; v->st[0] = winding[j].s; v->st[1] = winding[j].t; v->normal = tangents[0]; v->tangents[0] = tangents[1]; v->tangents[1] = tangents[2]; v->SetColor( packedColor ); tris->indexes[tris->numIndexes++] = tris->numVerts - 3; tris->indexes[tris->numIndexes++] = tris->numVerts - 2; tris->indexes[tris->numIndexes++] = tris->numVerts - 1; if ( material->ShouldCreateBackSides() ) { tris->indexes[tris->numIndexes++] = tris->numVerts - 2; tris->indexes[tris->numIndexes++] = tris->numVerts - 3; tris->indexes[tris->numIndexes++] = tris->numVerts - 1; } } for ( k = 0; k < shards[i]->decals.Num(); k++ ) { const idWinding &decalWinding = *shards[i]->decals[k]; for ( j = 2; j < decalWinding.GetNumPoints(); j++ ) { v = &decalTris->verts[decalTris->numVerts++]; v->Clear(); v->xyz = origin + decalWinding[0].ToVec3() * axis; v->st[0] = decalWinding[0].s; v->st[1] = decalWinding[0].t; v->normal = tangents[0]; v->tangents[0] = tangents[1]; v->tangents[1] = tangents[2]; v->SetColor( packedColor ); v = &decalTris->verts[decalTris->numVerts++]; v->Clear(); v->xyz = origin + decalWinding[j-1].ToVec3() * axis; v->st[0] = decalWinding[j-1].s; v->st[1] = decalWinding[j-1].t; v->normal = tangents[0]; v->tangents[0] = tangents[1]; v->tangents[1] = tangents[2]; v->SetColor( packedColor ); v = &decalTris->verts[decalTris->numVerts++]; v->Clear(); v->xyz = origin + decalWinding[j].ToVec3() * axis; v->st[0] = decalWinding[j].s; v->st[1] = decalWinding[j].t; v->normal = tangents[0]; v->tangents[0] = tangents[1]; v->tangents[1] = tangents[2]; v->SetColor( packedColor ); decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 3; decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 2; decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 1; if ( decalMaterial->ShouldCreateBackSides() ) { decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 2; decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 3; decalTris->indexes[decalTris->numIndexes++] = decalTris->numVerts - 1; } } } } tris->tangentsCalculated = true; decalTris->tangentsCalculated = true; SIMDProcessor->MinMax( tris->bounds[0], tris->bounds[1], tris->verts, tris->numVerts ); SIMDProcessor->MinMax( decalTris->bounds[0], decalTris->bounds[1], decalTris->verts, decalTris->numVerts ); memset( &surface, 0, sizeof( surface ) ); surface.shader = material; surface.id = 0; surface.geometry = tris; renderEntity->hModel->AddSurface( surface ); memset( &surface, 0, sizeof( surface ) ); surface.shader = decalMaterial; surface.id = 1; surface.geometry = decalTris; renderEntity->hModel->AddSurface( surface ); return true; }
void idAASLocal::DrawAreas(const idVec3& playerOrigin) { if ( file == NULL ) { return; } // Initialize AAS area colors if we haven't already done so if ( aasColors.Num() == 0 ) { // Get a color for each cluster int numClusters = file->GetNumClusters(); for ( int c = 0 ; c < numClusters ; c++ ) { aasColors.Alloc() = idVec4(gameLocal.random.RandomFloat() + 0.1f, gameLocal.random.RandomFloat() + 0.1f, gameLocal.random.RandomFloat() + 0.1f, 1); } } idMat3 playerViewMatrix(gameLocal.GetLocalPlayer()->viewAngles.ToMat3()); idList<int> clusterNums; // Paint the AAS areas for ( int i = 0 ; i < file->GetNumAreas() ; i++ ) { idVec3 areaCenter = AreaCenter(i); // angua: only draw areas near the player, no need to see them at the other end of the map if ( (areaCenter - playerOrigin).LengthFast() < 150 ) { idBounds areaBounds = GetAreaBounds(i); int clusterNum = file->GetArea(i).cluster; clusterNums.AddUnique(clusterNum); idVec4 color = (clusterNum <= 0) ? colorWhite : aasColors[clusterNum]; gameRenderWorld->DrawText(va("%d", i), areaCenter, 0.2f, color, playerViewMatrix, 1, 16); gameRenderWorld->DebugBox(color, idBox(areaBounds), 16); } } // Paint the cluster numbers for ( int i = 0 ; i < clusterNums.Num() ; i++ ) { int area = GetAreaInCluster(clusterNums[i]); if ( area <= 0 ) { continue; } idVec3 origin = file->GetArea(area).center; if ( (origin - playerOrigin).LengthFast() < 300 ) { gameRenderWorld->DrawText(va("%d", clusterNums[i]), origin, 1, colorRed, playerViewMatrix, 1, 16); } } }