#![allow(unused)]
#![allow(non_snake_case)]
#![allow(non_camel_case_types)]
#![allow(non_upper_case_globals)]
pub use drawstuff::drawstuff::*;
use ode_base::ode::{self, *};
pub use ode::{dBodyID, dGeomID, dTriIndex};
pub use ode::{dMatrix4, dMatrix3, dVector4, dVector3, dReal}; pub use ode::{dQuaternion};
#[warn(unused)]
#[warn(non_snake_case)]
#[warn(non_camel_case_types)]
#[warn(non_upper_case_globals)]
use std::error::Error;
pub use ode::err::{self, *};
pub use ode::mat::{self, *};
use ode::prim::{self, *};
pub use prim::{Matrix4, M4I, Matrix3, M3I, Quaternion, QI};
pub use prim::{PId, PI, PIh, PIt, PIq, PIx};
pub use prim::{PIh3, PIt2, PIt4, PIt5, PIq3, PIx5};
use ode::krp::{self, *};
pub use krp::{Krp, KRPnk, KRP100, KRP095, KRP080, KRP001};
pub mod trimeshconvex;
use trimeshconvex::*;
pub use trimeshconvex::{TriMesh, Convex};
pub use trimeshconvex::{custom, tetra, cube, icosahedron, bunny};
pub mod meta;
use meta::*;
pub use meta::{MetaInf, MetaConvex, MetaTriMesh, MetaComposite};
pub use meta::{MetaSphere, MetaBox, MetaCapsule, MetaCylinder, MetaPlane};
pub mod cls;
use cls::*;
pub use cls::{obg::{Obg, Gws}, AsPtr};
use std::collections::hash_map::Entry;
use std::collections::HashMap; use std::collections::btree_map::Entry as BTreeEntry;
use std::collections::BTreeMap;
use std::collections::VecDeque;
use asciiz::u8z::{U8zBuf, u8zz::{CArgsBuf}};
use std::ffi::{c_void};
pub extern crate impl_sim;
use once_cell::sync::Lazy;
pub static mut OYK_MUT: Lazy<Vec<ODE>> = Lazy::new(|| vec![ODE::new(0.002)]);
pub struct ODE { sim: Option<Box<dyn Sim>>, ptt: Option<U8zBuf>, wire_solid: i32, polyfill_wireframe: i32, sw_viewpoint: usize, pub cams: BTreeMap<usize, Cam>,
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
}
#[macro_export]
macro_rules! ode_sim {
($rs: ident, $rf: ident) => {
match &mut $rs.sim {
Some(s) => s.$rf(),
None => $rs.$rf()
}
};
($rs: ident, $rf: ident, $($e:expr),+) => {
match &mut $rs.sim {
Some(s) => s.$rf($($e),+),
None => $rs.$rf($($e),+)
}
};
}
#[macro_export]
macro_rules! ode_mut {
() => { (&mut OYK_MUT)[0] };
}
#[macro_export]
macro_rules! ode_ {
() => { (&OYK_MUT)[0] };
}
#[macro_export]
macro_rules! ode_get_mut {
($src: ident) => { (&mut OYK_MUT)[0].$src };
}
#[macro_export]
macro_rules! ode_get {
($src: ident) => { (&OYK_MUT)[0].$src };
}
macro_rules! ode_gws_set {
($dst: ident, $src: expr) => {
(&mut OYK_MUT)[0].gws.$dst = $src as usize
};
}
macro_rules! ode_gws_get {
($src: ident, $dst: ty) => {
(&OYK_MUT)[0].gws.$src as $dst
};
}
macro_rules! gws_dump {
() => {
unsafe {
let gws: &mut Gws = &mut ode_get_mut!(gws);
ostatln!("{:018p}", gws.world());
ostatln!("{:018p}", gws.space());
ostatln!("{:018p}", gws.ground());
ostatln!("{:018p}", gws.contactgroup());
}
()
};
}
impl ODE {
pub fn new(delta: dReal) -> ODE {
ostatln!("new ODE");
unsafe { dInitODE2(0); }
ODE{sim: None, ptt: None,
wire_solid: 1, polyfill_wireframe: 0, sw_viewpoint: 0,
cams: vec![
Cam::new(vec![5.0, 0.0, 2.0], vec![-180.0, 0.0, 0.0]),
Cam::new(vec![0.0, 0.0, 20.0], vec![-180.0, -30.0, 0.0]),
Cam::new(vec![5.36, 2.02, 4.28], vec![-162.0, -31.0, 0.0]),
Cam::new(vec![-8.3, -14.1, 3.1], vec![84.5, 1.0, 0.0]),
Cam::new(vec![4.0, 3.0, 5.0], vec![-150.0, -30.0, 3.0]),
Cam::new(vec![10.0, 10.0, 5.0], vec![-150.0, 0.0, 3.0]),
Cam::new(vec![-20.0, -20.0, 10.0], vec![45.0, -15.0, 0.0])
].into_iter().enumerate().collect(), rgts: vec![].into_iter().collect(), mgms: vec![].into_iter().collect(),
obgs: vec![].into_iter().collect(), mbgs: vec![].into_iter().collect(),
vbgs: vec![].try_into().unwrap_or_else(|o: std::convert::Infallible|
panic!("Expected VecDeque<dBodyID> from vec![] Infallible ({:?})", o)),
modified: false, gws: Gws::new(), t_delta: delta}
}
pub fn open() {
unsafe {
let gws: &mut Gws = &mut ode_get_mut!(gws);
gws.world_(0 as dWorldID); }
ODE::create_world();
}
pub fn close() {
ODE::clear_obgs();
ODE::clear_contactgroup();
ODE::destroy_world();
unsafe {
let v = &mut OYK_MUT;
drop(&v[0]); v.pop();
drop(v);
}
}
pub fn create_world() {
ostatln!("create world");
unsafe {
let gws: &mut Gws = &mut ode_get_mut!(gws);
gws.world_(dWorldCreate());
dWorldSetGravity(gws.world(), 0.0, 0.0, -9.8);
gws.space_(dHashSpaceCreate(0 as dSpaceID));
dSpaceSetCleanup(gws.space(), 1);
gws.ground_(dCreatePlane(gws.space(), 0.0, 0.0, 1.0, 0.0));
gws.contactgroup_(dJointGroupCreate(0));
}
}
pub fn destroy_world() {
ostatln!("destroy world");
unsafe {
let gws: &mut Gws = &mut ode_get_mut!(gws);
dSpaceDestroy(gws.space());
dWorldDestroy(gws.world());
}
}
pub fn modify(&mut self) {
self.modified = true;
}
pub fn is_modified(&mut self, f: bool) -> bool {
let r = self.modified;
if r { self.modified = f; }
r
}
pub fn num(&self) -> usize {
self.obgs.len()
}
pub fn reg_mgm(&mut self, geom: dGeomID, mi: Box<dyn MetaInf>) -> dVector4 {
let col = mi.get_tcm().col;
match self.mgms.entry(geom) { Entry::Occupied(mut oe) => {
let e = oe.get_mut();
println!("mgms {:?} already exists. skipped", geom); e
},
Entry::Vacant(ve) => { ve.insert(mi) }
};
col
}
pub fn reg_obg(&mut self, obg: Obg) -> dBodyID {
let id = obg.body();
let obgs: &mut HashMap<dBodyID, Obg> = &mut self.obgs;
let key = match obgs.entry(id) { Entry::Occupied(oe) => {
let k = oe.get().key.clone();
println!("obgs {:?}[{}] already exists. skipped", id, k); k
},
Entry::Vacant(ve) => { ve.insert(obg).key.clone() }
};
let mbgs: &mut BTreeMap<String, dBodyID> = &mut self.mbgs;
match mbgs.entry(key.clone()) { BTreeEntry::Occupied(mut oe) => {
let mut e = oe.get_mut();
println!("mbgs [{}] already exists. replaced", key); *e = id;
e
},
BTreeEntry::Vacant(ve) => { ve.insert(id) }
};
let vbgs: &mut VecDeque<dBodyID> = &mut self.vbgs;
vbgs.push_back(id);
self.modify();
id
}
pub fn creator_dm(&mut self, key: &str, mi: Box<dyn MetaInf>, fmdm: bool) ->
(dBodyID, dGeomID, Box<dMass>) {
let gws: &mut Gws = &mut self.gws;
let world: dWorldID = gws.world();
let space: dSpaceID = if key == "" { 0 as dSpaceID } else { gws.space() };
let body: dBodyID;
let geom: dGeomID;
let mut mass: Box<dMass> = Box::new(dMass::new());
unsafe {
geom = match mi.id() {
MetaId::Sphere => {
let ms = mi.as_sphere();
if fmdm {
dMassSetSphereTotal(&mut *mass, ms.dm, ms.r); }else{
dMassSetSphere(&mut *mass, ms.dm, ms.r);
}
dCreateSphere(space, ms.r)
},
MetaId::Box => {
let mb = mi.as_box();
if fmdm {
dMassSetBoxTotal(&mut *mass, mb.dm,
mb.lxyz[0], mb.lxyz[1], mb.lxyz[2]); }else{
dMassSetBox(&mut *mass, mb.dm, mb.lxyz[0], mb.lxyz[1], mb.lxyz[2]);
}
dCreateBox(space, mb.lxyz[0], mb.lxyz[1], mb.lxyz[2])
},
MetaId::Capsule => {
let mc = mi.as_capsule();
dMassSetCapsule(&mut *mass, mc.dm, 3, mc.r, mc.l);
dCreateCapsule(space, mc.r, mc.l)
},
MetaId::Cylinder => {
let mc = mi.as_cylinder();
dMassSetCylinder(&mut *mass, mc.dm, 3, mc.r, mc.l);
dCreateCylinder(space, mc.r, mc.l)
},
MetaId::Plane => {
let mp = mi.as_plane();
if fmdm {
dMassSetBoxTotal(&mut *mass, mp.dm,
mp.lxyz[0], mp.lxyz[1], mp.lxyz[2]); }else{
dMassSetBox(&mut *mass, mp.dm, mp.lxyz[0], mp.lxyz[1], mp.lxyz[2]);
}
dCreatePlane(space, mp.norm[0], mp.norm[1], mp.norm[2], mp.norm[3])
},
MetaId::Convex => {
let mc = mi.as_convex();
let g: dGeomID = CreateGeomConvexFromFVP(space, mc.fvp);
MassSetConvexAsTrimesh(&mut *mass, mc.dm, mc.fvp);
dGeomSetPosition(g, -mass.c[0], -mass.c[1], -mass.c[2]); dMassTranslate(&mut *mass, -mass.c[0], -mass.c[1], -mass.c[2]); g
},
MetaId::TriMesh => {
let mt = mi.as_trimesh();
let g: dGeomID = CreateGeomTrimeshFromVI(space, mt.tmv);
dMassSetTrimesh(&mut *mass, mt.dm, g);
dGeomSetPosition(g, -mass.c[0], -mass.c[1], -mass.c[2]); dMassTranslate(&mut *mass, -mass.c[0], -mass.c[1], -mass.c[2]); g
},
MetaId::Composite => {
panic!("use creator_composite for {:?}", mi.id());
},
_ => { panic!("creator not implemented for {:?}", mi.id()); }
};
}
let col = self.reg_mgm(geom, mi); (if key == "" {
0 as dBodyID
}else{
unsafe {
body = dBodyCreate(world);
dBodySetMass(body, &*mass);
dGeomSetBody(geom, body);
if !self.get_krp(geom).g { dBodyDisable(body); } }
let obg: Obg = Obg::new(key, body, geom, col);
self.reg_obg(obg)
}, geom, mass)
}
pub fn creator_m(&mut self, key: &str, mi: Box<dyn MetaInf>) ->
(dBodyID, dGeomID, Box<dMass>) {
self.creator_dm(key, mi, true)
}
pub fn creator(&mut self, key: &str, mi: Box<dyn MetaInf>) ->
(dBodyID, dGeomID, Box<dMass>) {
self.creator_dm(key, mi, false)
}
pub fn creator_composite(&mut self, key: &str, mi: Box<dyn MetaInf>) ->
(dBodyID, dGeomID, Box<dMass>) {
let gws: &mut Gws = &mut self.gws;
let world: dWorldID = gws.world();
let space: dSpaceID = gws.space();
let body: dBodyID;
let geom: dGeomID;
let mut mass: Box<dMass> = Box::new(dMass::new());
let mut gto: VecDeque<dGeomID> = vec![].try_into().unwrap(); let mut gts: HashMap<dGeomID, GeomOffset> = vec![].into_iter().collect();
unsafe {
body = dBodyCreate(world);
}
geom = match mi.id() {
MetaId::Composite => {
let mc = mi.as_composite();
unsafe {
for (j, emi) in mc.elems.iter().enumerate() {
let gtrans: dGeomID = dCreateGeomTransform(space);
dGeomTransformSetCleanup(gtrans, 1);
let (_, gsub, mut subm) = self.creator("", emi.dup());
dGeomTransformSetGeom(gtrans, gsub);
gto.push_front(gtrans); let o = &mc.ofs[j];
gts.entry(gtrans).or_insert_with(|| GeomOffset{gsub: gsub, o: o});
dGeomSetPosition(gsub, o[0], o[1], o[2]);
dMassTranslate(&mut *subm, o[0], o[1], o[2]);
let q = &mc.qs[j];
dGeomSetQuaternion(gsub, q.as_ptr() as *mut dReal);
dMassRotate(&mut *subm, dMatrix3::from_Q(*q).as_ptr() as *mut dReal);
dMassAdd(&mut *mass, &*subm);
self.rgts.entry(gsub).or_insert(gtrans); }
0 as dGeomID }
},
_ => { panic!("use creator for {:?}", mi.id()); }
};
unsafe {
for (gtrans, gso) in >s {
let o = gso.o;
dGeomSetPosition(gso.gsub, o[0]-mass.c[0], o[1]-mass.c[1], o[2]-mass.c[2]);
}
dMassTranslate(&mut *mass, -mass.c[0], -mass.c[1], -mass.c[2]);
dBodySetMass(body, &*mass); for gtrans in >o {
dGeomSetBody(*gtrans, body);
}
if !self.get_krp(gts[>o[0]].gsub).g { dBodyDisable(body); } }
gts.clear();
gto.clear();
let col = mi.get_tcm().col;
let obg: Obg = Obg::new(key, body, geom, col);
(self.reg_obg(obg), geom, mass)
}
pub fn get_grand_parent(&self, id: dGeomID) -> dBodyID {
unsafe {
let mut b: dBodyID = dGeomGetBody(id);
if b == 0 as dBodyID { b = dGeomGetBody(self.rgts[&id]); }
b
}
}
pub fn get_bounce(&self, id: dGeomID) -> dReal {
let gid: dGeomID = match unsafe { dGeomGetClass(id) } {
dGeomTransformClass => unsafe { dGeomTransformGetGeom(id) },
_ => id
}; match self.get_mgm(gid) {
Err(_) => KRP100.bounce, Ok(mgm) => mgm.get_krp().bounce
}
}
pub fn get_krp(&self, id: dGeomID) -> &Krp {
match self.get_mgm(id) {
Err(_) => &KRP100, Ok(mgm) => mgm.get_krp()
}
}
pub fn get_mgm_mut(&mut self, id: dGeomID) ->
Result<&mut Box<dyn MetaInf>, Box<dyn Error>> {
let mgms: &mut HashMap<dGeomID, Box<dyn MetaInf>> = &mut self.mgms;
Ok(mgms.get_mut(&id).ok_or(ODEError::no_mgm_id(id))?)
}
pub fn get_mgm(&self, id: dGeomID) ->
Result<&Box<dyn MetaInf>, Box<dyn Error>> {
let mgms: &HashMap<dGeomID, Box<dyn MetaInf>> = &self.mgms;
Ok(mgms.get(&id).ok_or(ODEError::no_mgm_id(id))?)
}
pub fn get_id(&self, k: String) -> Result<dBodyID, Box<dyn Error>> {
let mbgs: &BTreeMap<String, dBodyID> = &self.mbgs;
Ok(*mbgs.get(&k).ok_or(ODEError::no_key(k))?)
}
pub fn get_mut(&mut self, id: dBodyID) -> Result<&mut Obg, Box<dyn Error>> {
let obgs: &mut HashMap<dBodyID, Obg> = &mut self.obgs;
Ok(obgs.get_mut(&id).ok_or(ODEError::no_id(id))?)
}
pub fn find_mut(&mut self, k: String) -> Result<&mut Obg, Box<dyn Error>> {
let id: dBodyID = self.get_id(k)?;
self.get_mut(id)
}
pub fn get(&self, id: dBodyID) -> Result<&Obg, Box<dyn Error>> {
let obgs: &HashMap<dBodyID, Obg> = &self.obgs;
Ok(obgs.get(&id).ok_or(ODEError::no_id(id))?)
}
pub fn find(&self, k: String) -> Result<&Obg, Box<dyn Error>> {
let id: dBodyID = self.get_id(k)?;
self.get(id)
}
pub fn each_id(&self, la: fn(key: &str, id: dBodyID) -> bool) -> Vec<dBodyID> {
let mut r: Vec<dBodyID> = vec![];
for (k, v) in &self.mbgs {
r.push(if la(k, *v) { *v } else { 0 as dBodyID });
}
r
}
pub fn each(&self, la: fn(key: &str, id: dBodyID, obg: &Obg) -> bool) -> bool {
for (k, v) in &self.mbgs {
match self.get(*v) {
Err(e) => { println!("{}", e); }, Ok(obg) => { if !la(k, *v, obg) { return false; } }
}
}
true
}
pub fn destroy_obg(obg: &Obg) {
unsafe {
let mut geom: dGeomID = dBodyGetFirstGeom(obg.body());
while(geom != 0 as dGeomID){
let nextgeom: dGeomID = dBodyGetNextGeom(geom);
dGeomDestroy(geom);
geom = nextgeom;
}
dBodyDestroy(obg.body());
}
}
pub fn clear_obgs() {
unsafe {
let obgs: &HashMap<dBodyID, Obg> = &ode_get!(obgs);
for (id, obg) in obgs {
ODE::destroy_obg(obg); }
let obgs: &mut HashMap<dBodyID, Obg> = &mut ode_get_mut!(obgs);
obgs.clear();
let mbgs: &mut BTreeMap<String, dBodyID> = &mut ode_get_mut!(mbgs);
mbgs.clear();
let vbgs: &mut VecDeque<dBodyID> = &mut ode_get_mut!(vbgs);
vbgs.clear();
let mgms: &mut HashMap<dGeomID, Box<dyn MetaInf>> = &mut ode_get_mut!(mgms);
mgms.clear();
let rgts: &mut HashMap<dGeomID, dGeomID> = &mut ode_get_mut!(rgts);
rgts.clear();
let rode: &mut ODE = &mut ode_mut!();
rode.modify();
}
}
pub fn clear_contactgroup() {
unsafe {
let gws: &mut Gws = &mut ode_get_mut!(gws);
dJointGroupDestroy(gws.contactgroup());
gws.contactgroup_(dJointGroupCreate(0));
}
}
pub fn viewpoint_() {
unsafe {
let sw_viewpoint: &usize = &ode_get!(sw_viewpoint);
let cams: &mut BTreeMap<usize, Cam> = &mut ode_get_mut!(cams);
let cam = cams.get_mut(sw_viewpoint).unwrap(); let pos: &mut [f32] = &mut cam.pos;
let ypr: &mut [f32] = &mut cam.ypr;
dsSetViewpoint(pos as *mut [f32] as *mut f32, ypr as *mut [f32] as *mut f32);
}
}
pub fn viewpoint(f: bool) {
unsafe {
let p: &mut [f32] = &mut vec![0.0; 4];
let y: &mut [f32] = &mut vec![0.0; 4];
dsGetViewpoint(p as *mut [f32] as *mut f32, y as *mut [f32] as *mut f32);
let sw_viewpoint: &usize = &ode_get!(sw_viewpoint);
println!("viewpoint {} {:?}, {:?}", *sw_viewpoint, p, y);
match f {
true => {
let cams: &mut BTreeMap<usize, Cam> = &mut ode_get_mut!(cams);
let cam = cams.get_mut(sw_viewpoint).unwrap(); cam.pos = p.to_vec();
cam.ypr = y.to_vec();
},
_ => {}
}
}
}
pub fn sim_loop(
width: i32, height: i32,
r_sim: Option<Box<dyn Sim>>,
a: &[u8]) {
unsafe {
let sim: &mut Option<Box<dyn Sim>> = &mut ode_get_mut!(sim);
*sim = r_sim;
let ptt: &mut Option<U8zBuf> = &mut ode_get_mut!(ptt);
*ptt = Some(U8zBuf::from_u8array(a)); let mut dsfn: dsFunctions = dsFunctions{
version: DS_VERSION,
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()
};
let mut cab: CArgsBuf = CArgsBuf::from(&std::env::args().collect());
dsSimulationLoop(cab.as_argc(), cab.as_argv_ptr_mut(),
width, height, &mut dsfn);
}
}
} impl Drop for ODE {
fn drop(&mut self) {
unsafe { dCloseODE(); }
ostatln!("dropped ODE");
}
}
pub trait Sim {
fn super_mut(&mut self) -> &mut ODE {
unsafe {
&mut ode_mut!()
}
}
fn super_get(&self) -> &ODE {
unsafe {
&ode_!()
}
}
fn set_pos_R(&mut self, b: dBodyID, p: dVector3, m: dMatrix3) {
self.super_mut().get_mut(b).expect("no body").set_pos(p).set_rot(m);
}
fn set_pos_Q(&mut self, b: dBodyID, p: dVector3, q: dQuaternion) {
self.super_mut().get_mut(b).expect("no body").set_pos(p).set_quaternion(q);
}
fn draw_geom(&self, geom: dGeomID,
pos: Option<*const dReal>, rot: Option<*const dReal>, ws: i32);
fn draw_objects(&mut self);
fn start_callback(&mut self);
fn near_callback(&mut self, dat: *mut c_void, o1: dGeomID, o2: dGeomID);
fn step_callback(&mut self, pause: i32);
fn command_callback(&mut self, cmd: i32);
fn stop_callback(&mut self);
}
impl Sim for ODE {
fn draw_objects(&mut self) {
ostatln!("called default draw");
let wire_solid = self.wire_solid; let obgs = &self.obgs;
let vbgs = &self.vbgs;
for id in vbgs { let obg = &obgs[&id];
unsafe {
let mut g = dBodyGetFirstGeom(obg.body());
while g != 0 as dGeomID {
self.draw_geom(g, None, None, wire_solid);
g = dBodyGetNextGeom(g);
}
}
}
}
fn draw_geom(&self, geom: dGeomID,
pos: Option<*const dReal>, rot: Option<*const dReal>, ws: i32) {
if geom == 0 as dGeomID { return; }
unsafe {
let pos: *const dReal = pos.unwrap_or_else(|| dGeomGetPosition(geom));
let rot: *const dReal = rot.unwrap_or_else(|| dGeomGetRotation(geom));
let col: &dVector4 = match self.get_mgm(geom) {
Err(e) => {
let obg = self.get(dGeomGetBody(geom)).unwrap(); &obg.col
},
Ok(mgm) => {
let tcm = mgm.get_tcm();
dsSetTexture(tcm.tex);
&tcm.col
}
};
let c: Vec<f32> = col.into_iter().map(|v| *v as f32).collect();
dsSetColorAlpha(c[0], c[1], c[2], c[3]);
let cls = dGeomGetClass(geom);
match cls {
dSphereClass => {
let radius: dReal = dGeomSphereGetRadius(geom);
dsDrawSphereD(pos, rot, radius as f32);
},
dBoxClass => {
let mut lxyz: dVector3 = [0.0; 4];
dGeomBoxGetLengths(geom, lxyz.as_ptr_mut());
dsDrawBoxD(pos, rot, lxyz.as_ptr());
},
dCapsuleClass => {
let mut r: dReal = 0.0;
let mut l: dReal = 0.0;
dGeomCapsuleGetParams(geom, &mut r as *mut dReal, &mut l as *mut dReal);
dsDrawCapsuleD(pos, rot, l as f32, r as f32);
},
dCylinderClass => {
let mut r: dReal = 0.0;
let mut l: dReal = 0.0;
dGeomCylinderGetParams(geom, &mut r as *mut dReal, &mut l as *mut dReal);
dsDrawCylinderD(pos, rot, l as f32, r as f32);
},
dPlaneClass => {
let mut norm: dVector4 = [0.0; 4];
dGeomPlaneGetParams(geom, norm.as_ptr_mut());
let lxyz: dVector3 = [10.0, 10.0, 0.05, 0.0]; dsDrawBoxD(pos, rot, lxyz.as_ptr());
},
dRayClass => {
println!("not implemented class: {}", cls);
},
dConvexClass => {
match self.get_mgm(geom) {
Err(e) => { println!("not found convex {:?} geomID {:?}", e, geom); },
Ok(mgm) => {
let fvp: &convexfvp = &*mgm.as_convex().fvp;
dsDrawConvexD(pos, rot,
fvp.faces, fvp.faceCount, fvp.vtx, fvp.vtxCount, fvp.polygons);
}
}
},
dGeomTransformClass => {
let gt: dGeomID = dGeomTransformGetGeom(geom);
let gtpos: *const dReal = dGeomGetPosition(gt);
let gtrot: *const dReal = dGeomGetRotation(gt);
let mut rpos = dVector3::multiply0_331_pp(rot, gtpos);
let ppos = std::slice::from_raw_parts(pos, 4); for i in 0..4 { rpos[i] += ppos[i]; }
let rrot = dMatrix3::multiply0_333_pp(rot, gtrot);
self.draw_geom(gt, Some(rpos.as_ptr()), Some(rrot.as_ptr()), ws);
},
dTriMeshClass => {
match self.get_mgm(geom) {
Err(e) => { println!("not found trimesh {:?} geomID {:?}", e, geom); },
Ok(mgm) => {
let tmv: &trimeshvi = &*mgm.as_trimesh().tmv;
let vtx = tmv.as_slice_vtx();
let p = tmv.as_slice_indices();
for i in 0..p.len()/3 {
let idx = [p[i*3] as usize, p[i*3+1] as usize, p[i*3+2] as usize];
let v: [[dReal; 3]; 3] = [
[vtx[idx[0] * 3 + 0], vtx[idx[0] * 3 + 1], vtx[idx[0] * 3 + 2]],
[vtx[idx[1] * 3 + 0], vtx[idx[1] * 3 + 1], vtx[idx[1] * 3 + 2]],
[vtx[idx[2] * 3 + 0], vtx[idx[2] * 3 + 1], vtx[idx[2] * 3 + 2]]];
dsDrawTriangleD(pos, rot,
v[0].as_ptr(), v[1].as_ptr(), v[2].as_ptr(), ws);
}
}
}
},
dHeightfieldClass => {
println!("not implemented class: {}", cls);
},
_ => { println!("unknown class: {}", cls); }
}
}
}
fn start_callback(&mut self) {
ostatln!("called default start");
ODE::viewpoint_();
unsafe {
dsSetSphereQuality(3); dsSetCapsuleQuality(3); }
}
fn near_callback(&mut self, dat: *mut c_void, o1: dGeomID, o2: dGeomID) {
ostatln!("called default near");
let gws = &self.gws;
let world: dWorldID = gws.world();
let contactgroup: dJointGroupID = gws.contactgroup();
let ground: dGeomID = gws.ground();
unsafe {
if dGeomIsSpace(o1) != 0 || dGeomIsSpace(o2) != 0 {
dSpaceCollide2(o1, o2, dat, Some(c_near_callback));
if dGeomIsSpace(o1) != 0 {
dSpaceCollide(o1 as dSpaceID, dat, Some(c_near_callback));
}
if dGeomIsSpace(o2) != 0 {
dSpaceCollide(o2 as dSpaceID, dat, Some(c_near_callback));
}
return;
}
const num: usize = 40;
let contacts: &mut Vec<dContact> = &mut vec![dContact::new(); num];
let sz: i32 = std::mem::size_of::<dContact>() as i32;
let n: i32 = dCollide(o1, o2, num as i32, &mut contacts[0].geom, sz);
if ground == o1 || ground == o2 { let id: dGeomID = if ground == o1 { o2 } else { o1 };
let bounce: dReal = self.get_bounce(id);
for i in 0..n as usize {
let p: &mut dContact = &mut contacts[i];
p.surface.mode = dContactBounce | dContactSoftERP | dContactSoftCFM;
p.surface.bounce = bounce; p.surface.bounce_vel = 0.01; p.surface.mu = dInfinity; p.surface.soft_erp = 0.2;
p.surface.soft_cfm = 0.001;
let c: dJointID = dJointCreateContact(world, contactgroup, p);
dJointAttach(c, dGeomGetBody(o1), dGeomGetBody(o2));
}
}else{
let bounce: dReal = self.get_bounce(o1) * self.get_bounce(o2);
for i in 0..n as usize {
let p: &mut dContact = &mut contacts[i];
p.surface.mode = dContactBounce;
p.surface.bounce = bounce; p.surface.bounce_vel = 0.01; p.surface.mu = dInfinity; let c: dJointID = dJointCreateContact(world, contactgroup, p);
dJointAttach(c, dGeomGetBody(o1), dGeomGetBody(o2));
}
}
}
}
fn step_callback(&mut self, pause: i32) {
ostatln!("called default step");
let gws = &self.gws;
let t_delta = &self.t_delta;
if pause != 1 {
let mut tmp: HashMap<dBodyID, dVector3> = vec![].into_iter().collect();
for (id, mi) in &self.mgms {
if !mi.get_krp().k {
unsafe {
let b: dBodyID = self.get_grand_parent(*id);
tmp.entry(b).or_insert(*(dBodyGetPosition(b) as *const dVector3));
}
}
}
unsafe {
dSpaceCollide(gws.space(), 0 as *mut c_void, Some(c_near_callback));
dWorldStep(gws.world(), *t_delta);
dJointGroupEmpty(gws.contactgroup());
}
for (b, p) in &tmp {
unsafe {
dBodySetPosition(*b, p[0], p[1], p[2]);
}
}
}
ode_sim!(self, draw_objects)
}
fn command_callback(&mut self, cmd: i32) {
ostatln!("called default command");
match cmd as u8 as char {
'p' => {
unsafe {
let polyfill_wireframe: &mut i32 = &mut ode_get_mut!(polyfill_wireframe);
*polyfill_wireframe = 1 - *polyfill_wireframe;
dsSetDrawMode(*polyfill_wireframe);
}
},
'w' => {
unsafe {
let wire_solid: &mut i32 = &mut ode_get_mut!(wire_solid);
*wire_solid = 1 - *wire_solid;
}
},
'v' => {
ODE::viewpoint(false);
},
's' => {
ODE::viewpoint(true);
unsafe {
let sw_viewpoint: &mut usize = &mut ode_get_mut!(sw_viewpoint);
*sw_viewpoint = (*sw_viewpoint + 1) % self.cams.len();
}
ODE::viewpoint_();
ODE::viewpoint(false);
},
'r' => {
ODE::clear_obgs();
ODE::clear_contactgroup();
ode_sim!(self, start_callback)
},
_ => {}
}
}
fn stop_callback(&mut self) {
ostatln!("called default stop");
}
} unsafe extern "C"
fn c_start_callback() {
let rode: &mut ODE = &mut ode_mut!();
ode_sim!(rode, start_callback)
}
unsafe extern "C"
fn c_near_callback(dat: *mut c_void, o1: dGeomID, o2: dGeomID) {
let rode: &mut ODE = &mut ode_mut!();
ode_sim!(rode, near_callback, dat, o1, o2)
}
unsafe extern "C"
fn c_step_callback(pause: i32) {
let rode: &mut ODE = &mut ode_mut!();
ode_sim!(rode, step_callback, pause)
}
unsafe extern "C"
fn c_command_callback(cmd: i32) {
let rode: &mut ODE = &mut ode_mut!();
ode_sim!(rode, command_callback, cmd)
}
unsafe extern "C"
fn c_stop_callback() {
let rode: &mut ODE = &mut ode_mut!();
ode_sim!(rode, stop_callback)
}
#[macro_export]
macro_rules! ostat {
($($e:expr),+) => {};
}
pub use ostat;
#[macro_export]
macro_rules! ostatln {
($($e:expr),+) => {};
}
pub use ostatln;