[Add] Support for FreeBSD. Had to play around with the physics slightly
as FreeBSD didn't like the optimizations in Runge-Kuta forcing it to eventually become NaN.
This commit is contained in:
parent
2809e5323f
commit
a17b7792f3
15
bin/Makefile
15
bin/Makefile
@ -3,6 +3,7 @@ DEBUG := 1
|
||||
#DEBUG_PARANOID := 1
|
||||
|
||||
OS := LINUX
|
||||
#OS := FREEBSD
|
||||
#OS := WIN32
|
||||
#OS := MACOS
|
||||
export OS
|
||||
@ -36,10 +37,17 @@ CFLAGS += -DDATA_DEF=$(DATA_DEF)
|
||||
endif
|
||||
|
||||
# OS Stuff.
|
||||
|
||||
# Linux Stuff.
|
||||
ifeq ($(OS),LINUX)
|
||||
CFLAGS += -D_POSIX_SOURCE
|
||||
endif
|
||||
|
||||
# FreeBSD stuff.
|
||||
ifeq ($(OS),FREEBSD)
|
||||
CFLAGS += -D_POSIX_SOURCE -D__BSD_VISIBLE
|
||||
endif
|
||||
|
||||
# Debug stuff.
|
||||
ifdef DEBUG
|
||||
CFLAGS += -W -Wall -Wextra -Wunused -Wshadow -Wpointer-arith -Wmissing-prototypes \
|
||||
@ -51,10 +59,17 @@ CFLAGS += -DDEBUG_PARANOID
|
||||
endif
|
||||
|
||||
# Handle OS Debug stuff here.
|
||||
|
||||
# Linux Stuff.
|
||||
ifeq ($(OS), LINUX)
|
||||
LDFLAGS += -rdynamic
|
||||
endif # Linux.
|
||||
|
||||
# FreeBSD stuff.
|
||||
ifeq ($(OS), FREEBSD)
|
||||
LDFLAGS += -rdynamic
|
||||
endif
|
||||
|
||||
else # DEBUG
|
||||
CFLAGS += -O2 -funroll-loops -pipe -std=c99
|
||||
endif
|
||||
|
@ -729,12 +729,10 @@ static const char* debug_sigCodeToStr(int sig, int sig_code) {
|
||||
case SEGV_ACCERR: return "SIGEGV (invalid permissions for mapped object)";
|
||||
default: return "SIGSEGV";
|
||||
}
|
||||
else if(sig == SIGTRAP)
|
||||
else if(sig == SIGABRT)
|
||||
switch(sig_code) {
|
||||
case SI_USER: return "SIGTRAP (raised by program)";
|
||||
case TRAP_BRKPT: return "SIGTRAP (process breakpoint)";
|
||||
case TRAP_TRACE: return "SIGTRAP (process trace trap)";
|
||||
default: return "SIGTRAP";
|
||||
case SI_USER: return "SIGABRT (raised by program)";
|
||||
default: return "SIGABRT";
|
||||
}
|
||||
/* No suitable code found. */
|
||||
return strsignal(sig);
|
||||
@ -786,9 +784,9 @@ static void debug_sigInit(void) {
|
||||
sigaction(SIGFPE, &sa, &so);
|
||||
if(so.sa_handler == SIG_IGN)
|
||||
DEBUG("Unable to set up SIGFPE signal handler.");
|
||||
sigaction(SIGTRAP, &sa, &so);
|
||||
sigaction(SIGABRT, &sa, &so);
|
||||
if(so.sa_handler == SIG_IGN)
|
||||
DEBUG("Unable to get set up SIGTRAP signal handler.");
|
||||
DEBUG("Unable to get set up SIGABRT signal handler.");
|
||||
#endif /* #if defined(LINUX) && !defined(NODEBUG) */
|
||||
}
|
||||
|
||||
|
10
src/lfile.c
10
src/lfile.c
@ -9,7 +9,7 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#ifdef LINUX
|
||||
#if defined(LINUX) || defined(FREEBSD)
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -33,7 +33,7 @@ char* lfile_basePath(void) {
|
||||
char* home;
|
||||
|
||||
if(lephisto_base[0] == '\0') {
|
||||
#ifdef LINUX
|
||||
#if defined(LINUX) || defined(FREEBSD)
|
||||
home = getenv("HOME");
|
||||
snprintf(lephisto_base, PATH_MAX, "%s/.lephisto/", home);
|
||||
#else
|
||||
@ -71,7 +71,7 @@ int lfile_dirMakeExist(const char* path, ...) {
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#ifdef LINUX
|
||||
#if defined(LINUX) || defined(FREEBSD)
|
||||
struct stat buf;
|
||||
|
||||
stat(file, &buf);
|
||||
@ -105,7 +105,7 @@ int lfile_fileExists(const char* path, ...) {
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#ifdef LINUX
|
||||
#if defined(LINUX) || defined(FREEBSD)
|
||||
struct stat buf;
|
||||
|
||||
if(stat(file, &buf)==0) /* Stat worked, file must exist. */
|
||||
@ -140,7 +140,7 @@ char** lfile_readDir(int* lfiles, const char* path, ...) {
|
||||
va_end(ap);
|
||||
}
|
||||
|
||||
#ifdef LINUX
|
||||
#if defined(LINUX) || defined(FREEBSD)
|
||||
int i, j, k, n;
|
||||
DIR* d;
|
||||
struct dirent *dir;
|
||||
|
@ -5,13 +5,13 @@
|
||||
#define LOG(str, args...)(fprintf(stdout, str"\n", ## args))
|
||||
#ifdef DEBUG_PARANOID /* Will cause WARN's to blow up. */
|
||||
#define WARN(str, args...)(fprintf(stderr, "Warning: [%s] "str"\n", __func__, ## args), \
|
||||
raise(SIGRAP))
|
||||
abort())
|
||||
#else
|
||||
#define WARN(str, args...)(fprintf(stderr, "Warning: [%s] "str"\n", __func__, ## args))
|
||||
#endif
|
||||
|
||||
#define ERR(str, args...) (fprintf(stderr, "ERROR %s:%d: [%s] "str"\n", \
|
||||
__FILE__, __LINE__, __func__, ## args), raise(SIGTRAP))
|
||||
__FILE__, __LINE__, __func__, ## args), abort())
|
||||
|
||||
#ifdef DEBUG
|
||||
# undef DEBUG
|
||||
|
121
src/physics.c
121
src/physics.c
@ -96,37 +96,46 @@ double vect_dot(Vec2* a, Vec2* b) {
|
||||
return a->x * b->x + a->y * b->y;
|
||||
}
|
||||
|
||||
/* ================ */
|
||||
/* SOLID! */
|
||||
/* ================ */
|
||||
/* ================
|
||||
* SOLID!
|
||||
* ================
|
||||
*/
|
||||
|
||||
/* ==Update method.======================================== */
|
||||
/* d^2 x(t) / d t^2 = a, a = constant (acceleration) */
|
||||
/* x'(0) = v, x(0) = p */
|
||||
/* */
|
||||
/* d x(t) / d t = a*t + v, v = constant (initial velocity) */
|
||||
/* x(t) = a/2*t + v*t + p, p = constant (initial position) */
|
||||
/* */
|
||||
/* Since dt isn't actually differential this gives us an */
|
||||
/* error, so watch out with big values for dt. */
|
||||
/* ======================================================== */
|
||||
#if 0 /* Simply commenting this out to avoid silly warnings. */
|
||||
/* ==Update method.========================================
|
||||
* @fn static void simple_update(Solid* obj, const double dt)
|
||||
*
|
||||
* @brief Update the solids position using a euler integration.
|
||||
*
|
||||
* Simple method.
|
||||
*
|
||||
* d^2 x(t) / d t^2 = a, a = constant (acceleration)
|
||||
* x'(0) = v, x(0) = p
|
||||
*
|
||||
* d x(t) / d t = a*t + v, v = constant (initial velocity)
|
||||
* x(t) = a/2*t + v*t + p, p = constant (initial position)
|
||||
*
|
||||
* Since dt isn't actually differential this gives us an
|
||||
* error, so watch out with big values for dt.
|
||||
* ========================================================
|
||||
*/
|
||||
#if defined(FREEBSD)
|
||||
static void simple_update(Solid* obj, const double dt) {
|
||||
double px, py, vx, vy, ax, ay;
|
||||
|
||||
/* Make sure angle doesn't flip. */
|
||||
obj->dir += M_PI/360.*obj->dir_vel*dt;
|
||||
obj->dir += M_PI/180.*obj->dir_vel*dt;
|
||||
if(obj->dir > 2*M_PI) obj->dir -= 2*M_PI;
|
||||
if(obj->dir < 0.) obj->dir += 2*M_PI;
|
||||
|
||||
double px, py, vx, vy;
|
||||
px = obj->pos->x;
|
||||
py = obj->pos->y;
|
||||
vx = obj->vel->x;
|
||||
vy = obj->vel->y;
|
||||
/* Initial positions. */
|
||||
px = obj->pos.x;
|
||||
py = obj->pos.y;
|
||||
vx = obj->vel.x;
|
||||
vy = obj->vel.y;
|
||||
|
||||
if(obj->force.mod) { /* Force applied on an object. */
|
||||
double ax, ay;
|
||||
ax = obj->force->x/obj->mass;
|
||||
ay = obj->force->y/obj->mass;
|
||||
ax = obj->force.x /obj->mass;
|
||||
ay = obj->force.y /obj->mass;
|
||||
|
||||
vx += ax*dt;
|
||||
vy += ay*dt;
|
||||
@ -140,26 +149,39 @@ static void simple_update(Solid* obj, const double dt) {
|
||||
px += vx*dt;
|
||||
py += vy*dt;
|
||||
}
|
||||
obj->pos.mod = MOD(px, py);
|
||||
obj->pos.angle = ANGLE(px, py);
|
||||
|
||||
/* Update position and velocity. */
|
||||
vect_cset(&obj->vel, vx, vy);
|
||||
vect_cset(&obj->pos, px, py);
|
||||
}
|
||||
#endif
|
||||
#endif /* defined(FREEBSD) */
|
||||
|
||||
/* ==Runge-Kutta 4th method.=============================== */
|
||||
/* d^2 x(t) / d t^2 = a, a = constant(acceleration) */
|
||||
/* x'(0) = v, x(0) = p */
|
||||
/* x'' = f(t, x, x') = (x', a) */
|
||||
/* */
|
||||
/* x_ {n+1} = x_n + h/6 (k1 + 2*k2 + 3*k3 + k4) */
|
||||
/* h = (b-a)/2 */
|
||||
/* k1 = f(t_n, X_n), X_n = (x_n, x'_n) */
|
||||
/* k2 = f(t_n + h/2, X_n + h/2*k1) */
|
||||
/* k3 = f(t_n + h/2, X_n + h/2*k2) */
|
||||
/* k4 = f(t_n + h, X_n + h*k3) */
|
||||
/* */
|
||||
/* x_{n+1} = x_n + h/6x'_n + 3*h*a, 4*a) */
|
||||
/* ======================================================== */
|
||||
/* ==Runge-Kutta 4th method.===============================
|
||||
*
|
||||
* @brief Runge-Kutta method of updating a solid based on it's
|
||||
* acceleration.
|
||||
*
|
||||
* d^2 x(t) / d t^2 = a, a = constant(acceleration)
|
||||
* x'(0) = v, x(0) = p
|
||||
* x'' = f(t, x, x') = (x', a)
|
||||
*
|
||||
* x_ {n+1} = x_n + h/6 (k1 + 2*k2 + 3*k3 + k4)
|
||||
* h = (b-a)/2
|
||||
* k1 = f(t_n, X_n), X_n = (x_n, x'_n)
|
||||
* k2 = f(t_n + h/2, X_n + h/2*k1)
|
||||
* k3 = f(t_n + h/2, X_n + h/2*k2)
|
||||
* k4 = f(t_n + h, X_n + h*k3)
|
||||
*
|
||||
* x_{n+1} = x_n + h/6x'_n + 3*h*a, 4*a)
|
||||
*
|
||||
* Main advantage comes thanks to the fact that Lephisto is on
|
||||
* a 2D plane. Therefore RK chops it up in chunks and actually
|
||||
* creates a tiny curve instead of aproximating the curve for
|
||||
* a tiny staight line.
|
||||
* ========================================================
|
||||
*/
|
||||
|
||||
#if !defined(FREEBSD)
|
||||
#define RK4_MIN_H 0.01 /* Minimal pass we want. */
|
||||
static void rk4_update(Solid* obj, const double dt) {
|
||||
int i, N; /* For iteration and pass calculation. */
|
||||
@ -170,9 +192,11 @@ static void rk4_update(Solid* obj, const double dt) {
|
||||
if(obj->dir >= 2.*M_PI) obj->dir -= 2*M_PI;
|
||||
else if(obj->dir < 0.) obj->dir += 2*M_PI;
|
||||
|
||||
/* Initial RK parameters. */
|
||||
N = (dt > RK4_MIN_H) ? (int)(dt/RK4_MIN_H) : 1;
|
||||
h = dt / (double)N; /* Step. */
|
||||
|
||||
/* Initial positions and velocity. */
|
||||
px = obj->pos.x;
|
||||
py = obj->pos.y;
|
||||
vx = obj->vel.x;
|
||||
@ -212,26 +236,41 @@ static void rk4_update(Solid* obj, const double dt) {
|
||||
}
|
||||
vect_cset(&obj->pos, px, py);
|
||||
}
|
||||
#endif /* !defined(FREEBSD) */
|
||||
|
||||
/* Initialize a new solid. */
|
||||
void solid_init(Solid* dest, const double mass, const double dir,
|
||||
const Vec2* pos, const Vec2* vel) {
|
||||
dest->mass = mass;
|
||||
|
||||
/* Set direction velocity. */
|
||||
dest->dir_vel = 0.;
|
||||
|
||||
vect_cset(&dest->force, 0., 0.);
|
||||
/* Set force. */
|
||||
vectnull(&dest->force);
|
||||
|
||||
/* Set direction. */
|
||||
dest->dir = dir;
|
||||
if((dest->dir > 2.*M_PI) || (dest->dir < 0.))
|
||||
dest->dir = fmod(dest->dir, 2*M_PI);
|
||||
|
||||
/* Set velocity. */
|
||||
if(vel == NULL) vectnull(&dest->vel);
|
||||
else vectcpy(&dest->vel, vel);
|
||||
|
||||
/* Set position. */
|
||||
if(pos == NULL) vectnull(&dest->pos);
|
||||
else vectcpy(&dest->pos, pos);
|
||||
|
||||
/*
|
||||
* FreeBSD seems to have a bug with optimizations in rk4_update causing it to
|
||||
* eventually become NaN.
|
||||
*/
|
||||
#if defined(FREEBSD)
|
||||
dest->update = simple_update;
|
||||
#else
|
||||
dest->update = rk4_update;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Create a new solid. */
|
||||
|
Loading…
Reference in New Issue
Block a user