@@ -413,6 +413,33 @@ vector3f SystemBody::GetCoefficients(const double radius, const double atmHeight
413413 return vector3f (k, b, c);
414414}
415415
416+ /*
417+ * given ray and a circle, calculate points where ray intersects a circle
418+ * r - radius of a circle
419+ * v - ray start, given circle center is at origin
420+ * dir - ray direction, pre-normalized
421+ * x1, x2 - solutions
422+ *
423+ * returns false if circle is not intersected
424+ */
425+ bool rayCircleIntersection (double *x1, double *x2, const vector2d v, const double radius, const vector2d dir)
426+ {
427+ double b = -(v.x * dir.x + v.y * dir.y );
428+ double det = (b * b) - v.LengthSqr () + (radius * radius);
429+ // Output("DEBUG: v = [%lf, %lf], radius = %lf, dir = [%lf, %lf], b = %lf, det = %lf\n", v.x, v.y, radius, dir.x, dir.y, b, det);
430+
431+ if (det >= 0 ) {
432+ double sdet = sqrt (det);
433+
434+ *x1 = b - sdet;
435+ *x2 = b + sdet;
436+
437+ return true ;
438+ } else {
439+ return false ;
440+ }
441+ }
442+
416443// Calculate parameters used in the atmospheric model for shaders
417444AtmosphereParameters SystemBody::CalcAtmosphereParams () const
418445{
@@ -493,6 +520,72 @@ AtmosphereParameters SystemBody::CalcAtmosphereParams() const
493520 params.logDensityMap [i] = vector2f (rLogDensity, mLogDensity );
494521 }
495522
523+ // tests
524+ double tx1, tx2;
525+ if (GetName () == " Mars" ) {
526+ rayCircleIntersection (&tx1, &tx2, vector2d (0.0 , 4.0 ), 5.0 , vector2d (0.0 , 1.0 ));
527+ // Output("%s: test intersections %lf, %lf\n", GetName().c_str(), tx1, tx2);
528+ rayCircleIntersection (&tx1, &tx2, vector2d (0.0 , 4.0 ), 5.0 , vector2d (1.0 , 0.0 ));
529+ // Output("%s: test intersections %lf, %lf\n", GetName().c_str(), tx1, tx2);
530+ }
531+
532+ Output (" %s: generating density model\n " , GetName ());
533+
534+ // pre-calculate density LUT based on current height and angle to horizon
535+ for (int i = 0 ; i <= DENSITY_STEPS; ++i) {
536+ double startHeight = i * atmosHeight / DENSITY_STEPS;
537+
538+ for (int j = 0 ; j <= DENSITY_STEPS; ++j) {
539+ // pitch in radians
540+ double pitch = M_PI * ((1.0 * j / DENSITY_STEPS) - 0.5 );
541+ vector2d direction = vector2d (1.0 , 0.0 ).Rotate (pitch); // calculate in 2d space
542+ vector2d tCurrent = vector2d (0.0 , startHeight + radiusPlanet_in_m);
543+
544+ double atm1 = 0.0 , atm2 = 0.0 ;
545+ bool atmIntersection = rayCircleIntersection (&atm1, &atm2, tCurrent, radiusPlanet_in_m * params.atmosRadius , direction);
546+
547+ if (!atmIntersection)
548+ continue ;
549+
550+ double planet1 = 0.0 , planet2 = 0.0 ;
551+ bool planetIntersection = rayCircleIntersection (&planet1, &planet2, tCurrent, radiusPlanet_in_m - 0.01 , direction);
552+
553+ double startRay = 0.0 , finishRay = atm2;
554+ if (planetIntersection) {
555+ if (planet1 >= 0 ) finishRay = planet1; // we hit the planet
556+
557+ // otherwise we would hit the planet while tracing *backwards*
558+ }
559+
560+ int numSamples = 16 ;
561+ double segment = (finishRay - startRay) / numSamples;
562+ double rDensity = 0.0 , mDensity = 0.0 ;
563+ for (int k = 0 ; k < numSamples; ++k) {
564+ vector2d samplePosition = tCurrent + (segment * 0.5 ) * direction;
565+ double sampleHeight = samplePosition.Length () - radiusPlanet_in_m;
566+
567+ double sampleDensityR = GetAtmDensity (sampleHeight, GetAtmPressure (sampleHeight));
568+ double sampleDensityM = GetAtmDensity (6.66 * sampleHeight, GetAtmPressure (6.66 * sampleHeight));
569+ if (std::isnan (sampleDensityM))
570+ sampleDensityM = 0.0 ;
571+
572+ rDensity += segment * sampleDensityR;
573+ mDensity += segment * sampleDensityM;
574+
575+ tCurrent += direction * segment;
576+ }
577+
578+ double rLogDensity, mLogDensity ;
579+
580+ rLogDensity = rDensity > 0.0 ? log (rDensity) : -128.0 ;
581+ mLogDensity = mDensity > 0.0 ? log (mDensity ) : -128.0 ;
582+
583+ if (GetName () == " Mars" ) {
584+ // Output("%s: calculated density for ray (height = %lf, pitch = %lf): log(r) = %lf, log(m) = %lf\n\n", GetName().c_str(), startHeight, pitch, rLogDensity, mLogDensity);
585+ }
586+ }
587+ }
588+
496589 return params;
497590}
498591
0 commit comments