static void d3d_SetupSkyStuff(const SkyDef& Def, ViewParams* pParams) { LTVector percents; if(g_pSceneDesc->m_DrawMode == DRAWMODE_NORMAL) { const LTVector &min = world_bsp_shared->ExtentsMin(); const LTVector &max = world_bsp_shared->ExtentsMax(); percents.x = (pParams->m_Pos.x - min.x) / (max.x - min.x); percents.y = (pParams->m_Pos.y - min.y) / (max.y - min.y); percents.z = (pParams->m_Pos.z - min.z) / (max.z - min.z); } else { percents.Init(0.5f, 0.5f, 0.5f); } LTVector v = Def.m_ViewMax - Def.m_ViewMin; v.x *= percents.x; v.y *= percents.y; v.z *= percents.z; pParams->m_SkyViewPos = Def.m_ViewMin + v; }
void CSteamFX::TweakSystem() { LTFLOAT fIncValue = 0.01f; LTBOOL bChanged = LTFALSE; LTVector vScale; vScale.Init(); uint32 dwPlayerFlags = g_pGameClientShell->GetPlayerFlags(); // Move faster if running... if (dwPlayerFlags & BC_CFLG_RUN) { fIncValue = .5f; } // Move Red up/down... if ((dwPlayerFlags & BC_CFLG_FORWARD) || (dwPlayerFlags & BC_CFLG_REVERSE)) { //m_cs.vMinVel //m_cs.vMaxVel //m_cs.vColor1 //m_cs.vColor2 bChanged = LTTRUE; } // Add/Subtract number of particles per second if ((dwPlayerFlags & BC_CFLG_STRAFE_RIGHT) || (dwPlayerFlags & BC_CFLG_STRAFE_LEFT)) { fIncValue = dwPlayerFlags & BC_CFLG_STRAFE_RIGHT ? fIncValue : -fIncValue; //m_cs.fParticlesPerSecond += (LTFLOAT)(fIncValue * 101.0); //m_cs.fParticlesPerSecond = m_cs.fParticlesPerSecond < 0.0f ? 0.0f : // (m_cs.fParticlesPerSecond > MAX_PARTICLES_PER_SECOND ? MAX_PARTICLES_PER_SECOND : m_cs.fParticlesPerSecond); bChanged = LTTRUE; } // Lower/Raise burst wait... if ((dwPlayerFlags & BC_CFLG_JUMP) || (dwPlayerFlags & BC_CFLG_DUCK)) { fIncValue = dwPlayerFlags & BC_CFLG_DUCK ? -fIncValue : fIncValue; bChanged = LTTRUE; } if (bChanged) { //g_pGameClientShell->CSPrint("Particles per second: %.2f", m_cs.fParticlesPerSecond); } }
bool CPolyFanFX::Init(ILTClient *pClientDE, FX_BASEDATA *pBaseData, const CBaseFXProps *pProps) { // Perform base class initialisation if (!CBaseFX::Init(pClientDE, pBaseData, pProps)) return false; LTVector vPos; if( m_hParent ) { m_pLTClient->GetObjectPos(m_hParent, &vPos); } else { vPos = m_vCreatePos; } LTVector vScale; vScale.Init(1.0f, 1.0f, 1.0f); ObjectCreateStruct ocs; INIT_OBJECTCREATESTRUCT(ocs); ocs.m_ObjectType = OT_NORMAL; ocs.m_Flags = 0; ocs.m_Pos = vPos; ocs.m_Scale = vScale; strcpy(ocs.m_Filename, GetProps()->m_sPolyFanName); m_hObject = m_pLTClient->CreateObject(&ocs); // Success !! return true; }
bool GetIntersectionUnderPoint( LTVector &vInPt, HOBJECT *pFilterList, LTVector &vOutNormal, LTVector &vOutPt ) { IntersectQuery iq; IntersectInfo ii; vOutNormal.Init(0, 1, 0); iq.m_Flags = IGNORE_NONSOLID | INTERSECT_OBJECTS | INTERSECT_HPOLY; iq.m_From = vInPt; iq.m_To = iq.m_From + LTVector( 0, -1, 0) * 256.0f; iq.m_FilterFn = ObjListFilterFn; iq.m_pUserData = pFilterList; if( g_pLTClient->IntersectSegment( iq, &ii ) ) { if( ii.m_hObject ) { vOutNormal = ii.m_Plane.m_Normal; vOutPt = ii.m_Point; return true; } } return false; }
void CScreenTintMgr::Update() { if (!m_bChanged) return; LTVector vTemp; vTemp.Init(0.0f,0.0f,0.0f); for (int i = 0; i < NUM_TINT_EFFECTS; i++) { vTemp.x = LTMAX(vTemp.x,m_avTints[i].x); vTemp.y = LTMAX(vTemp.y,m_avTints[i].y); vTemp.z = LTMAX(vTemp.z,m_avTints[i].z); } if (vTemp.x > 1.0f) vTemp.x = 1.0f; if (vTemp.y > 1.0f) vTemp.y = 1.0f; if (vTemp.z > 1.0f) vTemp.z = 1.0f; m_bChanged = false; //g_pLTClient->SetCameraLightAdd( g_pPlayerMgr->GetPlayerCamera()->GetCamera(), &vTemp); }
void GameBase::CreateBoundingBox() { if (m_hDimsBox) return; if (!g_vtDimsAlpha.IsInitted()) { g_vtDimsAlpha.Init(g_pLTServer, "DimsAlpha", LTNULL, 1.0f); } ObjectCreateStruct theStruct; INIT_OBJECTCREATESTRUCT(theStruct); LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); theStruct.m_Pos = vPos; SAFE_STRCPY(theStruct.m_Filename, "Models\\1x1_square.abc"); SAFE_STRCPY(theStruct.m_SkinName, "Models\\1x1_square.dtx"); theStruct.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT | FLAG_GOTHRUWORLD; theStruct.m_ObjectType = OT_MODEL; HCLASS hClass = g_pLTServer->GetClass("BaseClass"); LPBASECLASS pModel = g_pLTServer->CreateObject(hClass, &theStruct); if (pModel) { m_hDimsBox = pModel->m_hObject; LTVector vDims; g_pLTServer->GetObjectDims(m_hObject, &vDims); LTVector vScale; VEC_DIVSCALAR(vScale, vDims, 0.5f); g_pLTServer->ScaleObject(m_hDimsBox, &vScale); } LTVector vOffset; LTRotation rOffset; vOffset.Init(); rOffset.Init(); HATTACHMENT hAttachment; LTRESULT dRes = g_pLTServer->CreateAttachment(m_hObject, m_hDimsBox, LTNULL, &vOffset, &rOffset, &hAttachment); if (dRes != LT_OK) { g_pLTServer->RemoveObject(m_hDimsBox); m_hDimsBox = LTNULL; } LTVector vColor = GetBoundingBoxColor(); g_pLTServer->SetObjectColor(m_hDimsBox, vColor.x, vColor.y, vColor.z, g_vtDimsAlpha.GetFloat()); }
LTBOOL CProjectileFX::MoveServerObj() { if (!m_pClientDE || !m_bLocal || !m_hServerObject || !g_pWeaponMgr) return LTFALSE; ILTClientPhysics* pPhysicsLT = (ILTClientPhysics *)m_pClientDE->Physics(); if (!pPhysicsLT) return LTFALSE; LTFLOAT fTime = m_pClientDE->GetTime(); // If we didn't hit anything we're done... if (fTime >= (m_fStartTime + m_pProjectileFX->fLifeTime)) { return LTFALSE; } LTFLOAT fFrameTime = g_pGameClientShell->GetFrameTime(); // Zero out the acceleration to start with. LTVector zeroVec; zeroVec.Init(); pPhysicsLT->SetAcceleration(m_hServerObject, &zeroVec); LTBOOL bRet = LTTRUE; MoveInfo info; info.m_hObject = m_hServerObject; info.m_dt = fFrameTime; pPhysicsLT->UpdateMovement(&info); if (info.m_Offset.MagSqr() > 0.01f) { LTVector vDiff, vNewPos, vCurPos; m_pClientDE->GetObjectPos(m_hServerObject, &vCurPos); vNewPos = vCurPos + info.m_Offset; pPhysicsLT->MoveObject(m_hServerObject, &vNewPos, 0); vDiff = vCurPos - vNewPos; if (vDiff.MagSqr() < 5.0f) { bRet = LTFALSE; } } else { bRet = LTFALSE; } return bRet; }
void TestSubtitleFn(int argc, char **argv) { // Track the current execution shell scope for proper SEM behavior CGameClientShell::CClientShellScopeTracker cScopeTracker; if (argc <= 0) return; LTVector vPos; vPos.Init(); g_pSubtitles->Show(argv[0],vPos); }
LTBOOL gr_IntersectPlanes( LTPlane &plane0, LTPlane &plane1, LTPlane &plane2, LTVector &vOut) { LTMatrix mPlanes; /* Math behind this: Plane equation is Ax + By + Cz - D = 0 Standard matrix equation Ax = b. So stick the plane equations into the A matrix: A B C -D (from plane 0) A B C -D (from plane 1) A B C -D (from plane 2) 0 0 0 1 then the b vector is: [0 0 0 1] and we're solving for the x vector so: ~AAx = ~Ab x = ~Ab */ mPlanes.Init( plane0.m_Normal[0], plane0.m_Normal[1], plane0.m_Normal[2], -plane0.m_Dist, plane1.m_Normal[0], plane1.m_Normal[1], plane1.m_Normal[2], -plane1.m_Dist, plane2.m_Normal[0], plane2.m_Normal[1], plane2.m_Normal[2], -plane2.m_Dist, 0.0f, 0.0f, 0.0f, 1.0f); // If we can't invert the matrix, then two or more planes are equal. if(!mPlanes.Inverse()) return LTFALSE; // Since our b vector is all zeros, we don't need to do a full matrix multiply. // vOut = mPlaneNormal * vPlaneDist; vOut.Init( mPlanes.m[0][3], mPlanes.m[1][3], mPlanes.m[2][3]); vOut *= (1.0f / mPlanes.m[3][3]); return LTTRUE; }
//---------------------------------------------------------------------------// static void GetSmallestPushaway ( LTVector &moverMin, LTVector &moverMax, LTVector &blockerMin, LTVector &blockerMax, LTVector &pushAmount, int32 &pushPlane ) { float minPush; int32 minPushDim = 0; float testPush; int32 i, curPushPlane, minPushPlane; minPush = (float)MAX_CREAL; curPushPlane = 0; minPushPlane = 0; for(i=0; i < 3; i++) { testPush = blockerMax[i] - moverMin[i]; if(fabs(testPush) < fabs(minPush)) { minPush = testPush; minPushDim = i; minPushPlane = curPushPlane; } ++curPushPlane; testPush = blockerMin[i] - moverMax[i]; if(fabs(testPush) < fabs(minPush)) { minPush = testPush; minPushDim = i; minPushPlane = curPushPlane; } ++curPushPlane; } pushAmount.Init(0.0f, 0.0f, 0.0f); pushAmount[minPushDim] = minPush; pushPlane = minPushPlane; }
void CCharacterHitBox::GetDefaultModelDims( LTVector &vDims ) { vDims.Init(); if( !m_hModel || !m_hObject ) return; HMODELANIM hAni = g_pModelLT->GetCurAnim( m_hModel, MAIN_TRACKER, hAni ); if( hAni != INVALID_ANI ) { g_pModelLT->GetModelAnimUserDims( m_hModel, hAni, &vDims ); } else { g_pPhysicsLT->GetObjectDims( m_hObject, &vDims ); } }
//called when a sphere shape is encountered. This will provide the center of the sphere relative //to the transform heirarchy and the radius of that sphere virtual void HandleSphere(const LTVector& vCenter, float fRadius, float fMassKg, float fDensityG) { m_fTotalMassKg += fMassKg; float fVolume, fSurfaceArea; if(ApplySphereBuoyancy(vCenter, fRadius, m_SurfacePlane, fVolume, fSurfaceArea)) { m_fSurfaceArea += fSurfaceArea; float fWaterDensity = CalcSphereWaterDensity(m_fDensity, fRadius, fMassKg, fDensityG); LTVector vForce = CalcBuoyancyForceVector(m_vGravity, fWaterDensity, fVolume); if( LTIsNaN( vForce ) || vForce.MagSqr() > 1000000.0f * 1000000.0f ) { LTERROR( "Invalid force detected." ); vForce.Init( 0.0f, 10.0f, 0.0f ); } g_pLTBase->PhysicsSim()->ApplyRigidBodyForceWorldSpace(m_hRigidBody, vCenter, vForce); } }
bool CDynaLightFX::Init(ILTClient *pClientDE, FX_BASEDATA *pBaseData, const CBaseFXProps *pProps) { // Perform base class initialisation if (!CBaseFX::Init(pClientDE, pBaseData, pProps)) return false; LTVector vScale; vScale.Init(100.0f, 100.0f, 100.0f); ObjectCreateStruct ocs; INIT_OBJECTCREATESTRUCT(ocs); ocs.m_ObjectType = OT_LIGHT; ocs.m_Flags = pBaseData->m_dwObjectFlags; ocs.m_Flags2 |= pBaseData->m_dwObjectFlags2; ocs.m_Pos = m_vCreatePos; ocs.m_Rotation = m_rCreateRot; ocs.m_Scale = vScale; if(GetProps()->m_bForceLightWorld) { ocs.m_Flags2 |= FLAG2_FORCEDYNAMICLIGHTWORLD; } // Lights can't be really close ocs.m_Flags &= ~FLAG_REALLYCLOSE; // Create the light m_hObject = m_pLTClient->CreateObject(&ocs); // We want the colour updated thankyou m_bUpdateColour = true; m_bUpdateScale = true; // Success !! return true; }
//called when an OBB shape is encountered. This will provide the transform of the OBB relative to //the transform heirarchy and the half dimensions of the OBB virtual void HandleOBB(const LTRigidTransform& tTransform, const LTVector& vHalfDims, float fMassKg, float fDensityG) { m_fTotalMassKg += fMassKg; float fVolume, fSurfaceArea; LTVector vApplyAt; if(ApplyOBBBuoyancy(tTransform, vHalfDims, m_SurfacePlane, fVolume, vApplyAt, fSurfaceArea)) { m_fSurfaceArea += fSurfaceArea; float fWaterDensity = CalcOBBWaterDensity(m_fDensity, vHalfDims, fMassKg, fDensityG); LTVector vForce = CalcBuoyancyForceVector(m_vGravity, fWaterDensity, fVolume); if( LTIsNaN( vForce ) || vForce.MagSqr() > 1000000.0f * 1000000.0f ) { LTERROR( "Invalid force detected." ); vForce.Init( 0.0f, 10.0f, 0.0f ); } g_pLTBase->PhysicsSim()->ApplyRigidBodyForceWorldSpace(m_hRigidBody, vApplyAt, vForce); } }
//called when a capsule shape is encounered. This will provide the two end points of the capsule //relative to the transform heirarchy and the radius of the capsule virtual void HandleCapsule(const LTVector& vPt1, const LTVector& vPt2, float fRadius, float fMassKg, float fDensityG) { m_fTotalMassKg += fMassKg; float fVolume, fSurfaceArea; LTVector vApplyAt; //determine the lenght of the capsule axis float fLength = vPt1.Dist(vPt2); if(ApplyCapsuleBuoyancy(vPt1, vPt2, fLength, fRadius, m_SurfacePlane, fVolume, vApplyAt, fSurfaceArea)) { m_fSurfaceArea += fSurfaceArea; float fWaterDensity = CalcCapsuleWaterDensity(m_fDensity, fRadius, fLength, fMassKg, fDensityG); LTVector vForce = CalcBuoyancyForceVector(m_vGravity, fWaterDensity, fVolume); if( LTIsNaN( vForce ) || vForce.MagSqr() > 1000000.0f * 1000000.0f ) { LTERROR( "Invalid force detected." ); vForce.Init( 0.0f, 10.0f, 0.0f ); } g_pLTBase->PhysicsSim()->ApplyRigidBodyForceWorldSpace(m_hRigidBody, vApplyAt, vForce); } }
// Gives each object a touch notification and creates container links for them. void DoNonsolidCollision(MoveAbstract *pAbstract, LTObject *pObj1, LTObject *pObj2) { CollisionInfo *pInfo; LTVector zeroVec; pInfo = pAbstract->GetCollisionInfo(); // Setup the collision info... pInfo->m_Plane.m_Normal.Init(); pInfo->m_Plane.m_Dist = 0.0f; pInfo->m_hPoly = INVALID_HPOLY; zeroVec.Init(); if(pObj1->m_Flags & FLAG_TOUCH_NOTIFY) { pAbstract->DoTouchNotify(pObj1, pObj2, zeroVec, 0.0f); } if(pObj2->m_Flags & FLAG_TOUCH_NOTIFY) { pAbstract->DoTouchNotify(pObj2, pObj1, zeroVec, 0.0f); } // Update area object touching. if(pObj1->m_Flags & FLAG_CONTAINER) { pAbstract->PutObjectInContainer(pObj2, pObj1); } if(pObj2->m_Flags & FLAG_CONTAINER) { pAbstract->PutObjectInContainer(pObj1, pObj2); } }
void CFlashLightPlayer::GetLightPositions(LTVector& vStartPos, LTVector& vEndPos, LTVector& vUOffset, LTVector& vROffset) { vStartPos.Init(); vEndPos.Init(); vUOffset.Init(); vROffset.Init(); CMoveMgr* pMoveMgr = g_pPlayerMgr->GetMoveMgr(); if (!pMoveMgr) return; LTRotation rRot; if (pMoveMgr->GetVehicleMgr()->IsVehiclePhysics()) { if (g_pPlayerMgr->IsFirstPerson()) { pMoveMgr->GetVehicleMgr()->GetVehicleLightPosRot(vStartPos, rRot); } else // 3rd person vehicle { // Get light pos on 3rd-person vehicle... HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject(); if (hPlayerObj) { g_pLTClient->GetObjectRotation(hPlayerObj, &rRot); g_pLTClient->GetObjectPos(hPlayerObj, &vStartPos); } } } else if (g_pPlayerMgr->IsFirstPerson()) { HOBJECT hCamera = g_pPlayerMgr->GetCamera(); if (!hCamera) return; g_pLTClient->GetObjectRotation(hCamera, &rRot); g_pLTClient->GetObjectPos(hCamera, &vStartPos); } else // 3rd person { // Get light pos from 3rd-person model... HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject(); if (hPlayerObj) { // g_pLTClient->GetObjectRotation(hPlayerObj, &rRot); // g_pLTClient->GetObjectPos(hPlayerObj, &vStartPos); HMODELSOCKET hSocket; if ( LT_OK == g_pModelLT->GetSocket(hPlayerObj, "LeftHand", hSocket) ) { LTransform tf; if ( LT_OK == g_pModelLT->GetSocketTransform(hPlayerObj, hSocket, tf, LTTRUE) ) { vStartPos = tf.m_Pos; rRot = tf.m_Rot; } } } } vEndPos = vStartPos + (rRot.Forward() * g_cvarFLLightOffsetForward.GetFloat()); if (g_pPlayerMgr->IsFirstPerson()) { vROffset = (rRot.Right() * g_cvarFLLightOffsetRight.GetFloat()); vUOffset = (rRot.Up() * g_cvarFLLightOffsetUp.GetFloat()); // Update the Start/End position to addjust for any offset... vEndPos += vROffset; vEndPos += vUOffset; vStartPos += vROffset; vStartPos += vUOffset; } }
//function that handles the custom rendering void CBaseSpriteFX::RenderSprite(ILTCustomRenderCallback* pInterface, const LTRigidTransform& tCamera) { //setup our vertex declaration if(pInterface->SetVertexDeclaration(g_ClientFXVertexDecl.GetTexTangentSpaceDecl()) != LT_OK) return; //bind a quad index stream if(pInterface->BindQuadIndexStream() != LT_OK) return; //determine how many indices we are going to need uint32 nNumIndices = (GetProps()->m_bTwoSided) ? 12 : 6; uint32 nNumVertices = (GetProps()->m_bTwoSided) ? 8 : 4; //sanity check to ensure that we can at least render a sprite LTASSERT(QUAD_RENDER_INDEX_STREAM_SIZE >= nNumIndices, "Error: Quad index list is too small to render a sprite"); LTASSERT(DYNAMIC_RENDER_VERTEX_STREAM_SIZE / sizeof(STexTangentSpaceVert) >= nNumVertices, "Error: Dynamic vertex buffer size is too small to render a sprite"); //determine the up and right vectors for the sprite LTVector vTangent, vBinormal; //get the position of this sprite LTRigidTransform tObjTransform; g_pLTClient->GetObjectTransform(m_hObject, &tObjTransform); //determine the center of this sprite LTVector vCenter = tObjTransform.m_vPos; //determine the orientation of the sprite based upon its facing if(GetProps()->m_bAlignToCamera) { //apply the to camera offset LTVector vToCamera = tCamera.m_vPos - vCenter; float fScale = GetProps()->m_fToCameraOffset / vToCamera.Mag(); vCenter += vToCamera * fScale; //perform the rotation float fCosAng = LTCos(m_fCurrRotationRad); float fSinAng = LTSin(m_fCurrRotationRad); LTVector vRight = tCamera.m_rRot.Right(); LTVector vUp = -tCamera.m_rRot.Up(); vTangent = fCosAng * vRight + fSinAng * vUp; vBinormal = fCosAng * vUp - fSinAng * vRight; } else if(GetProps()->m_bAlignAroundZ) { //we want to orient around the Z axis and align to the camera //we need to determine our U vector, which is always our forward LTVector vU = tObjTransform.m_rRot.Forward(); //and now we want to offset our center so that we are anchored on the right hand //side of the sprite to the point vCenter += vU * (m_fWidth * 0.5f); //determine the axis from our camera to our object LTVector vToCamera = tCamera.m_vPos - vCenter; //and now derive our V vector from the forward and the direction to the camera LTVector vV = vToCamera.Cross(vU); //detect degenerate cases if(vV == LTVector::GetIdentity()) { //degenerate case, any orientation will work fine since the sprite won't //be visible anyway vV.Init(0.0f, 1.0f, 0.0f); } //and normalize our vector vV.Normalize(); //now we can determine our tangent and binormal vectors vTangent = -vU; vBinormal = vV; } else { vTangent = -tObjTransform.m_rRot.Right(); vBinormal = -tObjTransform.m_rRot.Up(); } LTVector vNormal = vBinormal.Cross(vTangent); //scale the right and down values to be the appropriate size LTVector vRight = vTangent * m_fWidth * -0.5f; LTVector vDown = vBinormal * m_fWidth * GetProps()->m_fAspectRatio * 0.5f; //lock down our buffer for rendering SDynamicVertexBufferLockRequest LockRequest; if(pInterface->LockDynamicVertexBuffer(nNumVertices, LockRequest) != LT_OK) return; //fill in our sprite vertices STexTangentSpaceVert* pCurrOut = (STexTangentSpaceVert*)LockRequest.m_pData; uint32 nColor = SETRGBA( (uint8)(m_vColor.x * 255.0f), (uint8)(m_vColor.y * 255.0f), (uint8)(m_vColor.z * 255.0f), (uint8)(m_vColor.w * 255.0f)); //fill in the particle vertices pCurrOut[0].m_vPos = vCenter + vRight - vDown; pCurrOut[0].m_vUV.Init(0.0f, 0.0f); pCurrOut[1].m_vPos = vCenter - vRight - vDown; pCurrOut[1].m_vUV.Init(1.0f, 0.0f); pCurrOut[2].m_vPos = vCenter - vRight + vDown; pCurrOut[2].m_vUV.Init(1.0f, 1.0f); pCurrOut[3].m_vPos = vCenter + vRight + vDown; pCurrOut[3].m_vUV.Init(0.0f, 1.0f); //setup the remaining vertex components for(uint32 nCurrVert = 0; nCurrVert < 4; nCurrVert++) { pCurrOut[nCurrVert].m_nPackedColor = nColor; pCurrOut[nCurrVert].m_vNormal = vNormal; pCurrOut[nCurrVert].m_vTangent = vTangent; pCurrOut[nCurrVert].m_vBinormal = vBinormal; } //and fill in the back side if appropriate if(GetProps()->m_bTwoSided) { pCurrOut[4].m_vPos = vCenter - vRight - vDown; pCurrOut[4].m_vUV.Init(1.0f, 0.0f); pCurrOut[5].m_vPos = vCenter + vRight - vDown; pCurrOut[5].m_vUV.Init(0.0f, 0.0f); pCurrOut[6].m_vPos = vCenter + vRight + vDown; pCurrOut[6].m_vUV.Init(0.0f, 1.0f); pCurrOut[7].m_vPos = vCenter - vRight + vDown; pCurrOut[7].m_vUV.Init(1.0f, 1.0f); //setup the remaining vertex components for(uint32 nCurrVert = 4; nCurrVert < 8; nCurrVert++) { pCurrOut[nCurrVert].m_nPackedColor = nColor; pCurrOut[nCurrVert].m_vNormal = -vNormal; pCurrOut[nCurrVert].m_vTangent = -vTangent; pCurrOut[nCurrVert].m_vBinormal = vBinormal; } } //unlock and render the batch pInterface->UnlockAndBindDynamicVertexBuffer(LockRequest); pInterface->RenderIndexed( eCustomRenderPrimType_TriangleList, 0, nNumIndices, LockRequest.m_nStartIndex, 0, nNumVertices); }
bool CTrackedNodeMgr::SetNodeConstraints( HTRACKEDNODE ID, const LTVector& vMovConeAxis, const LTVector& vMovConeUp, float fXDiscomfortAngle, float fYDiscomfortAngle, float fXMaxAngle, float fYMaxAngle, float fMaxAngVel ) { //sanity checks if(!CheckValidity(ID)) return false; //ok, we have a valid ID, so let us setup the parameters CTrackedNode* pNode = (CTrackedNode*)ID; //see if the up and forward vectors are valid LTVector vForward = vMovConeAxis; LTVector vUp = vMovConeUp; //ensure proper scale vForward.Normalize(); vUp.Normalize(); //ensure they form a valid space (and not a plane) if(vUp.Dot(vForward) > 0.99f) { //not valid, we need to try a different up, our preference is the world up vUp.Init(0.0f, 1.0f, 0.0f); if(vUp.Dot(vForward) > 0.99f) { //ok, forward is already taking the up....so, tilt us back vUp.Init(0.0f, 0.0f, -1.0f); } } //now generate the right, and ensure orthogonality LTVector vRight = vForward.Cross(vUp); vUp = vRight.Cross(vForward); vRight.Normalize(); vUp.Normalize(); //setup this as the basis space pNode->m_mInvTargetTransform.SetBasisVectors(&vRight, &vUp, &vForward); pNode->m_mInvTargetTransform.Transpose(); //we need to make sure that their angular constraints are valid (meaning that they are positive and //less than 90 deg) fXMaxAngle = LTCLAMP(fXMaxAngle, 0.0f, DEG2RAD(89.0f)); fYMaxAngle = LTCLAMP(fYMaxAngle, 0.0f, DEG2RAD(89.0f)); fXDiscomfortAngle = LTCLAMP(fXDiscomfortAngle, 0.0f, fXMaxAngle); fYDiscomfortAngle = LTCLAMP(fYDiscomfortAngle, 0.0f, fYMaxAngle); //now precompute the tangent of those values (used for finding the height of the cone created which //is used in the threshold determination code) pNode->m_fTanXDiscomfort = (float)tan(fXDiscomfortAngle); pNode->m_fTanYDiscomfort = (float)tan(fYDiscomfortAngle); pNode->m_fTanXThreshold = (float)tan(fXMaxAngle); pNode->m_fTanYThreshold = (float)tan(fYMaxAngle); //handle setting up the maximum angular velocity pNode->m_fMaxAngVel = (float)fabs(fMaxAngVel); //and we are ready for primetime return true; }
void Prop::HandleAttachmentTouch( HOBJECT hToucher ) { if( !hToucher || !m_bAttachmentShotOff ) return; // Don't touch the owner... if( hToucher == m_hAttachmentOwner ) return; // Or any non-solid objects... uint32 dwToucherFlags; g_pCommonLT->GetObjectFlags( hToucher, OFT_Flags, dwToucherFlags ); if( !(dwToucherFlags & FLAG_SOLID) ) return; CollisionInfo info; g_pLTServer->GetLastCollision( &info ); LTVector vVel; g_pPhysicsLT->GetVelocity( m_hObject, &vVel ); // Calculate where we really hit the world... if( IsMainWorld( hToucher )) { LTVector vPos, vCurVel, vP0, vP1; g_pLTServer->GetObjectPos( m_hObject, &vPos ); vP1 = vPos; vCurVel = vVel * g_pLTServer->GetFrameTime(); vP0 = vP1 - vCurVel; vP1 += vCurVel; LTFLOAT fDot1 = VEC_DOT( info.m_Plane.m_Normal, vP0 ) - info.m_Plane.m_Dist; LTFLOAT fDot2 = VEC_DOT( info.m_Plane.m_Normal, vP1 ) - info.m_Plane.m_Dist; if( fDot1 < 0.0f && fDot2 < 0.0f || fDot1 > 0.0f && fDot2 > 0.0f ) { vPos = vP1; } else { LTFLOAT fPercent = -fDot1 / (fDot2 - fDot1); VEC_LERP( vPos, vP0, vP1, fPercent); } // Set our new "real" pos... g_pLTServer->SetObjectPos( m_hObject, &vPos ); } // If we're on the ground (or an object), stop movement... CollisionInfo standingInfo; g_pLTServer->GetStandingOn( m_hObject, &standingInfo ); CollisionInfo* pInfo = standingInfo.m_hObject ? &standingInfo : &info; if( pInfo->m_hObject ) { // Don't stop on walls... if( pInfo->m_Plane.m_Normal.y > 0.75f ) { vVel.Init(); // Turn off gravity, solid, and touch notify.... uint32 dwFlags = FLAG_POINTCOLLIDE | FLAG_NOSLIDING | FLAG_TOUCH_NOTIFY | FLAG_GRAVITY; g_pCommonLT->SetObjectFlags( m_hObject, OFT_Flags, 0, dwFlags ); // Rotate to rest... if( m_bRotating ) { LTRotation rRot( 0.0f, m_fYaw, 0.0f ); g_pLTServer->SetObjectRotation( m_hObject, &rRot ); m_bRotating = false; StartFade( s_vtAttachmentFadeDuration.GetFloat(), s_vtAttachmentFadeDelay.GetFloat() ); } } } // Remove the stoping velocity... vVel = -info.m_vStopVel; g_pPhysicsLT->SetVelocity( m_hObject, &vVel ); }
bool CFallingStuffFX::Update(float tmFrameTime) { // Base class update first m_vLastPos = m_vPos; if (!CBaseFX::Update(tmFrameTime)) return false; //increment our emission time by the elapsed frame time m_tmElapsedEmission += tmFrameTime; if (!IsShuttingDown() && !IsSuspended() && (m_tmElapsedEmission > GetProps()->m_tmFallingStuffFXEmission)) { ObjectCreateStruct ocs; INIT_OBJECTCREATESTRUCT(ocs); LTVector vScale; vScale.Init(m_scale, m_scale, m_scale); LTVector vInterp; LTVector vInterpCur = m_vPos; // Calculate interpolant for particle system if (GetProps()->m_nFallingStuffFXEmission) { vInterp = m_vPos - m_vLastPos; vInterp /= (float)GetProps()->m_nFallingStuffFXEmission; } for (uint32 i = 0; i < GetProps()->m_nFallingStuffFXEmission; i ++) { ocs.m_ObjectType = OT_SPRITE; ocs.m_Flags = FLAG_VISIBLE | FLAG_NOLIGHT | FLAG_ROTATABLESPRITE; // Compute the initial position float xRand = GetProps()->m_fRadius * ((-10000.0f + (rand() % 20000)) / 10000.0f); float zRand = GetProps()->m_fRadius * ((-10000.0f + (rand() % 20000)) / 10000.0f); ocs.m_Pos = m_vPos + (m_vRight * xRand) + (m_vUp * zRand); ocs.m_Scale = vScale; strcpy(ocs.m_Filename, GetProps()->m_sSpriteName); // Move the start point vInterpCur += vInterp; HLOCALOBJ hNewSprite = m_pLTClient->CreateObject(&ocs); if (hNewSprite) { // Create a new sprite FALLING_THING *pNewSprite = debug_new( FALLING_THING ); if (GetProps()->m_nImpactCreate) { if (g_dwSplash > (uint32)GetProps()->m_nImpactCreate) { pNewSprite->m_bSplash = true; g_dwSplash = 0; } else { pNewSprite->m_bSplash = false; } } else { pNewSprite->m_bSplash = false; } g_dwSplash ++; if (pNewSprite) { LTVector v; // Compute the initial velocity v = m_vPlaneDir * GetProps()->m_fVel; pNewSprite->m_hObject = hNewSprite; pNewSprite->m_vVel = v; pNewSprite->m_tmElapsed = 0.0f; pNewSprite->m_vPos = ocs.m_Pos; pNewSprite->m_vLastPos = ocs.m_Pos; m_collSprites.AddTail(pNewSprite); } } } m_tmElapsedEmission = 0.0f; // And store the last position m_vLastPos = m_vPos; } LTMatrix mSpin; if (GetProps()->m_bUseSpin) { // Setup rotation LTMatrix vRight; LTMatrix vUp; LTMatrix vForward; LTMatrix vTmp; Mat_SetupRot(&vRight, &m_vRight, m_xRot); Mat_SetupRot(&vUp, &m_vUp, m_yRot); Mat_SetupRot(&vForward, &m_vPlaneDir, m_zRot); MatMul(&vTmp, &vRight, &vUp); MatMul(&mSpin, &vTmp, &vForward); m_xRot += GetProps()->m_vRotAdd.x * tmFrameTime; m_yRot += GetProps()->m_vRotAdd.y * tmFrameTime; m_zRot += GetProps()->m_vRotAdd.z * tmFrameTime; } // Get the camera rotation LTRotation orient; m_pLTClient->GetObjectRotation(m_hCamera, &orient); LTRotation dRot(orient); LTVector vF = orient.Forward(); float rot = (float)atan2(vF.x, vF.z); // Update the sprites.... CLinkListNode<FALLING_THING *> *pNode = m_collSprites.GetHead(); CLinkListNode<FALLING_THING *> *pDelNode; while (pNode) { pDelNode = NULL; FALLING_THING *pSprite = pNode->m_Data; //adjust our elapsed time pSprite->m_tmElapsed += tmFrameTime; // Check for expiration if (pSprite->m_tmElapsed > GetProps()->m_tmSpriteLifespan) { // Destroy this object m_pLTClient->RemoveObject(pSprite->m_hObject); pDelNode = pNode; } else { // Update !! pSprite->m_vLastPos = pSprite->m_vPos; pSprite->m_vPos += (pSprite->m_vVel * tmFrameTime); // Rotate if neccessary TVector3<float> vPos = pSprite->m_vPos; if (GetProps()->m_bUseSpin) { MatVMul_InPlace(&mSpin, &vPos); } // Add in wind vPos += (GetProps()->m_vWind * GetProps()->m_fWindAmount) * tmFrameTime; // Setup the new sprite position LTVector vPos2 = vPos; m_pLTClient->SetObjectPos(pSprite->m_hObject, &vPos2); // Setup the colour float r, g, b, a; m_pLTClient->GetObjectColor(pSprite->m_hObject, &r, &g, &b, &a); CalcColour(pSprite->m_tmElapsed, GetProps()->m_tmSpriteLifespan, &r, &g, &b, &a); m_pLTClient->SetObjectColor(pSprite->m_hObject, r, g, b, a); // Setup the scale float scale = 0.1f; CalcScale(pSprite->m_tmElapsed, GetProps()->m_tmSpriteLifespan, &scale); LTVector vScale; vScale.Init(scale, scale * GetProps()->m_fStretchMul, scale); m_pLTClient->SetObjectScale(pSprite->m_hObject, &vScale); // Setup the rotation dRot = LTRotation(0, 0, 0, 1); LTRotation orient(dRot); orient.Rotate( orient.Up(), rot ); m_pLTClient->SetObjectRotation(pSprite->m_hObject, &orient); // Check to see if we need to start a splash sprite if (pSprite->m_bSplash) { ClientIntersectQuery ciq; ClientIntersectInfo cii; ciq.m_From = pSprite->m_vLastPos; ciq.m_To = pSprite->m_vPos; if ((GetProps()->m_sImpactSpriteName[0]) && (m_pLTClient->IntersectSegment(&ciq, &cii))) { // Create a splash sprite SPLASH *pSplash = debug_new( SPLASH ); ObjectCreateStruct ocs; INIT_OBJECTCREATESTRUCT(ocs); LTVector vScale; vScale.Init(0.0f, 0.0f, 0.0f); ocs.m_ObjectType = OT_SPRITE; ocs.m_Flags = FLAG_VISIBLE | FLAG_ROTATABLESPRITE | FLAG_NOLIGHT; ocs.m_Pos = cii.m_Point + (cii.m_Plane.m_Normal * 2.0f); ocs.m_Scale = vScale; LTRotation dOrient( cii.m_Plane.m_Normal, LTVector(0.0f, 1.0f, 0.0f) ); strcpy(ocs.m_Filename, GetProps()->m_sImpactSpriteName); pSplash->m_hObject = m_pLTClient->CreateObject(&ocs); pSplash->m_scale = 0.0f; LTRotation orient(dRot); m_pLTClient->SetObjectRotation(pSplash->m_hObject, &orient); pSplash->m_tmElapsed = 0.0f; m_collSplashes.AddTail(pSplash); // Destroy this object m_pLTClient->RemoveObject(pSprite->m_hObject); // Delete the sprite pDelNode = pNode; } } } pNode = pNode->m_pNext; if (pDelNode) m_collSprites.Remove(pDelNode); } // Update our splashes CLinkListNode<SPLASH *> *pSplashNode = m_collSplashes.GetHead(); while (pSplashNode) { CLinkListNode<SPLASH *> *pDelNode = NULL; SPLASH *pSplash = pSplashNode->m_Data; //update the elapsed time on the splash pSplash->m_tmElapsed += tmFrameTime; // Calculate the new scale float scale = GetProps()->m_fImpactScale1 + ((GetProps()->m_fImpactScale2 - GetProps()->m_fImpactScale1) * (pSplash->m_tmElapsed / GetProps()->m_tmImpactLifespan)); LTVector vScale(scale, scale, scale); m_pLTClient->SetObjectScale(pSplash->m_hObject, &vScale); float r, g, b, a; m_pLTClient->GetObjectColor(pSplash->m_hObject, &r, &g, &b, &a); a = (float)(int)(pSplash->m_tmElapsed / GetProps()->m_tmImpactLifespan); if (a < 0.0f) a = 0.0f; if (a > 1.0f) a = 1.0f; m_pLTClient->SetObjectColor(pSplash->m_hObject, r, g, b, a); if (pSplash->m_tmElapsed > GetProps()->m_tmImpactLifespan) { m_pLTClient->RemoveObject(pSplash->m_hObject); pDelNode = pSplashNode; } pSplashNode = pSplashNode->m_pNext; if (pDelNode) m_collSplashes.Remove(pDelNode); } // Success !! return true; }
void CLineSystemFX::TweakSystem() { LTFLOAT fIncValue = 0.01f; LTBOOL bChanged = LTFALSE; LTVector vScale; vScale.Init(); uint32 dwPlayerFlags = g_pPlayerMgr->GetPlayerFlags(); // Move faster if running... if (dwPlayerFlags & BC_CFLG_RUN) { fIncValue = .5f; } // Move Red up/down... if ((dwPlayerFlags & BC_CFLG_FORWARD) || (dwPlayerFlags & BC_CFLG_REVERSE)) { fIncValue = dwPlayerFlags & BC_CFLG_FORWARD ? fIncValue : -fIncValue; m_cs.vMinVel.y += (LTFLOAT)(fIncValue * 101.0); m_cs.vMaxVel.y += (LTFLOAT)(fIncValue * 101.0); //m_cs.vColor1 //m_cs.vColor2 bChanged = LTTRUE; } // Add/Subtract number of lines per second if ((dwPlayerFlags & BC_CFLG_STRAFE_RIGHT) || (dwPlayerFlags & BC_CFLG_STRAFE_LEFT)) { fIncValue = dwPlayerFlags & BC_CFLG_STRAFE_RIGHT ? fIncValue : -fIncValue; m_cs.fLinesPerSecond += (LTFLOAT)(fIncValue * 101.0); m_cs.fLinesPerSecond = m_cs.fLinesPerSecond < 0.0f ? 0.0f : (m_cs.fLinesPerSecond > MAX_LINES_PER_SECOND ? MAX_LINES_PER_SECOND : m_cs.fLinesPerSecond); bChanged = LTTRUE; } // Change line length... if ((dwPlayerFlags & BC_CFLG_JUMP) || (dwPlayerFlags & BC_CFLG_DUCK)) { fIncValue = dwPlayerFlags & BC_CFLG_DUCK ? -fIncValue : fIncValue; // Adjust length and slope of lines... m_cs.fLineLength += (fIncValue*2.0f); m_vStartOffset.y = m_cs.fLineLength / 2.0f; m_vEndOffset.y = -m_cs.fLineLength / 2.0f; float fVal = (float)fabs(m_cs.vMaxVel.y); if (fVal > 0.0) { m_vEndOffset.x = (m_cs.fLineLength * (g_vWorldWindVel.x / fVal)); } if (fVal > 0.0) { m_vEndOffset.z = (m_cs.fLineLength * (g_vWorldWindVel.z / fVal)); } bChanged = LTTRUE; } if (bChanged) { g_pGameClientShell->CSPrint("Lines per second: %.2f", m_cs.fLinesPerSecond); g_pGameClientShell->CSPrint("Line length: %.2f", m_vStartOffset.y - m_vEndOffset.y); g_pGameClientShell->CSPrint("Velocity: %.2f", m_cs.vMinVel.y); } }
//* // ----------------------------------------------------------------------- // // Returns the vector that the physics would have the object move by. // ----------------------------------------------------------------------- // void CalcMotion ( MotionInfo* pInfo, LTObject* pObj, //the object LTVector& dr, //displacement LTVector& v, //velocity LTVector& a, //acceleration const bool bApplyGravity, const float dt //time step ) { LTVector velocityDelta, accelDelta; LTVector q, slopeVel, slopeAccel, vel; const LTVector *n; LTVector objectNormal, vTemp, vTemp2; float fExp; float timeIntegral; float velocityMagSqr, accelMagSqr; LTBOOL bFriction; bFriction = LTFALSE; timeIntegral = dt * dt * 0.5f; velocityMagSqr = v.MagSqr(); accelMagSqr = a.MagSqr(); // [KLS - 3/12/02] - Added support for per-object force override... LTVector vForce = pObj->GetGlobalForceOverride(); // If the global force override is zero, use the MotionInfo force... if (LTVector(0.0, 0.0, 0.0) == vForce) { vForce = pInfo->m_Force; } /* // Debug variables LTVector vOldAccel, vOldVel, vOldPos; vOldAccel = a; vOldVel = v; vOldPos = pObj->GetPos(); //*/ // Stop objects that are moving very slowly... if(velocityMagSqr < 0.1f ) { v.Init(); velocityMagSqr = 0; } if( accelMagSqr < 0.1f ) { a.Init(); accelMagSqr = 0; } // Zero out the displacement to start with. dr.Init(); // Update objects affected by gravity... if(bApplyGravity) { // Add friction to objects standing on something... if(pObj->m_pStandingOn) { // Try to disable their physics. if( velocityMagSqr < 0.1f && accelMagSqr < 0.1f ) { pObj->m_Velocity.Init(); pObj->m_Acceleration.Init(); pObj->m_InternalFlags &= ~IFLAG_APPLYPHYSICS; return; } else { // Check if object on world geometry... if( pObj->m_pNodeStandingOn ) { // Calculate vector parallel to plane... n = &pObj->m_pNodeStandingOn->GetPlane()->m_Normal; } else { // Object standing on another object, so assume opposite to gravity... n = &objectNormal; objectNormal = -pInfo->m_UnitForce; } // Calculate the acceleration including the force LTVector vAccelWithForce = a + vForce; // If we're on a slope that's at enough of an angle, allow it to slide LTVector vForceDir = vForce; vForceDir.Norm(); if (vForceDir.Dot(*n) > pInfo->m_SlideRatio) { float fAccelMag = vAccelWithForce.Mag(); a = vAccelWithForce - *n * n->Dot(vAccelWithForce); // Don't allow it to accelerate up the slope.. float fAccelDotForce = a.Dot(vForceDir); if (fAccelDotForce < 0.0f) { a -= vForceDir * fAccelDotForce; } a.Norm(fAccelMag); // dsi_ConsolePrint("Steep"); } else { // Figure out what our new velocity would be if only the force was used (i.e. are they jumping?) LTVector vNewVel = v + vForce * dt; // If we're going to be moving away from the plane, use the full force if (vNewVel.Dot(*n) > 0.01f) { a = vAccelWithForce; // dsi_ConsolePrint("Jump"); } // If the acceleration without the force isn't moving into the surface, project it there else if (a.Dot(*n) > 0.01f) { float fAccelMag = a.Mag(); a -= *n * (n->Dot(a) + 1.0f); a.Norm(fAccelMag); bFriction = LTTRUE; // dsi_ConsolePrint("Downhill"); } else { bFriction = LTTRUE; // dsi_ConsolePrint("Walk"); } } } } // Otherwise just apply gravity else { a += vForce; // dsi_ConsolePrint("Fall"); } } // If there's no gravity and they aren't moving, then disable their physics else if( velocityMagSqr < 0.1f && accelMagSqr < 0.1f ) { pObj->m_Velocity.Init(); pObj->m_Acceleration.Init(); pObj->m_InternalFlags &= ~IFLAG_APPLYPHYSICS; return; } // If friction // new velocity is given by: v = ( a / k ) + ( v_0 - a / k ) * exp( -k * t ) // new position is given by: x = x_0 + ( a / k ) * t + ( k * v_0 - a ) * ( 1 - exp( -k * t )) / k^2 if( bFriction && pObj->m_FrictionCoefficient > 0.0f ) { // Velocity... fExp = ( float )exp( -pObj->m_FrictionCoefficient * dt ); vTemp = a / pObj->m_FrictionCoefficient; vTemp2 = v - vTemp; vTemp2 *= fExp; vel = vTemp2 + vTemp; // Position delta... dr = vTemp * dt; vTemp = v * pObj->m_FrictionCoefficient; vTemp -= a; vTemp *= (( 1.0f - fExp ) / pObj->m_FrictionCoefficient / pObj->m_FrictionCoefficient); dr += vTemp; pObj->m_Velocity = vel; v = pObj->m_Velocity; } // If no friction // new velocity is given by: v = v_0 + a * t // new position is given by: x = x_0 + v_0 * t + .5 * a * t^2 else { // Find the change in velocity... velocityDelta = a * dt; // Position delta... dr = v * dt; vTemp = a * (timeIntegral * 0.5f); dr += vTemp; // Add the final velocity to the new velocity. pObj->m_Velocity += velocityDelta; v = pObj->m_Velocity; } /* // Show debug information, filtering out the server-side player object if(bApplyGravity) { dsi_ConsolePrint("Old - A:<%7.1f,%7.1f,%7.1f> V:<%7.1f,%7.1f,%7.1f> P:<%7.1f,%7.1f,%7.1f>", VEC_EXPAND(vOldAccel), VEC_EXPAND(vOldVel), VEC_EXPAND(vOldPos)); LTVector vNewAccel, vNewVel, vNewPos; vNewAccel = a; vNewVel = v; vNewPos = vOldPos + dr; dsi_ConsolePrint("New - A:<%7.1f,%7.1f,%7.1f> V:<%7.1f,%7.1f,%7.1f> P:<%7.1f,%7.1f,%7.1f>", VEC_EXPAND(vNewAccel), VEC_EXPAND(vNewVel), VEC_EXPAND(vNewPos)); } //*/ return; }
//given an animation and a keyframe, this will find the dims that encompass the //model bool CDimensionsDlg::FindAnimDims(Model* pModel, uint32 nAnim, uint32 nKeyFrame, LTVector& vDims) { //clear out the dims to start out with in case we fail vDims.Init(); AnimTracker tracker, *pTracker; tracker.m_TimeRef.Init(pModel, nAnim, nKeyFrame, nAnim, nKeyFrame, 0.0f); AnimInfo *pAnim = &pModel->m_Anims[nAnim]; pTracker = &tracker;//pAnim->m_pAnim; static CMoArray<TVert> tVerts; // Use the model code to setup the vertices. int nTrackers = 1; nTrackers = DMIN(nTrackers, MAX_GVP_ANIMS); GVPStruct gvp; gvp.m_nAnims = 0; for(int i = 0; i < nTrackers; i++) { gvp.m_Anims[i] = pTracker[i].m_TimeRef; gvp.m_nAnims++; } LTMatrix m; m.Identity(); int nWantedVerts = pModel->GetTotalNumVerts() * 2; if(tVerts.GetSize() < nWantedVerts) { if(!tVerts.SetSize(nWantedVerts)) return false; } gvp.m_VertexStride = sizeof(TVert); gvp.m_Vertices = tVerts.GetArray(); gvp.m_BaseTransform = m; gvp.m_CurrentLODDist = 0; if (AlternateGetVertexPositions(pModel, &gvp, true, false, false, false)) { LTVector vMax(0, 0, 0); for (i = 0; i < pModel->GetTotalNumVerts(); i ++) { TVert v = tVerts[i]; if (fabs(v.m_vPos.x) > vMax.x) vMax.x = (float)fabs(v.m_vPos.x); if (fabs(v.m_vPos.y) > vMax.y) vMax.y = (float)fabs(v.m_vPos.y); if (fabs(v.m_vPos.z) > vMax.z) vMax.z = (float)fabs(v.m_vPos.z); } // Setup the new dims.... //round max up to the .1 decimal place vMax.x = (float)(ceil(vMax.x * 10.0) / 10.0); vMax.y = (float)(ceil(vMax.y * 10.0) / 10.0); vMax.z = (float)(ceil(vMax.z * 10.0) / 10.0); vDims = vMax; return true; } //failure return false; }
// Wrap the textures, starting at a poly index void CRVTrackerTextureWrap::WrapTexture(CTWPolyInfo *pPoly, const CVector &vWrapDir, CTextExtents &cExtents) const { // Mark this poly as wrapped pPoly->m_bTouched = TRUE; CTexturedPlane& Texture = pPoly->m_pPoly->GetTexture(GetCurrTexture()); // Get the texture space LTVector vWrapO = Texture.GetO(); LTVector vWrapP = Texture.GetP(); LTVector vWrapQ = Texture.GetQ(); // Get the texture offset projections float fWrapOdotP = vWrapO.Dot(vWrapP); float fWrapOdotQ = vWrapO.Dot(vWrapQ); // Update the texturing extents for (uint32 nExtentLoop = 0; nExtentLoop < pPoly->m_aEdges.GetSize(); ++nExtentLoop) { LTVector vEdgePt = pPoly->m_aEdges[nExtentLoop]->m_aPt[0]; float fCurU = vWrapP.Dot(vEdgePt) - fWrapOdotP; float fCurV = vWrapQ.Dot(vEdgePt) - fWrapOdotQ; cExtents.m_fMinU = LTMIN(fCurU, cExtents.m_fMinU); cExtents.m_fMaxU = LTMAX(fCurU, cExtents.m_fMaxU); cExtents.m_fMinV = LTMIN(fCurV, cExtents.m_fMinV); cExtents.m_fMaxV = LTMAX(fCurV, cExtents.m_fMaxV); } CMoArray<uint32> aNeighbors; CMoArray<float> aDots; // Insert the neighbors into a list in dot-product order for (uint32 nNeighborLoop = 0; nNeighborLoop < pPoly->m_aNeighbors.GetSize(); ++nNeighborLoop) { CTWPolyInfo *pNeighbor = pPoly->m_aNeighbors[nNeighborLoop]; // Skip edges that don't have a neighbor if (!pNeighbor) continue; // Skip neighbors that are already wrapped if (pNeighbor->m_bTouched) continue; // Get our dot product float fCurDot = vWrapDir.Dot(pPoly->m_aEdges[nNeighborLoop]->m_Plane.m_Normal); if ((m_bRestrictWalkDir) && (fCurDot < 0.707f)) continue; // Mark this neighbor as touched (to avoid later polygons pushing it onto the stack) pNeighbor->m_bTouched = TRUE; // Insert it into the list for (uint32 nInsertLoop = 0; nInsertLoop < aNeighbors.GetSize(); ++nInsertLoop) { if (fCurDot > aDots[nInsertLoop]) break; } aDots.Insert(nInsertLoop, fCurDot); aNeighbors.Insert(nInsertLoop, nNeighborLoop); } // Recurse through its neighbors for (uint32 nWrapLoop = 0; nWrapLoop < aNeighbors.GetSize(); ++nWrapLoop) { CTWPolyInfo *pNeighbor = pPoly->m_aNeighbors[aNeighbors[nWrapLoop]]; CTWEdgeInfo *pEdge = pPoly->m_aEdges[aNeighbors[nWrapLoop]]; ////////////////////////////////////////////////////////////////////////////// // Wrap this neighbor // Create a matrix representing the basis of the polygon in relation to this edge LTMatrix mPolyBasis; mPolyBasis.SetTranslation(0.0f, 0.0f, 0.0f); mPolyBasis.SetBasisVectors(&pEdge->m_vDir, &pPoly->m_pPoly->m_Plane.m_Normal, &pEdge->m_Plane.m_Normal); // Create a new basis for the neighbor polygon LTMatrix mNeighborBasis; LTVector vNeighborForward; vNeighborForward = pNeighbor->m_pPoly->m_Plane.m_Normal.Cross(pEdge->m_vDir); // Just to be sure.. vNeighborForward.Norm(); mNeighborBasis.SetTranslation(0.0f, 0.0f, 0.0f); mNeighborBasis.SetBasisVectors(&pEdge->m_vDir, &pNeighbor->m_pPoly->m_Plane.m_Normal, &vNeighborForward); // Create a rotation matrix from here to there LTMatrix mRotation; mRotation = mNeighborBasis * ~mPolyBasis; // Rotate the various vectors LTVector vNewP; LTVector vNewQ; LTVector vNewDir; mRotation.Apply3x3(vWrapP, vNewP); mRotation.Apply3x3(vWrapQ, vNewQ); mRotation.Apply3x3(vWrapDir, vNewDir); // Rotate the texture basis if we're following a path if (m_nWrapStyle == k_WrapPath) { LTVector vNeighborEdgeDir; if (GetSimilarEdgeDir(pNeighbor, vNewDir, vNeighborEdgeDir, 0.707f)) { LTMatrix mRotatedNeighbor; LTVector vNeighborRight; vNeighborRight = vNeighborEdgeDir.Cross(pNeighbor->m_pPoly->m_Plane.m_Normal); vNeighborRight.Norm(); // Make sure we're pointing the right way... if (vNeighborRight.Dot(pEdge->m_vDir) < 0.0f) vNeighborRight = -vNeighborRight; mRotatedNeighbor.SetTranslation(0.0f, 0.0f, 0.0f); mRotatedNeighbor.SetBasisVectors(&vNeighborRight, &pNeighbor->m_pPoly->m_Plane.m_Normal, &vNeighborEdgeDir); // Build a basis based on an edge from the current polygon LTVector vBestPolyEdge; GetSimilarEdgeDir(pPoly, vWrapDir, vBestPolyEdge); LTVector vPolyRight = vBestPolyEdge.Cross(pNeighbor->m_pPoly->m_Plane.m_Normal); vPolyRight.Norm(); // Make sure we're pointing the right way... if (vPolyRight.Dot(pEdge->m_vDir) < 0.0f) vPolyRight = -vPolyRight; // Build the poly edge matrix LTMatrix mPolyEdgeBasis; mPolyEdgeBasis.SetTranslation(0.0f, 0.0f, 0.0f); mPolyEdgeBasis.SetBasisVectors(&vPolyRight, &pNeighbor->m_pPoly->m_Plane.m_Normal, &vBestPolyEdge); // Get a matrix from here to there LTMatrix mRotator; mRotator = mRotatedNeighbor * ~mPolyEdgeBasis; // Rotate the texture basis mRotator.Apply3x3(vNewP); mRotator.Apply3x3(vNewQ); // And use the new edge as the new direction vNewDir = vNeighborEdgeDir; } // Remove skew from vNewP/vNewQ if ((float)fabs(vNewP.Dot(vNewQ)) > 0.001f) { float fMagP = vNewP.Mag(); float fMagQ = vNewQ.Mag(); vNewQ *= 1.0f / fMagQ; vNewP -= vNewQ * vNewQ.Dot(vNewP); vNewP.Norm(fMagP); vNewQ *= fMagQ; } } // Get the first edge point.. CVector vEdgePt = pEdge->m_aPt[0]; // Calculate the texture coordinate at this point float fWrapU = vWrapP.Dot(vEdgePt) - fWrapOdotP; float fWrapV = vWrapQ.Dot(vEdgePt) - fWrapOdotQ; // Build the new offset float fNewOdotP = vNewP.Dot(vEdgePt) - fWrapU; float fNewOdotQ = vNewQ.Dot(vEdgePt) - fWrapV; LTVector vNewO; vNewO.Init(); float fNewPMag = vNewP.MagSqr(); if (fNewPMag > 0.0f) vNewO += vNewP * (fNewOdotP / fNewPMag); float fNewQMag = vNewQ.MagSqr(); if (fNewQMag > 0.0f) vNewO += vNewQ * (fNewOdotQ / fNewQMag); pNeighbor->m_pPoly->SetTextureSpace(GetCurrTexture(), vNewO, vNewP, vNewQ); // Recurse into this neighbor WrapTexture(pNeighbor, vNewDir, cExtents); } }
void CLaserBeam::Update(LTVector &vBeamStartPos, const LTRotation* pRDirRot, LTBOOL b3rdPerson, LTBOOL bDetect) { if (!m_bOn) return; // Calculate beam position... HOBJECT hCamera = g_pPlayerMgr->GetCamera(); if (!hCamera) return; HLOCALOBJ hPlayerObj = g_pLTClient->GetClientObject(); if (!hPlayerObj) return; HOBJECT hFilterList[] = {hPlayerObj, g_pPlayerMgr->GetMoveMgr()->GetObject(), LTNULL}; IntersectQuery qInfo; IntersectInfo iInfo; LTVector vPos(0, 0, 0); LTRotation rRot; LTVector vU, vR, vF; if (pRDirRot && b3rdPerson) { vPos = vBeamStartPos; vU = pRDirRot->Up(); vR = pRDirRot->Right(); vF = pRDirRot->Forward(); } else { g_pLTClient->GetObjectRotation(hCamera, &rRot); g_pLTClient->GetObjectPos(hCamera, &vPos); vU = rRot.Up(); vR = rRot.Right(); vF = rRot.Forward(); if (g_cvarLaserBeamDebug.GetFloat() == 0.0f) { vBeamStartPos += vPos; } else if (g_cvarLaserBeamDebug.GetFloat() == 1.0f) { vBeamStartPos = vPos; } else if (pRDirRot) { vU = pRDirRot->Up(); vR = pRDirRot->Right(); vF = pRDirRot->Forward(); vBeamStartPos = vBeamStartPos; } } LTVector vEndPos = vPos + (vF * 10000.0f); qInfo.m_From = vPos; qInfo.m_To = vEndPos; qInfo.m_Flags = INTERSECT_OBJECTS | IGNORE_NONSOLID; qInfo.m_FilterFn = ObjListFilterFn; qInfo.m_pUserData = hFilterList; if (g_pLTClient->IntersectSegment(&qInfo, &iInfo)) { vEndPos = iInfo.m_Point; } // Show the light beam... LTVector vColor = LTVector(GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f), GetRandom(35.0f, 55.0f));; LTFLOAT fAlpha = g_cvarLaserBeamAlpha.GetFloat(); if (iInfo.m_hObject && bDetect) { uint32 dwUsrFlgs = 0; g_pCommonLT->GetObjectFlags(iInfo.m_hObject, OFT_User, dwUsrFlgs); if (dwUsrFlgs & USRFLG_CHARACTER) { fAlpha = 0.95f; vColor.Init(GetRandom(35.0f, 55.0f), GetRandom(235.0f, 255.0f), GetRandom(35.0f, 55.0f));; } } LTFLOAT fWidth = g_cvarLaserBeamThickness.GetFloat(); fWidth = b3rdPerson ? fWidth*2.0f : fWidth; vBeamStartPos += (vF * g_cvarLaserBeamFOffset.GetFloat()); vBeamStartPos += (vR * g_cvarLaserBeamROffset.GetFloat()); vBeamStartPos += (vU * g_cvarLaserBeamUOffset.GetFloat()); PLFXCREATESTRUCT pls; if (g_cvarLaserBeamDebug.GetFloat() >= 0.0f) { // g_pLTClient->CPrint("StartPos = %.2f, %.2f, %.2f", VEC_EXPAND(vBeamStartPos)); // g_pLTClient->CPrint("EndPos = %.2f, %.2f, %.2f", VEC_EXPAND(vEndPos)); } pls.vStartPos = vBeamStartPos; pls.vEndPos = vEndPos; pls.vInnerColorStart = vColor; pls.vInnerColorEnd = pls.vInnerColorStart; pls.vOuterColorStart = LTVector(0, 0, 0); pls.vOuterColorEnd = LTVector(0, 0, 0); pls.fAlphaStart = fAlpha; pls.fAlphaEnd = fAlpha; pls.fMinWidth = 0; pls.fMaxWidth = fWidth; pls.fMinDistMult = 1.0f; pls.fMaxDistMult = 1.0f; pls.fLifeTime = 1.0f; pls.fAlphaLifeTime = 1.0f; pls.fPerturb = 0.0f; pls.bAdditive = LTTRUE; pls.bAlignFlat = b3rdPerson ? LTFALSE : LTTRUE; pls.nWidthStyle = PLWS_CONSTANT; pls.nNumSegments = (int)g_cvarLaserBeamNumSegments.GetFloat(); if (m_LightBeam.HasBeenDrawn()) { // Keep the light beam in the vis list... m_LightBeam.SetPos(vBeamStartPos); // Hide the beam in portals if 1st person...Also set flag really // close to true... uint32 dwFlags2, dwFlags; dwFlags = m_LightBeam.GetFlags(); dwFlags2 = m_LightBeam.GetFlags2(); if (b3rdPerson) { dwFlags &= ~FLAG_REALLYCLOSE; } else { if (g_cvarLaserBeamDebug.GetFloat() > 1.0f) { dwFlags |= FLAG_REALLYCLOSE; pls.bUseObjectRotation = LTTRUE; } } m_LightBeam.SetFlags(dwFlags); m_LightBeam.SetFlags2(dwFlags2); m_LightBeam.ReInit(&pls); } else { m_LightBeam.Init(&pls); m_LightBeam.CreateObject(g_pLTClient); } m_LightBeam.Update(); }
void CGrenade::HandleImpact(HOBJECT hObj) { if (!g_vtGrenadeDampenPercent.IsInitted()) { g_vtGrenadeDampenPercent.Init(g_pLTServer, "GrenadeDampenPercent", LTNULL, DEFAULT_GRENADE_DAMPEN_PERCENT); } if (!g_vtGrenadeMinVelMag.IsInitted()) { g_vtGrenadeMinVelMag.Init(g_pLTServer, "GrenadeMinVelMag", LTNULL, DEFAULT_GRENADE_MIN_VELOCITY); } LTVector vVel; g_pLTServer->GetVelocity(m_hObject, &vVel); // See if we are impacting on liquid... LTBOOL bEnteringLiquid = LTFALSE; uint16 code; if (g_pLTServer->GetContainerCode(hObj, &code)) { if (IsLiquid((ContainerCode)code)) { bEnteringLiquid = LTTRUE; } } CollisionInfo info; g_pLTServer->GetLastCollision(&info); // Do the bounce, if the object we hit isn't liquid... if (!bEnteringLiquid) { vVel += (info.m_vStopVel * 2.0f); } // Dampen the grenade's new velocity based on the surface type... LTFLOAT fDampenPercent = g_vtGrenadeDampenPercent.GetFloat(); m_eLastHitSurface = GetSurfaceType(info); SURFACE* pSurf = g_pSurfaceMgr->GetSurface(m_eLastHitSurface); if (pSurf) { // Play a bounce sound (based on the surface type) if one isn't // already playing... if ( ShouldPlayBounceSound(pSurf) ) { // Only play one sound at a time... if (m_hBounceSnd) { g_pLTServer->KillSound(m_hBounceSnd); m_hBounceSnd = LTNULL; } uint32 dwFlags = PLAYSOUND_GETHANDLE | PLAYSOUND_TIME; int nVolume = IsLiquid(m_eContainerCode) ? 50 : 100; LTVector vPos; g_pLTServer->GetObjectPos(m_hObject, &vPos); m_hBounceSnd = g_pServerSoundMgr->PlaySoundFromPos(vPos, (char*)GetBounceSound(pSurf), pSurf->fGrenadeSndRadius, SOUNDPRIORITY_MISC_MEDIUM, dwFlags, nVolume); } fDampenPercent = (1.0f - pSurf->fHardness); } fDampenPercent = fDampenPercent > 1.0f ? 1.0f : (fDampenPercent < 0.0f ? 0.0f : fDampenPercent); vVel *= (1.0f - fDampenPercent); // See if we should come to a rest... LTVector vTest = vVel; vTest.y = 0.0f; if (vTest.Mag() < g_vtGrenadeMinVelMag.GetFloat()) { // If we're on the ground (or an object), stop movement... CollisionInfo standingInfo; g_pLTServer->GetStandingOn(m_hObject, &standingInfo); CollisionInfo* pInfo = standingInfo.m_hObject ? &standingInfo : &info; if (pInfo->m_hObject) { // Don't stop on walls... if (pInfo->m_Plane.m_Normal.y > 0.75f) { vVel.Init(); // Turn off gravity, solid, and touch notify.... uint32 dwFlags = g_pLTServer->GetObjectFlags(m_hObject); dwFlags &= ~(FLAG_GRAVITY | FLAG_TOUCH_NOTIFY | FLAG_SOLID); g_pLTServer->SetObjectFlags(m_hObject, dwFlags); // Rotate to rest... RotateToRest(); } } } // Reset rotation velocities due to the bounce... ResetRotationVel(&vVel, pSurf); // We need to subtact this out because the engine will add it back in, // kind of a kludge but necessary... vVel -= info.m_vStopVel; g_pLTServer->SetVelocity(m_hObject, &vVel); m_cBounces++; }