Esempio n. 1
0
void plWin32StreamingSound::IStreamUpdate()
{
    if(!fReallyPlaying)
        return;

    if(hsTimer::GetMilliSeconds() - fLastStreamingUpdate < STREAMING_UPDATE_MS) // filter out update requests so we aren't doing this more that we need to 
        return;

    plProfile_BeginTiming( StreamSndShoveTime );
    if(fDSoundBuffer)
    {
        if(fDSoundBuffer->BuffersQueued() == 0 && fDataStream->NumBytesLeft() == 0 && !fDSoundBuffer->IsLooping())
        {
            // If we are fading out it's possible that we will hit this multiple times causing this sound to try and fade out multiple times, never allowing it to actually stop
            if(!fStopping)
            {
                fStopping = true;
                Stop();
                plProfile_EndTiming( StreamSndShoveTime );
            }
            return;
        }

        if(!fDSoundBuffer->StreamingFillBuffer(fDataStream))
        {
            plStatusLog::AddLineS("audio.log", "%s Streaming buffer fill failed", GetKeyName().c_str());
        }
    }
    plProfile_EndTiming( StreamSndShoveTime );
}
void plCoordinateInterface::ITransformChanged(hsBool force, uint16_t reasons, hsBool checkForDelay)
{
    plProfile_IncCount(CITrans, 1);
    plProfile_BeginTiming(CITransT);

    // inherit reasons for transform change from our parents
    fReason |= reasons;
    
    uint16_t propagateReasons = fReason;

    hsBool process = !(checkForDelay && GetProperty(kDelayedTransformEval)) || !fDelayedTransformsEnabled;

    if (process)
    {
        if( fState & kTransformDirty )
            force = true;
    }

    if( force )
    {
        IRecalcTransforms();

        plProfile_IncCount(CISet, 1);
        plProfile_BeginTiming(CISetT);
        if( IGetOwner() )
        {
            IGetOwner()->ISetTransform(fLocalToWorld, fWorldToLocal);
        }
        plProfile_EndTiming(CISetT);
        fState &= ~kTransformDirty;     
    }

    plProfile_EndTiming(CITransT);
    if (process)
    {
        int i;
        for( i = 0; i < fChildren.GetCount(); i++ )
        {
            if( fChildren[i] && fChildren[i]->GetVolatileCoordinateInterface() )
                fChildren[i]->GetVolatileCoordinateInterface()->ITransformChanged(force, propagateReasons, checkForDelay);
        }
    }
    else if (force)
    {
        plProfile_IncCount(CIDirty, 1);
        plProfile_BeginTiming(CITransT);
        // Our parent is dirty and we're bailing out on evaluating right now.
        // Need to ensure we'll be evaluated in the delay pass
        plProfile_BeginTiming(CIDirtyT);
        IDirtyTransform();
        plProfile_EndTiming(CIDirtyT);
        plProfile_EndTiming(CITransT);
    }       
}
Esempio n. 3
0
void    plGBufferGroup::ISendStorageToBuffers( plPipeline *pipe, bool adjustForNvidiaLighting )
{
    plProfile_BeginTiming(DrawRefillVertex);

    /// Creating or refreshing?
    for (size_t i = 0; i < fVertBuffStorage.size(); i++)
        pipe->CheckVertexBufferRef(this, i);
    plProfile_EndTiming(DrawRefillVertex);

    plProfile_BeginTiming(DrawRefillIndex);

    for (size_t i = 0; i < fIdxBuffStorage.size(); i++)
        pipe->CheckIndexBufferRef(this, i);

    plProfile_EndTiming(DrawRefillIndex);
}
Esempio n. 4
0
void plPipelineViewSettings::RefreshCullTree()
{
    if (fCullTreeDirty)
    {
        plProfile_BeginTiming(DrawOccBuild);

        fCullTree.Reset();

        fCullTree.SetViewPos(GetViewPositionWorld());

        if (fCullProxy && !fPipeline->IsDebugFlagSet(plPipeDbg::kFlagOcclusionSnap))
        {
            fCullProxy->GetKey()->UnRefObject();
            fCullProxy = nullptr;

            fDrawableTypeMask &= ~plDrawable::kOccSnapProxy;
        }

        bool doCullSnap = fPipeline->IsDebugFlagSet(plPipeDbg::kFlagOcclusionSnap) && !fCullProxy && !fPipeline->GetViewStackSize();
        if( doCullSnap )
        {
            fCullTree.BeginCapturePolys();
            fCullTree.SetVisualizationYon(fTransform.GetYon());
        }
        fCullTree.InitFrustum(fTransform.GetWorldToNDC());
        fCullTreeDirty = false;

        if (fMaxCullNodes)
        {
            int i;
            for (i = 0; i < fCullPolys.GetCount(); i++)
            {
                fCullTree.AddPoly(*fCullPolys[i]);
                if (fCullTree.GetNumNodes() >= fMaxCullNodes)
                    break;
            }
            fCullPolys.SetCount(0);
            plProfile_Set(OccPolyUsed, i);

            for (i = 0; i < fCullHoles.GetCount(); i++)
            {
                fCullTree.AddPoly(*fCullHoles[i]);
            }
            fCullHoles.SetCount(0);
            plProfile_Set(OccNodeUsed, fCullTree.GetNumNodes());
        }

        if (doCullSnap)
        {
            fCullTree.EndCapturePolys();
            MakeOcclusionSnap();
        }

        plProfile_EndTiming(DrawOccBuild);
    }
}
hsBool plAVIWriterImp::MsgReceive(plMessage* msg)
{
#if HS_BUILD_FOR_WIN32
    plRenderMsg* renderMsg = plRenderMsg::ConvertNoRef(msg);
    if (renderMsg)
    {
        plProfile_BeginTiming(AviCapture);

        ICaptureFrame(renderMsg->Pipeline());
        plProfile_EndTiming(AviCapture);

    }
#endif

    return hsKeyedObject::MsgReceive(msg);
}
void plCoordinateInterface::IRecalcTransforms()
{
    plProfile_IncCount(CIRecalc, 1);
    plProfile_BeginTiming(CIRecalcT);
    if( fParent )
    {
        fLocalToWorld = IMatrixMul34(fParent->GetLocalToWorld(), fLocalToParent);
        fWorldToLocal = IMatrixMul34(fParentToLocal, fParent->GetWorldToLocal());
    }
    else
    {
        fLocalToWorld = fLocalToParent;
        fWorldToLocal = fParentToLocal;
    }
    plProfile_EndTiming(CIRecalcT);
}
Esempio n. 7
0
bool plPipelineViewSettings::HarvestVisible(plSpaceTree* space, hsTArray<int16_t>& visList)
{
    if (!space)
        return false;

    space->SetViewPos(GetViewPositionWorld());

    space->Refresh();

    if (fCullTreeDirty)
        RefreshCullTree();

    plProfile_BeginTiming(Harvest);
    fCullTree.Harvest(space, visList);
    plProfile_EndTiming(Harvest);

    return visList.GetCount() != 0;
}
Esempio n. 8
0
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);
}
Esempio n. 9
0
void pl3DPipeline::BeginVisMgr(plVisMgr* visMgr)
{
    // Make Light Lists /////////////////////////////////////////////////////
    // Look through all the current lights, and fill out two lists.
    // Only active lights (not disabled, not exactly black, and not
    // ignored because of visibility regions by plVisMgr) will
    // be considered.
    // The first list is lights that will affect the avatar and similar
    // indeterminately mobile (physical) objects - fCharLights.
    // The second list is lights that aren't restricted by light include
    // lists.
    // These two abbreviated lists will be further refined for each object
    // and avatar to find the strongest 8 lights which affect that object.
    // A light with an include list, or LightGroup Component) has
    // been explicitly told which objects it affects, so they don't
    // need to be in the search lists.
    // These lists are only constructed once per render, but searched
    // multiple times

    plProfile_BeginTiming(FindSceneLights);
    fCharLights.SetCount(0);
    fVisLights.SetCount(0);
    if (visMgr)
    {
        const hsBitVector& visSet = visMgr->GetVisSet();
        const hsBitVector& visNot = visMgr->GetVisNot();
        plLightInfo* light;

        for (light = fActiveLights; light != nullptr; light = light->GetNext())
        {
            plProfile_IncCount(LightActive, 1);
            if (!light->IsIdle() && !light->InVisNot(visNot) && light->InVisSet(visSet))
            {
                plProfile_IncCount(LightOn, 1);
                if (light->GetProperty(plLightInfo::kLPHasIncludes))
                {
                    if (light->GetProperty(plLightInfo::kLPIncludesChars))
                        fCharLights.Append(light);
                }
                else
                {
                    fVisLights.Append(light);
                    fCharLights.Append(light);
                }
            }
        }
    }
    else
    {
        plLightInfo* light;
        for (light = fActiveLights; light != nullptr; light = light->GetNext())
        {
            plProfile_IncCount(LightActive, 1);
            if (!light->IsIdle())
            {
                plProfile_IncCount(LightOn, 1);
                if (light->GetProperty(plLightInfo::kLPHasIncludes))
                {
                    if (light->GetProperty(plLightInfo::kLPIncludesChars))
                        fCharLights.Append(light);
                }
                else
                {
                    fVisLights.Append(light);
                    fCharLights.Append(light);
                }
            }
        }
    }
    plProfile_IncCount(LightVis, fVisLights.GetCount());
    plProfile_IncCount(LightChar, fCharLights.GetCount());

    plProfile_EndTiming(FindSceneLights);
}
Esempio n. 10
0
void hsAffineParts::ComposeInverseMatrix(hsMatrix44 *out) const
{
    plProfile_BeginTiming(Compose);
#ifndef PL_OPTIMIZE_COMPOSE
    // Built U matrix
    hsMatrix44 U;
    fU.Conjugate().MakeMatrix(&U);

    // Build scale factor matrix
    hsMatrix44 K;
    hsVector3 invK;
    invK.Set(hsInvert(fK.fX),hsInvert(fK.fY),hsInvert(fK.fZ));
    K.MakeScaleMat(&invK);

    // Build Utranspose matrix
    hsMatrix44 Utp;
    U.GetTranspose(&Utp);

    // Build R matrix
    hsMatrix44 R;
    fQ.Conjugate().MakeMatrix(&R);

    // Build flip matrix
//  hsAssert(fF == 1.0 || fF == -1.0, "Invalid flip portion of affine parts");
    hsMatrix44 F;
    if (fF==-1.0)
    {
        hsVector3 s;
        s.Set(-1,-1,-1);
        F.MakeScaleMat(&s);
    }
    else
        F.Reset();

    // Build translate matrix
    hsMatrix44 T;
    T.MakeTranslateMat(&-fT);

    //
    // Concat mats
    //
    *out = Utp * K;
    *out = (*out) * U;
    *out = (*out) * R;
    *out = (*out) * F;
    *out = (*out) * T;
#else // PL_OPTIMIZE_COMPOSE
    // Same kind of thing here, except now M = Ut K U R F T
    // and again
    // T =  |1  0   0   Tx|
    //      |0  1   0   Ty|
    //      |0  0   1   Tz|
    // F =  |f  0   0   0|
    //      |0  f   0   0|
    //      |0  0   f   0|, where f is either 1 or -1
    // R =  |R00    R01 R02 0|
    //      |R10    R11 R12 0|
    //      |R20    R21 R22 0|
    // U =  |U00    U01 U02 0|
    //      |U10    U11 U12 0|
    //      |U20    U21 U22 0|
    // K =  |Sx     0   0   0|
    //      |0      Sy  0   0|
    //      |0      0   Sz  0|
    // Ut = |U00    U10 U20 0|
    //      |U01    U11 U21 0|
    //      |U02    U12 U22 0|, where Uij is from matrix U
    //
    // So, Ut * K =
    //      |U00*Sx     U10*Sy  U20*Sz  0|
    //      |U01*Sx     U11*Sy  U21*Sz  0|
    //      |U02*Sx     U12*Sy  U22*Sz  0|
    //
    // (Ut * K) * U = UK =
    //      |Ut0*S dot Ut0  Ut0*S dot Ut1   Ut0*S dot Ut2   0|
    //      |Ut1*S dot Ut0  Ut1*S dot Ut1   Ut1*S dot Ut2   0|
    //      |Ut2*S dot Ut0  Ut2*S dot Ut1   Ut2*S dot Ut2   0|
    //
    // (((Ut * K) * U) * R)[i][j] = UK[i] dot Rc[j]
    //
    // Again we'll stuff the flip into the scale.
    //
    // Now, because the T is on the other end of the concat (closest
    // to the vertex), we can't just stuff it in. If Mr is the
    // rotation part of the final matrix (Ut * K * U * R * F), then
    // the translation components M[i][3] = Mr[i] dot T.
    //
    //
    hsVector3 Ut[3];
    QuatTo3VectorsTranspose(fU.Conjugate(), Ut);

    int i, j;

    hsVector3 invK;
    invK.Set(hsInvert(fK.fX),hsInvert(fK.fY),hsInvert(fK.fZ));
    hsVector3 UK[3];
    for( i = 0; i < 3; i++ )
    {
        for( j = 0; j < 3; j++ )
        {
            // SUt[i] = (Ut[i].fX * invK.fX, Ut[i].fY * invK.fY, Ut[i].fZ * invK.fZ)
            // So SUt[i].InnerProduct(Ut[j]) ==
            //      Ut[i].fX * invK.fX * Ut[j].fX
            //          + Ut[i].fY * invK.fY * Ut[j].fY
            //          + Ut[i].fZ * invK.fZ * Ut[j].fZ

            UK[i][j] = Ut[i].fX * invK.fX * Ut[j].fX
                       + Ut[i].fY * invK.fY * Ut[j].fY
                       + Ut[i].fZ * invK.fZ * Ut[j].fZ;
        }
    }

    hsVector3 Rt[3];
    QuatTo3VectorsTranspose(fQ.Conjugate(), Rt);

    float f = fF < 0 ? -1.f : 1.f;
    for( i = 0; i < 3; i++ )
    {
        for( j = 0; j < 3; j++ )
        {
            out->fMap[i][j] = UK[i].InnerProduct(Rt[j]) * f;
        }

        out->fMap[i][3] = -(fT.InnerProduct((hsPoint3*)(&out->fMap[i])));
    }

    out->fMap[3][0] = out->fMap[3][1] = out->fMap[3][2] = 0.f;
    out->fMap[3][3] = 1.f;
    out->NotIdentity();

#endif // PL_OPTIMIZE_COMPOSE
    plProfile_EndTiming(Compose);
}
Esempio n. 11
0
//
// Create an affine matrix from the various parts
//
// AffineParts:
//    Vector t; /* Translation components */
//    Quat   q; /* Essential rotation     */
//    Quat   u; /* Stretch rotation   */
//    Vector k; /* Stretch factors    */
//    float  f; /* Sign of determinant    */
//
// A matrix M is decomposed by : M = T F R U K Utranspose.
//      T is the translate mat.
//      F is +-Identity (to flip the rotation or not).
//      R is the rot matrix.
//      U is the stretch matrix.
//      K is the scale factor matrix.
//
void hsAffineParts::ComposeMatrix(hsMatrix44 *out) const
{
    plProfile_BeginTiming(Compose);
#ifndef PL_OPTIMIZE_COMPOSE
    // Built U matrix
    hsMatrix44 U;
    fU.MakeMatrix(&U);

    // Build scale factor matrix
    hsMatrix44 K;
    K.MakeScaleMat(&fK);

    // Build Utranspose matrix
    hsMatrix44 Utp;
    U.GetTranspose(&Utp);

    // Build R matrix
    hsMatrix44 R;
    fQ.MakeMatrix(&R);

    // Build flip matrix
//  hsAssert(fF == 1.0 || fF == -1.0, "Invalid flip portion of affine parts");
    hsMatrix44 F;
    if (fF==-1.0)
    {
        hsVector3 s;
        s.Set(-1,-1,-1);
        F.MakeScaleMat(&s);
    }
    else
        F.Reset();

    // Build translate matrix
    hsMatrix44 T;
    T.MakeTranslateMat(&fT);

    //
    // Concat mats
    //
    *out =  K * Utp;
    *out =  U * (*out);
    *out =  R * (*out);     // Q
    *out =  F * (*out);
    *out =  T * (*out);     // Translate happens last
#else // PL_OPTIMIZE_COMPOSE
    // M = T F R U K Ut,
    // but these are mostly very sparse matrices. So rather
    // than construct the full 6 matrices and concatenate them,
    // we'll work out by hand what the non-zero results will be.
    // T =  |1  0   0   Tx|
    //      |0  1   0   Ty|
    //      |0  0   1   Tz|
    // F =  |f  0   0   0|
    //      |0  f   0   0|
    //      |0  0   f   0|, where f is either 1 or -1
    // R =  |R00    R01 R02 0|
    //      |R10    R11 R12 0|
    //      |R20    R21 R22 0|
    // U =  |U00    U01 U02 0|
    //      |U10    U11 U12 0|
    //      |U20    U21 U22 0|
    // K =  |Sx     0   0   0|
    //      |0      Sy  0   0|
    //      |0      0   Sz  0|
    // Ut = |U00    U10 U20 0|
    //      |U01    U11 U21 0|
    //      |U02    U12 U22 0|, where Uij is from matrix U
    //
    // So, K * Ut =
    //      |Sx*U00 Sx*U10  Sx*U20  0|
    //      |Sy*U01 Sy*U11  Sy*U21  0|
    //      |Sz*U02 Sz*U12  Sz*U22  0|
    //
    // U * (K * Ut) =
    //      | U0 dot S*U0   U0 dot S*U1 U0 dot S*U2 0|
    //      | U1 dot S*U0   U1 dot S*U1 U1 dot S*U2 0|
    //      | U2 dot S*U0   U2 dot S*U1 U2 dot S*U2 0|
    //
    // Let's call that matrix UK
    //
    // Now R * U * K * Ut = R * UK =
    //      | R0 dot UKc0   R0 dot UKc1 R0 dot UKc2     0|
    //      | R1 dot UKc0   R1 dot UKc1 R1 dot UKc2     0|
    //      | R2 dot UKc0   R2 dot UKc1 R2 dot UKc2     0|, where UKci is column i from UK
    //
    // if f is -1, we negate the matrix we have so far, else we don't. We can
    // accomplish this cleanly by just negating the scale vector S if f == -1.
    //
    // Since the translate is last, we can just stuff it into the 4th column.
    //
    // Since we only ever use UK as column vectors, we'll just construct it
    // into 3 vectors representing the columns.
    //
    // The quat MakeMatrix function is pretty efficient, but it does a little more work
    // than it has to filling out the whole matrix when we only need the 3x3 rotation,
    // and we'd rather have it in the form of vectors anyway, so we'll use our own
    // quat to 3 vectors function here.

    hsVector3 U[3];
    QuatTo3Vectors(fU, U);

    int i, j;

    hsVector3 UKt[3];
    for( i = 0; i < 3; i++ )
    {
        for( j = 0; j < 3; j++ )
        {
            // SU[j] = (fK.fX * U[j].fX, fK.fY * U[j].fY, fK.fZ * U[j].fZ)
            UKt[j][i] = U[i].fX * fK.fX * U[j].fX
                        + U[i].fY * fK.fY * U[j].fY
                        + U[i].fZ * fK.fZ * U[j].fZ;
        }
    }

    hsVector3 R[3];
    QuatTo3Vectors(fQ, R);

    float f = fF < 0 ? -1.f : 1.f;
    for( i = 0; i < 3; i++ )
    {
        for( j = 0; j < 3; j++ )
        {
            out->fMap[i][j] = R[i].InnerProduct(UKt[j]) * f;
        }

        out->fMap[i][3] = fT[i];
    }

    out->fMap[3][0] = out->fMap[3][1] = out->fMap[3][2] = 0.f;
    out->fMap[3][3] = 1.f;
    out->NotIdentity();

#endif // PL_OPTIMIZE_COMPOSE
    plProfile_EndTiming(Compose);
}
hsBool plLOSDispatch::MsgReceive(plMessage* msg)
{

    plLOSRequestMsg* requestMsg = plLOSRequestMsg::ConvertNoRef(msg);
    if (requestMsg)
    {
        plProfile_BeginTiming(LineOfSight);

        plSimulationMgr* sim = plSimulationMgr::GetInstance();

        plKey worldKey = requestMsg->fWorldKey;
        if (!worldKey)
        {
            plArmatureMod* av = plAvatarMgr::GetInstance()->GetLocalAvatar();
            if ( av && av->GetController() )
                worldKey = av->GetController()->GetSubworld();
        }

        hsPoint3 from = requestMsg->fFrom;
        hsPoint3 at = requestMsg->fTo;

        // requests are always sent in world space, but they might
        // need to be converted to subworld space
        hsMatrix44 l2w, w2l;
        if (worldKey)
        {
            plSceneObject* so = plSceneObject::ConvertNoRef(worldKey->ObjectIsLoaded());
            if (so)
            {
                l2w = so->GetLocalToWorld();
                w2l = so->GetWorldToLocal();
                from = w2l * from;
                at = w2l * at;
            }
        }
        else
        {
            l2w.Reset();
            w2l.Reset();
        }

        NxScene* scene = sim->GetScene(worldKey);

        gMyReport.InitCast(requestMsg->GetRequestType(), requestMsg->GetTestType());

        hsVector3 norm = hsVector3(at - from);
        float dist = norm.Magnitude();
        norm.Normalize();

        NxRay worldRay;
        worldRay.dir = plPXConvert::Vector(norm);
        worldRay.orig = plPXConvert::Point(from);
        //PhysX will complain to log if ray distance is less than or equal to Zero, besides shouldn't  bother throwing 
        // a point, and if we have negative we have some serious problems
        if(dist>0.0f)
        {
            scene->raycastAllShapes(worldRay, gMyReport, NX_ALL_SHAPES, 0xffffffff, dist, NX_RAYCAST_DISTANCE | NX_RAYCAST_IMPACT | NX_RAYCAST_NORMAL);
        }
        else{
            SimLog("%s sent out a LOS request with a ray length of %d.", requestMsg->GetSender()->GetName().c_str(), dist);
        }
        if (gMyReport.GotHit())
        {
            // We got a hit, save off the info
            plMessage* hitMsg = ICreateHitMsg(requestMsg, l2w);

            if (requestMsg->GetCullDB() != plSimDefs::kLOSDBNone)
            {
                // If we have a cull db, adjust the length of the raycast to be from the
                // original point to the object we hit.  If we find anything from the cull
                // db in there, the cast fails.
                float dist = gMyReport.GetDistance();
                if(dist!=0.0)
                {
                    gMyReport.InitCast(requestMsg->GetCullDB(), plLOSRequestMsg::kTestAny);
                    scene->raycastAllShapes(worldRay, gMyReport, NX_ALL_SHAPES, 0xffffffff, dist, NX_RAYCAST_DISTANCE | NX_RAYCAST_IMPACT | NX_RAYCAST_NORMAL);

                    if (gMyReport.GotHit())
                    {
                        delete hitMsg;
                        hitMsg = nil;

                        if (requestMsg->GetReportType() == plLOSRequestMsg::kReportMiss ||
                            requestMsg->GetReportType() == plLOSRequestMsg::kReportHitOrMiss)
                        {
                            ICreateMissMsg(requestMsg)->Send();
                        }
                    }
                }
                else// we are right on top of the object I assume that means we hit it
                {// since PhysX would have complained we will log it anyways. Just so we have a better idea, where this
                    //was happening previously
                    SimLog("%s sent out a LOS request. The second cast for culling was of length 0. ABORTING and assuming hit.", requestMsg->GetSender()->GetName().c_str());
                }

            }

            if (hitMsg &&
                (requestMsg->GetReportType() == plLOSRequestMsg::kReportHit ||
                requestMsg->GetReportType() == plLOSRequestMsg::kReportHitOrMiss))
                hitMsg->Send();
        }
        else
        {
            if (requestMsg->GetReportType() == plLOSRequestMsg::kReportMiss ||
                requestMsg->GetReportType() == plLOSRequestMsg::kReportHitOrMiss)
            {
                ICreateMissMsg(requestMsg)->Send();
            }
        }

        plProfile_EndTiming(LineOfSight);
        gMyReport.ResetHitObj();
        return true;
    }

    return hsKeyedObject::MsgReceive(msg);
}
void    plWin32GroupedSound::IFillCurrentSound( int16_t newCurrent /*= -1*/ )
{
    //void  *dataPtr;
    //uint32_t    dataLength;

    if( !fDSoundBuffer && plgAudioSys::Active() )
        LoadSound( IsPropertySet( kPropIs3DSound ) );

    plProfile_BeginTiming( StaticSndShoveTime );

    // Make sure we're stopped first. Don't want to be filling while we're playing
    Stop();

    if( newCurrent != -1 )
    {
        fCurrentSound = (uint16_t)newCurrent;

        if( fCurrentSound >= fStartPositions.GetCount() )
        {
            // Invalid index!
            hsAssert( false, "Invalid index in plWin32GroupedSound::IFillCurrentSound()" );
            fCurrentSound = -1;
            return;
        }

        // Set our length based on the current sound
        fCurrentSoundLength = IGetSoundbyteLength( fCurrentSound );
        if( fDataBufferKey->ObjectIsLoaded() )
            SetLength( fCurrentSoundLength / ((plSoundBuffer *)fDataBufferKey->ObjectIsLoaded())->GetHeader().fAvgBytesPerSec );
    
        // Update our volume as well
        SetVolume( fVolumes[ fCurrentSound ] );
    }

    if( fDSoundBuffer != nil )
    {
        /// Lock our buffer
        //fDSoundBuffer->Lock( dataLength, dataPtr );

        /// Copy or de-swizzle?
        //if( fDataBuffer->GetHeader().fNumChannels == fNumDestChannels )
        {
            // Just copy
            //memcpy( dataPtr, (uint8_t *)fDataBuffer->GetData() + fStartPositions[ fCurrentSound ], fCurrentSoundLength );
            //dataPtr = (uint8_t *)dataPtr + fCurrentSoundLength;
            //dataLength -= fCurrentSoundLength;
        }
        //else
        {
            // We're extracting a single channel of sound into our sound buffer, so it isn't a straight copy...

            /*plProfile_BeginTiming( StaticSwizzleTime );

            plSoundDeswizzler   deswiz( (uint8_t *)fDataBuffer->GetData() + fStartPositions[ fCurrentSound ], fCurrentSoundLength, 
                                        (uint8_t)(fDataBuffer->GetHeader().fNumChannels), fNumDestBytesPerSample );

            deswiz.Extract( fChannelSelect, dataPtr );

            dataPtr = (uint8_t *)dataPtr + fCurrentSoundLength / fDataBuffer->GetHeader().fNumChannels;
            dataLength -= fCurrentSoundLength / fDataBuffer->GetHeader().fNumChannels;

            plProfile_EndTiming( StaticSwizzleTime );*/
        }

        /// Fill the remaining part with empty space
        //memset( dataPtr, 0, dataLength );

        /// Finally, unlock!
        //fDSoundBuffer->Unlock();
    }

    /// All done!
    plProfile_EndTiming( StaticSndShoveTime );
}
Esempio n. 14
0
void plDispatch::IMsgDispatch()
{
    if( !fMsgDispatchLock.TryLock() )
        return;

    if( fMsgActive )
    {
        fMsgDispatchLock.Unlock();
        return;
    }

    fMsgActive = true;
    int responseLevel=0;

    fMsgCurrentMutex.Lock();

    plMsgWrap* origTail = fMsgTail;
    while((fMsgCurrent = fMsgHead))
    {
        IDequeue(&fMsgHead, &fMsgTail);
        fMsgCurrentMutex.Unlock();

        plMessage* msg = fMsgCurrent->fMsg;
        bool nonLocalMsg = msg && msg->HasBCastFlag(plMessage::kNetNonLocal);

#ifdef HS_DEBUGGING
        int watchIdx = fMsgWatch.Find(msg);
        if( fMsgWatch.kMissingIndex != watchIdx )
        {
            fMsgWatch.Remove(watchIdx);
#if HS_BUILD_FOR_WIN32
            __asm { int 3 }
#endif // HS_BUILD_FOR_WIN32
        }
#endif // HS_DEBUGGING

        static uint64_t startTicks = 0;
        if (plDispatchLogBase::IsLogging())
            startTicks = hsTimer::GetFullTickCount();

        int i, numReceivers=0;
        for( i = 0; fMsgCurrent && i < fMsgCurrent->GetNumReceivers(); i++ )
        {
            const plKey& rcvKey = fMsgCurrent->GetReceiver(i);
            plReceiver* rcv = rcvKey ? plReceiver::ConvertNoRef(rcvKey->ObjectIsLoaded()) : nil;
            if( rcv )
            {
                if (nonLocalMsg)
                {
                    // localOnly objects should not get remote messages
                    plSynchedObject* synchedObj = plSynchedObject::ConvertNoRef(rcv);
                    if (synchedObj && !synchedObj->IsNetSynched() )
                    {
                        continue;
                    }

                    if (plNetObjectDebuggerBase::GetInstance())
                    {   // log net msg if this is a debug object
                        hsKeyedObject* ko = hsKeyedObject::ConvertNoRef(rcv);
                        if (plNetObjectDebuggerBase::GetInstance()->IsDebugObject(ko))
                        {
                            hsLogEntry(plNetObjectDebuggerBase::GetInstance()->LogMsg(
                                plString::Format("<RCV> object:%s, GameMessage %s st=%.3f rt=%.3f",
                                ko->GetKeyName().c_str(), msg->ClassName(), hsTimer::GetSysSeconds(), hsTimer::GetSeconds()).c_str()));
                        }
                    }
                }

#ifndef PLASMA_EXTERNAL_RELEASE
                uint32_t rcvTicks = hsTimer::GetPrecTickCount();

                // Object could be deleted by this message, so we need to log this stuff now
                plString keyname = "(unknown)";
                const char* className = "(unknown)";
                uint32_t clonePlayerID = 0;
                if (plDispatchLogBase::IsLoggingLong())
                {
                    hsKeyedObject* ko = hsKeyedObject::ConvertNoRef(rcv);
                    if (ko)
                    {
                        keyname = ko->GetKeyName();
                        clonePlayerID = ko->GetKey()->GetUoid().GetClonePlayerID();
                        className = ko->ClassName();
                    }
                }
#endif // PLASMA_EXTERNAL_RELEASE

                #ifdef HS_DEBUGGING
                if (msg->GetBreakBeforeDispatch())
                    DebugBreakIfDebuggerPresent();
                #endif
                    
                plProfile_BeginTiming(MsgReceive);
                rcv->MsgReceive(msg);
                plProfile_EndTiming(MsgReceive);

#ifndef PLASMA_EXTERNAL_RELEASE
                if (plDispatchLogBase::IsLoggingLong())
                {
                    rcvTicks = hsTimer::GetPrecTickCount() - rcvTicks;

                    float rcvTime = (float)(hsTimer::PrecTicksToSecs(rcvTicks) * 1000.f);
                    // If the receiver takes more than 5 ms to process its message, log it
                    if (rcvTime > 5.f)
                        plDispatchLogBase::GetInstance()->LogLongReceive(keyname.c_str(), className, clonePlayerID, msg, rcvTime);
                }
#endif // PLASMA_EXTERNAL_RELEASE

                numReceivers++;

                if (fMsgRecieveCallback != nil)
                    fMsgRecieveCallback();
            }
        }

        // for message logging
//      if (plDispatchLogBase::IsLogging())
//      {
//          float sendTime = hsTimer::FullTicksToMs(hsTimer::GetFullTickCount() - startTicks);
//
//          plDispatchLogBase::GetInstance()->DumpMsg(msg, numReceivers, (int)sendTime, responseLevel*2 /* indent */);
//          if (origTail==fMsgCurrent)
//          {   // if we deliver more msgs after this, they must be response msgs
//              responseLevel++;
//              origTail = fMsgTail;
//          }
//      }

        fMsgCurrentMutex.Lock();

        delete fMsgCurrent;
        // TEMP
        fMsgCurrent = (class plMsgWrap *)0xdeadc0de;
    }
Esempio n. 15
0
void plSimulationMgr::Advance(float delSecs)
{
    if (fSuspended)
        return;

    fAccumulator += delSecs;
    if (fAccumulator < kDefaultStepSize)
    {
        // Not enough time has passed to perform a substep.
        plPXPhysicalControllerCore::UpdateNonPhysical(fAccumulator / kDefaultStepSize);
        return;
    }
    else if (fAccumulator > kDefaultMaxDelta)
    {
        if (fExtraProfile)
            Log("Step clamped from %f to limit of %f", fAccumulator, kDefaultMaxDelta);
        fAccumulator = kDefaultMaxDelta;
    }

    ++fStepCount;

    // Perform as many whole substeps as possible saving the remainder in our accumulator.
    int numSubSteps = (int)(fAccumulator / kDefaultStepSize + 0.000001f);
    float delta = numSubSteps * kDefaultStepSize;
    fAccumulator -= delta;

    plProfile_IncCount(StepLen, (int)(delta*1000));
    plProfile_BeginTiming(Step);

    plPXPhysicalControllerCore::Apply(delta);
    
    for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
    {
        NxScene* scene = it->second;
        bool do_advance = true;
        if (fSubworldOptimization)
        {
            plKey world = (plKey)it->first;
            if (world == GetKey())
                world = nil;
            do_advance = plPXPhysicalControllerCore::AnyControllersInThisWorld(world);
        }
        if (do_advance)
        {
            scene->simulate(delta);
            scene->flushStream();
            scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
        }
    }

    plPXPhysicalControllerCore::Update(numSubSteps, fAccumulator / kDefaultStepSize);

    plProfile_EndTiming(Step);
#ifndef PLASMA_EXTERNAL_RELEASE
    if(plSimulationMgr::fDisplayAwakeActors)IDrawActiveActorList();
#endif 
    if (fExtraProfile)
    {
        int contacts = 0, dynActors = 0, dynShapes = 0, awake = 0, stShapes=0, actors=0, scenes=0, controllers=0 ;
        for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
        {
            bool do_advance = true;
            if (fSubworldOptimization)
            {
                plKey world = (plKey)it->first;
                if (world == GetKey())
                    world = nil;
                do_advance = plPXPhysicalControllerCore::AnyControllersInThisWorld(world);
            }
            if (do_advance)
            {
                NxScene* scene = it->second;
                NxSceneStats stats;
                scene->getStats(stats);

                contacts += stats.numContacts;
                dynActors += stats.numDynamicActors;
                dynShapes += stats.numDynamicShapes;
                awake += stats.numDynamicActorsInAwakeGroups;
                stShapes += stats.numStaticShapes;
                actors += stats.numActors;
                scenes += 1;
                controllers += plPXPhysicalControllerCore::NumControllers();
            }
        }

        plProfile_IncCount(Awake, awake);
        plProfile_IncCount(Contacts, contacts);
        plProfile_IncCount(DynActors, dynActors);
        plProfile_IncCount(DynShapes, dynShapes);
        plProfile_IncCount(StaticShapes, stShapes);
        plProfile_IncCount(Actors, actors);
        plProfile_IncCount(Scenes, scenes);
        plProfile_IncCount(Controllers, controllers);
    }

    plProfile_IncCount(AnimatedPhysicals, plPXPhysical::fNumberAnimatedPhysicals);
    plProfile_IncCount(AnimatedActivators, plPXPhysical::fNumberAnimatedActivators);

    fSoundMgr->Update();

    plProfile_BeginTiming(ProcessSyncs);
    IProcessSynchs();
    plProfile_EndTiming(ProcessSyncs);

    plProfile_BeginTiming(UpdateContexts);
    ISendUpdates();
    plProfile_EndTiming(UpdateContexts);
}
Esempio n. 16
0
void plPipelineViewSettings::GetVisibleSpans(plDrawableSpans* drawable, hsTArray<int16_t>& visList, plVisMgr* visMgr)
{
    static hsTArray<int16_t> tmpVis;
    tmpVis.SetCount(0);
    visList.SetCount(0);

    drawable->GetSpaceTree()->SetViewPos(GetViewPositionWorld());

    drawable->GetSpaceTree()->Refresh();

    if (fCullTreeDirty)
        RefreshCullTree();

    const float viewDist = GetViewDirWorld().InnerProduct(GetViewPositionWorld());

    const hsTArray<plSpan *>    &spans = drawable->GetSpanArray();

    plProfile_BeginTiming(Harvest);
    if (visMgr)
    {
        drawable->SetVisSet(visMgr);
        fCullTree.Harvest(drawable->GetSpaceTree(), tmpVis);
        drawable->SetVisSet(nullptr);
    }
    else
    {
        fCullTree.Harvest(drawable->GetSpaceTree(), tmpVis);
    }

    // This is a big waste of time, As a desparate "optimization" pass, the artists
    // insist on going through and marking objects to fade or pop out of rendering
    // past a certain distance. This breaks the batching and requires more CPU to
    // check the objects by distance. Since there is no pattern to the distance at
    // which objects will be told not to draw, there's no way to make this hierarchical,
    // which is what it would take to make it a performance win. So they succeed in
    // reducing the poly count, but generally the frame rate goes _down_ as well.
    // Unfortunately, this technique actually does work in a few key areas, so
    // I haven't been able to purge it.
    if (fPipeline->IsDebugFlagSet(plPipeDbg::kFlagSkipVisDist))
    {
        int i;
        for (i = 0; i < tmpVis.GetCount(); i++)
        {
            if (spans[tmpVis[i]]->fSubType & fSubDrawableTypeMask)
            {
                visList.Append(tmpVis[i]);
            }
        }
    }
    else
    {
        int i;
        for (i = 0; i < tmpVis.GetCount(); i++)
        {
            if (spans[tmpVis[i]]->fSubType & fSubDrawableTypeMask)
            {
                // We'll check here for spans we can discard because they've completely distance faded out.
                // Note this is based on view direction distance (because the fade is), rather than the
                // preferrable distance to camera we sort by.
                float minDist, maxDist;
                if (drawable->GetSubVisDists(tmpVis[i], minDist, maxDist))
                {
                    const hsBounds3Ext& bnd = drawable->GetSpaceTree()->GetNode(tmpVis[i]).fWorldBounds;
                    hsPoint2 depth;
                    bnd.TestPlane(GetViewDirWorld(), depth);

                    if ((0 < minDist + viewDist - depth.fY) ||(0 > maxDist + viewDist - depth.fX))
                        continue;
                }

                visList.Append(tmpVis[i]);
            }
        }
    }
    plProfile_EndTiming(Harvest);
}
Esempio n. 17
0
void plSimulationMgr::Advance(float delSecs)
{
    if (fSuspended)
        return;

    plProfile_IncCount(StepLen, (int)(delSecs*1000));

#ifndef PLASMA_EXTERNAL_RELASE
    uint32_t stepTime = hsTimer::GetPrecTickCount();
#endif
    plProfile_BeginTiming(Step);
    plPXPhysicalControllerCore::UpdatePrestep(delSecs);
    plPXPhysicalControllerCore::UpdatePoststep( delSecs);
    
    for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
    {
        NxScene* scene = it->second;
        bool do_advance = true;
        if (fSubworldOptimization)
        {
            plKey world = (plKey)it->first;
            if (world == GetKey())
                world = nil;
            do_advance = plPXPhysicalControllerCore::AnyControllersInThisWorld(world);
        }
        if (do_advance)
        {
            scene->simulate(delSecs);
            scene->flushStream();
            scene->fetchResults(NX_RIGID_BODY_FINISHED, true);
        }
    }
    plPXPhysicalControllerCore::UpdatePostSimStep(delSecs);

    plProfile_EndTiming(Step);
#ifndef PLASMA_EXTERNAL_RELEASE
    if(plSimulationMgr::fDisplayAwakeActors)IDrawActiveActorList();
#endif 
    if (fExtraProfile)
    {
        int contacts = 0, dynActors = 0, dynShapes = 0, awake = 0, stShapes=0, actors=0, scenes=0, controllers=0 ;
        for (SceneMap::iterator it = fScenes.begin(); it != fScenes.end(); it++)
        {
            bool do_advance = true;
            if (fSubworldOptimization)
            {
                plKey world = (plKey)it->first;
                if (world == GetKey())
                    world = nil;
                do_advance = plPXPhysicalControllerCore::AnyControllersInThisWorld(world);
            }
            if (do_advance)
            {
                NxScene* scene = it->second;
                NxSceneStats stats;
                scene->getStats(stats);

                contacts += stats.numContacts;
                dynActors += stats.numDynamicActors;
                dynShapes += stats.numDynamicShapes;
                awake += stats.numDynamicActorsInAwakeGroups;
                stShapes += stats.numStaticShapes;
                actors += stats.numActors;
                scenes += 1;
                controllers += plPXPhysicalControllerCore::NumControllers();
            }
        }

        plProfile_IncCount(Awake, awake);
        plProfile_IncCount(Contacts, contacts);
        plProfile_IncCount(DynActors, dynActors);
        plProfile_IncCount(DynShapes, dynShapes);
        plProfile_IncCount(StaticShapes, stShapes);
        plProfile_IncCount(Actors, actors);
        plProfile_IncCount(Scenes, scenes);
        plProfile_IncCount(Controllers, controllers);
    }

    plProfile_IncCount(AnimatedPhysicals, plPXPhysical::fNumberAnimatedPhysicals);
    plProfile_IncCount(AnimatedActivators, plPXPhysical::fNumberAnimatedActivators);

    fSoundMgr->Update();

    plProfile_BeginTiming(ProcessSyncs);
    IProcessSynchs();
    plProfile_EndTiming(ProcessSyncs);

    plProfile_BeginTiming(UpdateContexts);
    ISendUpdates();
    plProfile_EndTiming(UpdateContexts);
}
Esempio n. 18
0
bool plWin32StaticSound::LoadSound( bool is3D )
{
    if (fFailed)
        return false;

    if( fPriority > plgAudioSys::GetPriorityCutoff() )
        return false;   // Don't set the failed flag, just return

    if (plgAudioSys::Active() && !fDSoundBuffer)
    {
        // Debug flag #1
        if( fChannelSelect > 0 && plgAudioSys::IsDebugFlagSet( plgAudioSys::kDisableRightSelect ) )
        {
            // Force a fail
            fFailed = true;
            return false;
        }

        // We need it to be resident to read in
        plSoundBuffer::ELoadReturnVal retVal = IPreLoadBuffer(true);
        plSoundBuffer *buffer = (plSoundBuffer *)fDataBufferKey->ObjectIsLoaded();  
        if(!buffer)
        {
            return plSoundBuffer::kError;
        }

        if( retVal == plSoundBuffer::kPending)  // we are still reading data. 
        {
            return true;
        }

        if( retVal == plSoundBuffer::kError )
        {
            plString str = plFormat("Unable to open .wav file {}", fDataBufferKey ? fDataBufferKey->GetName() : "nil");
            IPrintDbgMessage( str.c_str(), true );
            fFailed = true;
            return false;
        }
        
        SetProperty( kPropIs3DSound, is3D );

        plWAVHeader header = buffer->GetHeader();

        // Debug flag #2
        if( fChannelSelect == 0 && header.fNumChannels > 1 && plgAudioSys::IsDebugFlagSet( plgAudioSys::kDisableLeftSelect ) )
        {
            // Force a fail
            fFailed = true;
            return false;
        }
        uint32_t bufferSize = buffer->GetDataLength();

        if( header.fNumChannels > 1 && is3D )
        {
            // We can only do a single channel of 3D sound. So copy over one (later)
            bufferSize              /= header.fNumChannels;
            header.fBlockAlign      /= header.fNumChannels;
            header.fAvgBytesPerSec  /= header.fNumChannels;
            header.fNumChannels = 1;
        }

        bool tryStatic = true;
        // If we want FX, we can't use a static voice, but EAX doesn't fit under that limitation :)
        if( 0 )
            tryStatic = false;

        // Create our DSound buffer (or rather, the wrapper around it)
        fDSoundBuffer = new plDSoundBuffer( bufferSize, header, is3D, IsPropertySet( kPropLooping ), tryStatic );
        if( !fDSoundBuffer->IsValid() )
        {
            plString str = plFormat("Can't create sound buffer for {}.wav. This could happen if the wav file is a stereo file."
                                    " Stereo files are not supported on 3D sounds. If the file is not stereo then please report this error.",
                                    GetFileName());
            IPrintDbgMessage(str.c_str(), true);
            fFailed = true;

            delete fDSoundBuffer;
            fDSoundBuffer = nil;

            return false;
        }
    
        plProfile_BeginTiming( StaticSndShoveTime );

        if(!fDSoundBuffer->FillBuffer(buffer->GetData(), buffer->GetDataLength(), &header))
        {
            delete fDSoundBuffer;
            fDSoundBuffer = nil;
            plStatusLog::AddLineS("audio.log", "Could not play static sound, no voices left %s", GetKeyName().c_str());
            return false;
        }

        plProfile_EndTiming( StaticSndShoveTime );
        IRefreshEAXSettings( true );

        fTotalBytes = bufferSize;

        plProfile_NewMem(MemSounds, fTotalBytes);

        // get pertinent info
        float length = (float)bufferSize / (float)header.fAvgBytesPerSec;
        SetLength(length);

        if( fLoadFromDiskOnDemand && !IsPropertySet( kPropLoadOnlyOnCall ) )
            FreeSoundData();

        return true;
    }
    return false;
}