PageRenderTime 49ms CodeModel.GetById 39ms app.highlight 3ms RepoModel.GetById 2ms app.codeStats 0ms

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