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)); } } }
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]); } } }
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; }
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; }
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; }
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++; }
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 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); } } }
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; }
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; }
virtual int proc( ReferenceMaker *rmaker ) { fList.Append( rmaker ); return DEP_ENUM_CONTINUE; }
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); }
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); }
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; }
// // 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); } }
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]; }
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); }
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); }
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; } }
// 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()); } }