//Given a direction vector, get the rotation around the y axis float GetYRotation(float fX, float fY, float fZ) { D3DVECTOR rlvPreDef, rlvDir; D3DVALUE valCosTheta, fTheta; // The pre-defined angle. rlvPreDef.x = 0.0F; rlvPreDef.y = 0.0F; rlvPreDef.z = 1.0F; // Make a D3DVECTOR from this vector. rlvDir.x = fX; rlvDir.y = fY; rlvDir.z = fZ; // First need angle between the pre-defined angle and rlvDir. valCosTheta = D3DRMVectorDotProduct(&rlvPreDef, &rlvDir); fTheta = (D3DVALUE)acos(valCosTheta); // This will always be the acute angle. Since rotation will always be in positive direction we must // give correct angle (possibly obtuse) for that direction. if (rlvDir.x < 0.0F) { // Acute angle will not work, need obtuse angle. fTheta = (2*PI) - fTheta; } return fTheta; }
STDMETHODIMP CVectorObject::get_Rotation(float *pfTheta) { D3DVECTOR rlvPreDef, rlvDir; D3DVALUE valCosTheta; // The pre-defined angle. rlvPreDef.x = 0.0F; rlvPreDef.y = 0.0F; rlvPreDef.z = 1.0F; // Make a D3DVECTOR from this vector. rlvDir.x = m_x; rlvDir.y = m_y; rlvDir.z = m_z; D3DRMVectorNormalize(&rlvDir); // First need angle between the pre-defined angle and rlvDir. valCosTheta = D3DRMVectorDotProduct(&rlvPreDef, &rlvDir); *pfTheta = (D3DVALUE)acos(valCosTheta); // This will always be the acute angle. Since rotation will always be in positive direction we must // give correct angle (possibly obtuse) for that direction. if (rlvDir.x < 0.0F) { // Acute angle will not work, need obtuse angle. *pfTheta = (2*PI) - *pfTheta; } return S_OK; }
/* Interpolation between two quaternions */ LPD3DRMQUATERNION WINAPI D3DRMQuaternionSlerp(LPD3DRMQUATERNION q, LPD3DRMQUATERNION a, LPD3DRMQUATERNION b, D3DVALUE alpha) { D3DVALUE dot, epsilon, temp, theta, u; D3DVECTOR v1, v2; dot = a->s * b->s + D3DRMVectorDotProduct(&a->v, &b->v); epsilon = 1.0f; temp = 1.0f - alpha; u = alpha; if (dot < 0.0) { epsilon = -1.0; dot = -dot; } if( 1.0f - dot > 0.001f ) { theta = acos(dot); temp = sin(theta * temp) / sin(theta); u = sin(theta * alpha) / sin(theta); } q->s = temp * a->s + epsilon * u * b->s; D3DRMVectorScale(&v1, &a->v, temp); D3DRMVectorScale(&v2, &b->v, epsilon * u); D3DRMVectorAdd(&q->v, &v1, &v2); return q; }
/* Reflection of a vector on a surface */ LPD3DVECTOR WINAPI D3DRMVectorReflect(LPD3DVECTOR r, LPD3DVECTOR ray, LPD3DVECTOR norm) { D3DVECTOR sca, temp; D3DRMVectorSubtract(&temp, D3DRMVectorScale(&sca, norm, 2.0*D3DRMVectorDotProduct(ray,norm)), ray); *r = temp; return r; }
/* Product of 2 quaternions */ LPD3DRMQUATERNION WINAPI D3DRMQuaternionMultiply(LPD3DRMQUATERNION q, LPD3DRMQUATERNION a, LPD3DRMQUATERNION b) { D3DRMQUATERNION temp; D3DVECTOR cross_product; D3DRMVectorCrossProduct(&cross_product, &a->v, &b->v); temp.s = a->s * b->s - D3DRMVectorDotProduct(&a->v, &b->v); temp.v.u1.x = a->s * b->v.u1.x + b->s * a->v.u1.x + cross_product.u1.x; temp.v.u2.y = a->s * b->v.u2.y + b->s * a->v.u2.y + cross_product.u2.y; temp.v.u3.z = a->s * b->v.u3.z + b->s * a->v.u3.z + cross_product.u3.z; *q = temp; return q; }