/*****************************************************************************************
 *                                                                                       *
 * OpenSpace                                                                             *
 *                                                                                       *
 * Copyright (c) 2014                                                                    *
 *                                                                                       *
 * Permission is hereby granted, free of charge, to any person obtaining a copy of this  *
 * software and associated documentation files (the "Software"), to deal in the Software *
 * without restriction, including without limitation the rights to use, copy, modify,    *
 * merge, publish, distribute, sublicense, and/or sell copies of the Software, and to    *
 * permit persons to whom the Software is furnished to do so, subject to the following   *
 * conditions:                                                                           *
 *                                                                                       *
 * The above copyright notice and this permission notice shall be included in all copies *
 * or substantial portions of the Software.                                              *
 *                                                                                       *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,   *
 * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A         *
 * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT    *
 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF  *
 * CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE  *
 * OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.                                         *
 ****************************************************************************************/

#ifndef ELLIPSOID_HGLSL
#define ELLIPSOID_HGLSL

struct PositionNormalPair {
	vec3 position;
	vec3 normal;
};

struct Intersection {
    bool  intersects;
    float nearParameter;// Along ray
    float farParameter;	// Along ray
};

vec3 geodeticSurfaceNormal(float latitude, float longitude)
{
	float cosLat = cos(latitude);
	return vec3(
		cosLat * cos(longitude),
		cosLat * sin(longitude), 
		sin(latitude));
}

PositionNormalPair geodetic3ToCartesian(
	float latitude,
	float longitude,
	float height,
	vec3 radiiSquared)
{
	vec3 normal = geodeticSurfaceNormal(latitude, longitude);
	vec3 k = radiiSquared * normal;
	float gamma = sqrt(dot(k, normal));
	vec3 rSurface = k / gamma;
	PositionNormalPair toReturn;
	toReturn.position = rSurface + height * normal;
	toReturn.normal = normal;
	return toReturn;
}

PositionNormalPair geodetic2ToCartesian(float latitude, float longitude, vec3 radiiSquared)
{
	// Position on surface : height = 0
	return geodetic3ToCartesian(latitude, longitude, 0, radiiSquared);
}

vec3 latLonToCartesian(float latitude, float longitude, float radius) {
	return radius * vec3(
		cos(latitude) * cos(longitude),
		cos(latitude) * sin(longitude),
		sin(latitude));
}

//
// Assumes ellipsoid is at (0, 0, 0)
//
Intersection rayIntersectEllipsoid(
	vec3 rayOrigin,
	vec3 rayOriginSquared,
	vec3 rayDirection,
	vec3 oneOverEllipsoidRadiiSquared)
{
    float a = dot(rayDirection * rayDirection, oneOverEllipsoidRadiiSquared);
    float b = 2.0 * dot(rayOrigin * rayDirection, oneOverEllipsoidRadiiSquared);
    float c = dot(rayOriginSquared, oneOverEllipsoidRadiiSquared) - 1.0;
    float discriminant = b * b - 4.0 * a * c;

    if (discriminant < 0.0) {
        return Intersection(false, 0.0, 0.0);
    }
    else if (discriminant == 0.0) {
        float time = -0.5 * b / a;
        return Intersection(true, time, time);
    }

    float t = -0.5 * (b + (b > 0.0 ? 1.0 : -1.0) * sqrt(discriminant));
    float root1 = t / a;
    float root2 = c / t;

    return Intersection(true, min(root1, root2), max(root1, root2));
}

#endif // ELLIPSOID_HGLSL