---
--- Generated by EmmyLua(https://github.com/EmmyLua)
--- Created by HUAFEI2.
--- DateTime: 2020/6/29 11:48
---

---@class LPlane
LPlane = LPlane or class("LPlane");

---@enum number
---@readonly
local KPointSide =
{
    IN_PLANE = 0,
    FRONT_PLANE = 1,
    BEHIND_PLAN = 2
};

function LPlane:ctor()
    self.vNormal = LVec3:new();
    self.d = 0.0;
end

---@param vNormal LVec3
---@param d number
---@return LPlane
function LPlane:Set(vNormal, d)
    self.vNormal:CopyFrom(vNormal);
    self.d = d;
    return self;
end

---@return LPlane
function LPlane:Normalize()
    PlaneNormalize(self);
    return self;
end

---@param plane LPlane
---@param vec3_a LVec3
---@param vec3_b LVec3
---@param vec3_c LVec3
---@return LPlane
function ComputePlaneFromPoints(plane, vec3_a, vec3_b, vec3_c)
    local kEdge1 = vec3_b.clone();
    kEdge1:Minus(vec3_a);
    
    local kEdge2 = vec3_c.clone();
    kEdge2:Minus(vec3_b);
    
    Vec3Cross(plane.vNormal, kEdge1, kEdge2);
    plane.vNormal:Normalize();
    return plane;
end

---@param plane LPlane
---@param normal LVec3
---@param fDist number
---@return LPlane
function ComputePlaneFromNormalDist(plane, normal, fDist)
    local oneOverLength = 1.0 / normal.length();
    plane.vNormal = normal * oneOverLength;
    plane.d = fDist * oneOverLength;
    return plane;
end

---@param plane LPlane
---@param point LVec3
---@param normal LVec3
---@return LPlane
function ComputePlaneFromPointNormal(plane, point, normal)
    plane.vNormal:CopyFrom(normal);
    plane.d = plane.vNormal:Dot(point);
    return plane;
end

---@param plane LPlane
---@param point LVec3
---@return number
function ComputeDistance(plane, point)
    return plane.vNormal.dot(point) - plane.d;
end

---@param plane LPlane
---@return LPlane
function PlaneNormalize(plane)
    plane.vNormal.normalize();
    return plane;
end

---@param plane LPlane
---@param point LVec3
---@return number
function GetToPlaneSide(plane, pPoint)
    local fdist = ComputeDistance(plane, pPoint);
    if (fdist > 0) then
        return KPointSide.FRONT_PLANE;
    elseif (fdist < 0) then
        return KPointSide.BEHIND_PLANE;
    else
        return KPointSide.IN_PLANE;
    end
end

---@param vOut LVec3
---@param plane LPlane
---@param v1 LVec3
---@param v2 LVec3
---@return boolean
function PlaneIntersectLine(vOut, plane, v1, v2)
    vOut.x = 0.0; vOut.y = 0.0; vOut.z = 0.0;
    local direction = LVec3:new();
    local normal = LVec3:new();
    local dot, temp;
    normal:CopyFrom(plane.vNormal);

    Vec3Minus(direction, v2, v1);
    dot = normal:Dot(direction);
    if (dot == 0.0) then
        return false;
    else
        temp = (plane.d - normal.dot(v1)) / dot;
        out:CopyFrom(v1):Add(direction:Multiply(temp));
        return true;
    end
end
