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;
}
Example #3
0
//------------------------------------------------------------------------------
// 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);
    }
}
Example #5
0
//------------------------------------------------------------------------------
// 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);
            }
        }
    }
}