1. Euphoria Chipmunk Physics

Hello,

I have managed to wrap the chipmunk physics library for Euphoria. http://www.rapideuphoria.com/uploads/euchipmunkphy.zip You can get it from the link. I was hoping to make a demo to go with it, however, I could not figure out how to Euphorialize the hello world chipmunk example that is written in C. The wrapper itself seems to work fine. I did test it and check it against some functions and procedures and it seems to work. No errors came up. Any comments or suggestions are welcomed.

new topic     » topic index » view message » categorize

2. Re: Euphoria Chipmunk Physics

Icy_Viking said...

Hello,

I have managed to wrap the chipmunk physics library for Euphoria. http://www.rapideuphoria.com/uploads/euchipmunkphy.zip You can get it from the link. I was hoping to make a demo to go with it, however, I could not figure out how to Euphorialize the hello world chipmunk example that is written in C. The wrapper itself seems to work fine. I did test it and check it against some functions and procedures and it seems to work. No errors came up. Any comments or suggestions are welcomed.

I had a look at your code and I'm not sure if you're going to be able to do this the way you're intending. The problem is that the Chipmunk library passes structures by value. Every time you see the code passing cpVect without an asterisk *, that means it's passing two literal C_DOUBLE values on the stack. This is the same problem you'd have on Allegro 5. Euphoria's C interop routines are simply not designed to pass structures by value at this time. I assume this is why I saw all of the vector parameters declared as sequence in your wrapper code. Unfortunately that will not work either. I was able to work around this in Allegro 5 by using a C shim library that manually peeked and poked the values as pointers instead.

Take the following C definitions:

typedef struct cpVect{ 
    cpFloat x, y; 
} cpVect 
 
cpVect cpBodyGetPosition(const cpBody *body) 
void cpBodySetPosition(cpBody *body, cpVect pos) 

And here is the non-functional wrapper code:

-- structure offets 
constant cpVect_x = 0 -- cpFloat (C_DOUBLE) 
constant cpVext_y = 8 -- cpFloat (C_DOUBLE) 
constant SIZEOF_CPVECT = 16 
 
constant x_cpBodyGetPosition = define_c_func( chipmunk, "+cpBodyGetPosition", {C_POINTER}, {C_DOUBLE,C_DOUBLE} /* return value must be an atom. this will not work! */ ) 
constant x_cpBodySetPosition = define_c_proc( chipmunk, "+cpBodySetPosition", {C_POINTER,C_DOUBLE,C_DOUBLE} /* this is 'cheating' but should technically work */ ) 

Another issue is that some C functions, like cpv() are declared as static inline, which prevents them from being exported by the library.

-Greg

new topic     » goto parent     » topic index » view message » categorize

3. Re: Euphoria Chipmunk Physics

ghaberek said...
Icy_Viking said...

Hello,

I have managed to wrap the chipmunk physics library for Euphoria. http://www.rapideuphoria.com/uploads/euchipmunkphy.zip You can get it from the link. I was hoping to make a demo to go with it, however, I could not figure out how to Euphorialize the hello world chipmunk example that is written in C. The wrapper itself seems to work fine. I did test it and check it against some functions and procedures and it seems to work. No errors came up. Any comments or suggestions are welcomed.

I had a look at your code and I'm not sure if you're going to be able to do this the way you're intending. The problem is that the Chipmunk library passes structures by value. Every time you see the code passing cpVect without an asterisk *, that means it's passing two literal C_DOUBLE values on the stack. This is the same problem you'd have on Allegro 5. Euphoria's C interop routines are simply not designed to pass structures by value at this time. I assume this is why I saw all of the vector parameters declared as sequence in your wrapper code. Unfortunately that will not work either. I was able to work around this in Allegro 5 by using a C shim library that manually peeked and poked the values as pointers instead.

Take the following C definitions:

typedef struct cpVect{ 
    cpFloat x, y; 
} cpVect 
 
cpVect cpBodyGetPosition(const cpBody *body) 
void cpBodySetPosition(cpBody *body, cpVect pos) 

And here is the non-functional wrapper code:

-- structure offets 
constant cpVect_x = 0 -- cpFloat (C_DOUBLE) 
constant cpVext_y = 8 -- cpFloat (C_DOUBLE) 
constant SIZEOF_CPVECT = 16 
 
