/src/SDLx/Controller/Interface.xs

http://github.com/PerlGameDev/SDL · Unknown · 241 lines · 203 code · 38 blank · 0 comment · 0 complexity · 80cc7118eee2a6ce304c343af1027b1d MD5 · raw file

  1. #include "EXTERN.h"
  2. #include "perl.h"
  3. #include "XSUB.h"
  4. #include "ppport.h"
  5. #include "defines.h"
  6. #include "helper.h"
  7. #ifndef aTHX_
  8. #define aTHX_
  9. #endif
  10. #include "SDLx/Controller/Interface.h"
  11. AV *acceleration_cb( SDLx_Interface *obj, float t )
  12. {
  13. SV *tmpsv;
  14. if( !(SvROK(obj->acceleration) && (tmpsv = obj->acceleration) ) )
  15. croak( "Interface doesn't not contain an acceleration callback" );
  16. dSP;
  17. AV *array = newAV();
  18. int i;
  19. int count;
  20. SDLx_State *copyState = (SDLx_State *)safemalloc( sizeof(SDLx_State) );
  21. copy_state( copyState, obj->current );
  22. copyState->owned = 0;
  23. ENTER;
  24. SAVETMPS;
  25. PUSHMARK(SP);
  26. XPUSHs( sv_2mortal(newSVnv(t)) );
  27. XPUSHs( sv_2mortal( obj2bag( sizeof(SDLx_State *), (void *)copyState, "SDLx::Controller::State" ) ) );
  28. PUTBACK;
  29. count = call_sv( obj->acceleration, G_ARRAY );
  30. SPAGAIN;
  31. /* warn( "state %p, state->x %f", copyState, ((SDLx_State *)copyState)->x ); */
  32. for( i = 0; i < count; i++ )
  33. av_push( array, newSVnv(POPn) );
  34. /* warn ("before obj->current->x %f", obj->current->x); */
  35. copy_state( obj->current, copyState );
  36. /* warn ("after obj->current->x %f", obj->current->x); */
  37. PUTBACK;
  38. FREETMPS;
  39. LEAVE;
  40. return array;
  41. }
  42. void evaluate(SDLx_Interface *obj, SDLx_Derivative *out, SDLx_State *initial, float t)
  43. {
  44. out->dx = initial->v_x;
  45. out->dy = initial->v_y;
  46. out->drotation = initial->ang_v;
  47. AV *accel = acceleration_cb(obj, t);
  48. SV *temp;
  49. temp = av_pop(accel);
  50. out->dv_x = sv_nv(temp);
  51. SvREFCNT_dec(temp);
  52. temp = av_pop(accel);
  53. out->dv_y = sv_nv(temp);
  54. SvREFCNT_dec(temp);
  55. temp = av_pop(accel);
  56. out->dang_v = sv_nv(temp);
  57. SvREFCNT_dec(temp);
  58. SvREFCNT_dec((SV *)accel);
  59. }
  60. void evaluate_dt(SDLx_Interface *obj, SDLx_Derivative *out, SDLx_State *initial, float t, float dt, SDLx_Derivative *d)
  61. {
  62. SDLx_State state;
  63. state.x = initial->x + d->dx * dt;
  64. state.y = initial->y + d->dy * dt;
  65. state.rotation = initial->rotation + d->drotation * dt;
  66. state.v_x = initial->v_x + d->dv_x * dt;
  67. state.v_y = initial->v_y + d->dv_y * dt;
  68. state.ang_v = initial->ang_v + d->dang_v * dt;
  69. out->dx = state.v_x;
  70. out->dy = state.v_y;
  71. out->drotation = state.ang_v;
  72. AV *accel = acceleration_cb(obj, t+dt);
  73. SV *temp;
  74. temp = av_pop(accel);
  75. out->dv_x = sv_nv(temp);
  76. SvREFCNT_dec(temp);
  77. temp = av_pop(accel);
  78. out->dv_y = sv_nv(temp);
  79. SvREFCNT_dec(temp);
  80. temp = av_pop(accel);
  81. out->dang_v = sv_nv(temp);
  82. SvREFCNT_dec(temp);
  83. SvREFCNT_dec((SV *)accel);
  84. }
  85. void integrate( SDLx_Interface *object, float t, float dt)
  86. {
  87. SDLx_State *state = object->current;
  88. SDLx_Derivative *a = (SDLx_Derivative *)safemalloc( sizeof(SDLx_Derivative) );
  89. SDLx_Derivative *b = (SDLx_Derivative *)safemalloc( sizeof(SDLx_Derivative) );
  90. SDLx_Derivative *c = (SDLx_Derivative *)safemalloc( sizeof(SDLx_Derivative) );
  91. SDLx_Derivative *d = (SDLx_Derivative *)safemalloc( sizeof(SDLx_Derivative) );
  92. evaluate(object, a, state, t);
  93. evaluate_dt(object, b, state, t, dt*0.5f, a);
  94. evaluate_dt(object, c, state, t, dt*0.5f, b);
  95. evaluate_dt(object, d, state, t, dt, c);
  96. const float dxdt = 1.0f/6.0f * (a->dx + 2.0f * (b->dx + c->dx) + d->dx);
  97. const float dv_xdt = 1.0f/6.0f * (a->dv_x + 2.0f * (b->dv_x + c->dv_x) + d->dv_x);
  98. const float dydt = 1.0f/6.0f * (a->dy + 2.0f * (b->dy + c->dy) + d->dy);
  99. const float dv_ydt = 1.0f/6.0f * (a->dv_y + 2.0f * (b->dv_y + c->dv_y) + d->dv_y);
  100. const float drotationdt = 1.0f/6.0f * (a->drotation + 2.0f * (b->drotation + c->drotation) + d->drotation);
  101. const float dv_angdt = 1.0f/6.0f * (a->dang_v + 2.0f * (b->dang_v + c->dang_v) + d->dang_v);
  102. state->x = state->x + dxdt * dt;
  103. state->v_x = state->v_x + dv_xdt * dt;
  104. state->y = state->y + dydt * dt;
  105. state->v_y = state->v_y + dv_ydt * dt;
  106. state->rotation = state->rotation + drotationdt * dt;
  107. state->ang_v = state->ang_v + dv_angdt * dt;
  108. safefree(a);
  109. safefree(b);
  110. safefree(c);
  111. safefree(d);
  112. }
  113. MODULE = SDLx::Controller::Interface PACKAGE = SDLx::Controller::Interface PREFIX = objx_
  114. SDLx_Interface *
  115. objx_make( CLASS, ... )
  116. char *CLASS
  117. CODE:
  118. RETVAL = (SDLx_Interface *)safemalloc( sizeof(SDLx_Interface) );
  119. RETVAL->previous = (SDLx_State *)safemalloc( sizeof(SDLx_State) );
  120. RETVAL->current = (SDLx_State *)safemalloc( sizeof(SDLx_State) );
  121. RETVAL->acceleration = newSViv(-1);
  122. RETVAL->current->x = 0;
  123. RETVAL->current->y = 0;
  124. RETVAL->current->v_x = 0;
  125. RETVAL->current->v_y = 0;
  126. RETVAL->current->rotation = 0;
  127. RETVAL->current->ang_v = 0;
  128. RETVAL->current->owned = 1;
  129. RETVAL->previous->owned = 1;
  130. if(items > 1) (RETVAL->current)->x = SvIV(ST(1));
  131. if(items > 2) (RETVAL->current)->y = SvIV(ST(2));
  132. if(items > 3) (RETVAL->current)->v_x = SvIV(ST(3));
  133. if(items > 4) (RETVAL->current)->v_y = SvIV(ST(4));
  134. if(items > 5) (RETVAL->current)->rotation = SvIV(ST(5));
  135. if(items > 6) (RETVAL->current)->ang_v = SvIV(ST(6));
  136. copy_state(RETVAL->previous, RETVAL->current);
  137. OUTPUT:
  138. RETVAL
  139. void
  140. objx_set_acceleration(obj, callback)
  141. SDLx_Interface *obj
  142. SV *callback
  143. CODE:
  144. SV *tmpsv = NULL;
  145. if( !(SvROK(callback) && (tmpsv = (SV*)SvRV(callback)) && SvTYPE(tmpsv) == SVt_PVCV ) )
  146. croak( "Acceleration callback needs to be a code ref, %p", callback );
  147. obj->acceleration = SvRV( newRV_inc(callback) );
  148. AV *
  149. objx_acceleration(obj, t)
  150. SDLx_Interface* obj
  151. float t
  152. CODE:
  153. RETVAL = acceleration_cb(obj, t);
  154. sv_2mortal((SV*)RETVAL);
  155. OUTPUT:
  156. RETVAL
  157. SDLx_State *
  158. objx_interpolate(obj, alpha)
  159. SDLx_Interface *obj
  160. float alpha
  161. PREINIT:
  162. char *CLASS = "SDLx::Controller::State";
  163. CODE:
  164. SDLx_State *out = (SDLx_State *)safemalloc(sizeof(SDLx_State ));
  165. interpolate( obj,out, alpha);
  166. out->owned = 0; /* condition free */
  167. RETVAL = out;
  168. OUTPUT:
  169. RETVAL
  170. SDLx_State *
  171. objx_current ( obj, ... )
  172. SDLx_Interface *obj
  173. PREINIT:
  174. char * CLASS = "SDLx::Controller::State";
  175. CODE:
  176. RETVAL = obj->current;
  177. OUTPUT:
  178. RETVAL
  179. SDLx_State *
  180. objx_previous ( obj, ... )
  181. SDLx_Interface *obj
  182. PREINIT:
  183. char *CLASS = "SDLx::Controller::State";
  184. CODE:
  185. RETVAL = obj->previous;
  186. OUTPUT:
  187. RETVAL
  188. void
  189. objx_update(obj, t, dt)
  190. SDLx_Interface *obj
  191. float t
  192. float dt
  193. CODE:
  194. copy_state( obj->previous, obj->current);
  195. integrate( obj, t, dt );
  196. void
  197. objx_DESTROY( obj )
  198. SDLx_Interface *obj
  199. CODE:
  200. SvREFCNT_dec(obj->acceleration);
  201. safefree(obj->previous);
  202. safefree(obj->current);
  203. safefree(obj);