Exemple #1
0
void    plAnimStealthNode::GetAllStopPoints( hsTArray<float> &out )
{
    if( fCachedSegMap == nil )
        return;

    for (SegmentMap::iterator it = fCachedSegMap->begin(); it != fCachedSegMap->end(); it++)
    {
        SegmentSpec *spec = it->second;
        if( spec->fType == SegmentSpec::kStopPoint )
        {
            out.Append( spec->fStart );
        }
    }
}
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));
        }
    }
}
Exemple #3
0
void plSpanInstance::setPosDeltas(const hsTArray<hsVector3>& verts) {
    delete[] fPosDelta;
    fNumVerts = verts.getSize();
    fPosDelta = new unsigned char[fNumVerts * CalcPosStride(fEncoding)];

    switch (fEncoding.getCode() & plSpanEncoding::kPosMask) {
    case plSpanEncoding::kPos888:
        {
            unsigned char* pp = fPosDelta;
            for (unsigned int i=0; i<fNumVerts; i++) {
                pp[0] = (unsigned char)(verts[i].X / fEncoding.getPosScale());
                pp[1] = (unsigned char)(verts[i].Y / fEncoding.getPosScale());
                pp[2] = (unsigned char)(verts[i].Z / fEncoding.getPosScale());
                pp += 3;
            }
        }
        break;
    case plSpanEncoding::kPos161616:
        {
            unsigned short* pp = (unsigned short*)fPosDelta;
            for (unsigned int i=0; i<fNumVerts; i++) {
                pp[0] = (unsigned short)(verts[i].X / fEncoding.getPosScale());
                pp[1] = (unsigned short)(verts[i].X / fEncoding.getPosScale());
                pp[2] = (unsigned short)(verts[i].X / fEncoding.getPosScale());
                pp += 3;
            }
        }
        break;
    case plSpanEncoding::kPos101010:
        {
            unsigned int* pp = (unsigned int*)fPosDelta;
            for (unsigned int i=0; i<fNumVerts; i++) {
                *pp = ((unsigned int)(verts[i].Z / fEncoding.getPosScale()) & 0x3F) << 20
                    | ((unsigned int)(verts[i].Y / fEncoding.getPosScale()) & 0x3F) << 10
                    | ((unsigned int)(verts[i].X / fEncoding.getPosScale()) & 0x3F);
                pp++;
            }
        }
        break;
    case plSpanEncoding::kPos008:
        {
            unsigned char* pp = fPosDelta;
            for (unsigned int i=0; i<fNumVerts; i++) {
                *pp = (unsigned char)(verts[i].Z / fEncoding.getPosScale());
                pp++;
            }
        }
        break;
    }
}
void plDInputMgr::Init(HINSTANCE hInst, HWND hWnd)
{
    
    HRESULT         hr; 
    hr = DirectInput8Create(hInst, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&fDI->fDInput, NULL); 
    hsAssert(!hr, "failed to initialize directInput!"); 
    // enumerate game controllers
    Pfunc1 fPtr = &plDInputMgr::EnumGamepadCallback;
    int i = 0;
    

    // set up the action mapping
    fDI->fActionFormat = new DIACTIONFORMAT;
    fDI->fActionFormat->dwSize        = sizeof(DIACTIONFORMAT);
    fDI->fActionFormat->dwActionSize  = sizeof(DIACTION);
    fDI->fActionFormat->dwDataSize    = NUM_ACTIONS * sizeof(DWORD);
    fDI->fActionFormat->dwNumActions  = NUM_ACTIONS;
    fDI->fActionFormat->guidActionMap = PL_ACTION_GUID;
    fDI->fActionFormat->dwGenre       = DIVIRTUAL_FIGHTING_THIRDPERSON;
    fDI->fActionFormat->rgoAction     = fActionMap;
    fDI->fActionFormat->dwBufferSize  = 16;
    fDI->fActionFormat->lAxisMin      = -1000;
    fDI->fActionFormat->lAxisMax      = 1000;
    sprintf( fDI->fActionFormat->tszActionMap, "Plasma 2.0 Game Actions" );

    // this call should not work:
    fDI->fDInput->EnumDevices(DI8DEVCLASS_GAMECTRL, fPtr, fDI, DIEDFL_ATTACHEDONLY); 
    
    // apply the mapping to the game controller 
    // this is the correct <but broken> way to apply the action map:
//  Pfunc3 fPtr3 = &plDInputMgr::EnumSuitableDevices;
//  hr = fDI->fDInput->EnumDevicesBySemantics(NULL, fDI->fActionFormat, EnumSuitableDevices, fDI, NULL);

    
    for (i = 0; i < fDI->fSticks.Count(); i++)
    {
        fDI->fSticks[i]->fCaps = new DIDEVCAPS; 
        fDI->fSticks[i]->fCaps->dwSize = sizeof(DIDEVCAPS);
        hr = fDI->fSticks[i]->fDevice->GetCapabilities(fDI->fSticks[i]->fCaps);
        hsAssert(!hr, "Unable to acquire devcaps in DInput Device!"); 
        hr = fDI->fSticks[i]->fDevice->Acquire();
        hsAssert(!hr, "Unable to acquire DInput Device!"); 
    }

    fhWnd = hWnd;
    
    for (i = 0; i < fDI->fSticks.Count(); i++)
        fInputDevice.Append( new plDInputDevice );
}
// Find ALL bindings that could be triggered by this combo. Meaning that if we have multiple
// bindings for a key with different shift/ctrl combinations, we want any that are satisfied with
// the given combo.
// We guarantee that the first binding in the result array is that one with priority.
void plKeyMap::IFindAllBindingsByKey(const plKeyCombo &combo, hsTArray<plKeyBinding*> &result) const
{
    uint32_t i;
    uint8_t bestScore = 0;
    for (i = 0; i < fBindings.GetCount(); i++)
    {
        hsBool s1, s2;
        s1 = fBindings[i]->GetKey1().IsSatisfiedBy(combo);
        s2 = fBindings[i]->GetKey2().IsSatisfiedBy(combo);
        if (s1 || s2)
        {
            uint8_t myScore = 0;
            if (s1)
                myScore = fBindings[i]->GetKey1().fFlags;
            if (s2 && (fBindings[i]->GetKey2().fFlags > myScore))
                myScore = fBindings[i]->GetKey2().fFlags;

            if (myScore >= bestScore)
                result.Insert(0, fBindings[i]);
            else
                result.Append(fBindings[i]);
        }
    }
}
Exemple #6
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]);
    }
}
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;
}
Exemple #8
0
bool    plAnimComponent::GetKeyList( INode *restrictedNode, hsTArray<plKey> &outKeys )
{
    if( restrictedNode != nil )
    {
        if( fMods.find( (plMaxNode *)restrictedNode ) != fMods.end() )
        {
            outKeys.Append( fMods[ (plMaxNode *)restrictedNode ]->GetKey() );
            return true;
        }
        return false;
    }
    else
    {
        hsAssert( false, "DO SOMETHING!" );
        return false;
    }
}
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;
}
Exemple #10
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;
}
Exemple #11
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++;
}
Exemple #12
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);
        }
    }
}
Exemple #13
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);
        }
    }
}
Exemple #14
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;
}
Exemple #15
0
 plMsgWrap&                      AddReceiver(const plKey& rcv) 
                                 { 
                                     hsAssert(rcv, "Trying to send mail to nil receiver");
                                     fReceivers.Append(rcv); return *this;
                                 }