constant x_cpBodyGetPosition = define_c_func( chipmunk, "+cpBodyGetPosition", {C_POINTER}, {C_DOUBLE,C_DOUBLE} /* return value must be an atom. this will not work! */ ) 
constant x_cpBodySetPosition = define_c_proc( chipmunk, "+cpBodySetPosition", {C_POINTER,C_DOUBLE,C_DOUBLE} /* this is 'cheating' but should technically work */ ) 

Another issue is that some C functions, like cpv() are declared as static inline, which prevents them from being exported by the library.

-Greg

Ah. I did not think of that. So it seems some more tricks and hacks sorta to speak would be needed in order to make this fully work. Even though Chipmunk is written in C as is Allegro, it seems some libraries are harder to wrap than others. Still a worthy shot, if nothing less. I wonder if Phix might be better at wrapping some of these libraries, it is very similar to Euphoria?

new topic     » goto parent     » topic index » view message » categorize

4. Re: Euphoria Chipmunk Physics

Icy_Viking said...

Ah. I did not think of that. So it seems some more tricks and hacks sorta to speak would be needed in order to make this fully work. Even though Chipmunk is written in C as is Allegro, it seems some libraries are harder to wrap than others. Still a worthy shot, if nothing less. I wonder if Phix might be better at wrapping some of these libraries, it is very similar to Euphoria?

As far as I can tell, Phix currently only supports a single return value as well. See builtins/VM/pcfunc.e. I'm not too sure how much work would be involved in extended Euphoria or Phix to handle this. Perhaps Pete or Jim could chime in on this.

-Greg

new topic     » goto parent     » topic index » view message » categorize

5. Re: Euphoria Chipmunk Physics

Icy_Viking said...

Ah. I did not think of that. So it seems some more tricks and hacks sorta to speak would be needed in order to make this fully work. Even though Chipmunk is written in C as is Allegro, it seems some libraries are harder to wrap than others. Still a worthy shot, if nothing less. I wonder if Phix might be better at wrapping some of these libraries, it is very similar to Euphoria?

If you can stretch to a teensie weensie bit of inline assembly then yes, Phix would indeed be better.

As well as (and completely independently of) c_func and define_c_func, in Phix you can call directly from inline assembly, with no other declaration required, eg:

function GetLastError() 
integer res 
#ilASM{ 
        call "kernel32.dll","GetLastError" 
        mov [res],eax 
      } 
    return res 
end function 

Unfortunately I have no direct experience with those rarer kinds of C functions, but if you can compile a bit of C, you can disassemble it with demo\pGUI\filedump.exw to see what a call translates to.

Pete

PS For some reason, I also wrote "For cross-platform use, #ilASM also has the guards [32], [64], [PE32], [PE64], ELF32], and [ELF64]" and I refuse to delete it.
Documentation of #ilASM is sketchy (but see phix.chm/internals, especially pLoadFlt..pStoreMint) however there are plenty of examples in builtins\VM
Also I would recommend something like tinycc over something that translates everything to incomprehensible SSE2 instructions

PPS another resource I often use is https://board.flatassembler.net/search.php to see if there is an example for a specific call

new topic     » goto parent     » topic index » view message » categorize

6. Re: Euphoria Chipmunk Physics

Well I have tried my hand at this again. http://www.rapideuphoria.com/uploads/euchipmunkphy.zip

I re-wrote the sequence parts as atoms and declared them as C_FLOATS. While this isn't perfect, I believe it is a step up. I also started work on a demo, but I got machine level exception errors on some calls. The commands commented out are where the machine-level exceptions occur. I simply treat cpVect and cpv as two separate x and y vars. I have declared them in the wrapper like this as well.

--Demo not currently working 
include std/machine.e 
include std/get.e 
 
include EuChipmunk.ew 
 
atom grav_x = 0 
atom grav_y = -100 
 
sequence gravity = {grav_x,grav_y} 
 
atom space = cpSpaceNew() 
cpSpaceSetGravity(space,gravity[1],gravity[2]) 
 
atom ground = cpSegmentShapeNew(cpSpaceGetStaticBody(space),-20,5,20,-5,0) 
cpShapeSetFriction(ground,1) 
cpSpaceAddShape(space,ground) 
 
atom radius = 5 
atom mass = 1 
 
atom moment = cpMomentForCircle(mass,0,radius,0,0) 
atom ballBody = cpSpaceAddBody(space,cpBodyNew(mass,moment)) 
 
--cpBodySetPos(ballBody,0,15) 
 
atom ballShape = cpSpaceAddShape(space,cpCircleShapeNew(ballBody,radius,0,0)) 
cpShapeSetFriction(ballShape,0.7) 
 
