564 lines
14 KiB
C
564 lines
14 KiB
C
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <assert.h>
|
|
#include <math.h>
|
|
#include <stdbool.h>
|
|
#include <unistd.h>
|
|
#include <termios.h>
|
|
#include <limits.h>
|
|
#include <time.h>
|
|
|
|
#include "hash.h"
|
|
#include "base.h"
|
|
|
|
int ln_baseN(int n, int b) {
|
|
int r = 0;
|
|
while(n != 0) {
|
|
n = n / b;
|
|
r++;
|
|
}
|
|
return r;
|
|
}
|
|
|
|
int pw(int x, int n) {
|
|
if (n<0)
|
|
return 0;
|
|
if (n==0)
|
|
return 1;
|
|
if (n%2==0)
|
|
return pw(x*x, n/2);
|
|
return x*pw(x*x, n/2);
|
|
}
|
|
|
|
double pwf(double x, int n) {
|
|
if (n<0)
|
|
return 0.0;
|
|
if (n==0)
|
|
return 1.0;
|
|
if (n%2==0)
|
|
return pwf(x*x, n/2);
|
|
return x*pwf(x*x, n/2);
|
|
}
|
|
|
|
int abs(int n) {
|
|
if(n > 0) {
|
|
return n;
|
|
} else {
|
|
return (-n);
|
|
}
|
|
}
|
|
|
|
int min(int a, int b) {
|
|
if(a > b) {
|
|
return b;
|
|
};
|
|
return a;
|
|
}
|
|
|
|
int max(int a, int b) {
|
|
if(a < b) {
|
|
return b;
|
|
};
|
|
return a;
|
|
}
|
|
|
|
float minf(float a, float b) {
|
|
if(a > b) {
|
|
return b;
|
|
};
|
|
return a;
|
|
}
|
|
|
|
float maxf(float a, float b) {
|
|
if(a < b) {
|
|
return b;
|
|
};
|
|
return a;
|
|
}
|
|
|
|
double mind(double a, double b) {
|
|
if(a > b) {
|
|
return b;
|
|
};
|
|
return a;
|
|
}
|
|
|
|
double maxd(double a, double b) {
|
|
if(a < b) {
|
|
return b;
|
|
};
|
|
return a;
|
|
}
|
|
|
|
double absf(double n) {
|
|
if(n > 0.0f) {
|
|
return n;
|
|
} else {
|
|
return (-n);
|
|
}
|
|
}
|
|
|
|
bool xor(bool a, bool b) {
|
|
return ((a && !b) || (!a && b));
|
|
}
|
|
|
|
// n >= 0
|
|
int reverse(int n) {
|
|
int res = 0;
|
|
int nexp = pw(10, ln_baseN(n, 10));
|
|
int cexp = nexp/10;
|
|
int left = n;
|
|
while(cexp > 0) {
|
|
res += (left%10)*cexp;
|
|
cexp /= 10;
|
|
left /= 10;
|
|
}
|
|
//printf("%d -> %d\n", n, res);
|
|
return res;
|
|
}
|
|
|
|
int convex_seg(int x1, int x2, double theta) {
|
|
return (int)(((1.0f - theta) * x1 + theta * x2));
|
|
}
|
|
|
|
double convex_pt(double a, double b, double theta) {
|
|
return (a+(b-a)*theta);
|
|
}
|
|
|
|
double convex_tri(double a, double tha, double b, double thb, double c, double thc) {
|
|
return (a*tha + b*thb + c*thc);
|
|
}
|
|
|
|
pt_2d convex_pt2d(pt_2d A, pt_2d B, double theta) {
|
|
pt_2d res;
|
|
res.x = A.x+(B.x-A.x)*theta;
|
|
res.y = A.y+(B.y-A.y)*theta;
|
|
res.z = A.z+(B.z-A.z)*theta;
|
|
return res;
|
|
}
|
|
|
|
pt_2d convex_pt2d_tri(pt_2d A, double tha, pt_2d B, double thb, pt_2d C, double thc) {
|
|
pt_2d res;
|
|
res.x = A.x*tha+B.x*thb+C.x*thc;
|
|
res.y = A.y*tha+B.y*thb+C.y*thc;
|
|
res.z = A.z*tha+B.z*thb+C.z*thc;
|
|
return res;
|
|
}
|
|
|
|
bool is_an_integer(char c) {
|
|
return ((int)c >= 48 && (int)c <= 57);
|
|
}
|
|
|
|
pt_2d vect_diff(pt_2d p1, pt_2d p2) {
|
|
pt_2d res;
|
|
res.x = p2.x - p1.x;
|
|
res.y = p2.y - p1.y;
|
|
res.z = p2.z - p1.z;
|
|
return res;
|
|
}
|
|
|
|
double dot2D(pt_2d p1, pt_2d p2) {
|
|
return p1.x * p2.x + p1.y * p2.y;
|
|
}
|
|
|
|
double dot3D(pt_2d p1, pt_2d p2) {
|
|
return p1.x * p2.x + p1.y * p2.y + p1.z * p2.z;
|
|
}
|
|
|
|
double to_double(int n) {
|
|
return (double)n;
|
|
}
|
|
|
|
int to_int(double n) {
|
|
return (int)n;
|
|
}
|
|
|
|
int line_count(char* filename) {
|
|
FILE* ptr = fopen(filename, "r");
|
|
char c = 'd';
|
|
|
|
int n = 0;
|
|
while(c != EOF) {
|
|
if(c == '\n') {
|
|
n += 1;
|
|
};
|
|
c = fgetc(ptr);
|
|
};
|
|
fclose(ptr);
|
|
return (n+1);
|
|
}
|
|
|
|
int str_to_int(char* s) {
|
|
int res = 0;
|
|
int i = 0;
|
|
while(s[i] != '\0' && is_an_integer(s[i])) {
|
|
res *= 10;
|
|
res += (int)s[i] - 48;
|
|
i++;
|
|
};
|
|
return res;
|
|
}
|
|
|
|
bool str_equal(char* s1, char* s2) {
|
|
if(s1[0] == '\0' || s2[0] == '\0') {
|
|
return (s1[0] == '\0' && s2[0] == '\0');
|
|
}
|
|
return (s1[0] == s2[0] && str_equal(&s1[1], &s2[1]));
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
|
|
cube_0* create_cube_0(double x, double y, double z, double w, double h, double d, double hz_a, double vt_a, int r, int g, int b) {
|
|
cube_0* cb = malloc(sizeof(cube_0));
|
|
cb->red = r;
|
|
cb->green = g;
|
|
cb->blue = b;
|
|
cb->x = x;
|
|
cb->y = y;
|
|
cb->z = z;
|
|
cb->w = w;
|
|
cb->h = h;
|
|
cb->d = d;
|
|
cb->hz_angle = hz_a;
|
|
cb->vt_angle = vt_a;
|
|
return cb;
|
|
}
|
|
|
|
void fill_cube_0(cube_0* cb, double x, double y, double z, double w, double h, double d, double hz_a, double vt_a, int r, int g, int b) {
|
|
cb->red = r;
|
|
cb->green = g;
|
|
cb->blue = b;
|
|
cb->x = x;
|
|
cb->y = y;
|
|
cb->z = z;
|
|
cb->w = w;
|
|
cb->h = h;
|
|
cb->d = d;
|
|
cb->hz_angle = hz_a;
|
|
cb->vt_angle = vt_a;
|
|
}
|
|
|
|
cube create_cube(double x, double y, double z, double w, double h, double d, double hz_a, double vt_a, int r, int g, int b) {
|
|
cube cb = malloc(sizeof(cube_0));
|
|
cb = create_cube_0(x, y, z, w, h, d, hz_a, vt_a, r, g, b);
|
|
return cb;
|
|
}
|
|
|
|
void free_cube(cube c) {
|
|
free(c);
|
|
}
|
|
|
|
teleporter* create_teleporter(
|
|
double x, double y, double z, double w, double h, double d, double hz_a, double vt_a, int r, int g, int b,
|
|
int chx_dest, int chy_dest, double x_dest, double y_dest, double z_dest
|
|
) {
|
|
teleporter* tp = malloc(sizeof(teleporter));
|
|
tp->dest_chx = chx_dest;
|
|
tp->dest_chy = chy_dest;
|
|
tp->dest_x = x_dest;
|
|
tp->dest_y = y_dest;
|
|
tp->dest_z = z_dest;
|
|
tp->hitbox = create_cube_0(x, y, z, w, h, d, hz_a, vt_a, r, g, b);
|
|
return tp;
|
|
}
|
|
|
|
void copy_cube(cube_0* src, cube_0* dest) {
|
|
dest->red = src->red;
|
|
dest->green = src->green;
|
|
dest->blue = src->blue;
|
|
dest->hz_angle = src->hz_angle;
|
|
dest->vt_angle = src->vt_angle;
|
|
dest->x = src->x;
|
|
dest->y = src->y;
|
|
dest->z = src->z;
|
|
dest->w = src->w;
|
|
dest->h = src->h;
|
|
dest->d = src->d;
|
|
}
|
|
|
|
void copy_entity(entity* src, entity* dest) {
|
|
dest->damage = src->damage;
|
|
dest->entity_type = src->entity_type;
|
|
*(dest->hitpoints) = *(src->hitpoints);
|
|
|
|
dest->metad1 = src->metad1;
|
|
dest->metad2 = src->metad2;
|
|
dest->metad3 = src->metad3;
|
|
dest->metad4 = src->metad4;
|
|
dest->metad5 = src->metad5;
|
|
dest->metad6 = src->metad6;
|
|
dest->metad7 = src->metad7;
|
|
dest->metad8 = src->metad8;
|
|
dest->metad9 = src->metad9;
|
|
dest->metai1 = src->metai1;
|
|
dest->metai2 = src->metai2;
|
|
dest->metai3 = src->metai3;
|
|
dest->metai4 = src->metai4;
|
|
dest->metai5 = src->metai5;
|
|
dest->metai6 = src->metai6;
|
|
dest->metach1 = src->metach1;
|
|
dest->metach2 = src->metach2;
|
|
|
|
dest->updatePos = src->updatePos;
|
|
dest->onHit = src->onHit;
|
|
dest->onDeath = src->onDeath;
|
|
|
|
dest->tex = src->tex;
|
|
dest->tex2 = src->tex2;
|
|
|
|
copy_cube(src->pos, dest->pos);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
|
|
double distance_pt_pt_3d(double x0, double y0, double z0, double x1, double y1, double z1) {
|
|
return sqrt((x1 - x0)*(x1 - x0)+(y1 - y0)*(y1 - y0)+(z1 - z0)*(z1 - z0));
|
|
}
|
|
|
|
double distance_pt_pt_2d_sq(double x0, double y0, double x1, double y1) {
|
|
return (x1 - x0)*(x1 - x0)+(y1 - y0)*(y1 - y0);
|
|
}
|
|
|
|
double distance_pt_pt_3d_sq(double x0, double y0, double z0, double x1, double y1, double z1) {
|
|
return (x1 - x0)*(x1 - x0)+(y1 - y0)*(y1 - y0)+(z1 - z0)*(z1 - z0);
|
|
}
|
|
|
|
double distance_pt_seg_3d(double x, double y, double z, double sx, double sy, double sz, double ex, double ey, double ez) {
|
|
double theta = -(
|
|
((ex - sx) * (sx - x) + (ey - sy) * (sy - y) + (ez - sz) * (sz - z)) /
|
|
((ex - sx) * (ex - sx) + (ey - sy) * (ey - sy) + (ez - sz) * (ez - sz))
|
|
);
|
|
if(theta >= 0.0 && theta <= 1.0) {
|
|
return (distance_pt_pt_3d(x, y, z, convex_pt(sx, ex, theta), convex_pt(sy, ey, theta), convex_pt(sz, ez, theta)));
|
|
} else if (theta < 0.0) {
|
|
return (distance_pt_pt_3d(x, y, z, sx, sy, sz));
|
|
} else {
|
|
return (distance_pt_pt_3d(x, y, z, ex, ey, ez));
|
|
}
|
|
}
|
|
|
|
double distance_pt_cube_axis(double coord, double begin, double end) {
|
|
if(coord < begin) {
|
|
return (begin);
|
|
} else if(coord > end) {
|
|
return (end);
|
|
} else {
|
|
return (coord);
|
|
}
|
|
}
|
|
|
|
double distance_pt_cube_aligned_3d(double x0, double y0, double z0, double cx, double cy, double cz, double cw, double ch, double cd) {
|
|
double clx = distance_pt_cube_axis(x0, cx, cx+cw);
|
|
double cly = distance_pt_cube_axis(y0, cy, cy+ch);
|
|
double clz = distance_pt_cube_axis(z0, cz, cz+cd);
|
|
return sqrt((x0-clx)*(x0-clx) + (y0-cly)*(y0-cly) + (z0-clz)*(z0-clz));
|
|
}
|
|
|
|
double distance_pt_cube_aligned_3d_infinite(double x0, double y0, double z0, double cx, double cy, double cz, double cw, double ch, double cd) {
|
|
double clx = distance_pt_cube_axis(x0, cx, cx+cw);
|
|
double cly = distance_pt_cube_axis(y0, cy, cy+ch);
|
|
double clz = distance_pt_cube_axis(z0, cz, cz+cd);
|
|
return maxd(maxd(absf(clx-x0), absf(cly-y0)), absf(clz-z0));
|
|
}
|
|
|
|
double distance_pt_cube_0_3d(double x0, double y0, double z0, cube_0* c) {
|
|
// places the origin at the center of the cube
|
|
double x = x0 - (c->x + c->w/2.0);
|
|
double y = y0 - (c->y + c->h/2.0);
|
|
double z = z0 - (c->z + c->d/2.0);
|
|
|
|
// rotate the point : y then x
|
|
double xry = x*cos(c->hz_angle) + z*sin(c->hz_angle);
|
|
double yry = y;
|
|
double zry = z*cos(c->hz_angle) - x*sin(c->hz_angle);
|
|
|
|
double xrx = xry;
|
|
double yrx = yry*cos(c->vt_angle) - zry*sin(c->vt_angle);
|
|
double zrx = zry*cos(c->vt_angle) + yry*sin(c->vt_angle);
|
|
|
|
// now the cube and pt are aligned, and (0, 0, 0) is at the cube's (bary)center
|
|
return distance_pt_cube_aligned_3d(xrx, yrx, zrx, -c->w/2.0, -c->h/2.0, -c->d/2.0, c->w, c->h, c->d);
|
|
}
|
|
|
|
double distance_pt_cube_0_3d_infinite(double x0, double y0, double z0, cube_0* c) {
|
|
// places the origin at the center of the cube
|
|
double x = x0 - (c->x + c->w/2.0);
|
|
double y = y0 - (c->y + c->h/2.0);
|
|
double z = z0 - (c->z + c->d/2.0);
|
|
|
|
// rotate the point : y then x
|
|
double xry = x*cos(c->hz_angle) + z*sin(c->hz_angle);
|
|
double yry = y;
|
|
double zry = z*cos(c->hz_angle) - x*sin(c->hz_angle);
|
|
|
|
double xrx = xry;
|
|
double yrx = yry*cos(c->vt_angle) - zry*sin(c->vt_angle);
|
|
double zrx = zry*cos(c->vt_angle) + yry*sin(c->vt_angle);
|
|
|
|
// now the cube and pt are aligned, and (0, 0, 0) is at the cube's (bary)center
|
|
return distance_pt_cube_aligned_3d_infinite(xrx, yrx, zrx, -c->w/2.0, -c->h/2.0, -c->d/2.0, c->w, c->h, c->d);
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
|
|
void project_to_camera(double x0, double y0, double z0, double* rx, double* ry, double* rz) {
|
|
// align pt to (0, 0, 0)
|
|
double x = x0 - camx;
|
|
double y = y0 - camy;
|
|
double z = z0 - camz;
|
|
|
|
// rotate (y)
|
|
double xry = x*cos(rot_hz) - z*sin(rot_hz);
|
|
double yry = y;
|
|
double zry = z*cos(rot_hz) + x*sin(rot_hz);
|
|
|
|
// rotate (x)
|
|
if(rx != NULL) {*rx = xry;}
|
|
if(ry != NULL) {*ry = yry*cos(rot_vt) + zry*sin(rot_vt);}
|
|
if(rz != NULL) {*rz = zry*cos(rot_vt) - yry*sin(rot_vt);}
|
|
}
|
|
|
|
void project_to_cube(double x0, double y0, double z0, double* rx, double* ry, double* rz, cube_0* c) {
|
|
// align pt to (0, 0, 0)
|
|
double x = x0 - (c->x + c->w/2.0);
|
|
double y = y0 - (c->y + c->h/2.0);
|
|
double z = z0 - (c->z + c->d/2.0);
|
|
|
|
// rotate (y)
|
|
double xry = x*cos(c->hz_angle) - z*sin(c->hz_angle);
|
|
double yry = y;
|
|
double zry = z*cos(c->hz_angle) + x*sin(c->hz_angle);
|
|
|
|
// rotate (x)
|
|
if(rx != NULL) {*rx = c->x + c->w/2.0 + xry;}
|
|
if(ry != NULL) {*ry = c->y + c->h/2.0 + yry*cos(c->vt_angle) + zry*sin(c->vt_angle);}
|
|
if(rz != NULL) {*rz = c->z + c->d/2.0 + zry*cos(c->vt_angle) - yry*sin(c->vt_angle);}
|
|
}
|
|
|
|
pt_2d rotate_to_x_axis(double x, double y, double z, double y0, double z0, int angle) {
|
|
pt_2d res;
|
|
|
|
res.x = x;
|
|
res.y = y0+(y-y0)*cos(angle) + (z-z0)*sin(angle);
|
|
res.z = z0+(z-z0)*cos(angle) - (y-y0)*sin(angle);
|
|
|
|
//printf("> %lf %lf %lf <\n", res.x, res.y, res.z);
|
|
return res;
|
|
}
|
|
|
|
pt_2d rotate_to_y_axis(double x, double y, double z, double x0, double z0, int angle) {
|
|
pt_2d res;
|
|
|
|
res.x = x0+(x-x0)*cos(angle) - (z-z0)*sin(angle);
|
|
res.y = y;
|
|
res.z = z0+(z-z0)*cos(angle) + (x-x0)*sin(angle);
|
|
|
|
return res;
|
|
}
|
|
|
|
// ------------------------------------------------------------------------------------------------ //
|
|
|
|
void remove_entity(entity** arr, int* memlen, int* len, int index) {
|
|
if(*len > 0) {
|
|
entity* temp = arr[index];
|
|
arr[index] = arr[*len -1];
|
|
arr[*len -1] = temp;
|
|
*len -= 1;
|
|
}
|
|
}
|
|
|
|
entity* remove_entity_return(entity** arr, int* memlen, int* len, int index) {
|
|
if(*len > 0) {
|
|
entity* temp = arr[index];
|
|
arr[index] = arr[*len -1];
|
|
arr[*len -1] = temp;
|
|
*len -= 1;
|
|
return temp;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
void add_entity(entity** arr, int* memlen, int* len, entity* ent) {
|
|
if(*memlen == *len) {
|
|
entity** newarr = malloc(sizeof(entity*)*2*(*memlen));
|
|
for(int k = 0; k < *len; k++) {
|
|
newarr[k] = arr[k];
|
|
}
|
|
for(int k = *len; k < 2*(*memlen); k++) {
|
|
newarr[k] = malloc(sizeof(entity));
|
|
newarr[k]->pos = malloc(sizeof(cube_0));
|
|
newarr[k]->hitpoints = malloc(sizeof(int));
|
|
}
|
|
free(*arr);
|
|
arr = newarr;
|
|
*memlen *= 2;
|
|
}
|
|
copy_entity(ent, arr[*len]);
|
|
*len += 1;
|
|
}
|
|
|
|
int is_neg0 = 1;
|
|
int read_int(FILE* ptr) {
|
|
bool is_reading = false;
|
|
int buffer = 0;
|
|
int sign = 1;
|
|
char c = fgetc(ptr);
|
|
while(c != EOF) {
|
|
if(c == '-') {
|
|
sign = -1;
|
|
} else if((int)c >= 48 && (int)c <= 57) {
|
|
is_reading = true;
|
|
buffer = 10*buffer + (int)c - 48;
|
|
} else if(is_reading) {
|
|
if(sign == -1 && buffer == 0) {
|
|
is_neg0 = -1;
|
|
} else {
|
|
is_neg0 = 1;
|
|
}
|
|
return buffer*sign;
|
|
}
|
|
c = fgetc(ptr);
|
|
}
|
|
if(sign == -1 && buffer == 0) {
|
|
is_neg0 = -1;
|
|
} else {
|
|
is_neg0 = 1;
|
|
}
|
|
return buffer*sign;
|
|
}
|
|
|
|
char* read_string(FILE* ptr) {
|
|
char* res0 = malloc(sizeof(char)*52);
|
|
char c = fgetc(ptr);
|
|
int i = 0;
|
|
while(c != EOF && c == ' ') { // ignore initial spaces
|
|
c = fgetc(ptr);
|
|
}
|
|
while(c != EOF && c != ',') {
|
|
res0[i] = c;
|
|
i += 1;
|
|
c = fgetc(ptr);
|
|
}
|
|
res0[i] = '\0';
|
|
return res0;
|
|
}
|
|
|
|
double sign(double __x) {
|
|
if(__x >= 0.0) {
|
|
return 1.0;
|
|
}
|
|
return -1.0;
|
|
}
|
|
|
|
double read_float(FILE* ptr) {
|
|
int ent = read_int(ptr);
|
|
int sn0 = is_neg0;
|
|
int frac = read_int(ptr);
|
|
//printf("%d.%d; ", ent, frac);
|
|
if(ent != 0.0) {
|
|
return sn0*(ent/abs(ent))*(absf((double)ent) + ((double)frac)/(pow(10.0, (double)ln_baseN(frac, 10))));
|
|
} else {
|
|
//printf("%d, %d\n", ent, frac);
|
|
return sn0*((double)frac)/(pow(10.0, (double)ln_baseN(frac, 10)));
|
|
}
|
|
} |