Files
GameLib/GameLib/Util.c

378 lines
6.6 KiB
C

// Copyright (C) 2011 Valeriano Alfonso Rodriguez (Kableado)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "Util.h"
////////////////////////////////////////////////
// vec2 //
//////////
// A 2D vector.
float vec2_norm(vec2 v){
float len;
len=vec2_len(v);
vec2_scale(v,v,1.0f/len);
return(len);
}
void vec2_orthogonalize4(vec2 v) {
if (fabs(v[0]) > fabs(v[1])) {
if (v[0] >= 0) {
v[0] = 1.0f;
v[1] = 0.0f;
} else {
v[0] = -1.0f;
v[1] = 0.0f;
}
} else {
if (v[1] >= 0) {
v[1] = 1.0f;
v[0] = 0.0f;
} else {
v[1] = -1.0f;
v[0] = 0.0f;
}
}
}
void vec2_orthogonalize8(vec2 v) {
float diff = fabs(fabs(v[0]) - fabs(v[1]));
if (diff > 0.2f) {
if (fabs(v[0]) > fabs(v[1])) {
if (v[0] >= 0) {
v[0] = 1.0f;
v[1] = 0.0f;
} else {
v[0] = -1.0f;
v[1] = 0.0f;
}
} else {
if (v[1] >= 0) {
v[1] = 1.0f;
v[0] = 0.0f;
} else {
v[1] = -1.0f;
v[0] = 0.0f;
}
}
} else {
if (v[0] > 0.0f) {
v[0] = 0.707f;
} else {
v[0] = -0.707f;
}
if (v[1] > 0.0f) {
v[1] = 0.707f;
} else {
v[1] = -0.707f;
}
}
}
/////////////////////////////
// SolveQuadratic
//
// Solves a Quadratic equation using a, b and c coeficients.
int SolveQuadratic(float a,float b,float c,float *Rmin,float *Rmax){
float root;
float divisor;
float b2;
b2=b*b;
root=b2-4.0*a*c;
if(root<0){
// Complex
return(0);
}
divisor=(2.0*a);
if(fabs(divisor)==0.0f){
// +inf -inf
return(0);
}
root=sqrtf(root);
Rmin[0]=(float)((-b-root)/divisor);
Rmax[0]=(float)((-b+root)/divisor);
return(1);
}
/////////////////////////////
// Intersec_RayUnitCircle
//
// Intersection between a ray and a Unit Circle.
int Intersec_RayUnitCircle(vec2 orig,vec2 vel,vec2 center,float *t){
float a,b,c;
float Rmin,Rmax;
vec2 distv;
float qlvel;
float qdistv;
// Check if the collision is even posible
qlvel=vec2_dot(vel,vel);
if(fabs(qlvel)<=0.0f)
return(0);
vec2_minus(distv,orig,center);
qdistv=vec2_dot(distv,distv);
// Solve as a unit circle
a=qlvel;
b=2.0f*vec2_dot(distv,vel);
c=qdistv-1.0f;
if(SolveQuadratic(a,b,c,&Rmin,&Rmax)){
if(Rmin>=-0.0f && Rmin<Rmax && Rmin<=1.0f){
*t=Rmin;
return(1);
}
if(Rmax>=-0.0f && Rmin>Rmax && Rmax<=1.0f){
*t=Rmax;
return(1);
}
}
return(0);
}
/////////////////////////////
// Colision_CircleCircle
//
// Colision point of a circle against another circle.
int Colision_CircleCircle(
vec2 cir1,float rad1,vec2 vel,
vec2 cir2,float rad2,
float *t,vec2 n)
{
vec2 vel_a,orig_a,cen_a,temp;
float rads,invrads;
float maxx,minx;
float maxy,miny;
// Check if the collision is even posible
rads=rad1+rad2;
minx=cir1[0]-rads;
maxx=cir1[0]+rads;
if(vel[0]>0){
maxx+=vel[0];
}else{
minx+=vel[0];
}
if(cir2[0]<minx || cir2[0]>maxx)
return(0);
miny=cir1[1]-rads;
maxy=cir1[1]+rads;
if(vel[1]>0){
maxy+=vel[1];
}else{
miny+=vel[1];
}
if(cir2[1]<miny || cir2[1]>maxy)
return(0);
// Convert to a unit circle vs ray
invrads=1.0f/rads;
vec2_scale(vel_a,vel,invrads);
vec2_scale(orig_a,cir1,invrads);
vec2_scale(cen_a,cir2,invrads);
if(Intersec_RayUnitCircle(orig_a,vel_a,cen_a,t)){
// Calculate n
vec2_scaleadd(temp,cir1,vel,*t);
vec2_minus(n,temp,cir2);
vec2_scale(n,n,invrads);
return(1);
}
return(0);
}
/////////////////////////////
// Intersect_RayEdge
//
// Intersection between a ray and a edge.
int Intersect_RayEdge(
vec2 pos,vec2 vel,
vec2 norm,vec2 edgePos,float len,
float *t)
{
vec2 pos2,intersection,perp,edgePos2;
float delta,d1,d2,hLen;
vec2_plus(pos2,pos,vel);
hLen=len/2;
// Check intersection against the line
delta=vec2_dot(norm,edgePos);
d1=vec2_dot(pos ,norm)-delta;
d2=vec2_dot(pos2,norm)-delta;
if(d1>=-0.0001f && d2<=0.0001f){
// Intersection with line, Calculate intersection point
*t=d1/(d1-d2);
vec2_scaleadd(intersection,pos,vel,*t);
// Perpendicular
vec2_perp(perp,norm);
// Check sides
vec2_scaleadd(edgePos2,edgePos,perp,-hLen);
delta=-vec2_dot(perp,edgePos2);
d1=(-vec2_dot(perp,intersection))-delta;
vec2_scaleadd(edgePos2,edgePos,perp,hLen);
delta=vec2_dot(perp,edgePos2);
d2=vec2_dot(perp,intersection)-delta;
if(d1<=0.0f && d2<=0.0f){
// Intersection inside Edge.
return(1);
}
}
return(0);
}
/////////////////////////////
// absmod
//
int absmod(int v,int d){
if(v<0){
v+=d*(((v/d)*(-1))+1);
return(v);
}else{
return(v%d);
}
}
float fabsmod(float v,int d){
if(v<0){
v+=d*((((int)(v/d))*(-1))+1);
return(v);
}else{
v-=d*(((int)(v/d))+1);
return(v);
}
}
/////////////////////////////
// IsBigEndian
//
int IsBigEndian(){
union{
unsigned int i;
char c[4];
} bint={0x01020304};
return bint.c[0]==1;
}
/////////////////////////////
// EndsWith
//
int EndsWith(char *str, char *suffix){
if (!str || !suffix)
return 0;
int lenStr = strlen(str);
int lenSuffix = strlen(suffix);
if (lenSuffix > lenStr)
return 0;
return strncmp(str+lenStr-lenSuffix, suffix, lenSuffix)==0;
}
/////////////////////////////
// Rand
//
// (LGC++) + cambio de semilla
#define __seed_n 30
#define __seed_a 30
#define __seed_b 5
#define __seed_c 10
#define __seed_d 15
//#define __LGC_a 1664525ul
//#define __LGC_c 1013904223ul
//#define __LGC_m 4294967296ul
#define __LGC_a 16807ul
#define __LGC_c 2
#define __LGC_m 2147483647ul
unsigned __seeds[30];
int __seed_i = -1;
unsigned __rand_count;
unsigned __rand_orig_seed;
void Rand_Seed(unsigned seed) {
int i;
__seeds[0] = seed;
for (i = 1; i < 30; i++) {
__seeds[i] = (__seeds[i - 1] * __LGC_a + __LGC_c) % __LGC_m;
//__seeds[i]=(__seeds[i-1]*__LGC_a+__LGC_c);
}
__seed_i = 29;
// Cambio de semilla
__rand_count = 0;
__rand_orig_seed = seed;
}
unsigned Rand_Get() {
unsigned val;
int a, b, c, d;
if (__seed_i == -1) {
Rand_Seed(1);
}
a = __seed_i - __seed_a;
if (a < 0)
a += __seed_n;
b = __seed_i - __seed_b;
if (b < 0)
b += __seed_n;
c = __seed_i - __seed_c;
if (c < 0)
c += __seed_n;
d = __seed_i - __seed_d;
if (d < 0)
d += __seed_n;
val = __seeds[a] ^ __seeds[b] ^ __seeds[c] ^ __seeds[d];
a = __seed_i - 1;
if (a < 0)
a = __seed_n - 1;
__seeds[__seed_i] = (__seeds[a] * __LGC_a + __LGC_c) % __LGC_m;
//__seeds[__seed_i]=(__seeds[a]*__LGC_a+__LGC_c);
__seed_i++;
if (__seed_i == __seed_n)
__seed_i = 0;
// Cambio de semilla
__rand_count++;
if (__rand_count > (1 << 15)) {
Rand_Seed(__rand_orig_seed + 1);
}
return (val);
}
/////////////////////////////
// Print
//
// Prints the formated text
int Print(char *fmt, ...) {
va_list ap;
int n;
// Print
va_start(ap, fmt);
n = vprintf(fmt, ap);
va_end(ap);
// Flush
fflush(stdout);
return(n);
}