[ODE] dBodyAddForce / dBodyAddTorque don't do anything!

Patrick McColgan patrick at torcinteractive.com
Tue Jun 21 16:49:39 MST 2005


If you have auto-disabling the body may have been disabled and hence not 
updated.

You may want to check it with dBodyIsEnabled, and if its the case 
explicitly enable it with dBodyEnable each time you add a force or a torque.


Richard Jones wrote:

>Hi:
>
>I'm doing some bindings for ODE to the Objective CAML language.
>
>As part of these bindings, I'm doing a simple wireframe-only
>"roll-em-up" game (think Katamari Damashii for those familiar with
>that game), which will just form an example for how to use the
>library.
>
>So far it's going quite well - the ball falls down, bounces off
>scenery and so on.  However I cannot get dBodyAddForce,
>dBodyAddTorque, dBodyAddRelForce or dBodyAddRelTorque to do anything
>at all.  Even when I set the fx/fy/fz to wild numbers, the ball isn't
>affected.  I've added debugging print statements to the low level
>bindings which prove that the C function actually gets called and with
>the right parameters.
>
>It seems unlikely that dBodyAddForce, etc. are actually broken.  So
>can anyone suggest what I'm doing wrong?
>
>Rich.
>
>----------------------------------------------------------------------
>(* Toy wireframe version of Katamari Damashii.
> * Copyright (C) 2005 Richard W.M. Jones <rich at annexia.org>
> * $Id$
> *
> * This program is free software; you can redistribute it and/or modify
> * it under the terms of the GNU General Public License as published by
> * the Free Software Foundation; either version 2 of the License, or
> * (at your option) any later version.
> *
> * This program is distributed in the hope that it will be useful,
> * but WITHOUT ANY WARRANTY; without even the implied warranty of
> * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> * GNU General Public License for more details.
> *
> * You should have received a copy of the GNU General Public License
> * along with this program; if not, write to the Free Software
> * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
> *)
>
>open Printf
>
>open ExtList
>
>open Ode.LowLevel
>
>let width, height = 640, 480
>
>(* Stepsize for physics (in secs). *)
>let stepsize = 0.005
>
>(* Real time / Physics time.  If set to 1., then physics proceeds at the
> * same pace as real time.  If > 1, then physics is slowed down.
> *)
>let timescale = 4.
>
>let initial = 0., 0., 1.		(* Initial position for katamari. *)
>
>let eye = ref (0., -2., 1.)		(* Camera location. *)
>let up = ref (0., 1., 2.)		(* Up vector. *)
>let center = ref (0., 0., 0.5)		(* Center of camera. *)
>
>let init_gl () =
>  GlDraw.viewport ~x:0 ~y:0 ~w:width ~h:height;
>  GlClear.color (0.9375, 0., 1.);
>  GlClear.depth 1.0;
>  GlFunc.depth_func `less;
>  Gl.enable `depth_test;
>  GlDraw.shade_model `smooth;
>  GlMat.mode `projection;
>  GlMat.load_identity ();
>  GluMat.perspective ~fovy:45. ~aspect:(float width /. float height)
>    ~z:(0.1, 100.);
>  GlMat.mode `modelview
>
>let draw_scene kata boxes =
>  GlClear.clear [ `color; `depth ];
>
>  (* Camera. *)
>  GlMat.load_identity ();
>  GluMat.look_at ~eye:!eye ~center:!center ~up:!up;
>
>  (* Katamari. *)
>  GlMat.push ();
>  let x, y, z = dGeomGetPosition kata in
>  let r = dGeomGetRotation kata in
>  let matrix = [|
>    [| r.r11; r.r21; r.r31; 0. |];
>    [| r.r12; r.r22; r.r32; 0. |];
>    [| r.r13; r.r23; r.r33; 0. |];
>    [| x; y; z; 1. |]
>  |] in
>  GlMat.mult (GlMat.of_array matrix);
>  let radius = dGeomSphereGetRadius kata in
>  Glut.wireSphere ~radius ~slices:10 ~stacks:10;
>  GlMat.pop ();
>
>  (* Boxes. *)
>  let draw_box box =
>    GlMat.push ();
>    let x, y, z = dGeomGetPosition box in
>    GlMat.translate ~x ~y ~z ();
>    let lx, ly, lz = dGeomBoxGetLengths box in
>    GlMat.scale ~x:lx ~y:ly ~z:lz ();
>    Glut.wireCube ~size:1.;
>    GlMat.pop ();
>  in
>  Array.iter draw_box boxes;
>
>  Sdlgl.swap_buffers ()
>
>(* Surface parameters used for all contact points. *)
>let surface_params = {
>  sp_mode = [`dContactBounce];
>  sp_mu = dInfinity; sp_mu2 = 0.;
>  sp_bounce = 0.7; sp_bounce_vel = 0.1;
>  sp_soft_erp = 0.; sp_soft_cfm = 0.;
>  sp_motion1 = 0.; sp_motion2 = 0.;
>  sp_slip1 = 0.; sp_slip2 = 0.;
>}
>
>let main () =
>  Random.self_init ();
>
>  (* Initialise SDL. *)
>  Sdl.init [`VIDEO];
>  Sdlgl.set_attr [];
>  let surface = Sdlvideo.set_video_mode ~w:width ~h:height ~bpp:32 [`OPENGL] in
>
>  (* Create the ODE world. *)
>  let ode = dWorldCreate () in
>  dWorldSetGravity ode ~x:0. ~y:0. ~z:(-9.81);
>
>  (* Create the objects in the world. *)
>  let space = dHashSpaceCreate None in
>  dHashSpaceSetLevels space (-4) 4; (* 1/16 .. 16 units. *)
>
>  (* The ground plane goes through the world origin, with the normal
>   * facing upwards towards +z.
>   *)
>  let plane = dCreatePlane (Some space) ~a:0. ~b:0. ~c:1. ~d:0. in
>
>  (* Create the katamari. *)
>  let kata, kata_body =
>    let radius = 0.5 in
>    let body = dBodyCreate ode in
>    dBodySetAutoDisableFlag body false;
>    let mass = dMassCreate () in
>    dMassSetZero mass;
>    dMassSetSphereTotal mass ~total_mass:1. ~radius;
>    dBodySetMass body mass;
>    dMassDestroy mass;
>    let kata = dCreateSphere (Some space) ~radius in
>    dGeomSetBody kata body;
>    let x, y, z = initial in
>    dGeomSetPosition kata ~x ~y ~z;
>    kata, body in
>
>  (* Scatter boxes around. *)
>  let boxes =
>    let create_box i =
>      let lx, ly, lz = Random.float 0.5, Random.float 0.5, Random.float 0.5 in
>      let box = dCreateBox (Some space) ~lx ~ly ~lz in
>      let x, y, z = Random.float 10. -. 5., Random.float 10. -. 5., lz/.2. in
>      dGeomSetPosition box ~x ~y ~z;
>      box
>    in
>    Array.init 20 (fun i -> create_box i) in
>
>  (* A group to hold the contact joints. *)
>  let contact_joint_group = dJointGroupCreate () in
>
>  (* Initialise GL state. *)
>  init_gl ();
>
>  (* Current key state. *)
>  let key_forward = ref false in
>  let key_backward = ref false in
>  let key_left = ref false in
>  let key_right = ref false in
>
>  (* Start the clocks counting. *)
>  let current_time =
>    let base = Unix.gettimeofday () in
>    fun () ->
>      Unix.gettimeofday () -. base
>  in
>
>  (* "Physics time" starts off coincident with real time. *)
>  let physics_time = ref 0. in
>
>  let rec main_loop () =
>    (* Draw it. *)
>    draw_scene kata boxes;
>
>    (* Act on events. *)
>    let quit = ref false in
>    let rec read_events () =
>      match Sdlevent.poll () with
>	| None -> ()
>	| Some event -> do_event event; read_events ()
>    and do_event = function
>      | Sdlevent.QUIT -> quit := true (* window closed: quit *)
>      | Sdlevent.KEYDOWN ke ->
>	  (match ke.Sdlevent.keysym with
>	     | Sdlkey.KEY_ESCAPE -> quit := true (* escape key: quit *)
>	     | Sdlkey.KEY_UP -> key_forward := true
>	     | Sdlkey.KEY_DOWN -> key_backward := true
>	     | Sdlkey.KEY_LEFT -> key_left := true
>	     | Sdlkey.KEY_RIGHT -> key_right := true
>	     | _ -> read_events () (* ignore this key *)
>	  )
>      | Sdlevent.KEYUP ke ->
>	  (match ke.Sdlevent.keysym with
>	     | Sdlkey.KEY_UP -> key_forward := false
>	     | Sdlkey.KEY_DOWN -> key_backward := false
>	     | Sdlkey.KEY_LEFT -> key_left := false
>	     | Sdlkey.KEY_RIGHT -> key_right := false
>	     | _ -> read_events () (* ignore this key *)
>	  )
>      | _ -> () (* ignore this event *)
>    in
>    read_events ();
>    let quit = !quit in
>
>    (* Run the physics loop until we catch up with real time. *)
>    let rec physics_loop to_time =
>      if timescale *. !physics_time < to_time then (
>	let nr_contacts = ref 0 in
>
>	(* Accumulate forces on the katamari according to the current
>	 * key states.
>	 *)
>	if !key_forward then
>	  dBodyAddTorque kata_body ~fx:0. ~fy:1. ~fz:0.;
>	if !key_backward then
>	  dBodyAddTorque kata_body ~fx:0. ~fy:(-0.7) ~fz:0.;
>
>	(* Collision detection. *)
>	let near geom1 geom2 =
>	  (* geom1 and geom2 are close.  Test if they collide. *)
>	  let contacts = dCollide geom1 geom2 ~max:4 in
>
>	  if Array.length contacts > 0 then (
>	    (* Get the bodies, if any. *)
>	    let body1 = dGeomGetBody geom1 in
>	    let body2 = dGeomGetBody geom2 in
>
>	    (* For each collision, create a contact joint. *)
>	    Array.iter (
>	      fun contact_geom ->
>		incr nr_contacts;
>
>		(* Create the contact joint. *)
>		let contact = {
>		  c_surface = surface_params;
>		  c_geom = contact_geom;
>		  c_fdir1 = { x = 0.; y = 0.; z = 0. }
>		} in
>		let joint =
>		  dJointCreateContact ode (Some contact_joint_group) contact in
>
>		(* Attach that joint to the two bodies.  The bodies may be
>		 * 'None' indicating a collision with the static world, but
>		 * that's OK.
>		 *)
>		dJointAttach joint body1 body2
>	    ) contacts
>	  )
>	in
>	dSpaceCollide space near;
>
>	(* Take a simulation step. *)
>	dWorldQuickStep ode stepsize;
>	physics_time := !physics_time +. stepsize;
>
>	(* Remove and destroy the contact joints. *)
>	dJointGroupEmpty contact_joint_group;
>
>	physics_loop to_time
>      )
>    in
>    physics_loop (current_time ());
>
>    (* Run the garbage collector at a predictable point. *)
>    Gc.full_major ();
>
>    (* Loop unless user has quit. *)
>    if not quit then main_loop ()
>  in
>  main_loop ();
>
>  (* Clean up the world. *)
>  dGeomDestroy plane;
>  dSpaceDestroy space;
>
>  (* Destroy the ODE world and clean up. *)
>  dWorldDestroy ode;
>  dCloseODE ();
>
>  (* Quit SDL. *)
>  Sdl.quit ();
>
>  (* Find any memory allocation bugs. *)
>  Gc.full_major ()
>
>let () =
>  main ()
>
>
>  
>



More information about the ODE mailing list