// Called after the simulation has run....sends new positions to the various scene objects // *** want to do this in response to an update message.... void plPXPhysical::SendNewLocation(bool synchTransform, bool isSynchUpdate) { // we only send if: // - the body is active or forceUpdate is on // - the mass is non-zero // - the physical is not passive bool bodyActive = !fActor->isSleeping(); bool dynamic = fActor->isDynamic(); if ((bodyActive || isSynchUpdate) && dynamic)// && fInitialTransform) { plProfile_Inc(MaySendLocation); if (!GetProperty(plSimulationInterface::kPassive)) { hsMatrix44 curl2w = fCachedLocal2World; // we're going to cache the transform before sending so we can recognize if it comes back IGetTransformGlobal(fCachedLocal2World); if (!CompareMatrices(curl2w, fCachedLocal2World, .0001f)) { plProfile_Inc(LocationsSent); plProfile_BeginLap(PhysicsUpdates, GetKeyName().c_str()); // quick peek at the translation...last time it was corrupted because we applied a non-unit quaternion // hsAssert(real_finite(fCachedLocal2World.fMap[0][3]) && // real_finite(fCachedLocal2World.fMap[1][3]) && // real_finite(fCachedLocal2World.fMap[2][3]), "Bad transform outgoing"); if (fCachedLocal2World.GetTranslate().fZ < kMaxNegativeZPos) { SimLog("Physical %s fell to %.1f (%.1f is the max). Suppressing.", GetKeyName().c_str(), fCachedLocal2World.GetTranslate().fZ, kMaxNegativeZPos); // Since this has probably been falling for a while, and thus not getting any syncs, // make sure to save it's current pos so we'll know to reset it later DirtySynchState(kSDLPhysical, plSynchedObject::kBCastToClients); IEnable(false); } hsMatrix44 w2l; fCachedLocal2World.GetInverse(&w2l); plCorrectionMsg *pCorrMsg = new plCorrectionMsg(GetObjectKey(), fCachedLocal2World, w2l, synchTransform); pCorrMsg->Send(); if (fProxyGen) fProxyGen->SetTransform(fCachedLocal2World, w2l); plProfile_EndLap(PhysicsUpdates, GetKeyName().c_str()); } } } }
void plDynamicTextMap::Create( uint32_t width, uint32_t height, bool hasAlpha, uint32_t extraWidth, uint32_t extraHeight ) { SetConfig( hasAlpha ? kARGB32Config : kRGB32Config ); fVisWidth = (uint16_t)width; fVisHeight = (uint16_t)height; fHasAlpha = hasAlpha; for( fWidth = 1; fWidth < width + extraWidth; fWidth <<= 1 ); for( fHeight = 1; fHeight < height + extraHeight; fHeight <<= 1 ); // instead of allocating the fImage here, we'll wait for the first draw operation to be called (in IIsValid) fHasCreateBeenCalled = true; fRowBytes = fWidth << 2; fNumLevels = 1; fFlags |= plMipmap::kDontThrowAwayImage | plMipmap::kAutoGenMipmap; fCompressionType = plMipmap::kUncompressed; fUncompressedInfo.fType = plMipmap::UncompressedInfo::kRGB8888; // Destroy the old texture ref, if we have one. This should force the // pipeline to recreate one more suitable for our use SetDeviceRef( nil ); // Some init color SetFont( "Arial", 12 ); hsColorRGBA color; color.Set( 0,0,1,1); SetTextColor( color ); SetCurrLevel( 0 ); plProfile_Inc(DynaTexts); }
void plDSoundBuffer::IAllocate( uint32_t size, plWAVHeader &bufferDesc, hsBool enable3D, hsBool tryStatic ) { // Create a DSound buffer description fBufferDesc = new plWAVHeader; *fBufferDesc = bufferDesc; fBufferSize = size; // Do we want to try EAX? if( plgAudioSys::UsingEAX() ) fEAXSource.Init( this ); fValid = true; plProfile_Inc( NumAllocated ); }
// This form is assumed by convention to be global. void plPXPhysical::SetTransform(const hsMatrix44& l2w, const hsMatrix44& w2l, bool force) { // hsAssert(real_finite(l2w.fMap[0][3]) && real_finite(l2w.fMap[1][3]) && real_finite(l2w.fMap[2][3]), "Bad transform incoming"); // make sure the physical is dynamic. // also make sure there is some difference between the matrices... // ... but not when a subworld... because the subworld maybe animating and if the object is still then it is actually moving within the subworld if (force || (fActor->isDynamic() && (fWorldKey || !CompareMatrices(l2w, fCachedLocal2World, .0001f))) ) { ISetTransformGlobal(l2w); plProfile_Inc(SetTransforms); } else { if ( !fActor->isDynamic() && plSimulationMgr::fExtraProfile) SimLog("Setting transform on non-dynamic: %s.", GetKeyName().c_str()); } }
void plDSoundBuffer::Play( void ) { if(!source) return; ALenum error = alGetError(); // clear error // we dont want openal to loop our streaming buffers, or the buffer will loop back on itself. We will handle looping in the streaming sound if(fLooping && !fStreaming) alSourcei(source, AL_LOOPING, AL_TRUE); else alSourcei(source, AL_LOOPING, AL_FALSE); error = alGetError(); alSourcePlay(source); error = alGetError(); if(error != AL_NO_ERROR) plStatusLog::AddLineS("voice.log", "Play failed"); plProfile_Inc( SoundPlaying ); }
void pl3DPipeline::ICheckLighting(plDrawableSpans* drawable, hsTArray<int16_t>& visList, plVisMgr* visMgr) { if (fView.fRenderState & kRenderNoLights) return; if (!visList.GetCount()) return; plLightInfo* light; plProfile_BeginTiming(FindLights); // First add in the explicit lights (from LightGroups). // Refresh the lights as they are added (actually a lazy eval). plProfile_BeginTiming(FindPerm); for (size_t j = 0; j < visList.GetCount(); j++) { drawable->GetSpan(visList[j])->ClearLights(); if (IsDebugFlagSet(plPipeDbg::kFlagNoRuntimeLights)) continue; // Set the bits for the lights added from the permanent lists (during ClearLights()). const hsTArray<plLightInfo*>& permaLights = drawable->GetSpan(visList[j])->fPermaLights; for (size_t k = 0; k < permaLights.GetCount(); k++) { permaLights[k]->Refresh(); if (permaLights[k]->GetProperty(plLightInfo::kLPShadowLightGroup) && !permaLights[k]->IsIdle()) { // If it casts a shadow, attach the shadow now. ISetShadowFromGroup(drawable, drawable->GetSpan(visList[j]), permaLights[k]); } } const hsTArray<plLightInfo*>& permaProjs = drawable->GetSpan(visList[j])->fPermaProjs; for (size_t k = 0; k < permaProjs.GetCount(); k++) { permaProjs[k]->Refresh(); if (permaProjs[k]->GetProperty(plLightInfo::kLPShadowLightGroup) && !permaProjs[k]->IsIdle()) { // If it casts a shadow, attach the shadow now. ISetShadowFromGroup(drawable, drawable->GetSpan(visList[j]), permaProjs[k]); } } } plProfile_EndTiming(FindPerm); if (IsDebugFlagSet(plPipeDbg::kFlagNoRuntimeLights)) { plProfile_EndTiming(FindLights); return; } // Sort the incoming spans as either // A) moving - affected by all lights - moveList // B) specular - affected by specular lights - specList // C) visible - affected by moving lights - visList static hsTArray<int16_t> tmpList; static hsTArray<int16_t> moveList; static hsTArray<int16_t> specList; moveList.SetCount(0); specList.SetCount(0); plProfile_BeginTiming(FindSpan); for (size_t k = 0; k < visList.GetCount(); k++) { const plSpan* span = drawable->GetSpan(visList[k]); if (span->fProps & plSpan::kPropRunTimeLight) { moveList.Append(visList[k]); specList.Append(visList[k]); } else if (span->fProps & plSpan::kPropMatHasSpecular) { specList.Append(visList[k]); } } plProfile_EndTiming(FindSpan); // Make a list of lights that can potentially affect spans in this drawable // based on the drawables bounds and properties. // If the drawable has the PropCharacter property, it is affected by lights // in fCharLights, else only by the smaller list of fVisLights. plProfile_BeginTiming(FindActiveLights); static hsTArray<plLightInfo*> lightList; lightList.SetCount(0); if (drawable->GetNativeProperty(plDrawable::kPropCharacter)) { for (size_t i = 0; i < fCharLights.GetCount(); i++) { if (fCharLights[i]->AffectsBound(drawable->GetSpaceTree()->GetWorldBounds())) lightList.Append(fCharLights[i]); } } else { for (size_t i = 0; i < fVisLights.GetCount(); i++) { if (fVisLights[i]->AffectsBound(drawable->GetSpaceTree()->GetWorldBounds())) lightList.Append(fVisLights[i]); } } plProfile_EndTiming(FindActiveLights); // Loop over the lights and for each light, extract a list of the spans that light // affects. Append the light to each spans list with a scalar strength of how strongly // the light affects it. Since the strength is based on the object's center position, // it's not very accurate, but good enough for selecting which lights to use. plProfile_BeginTiming(ApplyActiveLights); for (size_t k = 0; k < lightList.GetCount(); k++) { light = lightList[k]; tmpList.SetCount(0); if (light->GetProperty(plLightInfo::kLPMovable)) { plProfile_BeginTiming(ApplyMoving); const hsTArray<int16_t>& litList = light->GetAffected(drawable->GetSpaceTree(), visList, tmpList, drawable->GetNativeProperty(plDrawable::kPropCharacter)); // PUT OVERRIDE FOR KILLING PROJECTORS HERE!!!! bool proj = nil != light->GetProjection(); if (fView.fRenderState & kRenderNoProjection) proj = false; for (size_t j = 0; j < litList.GetCount(); j++) { // Use the light IF light is enabled and // 1) light is movable // 2) span is movable, or // 3) Both the light and the span have specular const plSpan* span = drawable->GetSpan(litList[j]); bool currProj = proj; if (span->fProps & plSpan::kPropProjAsVtx) currProj = false; if (!(currProj && (span->fProps & plSpan::kPropSkipProjection))) { float strength, scale; light->GetStrengthAndScale(span->fWorldBounds, strength, scale); // We can't pitch a light because it's "strength" is zero, because the strength is based // on the center of the span and isn't conservative enough. We can pitch based on the // scale though, since a light scaled down to zero will have no effect no where. if (scale > 0) { plProfile_Inc(FindLightsFound); span->AddLight(light, strength, scale, currProj); } } } plProfile_EndTiming(ApplyMoving); } else if (light->GetProperty(plLightInfo::kLPHasSpecular)) { if (!specList.GetCount()) continue; plProfile_BeginTiming(ApplyToSpec); const hsTArray<int16_t>& litList = light->GetAffected(drawable->GetSpaceTree(), specList, tmpList, drawable->GetNativeProperty(plDrawable::kPropCharacter)); // PUT OVERRIDE FOR KILLING PROJECTORS HERE!!!! bool proj = nil != light->GetProjection(); if (fView.fRenderState & kRenderNoProjection) proj = false; for (size_t j = 0; j < litList.GetCount(); j++) { // Use the light IF light is enabled and // 1) light is movable // 2) span is movable, or // 3) Both the light and the span have specular const plSpan* span = drawable->GetSpan(litList[j]); bool currProj = proj; if (span->fProps & plSpan::kPropProjAsVtx) currProj = false; if (!(currProj && (span->fProps & plSpan::kPropSkipProjection))) { float strength, scale; light->GetStrengthAndScale(span->fWorldBounds, strength, scale); // We can't pitch a light because it's "strength" is zero, because the strength is based // on the center of the span and isn't conservative enough. We can pitch based on the // scale though, since a light scaled down to zero will have no effect no where. if (scale > 0) { plProfile_Inc(FindLightsFound); span->AddLight(light, strength, scale, currProj); } } } plProfile_EndTiming(ApplyToSpec); } else { if (!moveList.GetCount()) continue; plProfile_BeginTiming(ApplyToMoving); const hsTArray<int16_t>& litList = light->GetAffected(drawable->GetSpaceTree(), moveList, tmpList, drawable->GetNativeProperty(plDrawable::kPropCharacter)); // PUT OVERRIDE FOR KILLING PROJECTORS HERE!!!! bool proj = nil != light->GetProjection(); if (fView.fRenderState & kRenderNoProjection) proj = false; for (size_t j = 0; j < litList.GetCount(); j++) { // Use the light IF light is enabled and // 1) light is movable // 2) span is movable, or // 3) Both the light and the span have specular const plSpan* span = drawable->GetSpan(litList[j]); bool currProj = proj; if (span->fProps & plSpan::kPropProjAsVtx) currProj = false; if (!(currProj && (span->fProps & plSpan::kPropSkipProjection))) { float strength, scale; light->GetStrengthAndScale(span->fWorldBounds, strength, scale); // We can't pitch a light because it's "strength" is zero, because the strength is based // on the center of the span and isn't conservative enough. We can pitch based on the // scale though, since a light scaled down to zero will have no effect no where. if (scale > 0) { plProfile_Inc(FindLightsFound); span->AddLight(light, strength, scale, currProj); } } } plProfile_EndTiming(ApplyToMoving); } } plProfile_EndTiming(ApplyActiveLights); IAttachShadowsToReceivers(drawable, visList); plProfile_EndTiming(FindLights); }