1. Euphoria Chipmunk Physics
- Posted by Icy_Viking Mar 23, 2017
- 2167 views
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.
2. Re: Euphoria Chipmunk Physics
- Posted by ghaberek (admin) Mar 23, 2017
- 2165 views
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
3. Re: Euphoria Chipmunk Physics
- Posted by Icy_Viking Mar 23, 2017
- 2145 views
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?
4. Re: Euphoria Chipmunk Physics
- Posted by ghaberek (admin) Mar 23, 2017
- 2088 views
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
5. Re: Euphoria Chipmunk Physics
- Posted by petelomax Mar 23, 2017
- 2105 views
- Last edited Mar 27, 2017
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
6. Re: Euphoria Chipmunk Physics
- Posted by Icy_Viking Sep 14, 2017
- 1743 views
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)
7. Re: Euphoria Chipmunk Physics
- Posted by petelomax Sep 15, 2017
- 1702 views
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.
8. Re: Euphoria Chipmunk Physics
- Posted by Icy_Viking Oct 02, 2017
- 1628 views
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
9. Re: Euphoria Chipmunk Physics
- Posted by petelomax Oct 02, 2017
- 1602 views
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)
10. Re: Euphoria Chipmunk Physics
- Posted by Icy_Viking Oct 03, 2017
- 1576 views
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)
11. Re: Euphoria Chipmunk Physics
- Posted by petelomax Oct 03, 2017
- 1566 views
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
Pete