aboutsummaryrefslogtreecommitdiff
#include "util.h"

#include <SDL2/SDL.h>

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdarg.h>

unsigned int Util_Hash( const char *str )
{
    unsigned int hash, i, length;
    length = strlen(str);

    for(hash = i = 0; i < length; ++i)
    {
        hash += str[i];
        hash += (hash << 10);
        hash ^= (hash >> 6);
    }

    hash += (hash << 3);
    hash ^= (hash >> 11);
    hash += (hash << 15);

    return hash;
}

void Util_FatalError( const char *fmt, ... )
{
    fprintf(stderr, "Fatal Error:\n");

    va_list args;
    va_start(args, fmt);
    vfprintf(stderr, fmt, args);
    va_end(args);

    SDL_Quit();
    exit(1);
}

void Util_CheckGLError()
{
    GLenum error = glGetError();
    switch(error)
    {
        case GL_INVALID_ENUM:
            fprintf(stderr, "WARNING: GL_INVALID_ENUM\n");
            break;
        case GL_INVALID_VALUE:
            fprintf(stderr, "WARNING: GL_INVALID_VALUE\n");
            break;
        case GL_INVALID_OPERATION:
            fprintf(stderr, "WARNING: GL_INVALID_OPERATION\n");
            break;
        case GL_INVALID_FRAMEBUFFER_OPERATION:
            fprintf(stderr, "WARNING: GL_INVALID_FRAMEBUFFER_OPERATION\n");
            break;
        case GL_OUT_OF_MEMORY:
            fprintf(stderr, "WARNING: GL_OUT_OF_MEMORY\n");
            break;
        case GL_STACK_UNDERFLOW:
            fprintf(stderr, "WARNING: GL_STACK_UNDERFLOW\n");
            break;
        case GL_STACK_OVERFLOW:
            fprintf(stderr, "WARNING: GL_STACK_OVERFLOW\n");
            break;

        default:
            break;
    }
}

char *Util_LoadFile( const char *path )
{
	FILE* file = fopen( path, "r" );

	if(file == NULL)
    {
        Util_FatalError("File %s could not be found!\n", path);
    }

	fseek( file, 0, SEEK_END );
	size_t sizeOfFile = ftell( file );
	fseek( file, 0, SEEK_SET );
	char* file_data = malloc( sizeof(char) * sizeOfFile + 1 );
	fread( file_data, sizeof(char), sizeOfFile, file );
	file_data[sizeOfFile] = '\0';
	fclose(file);
	return file_data;
}

float Util_RandomF(float min, float max)
{
    return ( min + (float)rand() ) / ( (float)RAND_MAX / (max-min) );
}

int Util_RandomI(int min, int max)
{
    return ( rand() % (max-min) ) + min;
}

Vec3
Util_GetMouseRay(int screenWidth, int screenHeigth, Mat4 *viewMatrix, Mat4 *projectionMatrix,
                 int mouseX, int mouseY)
{
    Vec4 eyeCoords;
    Vec3 mouseRay;
    /* Normalized device coords NOTE: -y becouse for SDL y = 0 is the top of the screen */
    GLfloat normalX = ( 2.0f * (GLfloat)mouseX ) / (GLfloat) screenWidth - 1.0f;
    GLfloat normalY = 1.0f - (2.0f * (GLfloat)mouseY) / (GLfloat) screenHeigth;

    /* clipCoords include 4th component */
    Vec4 clipCoords = { normalX, normalY, -1.0f, 1.0f };

    /* Remove perpective */
    {
        Mat4 invertedProjection = mat4_inverse(projectionMatrix);
        eyeCoords = mat4_mul_vec4(&invertedProjection, &clipCoords);
        eyeCoords.z = -1.0f;
        eyeCoords.w = 0.0f;
    }

    /* Remove view matrix*/
    {
        Mat4 invertedViewMatrix = mat4_inverse(viewMatrix);
        Vec4 temp = mat4_mul_vec4(&invertedViewMatrix, &eyeCoords);

        mouseRay.x = temp.x;
        mouseRay.y = temp.y;
        mouseRay.z = temp.z;

        mouseRay = vec3_normalize(&mouseRay);
    }

    /* Return the ray in world coordinates */
    return mouseRay;
}