コード例 #1
0
ファイル: Frustum.cpp プロジェクト: MIFOZ/EFE-Engine
	void cFrustum::UpdateEndPoints()
	{
		float fXAngle = m_fFOV*0.5f;
		float fYAngle = m_fFOV*0.5f*m_fAspect;

		cVector3f vForward = m_mtxModelView.GetForward();
		cVector3f vUp = m_mtxModelView.GetUp();
		cVector3f vRight = m_mtxModelView.GetRight();

		cVector3f vUpDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(fXAngle, vRight)), vForward);
		cVector3f vDownDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(-fXAngle, vRight)), vForward);

		vForward = vForward * -1;

		float fRightAdd = sin(fYAngle);

		cVector3f vVec0 = vUpDir + vRight * fRightAdd;
		cVector3f vVec2 = vDownDir + vRight * fRightAdd;
		cVector3f vVec3 = vDownDir + vRight * -fRightAdd;
		cVector3f vVec1 = vUpDir + vRight * -fRightAdd;

		float fAngle0 = cMath::Vector3Angle(vVec0, vForward);
		float fAngle1 = cMath::Vector3Angle(vVec1, vForward);
		float fAngle2 = cMath::Vector3Angle(vVec2, vForward);
		float fAngle3 = cMath::Vector3Angle(vVec3, vForward);

		m_vEndPoints[0] = m_vOrigin + vVec0 * (m_fFarPlane/cos(fAngle0));
		m_vEndPoints[1] = m_vOrigin + vVec1 * (m_fFarPlane/cos(fAngle1));
		m_vEndPoints[2] = m_vOrigin + vVec2 * (m_fFarPlane/cos(fAngle2));
		m_vEndPoints[3] = m_vOrigin + vVec3 * (m_fFarPlane/cos(fAngle3));
	}
コード例 #2
0
ファイル: Frustum.cpp プロジェクト: ArchyInf/HPL1Engine
	void cFrustum::UpdateEndPoints()
	{
		float fXAngle = mfFOV*0.5f;
		float fYAngle = mfFOV*0.5f*mfAspect;

		cVector3f vForward = m_mtxModelView.GetForward();
		cVector3f vUp = m_mtxModelView.GetUp();
		cVector3f vRight = m_mtxModelView.GetRight();

		//Point the forward vec in different dirs.
		cVector3f vUpDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(fXAngle,vRight)), vForward);
		cVector3f vDownDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(-fXAngle,vRight)), vForward);

		//cVector3f vRightDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(fYAngle,vUp)), vForward);
		//cVector3f vLeftDir = cMath::MatrixMul(cMath::MatrixQuaternion(cQuaternion(-fYAngle,vUp)), vForward);
		
		vForward = vForward *-1;

		float fRightAdd = sin(fYAngle);
		//float fUpAdd = sin(fXAngle);
		
		cVector3f vVec0 = vUpDir + vRight * fRightAdd;
		cVector3f vVec2 = vDownDir + vRight * fRightAdd;
		cVector3f vVec3 = vDownDir + vRight * -fRightAdd;
		cVector3f vVec1 = vUpDir + vRight * -fRightAdd;

		/*cVector3f vVec0 = vUpDir;//cMath::Vector3Normalize(vUpDir+vRightDir);
		cVector3f vVec1 = vRightDir;//cMath::Vector3Normalize(vUpDir+vLeftDir);
		cVector3f vVec2 = vDownDir;//cMath::Vector3Normalize(vDownDir+vLeftDir);
		cVector3f vVec3 = vLeftDir;//cMath::Vector3Normalize(vDownDir+vRightDir);*/
		
		//angles between forward and the vectors
		float fAngle0 = cMath::Vector3Angle(vVec0, vForward);
		float fAngle1 = cMath::Vector3Angle(vVec1, vForward);
		float fAngle2 = cMath::Vector3Angle(vVec2, vForward);
		float fAngle3 = cMath::Vector3Angle(vVec3, vForward);

		//create end points.
		mvEndPoints[0] = mvOrigin + vVec0 * (mfFarPlane/cos(fAngle0));
		mvEndPoints[1] = mvOrigin + vVec1 * (mfFarPlane/cos(fAngle1));
		mvEndPoints[2] = mvOrigin + vVec2 * (mfFarPlane/cos(fAngle2));
		mvEndPoints[3] = mvOrigin + vVec3 * (mfFarPlane/cos(fAngle3));
				
		/*mvEndPoints[0] = mvOrigin + (vUpDir+vRightDir)	 * mfFarPlane *-1;
		mvEndPoints[1] = mvOrigin + (vUpDir+vLeftDir)	 * mfFarPlane*-1;
		mvEndPoints[2] = mvOrigin + (vDownDir+vRightDir)* mfFarPlane*-1;
		mvEndPoints[3] = mvOrigin + (vDownDir+vLeftDir) * mfFarPlane*-1;*/
	}
