//------------------------------------------------------------------------------ // processFirePDU() callback -- //------------------------------------------------------------------------------ void NetIO::processFirePDU(const FirePDU* const pdu) { // Get the Firing Player's ID unsigned short fPlayerId = pdu->firingEntityID.ID; unsigned short fSiteId = pdu->firingEntityID.simulationID.siteIdentification; unsigned short fApplicationId = pdu->firingEntityID.simulationID.applicationIdentification; //std::cout << "NetIO::processFirePDU() fired"; //std::cout << "(" << pdu->firingEntityID.ID; //std::cout << "," << pdu->firingEntityID.simulationID.applicationIdentification ; //std::cout << "," << pdu->firingEntityID.simulationID.siteIdentification; //std::cout << ")" << std::endl; // Ignore our own PDUs if (fSiteId == getSiteID() && fApplicationId == getApplicationID()) return; //pdu->dumpData(); // Get the Munition Player's ID unsigned short mPlayerId = pdu->munitionID.ID; unsigned short mSiteId = pdu->munitionID.simulationID.siteIdentification; unsigned short mApplicationId = pdu->munitionID.simulationID.applicationIdentification; // Get the Target Player's ID unsigned short tPlayerId = pdu->targetEntityID.ID; unsigned short tSiteId = pdu->targetEntityID.simulationID.siteIdentification; unsigned short tApplicationId = pdu->targetEntityID.simulationID.applicationIdentification; // --- // 1) Find the target (local) player // --- Simulation::Player* tPlayer = 0; if (tSiteId == getSiteID() && tApplicationId == getApplicationID()) { // Must be local SPtr<Basic::PairStream> players( getSimulation()->getPlayers() ); tPlayer = getSimulation()->findPlayer(tPlayerId); } //std::cout << "Net Fire(2) tPlayer = " << tPlayer << std::endl; // --- // 2) Find the firing player and munitions (networked) IPlayers // --- Simulation::Nib* fNib = 0; Simulation::Nib* mNib = 0; if (fSiteId != getSiteID() || fApplicationId != getApplicationID()) { // Must be networked players fNib = findDisNib(fPlayerId, fSiteId, fApplicationId, INPUT_NIB); mNib = findDisNib(mPlayerId, mSiteId, mApplicationId, INPUT_NIB); } //std::cout << "Net Fire(3) fNib = " << fNib << ", mNib = " << mNib << std::endl; // --- Nothing really needs to be done. }
//------------------------------------------------------------------------------ // processDetonationPDU() callback -- //------------------------------------------------------------------------------ void NetIO::processDetonationPDU(const DetonationPDU* const pdu) { // Get the Firing Player's ID unsigned short fPlayerId = pdu->firingEntityID.ID; unsigned short fSiteId = pdu->firingEntityID.simulationID.siteIdentification; unsigned short fApplicationId = pdu->firingEntityID.simulationID.applicationIdentification; // Ignore our own PDUs if (fSiteId == getSiteID() && fApplicationId == getApplicationID()) return; // Get the Munition Player's ID unsigned short mPlayerId = pdu->munitionID.ID; unsigned short mSiteId = pdu->munitionID.simulationID.siteIdentification; unsigned short mApplicationId = pdu->munitionID.simulationID.applicationIdentification; // Get the Target Player's ID unsigned short tPlayerId = pdu->targetEntityID.ID; unsigned short tSiteId = pdu->targetEntityID.simulationID.siteIdentification; unsigned short tApplicationId = pdu->targetEntityID.simulationID.applicationIdentification; // --- // 1) Find the target player // --- simulation::Player* tPlayer = nullptr; if (tPlayerId != 0 && tSiteId != 0 && tApplicationId != 0) { simulation::Nib* tNib = findDisNib(tPlayerId, tSiteId, tApplicationId, OUTPUT_NIB); if (tNib != nullptr) { tPlayer = tNib->getPlayer(); } } //std::cout << "Net kill(2) tPlayer = " << tPlayer << std::endl; // --- // 2) Find the firing player and munitions (networked) IPlayers // --- simulation::Player* fPlayer = nullptr; if (fPlayerId != 0 && fSiteId != 0 && fApplicationId != 0) { simulation::Nib* fNib = findDisNib(fPlayerId, fSiteId, fApplicationId, INPUT_NIB); if (fNib != nullptr) { fPlayer = fNib->getPlayer(); } else { base::safe_ptr<base::PairStream> players( getSimulation()->getPlayers() ); fPlayer = getSimulation()->findPlayer(fPlayerId); } } simulation::Nib* mNib = nullptr; if (mPlayerId != 0 && mSiteId != 0 && mApplicationId != 0) { mNib = findDisNib(mPlayerId, mSiteId, mApplicationId, INPUT_NIB); } //std::cout << "Net kill(3) fNib = " << fNib << ", mNib = " << mNib << std::endl; // --- // 3) Update the data of the munition's NIB and player // --- simulation::Weapon* mPlayer = nullptr; if (mNib != nullptr) { // --- // a) Set the munition's NIB to the location of the detonation // --- // Get the geocentric position, velocity and acceleration from the PDU osg::Vec3d geocPos; geocPos[base::Nav::IX] = pdu->location.X_coord; geocPos[base::Nav::IY] = pdu->location.Y_coord; geocPos[base::Nav::IZ] = pdu->location.Z_coord; osg::Vec3d geocVel; geocVel[base::Nav::IX] = pdu->velocity.component[0]; geocVel[base::Nav::IY] = pdu->velocity.component[1]; geocVel[base::Nav::IZ] = pdu->velocity.component[2]; osg::Vec3d geocAcc(0,0,0); osg::Vec3d geocAngles(0,0,0); osg::Vec3d arates(0,0,0); // (re)initialize the dead reckoning function mNib->resetDeadReckoning( simulation::Nib::STATIC_DRM, geocPos, geocVel, geocAcc, geocAngles, arates); // Set the NIB's mode to DETONATED mNib->setMode(simulation::Player::DETONATED); // Find the munition player and set its mode, location and target position mPlayer = dynamic_cast<simulation::Weapon*>(mNib->getPlayer()); if (mPlayer != nullptr) { // Munition's mode mPlayer->setMode(simulation::Player::DETONATED); // munition's position, velocity and acceleration at the time of the detonation mPlayer->setGeocPosition(geocPos); mPlayer->setGeocVelocity(geocVel); mPlayer->setGeocAcceleration(geocAcc); // detonation results mPlayer->setDetonationResults(simulation::Weapon::Detonation(pdu->detonationResult)); // Munition's target player and the location of detonation relative to target mPlayer->setTargetPlayer(tPlayer,false); double x = pdu->locationInEntityCoordinates.component[0]; double y = pdu->locationInEntityCoordinates.component[1]; double z = pdu->locationInEntityCoordinates.component[2]; osg::Vec3 loc(x,y,z); mPlayer->setDetonationLocation(loc); // Munition's launcher if (mPlayer->getLaunchVehicle() == nullptr && fPlayer != nullptr) { mPlayer->setLaunchVehicle(fPlayer); } } } // --- // 4) Check all local players for the effects of the detonation // --- if (mPlayer != nullptr) { mPlayer->checkDetonationEffect(); } }
//------------------------------------------------------------------------------ // IffManager() -- (Output support) IFF manager //------------------------------------------------------------------------------ bool Nib::IffManager(const double curExecTime) { NetIO* disIO = static_cast<NetIO*>(getNetIO()); const base::Pair* pair = getPlayer()->getRadioByType(typeid(models::Iff)); // OK if the player has an IFF transponder and we're the correct version. bool ok = (disIO->getVersion() >= NetIO::VERSION_1278_1A) && (pair != nullptr); if (ok) { const models::Iff* iffSystem = static_cast<const models::Iff*>(pair->object()); if (isIffUpdateRequired(curExecTime, iffSystem)) { // Standard header stuff IffAtcNavaidsPDU pdu; pdu.header.protocolVersion = disIO->getVersion(); pdu.header.exerciseIdentifier = disIO->getExerciseID(); pdu.header.PDUType = NetIO::PDU_IFF_ATC_NAVAIDS; pdu.header.protocolFamily = NetIO::PDU_FAMILY_DIS_EMISSION_REG; pdu.header.timeStamp = disIO->timeStamp(); pdu.header.length = sizeof(IffAtcNavaidsPDU); // Entity ID pdu.emittingEntityID.simulationID.siteIdentification = getSiteID(); pdu.emittingEntityID.simulationID.applicationIdentification = getApplicationID(); pdu.emittingEntityID.ID = getPlayerID(); // Location (default is center of parent entity) pdu.location.component[0] = 0; pdu.location.component[1] = 0; pdu.location.component[2] = 0; // System ID (for now just use a standard Mark X11; upgrade to type from IFF later) pdu.systemID.systemType = 1; // Mark X11 pdu.systemID.systemName = 2; // Mark X11 pdu.systemID.systemMode = 0; // Other pdu.systemID.options = iffOptions; // Option bits // Functional operational data pdu.operationalData.systemStatus = iffFunOpData->systemStatus; pdu.operationalData.alternateParam4 = iffFunOpData->alternateParam4; pdu.operationalData.informationLayers = iffFunOpData->informationLayers; pdu.operationalData.modifier = iffFunOpData->modifier; pdu.operationalData.param1 = iffFunOpData->param1; pdu.operationalData.param2 = iffFunOpData->param2; pdu.operationalData.param3 = iffFunOpData->param3; pdu.operationalData.param4 = iffFunOpData->param4; pdu.operationalData.param5 = iffFunOpData->param5; pdu.operationalData.param6 = iffFunOpData->param6; // Event ID pdu.eventID.simulationID.siteIdentification = disIO->getSiteID(); pdu.eventID.simulationID.applicationIdentification = disIO->getApplicationID(); pdu.eventID.eventNumber = disIO->getNewIffEventID(); //pdu.dumpData(); if (base::NetHandler::isNotNetworkByteOrder()) pdu.swapBytes(); ok = disIO->sendData(reinterpret_cast<char*>(&pdu), sizeof(pdu)); iffLastExecTime = curExecTime; } } return ok; }
//------------------------------------------------------------------------------ // entityStateManager() -- (Output support) // -- Update the entity object for this NIB(Player) //------------------------------------------------------------------------------ bool Nib::entityStateManager(const LCreal curExecTime) { bool ok = false; // Get the player pointer const Simulation::Player* player = getPlayer(); if (player == nullptr) return ok; // Dummy weapon? const Simulation::Weapon* ww = dynamic_cast<const Simulation::Weapon*>( player ); if (ww != nullptr) { if (ww->isDummy()) return ok; } if (isPlayerStateUpdateRequired(curExecTime)) { // // Send an entity state PDU // 1) create buffer // 2) set state information // 3) send data // // Get our NetIO and the main simulation NetIO* disIO = static_cast<NetIO*>(getNetIO()); Simulation::Simulation* sim = disIO->getSimulation(); // Capture the player data, reset the dead reckoning and // mark the current time. playerState2Nib(); // --- // Create buffer and cast it as an entity state PDU // --- char pduBuffer[NetIO::MAX_PDU_SIZE]; EntityStatePDU* pdu = (EntityStatePDU*) &pduBuffer[0]; // // Entity state PDU structure // ========================================================= // PDUHeader header; // EntityIdentifierDIS entityID; // uint8_t forceID; // uint8_t numberOfArticulationParameters; // EntityType entityType; // EntityType alternativeType; // VectorDIS entityLinearVelocity; // WorldCoordinates entityLocation; // EulerAngles entityOrientation; // uint32_t appearance; // uint8_t deadReckoningAlgorithm; // uint8_t otherParameters[15]; // VectorDIS DRentityLinearAcceleration; // AngularVelocityVectorDIS DRentityAngularVelocity; // EntityMarking entityMarking; // uint32_t capabilities; // ========================================================= // // --- // Standard header (PDUHeader) // --- pdu->header.protocolVersion = disIO->getVersion(); pdu->header.exerciseIdentifier = disIO->getExerciseID(); pdu->header.PDUType = NetIO::PDU_ENTITY_STATE; pdu->header.protocolFamily = NetIO::PDU_FAMILY_ENTITY_INFO; // if (disIO->getTimeline() == Simulation::NetIO::UTC) pdu->header.timeStamp = disIO->makeTimeStamp( getTimeUtc(), true ); else pdu->header.timeStamp = disIO->makeTimeStamp( getTimeExec(), false ); // pdu->header.status = 0; pdu->header.padding = 0; // --- // Entity ID (EntityIdentifierID) // --- pdu->entityID.simulationID.siteIdentification = getSiteID(); pdu->entityID.simulationID.applicationIdentification = getApplicationID(); pdu->entityID.ID = getPlayerID(); // --- // Force ID: When mapping Player side to force IDs ... // --- if (getSide() == Simulation::Player::BLUE) { // blue's are friendly, ... pdu->forceID = NetIO::FRIENDLY_FORCE; } else if (getSide() == Simulation::Player::RED) { // red's are not, ... pdu->forceID = NetIO::OPPOSING_FORCE; } else if (getSide() == Simulation::Player::WHITE) { // white is neutral, ... pdu->forceID = NetIO::NEUTRAL_FORCE; } else { // and everyone else is type OTHER. pdu->forceID = NetIO::OTHER_FORCE; } // --- // Entity type (EntityType) // --- pdu->entityType.kind = getEntityKind(); pdu->entityType.domain = getEntityDomain(); pdu->entityType.country = getEntityCountry(); pdu->entityType.category = getEntityCategory(); pdu->entityType.subcategory = getEntitySubcategory(); pdu->entityType.specific = getEntitySpecific(); pdu->entityType.extra = getEntityExtra(); // --- // Alternative type (EntityType) // --- pdu->alternativeType.kind = getEntityKind(); pdu->alternativeType.domain = getEntityDomain(); pdu->alternativeType.country = getEntityCountry(); pdu->alternativeType.category = getEntityCategory(); pdu->alternativeType.subcategory = getEntitySubcategory(); pdu->alternativeType.specific = getEntitySpecific(); pdu->alternativeType.extra = getEntityExtra(); // --- // Player position and orientation state data data // 1) All data is geocentric (ECEF) // 2) The playerState2Nib() function, which was called above, captures // the state data and passed the state data to the dead reckoning // system, and we're using this DR captured data. // --- { // --- // Entity linear velocity (VectorDIS) // --- osg::Vec3d geocVel = getDrVelocity(); pdu->entityLinearVelocity.component[0] = static_cast<float>(geocVel[0]); pdu->entityLinearVelocity.component[1] = static_cast<float>(geocVel[1]); pdu->entityLinearVelocity.component[2] = static_cast<float>(geocVel[2]); // --- // Entity location (WorldCoordinates) // --- osg::Vec3d geocPos = getDrPosition(); pdu->entityLocation.X_coord = geocPos[Basic::Nav::IX]; pdu->entityLocation.Y_coord = geocPos[Basic::Nav::IY]; pdu->entityLocation.Z_coord = geocPos[Basic::Nav::IZ]; // --- // Entity orientation (EulerAngles) // --- osg::Vec3d geocAngles = getDrEulerAngles(); pdu->entityOrientation.phi = static_cast<float>(geocAngles[Basic::Nav::IPHI]); pdu->entityOrientation.theta = static_cast<float>(geocAngles[Basic::Nav::ITHETA]); pdu->entityOrientation.psi = static_cast<float>(geocAngles[Basic::Nav::IPSI]); } // --- // Appearance bits generic to all domains (except munitions) // --- { pdu->appearance = 0x0; // --- // Frozen? // --- if ( isFrozen() || sim->isFrozen() ) { pdu->appearance |= FROZEN_BIT; } // Deactive this entity? { if (isMode(Simulation::Player::DELETE_REQUEST) || player->isDead() ) pdu->appearance |= DEACTIVATE_BIT; } // Damage or health? (Bits 3-4) { unsigned int bits = 0; if (getDamage() > 0.9f) bits = 3; // Destroyed or Fatality else if (getDamage() > 0.5) bits = 2; // Moderate else if (getDamage() > 0.0) bits = 1; // Slight else bits = 0; // None pdu->appearance |= (bits << 3); } // Camouflage type // Note: air platform appearance bits 17 and 18 are not used, but we're using them the same as land platforms { unsigned int bits = getCamouflageType(); if (bits > 0 && bits <= 4) { pdu->appearance |= CAMOUFLAGE_BIT; // Land based camouflage bits if (player->isMajorType(Simulation::Player::GROUND_VEHICLE)) { // Subtract one to match DIS camouflage bits. // Our camouflage type for DIS is the camouflage appearance bits // plus one because our camouflage type of zero is no camouflage. bits--; pdu->appearance |= (bits << 17); } } } // Life forms appearance bits if (player->isMajorType(Simulation::Player::LIFE_FORM)) { const Simulation::LifeForm* lf = dynamic_cast<const Simulation::LifeForm*>(player); if (lf != nullptr) { // Health (aka damaged for other domains) same bits (3-4) - this is from the NIB, because it IS // updated // bits 5-8 compliance (not implemented) // bits 9 - 11 unused // bit 12 flashlight (not implemented) // bits 13-15 unused // bits 16 - 19 life form state // data is from the player, because NIB doesn't have actions associated with it { unsigned int bits = 1; // upright, standing still if (lf->getActionState() == Simulation::LifeForm::UPRIGHT_STANDING) bits = 1; // standing else if (lf->getActionState() == Simulation::LifeForm::UPRIGHT_WALKING) bits = 2; // walking else if (lf->getActionState() == Simulation::LifeForm::UPRIGHT_RUNNING) bits = 3; // running else if (lf->getActionState() == Simulation::LifeForm::KNEELING) bits = 4; // kneeling else if (lf->getActionState() == Simulation::LifeForm::PRONE) bits = 5; // prone else if (lf->getActionState() == Simulation::LifeForm::CRAWLING) bits = 6; // crawling else if (lf->getActionState() == Simulation::LifeForm::SWIMMING) bits = 7; // swimming else if (lf->getActionState() == Simulation::LifeForm::PARACHUTING) bits = 8; // parachuting else if (lf->getActionState() == Simulation::LifeForm::JUMPING) bits = 9; // jumping else if (lf->getActionState() == Simulation::LifeForm::SITTING) bits = 10; // sitting else if (lf->getActionState() == Simulation::LifeForm::SQUATTING) bits = 11; // squatting else if (lf->getActionState() == Simulation::LifeForm::CROUCHING) bits = 12; // crouching else if (lf->getActionState() == Simulation::LifeForm::WADING) bits = 13; // wading else if (lf->getActionState() == Simulation::LifeForm::SURRENDER) bits = 14; // surrender else if (lf->getActionState() == Simulation::LifeForm::DETAINED) bits = 15; // detained else bits = 1; pdu->appearance |= (bits << 16); } // bit 20 unused // bit 21 frozen status (taken care of above) // bits 24 - 25 weapon 1 (not implemented) // bits 26-27 weapon 2 (N/I) // bits 28-29 } } // Common Non-life form appearance bits else { // Smoking? (Bits 5-6) Standard (IST-CF-03-01, May 5, 2003) { unsigned int bits = 0; if (getSmoke() > 0.9f) bits = 3; else if (getSmoke() > 0.5) bits = 2; else if (getSmoke() > 0.0) bits = 1; else bits = 0; pdu->appearance |= (bits << 5); } // Flames? (Bit 15) Standard (IST-CF-03-01, May 5, 2003) { if (getFlames() > 0.5f) pdu->appearance |= FLAMES_BIT; } // Power plant status bit (just leave ON for now) pdu->appearance |= POWER_PLANT_BIT; } } // --- // Dead reckoning algorithm // --- pdu->deadReckoningAlgorithm = static_cast<unsigned char>(getDeadReckoning()); // --- // Other parameters // --- for (unsigned int i=0; i<15; i++) { pdu->otherParameters[i] = 0; } // --- // Dead reckoning information // --- { // --- // Dead reckoning linear acceleration (VectorDIS) // --- osg::Vec3d geocAcc = getDrAcceleration(); pdu->DRentityLinearAcceleration.component[0] = static_cast<float>(geocAcc[0]); pdu->DRentityLinearAcceleration.component[1] = static_cast<float>(geocAcc[1]); pdu->DRentityLinearAcceleration.component[2] = static_cast<float>(geocAcc[2]); // --- // Dead reckoning angular velocity (AngularVelocityVectorDIS) // --- osg::Vec3d geocAngVel = getDrAngularVelocities(); pdu->DRentityAngularVelocity.x_axis = static_cast<float>(geocAngVel[Basic::Nav::IX]); pdu->DRentityAngularVelocity.y_axis = static_cast<float>(geocAngVel[Basic::Nav::IY]); pdu->DRentityAngularVelocity.z_axis = static_cast<float>(geocAngVel[Basic::Nav::IZ]); } // --- // Entity marking (EntityMarking) // --- { const char* const pName = getPlayerName(); size_t nameLen = std::strlen(pName); for (unsigned int i = 0; i < EntityMarking::BUFF_SIZE; i++) { if (i < nameLen) { pdu->entityMarking.marking[i] = pName[i]; } else { pdu->entityMarking.marking[i] = '\0'; } } pdu->entityMarking.characterSet = 1; } // --- // Capabilities // --- pdu->capabilites = 0x0; // --- // Articulation parameters // --- pdu->numberOfArticulationParameters = manageArticulationParameters(pdu); // Size of the PDU package unsigned short length = sizeof(EntityStatePDU) + (pdu->numberOfArticulationParameters * sizeof(VpArticulatedPart)); pdu->header.length = length; if (Basic::NetHandler::isNotNetworkByteOrder()) pdu->swapBytes(); ok = disIO->sendData( reinterpret_cast<char*>(pdu), length ); } return ok; }
//------------------------------------------------------------------------------ // munitionDetonationMsgFactory() -- (Output) Munition detonation message factory //------------------------------------------------------------------------------ bool Nib::munitionDetonationMsgFactory(const LCreal) { // Dummy weapon? const Simulation::Weapon* ww = dynamic_cast<const Simulation::Weapon*>( getPlayer() ); if (ww != 0) { if (ww->isDummy()) return true; } bool ok = true; //std::cout << "NetIO::munitionDetonationMsgFactory() HERE!!" << std::endl; // Get our NetIO NetIO* disIO = (NetIO*)(getNetIO()); // If our NIB's player just detonated, then it must be a weapon! Simulation::Weapon* mPlayer = dynamic_cast<Simulation::Weapon*>(getPlayer()); if (mPlayer == 0) return false; // Ok, we have the weapon, now get the firing and target players Simulation::Player* tPlayer = mPlayer->getTargetPlayer(); Simulation::Player* fPlayer = mPlayer->getLaunchVehicle(); if (fPlayer == 0) return false; // --- // PDU header // --- DetonationPDU pdu; pdu.header.protocolVersion = disIO->getVersion(); pdu.header.PDUType = NetIO::PDU_DETONATION; pdu.header.protocolFamily = NetIO::PDU_FAMILY_WARFARE; pdu.header.length = sizeof(DetonationPDU); pdu.header.exerciseIdentifier = disIO->getExerciseID(); pdu.header.timeStamp = disIO->timeStamp(); pdu.header.status = 0; pdu.header.padding = 0; // --- // Set the PDU data with the firing (launcher) player's id // --- pdu.firingEntityID.ID = fPlayer->getID(); pdu.firingEntityID.simulationID.siteIdentification = getSiteID(); pdu.firingEntityID.simulationID.applicationIdentification = getApplicationID(); // --- // Set the PDU data with the munition's ID // --- pdu.munitionID.ID = mPlayer->getID(); pdu.munitionID.simulationID.siteIdentification = getSiteID(); pdu.munitionID.simulationID.applicationIdentification = getApplicationID(); // --- // Set the PDU data with the target's ID // --- { bool tOk = false; if (tPlayer != 0) { pdu.targetEntityID.ID = tPlayer->getID(); if (tPlayer->isLocalPlayer()) { // Local player, use our site/app/exerc IDs pdu.targetEntityID.simulationID.siteIdentification = getSiteID(); pdu.targetEntityID.simulationID.applicationIdentification = getApplicationID(); tOk = true; } else { // Networked player, use its NIB's IDs const Nib* fNIB = dynamic_cast<const Nib*>( tPlayer->getNib() ); if (fNIB != 0) { pdu.targetEntityID.simulationID.siteIdentification = fNIB->getSiteID(); pdu.targetEntityID.simulationID.applicationIdentification = fNIB->getApplicationID(); tOk = true; } } } if (!tOk) { pdu.targetEntityID.ID = 0; pdu.targetEntityID.simulationID.siteIdentification = 0; pdu.targetEntityID.simulationID.applicationIdentification = 0; } } // --- // Event ID // --- pdu.eventID.simulationID.siteIdentification = getSiteID(); pdu.eventID.simulationID.applicationIdentification = getApplicationID(); pdu.eventID.eventNumber = mPlayer->getReleaseEventID(); // --- // Location & Velocity // --- // World Coordinates osg::Vec3d geocPos = mPlayer->getGeocPosition(); pdu.location.X_coord = geocPos[Basic::Nav::IX]; pdu.location.Y_coord = geocPos[Basic::Nav::IY]; pdu.location.Z_coord = geocPos[Basic::Nav::IZ]; // Velocity osg::Vec3d geocVel = mPlayer->getGeocVelocity(); pdu.velocity.component[0] = (float)geocVel[Basic::Nav::IX]; pdu.velocity.component[1] = (float)geocVel[Basic::Nav::IY]; pdu.velocity.component[2] = (float)geocVel[Basic::Nav::IZ]; // --- // Burst // --- pdu.burst.munition.kind = getEntityKind(); pdu.burst.munition.domain = getEntityDomain(); pdu.burst.munition.country = getEntityCountry(); pdu.burst.munition.category = getEntityCategory(); pdu.burst.munition.subcategory = getEntitySubcategory(); pdu.burst.munition.specific = getEntitySpecific(); pdu.burst.munition.extra = getEntityExtra(); pdu.burst.warhead = 0; pdu.burst.fuse = 0;; pdu.burst.quantity = 1; pdu.burst.rate = 0; // --- // Location // --- osg::Vec3 lpos = mPlayer->getDetonationLocation(); pdu.locationInEntityCoordinates.component[0] = (float) lpos[0]; pdu.locationInEntityCoordinates.component[1] = (float) lpos[1]; pdu.locationInEntityCoordinates.component[2] = (float) lpos[2]; // --- // Results // --- pdu.detonationResult = (unsigned char)( mPlayer->getDetonationResults() ); pdu.numberOfArticulationParameters = 0; //std::cout << "NetIO::munitionDetonationMsgFactory() results: " << int(pdu.detonationResult) << std::endl; //pdu.dumpData(); // --- // Send the PDU // --- if (Basic::NetHandler::isNotNetworkByteOrder()) pdu.swapBytes(); ok = disIO->sendData((char*)&pdu,sizeof(pdu)); // Set the detonation message sent flag so that we don't do this again. setDetonationMessageSent(true); return ok; }
//------------------------------------------------------------------------------ // updateBasicEntity() -- (Output support) // -- sets the BasicEntity attribute values that need to be updated // // -- We send all published BasicEntity attributes every time. // // The function isPlayerStateUpdateRequired() checking if the player's state // needs to be resent. Therefore, we're not check the individual update // required flags with isAttributeUpdateRequired(), but we do clear them // with setAttributeUpdateRequiredFlag(). // // (Also handles the host to network byte swapping) //------------------------------------------------------------------------------ void Nib::updateBasicEntity( RTI::AttributeHandleValuePairSet* attrs, const double) { if (baseEntity != nullptr) { // Our handler NetIO* netIO = static_cast<NetIO*>(getNetIO()); // Our simulation simulation::Simulation* ourSim = netIO->getSimulation(); // Get the player data playerState2Nib(); // Entity ID if (isAttributeUpdateEnabled(NetIO::ENTITY_IDENTIFIER_AI)) { EntityIdentifierStruct* entityId = &baseEntity->entityIdentifier; entityId->federateIdentifier.siteID = getSiteID(); entityId->federateIdentifier.applicationID = getApplicationID(); entityId->entityNumber = getPlayerID(); //std::cout << "Send Federate ID: (" << entityId->entityNumber << "," << entityId->federateIdentifier.applicationID << "," << entityId->federateIdentifier.siteID << ")" << std::endl; EntityIdentifierStruct netBuffer; base::NetHandler::toNetOrder(&netBuffer.federateIdentifier.applicationID, entityId->federateIdentifier.applicationID ); base::NetHandler::toNetOrder(&netBuffer.federateIdentifier.siteID, entityId->federateIdentifier.siteID ); base::NetHandler::toNetOrder(&netBuffer.entityNumber, entityId->entityNumber ); attrs->add(netIO->getObjectAttributeHandle( NetIO::ENTITY_IDENTIFIER_AI), reinterpret_cast<char*>(&netBuffer), sizeof(EntityIdentifierStruct) ); setAttributeUpdateRequiredFlag(NetIO::ENTITY_IDENTIFIER_AI, false); } // Entity Type if (isAttributeUpdateEnabled(NetIO::ENTITY_TYPE_AI)) { EntityTypeStruct* entityType = &baseEntity->entityType; entityType->entityKind = getEntityKind(); entityType->domain = getEntityDomain(); entityType->countryCode = getEntityCountry(); entityType->category = getEntityCategory(); entityType->subcategory = getEntitySubcategory(); entityType->specific = getEntitySpecific(); entityType->extra = getEntityExtra(); // Network byte order: all bytes except country code which is unsigned short. EntityTypeStruct netBuffer = *entityType; base::NetHandler::toNetOrder(&netBuffer.countryCode, entityType->countryCode ); attrs->add(netIO->getObjectAttributeHandle( NetIO::ENTITY_TYPE_AI), reinterpret_cast<char*>(&netBuffer), sizeof(EntityTypeStruct) ); setAttributeUpdateRequiredFlag(NetIO::ENTITY_TYPE_AI, false); } // Spatial Structure if (isAttributeUpdateEnabled(NetIO::SPATIAL_AI)) { osg::Vec3d pos = getDrPosition(); osg::Vec3d vel = getDrVelocity(); osg::Vec3d accel = getDrAcceleration(); osg::Vec3d angles = getDrEulerAngles(); osg::Vec3d arates = getDrAngularVelocities(); // NIB's base entity structures SpatialStruct* spatial = &(baseEntity->spatial); SpatialRVStruct* spatialRvw = &(baseEntity->spatialRvw); // Net order buffer (used to send the attribute to the RTI) const unsigned int SPATIAL_NET_BUFFER_SIZE = sizeof(SpatialStruct) + sizeof(SpatialRVStruct); unsigned char netBuffer[SPATIAL_NET_BUFFER_SIZE]; SpatialStruct* netSpatial = reinterpret_cast<SpatialStruct*>(&netBuffer[0]); SpatialRVStruct* netSpatialRvw = reinterpret_cast<SpatialRVStruct*>(&netBuffer[sizeof(SpatialStruct)]); // Ref Position double refLat = 0.0; double refLon = 0.0; if (ourSim != nullptr) { refLat = ourSim->getRefLatitude(); refLon = ourSim->getRefLongitude(); } // Convert position vector to Lat/Lon/Alt double alt = 0.0; double simCoord[3] = { 0.0, 0.0, 0.0 }; base::Nav::convertPosVec2LL( refLat, refLon, pos, &simCoord[base::Nav::ILAT], &simCoord[base::Nav::ILON], &alt ); simCoord[base::Nav::IALT] = alt; //std::cout << "RprFom::Nib::entityState2Nib(): simCoord(" << simCoord[Basic::Nav::ILAT] << "," << simCoord[Basic::Nav::ILON] << "," << simCoord[Basic::Nav::IALT] << ")" << std::endl; // Convert to geocentric coordinates double geocPos[3] = { 0.0, 0.0, 0.0 }; double geocVel[3] = { 0.0, 0.0, 0.0 }; double geocAcc[3] = { 0.0, 0.0, 0.0 }; base::Nav::getWorldPosAccVel(simCoord, vel.ptr(), accel.ptr(), geocPos, geocVel, geocAcc); // Dead reckoning algorithm { spatial->deadReckoningAlgorithm = DRM_RVW; netSpatial->deadReckoningAlgorithm = spatial->deadReckoningAlgorithm; } // Is Frozen? { bool simFrz = false; if (ourSim != nullptr) simFrz = ourSim->isFrozen(); if (isFrozen() || simFrz) spatialRvw->isFrozen = RTI::RTI_TRUE; // Is this object or the simulation frozen? else spatialRvw->isFrozen = RTI::RTI_FALSE; netSpatialRvw->isFrozen = spatialRvw->isFrozen; } // World Location { WorldLocationStruct* worldLocation = &spatialRvw->worldLocation; WorldLocationStruct* netWorldLocation = &netSpatialRvw->worldLocation; worldLocation->x = geocPos[base::Nav::IX]; worldLocation->y = geocPos[base::Nav::IY]; worldLocation->z = geocPos[base::Nav::IZ]; base::NetHandler::toNetOrder(&netWorldLocation->x, worldLocation->x); base::NetHandler::toNetOrder(&netWorldLocation->y, worldLocation->y); base::NetHandler::toNetOrder(&netWorldLocation->z, worldLocation->z); } // Velocity vector { VelocityVectorStruct* velocityVector = &spatialRvw->velocityVector; VelocityVectorStruct* netVelocityVector = &netSpatialRvw->velocityVector; velocityVector->xVelocity = static_cast<RTI::Float>(geocVel[base::Nav::IX]); velocityVector->yVelocity = static_cast<RTI::Float>(geocVel[base::Nav::IY]); velocityVector->zVelocity = static_cast<RTI::Float>(geocVel[base::Nav::IZ]); base::NetHandler::toNetOrder(&netVelocityVector->xVelocity, velocityVector->xVelocity); base::NetHandler::toNetOrder(&netVelocityVector->yVelocity, velocityVector->yVelocity); base::NetHandler::toNetOrder(&netVelocityVector->zVelocity, velocityVector->zVelocity); } // Acceleration vector { AccelerationVectorStruct* accelerationVector = &spatialRvw->accelerationVector; AccelerationVectorStruct* netAccelerationVector = &netSpatialRvw->accelerationVector; accelerationVector->xAcceleration = static_cast<RTI::Float>(geocAcc[base::Nav::IX]); accelerationVector->yAcceleration = static_cast<RTI::Float>(geocAcc[base::Nav::IY]); accelerationVector->zAcceleration = static_cast<RTI::Float>(geocAcc[base::Nav::IZ]); base::NetHandler::toNetOrder(&netAccelerationVector->xAcceleration, accelerationVector->xAcceleration); base::NetHandler::toNetOrder(&netAccelerationVector->yAcceleration, accelerationVector->yAcceleration); base::NetHandler::toNetOrder(&netAccelerationVector->zAcceleration, accelerationVector->zAcceleration); } // Orientation { OrientationStruct* orientation = &spatialRvw->orientation; OrientationStruct* netOrientation = &netSpatialRvw->orientation; // Convert Euler angles to geocentric angles double geocAngles[3] = { 0.0, 0.0, 0.0 }; base::Nav::getGeocAngle(simCoord, angles.ptr(), geocAngles); orientation->phi = static_cast<RTI::Float>(geocAngles[base::Nav::IPHI]); orientation->theta = static_cast<RTI::Float>(geocAngles[base::Nav::ITHETA]); orientation->psi = static_cast<RTI::Float>(geocAngles[base::Nav::IPSI]); base::NetHandler::toNetOrder(&netOrientation->phi, orientation->phi); base::NetHandler::toNetOrder(&netOrientation->theta, orientation->theta); base::NetHandler::toNetOrder(&netOrientation->psi, orientation->psi); } // Angular velocity vector (all zeros for now) { AngularVelocityVectorStruct* angularVelocityVector = &spatialRvw->angularVelocity; AngularVelocityVectorStruct* netAngularVelocityVector = &netSpatialRvw->angularVelocity; angularVelocityVector->xAngularVelocity = 0; angularVelocityVector->yAngularVelocity = 0; angularVelocityVector->zAngularVelocity = 0; base::NetHandler::toNetOrder(&netAngularVelocityVector->xAngularVelocity, angularVelocityVector->xAngularVelocity); base::NetHandler::toNetOrder(&netAngularVelocityVector->yAngularVelocity, angularVelocityVector->yAngularVelocity); base::NetHandler::toNetOrder(&netAngularVelocityVector->zAngularVelocity, angularVelocityVector->zAngularVelocity); } attrs->add( netIO->getObjectAttributeHandle(NetIO::SPATIAL_AI), reinterpret_cast<char*>(&netBuffer), SPATIAL_NET_BUFFER_SIZE ); setAttributeUpdateRequiredFlag(NetIO::SPATIAL_AI, false); } } }