/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
- #include "EXTERN.h"
- #include "perl.h"
- #include "XSUB.h"
- #include "ppport.h"
- #include "defines.h"
- #include "helper.h"
- #ifndef aTHX_
- #define aTHX_
- #endif
- #include "SDLx/Controller/Interface.h"
- AV *acceleration_cb( SDLx_Interface *obj, float t )
- {
- SV *tmpsv;
- if( !(SvROK(obj->acceleration) && (tmpsv = obj->acceleration) ) )
- croak( "Interface doesn't not contain an acceleration callback" );
- dSP;
- AV *array = newAV();
- int i;
- int count;
- SDLx_State *copyState = (SDLx_State *)safemalloc( sizeof(SDLx_State) );
- copy_state( copyState, obj->current );
- copyState->owned = 0;
- ENTER;
- SAVETMPS;
- PUSHMARK(SP);
- XPUSHs( sv_2mortal(newSVnv(t)) );
- XPUSHs( sv_2mortal( obj2bag( sizeof(SDLx_State *), (void *)copyState, "SDLx::Controller::State" ) ) );
- PUTBACK;
- count = call_sv( obj->acceleration, G_ARRAY );
- SPAGAIN;
- /* warn( "state %p, state->x %f", copyState, ((SDLx_State *)copyState)->x ); */
- for( i = 0; i < count; i++ )
- av_push( array, newSVnv(POPn) );
- /* warn ("before obj->current->x %f", obj->current->x); */
- copy_state( obj->current, copyState );
- /* warn ("after obj->current->x %f", obj->current->x); */
- PUTBACK;
- FREETMPS;
- LEAVE;
- return array;
- }
- void evaluate(SDLx_Interface *obj, SDLx_Derivative *out, SDLx_State *initial, float t)
- {
- out->dx = initial->v_x;
- out->dy = initial->v_y;
- out->drotation = initial->ang_v;
- AV *accel = acceleration_cb(obj, t);
- SV *temp;
- temp = av_pop(accel);
- out->dv_x = sv_nv(temp);
- SvREFCNT_dec(temp);
- temp = av_pop(accel);
- out->dv_y = sv_nv(temp);
- SvREFCNT_dec(temp);
- temp = av_pop(accel);
- out->dang_v = sv_nv(temp);
- SvREFCNT_dec(temp);
- SvREFCNT_dec((SV *)accel);
- }
- void evaluate_dt(SDLx_Interface *obj, SDLx_Derivative *out, SDLx_State *initial, float t, float dt, SDLx_Derivative *d)
- {
- SDLx_State state;
- state.x = initial->x + d->dx * dt;
- state.y = initial->y + d->dy * dt;
- state.rotation = initial->rotation + d->drotation * dt;
- state.v_x = initial->v_x + d->dv_x * dt;
- state.v_y = initial->v_y + d->dv_y * dt;
- state.ang_v = initial->ang_v + d->dang_v * dt;
- out->dx = state.v_x;
- out->dy = state.v_y;
- out->drotation = state.ang_v;
- AV *accel = acceleration_cb(obj, t+dt);
- SV *temp;
- temp = av_pop(accel);
- out->dv_x = sv_nv(temp);
- SvREFCNT_dec(temp);
- temp = av_pop(accel);
- out->dv_y = sv_nv(temp);
- SvREFCNT_dec(temp);
- temp = av_pop(accel);
- out->dang_v = sv_nv(temp);
- SvREFCNT_dec(temp);
- SvREFCNT_dec((SV *)accel);
- }
- void integrate( SDLx_Interface *object, float t, float dt)
- {
- SDLx_State *state = object->current;
- SDLx_Derivative *a = (SDLx_Derivative *)safemalloc( sizeof(SDLx_Derivative) );
- SDLx_Derivative *b = (SDLx_Derivative *)safemalloc( sizeof(SDLx_Derivative) );
- SDLx_Derivative *c = (SDLx_Derivative *)safemalloc( sizeof(SDLx_Derivative) );
- SDLx_Derivative *d = (SDLx_Derivative *)safemalloc( sizeof(SDLx_Derivative) );
- evaluate(object, a, state, t);
- evaluate_dt(object, b, state, t, dt*0.5f, a);
- evaluate_dt(object, c, state, t, dt*0.5f, b);
- evaluate_dt(object, d, state, t, dt, c);
- const float dxdt = 1.0f/6.0f * (a->dx + 2.0f * (b->dx + c->dx) + d->dx);
- const float dv_xdt = 1.0f/6.0f * (a->dv_x + 2.0f * (b->dv_x + c->dv_x) + d->dv_x);
- const float dydt = 1.0f/6.0f * (a->dy + 2.0f * (b->dy + c->dy) + d->dy);
- const float dv_ydt = 1.0f/6.0f * (a->dv_y + 2.0f * (b->dv_y + c->dv_y) + d->dv_y);
- const float drotationdt = 1.0f/6.0f * (a->drotation + 2.0f * (b->drotation + c->drotation) + d->drotation);
- const float dv_angdt = 1.0f/6.0f * (a->dang_v + 2.0f * (b->dang_v + c->dang_v) + d->dang_v);
- state->x = state->x + dxdt * dt;
- state->v_x = state->v_x + dv_xdt * dt;
- state->y = state->y + dydt * dt;
- state->v_y = state->v_y + dv_ydt * dt;
- state->rotation = state->rotation + drotationdt * dt;
- state->ang_v = state->ang_v + dv_angdt * dt;
- safefree(a);
- safefree(b);
- safefree(c);
- safefree(d);
- }
- MODULE = SDLx::Controller::Interface PACKAGE = SDLx::Controller::Interface PREFIX = objx_
- SDLx_Interface *
- objx_make( CLASS, ... )
- char *CLASS
- CODE:
- RETVAL = (SDLx_Interface *)safemalloc( sizeof(SDLx_Interface) );
- RETVAL->previous = (SDLx_State *)safemalloc( sizeof(SDLx_State) );
- RETVAL->current = (SDLx_State *)safemalloc( sizeof(SDLx_State) );
- RETVAL->acceleration = newSViv(-1);
- RETVAL->current->x = 0;
- RETVAL->current->y = 0;
- RETVAL->current->v_x = 0;
- RETVAL->current->v_y = 0;
- RETVAL->current->rotation = 0;
- RETVAL->current->ang_v = 0;
- RETVAL->current->owned = 1;
- RETVAL->previous->owned = 1;
- if(items > 1) (RETVAL->current)->x = SvIV(ST(1));
- if(items > 2) (RETVAL->current)->y = SvIV(ST(2));
- if(items > 3) (RETVAL->current)->v_x = SvIV(ST(3));
- if(items > 4) (RETVAL->current)->v_y = SvIV(ST(4));
- if(items > 5) (RETVAL->current)->rotation = SvIV(ST(5));
- if(items > 6) (RETVAL->current)->ang_v = SvIV(ST(6));
- copy_state(RETVAL->previous, RETVAL->current);
- OUTPUT:
- RETVAL
- void
- objx_set_acceleration(obj, callback)
- SDLx_Interface *obj
- SV *callback
- CODE:
- SV *tmpsv = NULL;
- if( !(SvROK(callback) && (tmpsv = (SV*)SvRV(callback)) && SvTYPE(tmpsv) == SVt_PVCV ) )
- croak( "Acceleration callback needs to be a code ref, %p", callback );
- obj->acceleration = SvRV( newRV_inc(callback) );
- AV *
- objx_acceleration(obj, t)
- SDLx_Interface* obj
- float t
- CODE:
- RETVAL = acceleration_cb(obj, t);
- sv_2mortal((SV*)RETVAL);
- OUTPUT:
- RETVAL
- SDLx_State *
- objx_interpolate(obj, alpha)
- SDLx_Interface *obj
- float alpha
- PREINIT:
- char *CLASS = "SDLx::Controller::State";
- CODE:
- SDLx_State *out = (SDLx_State *)safemalloc(sizeof(SDLx_State ));
- interpolate( obj,out, alpha);
- out->owned = 0; /* condition free */
- RETVAL = out;
- OUTPUT:
- RETVAL
- SDLx_State *
- objx_current ( obj, ... )
- SDLx_Interface *obj
- PREINIT:
- char * CLASS = "SDLx::Controller::State";
- CODE:
- RETVAL = obj->current;
- OUTPUT:
- RETVAL
- SDLx_State *
- objx_previous ( obj, ... )
- SDLx_Interface *obj
- PREINIT:
- char *CLASS = "SDLx::Controller::State";
- CODE:
- RETVAL = obj->previous;
- OUTPUT:
- RETVAL
- void
- objx_update(obj, t, dt)
- SDLx_Interface *obj
- float t
- float dt
- CODE:
- copy_state( obj->previous, obj->current);
- integrate( obj, t, dt );
- void
- objx_DESTROY( obj )
- SDLx_Interface *obj
- CODE:
- SvREFCNT_dec(obj->acceleration);
- safefree(obj->previous);
- safefree(obj->current);
- safefree(obj);