1#![allow(unused)]
34#![allow(non_snake_case)]
37#![allow(non_camel_case_types)]
38#![allow(non_upper_case_globals)]
39
40use ode_base::ode::{self, *};
46pub use ode::{convexfvp, trimeshvi};
47pub use ode::{dBodyID, dGeomID, dTriIndex};
48pub use ode::{dMatrix4, dMatrix3, dVector4, dVector3, dReal}; pub use ode::{dQuaternion};
50
51#[warn(unused)]
52#[warn(non_snake_case)]
55#[warn(non_camel_case_types)]
56#[warn(non_upper_case_globals)]
57
58use std::error::Error;
59
60pub use ode::err::{self, *};
62
63pub use ode::mat::{self, *};
65
66use ode::prim::{self, *};
68pub use prim::{Matrix4, M4I, Matrix3, M3I, Quaternion, QI};
69pub use prim::{PId, PI, PIh, PIt, PIq, PIx};
70pub use prim::{PIh3, PIt2, PIt4, PIt5, PIq3, PIx5};
71
72use ode::krp::{self, *};
74pub use krp::{Krp, KRPnk, KRP100, KRP095, KRP080, KRP001};
75
76pub mod trimeshconvex;
77use trimeshconvex::*;
78pub use trimeshconvex::{TriMesh, Convex};
79pub use trimeshconvex::{custom, tetra, cube, icosahedron, bunny};
80
81pub mod meta;
82use meta::*;
83pub use meta::{MetaInf, MetaConvex, MetaTriMesh, MetaComposite};
84pub use meta::{MetaSphere, MetaBox, MetaCapsule, MetaCylinder, MetaPlane};
85
86pub mod cls;
87use cls::*;
88pub use cls::{obg::{Obg, Gws}, AsPtr};
89
90pub mod ds;
91use ds::*;
92pub use ds::{Tdrawstuff, TdrawstuffSetter};
93
94use std::collections::hash_map::Entry;
95use std::collections::HashMap; use std::collections::btree_map::Entry as BTreeEntry;
97use std::collections::BTreeMap;
98use std::collections::VecDeque;
99
100use asciiz::u8z::{U8zBuf, u8zz::{CArgsBuf}};
101
102use std::ffi::{c_void, c_int};
103
104pub extern crate impl_sim;
105use once_cell::sync::Lazy;
108
109pub static mut OYK_MUT: Lazy<Vec<ODE>> = Lazy::new(|| vec![ODE::new(0.002)]);
111
112const KEY_HELP: &str = "
114 default defined key set
115 ctrl + 'P': pause on/off
116 ctrl + 'O': single step
117 ctrl + 'S': shadow on/off
118 ctrl + 'T': texture on/off
119 'w': wireframe (trimesh) solid/wireframe (show hidden face edge)
120 'p': wireframe (all) polyfill/wireframe (not show hidden face edge)
121 'v': show viewpoint (current num pos hpr)
122 's': change viewpoint (8 pattern preset/set)
123 'r': reset
124 '?': help (this message)
125";
126
127pub struct ODE { ds: Option<Box<dyn Tdrawstuff>>, sim: Option<Box<dyn Sim>>, ptt: Option<U8zBuf>, wire_solid: i32, polyfill_wireframe: i32, sw_viewpoint: usize, pub cams: BTreeMap<usize, Cam>,
137 rgts: HashMap<dGeomID, dGeomID>, mgms: HashMap<dGeomID, Box<dyn MetaInf>>, obgs: HashMap<dBodyID, Obg>, mbgs: BTreeMap<String, dBodyID>, vbgs: VecDeque<dBodyID>, modified: bool, gws: Gws, pub t_delta: dReal
146}
147
148#[macro_export]
150macro_rules! ode_sim {
151 ($rs: ident, $rf: ident) => {
152 match &mut $rs.sim {
153 Some(s) => s.$rf(),
154 None => $rs.$rf()
155 }
156 };
157 ($rs: ident, $rf: ident, $($e:expr),+) => {
158 match &mut $rs.sim {
159 Some(s) => s.$rf($($e),+),
160 None => $rs.$rf($($e),+)
161 }
162 };
163}
164#[macro_export]
168macro_rules! ode_mut {
169 () => { (&mut OYK_MUT)[0] };
170}
171#[macro_export]
175macro_rules! ode_ {
176 () => { (&OYK_MUT)[0] };
177}
178#[macro_export]
182macro_rules! ode_get_mut {
183 ($src: ident) => { (&mut OYK_MUT)[0].$src };
184}
185#[macro_export]
189macro_rules! ode_get {
190 ($src: ident) => { (&OYK_MUT)[0].$src };
191}
192macro_rules! ode_gws_set {
196 ($dst: ident, $src: expr) => {
197(&mut OYK_MUT)[0].gws.$dst = $src as usize
199 };
200}
201macro_rules! ode_gws_get {
205 ($src: ident, $dst: ty) => {
206(&OYK_MUT)[0].gws.$src as $dst
208 };
209}
210macro_rules! gws_dump {
214 () => {
215unsafe {
216 let gws: &mut Gws = &mut ode_get_mut!(gws);
217ostatln!("{:018p}", gws.world());
225 ostatln!("{:018p}", gws.space());
226 ostatln!("{:018p}", gws.ground());
227 ostatln!("{:018p}", gws.contactgroup());
228 ostatln!("{:018p}", gws.num_contact());
229}
230 ()
231 };
232}
233impl ODE {
237
238pub fn new(delta: dReal) -> ODE {
240 ostatln!("new ODE");
241 unsafe { dInitODE2(0); }
242 ODE{ds: None, sim: None, ptt: None,
243 wire_solid: 1, polyfill_wireframe: 0, sw_viewpoint: 0,
244 cams: vec![
245 Cam::new(vec![5.0, 0.0, 2.0], vec![-180.0, 0.0, 0.0]),
246 Cam::new(vec![0.0, 0.0, 20.0], vec![-180.0, -30.0, 0.0]),
247 Cam::new(vec![5.36, 2.02, 4.28], vec![-162.0, -31.0, 0.0]),
248 Cam::new(vec![-8.3, -14.1, 3.1], vec![84.5, 1.0, 0.0]),
249 Cam::new(vec![4.0, 3.0, 5.0], vec![-150.0, -30.0, 3.0]),
250 Cam::new(vec![10.0, 10.0, 5.0], vec![-150.0, 0.0, 3.0]),
251 Cam::new(vec![-20.0, -20.0, 10.0], vec![45.0, -15.0, 0.0])
252 ].into_iter().enumerate().collect(), rgts: vec![].into_iter().collect(), mgms: vec![].into_iter().collect(),
254 obgs: vec![].into_iter().collect(), mbgs: vec![].into_iter().collect(),
255 vbgs: vec![].try_into().unwrap_or_else(|o: std::convert::Infallible|
256 panic!("Expected VecDeque<dBodyID> from vec![] Infallible ({:?})", o)),
257 modified: false, gws: Gws::new(256), t_delta: delta}
258}
259
260pub fn ds_as_ref() -> &'static Box<dyn Tdrawstuff> {
262unsafe {
263 ode_get!(ds).as_ref().expect("get ds trait Tdrawstuff")
264}
265}
266
267pub fn open(drawstuff: impl Tdrawstuff + 'static,
272 delta: dReal, qsw: dReal, qsni: usize, cmcv: dReal, csl: dReal,
273 num_contact: usize) {
274unsafe {
275 ODE::set_drawstuff(&mut ode_get_mut!(ds), drawstuff);
276
277 ode_get_mut!(t_delta) = delta;
278 let gws: &mut Gws = &mut ode_get_mut!(gws);
280 gws.world_(0 as dWorldID); }
288 ODE::create_world(qsw, qsni, cmcv, csl, num_contact);
289}
291
292pub fn close() {
294 ODE::clear_obgs();
295 ODE::clear_contactgroup();
296 ODE::destroy_world();
297unsafe {
298 let v = &mut OYK_MUT;
300 drop(&v[0]); v.pop();
302 drop(v);
303}
304}
305
306pub fn create_world(qsw: dReal, qsni: usize, cmcv: dReal, csl: dReal,
308 num_contact: usize) {
309 ostatln!("create world");
310unsafe {
311 let gws: &mut Gws = &mut ode_get_mut!(gws);
312 gws.world_(dWorldCreate());
313 let wld = gws.world();
314 dWorldSetGravity(wld, 0.0, 0.0, -9.8);
315 ostatln!("QSW: {}", dWorldGetQuickStepW(wld)); dWorldSetQuickStepW(wld, qsw); ostatln!("QSNI: {}", dWorldGetQuickStepNumIterations(wld)); dWorldSetQuickStepNumIterations(wld, qsni as c_int);
319 ostatln!("CMCV: {}", dWorldGetContactMaxCorrectingVel(wld)); dWorldSetContactMaxCorrectingVel(wld, cmcv); ostatln!("CSL: {}", dWorldGetContactSurfaceLayer(wld)); dWorldSetContactSurfaceLayer(wld, csl); gws.space_(dHashSpaceCreate(0 as dSpaceID));
324 dSpaceSetCleanup(gws.space(), 1);
325 gws.ground_(dCreatePlane(gws.space(), 0.0, 0.0, 1.0, 0.0));
326 gws.contactgroup_(dJointGroupCreate(0));
327 gws.num_contact_(num_contact);
328 gws.contacts = (0..num_contact).into_iter().map(|_|
329 dContact::new()
330 ).collect::<Vec<_>>(); }
332}
333
334pub fn destroy_world() {
336 ostatln!("destroy world");
337unsafe {
338 let gws: &mut Gws = &mut ode_get_mut!(gws);
339 dSpaceDestroy(gws.space());
341 dWorldDestroy(gws.world());
342}
343}
344
345pub fn modify(&mut self) {
347 self.modified = true;
348}
349
350pub fn is_modified(&mut self, f: bool) -> bool {
352 let r = self.modified;
353 if r { self.modified = f; }
354 r
355}
356
357pub fn num(&self) -> usize {
359 self.obgs.len()
360}
361
362pub fn reg_mgm(&mut self, geom: dGeomID, mi: Box<dyn MetaInf>) -> dVector4 {
364 let col = mi.get_tcm().col;
365 match self.mgms.entry(geom) { Entry::Occupied(mut oe) => {
368 let e = oe.get_mut();
369 println!("mgms {:?} already exists. skipped", geom); e
371 },
372 Entry::Vacant(ve) => { ve.insert(mi) }
373 };
374 col
375}
376
377pub fn reg_obg(&mut self, obg: Obg) -> dBodyID {
379 let id = obg.body();
380 let obgs: &mut HashMap<dBodyID, Obg> = &mut self.obgs;
381 let key = match obgs.entry(id) { Entry::Occupied(oe) => {
384 let k = oe.get().key.clone();
385 println!("obgs {:?}[{}] already exists. skipped", id, k); k
387 },
388 Entry::Vacant(ve) => { ve.insert(obg).key.clone() }
389 };
390 let mbgs: &mut BTreeMap<String, dBodyID> = &mut self.mbgs;
391 match mbgs.entry(key.clone()) { BTreeEntry::Occupied(mut oe) => {
394 let mut e = oe.get_mut();
395 println!("mbgs [{}] already exists. replaced", key); *e = id;
397 e
398 },
399 BTreeEntry::Vacant(ve) => { ve.insert(id) }
400 };
401 let vbgs: &mut VecDeque<dBodyID> = &mut self.vbgs;
402 vbgs.push_back(id);
403 self.modify();
404 id
405}
406
407pub fn creator_dm(&mut self, key: &str, mi: Box<dyn MetaInf>, fmdm: bool) ->
410 (dBodyID, dGeomID, Box<dMass>) {
411 let gws: &mut Gws = &mut self.gws;
412 let world: dWorldID = gws.world();
413 let space: dSpaceID = if key == "" { 0 as dSpaceID } else { gws.space() };
414 let body: dBodyID;
415 let geom: dGeomID;
416 let mut mass: Box<dMass> = Box::new(dMass::new());
417unsafe {
418 geom = match mi.id() {
419 MetaId::Sphere => {
420 let ms = mi.as_sphere();
421 if fmdm {
422 dMassSetSphereTotal(&mut *mass, ms.dm, ms.r); }else{
424 dMassSetSphere(&mut *mass, ms.dm, ms.r);
425 }
426 dCreateSphere(space, ms.r)
427 },
428 MetaId::Box => {
429 let mb = mi.as_box();
430 if fmdm {
431 dMassSetBoxTotal(&mut *mass, mb.dm,
432 mb.lxyz[0], mb.lxyz[1], mb.lxyz[2]); }else{
434 dMassSetBox(&mut *mass, mb.dm, mb.lxyz[0], mb.lxyz[1], mb.lxyz[2]);
435 }
436 dCreateBox(space, mb.lxyz[0], mb.lxyz[1], mb.lxyz[2])
437 },
438 MetaId::Capsule => {
439 let mc = mi.as_capsule();
440 dMassSetCapsule(&mut *mass, mc.dm, 3, mc.r, mc.l);
441 dCreateCapsule(space, mc.r, mc.l)
442 },
443 MetaId::Cylinder => {
444 let mc = mi.as_cylinder();
445 dMassSetCylinder(&mut *mass, mc.dm, 3, mc.r, mc.l);
446 dCreateCylinder(space, mc.r, mc.l)
447 },
448 MetaId::Plane => {
449 let mp = mi.as_plane();
450 if fmdm {
451 dMassSetBoxTotal(&mut *mass, mp.dm,
452 mp.lxyz[0], mp.lxyz[1], mp.lxyz[2]); }else{
454 dMassSetBox(&mut *mass, mp.dm, mp.lxyz[0], mp.lxyz[1], mp.lxyz[2]);
455 }
456 dCreatePlane(space, mp.norm[0], mp.norm[1], mp.norm[2], mp.norm[3])
457 },
458 MetaId::Convex => {
459 let mc = mi.as_convex();
460 let g: dGeomID = CreateGeomConvexFromFVP(space, mc.fvp);
461 MassSetConvexAsTrimesh(&mut *mass, mc.dm, mc.fvp);
462 dGeomSetPosition(g, -mass.c[0], -mass.c[1], -mass.c[2]); dMassTranslate(&mut *mass, -mass.c[0], -mass.c[1], -mass.c[2]); g
465 },
466 MetaId::TriMesh => {
467 let mt = mi.as_trimesh();
468 let g: dGeomID = CreateGeomTrimeshFromVI(space, mt.tmv);
469 dMassSetTrimesh(&mut *mass, mt.dm, g);
470 dGeomSetPosition(g, -mass.c[0], -mass.c[1], -mass.c[2]); dMassTranslate(&mut *mass, -mass.c[0], -mass.c[1], -mass.c[2]); g
473 },
474 MetaId::Composite => {
475 panic!("use creator_composite for {:?}", mi.id());
476 },
477 _ => { panic!("creator not implemented for {:?}", mi.id()); }
478 };
479}
480 let col = self.reg_mgm(geom, mi); (if key == "" {
482 0 as dBodyID
483 }else{
484unsafe {
485 body = dBodyCreate(world);
486 dBodySetMass(body, &*mass);
487 dGeomSetBody(geom, body);
488 if !self.get_krp(geom).g { dBodyDisable(body); } }
490 let obg: Obg = Obg::new(key, body, geom, col);
491 self.reg_obg(obg)
492 }, geom, mass)
493}
494
495pub fn creator_m(&mut self, key: &str, mi: Box<dyn MetaInf>) ->
497 (dBodyID, dGeomID, Box<dMass>) {
498 self.creator_dm(key, mi, true)
499}
500
501pub fn creator(&mut self, key: &str, mi: Box<dyn MetaInf>) ->
503 (dBodyID, dGeomID, Box<dMass>) {
504 self.creator_dm(key, mi, false)
505}
506
507pub fn creator_composite(&mut self, key: &str, mi: Box<dyn MetaInf>) ->
509 (dBodyID, dGeomID, Box<dMass>) {
510 let gws: &mut Gws = &mut self.gws;
511 let world: dWorldID = gws.world();
512 let space: dSpaceID = gws.space();
513 let body: dBodyID;
514 let geom: dGeomID;
515 let mut mass: Box<dMass> = Box::new(dMass::new());
516 let mut gto: VecDeque<dGeomID> = vec![].try_into().unwrap(); let mut gts: HashMap<dGeomID, GeomOffset> = vec![].into_iter().collect();
520unsafe {
521 body = dBodyCreate(world);
522}
523 geom = match mi.id() {
524 MetaId::Composite => {
525 let mc = mi.as_composite();
526unsafe {
527 for (j, emi) in mc.elems.iter().enumerate() {
528 let gtrans: dGeomID = dCreateGeomTransform(space);
529 dGeomTransformSetCleanup(gtrans, 1);
530 let (_, gsub, mut subm) = self.creator("", emi.dup());
531 dGeomTransformSetGeom(gtrans, gsub);
532 gto.push_front(gtrans); let o = &mc.ofs[j];
534 gts.entry(gtrans).or_insert_with(|| GeomOffset{gsub: gsub, o: o});
535 dGeomSetPosition(gsub, o[0], o[1], o[2]);
536 dMassTranslate(&mut *subm, o[0], o[1], o[2]);
537 let q = &mc.qs[j];
538 dGeomSetQuaternion(gsub, q.as_ptr() as *mut dReal);
541 dMassRotate(&mut *subm, dMatrix3::from_Q(*q).as_ptr() as *mut dReal);
542 dMassAdd(&mut *mass, &*subm);
543 self.rgts.entry(gsub).or_insert(gtrans); }
545 0 as dGeomID }
547 },
548 _ => { panic!("use creator for {:?}", mi.id()); }
549 };
550unsafe {
551 for (gtrans, gso) in >s {
553 let o = gso.o;
554 dGeomSetPosition(gso.gsub, o[0]-mass.c[0], o[1]-mass.c[1], o[2]-mass.c[2]);
555 }
556 dMassTranslate(&mut *mass, -mass.c[0], -mass.c[1], -mass.c[2]);
557 dBodySetMass(body, &*mass); for gtrans in >o {
559 dGeomSetBody(*gtrans, body);
560 }
561 if !self.get_krp(gts[>o[0]].gsub).g { dBodyDisable(body); } }
563 gts.clear();
564 gto.clear();
565 let col = mi.get_tcm().col;
566 let obg: Obg = Obg::new(key, body, geom, col);
567 (self.reg_obg(obg), geom, mass)
568}
569
570pub fn get_grand_parent(&self, id: dGeomID) -> dBodyID {
573unsafe {
574 let mut b: dBodyID = dGeomGetBody(id);
575 if b == 0 as dBodyID { b = match self.rgts.get(&id) { None => 0 as dBodyID, Some(&g) => dGeomGetBody(g)
579 };
580 }
581 b
582}
583}
584
585pub fn get_ancestor(&self, id: dGeomID) -> (dBodyID, dBodyID) {
588unsafe {
589 let p: dBodyID = dGeomGetBody(id);
590 let gp: dBodyID = match self.rgts.get(&id) { None => 0 as dBodyID, Some(&g) => dGeomGetBody(g)
594 };
595 (p, gp)
596}
597}
598
599pub fn is_space(&self, o: dGeomID) -> bool {
601 unsafe { dGeomIsSpace(o) != 0 }
602}
603
604pub fn get_ground(&self) -> dGeomID {
606 let gws = &self.gws;
607 gws.ground()
608}
609
610pub fn get_contactgroup(&self) -> dJointGroupID {
612 let gws = &self.gws;
613 gws.contactgroup()
614}
615
616pub fn get_contacts(&mut self, o1: dGeomID, o2: dGeomID) -> i32 {
618 let gws = &mut self.gws;
619 let sz: i32 = std::mem::size_of::<dContact>() as i32;
620unsafe {
621 dCollide(o1, o2, gws.num_contact() as i32, &mut gws.contacts[0].geom, sz)
622}
623}
624
625pub fn ref_contacts_mut(&mut self) -> &mut Vec<dContact> {
627 &mut self.gws.contacts
628}
629
630pub fn ref_contacts(&self) -> &Vec<dContact> {
632 &self.gws.contacts
633}
634
635pub fn get_body_num_joints(&self, b: dBodyID) -> usize {
637 unsafe { dBodyGetNumJoints(b) as usize } }
639
640pub fn get_body_joint(&self, b: dBodyID, i: usize) -> dJointID {
642 unsafe { dBodyGetJoint(b, i as c_int) }
643}
644
645pub fn get_joint_num_bodies(&self, joint: dJointID) -> usize {
647 unsafe { dJointGetNumBodies(joint) as usize }
648}
649
650pub fn get_joint_body(&self, joint: dJointID, i: usize) -> dBodyID {
652 unsafe { dJointGetBody(joint, i as c_int) }
653}
654
655pub fn is_joint_enabled(&self, joint: dJointID) -> bool {
657 unsafe { dJointIsEnabled(joint) != 0 }
658}
659
660pub fn get_joint_type(&self, joint: dJointID) -> dJointType {
662 unsafe { dJointGetType(joint) }
663}
664
665pub fn get_joint_data(&self, joint: dJointID) -> *mut c_void {
667 unsafe { dJointGetData(joint) }
668}
669
670pub fn get_bounce(&self, id: dGeomID) -> dReal {
672 let gid: dGeomID = match unsafe { dGeomGetClass(id) } {
673 dGeomTransformClass => unsafe { dGeomTransformGetGeom(id) },
674 _ => id
675 }; match self.get_mgm(gid) {
677 Err(_) => KRP100.bounce, Ok(mgm) => mgm.get_krp().bounce
679 }
680}
681
682pub fn get_mu(&self, id: dGeomID) -> dReal {
684 let gid: dGeomID = match unsafe { dGeomGetClass(id) } {
685 dGeomTransformClass => unsafe { dGeomTransformGetGeom(id) },
686 _ => id
687 }; match self.get_mgm(gid) {
689 Err(_) => KRP100.mu, Ok(mgm) => mgm.get_krp().mu
691 }
692}
693
694pub fn get_krp_mut(&mut self, id: dGeomID) -> &mut Krp {
696 match self.get_mgm_mut(id) {
698 Err(_) => panic!("unregistered dGeomID MetaInf"), Ok(mgm) => mgm.get_krp_mut()
700 }
701}
702
703pub fn get_krp(&self, id: dGeomID) -> &Krp {
705 match self.get_mgm(id) {
707 Err(_) => &KRP100, Ok(mgm) => mgm.get_krp()
709 }
710}
711
712pub fn get_mgm_mut(&mut self, id: dGeomID) ->
714 Result<&mut Box<dyn MetaInf>, Box<dyn Error>> {
715 let mgms: &mut HashMap<dGeomID, Box<dyn MetaInf>> = &mut self.mgms;
716 Ok(mgms.get_mut(&id).ok_or(ODEError::no_mgm_id(id))?)
717}
718
719pub fn get_mgm(&self, id: dGeomID) ->
721 Result<&Box<dyn MetaInf>, Box<dyn Error>> {
722 let mgms: &HashMap<dGeomID, Box<dyn MetaInf>> = &self.mgms;
723 Ok(mgms.get(&id).ok_or(ODEError::no_mgm_id(id))?)
724}
725
726pub fn get_id(&self, k: String) -> Result<dBodyID, Box<dyn Error>> {
728 let mbgs: &BTreeMap<String, dBodyID> = &self.mbgs;
729 Ok(*mbgs.get(&k).ok_or(ODEError::no_key(k))?)
731}
732
733pub fn get_mut(&mut self, id: dBodyID) -> Result<&mut Obg, Box<dyn Error>> {
735 let obgs: &mut HashMap<dBodyID, Obg> = &mut self.obgs;
736 Ok(obgs.get_mut(&id).ok_or(ODEError::no_id(id))?)
737}
738
739pub fn find_mut(&mut self, k: String) -> Result<&mut Obg, Box<dyn Error>> {
741 let id: dBodyID = self.get_id(k)?;
742 self.get_mut(id)
743}
744
745pub fn get(&self, id: dBodyID) -> Result<&Obg, Box<dyn Error>> {
747 let obgs: &HashMap<dBodyID, Obg> = &self.obgs;
748 Ok(obgs.get(&id).ok_or(ODEError::no_id(id))?)
749}
750
751pub fn find(&self, k: String) -> Result<&Obg, Box<dyn Error>> {
753 let id: dBodyID = self.get_id(k)?;
754 self.get(id)
755}
756
757pub fn each_id<F>(&self, mut la: F) -> Vec<dBodyID>
760 where F: FnMut(&str, dBodyID) -> bool {
761 let mut r: Vec<dBodyID> = vec![];
762 for (k, v) in &self.mbgs {
763 r.push(if la(k, *v) { *v } else { 0 as dBodyID });
764 }
765 r
766}
767
768pub fn each<F>(&self, mut la: F) -> bool
771 where F: FnMut(&str, dBodyID, &Obg) -> bool {
772 for (k, v) in &self.mbgs {
773 match self.get(*v) {
774 Err(e) => { println!("{}", e); }, Ok(obg) => { if !la(k, *v, obg) { return false; } }
776 }
777 }
778 true
779}
780
781pub fn each_geom<F>(&self, obg: &Obg, mut la: F) -> bool
784 where F: FnMut(dGeomID, &Obg) -> bool {
785unsafe {
786 let mut geom: dGeomID = dBodyGetFirstGeom(obg.body());
787 while(geom != 0 as dGeomID){
788 let nextgeom: dGeomID = dBodyGetNextGeom(geom);
789 if !la(geom, obg) { return false; }
790 geom = nextgeom;
791 }
792 true
793}
794}
795
796pub fn destroy_obg(obg: &Obg) {
798unsafe {
799 let mut geom: dGeomID = dBodyGetFirstGeom(obg.body());
801 while(geom != 0 as dGeomID){
802 let nextgeom: dGeomID = dBodyGetNextGeom(geom);
803 dGeomDestroy(geom);
807 geom = nextgeom;
808 }
809 dBodyDestroy(obg.body());
810}
811}
812
813pub fn unregister_obg(&mut self, obg: &Obg, f: bool) -> Option<Obg> {
816unsafe {
817 let b = obg.body();
818 let rgts: &mut HashMap<dGeomID, dGeomID> = &mut ode_get_mut!(rgts);
819 let mgms: &mut HashMap<dGeomID, Box<dyn MetaInf>> = &mut ode_get_mut!(mgms);
820 self.each_geom(obg, |g, _o| {
821 rgts.remove(&g); mgms.remove(&g); true
824 });
825 let vbgs: &mut VecDeque<dBodyID> = &mut ode_get_mut!(vbgs);
826 match vbgs.iter().position(|&e| e == b) {
827 None => (),
828 Some(i) => { vbgs.remove(i); }
829 }
830 let mbgs: &mut BTreeMap<String, dBodyID> = &mut ode_get_mut!(mbgs);
831 mbgs.remove(&obg.key); let obgs: &mut HashMap<dBodyID, Obg> = &mut ode_get_mut!(obgs);
833 match obgs.remove(&b) { None => None,
835 Some(obg) => if f { ODE::destroy_obg(&obg); None } else { Some(obg) }
836 }
837}
838}
839
840pub fn unregister_obg_by_id(&mut self, id: dBodyID, f: bool) -> Option<Obg> {
843 unsafe {
845 let obgs: &mut HashMap<dBodyID, Obg> = &mut ode_get_mut!(obgs); match obgs.get(&id) {
847 None => None,
848 Some(obg) => self.unregister_obg(obg, f)
849 }
850}
851}
852
853pub fn clear_obgs() {
855unsafe {
856 let obgs: &HashMap<dBodyID, Obg> = &ode_get!(obgs);
857 for (id, obg) in obgs {
858 ODE::destroy_obg(obg); }
860 let obgs: &mut HashMap<dBodyID, Obg> = &mut ode_get_mut!(obgs);
861 obgs.clear();
862 let mbgs: &mut BTreeMap<String, dBodyID> = &mut ode_get_mut!(mbgs);
863 mbgs.clear();
864 let vbgs: &mut VecDeque<dBodyID> = &mut ode_get_mut!(vbgs);
865 vbgs.clear();
866 let mgms: &mut HashMap<dGeomID, Box<dyn MetaInf>> = &mut ode_get_mut!(mgms);
867 mgms.clear();
868 let rgts: &mut HashMap<dGeomID, dGeomID> = &mut ode_get_mut!(rgts);
869 rgts.clear();
870 let rode: &mut ODE = &mut ode_mut!();
871 rode.modify();
872}
873}
874
875pub fn clear_contactgroup() {
877unsafe {
878 let gws: &mut Gws = &mut ode_get_mut!(gws);
879 dJointGroupDestroy(gws.contactgroup());
880 gws.contactgroup_(dJointGroupCreate(0));
881}
882}
883
884pub fn viewpoint_() {
886 let ds = ODE::ds_as_ref();
887unsafe {
888 let sw_viewpoint: &usize = &ode_get!(sw_viewpoint);
889 let cams: &mut BTreeMap<usize, Cam> = &mut ode_get_mut!(cams);
890 let cam = cams.get_mut(sw_viewpoint).unwrap(); let pos: &mut [f32] = &mut cam.pos;
892 let ypr: &mut [f32] = &mut cam.ypr;
893 ds.SetViewpoint(pos as *mut [f32] as *mut f32, ypr as *mut [f32] as *mut f32);
894}
895}
896
897pub fn viewpoint(f: bool) {
899 let ds = ODE::ds_as_ref();
900unsafe {
901 let p: &mut [f32] = &mut vec![0.0; 4];
902 let y: &mut [f32] = &mut vec![0.0; 4];
903 ds.GetViewpoint(p as *mut [f32] as *mut f32, y as *mut [f32] as *mut f32);
904 let sw_viewpoint: &usize = &ode_get!(sw_viewpoint);
905 println!("viewpoint {} {:?}, {:?}", *sw_viewpoint, p, y);
906 match f {
907 true => {
908 let cams: &mut BTreeMap<usize, Cam> = &mut ode_get_mut!(cams);
909 let cam = cams.get_mut(sw_viewpoint).unwrap(); cam.pos = p.to_vec();
911 cam.ypr = y.to_vec();
912 },
913 _ => {}
914 }
915}
916}
917
918pub fn sim_loop(
920 width: i32, height: i32,
921 r_sim: Option<Box<dyn Sim>>,
922 a: &[u8]) {
923 let ds = ODE::ds_as_ref();
924unsafe {
925 let sim: &mut Option<Box<dyn Sim>> = &mut ode_get_mut!(sim);
926 *sim = r_sim;
927 let ptt: &mut Option<U8zBuf> = &mut ode_get_mut!(ptt);
928 *ptt = Some(U8zBuf::from_u8array(a)); let mut dsfn: dsFunctions_C = dsFunctions_C{
930 version: DS_VERSION,
931 start: Some(c_start_callback), step: Some(c_step_callback), command: Some(c_command_callback), stop: Some(c_stop_callback), path_to_textures: ptt.as_ref().expect("not init").as_i8p()
936 };
937
938 let mut cab: CArgsBuf = CArgsBuf::from(&std::env::args().collect());
939 ds.SimulationLoop(cab.as_argc(), cab.as_argv_ptr_mut(),
940 width, height, &mut dsfn);
941}
942}
943
944} impl Drop for ODE {
948 fn drop(&mut self) {
949 unsafe { dCloseODE(); }
950 ostatln!("dropped ODE");
951 }
952}
953
954pub trait Sim {
956 fn super_mut(&mut self) -> &mut ODE {
958unsafe {
959 &mut ode_mut!()
960}
961 }
962
963 fn super_get(&self) -> &ODE {
965unsafe {
966 &ode_!()
967}
968 }
969
970 fn set_pos_R(&mut self, b: dBodyID, p: dVector3, m: dMatrix3) {
972 self.super_mut().get_mut(b).expect("no body").set_pos(p).set_rot(m);
973 }
974
975 fn set_pos_Q(&mut self, b: dBodyID, p: dVector3, q: dQuaternion) {
977 self.super_mut().get_mut(b).expect("no body").set_pos(p).set_quaternion(q);
978 }
979
980 fn draw_geom(&self, geom: dGeomID,
982 pos: Option<*const dReal>, rot: Option<*const dReal>, ws: i32);
983 fn draw_objects(&mut self);
985 fn start_callback(&mut self);
987 fn near_callback(&mut self, dat: *mut c_void, o1: dGeomID, o2: dGeomID);
989 fn step_callback(&mut self, pause: i32);
991 fn command_callback(&mut self, cmd: i32);
993 fn stop_callback(&mut self);
995}
996
997impl Sim for ODE {
999
1000fn draw_objects(&mut self) {
1003 ostatln!("called default draw");
1004 let wire_solid = self.wire_solid; let obgs = &self.obgs;
1006 let vbgs = &self.vbgs;
1007 for id in vbgs { let obg = &obgs[&id];
1009unsafe {
1010 let mut g = dBodyGetFirstGeom(obg.body());
1011 while g != 0 as dGeomID {
1012 self.draw_geom(g, None, None, wire_solid);
1013 g = dBodyGetNextGeom(g);
1014 }
1015}
1016 }
1017}
1018
1019fn draw_geom(&self, geom: dGeomID,
1021 pos: Option<*const dReal>, rot: Option<*const dReal>, ws: i32) {
1022 if geom == 0 as dGeomID { return; }
1023 let ds = ODE::ds_as_ref();
1024unsafe {
1025 let pos: *const dReal = pos.unwrap_or_else(|| dGeomGetPosition(geom));
1026 let rot: *const dReal = rot.unwrap_or_else(|| dGeomGetRotation(geom));
1027 let col: &dVector4 = match self.get_mgm(geom) {
1028 Err(e) => {
1029 let obg = self.get(dGeomGetBody(geom)).unwrap(); &obg.col
1031 },
1032 Ok(mgm) => {
1033 let tcm = mgm.get_tcm();
1034 ds.SetTexture(tcm.tex);
1035 &tcm.col
1036 }
1037 };
1038 let c: Vec<f32> = col.into_iter().map(|v| *v as f32).collect();
1039 ds.SetColorAlpha(c[0], c[1], c[2], c[3]);
1040 let cls = dGeomGetClass(geom);
1041 match cls {
1042 dSphereClass => {
1043 let radius: dReal = dGeomSphereGetRadius(geom);
1044 ds.DrawSphereD(pos, rot, radius as f32);
1045 },
1046 dBoxClass => {
1047 let mut lxyz: dVector3 = [0.0; 4];
1048 dGeomBoxGetLengths(geom, lxyz.as_ptr_mut());
1049 ds.DrawBoxD(pos, rot, lxyz.as_ptr());
1050 },
1051 dCapsuleClass => {
1052 let mut r: dReal = 0.0;
1053 let mut l: dReal = 0.0;
1054 dGeomCapsuleGetParams(geom, &mut r as *mut dReal, &mut l as *mut dReal);
1055 ds.DrawCapsuleD(pos, rot, l as f32, r as f32);
1056 },
1057 dCylinderClass => {
1058 let mut r: dReal = 0.0;
1059 let mut l: dReal = 0.0;
1060 dGeomCylinderGetParams(geom, &mut r as *mut dReal, &mut l as *mut dReal);
1061 ds.DrawCylinderD(pos, rot, l as f32, r as f32);
1062 },
1063 dPlaneClass => {
1064 let mut norm: dVector4 = [0.0; 4];
1065 dGeomPlaneGetParams(geom, norm.as_ptr_mut());
1066 let lxyz: dVector3 = [10.0, 10.0, 0.05, 0.0]; ds.DrawBoxD(pos, rot, lxyz.as_ptr());
1069 },
1070 dRayClass => {
1071 println!("not implemented class: {}", cls);
1072 },
1073 dConvexClass => {
1074 match self.get_mgm(geom) {
1075 Err(e) => { println!("not found convex {:?} geomID {:?}", e, geom); },
1076 Ok(mgm) => {
1077 let fvp: &convexfvp = &*mgm.as_convex().fvp;
1078 ds.DrawConvexD(pos, rot,
1079 fvp.faces, fvp.faceCount, fvp.vtx, fvp.vtxCount, fvp.polygons);
1080 }
1081 }
1082 },
1083 dGeomTransformClass => {
1084 let gt: dGeomID = dGeomTransformGetGeom(geom);
1085 let gtpos: *const dReal = dGeomGetPosition(gt);
1086 let gtrot: *const dReal = dGeomGetRotation(gt);
1087 let mut rpos = dVector3::multiply0_331_pp(rot, gtpos);
1088 let ppos = std::slice::from_raw_parts(pos, 4); for i in 0..4 { rpos[i] += ppos[i]; }
1090 let rrot = dMatrix3::multiply0_333_pp(rot, gtrot);
1091 self.draw_geom(gt, Some(rpos.as_ptr()), Some(rrot.as_ptr()), ws);
1092 },
1093 dTriMeshClass => {
1094 match self.get_mgm(geom) {
1095 Err(e) => { println!("not found trimesh {:?} geomID {:?}", e, geom); },
1096 Ok(mgm) => {
1097 let tmv: &trimeshvi = &*mgm.as_trimesh().tmv;
1098let vtx = tmv.as_slice_vtx();
1112 let p = tmv.as_slice_indices();
1113 for i in 0..p.len()/3 {
1114 let idx = [p[i*3] as usize, p[i*3+1] as usize, p[i*3+2] as usize];
1115 let v: [[dReal; 3]; 3] = [
1116 [vtx[idx[0] * 3 + 0], vtx[idx[0] * 3 + 1], vtx[idx[0] * 3 + 2]],
1117 [vtx[idx[1] * 3 + 0], vtx[idx[1] * 3 + 1], vtx[idx[1] * 3 + 2]],
1118 [vtx[idx[2] * 3 + 0], vtx[idx[2] * 3 + 1], vtx[idx[2] * 3 + 2]]];
1119 ds.DrawTriangleD(pos, rot,
1120 v[0].as_ptr(), v[1].as_ptr(), v[2].as_ptr(), ws);
1121 }
1122 }
1123 }
1124 },
1125 dHeightfieldClass => {
1126 println!("not implemented class: {}", cls);
1127 },
1128 _ => { println!("unknown class: {}", cls); }
1129 }
1130}
1131}
1132
1133fn start_callback(&mut self) {
1135 ostatln!("called default start");
1136 let ds = ODE::ds_as_ref();
1137 ODE::viewpoint_();
1138unsafe {
1139 ds.SetSphereQuality(3); ds.SetCapsuleQuality(3); }
1142}
1143
1144fn near_callback(&mut self, dat: *mut c_void, o1: dGeomID, o2: dGeomID) {
1146 ostatln!("called default near");
1147 let gws = &self.gws;
1148 let world: dWorldID = gws.world();
1149 let contactgroup: dJointGroupID = gws.contactgroup();
1150 let ground: dGeomID = gws.ground();
1151unsafe {
1152 if dGeomIsSpace(o1) != 0 || dGeomIsSpace(o2) != 0 {
1153 dSpaceCollide2(o1, o2, dat, Some(c_near_callback));
1154 if dGeomIsSpace(o1) != 0 {
1155 dSpaceCollide(o1 as dSpaceID, dat, Some(c_near_callback));
1156 }
1157 if dGeomIsSpace(o2) != 0 {
1158 dSpaceCollide(o2 as dSpaceID, dat, Some(c_near_callback));
1159 }
1160 return;
1161 }
1162 let n = self.get_contacts(o1, o2);
1163 if ground == o1 || ground == o2 { let id: dGeomID = if ground == o1 { o2 } else { o1 };
1165 let bounce: dReal = self.get_bounce(id);
1166 let mu: dReal = self.get_mu(id);
1167 for i in 0..n as usize {
1168 let p: &mut dContact = &mut self.gws.contacts[i];
1169 p.surface.mode = dContactBounce | dContactSoftERP | dContactSoftCFM;
1170 p.surface.bounce = bounce; p.surface.bounce_vel = 1e-2; p.surface.mu = mu; p.surface.soft_erp = 0.2; p.surface.soft_cfm = 1e-3; let c: dJointID = dJointCreateContact(world, contactgroup, p);
1176 dJointAttach(c, dGeomGetBody(o1), dGeomGetBody(o2));
1178 }
1179 }else{
1180 let bounce: dReal = self.get_bounce(o1) * self.get_bounce(o2);
1181 let mu: dReal = dReal::min(self.get_mu(o1), self.get_mu(o2));
1182 for i in 0..n as usize {
1183 let p: &mut dContact = &mut self.gws.contacts[i];
1184 p.surface.mode = dContactBounce; p.surface.bounce = bounce; p.surface.bounce_vel = 1e-2; p.surface.mu = mu; let c: dJointID = dJointCreateContact(world, contactgroup, p);
1193 dJointAttach(c, dGeomGetBody(o1), dGeomGetBody(o2));
1195 }
1196 }
1197}
1198}
1199
1200fn step_callback(&mut self, pause: i32) {
1202 ostatln!("called default step");
1203 let gws = &self.gws;
1204 let t_delta = &self.t_delta;
1205 if pause != 1 {
1206 let mut tmp: HashMap<dBodyID, dVector3> = vec![].into_iter().collect();
1207 for (id, mi) in &self.mgms {
1208 if !mi.get_krp().k {
1209 let b: dBodyID = self.get_grand_parent(*id);
1210 if b == 0 as dBodyID { continue; }
1211 tmp.entry(b).or_insert(Obg::get_pos_mut_by_id(b)); }
1213 }
1214unsafe {
1215 dSpaceCollide(gws.space(), 0 as *mut c_void, Some(c_near_callback));
1216 dWorldStep(gws.world(), *t_delta);
1217 dJointGroupEmpty(gws.contactgroup());
1219}
1220 for (&b, p) in &tmp { Obg::set_pos_by_id(b, p); }
1221 }
1222 ode_sim!(self, draw_objects)
1223}
1224
1225fn command_callback(&mut self, cmd: i32) {
1227 ostatln!("called default command");
1228 let ds = ODE::ds_as_ref();
1229 match cmd as u8 as char {
1230 'p' => {
1231unsafe {
1232 let polyfill_wireframe: &mut i32 = &mut ode_get_mut!(polyfill_wireframe);
1233 *polyfill_wireframe = 1 - *polyfill_wireframe;
1234 ds.SetDrawMode(*polyfill_wireframe);
1235}
1236 },
1237 'w' => {
1238unsafe {
1239 let wire_solid: &mut i32 = &mut ode_get_mut!(wire_solid);
1240 *wire_solid = 1 - *wire_solid;
1241}
1242 },
1243 'v' => {
1244 ODE::viewpoint(false);
1245 },
1246 's' => {
1247 ODE::viewpoint(true);
1248unsafe {
1249 let sw_viewpoint: &mut usize = &mut ode_get_mut!(sw_viewpoint);
1250 *sw_viewpoint = (*sw_viewpoint + 1) % self.cams.len();
1251}
1252 ODE::viewpoint_();
1253 ODE::viewpoint(false);
1254 },
1255 'r' => {
1256 ODE::clear_obgs();
1257 ODE::clear_contactgroup();
1258 ode_sim!(self, start_callback)
1259 },
1260 '?' => {
1261 println!("{}", KEY_HELP);
1262 },
1263 _ => {}
1264 }
1265}
1266
1267fn stop_callback(&mut self) {
1269 ostatln!("called default stop");
1270}
1271
1272} unsafe extern "C"
1275fn c_start_callback() {
1276 let rode: &mut ODE = &mut ode_mut!();
1277 ode_sim!(rode, start_callback)
1278}
1279
1280unsafe extern "C"
1281fn c_near_callback(dat: *mut c_void, o1: dGeomID, o2: dGeomID) {
1282 let rode: &mut ODE = &mut ode_mut!();
1283 ode_sim!(rode, near_callback, dat, o1, o2)
1284}
1285
1286unsafe extern "C"
1287fn c_step_callback(pause: i32) {
1288 let rode: &mut ODE = &mut ode_mut!();
1289 ode_sim!(rode, step_callback, pause)
1290}
1291
1292unsafe extern "C"
1293fn c_command_callback(cmd: i32) {
1294 let rode: &mut ODE = &mut ode_mut!();
1295 ode_sim!(rode, command_callback, cmd)
1296}
1297
1298unsafe extern "C"
1299fn c_stop_callback() {
1300 let rode: &mut ODE = &mut ode_mut!();
1301 ode_sim!(rode, stop_callback)
1302}
1303
1304#[macro_export]
1306macro_rules! ostat {
1307 ($($e:expr),+) => {};
1309}
1310pub use ostat;
1311
1312#[macro_export]
1314macro_rules! ostatln {
1315 ($($e:expr),+) => {};
1317}
1318pub use ostatln;