//------------------------------------------------------------------------ void CVehicleDamageBehaviorBlowTire::Activate(bool activate) { if (activate == m_isActive) return; if (activate && m_pVehicle->IsDestroyed()) return; if (activate) { // NOTE: stance and physics position when getting into vehicles is set wrong if (!gEnv->pSystem->IsSerializingFile()) DamagePlayers(); } IVehicleComponent* pComponent = m_pVehicle->GetComponent(m_component.c_str()); if (!pComponent) return; IVehiclePart* pPart = pComponent->GetPart(0); if (!pPart) return; // if IVehicleWheel available, execute full damage behavior. if null, only apply effects IVehicleWheel* pWheel = pPart->GetIWheel(); if (activate) { IEntity* pEntity = m_pVehicle->GetEntity(); IPhysicalEntity* pPhysics = pEntity->GetPhysics(); const Matrix34& wheelTM = pPart->GetLocalTM(false); const SVehicleStatus& status = m_pVehicle->GetStatus(); if (pWheel) { const pe_cargeomparams* pParams = pWheel->GetCarGeomParams(); // handle destroyed wheel pe_params_wheel wheelParams; wheelParams.iWheel = pWheel->GetWheelIndex(); wheelParams.minFriction = wheelParams.maxFriction = 0.5f * pParams->maxFriction; pPhysics->SetParams(&wheelParams); if (IVehicleMovement* pMovement = m_pVehicle->GetMovement()) { SVehicleMovementEventParams params; params.pComponent = pComponent; params.iValue = pWheel->GetWheelIndex(); pMovement->OnEvent(IVehicleMovement::eVME_TireBlown, params); } if (status.speed > 0.1f) { // add angular impulse pe_action_impulse angImp; float amount = m_pVehicle->GetMass() * status.speed * Random(0.25f, 0.45f) * -sgn(wheelTM.GetTranslation().x); angImp.angImpulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount)); pPhysics->Action(&angImp); } m_aiImmobilizedTimer = m_pVehicle->SetTimer(-1, AI_IMMOBILIZED_TIME*1000, this); } if (!gEnv->pSystem->IsSerializingFile()) { // add linear impulse pe_action_impulse imp; imp.point = pPart->GetWorldTM().GetTranslation(); float amount = m_pVehicle->GetMass() * Random(0.1f, 0.15f); if (pWheel) { amount *= max(0.5f, min(10.f, status.speed)); if (status.speed < 0.1f) amount = -0.5f*amount; } else amount *= 0.5f; imp.impulse = pEntity->GetWorldTM().TransformVector(Vec3(0,0,amount)); pPhysics->Action(&imp); // effect IParticleEffect* pEffect = gEnv->pParticleManager->FindEffect(TIRE_BLOW_EFFECT); if (pEffect) { int slot = pEntity->LoadParticleEmitter(-1, pEffect); if (slot > -1) { float rotation = pWheel ? 0.5f * gf_PI * -sgn(wheelTM.GetTranslation().x) : gf_PI; Matrix34 tm = Matrix34::CreateRotationZ(rotation); tm.SetTranslation(wheelTM.GetTranslation()); pEntity->SetSlotLocalTM(slot, tm); } } // remove affected decals { Vec3 pos = pPart->GetWorldTM().GetTranslation(); AABB aabb = pPart->GetLocalBounds(); float radius = aabb.GetRadius(); Vec3 vRadius(radius,radius,radius); AABB areaBox(pos-vRadius, pos+vRadius); IRenderNode * pRenderNode = NULL; if (IEntityRenderProxy *pRenderProxy = (IEntityRenderProxy*)pEntity->GetProxy(ENTITY_PROXY_RENDER)) pRenderNode = pRenderProxy->GetRenderNode(); gEnv->p3DEngine->DeleteDecalsInRange(&areaBox, pRenderNode); } } } else { if (pWheel) { // restore wheel properties IPhysicalEntity* pPhysics = m_pVehicle->GetEntity()->GetPhysics(); pe_params_wheel wheelParams; for (int i=0; i<m_pVehicle->GetWheelCount(); ++i) { const pe_cargeomparams* pParams = m_pVehicle->GetWheelPart(i)->GetIWheel()->GetCarGeomParams(); wheelParams.iWheel = i; wheelParams.bBlocked = 0; wheelParams.suspLenMax = pParams->lenMax; wheelParams.bDriving = pParams->bDriving; wheelParams.minFriction = pParams->minFriction; wheelParams.maxFriction = pParams->maxFriction; pPhysics->SetParams(&wheelParams); } if (IVehicleMovement* pMovement = m_pVehicle->GetMovement()) { SVehicleMovementEventParams params; params.pComponent = pComponent; params.iValue = pWheel->GetWheelIndex(); // reset the particle status pMovement->OnEvent(IVehicleMovement::eVME_TireRestored, params); } } m_aiImmobilizedTimer = -1; } m_isActive = activate; }
bool CGutModel::CreateSphere(float radius, sVertexDecl *pVertexDecl, int stacks, int slices) { Release(); m_pMeshArray = new sModelMesh[1]; sModelMesh *pMesh = m_pMeshArray; if ( NULL==pMesh ) return false; m_pMeshArray[0].m_pVertexChunks = new sModelVertexChunk[1]; sModelVertexChunk *pVertexChunk = m_pMeshArray[0].m_pVertexChunks; if ( NULL==pVertexChunk ) return false; if ( pVertexDecl ) pVertexChunk->m_VertexDecl = *pVertexDecl; int num_vertices = (stacks+1)*(slices+1); int num_triangles = stacks*slices*2; int num_indices = num_triangles * 3; m_pMeshArray[0].m_iNumVertexChunks = 1; pVertexChunk->m_pVertexArray = new sModelVertex[num_vertices]; sModelVertex *pVertices = pVertexChunk->m_pVertexArray; if ( NULL==pVertices ) return false; pVertexChunk->m_pBatchArray = new sModelBatch[1]; sModelBatch *pBatch = pVertexChunk->m_pBatchArray; if ( NULL==pBatch ) return false; m_iNumMeshes = 1; m_iNumFaces = num_triangles; m_iNumVertices = num_vertices; pMesh->m_iNumFaces = num_triangles; pMesh->m_iNumVertices = num_vertices; pBatch->m_iNumIndices = num_indices; pBatch->m_iNumPrimitives = num_triangles; pBatch->m_iNumVertices = num_vertices; pBatch->m_iIndexArrayBegin = 0; pBatch->m_iIndexArrayEnd = num_indices; pVertexChunk->m_iNumBatches = 1; pVertexChunk->m_iNumIndices = num_indices; pVertexChunk->m_iNumVertices = num_vertices; pVertexChunk->m_iNumPrimitives = num_triangles; Vector4 vDefaultColor(1.0f); Vector4 vRadius(radius); const float theta_start_degree = 0.0f; const float theta_end_degree = 360.0f; const float phi_start_degree = -90.0f; const float phi_end_degree = 90.0f; float ts = FastMath::DegToRad(theta_start_degree); float te = FastMath::DegToRad(theta_end_degree); float ps = FastMath::DegToRad(phi_start_degree); float pe = FastMath::DegToRad(phi_end_degree); float theta_total = te - ts; float phi_total = pe - ps; float theta_inc = theta_total/stacks; float phi_inc = phi_total/slices; float ty_start = 1.0f; float ty_step = -1.0f/(float)slices; float tx_start = 1.0f; float tx_step = -1.0f/(float)stacks; Vector4 vTexcoord(tx_start, ty_start, 0.0f); int i,j; int index = 0; float theta = ts; for ( i=0; i<=stacks; i++ ) { float phi = ps; float sin_theta, cos_theta; FastMath::SinCos(theta, sin_theta, cos_theta); for ( j=0; j<=slices; j++, index++ ) { float sin_phi, cos_phi; FastMath::SinCos(phi, sin_phi, cos_phi); Vector4 vNormal(cos_phi * cos_theta, sin_phi, cos_phi * sin_theta); // Position pVertices[index].m_Position = vRadius * vNormal; // Normal pVertices[index].m_Normal = vNormal; // Color pVertices[index].m_Color = vDefaultColor; // Texcoord pVertices[index].m_Texcoord[0] = vTexcoord; // inc phi phi += phi_inc; // inc texcoord vTexcoord[1] += ty_step; } // inc theta theta += theta_inc; // reset & inc texcoord vTexcoord[0] += tx_step; vTexcoord[1] = ty_start; } // build index array unsigned short *pIndices = new unsigned short[num_triangles*3]; if ( pIndices==NULL ) { delete [] pVertices; return false; } pVertexChunk->m_pIndexArray = pIndices; int base = 0; index = 0; // triangle list for ( i=0; i<stacks; i++ ) { for ( j=0; j<slices; j++ ) { pIndices[index++] = base; pIndices[index++] = base+1; pIndices[index++] = base+slices+1; pIndices[index++] = base+1; pIndices[index++] = base+slices+2; pIndices[index++] = base+slices+1; base++; } base++; } return true; }