atom timeStep = 1.0 / 60.0 
 
--atom pos = cpBodyGetPosition(ballBody) 
--atom vel = cpBodyGetVelocity(ballBody) 
 
cpSpaceStep(space,timeStep) 
 
printf(1,"Ball: %d",{ballBody}) 
position(2,1) 
puts(1,"Press ESC to exit!\n") 
 
integer key  
while 1 do 
	key = get_key() 
	 
	if key = 27 then 
		exit 
	end if 
end while 
 
cpShapeFree(ballShape) 
cpBodyFree(ballBody) 
cpShapeFree(ground) 
cpSpaceFree(space) 
 
new topic     » goto parent     » topic index » view message » categorize

7. Re: Euphoria Chipmunk Physics

OK, I've had a closer look. From what I gather, passing/returning structures is highly compiler-dependent. I've pushed a working win32/phix-only version to PCAN.

Note that I only modified cpBodyGetPosition, cpBodySetPosition, cpBodyGetVelocity, deleted cpBodySetPos, and I think I spotted a simple typo in cpDampedSpringInit (untested).

Regards,
Pete

PS: during my investigations, I found that cpFloat is in fact C_DOUBLE, not C_FLOAT.

new topic     » goto parent     » topic index » view message » categorize

8. Re: Euphoria Chipmunk Physics

petelomax said...

OK, I've had a closer look. From what I gather, passing/returning structures is highly compiler-dependent. I've pushed a working win32/phix-only version to PCAN.

Note that I only modified cpBodyGetPosition, cpBodySetPosition, cpBodyGetVelocity, deleted cpBodySetPos, and I think I spotted a simple typo in cpDampedSpringInit (untested).

Regards,
Pete

PS: during my investigations, I found that cpFloat is in fact C_DOUBLE, not C_FLOAT.

I fixed the typo in the code. At cpDampedSpringInit. http://www.rapideuphoria.com/uploads/euchipmunkphy.zip

new topic     » goto parent     » topic index » view message » categorize

9. Re: Euphoria Chipmunk Physics

Icy_Viking said...

I fixed the typo in the code. At cpDampedSpringInit. http://www.rapideuphoria.com/uploads/euchipmunkphy.zip

I assume you didn't get any closer to getting this working on OE.
If you study the inline assembly, at least you know precisely what needs to happen, and hopefully can then figure out a fudge, eg:

--public constant xcpBodyGetPosition = define_c_func(chip,"cpBodyGetPosition",{C_POINTER},C_POINTER) 
public constant xcpBodyGetPosition = define_c_proc(chip,"cpBodyGetPosition",{C_POINTER,C_POINTER}) 
 
global function cpBodyGetPosition(atom body) 
atom pMem = allocate(16) -- (actually a pair of 64-bit float return values) 
atom x, y 
 
    c_proc(xcpBodyGetPosition,{pMem,body}) 
    x = float64_to_atom(peek({pMem,8})) 
    y = float64_to_atom(peek({pMem+8,8})) 
    free(pMem) 
    return {x,y} 
end function 
 
--public constant xcpBodySetPosition = define_c_proc(chip,"cpBodySetPosition",{C_POINTER,C_POINTER}) 
public constant xcpBodySetPosition = define_c_proc(chip,"cpBodySetPosition",{C_POINTER,C_POINTER,C_POINTER,C_POINTER,C_POINTER}) 
--                                                                       (parameters are really one pointer and two 64-bit floats) 
 
global procedure cpBodySetPosition(atom body, atom x, atom y) 
atom pMem = allocate(16) -- (for conversion only) 
sequence xy4 
    poke(pMem,atom_to_float64(x)) 
    poke(pMem+8,atom_to_float64(y)) 
    xy4 = peek4u({pMem,4}) -- (pass two 64-bit floats as 4 dwords) 
    free(pMem) 
    c_proc(xcpBodySetPosition,body&xy4) 
end procedure 
 
--public constant xcpBodyGetVelocity = define_c_func(chip,"cpBodyGetVelocity",{C_POINTER},C_POINTER) 
public constant xcpBodyGetVelocity = define_c_proc(chip,"cpBodyGetVelocity",{C_POINTER,C_POINTER}) 
 
global function cpBodyGetVelocity(atom body) 
atom pMem = allocate(16) 
atom x, y 
 
    c_proc(xcpBodyGetVelocity,{pMem,body}) 
    x = float64_to_atom(peek({pMem,8})) 
    y = float64_to_atom(peek({pMem+8,8})) 
    free(pMem) 
    return {x,y} 
