1 //metadoc ODEWorld copyright Jonathan Wright, 2006
2 //metadoc ODEWorld license BSD revised
3 /*metadoc ODEWorld description
7 #include "IoODEWorld.h"
9 #include "IoODEJointGroup.h"
14 #define DATA(self) ((IoODEWorldData *)IoObject_dataPointer(self))
15 #define WORLDID (DATA(self)->worldId)
17 IoTag
*IoODEWorld_newTag(void *state
)
19 IoTag
*tag
= IoTag_newWithName_("ODEWorld");
20 IoTag_state_(tag
, state
);
21 IoTag_freeFunc_(tag
, (IoTagFreeFunc
*)IoODEWorld_free
);
22 IoTag_cloneFunc_(tag
, (IoTagCloneFunc
*)IoODEWorld_rawClone
);
26 IoODEWorld
*IoODEWorld_proto(void *state
)
28 IoObject
*self
= IoObject_new(state
);
29 IoObject_tag_(self
, IoODEWorld_newTag(state
));
31 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoODEWorldData
)));
34 DATA(self
)->bodies
= 0L;
35 DATA(self
)->jointGroups
= 0L;
37 IoState_registerProtoWithFunc_(state
, self
, IoODEWorld_proto
);
40 IoMethodTable methodTable
[] = {
41 {"worldId", IoODEWorld_worldId
},
42 {"bodies", IoODEWorld_bodies
},
43 {"jointGroups", IoODEWorld_jointGroups
},
45 {"gravity", IoODEWorld_gravity
},
46 {"setGravity", IoODEWorld_setGravity
},
47 {"erp", IoODEWorld_erp
},
48 {"setErp", IoODEWorld_setErp
},
49 {"cfm", IoODEWorld_cfm
},
50 {"setCfm", IoODEWorld_setCfm
},
52 {"step", IoODEWorld_step
},
53 {"quickStep", IoODEWorld_quickStep
},
57 IoObject_addMethodTable_(self
, methodTable
);
62 IoODEWorld
*IoODEWorld_rawClone(IoODEWorld
*proto
)
64 IoObject
*self
= IoObject_rawClonePrimitive(proto
);
65 IoObject_setDataPointer_(self
, calloc(1, sizeof(IoODEWorldData
)));
66 WORLDID
= dWorldCreate();
67 DATA(self
)->bodies
= List_new();
68 DATA(self
)->jointGroups
= List_new();
69 IoObject_inlineSetSlot_to_(self
, IOSYMBOL("Body"), IoODEBody_newBodyProtoWithWorld(IOSTATE
, self
));
70 IoObject_inlineSetSlot_to_(self
, IOSYMBOL("JointGroup"), IoODEJointGroup_newJointGroupProtoWithWorld(IOSTATE
, self
));
74 IoODEWorld
*IoODEWorld_new(void *state
)
76 IoODEWorld
*proto
= IoState_protoWithInitFunction_(state
, IoODEWorld_proto
);
77 return IOCLONE(proto
);
80 void IoODEWorld_free(IoODEWorld
*self
)
82 IoODEWorld_emptyJointGroups(self
);
86 dWorldDestroy(WORLDID
);
89 if(DATA(self
)->bodies
)
91 LIST_FOREACH(DATA(self
)->bodies
, i
, body
,
92 IoODEBody_worldDestroyed((IoODEBody
*)body
);
94 List_free(DATA(self
)->bodies
);
95 DATA(self
)->bodies
= 0L;
97 if(DATA(self
)->jointGroups
)
99 LIST_FOREACH(DATA(self
)->jointGroups
, i
, jointGroup
,
100 IoODEJointGroup_worldDestoryed((IoODEJointGroup
*)jointGroup
);
102 List_free(DATA(self
)->jointGroups
);
103 DATA(self
)->jointGroups
= 0L;
105 free(IoObject_dataPointer(self
));
108 void IoODEWorld_mark(IoODEWorld
*self
)
112 /* ----------------------------------------------------------- */
114 dWorldID
IoODEWorld_rawWorldId(IoODEWorld
*self
)
119 void IoODEWorld_addBody(IoODEWorld
*self
, IoODEBody
*body
)
121 List_append_(DATA(self
)->bodies
, body
);
124 void IoODEWorld_removeBody(IoODEWorld
*self
, IoODEBody
*body
)
126 List_remove_(DATA(self
)->bodies
, body
);
129 void IoODEWorld_addJointGroup(IoODEWorld
*self
, IoODEJointGroup
*jointGroup
)
131 List_append_(DATA(self
)->jointGroups
, jointGroup
);
134 void IoODEWorld_removeJointGroup(IoODEWorld
*self
, IoODEJointGroup
*jointGroup
)
136 List_remove_(DATA(self
)->jointGroups
, jointGroup
);
139 void IoODEWorld_emptyJointGroups(IoODEWorld
*self
)
141 if(DATA(self
)->jointGroups
)
143 LIST_FOREACH(DATA(self
)->jointGroups
, i
, jointGroup
,
144 IoODEJointGroup_rawEmpty((IoODEJointGroup
*)jointGroup
);
149 /* ----------------------------------------------------------- */
151 void IoODEWorld_assertHasWorldId(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
153 IOASSERT(WORLDID
, "ODE World cannot be used directly. Clone the world and use the clone.");
157 IoObject
*IoODEWorld_worldId(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
159 return IONUMBER((long)WORLDID
);
162 IoObject
*IoODEWorld_setGravity(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
164 const double x
= IoMessage_locals_doubleArgAt_(m
, locals
, 0);
165 const double y
= IoMessage_locals_doubleArgAt_(m
, locals
, 1);
166 const double z
= IoMessage_locals_doubleArgAt_(m
, locals
, 2);
168 IoODEWorld_assertHasWorldId(self
, locals
, m
);
169 dWorldSetGravity(WORLDID
, x
, y
, z
);
173 IoObject
*IoODEWorld_gravity(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
176 IoODEWorld_assertHasWorldId(self
, locals
, m
);
178 dWorldGetGravity(WORLDID
, gravity
);
180 return IoSeq_newVec3f(IOSTATE
, {gravity
[0], gravity
[1], gravity
[2]});
183 IoObject
*IoODEWorld_step(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
185 const double stepSize
= IoMessage_locals_doubleArgAt_(m
, locals
, 0);
187 IoODEWorld_assertHasWorldId(self
, locals
, m
);
188 dWorldStep(WORLDID
, stepSize
);
192 IoObject
*IoODEWorld_quickStep(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
194 const double stepSize
= IoMessage_locals_doubleArgAt_(m
, locals
, 0);
196 IoODEWorld_assertHasWorldId(self
, locals
, m
);
197 dWorldQuickStep(WORLDID
, stepSize
);
201 IoObject
*IoODEWorld_stepFast1(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
203 const double stepSize
= IoMessage_locals_doubleArgAt_(m
, locals
, 0);
204 const int maxIterations
= IoMessage_locals_intArgAt_(m
, locals
, 1);
206 IoODEWorld_assertHasWorldId(self
, locals
, m
);
207 dWorldStepFast1(WORLDID
, stepSize
, maxIterations
);
211 IoObject
*IoODEWorld_bodies(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
213 IoODEWorld_assertHasWorldId(self
, locals
, m
);
215 IoList
*list
= IoList_new(IOSTATE
);
216 IoList_rawAddBaseList_(list
, DATA(self
)->bodies
);
221 IoObject
*IoODEWorld_jointGroups(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
223 IoODEWorld_assertHasWorldId(self
, locals
, m
);
225 IoList
*list
= IoList_new(IOSTATE
);
226 IoList_rawAddBaseList_(list
, DATA(self
)->jointGroups
);
231 IoObject
*IoODEWorld_erp(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
233 IoODEWorld_assertHasWorldId(self
, locals
, m
);
234 return IONUMBER(dWorldGetERP(WORLDID
));
237 IoObject
*IoODEWorld_setErp(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
239 const double erp
= IoMessage_locals_doubleArgAt_(m
, locals
, 0);
240 IoODEWorld_assertHasWorldId(self
, locals
, m
);
241 dWorldSetERP(WORLDID
, erp
);
245 IoObject
*IoODEWorld_cfm(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
247 IoODEWorld_assertHasWorldId(self
, locals
, m
);
248 return IONUMBER(dWorldGetCFM(WORLDID
));
251 IoObject
*IoODEWorld_setCfm(IoODEWorld
*self
, IoObject
*locals
, IoMessage
*m
)
253 const double cfm
= IoMessage_locals_doubleArgAt_(m
, locals
, 0);
254 IoODEWorld_assertHasWorldId(self
, locals
, m
);
255 dWorldSetCFM(WORLDID
, cfm
);