void glopFrustum(GLContext *c,GLParam *p) { GLfloat *r; M4 m; GLfloat left=p[1].f; GLfloat right=p[2].f; GLfloat bottom=p[3].f; GLfloat top=p[4].f; GLfloat near=p[5].f; GLfloat farp=p[6].f; GLfloat x,y,A,B,C,D,tmp2=int2sll(2); x = slldiv(sllmul(tmp2,near), sllsub(right,left)); y = slldiv(sllmul(tmp2,near), sllsub(top,bottom)); A = slldiv(slladd(right,left), sllsub(right,left)); B = slldiv(slladd(top,bottom), sllsub(top,bottom)); C = slldiv(sllneg(slladd(farp,near)), sllsub(farp,near)); D = slldiv(sllneg(sllmul(sllmul(tmp2,farp),near)), sllsub(farp,near)); r=&m.m[0][0]; r[0]= x; r[1]=int2sll(0); r[2]=A; r[3]=int2sll(0); r[4]= int2sll(0); r[5]=y; r[6]=B; r[7]=int2sll(0); r[8]= int2sll(0); r[9]=int2sll(0); r[10]=C; r[11]=D; r[12]=int2sll(0); r[13]=int2sll(0); r[14]=int2sll(-1); r[15]=int2sll(0); gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode],&m); gl_matrix_update(c); }
// http://math.stackexchange.com/questions/1098487/atan2-faster-approximation // atan2(y,x) // a := min (|x|, |y|) / max (|x|, |y|) // s := a * a // r := ((-0.0464964749 * s + 0.15931422) * s - 0.327622764) * s * a + a // if |y| > |x| then r := 1.57079637 - r // if x < 0 then r := 3.14159274 - r // if y < 0 then r := -r sll sllatan2(sll y, sll x) { sll abs_x = sllabs(x); sll abs_y = sllabs(y); sll maxyx = MAX(abs_x, abs_y); sll minyx = MIN(abs_x, abs_y); sll a = slldiv(minyx, maxyx); sll s = sllmul(a, a); sll r_1 = sllmul(dbl2sll((-0.0464964749)), s); sll r_2 = slladd(r_1, dbl2sll(0.15931422)); sll r_3 = sllsub(sllmul(r_2, s), dbl2sll(0.327622764)); sll r = slladd(sllmul(sllmul(r_3, s), a), a); if(sllabs(y) > sllabs(x)) { r = sllsub(CONST_PI_2, r); } if(x < CONST_0) { r = sllsub(CONST_PI, r); } if(y < CONST_0) { r = sllneg(r); } return r; }
sll sllabs(sll x) { sll ret = x; if (x < CONST_0) { ret = sllneg(x); } return ret; }
void gl_M4_Rotate(M4 *a,GLfloat t,int u) { GLfloat s,c; int v,w; if ((v=u+1)>2) v=0; if ((w=v+1)>2) w=0; s=sllsin(t); c=sllcos(t); gl_M4_Id(a); a->m[v][v]=c; a->m[v][w]=sllneg(s); a->m[w][v]=s; a->m[w][w]=c; }
/* inverse of a 3x3 matrix */ void gl_M3_Inv(M3 *a,M3 *m) { GLfloat det; det = sllsub( slladd( slladd( sllsub( sllsub(sllmul(sllmul(m->m[0][0], m->m[1][1]), m->m[2][2]), sllmul(sllmul(m->m[0][0], m->m[1][2]), m->m[2][1])), sllmul(sllmul(m->m[1][0], m->m[0][1]), m->m[2][2])), sllmul(sllmul(m->m[1][0], m->m[0][2]), m->m[2][1])), sllmul(sllmul(m->m[2][0], m->m[0][1]), m->m[1][2])), sllmul(sllmul(m->m[2][0], m->m[0][2]), m->m[1][1])); a->m[0][0] = slldiv(sllsub(sllmul(m->m[1][1],m->m[2][2]), sllmul(m->m[1][2],m->m[2][1])), det); a->m[0][1] = sllneg(slldiv(sllsub(sllmul(m->m[0][1],m->m[2][2]), sllmul(m->m[0][2],m->m[2][1])), det)); a->m[0][2] = sllneg(slldiv(slladd(sllmul(sllneg(m->m[0][1]),m->m[1][2]), sllmul(m->m[0][2], m->m[1][1])), det)); a->m[1][0] = sllneg(slldiv(sllsub(sllmul(m->m[1][0],m->m[2][2]), sllmul(m->m[1][2],m->m[2][0])), det)); a->m[1][1] = slldiv(sllsub(sllmul(m->m[0][0],m->m[2][2]), sllmul(m->m[0][2],m->m[2][0])), det); a->m[1][2] = sllneg(slldiv(sllsub(sllmul(m->m[0][0],m->m[1][2]), sllmul(m->m[0][2],m->m[1][0])), det)); a->m[2][0] = slldiv(sllsub(sllmul(m->m[1][0],m->m[2][1]), sllmul(m->m[1][1],m->m[2][0])), det); a->m[2][1] = sllneg(slldiv(sllsub(sllmul(m->m[0][0],m->m[2][1]), sllmul(m->m[0][1],m->m[2][0])), det)); a->m[2][2] = slldiv(sllsub(sllmul(m->m[0][0],m->m[1][1]), sllmul(m->m[0][1],m->m[1][0])), det); }
void glopRotate(GLContext *c,GLParam *p) { #define SLL_M_PI dbl2sll(M_PI) M4 m; GLfloat u[3]; GLfloat angle; int dir_code; angle = slldiv(sllmul(p[1].f, SLL_M_PI), int2sll(180)); u[0]=p[2].f; u[1]=p[3].f; u[2]=p[4].f; /* simple case detection */ dir_code = ((sllvalue(u[0]) != sllvalue(int2sll(0)))<<2) | ((sllvalue(u[1]) != sllvalue(int2sll(0)))<<1) | (sllvalue(u[2]) != sllvalue(int2sll(0))); switch(dir_code) { case 0: gl_M4_Id(&m); break; case 4: if (sllvalue(u[0]) < sllvalue(int2sll(0))) angle=sllneg(angle); gl_M4_Rotate(&m,angle,0); break; case 2: if (sllvalue(u[1]) < sllvalue(int2sll(0))) angle=sllneg(angle); gl_M4_Rotate(&m,angle,1); break; case 1: if (sllvalue(u[2]) < sllvalue(int2sll(0))) angle=sllneg(angle); gl_M4_Rotate(&m,angle,2); break; default: { GLfloat cost, sint; /* normalize vector */ GLfloat len = slladd( slladd( sllmul(u[0],u[0]), sllmul(u[1],u[1]) ), sllmul(u[2],u[2])); if (sllvalue(len) == sllvalue(int2sll(0))) return; len = slldiv(int2sll(1), sllsqrt(len)); u[0] = sllmul(u[0], len); u[1] = sllmul(u[1], len); u[2] = sllmul(u[2], len); /* store cos and sin values */ cost=sllcos(angle); sint=sllsin(angle); /* fill in the values */ m.m[3][0]=m.m[3][1]=m.m[3][2]= m.m[0][3]=m.m[1][3]=m.m[2][3]=int2sll(0); m.m[3][3]=int2sll(1); /* do the math */ m.m[0][0]=slladd(sllmul(u[0],u[0]), sllmul(cost, sllsub(int2sll(1), sllmul(u[0],u[0])))); m.m[1][0]=sllsub(sllmul(sllmul(u[0],u[1]), sllsub(int2sll(1), cost)), sllmul(u[2],sint)); m.m[2][0]=slladd(sllmul(sllmul(u[2],u[0]), sllsub(int2sll(1), cost)), sllmul(u[1],sint)); m.m[0][1]=slladd(sllmul(sllmul(u[0],u[1]), sllsub(int2sll(1), cost)), sllmul(u[2],sint)); m.m[1][1]=slladd(sllmul(u[1],u[1]), sllmul(cost, sllsub(int2sll(1), sllmul(u[1],u[1])))); m.m[2][1]=sllsub(sllmul(sllmul(u[1],u[2]), sllsub(int2sll(1), cost)), sllmul(u[0],sint)); m.m[0][2]=sllsub(sllmul(sllmul(u[2],u[0]), sllsub(int2sll(1), cost)), sllmul(u[1],sint)); m.m[1][2]=slladd(sllmul(sllmul(u[1],u[2]), sllsub(int2sll(1), cost)), sllmul(u[0],sint)); m.m[2][2]=slladd(sllmul(u[2],u[2]), sllmul(cost, sllsub(int2sll(1), sllmul(u[2],u[2])))); } } gl_M4_MulLeft(c->matrix_stack_ptr[c->matrix_mode],&m); gl_matrix_update(c); }