public override double intersection(Ray r) { float t = float.MaxValue;//(r.Direction.X * r.Direction.X + r.Direction.Y * r.Direction.Y + r.Direction.Z * r.Direction.Z); List<poly> polynomMap = new List<poly>(); float rSquare, rInvSquare; rSquare = size * size; rInvSquare = invSizeSquare; float maxEstimatedPotential = 0.0f; float A = 0.0f; float B = 0.0f; float C = 0.0f; for (int i= 0; i< centerList.Count; i++) { Vector3 currentPoint = centerList[i]; Vector3 vDist = currentPoint - r.Start; float aa = 1.0f; float bb = - 2.0f * (r.Direction.X*vDist.X + r.Direction.Y*vDist.Y + r.Direction.Z*vDist.Z); float cc = (vDist.X*vDist.X + vDist.Y*vDist.Y + vDist.Z*vDist.Z); float BSquareOverFourMinusC = 0.25f * bb * bb - cc; float MinusBOverTwo = -0.5f * bb; float ATimeInvSquare = aa * rInvSquare; float BTimeInvSquare = bb * rInvSquare; float CTimeInvSquare = cc * rInvSquare; for (int j=0; j < zoneNumber - 1; j++) { float fDelta = BSquareOverFourMinusC + zoneTab[j].fCoef * rSquare; if (fDelta < 0.0f) { break; } float sqrtDelta = (float)Math.Sqrt(fDelta); float t0 = MinusBOverTwo - sqrtDelta; float t1 = MinusBOverTwo + sqrtDelta; poly poly0 = new poly(zoneTab[j].fGamma * ATimeInvSquare , zoneTab[j].fGamma * BTimeInvSquare , zoneTab[j].fGamma * CTimeInvSquare + zoneTab[j].fBeta, t0, zoneTab[j].fDeltaFInvSquare); poly poly1 = new poly(- poly0.a, - poly0.b, - poly0.c, t1, -poly0.fDeltaFInvSquare); maxEstimatedPotential += zoneTab[j].fDeltaFInvSquare; polynomMap.Add(poly0); polynomMap.Add(poly1); }; } if (polynomMap.Count < 2 || maxEstimatedPotential < 1.0f) { return 0; } polynomMap.Sort((x, y) => x.isLess(y)); maxEstimatedPotential = 0.0f; bool bResult = false; int it, itNext; for(it = 0, itNext = it+1; itNext < polynomMap.Count; it = itNext, itNext++) { A += polynomMap[it].a; B += polynomMap[it].b; C += polynomMap[it].c; maxEstimatedPotential += polynomMap[it].fDeltaFInvSquare; if (maxEstimatedPotential < 1.0f) { continue; } float fZoneStart = polynomMap[it].fDistance; float fZoneEnd = polynomMap[itNext].fDistance; if (t > fZoneStart && 0.01f < fZoneEnd ) { float fDelta = B * B - 4.0f * A * (C - 1.0f) ; if (fDelta < 0.0f) { continue; } if(A == 0) A = float.MinValue; float fInvA = (0.5f / A); float fSqrtDelta = (float)Math.Sqrt(fDelta); float t0 = fInvA * (- B - fSqrtDelta); float t1 = fInvA * (- B + fSqrtDelta); if ((t0 > 0.01f ) && (t0 >= fZoneStart ) && (t0 < fZoneEnd) && (t0 <= t )) { t = t0; bResult = true; } if ((t1 > 0.01f ) && (t1 >= fZoneStart ) && (t1 < fZoneEnd) && (t1 <= t )) { t = t1; bResult = true; } if (bResult) { return t; } } } return 0; }
public int isLess(poly p) { if (fDistance < p.fDistance) return -1; else if (fDistance == p.fDistance) return 0; else return 1; }