void    plEAXListener::ProcessMods( hsTArray<plEAXListenerMod *> &modArray )
{
#ifdef EAX_SDK_AVAILABLE
    int     i;
    float   totalStrength;
    hsBool  firstOne;

    plEAXListenerMod        *thisBigRegion = nil;
    EAXLISTENERPROPERTIES   finalProps;
    static int oldTime = timeGetTime();     // Get starting time
    int newTime;
    hsBool bMorphing = false;

    static plStatusLog  *myLog = nil;

    if( myLog == nil && plgAudioSys::AreExtendedLogsEnabled() )
        myLog = plStatusLogMgr::GetInstance().CreateStatusLog( 30, "EAX Reverbs", plStatusLog::kFilledBackground | plStatusLog::kDeleteForMe | plStatusLog::kDontWriteFile );
    else if( myLog != nil && !plgAudioSys::AreExtendedLogsEnabled() )
    {
        delete myLog;
        myLog = nil;
    }

    if( myLog != nil )
        myLog->Clear();

    if( modArray.GetCount() != fLastModCount )
    {
        kDebugLog "Clearing cache..." );
        ClearProcessCache();    // Code path changed, clear the entire cache
        fLastModCount = modArray.GetCount();
    }
Esempio n. 2
0
void plCullNode::ITakeHalfPoly(const plCullPoly& srcPoly, 
                               const hsTArray<int>& vtxIdx, 
                               const hsBitVector& onVerts, 
                               plCullPoly& outPoly) const
{
    if( vtxIdx.GetCount() > 2 )
    {
        int i;
        for( i = 0; i < vtxIdx.GetCount(); i++ )
        {
            int next = i < vtxIdx.GetCount()-1 ? i+1 : 0;
            int last = i ? i-1 : vtxIdx.GetCount()-1;

            // If these 3 verts are all on the plane, we may have created a collinear vertex (the middle one)
            // which we now want to skip.
            if( onVerts.IsBitSet(vtxIdx[i]) && onVerts.IsBitSet(vtxIdx[last]) && onVerts.IsBitSet(vtxIdx[next]) )
            {
#if 0 // FISH
                float dot = hsVector3(&srcPoly.fVerts[vtxIdx[last]], &srcPoly.fVerts[vtxIdx[i]]).InnerProduct(hsVector3(&srcPoly.fVerts[vtxIdx[next]], &srcPoly.fVerts[vtxIdx[i]]));
                if( dot <= 0 )
#endif // FISH
                    continue;
            }
            if( srcPoly.fClipped.IsBitSet(vtxIdx[i])
                ||(onVerts.IsBitSet(vtxIdx[i]) && onVerts.IsBitSet(vtxIdx[next])) )
                    outPoly.fClipped.SetBit(outPoly.fVerts.GetCount());
            outPoly.fVerts.Append(srcPoly.fVerts[vtxIdx[i]]);
        }
    }
    else
    {
        // Just need a break point
        hsStatusMessage("Under 2"); // FISH
    }
}
Esempio n. 3
0
void plMorphDelta::SetDeltas(int iSpan, const hsTArray<plVertDelta>& deltas, int numUVWChans, const hsPoint3* uvws)
{
    AllocDeltas(iSpan, deltas.GetCount(), numUVWChans);
    if( deltas.GetCount() )
    {
        HSMemory::BlockMove(&deltas[0], fSpans[iSpan].fDeltas.AcquireArray(), deltas.GetCount() * sizeof(plVertDelta));

        if( numUVWChans )
            HSMemory::BlockMove(uvws, fSpans[iSpan].fUVWs, deltas.GetCount() * numUVWChans * sizeof(*uvws));
    }
}
Esempio n. 4
0
// MorphDelta - ComputeDeltas
void plMorphDelta::ComputeDeltas(const hsTArray<plAccessSpan>& base, const hsTArray<plAccessSpan>& moved)
{
    SetNumSpans(base.GetCount());

    // For each span
    {
        // for( i = 0; i < numVerts; i++ )
        {
            // NOTE: we want to discard zero deltas, but a
            // delta in any channel forces us to save the whole thing.
            // But we don't want to compare to zero (because we'll end
            // up with a lot of near zero deltas), but the epsilon we
            // compare to needs to be different for comparing something
            // like a normal delta and a position delta.
            //
            // For position, normal, color and all uvws
            // Calc del and delLenSq
            // If any delLenSq big enough, set nonZero to true
            // If nonZero
            {
                // Append to deltas (i, del's)
            }
        }
    }
}
Esempio n. 5
0
static int ISearchLayerRecur(hsGMaterial* mat, const ST::string &segName, hsTArray<plKey>& keys)
{
    ST::string name = ( segName.compare( ENTIRE_ANIMATION_NAME ) == 0 ) ? ST::null : segName;
    int i;
    for( i = 0; i < mat->GetNumLayers(); i++ )
        ISearchLayerRecur(mat->GetLayer(i), name, keys);
    return keys.GetCount();
}
Esempio n. 6
0
void plSceneNode::Harvest(plVolumeIsect* isect, hsTArray<plDrawVisList>& levList)
{
    static hsTArray<int16_t> visList;
    visList.SetCount(0);
    GetSpaceTree()->HarvestLeaves(isect, visList);
    static hsTArray<int16_t> visSpans;
    visSpans.SetCount(0);

    int i;
    for( i = 0; i < visList.GetCount(); i++ )
    {
        int idx = visList[i];
        fDrawPool[idx]->GetSpaceTree()->HarvestLeaves(isect, visSpans);
        if( visSpans.GetCount() )
        {
            plDrawVisList* drawVis = levList.Push();
            drawVis->fDrawable = fDrawPool[idx];
            drawVis->fVisList.Swap(visSpans);
        }
    }
}
void plMorphSequence::IRenormalize(hsTArray<plAccessSpan>& dst) const
{
    int i;
    for( i = 0; i < dst.GetCount(); i++ )
    {
        hsAssert(dst[i].HasAccessVtx(), "Come on, everyone has vertices");
        plAccessVtxSpan& accVtx = dst[i].AccessVtx();
        int j;
        for( j = 0; j < accVtx.VertCount(); j++ )
        {
            hsFastMath::Normalize(accVtx.Normal(j));
        }
    }
}
Esempio n. 8
0
bool plGeoSpanDice::Dice(hsTArray<plGeometrySpan*>& spans) const
{
    int startingCount = spans.GetCount();

    hsTArray<plGeometrySpan*> out;
    hsTArray<plGeometrySpan*> next;

    while(spans.GetCount())
    {
        int i;
        for( i = 0; i < spans.GetCount(); i++ )
        {
            if( !IHalf(spans[i], next) )
            {
                out.Append(spans[i]);
            }
        }
        spans.Swap(next);
        next.SetCount(0);
    }
    spans.Swap(out);

    return spans.GetCount() != startingCount;
}
Esempio n. 9
0
void plInterMeshSmooth::FindEdges(hsTArray<plSpanHandle>& sets, hsTArray<uint16_t>* edgeVerts)
{
    int i;
    for( i = 0; i < sets.GetCount(); i++ )
    {
        const plSpan* span = sets[i].fDrawable->GetSpan(sets[i].fSpanIdx);
        if( !(span->fTypeMask & plSpan::kIcicleSpan) )
            continue;

        uint32_t nTris = sets[i].fDrawable->CvtGetNumTris(sets[i].fSpanIdx);
        uint16_t* idxList = sets[i].fDrawable->CvtGetIndexList(sets[i].fSpanIdx);
        uint32_t maxVertIdx = sets[i].fDrawable->CvtGetNumVerts(sets[i].fSpanIdx)-1;

        FindEdges(maxVertIdx, nTris, idxList, edgeVerts[i]);
    }
}
Esempio n. 10
0
bool plPipelineViewSettings::SubmitOccluders(const hsTArray<const plCullPoly*>& polyList)
{
    fCullPolys.SetCount(0);
    fCullHoles.SetCount(0);
    int i;
    for (i = 0; i < polyList.GetCount(); i++)
    {
        if (polyList[i]->IsHole())
            fCullHoles.Append(polyList[i]);
        else
            fCullPolys.Append(polyList[i]);
    }
    fCullTreeDirty = true;

    return true;
}
Esempio n. 11
0
void plInterMeshSmooth::FindSharedVerts(hsPoint3& searchPos, plSpanHandle& set, hsTArray<uint16_t>& edgeVerts, hsTArray<uint16_t>& shareVtx, hsVector3& normAccum)
{
    int i;
    for( i = 0; i < edgeVerts.GetCount(); i++ )
    {
        hsPoint3 pos = GetPosition(set, edgeVerts[i]);
        hsVector3 norm = GetNormal(set, edgeVerts[i]);
        if( searchPos == pos )
        {
            if( norm.InnerProduct(normAccum) > fMinNormDot )
            {
                shareVtx.Append(edgeVerts[i]);
                normAccum += norm;
            }
        }
    }
}
Esempio n. 12
0
void pl3DPipeline::IAttachSlaveToReceivers(int which, plDrawableSpans* drawable, const hsTArray<int16_t>& visList)
{
    plShadowSlave* slave = fShadows[which];

    // Whether the drawable is a character affects which lights/shadows affect it.
    bool isChar = drawable->GetNativeProperty(plDrawable::kPropCharacter);

    // If the shadow is part of a light group, it gets handled in ISetShadowFromGroup.
    // Unless the drawable is a character (something that moves around indeterminately,
    // like the avatar or a physical object), and the shadow affects all characters.
    if (slave->ObeysLightGroups() && !(slave->IncludesChars() && isChar))
        return;

    // Do a space tree harvest looking for spans that are visible and whose bounds
    // intercect the shadow volume.
    plSpaceTree* space = drawable->GetSpaceTree();

    static hsBitVector cache;
    cache.Clear();
    space->EnableLeaves(visList, cache);

    static hsTArray<int16_t> hitList;
    hitList.SetCount(0);
    space->HarvestEnabledLeaves(slave->fIsect, cache, hitList);

    // For the visible spans that intercect the shadow volume, attach the shadow
    // to all appropriate for receiving this shadow map.
    for (size_t i = 0; i < hitList.GetCount(); i++)
    {
        const plSpan* span = drawable->GetSpan(hitList[i]);
        hsGMaterial* mat = drawable->GetMaterial(span->fMaterialIdx);

        // Check that the span isn't flagged as unshadowable, or has
        // a material that we can't shadow onto.
        if (!IReceivesShadows(span, mat))
            continue;

        // Check for self shadowing. If the shadow doesn't want self shadowing,
        // and the span is part of the shadow caster, then skip.
        if (!IAcceptsShadow(span, slave))
            continue;

        // Add it to this span's shadow list for this frame.
        span->AddShadowSlave(fShadows[which]->fIndex);
    }
}
Esempio n. 13
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. 14
0
void plInterMeshSmooth::SmoothNormals(hsTArray<plSpanHandle>& sets)
{
    hsTArray<uint16_t>* shareVtx = new hsTArray<uint16_t>[sets.GetCount()];
    hsTArray<uint16_t>* edgeVerts = new hsTArray<uint16_t>[sets.GetCount()];
    FindEdges(sets, edgeVerts);

    int i;
    for( i = 0; i < sets.GetCount()-1; i++ )
    {
        int j;
        for( j = edgeVerts[i].GetCount()-1; j >= 0; --j )
        {
            hsPoint3 pos = GetPosition(sets[i], edgeVerts[i][j]);
            hsVector3 normAccum = GetNormal(sets[i], edgeVerts[i][j]);;

            shareVtx[i].Append(edgeVerts[i][j]);

            int k;
            for( k = i+1; k < sets.GetCount(); k++ )
            {
                FindSharedVerts(pos, sets[k], edgeVerts[k], shareVtx[k], normAccum);
            }

            normAccum.Normalize();
            GetNormal(sets[i], edgeVerts[i][j]) = normAccum;

            for( k = i+1; k < sets.GetCount(); k++ )
            {
                SetNormals(sets[k], shareVtx[k], normAccum);
            }

            // Now remove all the shared verts (which we just processed)
            // from edgeVerts so we don't process them again.
            for( k = i; k < sets.GetCount(); k++ )
            {
                int m;
                for( m = 0; m < shareVtx[k].GetCount(); m++ )
                {
                    int idx = edgeVerts[k].Find(shareVtx[k][m]);
                    hsAssert(idx != edgeVerts[k].kMissingIndex, "Lost vertex between find and remove");
                    edgeVerts[k].Remove(idx);
                }
                shareVtx[k].SetCount(0);
            }
        }
    }

    delete [] shareVtx;
    delete [] edgeVerts;
}
Esempio n. 15
0
void plSceneNode::CollectForRender(plPipeline* pipe, hsTArray<plDrawVisList>& levList, plVisMgr* visMgr)
{
    static hsTArray<int16_t> visList;
    visList.SetCount(0);
    pipe->HarvestVisible(GetSpaceTree(), visList);
    static hsTArray<int16_t> visSpans;
    visSpans.SetCount(0);

    int i;
    for( i = 0; i < visList.GetCount(); i++ )
    {
        int idx = visList[i];
        if( pipe->PreRender(fDrawPool[idx], visSpans, visMgr) )
        {
            plDrawVisList* drawVis = levList.Push();
            drawVis->fDrawable = fDrawPool[idx];
            drawVis->fVisList.Swap(visSpans);
        }
    }
}
Esempio n. 16
0
void hsVertexShader::ShadeNode(INode* node, hsMatrix44& l2w, hsMatrix44& w2l, hsTArray<plGeometrySpan *> &spans)
{
    // If we're flagged for WaterColor, our vertex colors are already done.
    if( ((plMaxNodeBase*)node)->GetCalcEdgeLens() || node->UserPropExists("XXXWaterColor") )
        return;

    fLightMapGen->InitNode(node);

    fLocalToWorld = l2w;
    hsMatrix44 tempMatrix = w2l; // l2w's inverse
    tempMatrix.GetTranspose( &fNormalToWorld ); // Inverse-transpose of the fLocalToWorld matrix, 
    
    int         i;
    for( i = 0; i < spans.GetCount(); i++ )
        IShadeSpan( spans[ i ], node);
    
    fLightMapGen->DeInitNode();

    fShaded++;
}
Esempio n. 17
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. 18
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);
}
uint32_t  plDrawableSpans::AddDISpans( hsTArray<plGeometrySpan *> &spans, uint32_t index )
{
    int             i;
    uint32_t          spanIdx;
    plSpan          *span;
    hsBounds3Ext    bounds;


    /// Do garbage cleanup first
    if( fNeedCleanup )
        IRemoveGarbage();

    if (index == (uint32_t)-1) // need a new one
    {
        /// Create a lookup entry
        index = fDIIndices.GetCount();
        fDIIndices.Append( new plDISpanIndex );
        fDIIndices[ index ]->fFlags = plDISpanIndex::kNone;
    }
    plDISpanIndex   *spanLookup = fDIIndices[ index ];


    /// Add the geometry spans to our list. Also add our internal span
    /// copies
    for( i = 0; i < spans.GetCount(); i++ )
    {
        spanLookup->Append( fSourceSpans.GetCount() );
        spans[ i ]->fSpanRefIndex = fSourceSpans.GetCount();
        fSourceSpans.Append( spans[ i ] );  

        spanIdx = fIcicles.GetCount();
        fIcicles.Append( plIcicle() );
        plIcicle *icicle = &fIcicles[ spanIdx ];
        span = (plSpan *)icicle;

        /// Set common stuff
        IAssignMatIdxToSpan( span, spans[ i ]->fMaterial );
        span->fLocalToWorld = spans[ i ]->fLocalToWorld;
        span->fWorldToLocal = spans[ i ]->fWorldToLocal;
        span->fProps |= ( spans[ i ]->fProps & plGeometrySpan::kPropRunTimeLight ) ? plSpan::kPropRunTimeLight : 0;
        if( spans[i]->fProps & plGeometrySpan::kPropNoShadowCast )
            span->fProps |= plSpan::kPropNoShadowCast;
        if( spans[i]->fProps & plGeometrySpan::kPropNoShadow )
            span->fProps |= plSpan::kPropNoShadow;
        if( spans[i]->fProps & plGeometrySpan::kPropForceShadow )
            span->fProps |= plSpan::kPropForceShadow;
        if( spans[i]->fProps & plGeometrySpan::kPropReverseSort )
            span->fProps |= plSpan::kPropReverseSort;
        if( spans[i]->fProps & plGeometrySpan::kPartialSort )
            span->fProps |= plSpan::kPartialSort;
        if( spans[i]->fProps & plGeometrySpan::kVisLOS )
        {
            span->fProps |= plSpan::kVisLOS;
            fProps |= plDrawable::kPropHasVisLOS;
        }

        span->fNumMatrices = spans[ i ]->fNumMatrices;
        span->fBaseMatrix = spans[ i ]->fBaseMatrix;
        span->fLocalUVWChans = spans[i]->fLocalUVWChans;
        span->fMaxBoneIdx = spans[i]->fMaxBoneIdx;
        span->fPenBoneIdx = (uint16_t)(spans[i]->fPenBoneIdx);

        bounds = spans[ i ]->fLocalBounds;
        span->fLocalBounds = bounds;
        bounds.Transform( &span->fLocalToWorld );
        span->fWorldBounds = bounds;
        span->fFogEnvironment = spans[ i ]->fFogEnviron;

        /// Add to our source indices
        fSpans.Append( span );
        fSpanSourceIndices.Append( spanIdx );
    }

    /// Rebuild the pointer array
    IRebuildSpanArray();

    SetSpaceTree(nil);

    fOptimized = false;

    return index;
}
Esempio n. 20
0
// MorphDelta - ComputeDeltas
void plMorphDelta::ComputeDeltas(const hsTArray<plGeometrySpan*>& base, const hsTArray<plGeometrySpan*>& moved, const hsMatrix44& d2b, const hsMatrix44& d2bTInv)
{
    SetNumSpans(base.GetCount());

    hsPoint3 delUVWs[8];

    // For each span
    int iSpan;
    for( iSpan = 0; iSpan < base.GetCount(); iSpan++ )
    {
        plAccessSpan baseAcc;
        plAccessGeometry::Instance()->AccessSpanFromGeometrySpan(baseAcc, base[iSpan]);
        plAccessSpan movedAcc;
        plAccessGeometry::Instance()->AccessSpanFromGeometrySpan(movedAcc, moved[iSpan]);

        plAccPosNormUVWIterator baseIter(&baseAcc.AccessVtx());
        plAccPosNormUVWIterator movedIter(&movedAcc.AccessVtx());


        plMorphSpan& dst = fSpans[iSpan];

        const uint16_t numUVWs = baseAcc.AccessVtx().NumUVWs();

        hsTArray<plVertDelta> deltas;
        hsTArray<hsPoint3> uvws;
        deltas.SetCount(0);
        uvws.SetCount(0);


        int iVert = 0;;
        for( baseIter.Begin(), movedIter.Begin(); baseIter.More(); baseIter.Advance(), movedIter.Advance() )
        {
            // NOTE: we want to discard zero deltas, but a
            // delta in any channel forces us to save the whole thing.
            // But we don't want to compare to zero (because we'll end
            // up with a lot of near zero deltas), but the epsilon we
            // compare to needs to be different for comparing something
            // like a normal delta and a position delta.
            //
            // For position, normal, color and all uvws
            // Calc del and delLenSq
            // If any delLenSq big enough, set nonZero to true
            bool nonZero = false;

            // These are actually min del SQUARED.
            plConst(float) kMinDelPos(1.e-4f); // From Budtpueller's Handbook of Constants
            plConst(float) kMinDelNorm(3.e-2f); // About 10 degrees
            plConst(float) kMinDelUVW(1.e-4f); // From BHC
            hsPoint3 mPos = d2b * *movedIter.Position();
            hsVector3 delPos( &mPos, baseIter.Position());
            float delPosSq = delPos.MagnitudeSquared();
            if( delPosSq > kMinDelPos )
                nonZero = true;
            else
                delPos.Set(0,0,0);


            hsVector3 delNorm = (d2bTInv * *movedIter.Normal()) - *baseIter.Normal();
            float delNormSq = delNorm.MagnitudeSquared();
            if( delNormSq > kMinDelNorm )
                nonZero = true;
            else
                delNorm.Set(0,0,0);

            int i;
            for( i = 0; i < numUVWs; i++ )
            {
                delUVWs[i] = *movedIter.UVW(i) - *baseIter.UVW(i);
                float delUVWSq = delUVWs[i].MagnitudeSquared();
                if( delUVWSq > kMinDelUVW )
                    nonZero = true;
                else
                    delUVWs[i].Set(0,0,0);
            }

            if( nonZero )
            {
                // Append to deltas (i, del's)
                plVertDelta del;
                del.fIdx = iVert;
                del.fPos = delPos;
                del.fNorm = delNorm;
                deltas.Append(del);

                for( i = 0; i < numUVWs; i++ )
                    uvws.Append(delUVWs[i]);
            }
            else
            {
                nonZero = false; // Breakpoint.
            }

            iVert++;
        }
        SetDeltas(iSpan, deltas, numUVWs, uvws.AcquireArray());
    }
}
Esempio n. 21
0
//
// wireframe debug draw method.  
// doesn't use any fancy subdivision or curvature measure when drawing.
// Changes current time.
//
void plAnimPath::IMakeSegment(hsTArray<uint16_t>& idx, hsTArray<hsPoint3>& pos,
                              hsPoint3& p1, hsPoint3& p2)
{
    hsVector3 del(&p2, &p1);
    hsVector3 up;
    up.Set(0,0,1.f);

    const float kOutLength = 0.25f;

    hsVector3 a = del % up;
    float magSq = a.MagnitudeSquared();
    if( magSq < 1.e-3f )
    {
        a.Set(kOutLength, 0, 0);
    }
    else
    {
        a *= hsFastMath::InvSqrtAppr(magSq);
        a *= kOutLength;
    }

    hsVector3 b = a % del;
    hsFastMath::Normalize(b);
    b *= kOutLength;

    hsPoint3 p1out, p2out;

    int baseIdx = pos.GetCount();

    pos.Append(p1);
    pos.Append(p2);

    p1out = p1;
    p1out += a;
    p2out = p2;
    p2out += a;

    pos.Append(p1out);
    pos.Append(p2out);

    p1out += -2.f * a;
    p2out += -2.f * a;

    pos.Append(p1out);
    pos.Append(p2out);

    p1out = p1;
    p1out += b;
    p2out = p2;
    p2out += b;

    pos.Append(p1out);
    pos.Append(p2out);

    p1out += -2.f * b;
    p2out += -2.f * b;

    pos.Append(p1out);
    pos.Append(p2out);

    int i;
    for( i = 0; i < 4; i++ )
    {
        int outIdx = baseIdx + 2 + i * 2;
        idx.Append(baseIdx);
        idx.Append(baseIdx + 1);
        idx.Append(baseIdx + outIdx);

        idx.Append(baseIdx + outIdx);
        idx.Append(baseIdx + 1);
        idx.Append(baseIdx + outIdx + 1);
    }
}
hsBool plMorphSequence::MsgReceive(plMessage* msg)
{
    plRenderMsg* rend = plRenderMsg::ConvertNoRef(msg);
    if( rend )
    {
        // For now, I'm ignoring the target weight stuff for shared meshes.
        // Can always add it in later if desired.
        if( fTgtWgts.GetCount() )
        {
            float delWgt = hsTimer::GetDelSysSeconds() / (kMorphTime > 0 ? kMorphTime : 1.e-3f);
            int i;
            for( i = 0; i < fTgtWgts.GetCount(); i++ )
            {
                float currWgt = GetWeight(fTgtWgts[i].fLayer, fTgtWgts[i].fDelta);
                if( fTgtWgts[i].fWeight < currWgt )
                {
                    if( fTgtWgts[i].fWeight >= (currWgt -= delWgt) )
                        currWgt = fTgtWgts[i].fWeight;
                }
                else if( fTgtWgts[i].fWeight > currWgt )
                {
                    if( fTgtWgts[i].fWeight <= (currWgt += delWgt) )
                        currWgt = fTgtWgts[i].fWeight;
                }
                
                fMorphs[fTgtWgts[i].fLayer].SetWeight(fTgtWgts[i].fDelta, currWgt);

                if( fTgtWgts[i].fWeight == currWgt )
                {
                    fTgtWgts.Remove(i);
                    i--;
                }
            }
            ISetDirty(true);
        }

        if( !(fMorphFlags & kDirty) )
        {
            // We went a whole frame without getting dirty, 
            // we can stop refreshing now.
            plgDispatch::Dispatch()->UnRegisterForExactType(plRenderMsg::Index(), GetKey());

            return true;
        }
        ISetDirty(false);
        if( fMorphFlags & kDirtyIndices )
            IFindIndices();

        if( fMorphFlags & kHaveShared )
        {
            IApplyShared();
        }
        else
        {
            Apply();
        }
        return true;
    }

    plSharedMeshBCMsg *smMsg = plSharedMeshBCMsg::ConvertNoRef(msg);
    if (smMsg)
    {
        if (IGetDrawInterface()->GetKey() == smMsg->GetSender() || IIsUsingDrawable(smMsg->fDraw))
            fMorphFlags |= kDirtyIndices;
    }           

    plGenRefMsg *refMsg = plGenRefMsg::ConvertNoRef(msg);
    if (refMsg)
    {
        plSharedMesh *mesh = plSharedMesh::ConvertNoRef(refMsg->GetRef());
        if (mesh)
        {
            if( refMsg->GetContext() & (plRefMsg::kOnCreate|plRefMsg::kOnRequest) )
            {
                AddSharedMesh(mesh);
            }
            else if( refMsg->GetContext() & plRefMsg::kOnReplace)
            {
                plSharedMesh *oldMesh = plSharedMesh::ConvertNoRef(refMsg->GetOldRef());
                if (oldMesh)
                    RemoveSharedMesh(oldMesh);
                AddSharedMesh(mesh);
            }
            else if( refMsg->GetContext() & (plRefMsg::kOnDestroy|plRefMsg::kOnRemove) )
                RemoveSharedMesh(mesh);             
            
            return true;
        }
    }
    
    return plSingleModifier::MsgReceive(msg);
}
Esempio n. 23
0
void plInterMeshSmooth::SetNormals(plSpanHandle& set, hsTArray<uint16_t>& shareVtx, hsVector3& norm)
{
    int i;
    for( i = 0; i < shareVtx.GetCount(); i++ )
        GetNormal(set, shareVtx[i]) = norm;
}
Esempio n. 24
0
 uint32_t                          GetNumReceivers() const { return fReceivers.GetCount(); }