float Math::ArcTanAngle(const float& x, const float& y) { if(x == 0) { if(y == 1) return Constants::PiOverTwo; else return -Constants::PiOverTwo; } else if(x > 0) return ATan(y / x); else if(x < 0) { if(y > 0) return ATan(y / x) + Constants::Pi; else return ATan(y / x) - Constants::Pi; } else return 0; }
inline Big<Exponent, Mantissa> atan2(Big<Exponent, Mantissa> const& y, Big<Exponent, Mantissa> const& x) { // return ATan2(y, 2); does not (yet) exist in ttmath... // See http://en.wikipedia.org/wiki/Atan2 Big<Exponent, Mantissa> const zero(0); Big<Exponent, Mantissa> const two(2); if (y == zero) { // return x >= 0 ? 0 : pi and pi=2*arccos(0) return x >= zero ? zero : two * ACos(zero); } return two * ATan((sqrt(x * x + y * y) - x) / y); }
Vector SDKGradientClass::Output(BaseShader *sh, ChannelData *sd) { Vector p=sd->p; Real r=0.0,angle,xx,yy; if (gdata.turbulence>0.0) { Vector res; Real scl=5.0*gdata.scale,tt=sd->t*gdata.freq*0.3; res = Vector(Turbulence(p*scl,tt,gdata.octaves,TRUE),Turbulence((p+Vector(0.34,13.0,2.43))*scl,tt,gdata.octaves,TRUE),0.0); if (gdata.absolute) { p.x = Mix(p.x,res.x,gdata.turbulence); p.y = Mix(p.y,res.y,gdata.turbulence); } else { p.x += (res.x-0.5)*gdata.turbulence; p.y += (res.y-0.5)*gdata.turbulence; } } // rotation p.x -= 0.5; p.y -= 0.5; xx = gdata.ca*p.x-gdata.sa*p.y + 0.5; yy = gdata.sa*p.x+gdata.ca*p.y + 0.5; p.x = xx; p.y = yy; if (gdata.mode<=SDKGRADIENTSHADER_MODE_CORNER && gdata.cycle && (sd->texflag&TEX_TILE)) { if (sd->texflag & TEX_MIRROR) { p.x = Modulo(p.x,RCO 2.0); if (p.x>=1.0) p.x=2.0-p.x; p.y = Modulo(p.y,RCO 2.0); if (p.y>= 1.0) p.y=2.0-p.y; } else { p.x = Modulo(p.x, RCO 1.0); p.y = Modulo(p.y, RCO 1.0); } } switch (gdata.mode) { case SDKGRADIENTSHADER_MODE_U: r = p.x; break; case SDKGRADIENTSHADER_MODE_V: r = 1.0-p.y; break; case SDKGRADIENTSHADER_MODE_DIAGONAL: r = (p.x+p.y)*0.5; break; case SDKGRADIENTSHADER_MODE_RADIAL: p.x-=0.5; p.y-=0.5; if (p.x==0.0) p.x=0.00001; angle = ATan(p.y/p.x); if (p.x<0.0) angle+=pi; if (angle<0.0) angle+=pi2; r = angle/pi2; break; case SDKGRADIENTSHADER_MODE_CIRCULAR: p.x-=0.5; p.y-=0.5; r = Sqrt(p.x*p.x+p.y*p.y)*2.0; break; case SDKGRADIENTSHADER_MODE_BOX: p.x = Abs(p.x - 0.5); p.y = Abs(p.y - 0.5); r = FMax(p.x,p.y)*2.0; break; case SDKGRADIENTSHADER_MODE_STAR: p.x = Abs(p.x - 0.5)-0.5; p.y = Abs(p.y - 0.5)-0.5; r = Sqrt(p.x*p.x+p.y*p.y) * 1.4142; break; case SDKGRADIENTSHADER_MODE_CORNER: { Real cx; Vector ca,cb; cx = FCut01(p.x); ca = Mix(gdata.c[0],gdata.c[1],cx); cb = Mix(gdata.c[2],gdata.c[3],cx); return Mix(ca,cb,FCut01(p.y)); break; } } return gdata.gradient->CalcGradientPixel(FCut01(r)); }
inline Big<Exponent, Mantissa> atan(Big<Exponent, Mantissa> const& v) { return ATan(v); }
/* * Prepare for projecting. */ void CPerspectiveProjection3D::Prepare(void) { FLOATmatrix3D t3dObjectStretch; // matrix for object stretch FLOATmatrix3D t3dObjectRotation; // matrix for object angles // calc. matrices for viewer and object angles and stretch MakeRotationMatrixFast( t3dObjectRotation, pr_ObjectPlacement.pl_OrientationAngle); MakeInverseRotationMatrixFast( pr_ViewerRotationMatrix, pr_ViewerPlacement.pl_OrientationAngle); t3dObjectStretch.Diagonal(pr_ObjectStretch); pr_vViewerPosition = pr_ViewerPlacement.pl_PositionVector; BOOL bXInverted = pr_ObjectStretch(1)<0; BOOL bYInverted = pr_ObjectStretch(2)<0; BOOL bZInverted = pr_ObjectStretch(3)<0; pr_bInverted = (bXInverted != bYInverted) != bZInverted; // if the projection is mirrored if (pr_bMirror) { // reflect viewer ReflectPositionVectorByPlane(pr_plMirror, pr_vViewerPosition); ReflectRotationMatrixByPlane_rows(pr_plMirror, pr_ViewerRotationMatrix); // get mirror plane in view space pr_plMirrorView = pr_plMirror; pr_plMirrorView -= pr_vViewerPosition; pr_plMirrorView *= pr_ViewerRotationMatrix; // invert inversion pr_bInverted = !pr_bInverted; } else if (pr_bWarp) { // get mirror plane in view space pr_plMirrorView = pr_plMirror; } // if the object is face-forward if (pr_bFaceForward) { // if it turns only heading if (pr_bHalfFaceForward) { // get the y-axis vector of object rotation FLOAT3D vY(t3dObjectRotation(1,2), t3dObjectRotation(2,2), t3dObjectRotation(3,2)); // find z axis of viewer FLOAT3D vViewerZ( pr_ViewerRotationMatrix(3,1), pr_ViewerRotationMatrix(3,2), pr_ViewerRotationMatrix(3,3)); // calculate x and z axis vectors to make object head towards viewer FLOAT3D vX = (-vViewerZ)*vY; vX.Normalize(); FLOAT3D vZ = vY*vX; // compose the rotation matrix back from those angles t3dObjectRotation(1,1) = vX(1); t3dObjectRotation(1,2) = vY(1); t3dObjectRotation(1,3) = vZ(1); t3dObjectRotation(2,1) = vX(2); t3dObjectRotation(2,2) = vY(2); t3dObjectRotation(2,3) = vZ(2); t3dObjectRotation(3,1) = vX(3); t3dObjectRotation(3,2) = vY(3); t3dObjectRotation(3,3) = vZ(3); // first apply object stretch then object rotation and then viewer rotation pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; // if it is fully face forward } else { // apply object stretch and banking only FLOATmatrix3D mBanking; MakeRotationMatrixFast( mBanking, ANGLE3D(0,0, pr_ObjectPlacement.pl_OrientationAngle(3))); pr_mDirectionRotation = mBanking; pr_RotationMatrix = mBanking*t3dObjectStretch; } } else { // first apply object stretch then object rotation and then viewer rotation pr_mDirectionRotation = pr_ViewerRotationMatrix*t3dObjectRotation; pr_RotationMatrix = pr_mDirectionRotation*t3dObjectStretch; } // calc. offset of object from viewer pr_TranslationVector = pr_ObjectPlacement.pl_PositionVector - pr_vViewerPosition; // rotate offset only by viewer angles pr_TranslationVector = pr_TranslationVector*pr_ViewerRotationMatrix; // transform handle from object space to viewer space and add it to the offset pr_TranslationVector -= pr_vObjectHandle*pr_RotationMatrix; FLOAT2D vMin, vMax; // if using a shadow projection if (ppr_fMetersPerPixel>0) { // caclulate factors FLOAT fFactor = ppr_fViewerDistance/ppr_fMetersPerPixel; ppr_PerspectiveRatios(1) = -fFactor; ppr_PerspectiveRatios(2) = -fFactor; pr_ScreenCenter = -pr_ScreenBBox.Min(); vMin = pr_ScreenBBox.Min(); vMax = pr_ScreenBBox.Max(); // if using normal projection } else if (ppr_boxSubScreen.IsEmpty()) { // calculate perspective constants FLOAT2D v2dScreenSize = pr_ScreenBBox.Size(); pr_ScreenCenter = pr_ScreenBBox.Center(); /* calculate FOVHeight from FOVWidth by formula: halfanglej = atan( tan(halfanglei)*jsize*aspect/isize ) */ ANGLE aHalfI = ppr_FOVWidth/2; ANGLE aHalfJ = ATan(TanFast(aHalfI)*v2dScreenSize(2)*pr_AspectRatio/v2dScreenSize(1)); /* calc. perspective ratios by formulae: xratio = isize/(2*tan(anglei/2)) yratio = jsize/(2*tan(anglej/2)) sign is negative since viewer is looking down the -z axis */ ppr_PerspectiveRatios(1) = -v2dScreenSize(1)/(2.0f*TanFast(aHalfI))*pr_fViewStretch; ppr_PerspectiveRatios(2) = -v2dScreenSize(2)/(2.0f*TanFast(aHalfJ))*pr_fViewStretch; vMin = pr_ScreenBBox.Min()-pr_ScreenCenter; vMax = pr_ScreenBBox.Max()-pr_ScreenCenter; // if using sub-drawport projection } else { // calculate perspective constants FLOAT2D v2dScreenSize = pr_ScreenBBox.Size(); pr_ScreenCenter = pr_ScreenBBox.Center(); /* calculate FOVHeight from FOVWidth by formula: halfanglej = atan( tan(halfanglei)*jsize*aspect/isize ) */ ANGLE aHalfI = ppr_FOVWidth/2; ANGLE aHalfJ = ATan(TanFast(aHalfI)*v2dScreenSize(2)*pr_AspectRatio/v2dScreenSize(1)); /* calc. perspective ratios by formulae: xratio = isize/(2*tan(anglei/2)) yratio = jsize/(2*tan(anglej/2)) sign is negative since viewer is looking down the -z axis */ ppr_PerspectiveRatios(1) = -v2dScreenSize(1)/(2.0f*TanFast(aHalfI))*pr_fViewStretch; ppr_PerspectiveRatios(2) = -v2dScreenSize(2)/(2.0f*TanFast(aHalfJ))*pr_fViewStretch; vMin = ppr_boxSubScreen.Min()-pr_ScreenCenter; vMax = ppr_boxSubScreen.Max()-pr_ScreenCenter; pr_ScreenCenter -= ppr_boxSubScreen.Min(); } // find factors for left, right, up and down clipping FLOAT fMinI = vMin(1); FLOAT fMinJ = vMin(2); FLOAT fMaxI = vMax(1); FLOAT fMaxJ = vMax(2); FLOAT fRatioX = ppr_PerspectiveRatios(1); FLOAT fRatioY = ppr_PerspectiveRatios(2); #define MySgn(x) ((x)>=0?1:-1) FLOAT fDZ = -1.0f; FLOAT fDXL = fDZ*fMinI/fRatioX; FLOAT fDXR = fDZ*fMaxI/fRatioX; FLOAT fDYU = -fDZ*fMinJ/fRatioY; FLOAT fDYD = -fDZ*fMaxJ/fRatioY; FLOAT fNLX = -fDZ; FLOAT fNLZ = +fDXL; FLOAT fOoNL = 1.0f/(FLOAT)sqrt(fNLX*fNLX+fNLZ*fNLZ); fNLX*=fOoNL; fNLZ*=fOoNL; FLOAT fNRX = +fDZ; FLOAT fNRZ = -fDXR; FLOAT fOoNR = 1.0f/(FLOAT)sqrt(fNRX*fNRX+fNRZ*fNRZ); fNRX*=fOoNR; fNRZ*=fOoNR; FLOAT fNDY = -fDZ; FLOAT fNDZ = +fDYD; FLOAT fOoND = 1.0f/(FLOAT)sqrt(fNDY*fNDY+fNDZ*fNDZ); fNDY*=fOoND; fNDZ*=fOoND; FLOAT fNUY = +fDZ; FLOAT fNUZ = -fDYU; FLOAT fOoNU = 1.0f/(FLOAT)sqrt(fNUY*fNUY+fNUZ*fNUZ); fNUY*=fOoNU; fNUZ*=fOoNU; // make clip planes pr_plClipU = FLOATplane3D(FLOAT3D( 0,fNUY,fNUZ), 0.0f); pr_plClipD = FLOATplane3D(FLOAT3D( 0,fNDY,fNDZ), 0.0f); pr_plClipL = FLOATplane3D(FLOAT3D(fNLX, 0,fNLZ), 0.0f); pr_plClipR = FLOATplane3D(FLOAT3D(fNRX, 0,fNRZ), 0.0f); // mark as prepared pr_Prepared = TRUE; // calculate constant value used for calculating z-buffer k-value from vertex's z coordinate pr_fDepthBufferFactor = -pr_NearClipDistance; pr_fDepthBufferMul = pr_fDepthBufferFar-pr_fDepthBufferNear; pr_fDepthBufferAdd = pr_fDepthBufferNear; // calculate ratio for mip factor calculation ppr_fMipRatio = pr_ScreenBBox.Size()(1)/(ppr_PerspectiveRatios(1)*640.0f); }