void rms::ComputeAlignAxisMatrix( const Vector3<Real> & vInitial, const Vector3<Real> & vAlignWith, Matrix3<Real> & matrix ) { // compute cosine of angle between vectors Real axisDot = vAlignWith.Dot( vInitial ); // compute rotation axis Vector3<Real> axisCross( vInitial.Cross( vAlignWith ) ); // apply rotation if necessary if (axisCross.SquaredLength() > Wml::Math<Real>::EPSILON) { // compute normalized axis and angle, then create rotation around axis axisCross.Normalize(); Real fAngle = Math<Real>::ACos( axisDot / vAlignWith.Length() ); matrix.FromAxisAngle( axisCross, fAngle ); } else if (axisDot < (Real)0) { // find some perpendicular vectors Wml::Vector3<Real> vPerp1, vPerp2; ComputePerpVectors( vInitial, vPerp1, vPerp2 ); matrix.FromAxisAngle( vPerp1, (Real)180 * Math<Real>::DEG_TO_RAD ); } else { matrix = Matrix3<Real>::IDENTITY; } }
void rms::ComputeAlignZAxisMatrix( const Vector3<Real> & vAlignWith, Matrix3<Real> & matrix, bool bInvert ) { // compute cosine of angle between vectors Real axisDot = vAlignWith.Dot( Vector3<Real>::UNIT_Z ); // compute rotation axis Vector3<Real> axisCross( Vector3<Real>::UNIT_Z.Cross( vAlignWith ) ); Real fInverter = (bInvert) ? (Real)-1 : (Real)1; // apply rotation if necessary if (axisCross.SquaredLength() > Wml::Math<Real>::EPSILON) { // compute normalized axis and angle, then create rotation around axis axisCross.Normalize(); Real fAngle = Math<Real>::ACos( axisDot / vAlignWith.Length() ); matrix.FromAxisAngle( axisCross, fAngle * fInverter ); } else if (axisDot < (Real)0) { matrix.FromAxisAngle( Vector3<Real>::UNIT_X, (Real)180 * Math<Real>::DEG_TO_RAD * fInverter ); } else { matrix = Matrix3<Real>::IDENTITY; } }
//---------------------------------------------------------------------------- static void MinimalBoxForAngles (int iQuantity, const Vector3* akPoint, Real afAngle[3], Box3& rkBox) { Real fCos0 = Math::Cos(afAngle[0]); Real fSin0 = Math::Sin(afAngle[0]); Real fCos1 = Math::Cos(afAngle[1]); Real fSin1 = Math::Sin(afAngle[1]); Vector3 kAxis(fCos0*fSin1,fSin0*fSin1,fCos1); Matrix3 kRot; kRot.FromAxisAngle(kAxis,afAngle[2]); Vector3 kMin = akPoint[0]*kRot, kMax = kMin; for (int i = 1; i < iQuantity; i++) { Vector3 kTest = akPoint[i]*kRot; if ( kTest.x < kMin.x ) kMin.x = kTest.x; else if ( kTest.x > kMax.x ) kMax.x = kTest.x; if ( kTest.y < kMin.y ) kMin.y = kTest.y; else if ( kTest.y > kMax.y ) kMax.y = kTest.y; if ( kTest.z < kMin.z ) kMin.z = kTest.z; else if ( kTest.z > kMax.z ) kMax.z = kTest.z; } Vector3 kMid = 0.5f*(kMax + kMin); Vector3 kRng = 0.5f*(kMax - kMin); rkBox.Center() = kRot*kMid; rkBox.Axis(0) = kRot.GetColumn(0); rkBox.Axis(1) = kRot.GetColumn(1); rkBox.Axis(2) = kRot.GetColumn(2); rkBox.Extent(0) = kRng.x; rkBox.Extent(1) = kRng.y; rkBox.Extent(2) = kRng.z; }
//---------------------------------------------------------------------------- static Real Volume (const Real* afAngle, void* pvUserData) { int iQuantity = ((PointArray*)pvUserData)->m_iQuantity; const Vector3* akPoint = ((PointArray*)pvUserData)->m_akPoint; Real fCos0 = Math::Cos(afAngle[0]); Real fSin0 = Math::Sin(afAngle[0]); Real fCos1 = Math::Cos(afAngle[1]); Real fSin1 = Math::Sin(afAngle[1]); Vector3 kAxis(fCos0*fSin1,fSin0*fSin1,fCos1); Matrix3 kRot; kRot.FromAxisAngle(kAxis,afAngle[2]); Vector3 kMin = akPoint[0]*kRot, kMax = kMin; for (int i = 1; i < iQuantity; i++) { Vector3 kTest = akPoint[i]*kRot; if ( kTest.x < kMin.x ) kMin.x = kTest.x; else if ( kTest.x > kMax.x ) kMax.x = kTest.x; if ( kTest.y < kMin.y ) kMin.y = kTest.y; else if ( kTest.y > kMax.y ) kMax.y = kTest.y; if ( kTest.z < kMin.z ) kMin.z = kTest.z; else if ( kTest.z > kMax.z ) kMax.z = kTest.z; } Real fVolume = (kMax.x-kMin.x)*(kMax.y-kMin.y)*(kMax.z-kMin.z); return fVolume; }
//--------------------------------------------------------------------------- long FAR PASCAL WndProc (HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { static Vector3 s_kEye; static QuadricSurface::ConvexPolyhedron s_kPoly; static int s_iSteps = 0; static Matrix3 s_kRot; Matrix3 kIncr; switch ( message ) { case WM_CREATE: { CreatePoly(s_kPoly); QuadricSurface::TessellateSphere(s_iSteps,s_kPoly); // initial camera orientation and eye point s_kRot.FromAxisAngle(Vector3::UNIT_Z,0.0f); s_kEye = 2.0f*s_kRot.GetColumn(2); return 0; } case WM_PAINT: { PAINTSTRUCT ps; HDC hDC = BeginPaint(hWnd,&ps); DrawPolyhedron(hDC,s_kEye,s_kRot,s_kPoly); EndPaint(hWnd,&ps); return 0; } case WM_KEYDOWN: { switch ( wParam ) { case VK_LEFT: { // rotate camera about its 'up' vector kIncr.FromAxisAngle(s_kRot.GetColumn(1),0.1f); s_kRot = kIncr*s_kRot; s_kEye = 2.0f*s_kRot.GetColumn(2); InvalidateRect(hWnd,NULL,TRUE); break; } case VK_RIGHT: { // rotate camera about its 'up' vector kIncr.FromAxisAngle(s_kRot.GetColumn(1),-0.1f); s_kRot = kIncr*s_kRot; s_kEye = 2.0f*s_kRot.GetColumn(2); InvalidateRect(hWnd,NULL,TRUE); break; } case VK_UP: { // rotate camera about its 'right' vector kIncr.FromAxisAngle(s_kRot.GetColumn(0),-0.1f); s_kRot = kIncr*s_kRot; s_kEye = 2.0f*s_kRot.GetColumn(2); InvalidateRect(hWnd,NULL,TRUE); break; } case VK_DOWN: { // rotate camera about its 'right' vector kIncr.FromAxisAngle(s_kRot.GetColumn(0),0.1f); s_kRot = kIncr*s_kRot; s_kEye = 2.0f*s_kRot.GetColumn(2); InvalidateRect(hWnd,NULL,TRUE); break; } } return 0; } case WM_CHAR: { switch ( wParam ) { case '+': case '=': { s_iSteps++; QuadricSurface::DeletePolyhedron(s_kPoly); CreatePoly(s_kPoly); QuadricSurface::TessellateSphere(s_iSteps,s_kPoly); InvalidateRect(hWnd,NULL,TRUE); break; } case '-': case '_': { if ( s_iSteps >= 1 ) { s_iSteps--; QuadricSurface::DeletePolyhedron(s_kPoly); CreatePoly(s_kPoly); QuadricSurface::TessellateSphere(s_iSteps,s_kPoly); InvalidateRect(hWnd,NULL,TRUE); } break; } case 'q': case 'Q': case VK_ESCAPE: { PostMessage(hWnd,WM_DESTROY,0,0); break; } } return 0; } case WM_DESTROY: { QuadricSurface::DeletePolyhedron(s_kPoly); PostQuitMessage(0); return 0; } } return DefWindowProc(hWnd,message,wParam,lParam); }