quadTransforms.cpp
Engine/source/math/util/quadTransforms.cpp
Detailed Description
1 2//----------------------------------------------------------------------------- 3// Copyright (c) 2012 GarageGames, LLC 4// 5// Permission is hereby granted, free of charge, to any person obtaining a copy 6// of this software and associated documentation files (the "Software"), to 7// deal in the Software without restriction, including without limitation the 8// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 9// sell copies of the Software, and to permit persons to whom the Software is 10// furnished to do so, subject to the following conditions: 11// 12// The above copyright notice and this permission notice shall be included in 13// all copies or substantial portions of the Software. 14// 15// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21// IN THE SOFTWARE. 22//----------------------------------------------------------------------------- 23 24#include "platform/platform.h" 25#include "math/util/quadTransforms.h" 26 27 28BiQuadToSqr::BiQuadToSqr( const Point2F &p00, 29 const Point2F &p10, 30 const Point2F &p11, 31 const Point2F &p01 ) 32 : m_kP00( p00 ) 33{ 34 m_kB = p10 - p00 ; // width 35 m_kC = p01 - p00; // height 36 m_kD = p11 + p00 - p10 - p01; // diagonal dist 37 38 if(mFabs(m_kD.x) < POINT_EPSILON) 39 m_kD.x = 0.f; 40 if(mFabs(m_kD.y) < POINT_EPSILON) 41 m_kD.y = 0.f; 42 43 m_fBC = mDotPerp( m_kB, m_kC ); 44 m_fBD = mDotPerp( m_kB, m_kD ); 45 m_fCD = mDotPerp( m_kC, m_kD ); 46} 47 48Point2F BiQuadToSqr::transform( const Point2F &p ) const 49{ 50 Point2F kA = m_kP00 - p; 51 52 F32 fAB = mDotPerp( kA, m_kB ); 53 F32 fAC = mDotPerp( kA, m_kC); 54 55 // 0 = ac*bc+(bc^2+ac*bd-ab*cd)*s+bc*bd*s^2 = k0 + k1*s + k2*s^2 56 F32 fK0 = fAC*m_fBC; 57 F32 fK1 = m_fBC*m_fBC + fAC*m_fBD - fAB*m_fCD; 58 F32 fK2 = m_fBC*m_fBD; 59 60 if (mFabs(fK2) > POINT_EPSILON) 61 { 62 // s-equation is quadratic 63 F32 fInv = 0.5f/fK2; 64 F32 fDiscr = fK1*fK1 - 4.0f*fK0*fK2; 65 F32 fRoot = mSqrt( mFabs(fDiscr) ); 66 67 Point2F kResult0( 0, 0 ); 68 kResult0.x = (-fK1 - fRoot)*fInv; 69 kResult0.y = fAB/(m_fBC + m_fBD*kResult0.x); 70 F32 fDeviation0 = deviation(kResult0); 71 if ( fDeviation0 == 0.0f ) 72 return kResult0; 73 74 Point2F kResult1( 0, 0 ); 75 kResult1.x = (-fK1 + fRoot)*fInv; 76 kResult1.y = fAB/(m_fBC + m_fBD*kResult1.x); 77 F32 fDeviation1 = deviation(kResult1); 78 if ( fDeviation1 == 0.0f ) 79 return kResult1; 80 81 if (fDeviation0 <= fDeviation1) 82 { 83 if ( fDeviation0 < POINT_EPSILON ) 84 return kResult0; 85 } 86 else 87 { 88 if ( fDeviation1 < POINT_EPSILON ) 89 return kResult1; 90 } 91 } 92 else 93 { 94 // s-equation is linear 95 Point2F kResult( 0, 0 ); 96 97 kResult.x = -fK0/fK1; 98 kResult.y = fAB/(m_fBC + m_fBD*kResult.x); 99 F32 fDeviation = deviation(kResult); 100 if ( fDeviation < POINT_EPSILON ) 101 return kResult; 102 } 103 104 // point is outside the quadrilateral, return invalid 105 return Point2F(F32_MAX,F32_MAX); 106} 107 108F32 BiQuadToSqr::deviation( const Point2F &sp ) 109{ 110 // deviation is the squared distance of the point from the unit square 111 F32 fDeviation = 0.0f; 112 F32 fDelta; 113 114 if (sp.x < 0.0f) 115 { 116 fDeviation += sp.x*sp.x; 117 } 118 else if (sp.x > 1.0f) 119 { 120 fDelta = sp.x - 1.0f; 121 fDeviation += fDelta*fDelta; 122 } 123 124 if (sp.y < 0.0f) 125 { 126 fDeviation += sp.y*sp.y; 127 } 128 else if (sp.y > 1.0f) 129 { 130 fDelta = sp.y - 1.0f; 131 fDeviation += fDelta*fDelta; 132 } 133 134 return fDeviation; 135} 136 137 138BiSqrToQuad3D::BiSqrToQuad3D( const Point3F& pnt00, 139 const Point3F& pnt10, 140 const Point3F& pnt11, 141 const Point3F& pnt01) 142{ 143 p00 = pnt00; 144 p10 = pnt10; 145 p11 = pnt11; 146 p01 = pnt01; 147} 148 149Point3F BiSqrToQuad3D::transform( const Point2F &p ) const 150{ 151 //Let p00, p10, p01, and p11 be your 3-tuples that are the quad's 152 //vertices. You can parameterize the quad as follows. 153 154 //q(s,t) = (1-s)*((1-t)*p00 + t*p01) + s*((1-t)*p10 + t*p11) 155 156 //for 0 <= s <= 1 and 0 <= t <= 1. Notice that q(0,0) = p00, 157 //q(1,0) = p10, q(0,1) = p01, and q(1,1) = p11, so the parameter 158 //"square" whose points are (s,t) will be mapped to the quad. 159 160 const F32 &s = p.x; 161 const F32 &t = p.y; 162 163 Point3F result = (1.0f-s)*((1.0f-t)*p00 + t*p01) + s*((1.0f-t)*p10 + t*p11); 164 return result; 165} 166 167