plCullNode::plCullStatus plCullNode::ISplitPoly(const plCullPoly& poly, 
                                                plCullPoly*& innerPoly, 
                                                plCullPoly*& outerPoly) const
{
    static hsTArray<float> depths;
    depths.SetCount(poly.fVerts.GetCount());

    static hsBitVector onVerts;
    onVerts.Clear();

    hsBool someInner = false;
    hsBool someOuter = false;
    hsBool someOn = false;
    int i;
    for( i = 0; i < poly.fVerts.GetCount(); i++ )
    {
        depths[i] = fNorm.InnerProduct(poly.fVerts[i]) + fDist;
        if( depths[i] < -kTolerance )
            someInner = true;
        else if( depths[i] > kTolerance )
            someOuter = true;
        else 
        {
            someOn = true;
            onVerts.SetBit(i);
        }
    }
    if( !(someInner || someOuter) )
    {
        (innerPoly = ScratchPolys().Push())->Init(poly);
        (outerPoly = ScratchPolys().Push())->Init(poly);
        return kSplit;
    }
    else if( !someInner )
    {
        IMarkClipped(poly, onVerts);
        return kClear;
    }
    else if( !someOuter )
    {
        IMarkClipped(poly, onVerts);
        return kCulled;
    }


    // Okay, it's split, now break it into the two polys
    (innerPoly = ScratchPolys().Push())->Init(poly);
    (outerPoly = ScratchPolys().Push())->Init(poly);

    static plCullPoly scrPoly;

    static hsBitVector inVerts;
    static hsBitVector outVerts;

    IBreakPoly(poly, depths,
        inVerts,
        outVerts,
        onVerts,
        scrPoly);

    static hsTArray<int> inPolyIdx;
    inPolyIdx.SetCount(0);
    static hsTArray<int> outPolyIdx;
    outPolyIdx.SetCount(0);

    for( i = 0; i < scrPoly.fVerts.GetCount(); i++ )
    {
        if( inVerts.IsBitSet(i) )
        {
            inPolyIdx.Append(i);
        }
        else if( outVerts.IsBitSet(i) )
        {
            outPolyIdx.Append(i);
        }
        else
        {
            inPolyIdx.Append(i);
            outPolyIdx.Append(i);
        }
    }

    ITakeHalfPoly(scrPoly, inPolyIdx, onVerts, *innerPoly);

    ITakeHalfPoly(scrPoly, outPolyIdx, onVerts, *outerPoly);

    return kSplit;
}
Exemple #17
0
 virtual int proc( ReferenceMaker *rmaker )
 {
     fList.Append( rmaker );
     return DEP_ENUM_CONTINUE;
 }
