void LifeForm::move(const LCreal fwd, const LCreal sdws) { if (getDamage() < 1) { osg::Vec3 old = getEulerAngles(); LCreal hdg = old.z(); LCreal tempFwd = fwd, tempSdws = sdws; // our deadband (if we are barely moving, just stop) if (lcAbs(tempFwd) < 0.9f) tempFwd = 0; if (lcAbs(tempSdws) < 0.9f) tempSdws = 0; const double xVel = tempFwd * (lcCos(hdg)); const double yVel = tempFwd * (lcSin(hdg)); // now calculate our sideways velocity const double xxVel = tempSdws * (lcCos((hdg + (90 * static_cast<LCreal>(Basic::Angle::D2RCC))))); const double yyVel = tempSdws * (lcSin((hdg + (90 * static_cast<LCreal>(Basic::Angle::D2RCC))))); // now add the vectors const double newXVel = xVel + xxVel; const double newYVel = yVel + yyVel; LCreal zVel = 0.0; setVelocity(static_cast<LCreal>(newXVel), static_cast<LCreal>(newYVel), zVel); } else setVelocity(0, 0, 0); }
// override our set velocity, so we can determine if we are walking, running, or standing bool LifeForm::setVelocity(const LCreal ue, const LCreal ve, const LCreal we) { bool ok = BaseClass::setVelocity(ue, ve, we); // based on our velocity, we will run or walk, or stand still const LCreal tempX = lcAbs(ue); const LCreal tempY = lcAbs(ve); // we only change our appearance bit if we are parachuting if (actionState != PARACHUTING) { // test for running and walking if (tempX == 0 && tempY == 0) actionState = UPRIGHT_STANDING; if (tempX > 0 || tempY > 0) actionState = UPRIGHT_WALKING; if (tempX > 8 || tempY > 8) actionState = UPRIGHT_RUNNING; } return ok; }
//------------------------------------------------------------------------------ // drawFunc() -- draws the object(s) //------------------------------------------------------------------------------ void DialArcSegment::drawFunc() { // get our data from our base class LCreal startAngle = getStartAngle(); LCreal radius = getRadius(); LCreal sweepAngle = getSweepAngle(); GLint curSlices = getSlices(); // our slice amount should go up as we get more of a sweep, if not, it will // look funny. Pretty much one slice per degree sweep LCreal y = lcAbs(static_cast<LCreal>(sweepAngle)); curSlices = curSlices + static_cast<GLint>(y * 0.05f); // draw our arc glPushMatrix(); GLUquadric* qobj = gluNewQuadric(); if (filled) gluQuadricDrawStyle(qobj, GL_FILL); else gluQuadricDrawStyle(qobj, GLU_SILHOUETTE); gluPartialDisk(qobj, radius, outerRadius, curSlices, 1, startAngle, sweepAngle); gluDeleteQuadric(qobj); glPopMatrix(); }
//------------------------------------------------------------------------------ // updateData() -- update non time-critical stuff here //------------------------------------------------------------------------------ void TestElectronic::updateData(const LCreal dt) { BaseClass::updateData(dt); updateTestValues(dt); // current heading / current heading bug { // max rate here is 120 degs / second LCreal delta = alim(lcAepcDeg(heading - curHdg), 120 * dt); curHdg = lcAepcDeg(curHdg + delta); // now figure our heading bug delta = alim(lcAepcDeg(headingBug - curBug), 120 * dt); curBug = lcAepcDeg(curBug + delta); if (navMode == ARC_MODE) { // we either move it to the left or right, depending on how far // off our slew is. LCreal diff = lcAepcDeg(curHdg - curBug); LCreal moveX = -1.8f; if (diff >= -36 && diff < 36) { if (diff > 0) moveX = 1.53f; else moveX = -1.8f; } int tempCurBug = static_cast<int>(curBug); if (tempCurBug < 0) tempCurBug += 360; // heading bug readout value and x position. send("bugro", UPDATE_VALUE, tempCurBug, hdgBugROSD); send("headingbugro", UPDATE_VALUE, moveX, hdgBugROMoveXSD); // heading bug actual position send("headingbug", UPDATE_VALUE6, heading - curBug, headingBugSD); } } // distance data / DME { // are we a distance type or DME type? bool distType = true; // initial type is DME bool distVis = true; // initial visibility is true LCreal curDist = alim(dist, 999.9f); // current distance to DME if (navSource == PRIMARY) { // valid DME makes our label visible distVis = dmeValid; if (navType == INAV) distType = false; } else if (navSource == SECONDARY) { // valid DME makes our label visible distVis = secDmeValid; if (secNavType == INAV) distType = false; else distVis = true; } send("distlabel", SELECT, distType, distTypeSD); send("distval", SET_VISIBILITY, distVis, distVisSD); send("distval", UPDATE_VALUE, curDist, curDistSD); } // course data { // which course pointer are we using? send("whichcourseptr", SELECT, navSource, whichCrsPtrSD); int curIntCourse = 0; LCreal tempCDI = 0; LCreal tempCourse = 0; // primary nav course if (navSource == PRIMARY) { curIntCourse = nint(course); tempCDI = cdi; tempCourse = course; } // secondary nav course else { curIntCourse = nint(secCourse); tempCDI = secCdi; tempCourse = secCourse; } if (curIntCourse < 0) curIntCourse += 360; // send the course readout send("course", UPDATE_VALUE, curIntCourse, courseSD); // here is the course deviation LCreal delta = alim (lcAepcDeg(tempCDI - curCdi), 4 * dt); curCdi = alim (curCdi + delta, 2.0); // now find our inches to translate the cdi LCreal cdiInch = curCdi * 0.43f; // now figure our course slew delta = alim(lcAepcDeg(tempCourse - curCourse), 120 * dt); curCourse = (lcAepcDeg(curCourse + delta)); // ok, do our color determination for the course pointer - primary first if (navSource == PRIMARY) { // dealing with our primary course pointer here bool vis = true; if (navMode == MAP_MODE || navMode == DECLUTTER) vis = false; send("primarycoursepointer", SET_VISIBILITY, vis, primaryCrsVisSD); // course pointer deviation and rotation send("primarycoursedev", UPDATE_VALUE, cdiInch, priCourseDevSD); send("primarycoursepointer", UPDATE_VALUE6, heading - curCourse, crsPntrSD); // course pointer color Basic::String* string = new Basic::String("white"); if (navType == VORTAC) { if ((vhfReceive && !(vhfDIC || vhfLGS)) || (vhfLocValid && vhfLGS)) string->setStr("green"); else string->setStr("yellow"); } else { if (dmeValid) string->setStr("green"); else string->setStr("yellow"); } send("primarycoursepointer", SET_COLOR, string->getString(), priCrsPtrColorSD); // get rid of our string string->unref(); } else { // secondary course pointer bool vis = true; if (secNavMode == MAP_MODE || secNavMode == DECLUTTER) vis = false; send("secondarycoursepointer", SET_VISIBILITY, vis, secondaryCrsVisSD); // course pointer deviation and rotation send("secondarycoursedev", UPDATE_VALUE, cdiInch, secCourseDevSD); send("secondarycoursepointer", UPDATE_VALUE2, curCourse - heading, secCrsPntrSD); // course pointer color Basic::String* string = new Basic::String("white"); if (secNavType == VORTAC) { if ((secVhfReceive && !(secVhfDIC || secVhfLGS)) || (secVhfLocValid && secVhfLGS)) string->setStr("green"); else string->setStr("yellow"); } else { if (secDmeValid) string->setStr("green"); else string->setStr("yellow"); } send("secondarycoursepointer", SET_COLOR, string->getString(), secCrsPtrColorSD); // get rid of our string string->unref(); } } // our data readouts (TTG, Gs, etc...) { // which readout are we using send("whichlabel", SELECT, readoutMode, roLabelSD); // send which readout we are going to use send("whichreadout", SELECT, readoutMode, roWhichSD); // first readout, which is our time to go if (readoutMode == ND_TTG) { LCreal curTTG = timeToGo / 60; send("ttg", UPDATE_VALUE, curTTG, ttgSD); } // ground speed, drift angle, drift angle side. else if (readoutMode == ND_GSP) { // ground speed send("groundspeed", UPDATE_VALUE, groundSpeed, groundSpeedSD); // drift angle send("driftangle", UPDATE_VALUE, abs(driftAngle), driftAngleSD); if (driftAngle < 0) send("driftangleside", SELECT, true, driftAngSideSD); else send("driftangleside", SELECT, false, driftAngSideSD); } // true air speed else if (readoutMode == ND_TAS) { int curTAS = nintd(trueAirSpeed * Basic::LinearVelocity::FPS2KTSCC); send("trueairspeed", UPDATE_VALUE, curTAS, trueAirSpeedSD); } // elapsed time else if (readoutMode == ND_ET) { int hour = static_cast<int>(elapsedTime / 3600); bool isMin = false; // default to show hours if (hour < 1) { isMin = true; // show in minutes send("elapsedtimemin", UPDATE_VALUE, elapsedTime, elapsedTimeSD); } else send("elapsedtimehour", UPDATE_VALUE, elapsedTime, elapsedTimeHRSD); // send which readout send("whichelapsedtimero", SELECT, isMin, whichETSD); } // wind speed, direction, and drift angle (again) else if (readoutMode == ND_WIND) { // wind direction send("winddirection", UPDATE_VALUE, windDir, windDirectionSD); // wind speed send("windspeed", UPDATE_VALUE, windSpeed, windSpeedSD); // wind drift angle (same as drift angle for test purposes) send("driftanglewind", UPDATE_VALUE, abs(driftAngle), driftAngleWindSD); bool left = false; // false is right side, true is left // drift angle side if (driftAngle < 0) left = true; send("driftanglewindside", SELECT, left, whichSideDAWindSD); } } // bearing readouts { // determine the source of our bearing int brgSrc = 1; // default to INAV if (navSource == PRIMARY) { if (navType == VORTAC) brgSrc = 2; // primary vortac else if (navType == TACAN) brgSrc = 3; // primary tacan send("bearingro", UPDATE_VALUE, bearing, brgROSD); } else { if (secNavType == VORTAC) brgSrc = 4; // secondary vortac else brgSrc = 5; // secondary tacan send("bearingro", UPDATE_VALUE, secBearing, secBrgROSD); } send("bearingsource", SELECT, brgSrc, brgSourceSD); } // glide slope { LCreal gsDev = static_cast<LCreal>(alim (gsDots, 2.1f) * 0.35f); send("glideslopedev", UPDATE_VALUE2, gsDev, glideSlopeSD); } // compass { // let's do decentered for both, and hsi mode will just set displacement to 0 send("compass", UPDATE_VALUE6, false, centeredSD); // send our compass heading send("compass", UPDATE_VALUE, curHdg, compassHdgSD); } // primary and secondary readout indicators (with asterisk) { // first of all, which position is the asterisk going in (primary or secondary?) send("whichnavsource", SELECT, navSource, whichNavSrcSD); // primary nav source selection int primaryPos = 1; // 1 is INAV if (navType == VORTAC) { // pilot if (loc == PILOT) { if (vhfLGS) primaryPos = 2; else primaryPos = 3; } // copilot else { if (vhfLGS) primaryPos = 4; else primaryPos = 5; } } else if (navType == TACAN) primaryPos = 6; send("whichprimaryreadout", SELECT, primaryPos, primaryPosSD); // now do our secondary source selections int secondaryPos = 1; if (secNavType == VORTAC) { // pilot if (loc == PILOT) { if (secVhfLGS) secondaryPos = 2; else secondaryPos = 3; } // copilot else { if (secVhfLGS) secondaryPos = 4; else secondaryPos = 5; } } else if (secNavType == TACAN) secondaryPos = 6; send("whichsecondaryreadout", SELECT, secondaryPos, secondaryPosSD); } // TO / FROM arrow - HSI mode only { LCreal toFrom = 0; if (navSource == PRIMARY) toFrom = 1 - lcAbs(lcAepcDeg(bearing - course)) / 90; else toFrom = 1 - lcAbs(lcAepcDeg(secBearing - secCourse)) / 90; LCreal delta = alim(toFrom - curToFrom, dt); curToFrom = alim(curToFrom + delta, 0.65f); // if we are positive, we are to, negative, from bool whichToFrom = (curToFrom > 0); send("toorfrom", SELECT, whichToFrom, toOrFromSD); // now send down where to translate send("tofrom", UPDATE_VALUE2, curToFrom, toFromSD); } }
//------------------------------------------------------------------------------ // setMaxRange() -- sets the max visual range //------------------------------------------------------------------------------ bool Otw::setMaxRange(const LCreal r) { maxRange = lcAbs(r); return true; }
void LifeForm::look(const LCreal up, const LCreal sdws) { if (getDamage() < 1) { if (lockMode != LOCKED) { lockMode = SEARCHING; // our up and sideways come in as -5 to 5, which is a rate to adjust heading const osg::Vec3 old = getEulerAngles(); LCreal hdg = old.z(); LCreal ptc = lookAngle; LCreal tempSdws = sdws; LCreal tempUp = up; if (lcAbs(tempSdws) < 0.00005) tempSdws = 0; if (lcAbs(tempUp) < 0.05) tempUp = 0; hdg += tempSdws; hdg = lcAepcRad(hdg); // we don't change our pitch when we look up and down, we only change our look angle, so we have to keep // that separate. WE do, however, change our heading based on where we are looking, so that is correct ptc += tempUp; if (ptc > 90) ptc = 90; else if (ptc < -90) ptc = -90; //std::cout << "HEADING = " << hdg << std::endl; setLookAngle(ptc); osg::Vec3 eul(0, 0, hdg); setEulerAngles(eul); // now based on this we need to know if we have a target in our crosshairs... tgtAquired = false; if (tgtPlayer != nullptr) tgtPlayer->unref(); tgtPlayer = nullptr; const osg::Vec3 myPos = getPosition(); osg::Vec3 tgtPos; osg::Vec3 vecPos; LCreal az = 0.0, el = 0.0, range = 0.0, diffAz = 0.0, diffEl = 0.0; const LCreal maxAz = (0.7f * static_cast<LCreal>(Basic::Angle::D2RCC)); const LCreal maxEl = (0.7f * static_cast<LCreal>(Basic::Angle::D2RCC)); //LCreal maxRange = 1500.0f; // long range right now const LCreal la = lookAngle * static_cast<LCreal>(Basic::Angle::D2RCC); Simulation* sim = getSimulation(); if (sim != nullptr) { Basic::PairStream* players = sim->getPlayers(); if (players != nullptr) { Basic::List::Item* item = players->getFirstItem(); while (item != nullptr && !tgtAquired) { Basic::Pair* pair = static_cast<Basic::Pair*>(item->getValue()); if (pair != nullptr) { Player* player = dynamic_cast<Player*>(pair->object()); if (player != nullptr && player != this && !player->isMajorType(WEAPON) && !player->isDestroyed()) { // ok, calculate our position from this guy tgtPos = player->getPosition(); vecPos = tgtPos - myPos; az = lcAtan2(vecPos.y(), vecPos.x()); range = (vecPos.x() * vecPos.x() + vecPos.y() * vecPos.y()); range = std::sqrt(range); // now get our elevation el = lcAtan2(-vecPos.z(), range); diffAz = lcAbs(lcAepcRad(az - static_cast<LCreal>(getHeadingR()))); diffEl = lcAbs(lcAepcRad(la - el)); if ((diffAz <= maxAz) && (diffEl <= maxEl)) { lockMode = TGT_IN_SIGHT; tgtAquired = true; if (tgtPlayer != player) { if (tgtPlayer != nullptr) tgtPlayer->unref(); tgtPlayer = player; tgtPlayer->ref(); } } } } item = item->getNext(); } players->unref(); players = nullptr; } } } // else we are locking on target, and need to follow our target player else { if (tgtPlayer == nullptr) lockMode = SEARCHING; else { const osg::Vec3 vecPos = tgtPlayer->getPosition() - getPosition(); const LCreal az = lcAtan2(vecPos.y(), vecPos.x()); LCreal range = (vecPos.x() * vecPos.x() + vecPos.y() * vecPos.y()); range = std::sqrt(range); // now get our elevation const LCreal el = lcAtan2(-vecPos.z(), range); // now force that on us setLookAngle(el * static_cast<LCreal>(Basic::Angle::R2DCC)); setEulerAngles(0, 0, az); } } } }