Beispiel #1
0
/**************************************************
*   Calculates one step for the tank based on its
*   movement and rotation vectors.  It then works out
*   how that movement affects its orientation on the
*   terrain and runs it against the collision engine.
*
*   This function should be written as procedurally as possible
*   because it is called every frame for every tank.
**************************************************/
void Tank::move()
{
    mRotation[1] += mCurrentRotationRate;

    float ySin = sin(TO_RADIANS(mRotation[1]));
    float yCos = cos(TO_RADIANS(mRotation[1]));

    Vector3D<float> driveMomentum;

    driveMomentum[0] = ySin * mCurrentMoveRate;
    driveMomentum[2] = yCos * mCurrentMoveRate;

    Vector3D<float> newPosition = mPosition + driveMomentum;


    if (mTurretConstantRotate)
    {
        mHeadRotation += mHeadRotationDirection;
    }

    if (mAIRotateCalled)
    {
        if (abs(mHeadRotation - mHeadTargetDirection) < mHeadRotationRate)
        {
            mHeadRotation = mHeadTargetDirection;
            mHeadTargetDirection = mHeadRotation;
        }
        else
        {
            mHeadRotation += mHeadRotationDirection;
            mHeadTargetDirection -= mHeadRotationRate;
        }
    }


    //transform the four control points to determine how the tank should sit
    //on the terrrain
    mTransformedBackLeftControl = mBackLeftControl;
    mTransformedBackRightControl = mBackRightControl;
    mTransformedFrontLeftControl = mFrontLeftControl;
    mTransformedFrontRightControl = mFrontRightControl;


    mTransformedFrontLeftControl[0] = mFrontLeftControl[0] * yCos + mFrontLeftControl[2] * ySin;
    mTransformedFrontLeftControl[2] = mFrontLeftControl[0] * -ySin + mFrontLeftControl[2] * yCos;
    mTransformedFrontLeftControl[0] += newPosition[0];
    mTransformedFrontLeftControl[2] += newPosition[2];
    mTransformedFrontLeftControl[1]
        += mTerrain->findHeight(mTransformedFrontLeftControl[0],
        mTransformedFrontLeftControl[2]) + mTankSize[1] / 2.0;
    float highestControlPoint = mTransformedFrontLeftControl[1];
    float lowestControlPoint = mTransformedFrontLeftControl[1];

    mTransformedFrontRightControl[0] = mFrontRightControl[0] * yCos + mFrontRightControl[2] * ySin;
    mTransformedFrontRightControl[2] = mFrontRightControl[0] * -ySin + mFrontRightControl[2] * yCos;
    mTransformedFrontRightControl[0] += newPosition[0];
    mTransformedFrontRightControl[2] += newPosition[2];
    mTransformedFrontRightControl[1]
        += mTerrain->findHeight(mTransformedFrontRightControl[0],
        mTransformedFrontRightControl[2]) + mTankSize[1] / 2.0;

    if (mTransformedFrontRightControl[1] > highestControlPoint)
    {
        highestControlPoint = mTransformedFrontRightControl[1];
    }
    else if (mTransformedFrontRightControl[1] < lowestControlPoint)
    {
        lowestControlPoint = mTransformedFrontRightControl[1];
    }

    mTransformedBackLeftControl[0] = mBackLeftControl[0] * yCos
        + mBackLeftControl[2] * ySin;
    mTransformedBackLeftControl[2] = mBackLeftControl[0] * -ySin
        + mBackLeftControl[2] * yCos;
    mTransformedBackLeftControl[0] += newPosition[0];
    mTransformedBackLeftControl[2] += newPosition[2];
    mTransformedBackLeftControl[1]
        += mTerrain->findHeight(mTransformedBackLeftControl[0],
        mTransformedBackLeftControl[2]) + mTankSize[1] / 2.0;

    if ( mTransformedBackLeftControl[1] > highestControlPoint)
    {
        highestControlPoint = mTransformedBackLeftControl[1];
    }
    else if (mTransformedBackLeftControl[1] < lowestControlPoint)
    {
        lowestControlPoint = mTransformedBackLeftControl[1];
    }

    mTransformedBackRightControl[0] = mBackRightControl[0] * yCos + mBackRightControl[2] * ySin;
    mTransformedBackRightControl[2] = mBackRightControl[0] * -ySin + mBackRightControl[2] * yCos;
    mTransformedBackRightControl[0] += newPosition[0];
    mTransformedBackRightControl[2] += newPosition[2];
    mTransformedBackRightControl[1]
        += mTerrain->findHeight(mTransformedBackRightControl[0],
        mTransformedBackRightControl[2]) + mTankSize[1] / 2.0;

    if (mTransformedBackRightControl[1] > highestControlPoint)
    {
        highestControlPoint = mTransformedBackRightControl[1];
    }
    else if (mTransformedBackRightControl[1] < lowestControlPoint)
    {
        lowestControlPoint = mTransformedBackRightControl[1];
    }

    //use the transformed control points to determine what angle the tank should sit at
    float zFront = atan((mTransformedFrontLeftControl[1] - mTransformedFrontRightControl[1]) / mTankSize[0]);
    float zBack = atan((mTransformedBackLeftControl[1] - mTransformedBackRightControl[1]) / mTankSize[0]);
    mRotation[2] = (abs(zFront) > abs(zBack)) ? TO_DEGREES(zFront)
        : TO_DEGREES(zBack);

    float xLeft = atan(( mTransformedBackLeftControl[1] - mTransformedFrontLeftControl[1]) / mTankSize[0]);
    float xRight = atan(( mTransformedBackRightControl[1] - mTransformedFrontRightControl[1]) / mTankSize[0]);
    mRotation[0] = (abs(xLeft) > abs(xRight)) ? TO_DEGREES(xLeft)
        : TO_DEGREES(xRight);

    //set the position to the highest of the four control points
    mPosition[1] = (highestControlPoint + lowestControlPoint) / 2.0
        + mTankSize[1] / 2.0;

    mPreviousPosition = mPosition;

    float friction = mTerrain->getFriction(mPosition[0], mPosition[2]);
    float cmr = fabs(mCurrentMoveRate);

    driveMomentum *= friction;
    mMomentum *= (1.0f - friction);
    if (mMomentum.isZero()) mMomentum.set(0.0f);

    float magnitude = mMomentum.length();
    mMomentum += driveMomentum;
    if (mMomentum.length() > cmr)
    {
        mMomentum.normalizeTo(magnitude > cmr ? magnitude : cmr);
    }

    mPosition += mMomentum;

    if (mPosition[0] < 1.25)
    {
        mPosition[0] = 1.25;
    }
    else if (mPosition[0] > mTerrainWidth - 2.25)
    {
        mPosition[0] = mTerrainWidth - 2.25;
    }

    if (mPosition[2] < 1.25)
    {
        mPosition[2] = 1.25;
    }
    else if (mPosition[2] > mTerrainHeight - 2.25)
    {
        mPosition[2] = mTerrainHeight - 2.25;
    }

}
Beispiel #2
0
void Frustum::enclose( const Frustum & other )
{
    vec3 n = glm::normalize(other.origin - other.at);
    vec3 u = glm::normalize(glm::cross(other.up, n));
    vec3 v = glm::normalize(glm::cross(n, u));
    if( type == Projection::PERSPECTIVE )
        this->orient( origin, other.getCenter(), up );
    mat4 m = this->getViewMatrix();

    vec3 p[8];

    // Get 8 points that define the frustum
    if( other.type == Projection::PERSPECTIVE ) {
        float dy = other.mNear * tanf( (float)TO_RADIANS(other.fovy) / 2.0f );
        float dx = other.ar * dy;
        vec3 c = other.origin - n * other.mNear;
        p[0] = c + u * dx + v * dy;
        p[1] = c - u * dx + v * dy;
        p[2] = c - u * dx - v * dy;
        p[3] = c + u * dx - v * dy;
        dy = other.mFar * tanf( (float)TO_RADIANS(other.fovy) / 2.0f );
        dx = other.ar * dy;
        c = other.origin - n * other.mFar;
        p[4] = c + u * dx + v * dy;
        p[5] = c - u * dx + v * dy;
        p[6] = c - u * dx - v * dy;
        p[7] = c + u * dx - v * dy;
    } else {
        vec3 c = other.origin - n * other.mNear;
        p[0] = c + u * other.xmax + v * other.ymax;
        p[1] = c + u * other.xmax + v * other.ymin;
        p[2] = c + u * other.xmin + v * other.ymax;
        p[3] = c + u * other.xmin + v * other.ymin;
        c = other.origin - n * other.mFar;
        p[4] = c + u * other.xmax + v * other.ymax;
        p[5] = c + u * other.xmax + v * other.ymin;
        p[6] = c + u * other.xmin + v * other.ymax;
        p[7] = c + u * other.xmin + v * other.ymin;
    }

    // Adjust frustum to contain
    if( type == Projection::PERSPECTIVE ) {
        fovy = 0.0f;
        mFar = 0.0f;
        mNear = std::numeric_limits<float>::max();
        float maxHorizAngle = 0.0f;
        for( int i = 0; i < 8; i++) {
            // Convert to local space
            vec4 pt = m * vec4(p[i],1.0f);

            if( pt.z < 0.0f ) {
                float d = -pt.z;
                float angle = atanf( fabs(pt.x) / d );
                if( angle > maxHorizAngle ) maxHorizAngle = angle;
                angle = (float)TO_DEGREES( atanf( fabs(pt.y) / d ) );
                if( angle * 2.0f > fovy ) fovy = angle * 2.0f;
                if( mNear > d ) mNear = d;
                if( mFar < d ) mFar = d;
            }
        }
        float h = ( mNear * tanf( (float)TO_RADIANS(fovy)/ 2.0f) ) * 2.0f;
        float w = ( mNear * tanf( maxHorizAngle ) ) * 2.0f;
        ar = w / h;
    } else {
        xmin = ymin = mNear = std::numeric_limits<float>::max();
        xmax = ymax = mFar = std::numeric_limits<float>::min();
        for( int i = 0; i < 8; i++) {
            // Convert to local space
            vec4 pt = m * vec4(p[i],1.0f);
            if( xmin > pt.x ) xmin = pt.x;
            if( xmax < pt.x ) xmax = pt.x;
            if( ymin > pt.y ) ymin = pt.y;
            if( ymax < pt.y ) ymax = pt.y;
            if( mNear > -pt.z ) mNear = -pt.z;
            if( mFar < -pt.z ) mFar = -pt.z;
        }
    }

}