コード例 #3
0
ファイル: cQuaternion.cpp プロジェクト: pilkch/library
    // *** Spherical linear interpolated quaternion between q1 and q2, with respect to t
    //
    // Everyone understands
    // the terms, "matrix to quaternion", "quaternion to matrix", "create quaternion matrix",
    // "quaternion multiplication", etc.. but "SLERP" is the stumbling block, even a little
    // bit after hearing what it stands for, "Spherical Linear Interpolation".  What that
    // means is that we have 2 quaternions (or rotations) and we want to interpolate between
    // them.  The reason what it's called "spherical" is that quaternions deal with a sphere.
    // Linear interpolation just deals with 2 points primarily, where when dealing with angles
    // and rotations, we need to use sin() and cos() for interpolation.  If we wanted to use
    // quaternions for camera rotations, which have much more instant and jerky changes in
    // rotations, we would use Spherical-Cubic Interpolation.  The equation for SLERP is this:
    //
    // q = (((b.a)^-1)^t)a
    //
    void cQuaternion::SlerpForMD3(const cQuaternion& q1, const cQuaternion& q2Original, float t)
    {
      cQuaternion q2(q2Original);

      // Here we do a check to make sure the 2 quaternions aren't the same, return q1 if they are
      if (q1.x == q2.x && q1.y == q2.y && q1.z == q2.z && q1.w == q2.w) {
        SetFromQuaternion(q1);
        return;
      }

      // Following the (b.a) part of the equation, we do a dot product between q1 and q2.
      // We can do a dot product because the same math applied for a 3D vector as a 4D vector.
      float result = (q1.x * q2.x) + (q1.y * q2.y) + (q1.z * q2.z) + (q1.w * q2.w);

      // If the dot product is less than 0, the angle is greater than 90 degrees
      if (result < 0.0f) {
        // Negate the second quaternion and the result of the dot product
        q2 = cQuaternion(-q2.x, -q2.y, -q2.z, -q2.w);
        result = -result;
      }

      // Set the first and second scale for the interpolation
      float scale0 = 1.0f - t;
      float scale1 = t;

      // Next, we want to actually calculate the spherical interpolation.  Since this
      // calculation is quite computationally expensive, we want to only perform it
      // if the angle between the 2 quaternions is large enough to warrant it.  If the
      // angle is fairly small, we can actually just do a simpler linear interpolation
      // of the 2 quaternions, and skip all the complex math.  We create a "delta" value
      // of 0.1 to say that if the cosine of the angle (result of the dot product) between
      // the 2 quaternions is smaller than 0.1, then we do NOT want to perform the full on
      // interpolation using.  This is because you won't really notice the difference.

      // Check if the angle between the 2 quaternions was big enough to warrant such calculations
      if (1.0f - result > 0.1f) {
        // Get the angle between the 2 quaternions, and then store the sin() of that angle
        float theta = (float)acos(result);
        float sinTheta = (float)sin(theta);

        // Calculate the scale for q1 and q2, according to the angle and it's sine value
        scale0 = (float)sin((1.0f - t)* theta) / sinTheta;
        scale1 = (float)sin((t * theta)) / sinTheta;
      }

      // Calculate the x, y, z and w values for the quaternion by using a special form of linear interpolation for quaternions
      x = (scale0 * q1.x) + (scale1 * q2.x),
      y = (scale0 * q1.y) + (scale1 * q2.y),
      z = (scale0 * q1.z) + (scale1 * q2.z),
      w = (scale0 * q1.w) + (scale1 * q2.w);
    }
