/*
 * 3D Engine 
 * vector.c: 
 * Based on pikuma.com 3D software renderer in C
 * Copyright (c) 2021 986-Studio. All rights reserved.
 *
 * Created by Manoël Trapier on 02/03/2021.
 */

#include <vector.h>
#include <math.h>

/* ---------------------------------------------- 2D Vectors operations --------------------------------------------- */
double vec2Getlength(vec2_t v)
{
    return sqrt(v.x * v.x + v.y * v.y);
}

vec2_t vec2AddVectors(vec2_t a, vec2_t b)
{
    vec2_t ret = { a.x + b.x, a.y + b.y};
    return ret;
}

vec2_t vec2SubVectors(vec2_t a, vec2_t b)
{
    vec2_t ret = { a.x - b.x, a.y - b.y};
    return ret;
}

vec2_t vec2ScalarMult(vec2_t a, double s)
{
    vec2_t ret = { a.x * s, a.y * s };
    return ret;
}

vec2_t vec2ScalarDiv(vec2_t a, double s)
{
    vec2_t ret = { a.x / s, a.y / s};
    return ret;
}

double vec2Dot(vec2_t a, vec2_t b)
{
    return a.x * b.x + a.y * b.y;
}

void vec2Normalize(vec2_t *a)
{
    double length = vec2Getlength(*a);
    *a = vec2ScalarDiv(*a, length);
}

vec2_t vec2FromVec4(vec4_t v)
{
    vec2_t ret = { v.x, v.y };
    return ret;
}

/* ---------------------------------------------- 3D Vectors operations --------------------------------------------- */
double vec3Getlength(vec3_t v)
{
    return sqrt(v.x * v.x + v.y * v.y + v.z * v.z);
}

vec3_t vec3AddVectors(vec3_t a, vec3_t b)
{
    vec3_t ret = { a.x + b.x, a.y + b.y , a.z + b.z };
    return ret;
}

vec3_t vec3SubVectors(vec3_t a, vec3_t b)
{
    vec3_t ret = { a.x - b.x, a.y - b.y , a.z - b.z };
    return ret;
}

vec3_t vec3ScalarMult(vec3_t a, double s)
{
    vec3_t ret = { a.x * s, a.y * s, a.z * s};
    return ret;
}

vec3_t vec3ScalarDiv(vec3_t a, double s)
{
    vec3_t ret = { a.x / s, a.y / s, a.z / s};
    return ret;
}

vec3_t vec3Cross(vec3_t a, vec3_t b)
{
    vec3_t ret =
    {
        .x = a.y * b.z - a.z * b.y,
        .y = a.z * b.x - a.x * b.z,
        .z = a.x * b.y - a.y * b.x,
    };
    return ret;
}

double vec3Dot(vec3_t a, vec3_t b)
{
    return a.x * b.x + a.y * b.y + a.z * b.z;
}

void vec3Normalize(vec3_t *a)
{
    double length = vec3Getlength(*a);
    *a = vec3ScalarDiv(*a, length);
}

vec3_t vec3RotateX(vec3_t original, double angle)
{
    vec3_t ret = {
        .x = original.x,
        .y = original.y * cos(angle) - original.z * sin(angle),
        .z = original.y * sin(angle) + original.z * cos(angle)
    };
    return ret;
}

vec3_t vec3RotateY(vec3_t original, double angle)
{
    vec3_t ret = {
        .x = original.x * cos(angle) + original.z * sin(angle),
        .y = original.y,
        .z = -original.x * sin(angle) + original.z * cos(angle)
    };
    return ret;
}

vec3_t vec3RotateZ(vec3_t original, double angle)
{
    vec3_t ret = {
        .x = original.x * cos(angle) - original.y * sin(angle),
        .y = original.x * sin(angle) + original.y * cos(angle),
        .z = original.z,
    };
    return ret;
}

/* ---------------------------------------------- 4D Vectors operations --------------------------------------------- */
vec4_t vec4FromVec3(vec3_t v)
{
    vec4_t ret = { v.x, v.y, v.z, 1 };
    return ret;
}