Пример #1
0
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);
    }
Пример #3
0
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);
}