コード例 #4
0
namespace hpl
{

//////////////////////////////////////////////////////////////////////////
// CONSTRUCTORS
//////////////////////////////////////////////////////////////////////////

//-----------------------------------------------------------------------

cQuaternion::cQuaternion()
{
}

//-----------------------------------------------------------------------

cQuaternion::cQuaternion(float afAngle, const cVector3f & avAxis)
{
    FromAngleAxis(afAngle,avAxis);
}

cQuaternion::cQuaternion(float afW, float afX, float afY, float afZ)
{
    w = afW;
    v.x = afX;
    v.y = afY;
    v.z = afZ;
}


//-----------------------------------------------------------------------

//////////////////////////////////////////////////////////////////////////
// PUBLIC METHODS
//////////////////////////////////////////////////////////////////////////


const cQuaternion cQuaternion::Identity = cQuaternion(1.0f,0.0f,0.0f,0.0f);

//-----------------------------------------------------------------------

void cQuaternion::Normalise()
{
    float fLen = w*w + v.x*v.x + v.y*v.y + v.z*v.z;
    float fFactor = 1.0f / sqrt(fLen);
    v = v * fFactor;
    w = w * fFactor;
}

//-----------------------------------------------------------------------

void cQuaternion::ToRotationMatrix(cMatrixf &a_mtxDest) const
{
    cMatrixf mtxA;

    float fTx  = 2.0f*v.x;
    float fTy  = 2.0f*v.y;
    float fTz  = 2.0f*v.z;
    float fTwx = fTx*w;
    float fTwy = fTy*w;
    float fTwz = fTz*w;
    float fTxx = fTx*v.x;
    float fTxy = fTy*v.x;
    float fTxz = fTz*v.x;
    float fTyy = fTy*v.y;
    float fTyz = fTz*v.y;
    float fTzz = fTz*v.z;

    a_mtxDest.m[0][0] = 1.0f-(fTyy+fTzz);
    a_mtxDest.m[0][1] = fTxy-fTwz;
    a_mtxDest.m[0][2] = fTxz+fTwy;
    a_mtxDest.m[1][0] = fTxy+fTwz;
    a_mtxDest.m[1][1] = 1.0f-(fTxx+fTzz);
    a_mtxDest.m[1][2] = fTyz-fTwx;
    a_mtxDest.m[2][0] = fTxz-fTwy;
    a_mtxDest.m[2][1] = fTyz+fTwx;
    a_mtxDest.m[2][2] = 1.0f-(fTxx+fTyy);
}


//-----------------------------------------------------------------------

void cQuaternion::FromRotationMatrix(const cMatrix<float> &a_mtxRot)
{
    float fTrace = a_mtxRot.m[0][0]+a_mtxRot.m[1][1]+a_mtxRot.m[2][2];
    float fRoot;

    if ( fTrace > 0.0 )
        {
            // |w| > 1/2, may as well choose w > 1/2
            fRoot = sqrt(fTrace + 1.0f);  // 2w
            w = 0.5f*fRoot;
            fRoot = 0.5f/fRoot;  // 1/(4w)
            v.x = (a_mtxRot.m[2][1]-a_mtxRot.m[1][2])*fRoot;
            v.y = (a_mtxRot.m[0][2]-a_mtxRot.m[2][0])*fRoot;
            v.z = (a_mtxRot.m[1][0]-a_mtxRot.m[0][1])*fRoot;
        }
    else
        {
            // |w| <= 1/2
            static size_t s_iNext[3] = { 1, 2, 0 };
            size_t i = 0;
            if ( a_mtxRot.m[1][1] > a_mtxRot.m[0][0] )
                i = 1;
            if ( a_mtxRot.m[2][2] > a_mtxRot.m[i][i] )
                i = 2;
            size_t j = s_iNext[i];
            size_t k = s_iNext[j];

            fRoot = sqrt(a_mtxRot.m[i][i]-a_mtxRot.m[j][j]-a_mtxRot.m[k][k] + 1.0f);
            float* apkQuat[3] = { &v.x, &v.y, &v.z };
            *apkQuat[i] = 0.5f*fRoot;
            fRoot = 0.5f/fRoot;
            w = (a_mtxRot.m[k][j]-a_mtxRot.m[j][k])*fRoot;
            *apkQuat[j] = (a_mtxRot.m[j][i]+a_mtxRot.m[i][j])*fRoot;
            *apkQuat[k] = (a_mtxRot.m[k][i]+a_mtxRot.m[i][k])*fRoot;
        }
}

//-----------------------------------------------------------------------

void cQuaternion::FromAngleAxis(float afAngle, const cVector3f &avAxis)
{
    // assert:  axis[] is unit length
    //
    // The quaternion representing the rotation is
    //   q = cos(A/2)+sin(A/2)*(x*i+y*j+z*k)

    float fHalfAngle = 0.5f*afAngle;
    float fSin = sin(fHalfAngle);
    w = cos(fHalfAngle);
    v.x = fSin*avAxis.x;
    v.y = fSin*avAxis.y;
    v.z = fSin*avAxis.z;
}

//-----------------------------------------------------------------------

cQuaternion cQuaternion::operator+(const cQuaternion &aqB) const
{
    cQuaternion qOut;
    qOut.v = v + aqB.v;
    qOut.w = w + aqB.w;

    return qOut;
}
//-----------------------------------------------------------------------

cQuaternion cQuaternion::operator-(const cQuaternion &aqB) const
{
    cQuaternion qOut;
    qOut.v = v - aqB.v;
    qOut.w = w - aqB.w;

    return qOut;
}
//-----------------------------------------------------------------------
cQuaternion cQuaternion::operator*(const cQuaternion &aqB) const
{
    cQuaternion qOut;

    qOut.w = w * aqB.w - v.x * aqB.v.x - v.y * aqB.v.y - v.z * aqB.v.z;
    qOut.v.x = w * aqB.v.x + v.x * aqB.w + v.y * aqB.v.z - v.z * aqB.v.y;
    qOut.v.y = w * aqB.v.y + v.y * aqB.w + v.z * aqB.v.x - v.x * aqB.v.z;
    qOut.v.z = w * aqB.v.z + v.z * aqB.w + v.x * aqB.v.y - v.y * aqB.v.x;

    return qOut;
}
//-----------------------------------------------------------------------
cQuaternion cQuaternion::operator*(float afScalar) const
{
    cQuaternion qOut;
    qOut.v = v * afScalar;
    qOut.w = w * afScalar;

    return qOut;
}

//-----------------------------------------------------------------------
}