// // 创建物理场景 // BOOL CSceneManager::CreatePhysicsScene(VOID) { for (EntityMap::const_iterator itEntity = m_meshs.begin(); itEntity != m_meshs.end(); ++itEntity) { const CEntityMesh *pEntityMesh = (const CEntityMesh *)itEntity->second; ASSERT(pEntityMesh); const CSubMesh *pPhysicsMesh = pEntityMesh->GetPhysicsSubMesh(); if (pPhysicsMesh == NULL) continue; if (pEntityMesh->IsEnablePhysicsQuery() == FALSE && pEntityMesh->IsEnablePhysicsSimulation() == FALSE) continue; const VEC3 *position = pEntityMesh->GetSceneNode()->GetWorldPosition(); const QUAT *orientation = pEntityMesh->GetSceneNode()->GetWorldOrientation(); const PxTransform pxLocalPose(PxVec3(0.0f, 0.0f, 0.0f)); const PxTransform pxGlobalPose(PxVec3((*position)[0], (*position)[1], (*position)[2]), PxQuat((*orientation)[0], (*orientation)[1], (*orientation)[2], (*orientation)[3])); const PxMaterial &pxMaterial = GetPhysicsStandardMaterial((MATERIAL_TYPE)pEntityMesh->GetPhysicsMaterial()->GetPhysics()->GetType()); const PxFilterData pxQueryFilterData = PxFilterData(QUERY_FLAGS_SCENE_MESH, 0, 0, 0); const PxFilterData pxSimulationFilterData = PxFilterData(SIMULATION_FLAGS_WORD0[pEntityMesh->GetPhysicsSimulationTypeIndex()], SIMULATION_FLAGS_WORD1[pEntityMesh->GetPhysicsSimulationTypeIndex()], 0, 0); PxRigidActor *pPxRigidActor = (PxRigidActor *)m_physics.CreateRigidActor(pEntityMesh->GetSceneNode()->GetName(), pxGlobalPose, FALSE, TRUE, TRUE); PxShape *pPxShape = PxCreateShapeMesh(pPxRigidActor, pPhysicsMesh->GetVertexBuffer(), pPhysicsMesh->GetVertexCount(), pPhysicsMesh->GetFaceBuffer(), pPhysicsMesh->GetFaceCount(), pxMaterial, pxLocalPose, pEntityMesh->IsEnablePhysicsQuery(), pEntityMesh->IsEnablePhysicsSimulation(), pxQueryFilterData, pxSimulationFilterData); pPxShape->userData = pEntityMesh->userData; } return TRUE; }
BOOL obj_ItemSpawnPoint::Update() { static int delayCheckSpawnPointsInAir = 100; if(delayCheckSpawnPointsInAir) --delayCheckSpawnPointsInAir; if(g_bEditMode && m_bEditorCheckSpawnPointAtStart && delayCheckSpawnPointsInAir ==0) { m_bEditorCheckSpawnPointAtStart = false; for(ITEM_SPAWN_POINT_VECTOR::iterator it=m_SpawnPointsV.begin(); it!=m_SpawnPointsV.end(); ++it) { PxVec3 from(it->pos.x, it->pos.y+1.0f, it->pos.z); PxRaycastHit hit; PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK,0,0,0), PxSceneQueryFilterFlags(PxSceneQueryFilterFlag::eSTATIC)); if(g_pPhysicsWorld->raycastSingle(from, PxVec3(0,-1,0), 10000, PxSceneQueryFlags(PxSceneQueryFlag::eIMPACT), hit, filter)) { r3dPoint3D hitPos(hit.impact.x, hit.impact.y, hit.impact.z); if(R3D_ABS(it->pos.y - hitPos.y) > 2.0f) { r3dArtBug("Item CP Spawn at %.2f, %.2f, %.2f has spawn position(s) in the air. Please select it and use Check Locations button\n", GetPosition().x, GetPosition().y, GetPosition().z); break; } } } r3dShowArtBugs(); } return parent::Update(); }
BOOL obj_Bullet::Update() { parent::Update(); const GameObject* owner = GameWorld().GetObject(ownerID); if( m_CreationTime+5.0f < r3dGetTime() ) // Bullets should only live for 5 seconds. { // yeah your dead. if(owner && owner->NetworkLocal) { PKT_C2C_PlayerHitNothing_s n; p2pSendToHost(owner, &n, sizeof(n), true); } return false; } r3dVector dir = (GetPosition() - oldstate.Position); if(dir.Length()==0) dir = m_FireDirection; // perform collision check m_AppliedVelocity += r3dVector(0, -9.81f, 0) * m_Weapon->m_AmmoMass * r3dGetFrameTime(); r3dPoint3D motion = m_AppliedVelocity * r3dGetFrameTime(); float motionLen = motion.Length(); motion.Normalize(); PxU32 collisionFlag = COLLIDABLE_STATIC_MASK; if(owner && owner->NetworkLocal) collisionFlag |= (1<<PHYSCOLL_NETWORKPLAYER); PxSphereGeometry sphere(0.0025f); // Make it tiny. 5 milimeter diameter PxTransform pose(PxVec3(GetPosition().x, GetPosition().y, GetPosition().z), PxQuat(0,0,0,1)); PxSweepHit hit; PxSceneQueryFilterData filter(PxFilterData(collisionFlag, 0, 0, 0), PxSceneQueryFilterFlag::eSTATIC|PxSceneQueryFilterFlag::eDYNAMIC); if(g_pPhysicsWorld->PhysXScene->sweepSingle(sphere, pose, PxVec3(motion.x, motion.y, motion.z), motionLen, PxSceneQueryFlag::eINITIAL_OVERLAP|PxSceneQueryFlag::eIMPACT|PxSceneQueryFlag::eNORMAL, hit, filter)) { // if the hit is the final stop. if ( OnHit(hit) ) { return false; } } else { // perform movement SetPosition(GetPosition() + m_AppliedVelocity * r3dGetFrameTime()); } if(m_ParticleTracer) m_ParticleTracer->SetPosition(GetPosition()); return true; }
void obj_DroppedItem::UpdateObjectPositionAfterCreation() { if(!PhysicsObject) return; PxActor* actor = PhysicsObject->getPhysicsActor(); if(!actor) return; PxBounds3 pxBbox = actor->getWorldBounds(); PxVec3 pxCenter = pxBbox.getCenter(); // place object on the ground, to prevent excessive bouncing { PxRaycastHit hit; PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK, 0, 0, 0), PxSceneQueryFilterFlag::eSTATIC); if(g_pPhysicsWorld->raycastSingle(PxVec3(pxCenter.x, pxCenter.y, pxCenter.z), PxVec3(0, -1, 0), 50.0f, PxSceneQueryFlag::eIMPACT, hit, filter)) { SetPosition(r3dPoint3D(hit.impact.x, hit.impact.y+0.1f, hit.impact.z)); } } }
float obj_ItemSpawnPoint::DrawPropertyEditor(float scrx, float scry, float scrw, float scrh, const AClass* startClass, const GameObjects& selected) { float starty = scry; starty += parent::DrawPropertyEditor(scrx, scry, scrw,scrh, startClass, selected ); if( IsParentOrEqual( &ClassData, startClass ) ) { starty += imgui_Static ( scrx, starty, "Item Spawn Point Parameters" ); starty += imgui_Value_Slider(scrx, starty, "Tick Period (sec)", &m_TickPeriod, 1.0f, 50000.0f, "%.2f"); starty += imgui_Value_Slider(scrx, starty, "Cooldown (sec)", &m_Cooldown, 1.0f, 50000.0f, "%.2f"); starty += imgui_Value_Slider(scrx, starty, "De-spawn (sec)", &m_DestroyItemTimer, 0.0f, 50000.0f, "%.2f"); int isOneItemSpawn = m_OneItemSpawn?1:0; starty += imgui_Checkbox(scrx, starty, "One Item Spawn", &isOneItemSpawn, 1); m_OneItemSpawn = isOneItemSpawn?true:false; if(!m_OneItemSpawn) { static stringlist_t lootBoxNames; static int* lootBoxIDs = NULL; static int numLootBoxes = 0; if(numLootBoxes == 0) { struct tempS { char* name; uint32_t id; }; std::vector<tempS> lootBoxes; { tempS holder; holder.name = "EMPTY"; holder.id = 0; lootBoxes.push_back(holder); } g_pWeaponArmory->startItemSearch(); while(g_pWeaponArmory->searchNextItem()) { uint32_t itemID = g_pWeaponArmory->getCurrentSearchItemID(); const BaseItemConfig* cfg = g_pWeaponArmory->getConfig(itemID); if( cfg->category == storecat_LootBox ) { tempS holder; holder.name = cfg->m_StoreName; holder.id = cfg->m_itemID; lootBoxes.push_back(holder); } } numLootBoxes = (int)lootBoxes.size(); lootBoxIDs = new int[numLootBoxes]; for(int i=0; i<numLootBoxes; ++i) { lootBoxNames.push_back(lootBoxes[i].name); lootBoxIDs[i] = lootBoxes[i].id; } } int sel = 0; static float offset = 0; for(int i=0; i<numLootBoxes; ++i) if(m_LootBoxID == lootBoxIDs[i]) sel = i; starty += imgui_Static ( scrx, starty, "Loot box:" ); if(imgui_DrawList(scrx, starty, 360, 122, lootBoxNames, &offset, &sel)) { m_LootBoxID = lootBoxIDs[sel]; PropagateChange( m_LootBoxID, &obj_ItemSpawnPoint::m_LootBoxID, this, selected ) ; } starty += 122; } else { starty += imgui_Value_SliderI(scrx, starty, "ItemID", (int*)&m_LootBoxID, 0, 1000000, "%d", false); PropagateChange( m_LootBoxID, &obj_ItemSpawnPoint::m_LootBoxID, this, selected ) ; } // don't allow multi edit of this if( selected.Count() <= 1 ) { { if(imgui_Button(scrx, starty, 200, 25, "Check locations")) { for(ITEM_SPAWN_POINT_VECTOR::iterator it=m_SpawnPointsV.begin(); it!=m_SpawnPointsV.end(); ++it) { PxVec3 from(it->pos.x, it->pos.y+1.0f, it->pos.z); PxRaycastHit hit; PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK,0,0,0), PxSceneQueryFilterFlags(PxSceneQueryFilterFlag::eSTATIC)); if(g_pPhysicsWorld->raycastSingle(from, PxVec3(0,-1,0), 10000, PxSceneQueryFlags(PxSceneQueryFlag::eIMPACT), hit, filter)) { r3dPoint3D hitPos(hit.impact.x, hit.impact.y, hit.impact.z); if(R3D_ABS(it->pos.y - hitPos.y) > 2.0f) { gCam = it->pos + r3dPoint3D(0,1,0); break; } } } } starty += 30; } if(imgui_Button(scrx+110, starty, 100, 25, "Add Location")) { ItemSpawn itemSpawn; itemSpawn.pos = GetPosition() + r3dPoint3D(2, 0, 2); m_SpawnPointsV.push_back(itemSpawn); m_SelectedSpawnPoint = m_SpawnPointsV.size()-1; } starty += 25; int i=0; for(ITEM_SPAWN_POINT_VECTOR::iterator it=m_SpawnPointsV.begin(); it!=m_SpawnPointsV.end(); ) { // selection button char tempStr[32]; sprintf(tempStr, "Location %d", i+1); if(imgui_Button(scrx, starty, 100, 25, tempStr, i==m_SelectedSpawnPoint)) { // shift click on location will set camera to it if(Keyboard->IsPressed(kbsLeftShift)) { extern BaseHUD* HudArray[6]; extern int CurHUDID; HudArray[CurHUDID]->FPS_Position = m_SpawnPointsV[i].pos; HudArray[CurHUDID]->FPS_Position.y += 0.1f; } m_SelectedSpawnPoint = i; } // delete button if(m_SpawnPointsV.size() > 1) { if(imgui_Button(scrx + 110, starty, 100, 25, "DEL")) { it = m_SpawnPointsV.erase(it); continue; } m_SelectedSpawnPoint = R3D_CLAMP(m_SelectedSpawnPoint, 0, (int)m_SpawnPointsV.size()-1); } starty += 25; ++it; ++i; } extern r3dPoint3D UI_TargetPos; if((Mouse->IsPressed(r3dMouse::mLeftButton)) && Keyboard->IsPressed(kbsLeftControl)) m_SpawnPointsV[m_SelectedSpawnPoint].pos = UI_TargetPos; } } return starty-scry; }
void obj_Grenade::onExplode() { // if owner disappeared, do nothing. const GameObject* owner = GameWorld().GetObject(ownerID); if(!owner) return; bool closeToGround = false; PxRaycastHit hit; PxSceneQueryFilterData filter(PxFilterData(COLLIDABLE_STATIC_MASK, 0, 0, 0), PxSceneQueryFilterFlag::eSTATIC); if(g_pPhysicsWorld->raycastSingle(PxVec3(GetPosition().x, GetPosition().y+1, GetPosition().z), PxVec3(0, -1, 0), 50.0f, PxSceneQueryFlag::eDISTANCE, hit, filter)) { if(hit.distance < 5.0f) closeToGround = true; } if(closeToGround) { // add decal DecalParams params; params.Dir = lastCollisionNormal; params.Pos = GetPosition(); params.TypeID = GetDecalID( r3dHash::MakeHash(""), r3dHash::MakeHash(m_Weapon->m_PrimaryAmmo->getDecalSource()) ); if( params.TypeID != INVALID_DECAL_ID ) g_pDecalChief->Add( params ); } //check for underwater splash r3dPoint3D waterSplashPos; extern bool TraceWater(const r3dPoint3D& start, const r3dPoint3D& finish, r3dPoint3D& waterSplashPos); if( TraceWater( GetPosition() - r3dPoint3D(0.0f, m_Weapon->m_AmmoArea, 0.0f), GetPosition() + r3dPoint3D(0.0f, m_Weapon->m_AmmoArea, 0.0f), waterSplashPos)) { SpawnImpactParticle(r3dHash::MakeHash("Water"), r3dHash::MakeHash(m_Weapon->m_PrimaryAmmo->getDecalSource()), waterSplashPos, r3dPoint3D(0,1,0)); extern void WaterSplash(const r3dPoint3D& waterSplashPos, float height, float size, float amount, int texIdx); WaterSplash(GetPosition(), m_Weapon->m_AmmoArea, 10.0f/m_Weapon->m_AmmoArea, 0.04f, 1); } SpawnImpactParticle(r3dHash::MakeHash(""), r3dHash::MakeHash(m_Weapon->m_PrimaryAmmo->getDecalSource()), GetPosition(), r3dPoint3D(0,1,0)); // Start radial blur effect gExplosionVisualController.AddExplosion(GetPosition(), m_Weapon->m_AmmoArea); // for now hard coded for flash bang grenade if(m_Weapon->m_itemID == 101137) { // only apply flashbank for local player if(gClientLogic().localPlayer_ && !gClientLogic().localPlayer_->bDead) { // check that player can actually see explosion (need better test, for when explosion is behind wall) bool explosionVisible = r3dRenderer->IsSphereInsideFrustum(GetPosition(), 2.0f)>0; if(explosionVisible) { float radiusAdd = 0.0f; float durationAdd = 0.0f; float dist = (GetPosition()-gClientLogic().localPlayer_->GetPosition()).Length(); float str = 1.0f - R3D_CLAMP(dist / (GPP->c_fFlashBangRadius+radiusAdd), 0.0f, 1.0f); if (str > 0.01f) { FlashBangEffectParams fbep; fbep.duration = (GPP->c_fFlashBangDuration+durationAdd) * str; fbep.pos = GetPosition(); gFlashbangVisualController.StartEffect(fbep); } } } } // do damage only if owner is local player, otherwise we will broadcast damage multiple times r3d_assert(owner); if(owner->NetworkLocal) { gClientLogic().ApplyExplosionDamage(GetPosition(), m_Weapon->m_AmmoArea, 0, r3dVector(0,0,0), 360.0f); } setActiveFlag(0); #if APEX_ENABLED // Apply apex destructions g_pApexWorld->ApplyAreaDamage(m_Weapon->m_AmmoDamage * 0.01f, 1, GetPosition(), m_Weapon->m_AmmoArea, true); #endif }