Exemple #18
0
void plLeafController::setKeys(const hsTArray<hsKeyFrame*>& keys, unsigned int type) {
    DeallocKeys();
    AllocKeys(keys.getSize(), type);
    for (size_t i=0; i<keys.getSize(); i++)
        fKeys[i] = keys[i];
}
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);
}
Exemple #20
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;
}
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);
}
Exemple #22
0
 uint32_t                          GetNumReceivers() const { return fReceivers.GetCount(); }
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;
}
Exemple #24
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);
    }
}
Exemple #25
0
void plLeafController::setEaseControllers(const hsTArray<class plEaseController*>& controllers) {
    DeallocControllers();
    AllocControllers(controllers.getSize());
    for (size_t i=0; i<controllers.getSize(); i++)
        fEaseControllers[i] = controllers[i];
}
Exemple #26
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);
}
Exemple #27
0
 void append(const hsTArray<T>& items) {
     size_t ins = getSize();
     incSize(items.getSize());
     for (size_t i=0; i<items.getSize(); i++)
         data[ins + i] = items.get(i);
 }
Exemple #28
0
void plInterMeshSmooth::FindEdges(uint32_t maxVtxIdx, uint32_t nTris, uint16_t* idxList, hsTArray<uint16_t>& edgeVerts)
{
    hsTArray<EdgeBin>*  bins = new hsTArray<EdgeBin>[maxVtxIdx+1];

    hsBitVector edgeVertBits;
    // For each vert pair (edge) in idxList
    int i;
    for( i = 0; i < nTris; i++ )
    {
        int j;
        for( j = 0; j < 3; j++ )
        {
            int jPlus = j < 2 ? j+1 : 0;
            int idx0 = idxList[i*3 + j];
            int idx1 = idxList[i*3 + jPlus];

            int lo, hi;

            // Look in the LUT for the lower index.
            if( idx0 < idx1 )
            {
                lo = idx0;
                hi = idx1;
            }
            else
            {
                lo = idx1;
                hi = idx0;
            }

            hsTArray<EdgeBin>& loBin = bins[lo];
            // In that bucket, look for the higher index.
            int k;
            for( k = 0; k < loBin.GetCount(); k++ )
            {
                if( loBin[k].fVtx == hi )
                    break;
            }

            // If we find it, increment it's count,
            // else add it.
            if( k < loBin.GetCount() )
            {
                loBin[k].fCount++;
            }
            else
            {
                EdgeBin* b = loBin.Push();
                b->fVtx = hi;
                b->fCount = 1;
            }
        }
    }

    // For each bucket in the LUT,
    for( i = 0; i < maxVtxIdx+1; i++ )
    {
        hsTArray<EdgeBin>& loBin = bins[i];
        // For each higher index
        int j;
        for( j = 0; j < loBin.GetCount(); j++ )
        {
            // If the count is one, it's an edge, so set the edge bit for both indices (hi and lo)
            if( 1 == loBin[j].fCount )
            {
                edgeVertBits.SetBit(i);
                edgeVertBits.SetBit(loBin[j].fVtx);
            }
        }
    }

    // Now translate the bitvector to a list of indices.
    for( i = 0; i < maxVtxIdx+1; i++ )
    {
        if( edgeVertBits.IsBitSet(i) )
            edgeVerts.Append(i);
    }
    delete [] bins;
}
void plMorphSequence::SetWeight(int iLay, int iDel, float w, plKey meshKey /* = nil */)
{
    int index = IFindSharedMeshIndex(meshKey);

    // Only dirty if the weight isn't for a pending mesh
    if(meshKey == nil || index >= 0)
        ISetDirty(true);

    if (meshKey == nil)
    {
        if( iLay < fMorphs.GetCount() )
        {
            if( kMorphTime > 0 )
            {
                plMorphTarget tgt;
                tgt.fLayer = iLay;
                tgt.fDelta = iDel;
                tgt.fWeight = w;

                fTgtWgts.Append(tgt);
            }
            else
            {
                fMorphs[iLay].SetWeight(iDel, w);
            }
        }
    }
    else if (index >= 0)
    {
        fSharedMeshes[index].fArrayWeights[iLay].fDeltaWeights[iDel] = w;
        fSharedMeshes[index].fFlags |= plSharedMeshInfo::kInfoDirtyMesh;
        if (index == fGlobalLayerRef)
            ISetAllSharedToGlobal();
    }
    else
    {
        // Setting weight for a mesh we haven't added yet (loading state)
        index = IFindPendingStateIndex(meshKey);
        if (index < 0)
        {
            fPendingStates.Push();
            index = fPendingStates.GetCount() - 1;
            fPendingStates[index].fSharedMeshKey = meshKey;
        }
        if (fPendingStates[index].fArrayWeights.GetCount() <= iLay)
        {
            int had = fPendingStates[index].fArrayWeights.GetCount();
            hsTArray<plMorphArrayWeights> temp(iLay + 1);
            temp = fPendingStates[index].fArrayWeights;
            temp.SetCount(iLay + 1);

            fPendingStates[index].fArrayWeights.Swap(temp);
            int i;
            for( i = had; i < iLay+1; i++ )
                fPendingStates[index].fArrayWeights[i].fDeltaWeights.Reset();
        }
        if (fPendingStates[index].fArrayWeights[iLay].fDeltaWeights.GetCount() <= iDel)
            fPendingStates[index].fArrayWeights[iLay].fDeltaWeights.ExpandAndZero(iDel + 1);

        fPendingStates[index].fArrayWeights[iLay].fDeltaWeights[iDel] = w;
    }
}
Exemple #30
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());
    }
}