end function 

HTH, Pete

EDIT: added a couple of missing ) and swapped body/pMem order, it now seems to work (on Phix anyway)

new topic     » goto parent     » topic index » view message » categorize

10. Re: Euphoria Chipmunk Physics

Well I added in those changes to the wrapper.

Wrapper

public constant xcpBodyGetPosition = define_c_proc(chip,"cpBodyGetPosition",{C_POINTER,C_POINTER}) 
 
public function cpBodyGetPosition(atom body) 
 
 atom pMem = allocate(16) 
 atom x,y 
  
 c_proc(xcpBodyGetPosition,{pMem,body}) 
 x = float64_to_atom(peek({pMem,8})) 
 y = float64_to_atom(peek({pMem+8,8})) 
 free(pMem) 
  
 return x+y 
	 
end function 
 
--set position of body 
public constant xcpBodySetPosition = define_c_proc(chip,"cpBodySetPosition",{C_POINTER,C_POINTER,C_POINTER,C_POINTER,C_POINTER}) 
 
public procedure cpBodySetPosition(atom body,atom x,atom y) 
 
 atom pMem = allocate(16) 
 sequence xy4 
 poke(pMem,atom_to_float64(x)) 
 poke(pMem+8,atom_to_float64(y)) 
 xy4 = peek4u({pMem,4}) 
 free(pMem) 
 c_proc(xcpBodySetPosition,body&xy4) 
	 
end procedure 
 
public constant xcpBodyGetVelocity = define_c_proc(chip,"cpBodyGetVelocity",{C_POINTER,C_POINTER}) 
 
public function cpBodyGetVelocity(atom body) 
 
 atom pMem = allocate(16) 
 atom x,y 
  
 c_proc(xcpBodyGetVelocity,{pMem,body}) 
 x = float64_to_atom(peek({pMem,8})) 
 y = float64_to_atom(peek({pMem+8,8})) 
 free(pMem) 
 return x+y 
	 
end function 

Example - Demo almost works except for values contain nunVal.

--Demo not currently working 
include std/machine.e 
include std/get.e 
 
include EuChipmunk.ew 
 
atom grav_x = 0 
atom grav_y = -100 
 
sequence gravity = {grav_x,grav_y} 
 
atom space = cpSpaceNew() 
cpSpaceSetGravity(space,gravity[1],gravity[2]) 
 
atom ground = cpSegmentShapeNew(cpSpaceGetStaticBody(space),-20,5,20,-5,0) 
cpShapeSetFriction(ground,1) 
cpSpaceAddShape(space,ground) 
 
atom radius = 5 
atom mass = 1 
 
atom moment = cpMomentForCircle(mass,0,radius,0,0) 
atom ballBody = cpSpaceAddBody(space,cpBodyNew(mass,moment)) 
 
cpBodySetPosition(ballBody,0,10) 
 
atom ballShape = cpSpaceAddShape(space,cpCircleShapeNew(ballBody,radius,0,0)) 
cpShapeSetFriction(ballShape,0.7) 
 
atom timeStep = 1.0 / 60.0 
 
 
for x = 0 to 2 by timeStep do 
	 
atom pos = (cpBodyGetPosition(ballBody)) 
atom vel = cpBodyGetVelocity(ballBody) 
 
 printf(1,"Pos: %d:: Vel: %d",{pos,vel}) 
	 cpSpaceStep(space,timeStep) 
end for 
 
integer key 
while 1 do 
	key = get_key() 
	 
	if key = 27 then 
		exit 
	end if 
end while 
 
 
cpShapeFree(ballShape) 
cpBodyFree(ballBody) 
cpShapeFree(ground) 
cpSpaceFree(space) 
 
new topic     » goto parent     » topic index » view message » categorize

11. Re: Euphoria Chipmunk Physics

Icy_Viking said...

Example - Demo almost works except for values contain nunVal.

On Phix I get pos of {0,10} and vel of {0,0} for the first 3 iterations (using a while instead of a for loop), then {-1,0} for the rest

You are aware, I take it, that cpSpaceSetGravity, cpSegmentShapeNew, cpShapeSetFriction, etc may all need similar changes?

Of course I'm available for hire at £100/day smile

Pete

new topic     » goto parent     » topic index » view message » categorize

Search



Quick Links

User menu

Not signed in.

Misc Menu