# HG changeset patch # User Robert McIntyre # Date 1328365212 25200 # Node ID f1b078375484d799ae6bf51e22843c9a47873b10 # Parent 11bd5f0625ad8454b66cb02a7e7ef040665b6b1a refactored movement diff -r 11bd5f0625ad -r f1b078375484 org/movement.org --- a/org/movement.org Sat Feb 04 07:09:40 2012 -0700 +++ b/org/movement.org Sat Feb 04 07:20:12 2012 -0700 @@ -6,56 +6,68 @@ #+SETUPFILE: ../../aurellem/org/setup.org #+INCLUDE: ../../aurellem/org/level-0.org + +Surprisingly enough, terristerial creatures only move by using torque +applied about their joints. There's not a single straight line of +force in the human body at all! (A straight line of force would +correspond to some sort of jet or rocket propulseion.) + + +Here's how motor-control/ proprioception will work: Each muscle is +defined by a 1-D array of numbers (the "motor pool") each of which +represent muscle fibers. A muscle also has a scalar :strength factor +which determines how strong the muscle as a whole is. The effector +function for a muscle takes a number < (count motor-pool) and that +number is said to "activate" all the muscle fibers whose index is +lower than the number. Each fiber will apply force in proportion to +its value in the array. Lower values cause less force. The lower +values can be put at the "beginning" of the 1-D array to simulate the +layout of actual human muscles, which are capable of more percise +movements when exerting less force. + #+name: movement #+begin_src clojure (ns cortex.movement + "Give simulated creatures defined in special blender files the power + to move around in a simulated environment." + {:author "Robert McIntyre"} (:use (cortex world util sense body)) - (:import jme3tools.converters.ImageToAwt) - (:import java.awt.image.BufferedImage)) + (:use clojure.contrib.def) + (:import java.awt.image.BufferedImage) + (:import com.jme3.scene.Node) + (:import com.jme3.math.Vector3f) + (:import com.jme3.bullet.control.RigidBodyControl)) -(cortex.import/mega-import-jme3) - -;; here's how motor-control/ proprioception will work: Each muscle is -;; defined by a 1-D array of numbers (the "motor pool") each of which -;; represent muscle fibers. A muscle also has a scalar :strength -;; factor which determines how strong the muscle as a whole is. -;; The effector function for a muscle takes a number < (count -;; motor-pool) and that number is said to "activate" all the muscle -;; fibers whose index is lower than the number. Each fiber will apply -;; force in proportion to its value in the array. Lower values cause -;; less force. The lower values can be put at the "beginning" of the -;; 1-D array to simulate the layout of actual human muscles, which are -;; capable of more percise movements when exerting less force. - -(defn muscle-fiber-values - "get motor pool strengths" - [#^BufferedImage image] +(defn muscle-profile + "Return a vector where each entry is the strength of the \"motor + pool\" at that part in the muscle." + [#^BufferedImage profile] (vec - (let [width (.getWidth image)] + (let [width (.getWidth profile)] (for [x (range width)] (- 255 (bit-and 0x0000FF - (.getRGB image x 0))))))) + (.getRGB profile x 0))))))) -(defn creature-muscles - "Return the children of the creature's \"muscles\" node." - [#^Node creature] - (if-let [muscle-node (.getChild creature "muscles")] - (seq (.getChildren muscle-node)) - (do (println-repl "could not find muscles node") []))) +(defvar + ^{:arglists '([creature])} + muscles + (sense-nodes "muscles") + "Return the children of the creature's \"muscles\" node.") -(defn single-muscle [#^Node parts #^Node muscle] +(defn movement-fn + "Returns a function which when called with a integer value inside a + running simulation, will cause movement in the creature according + to the muscle's position and strength profile" + [#^Node parts #^Node muscle] (let [target (closest-node parts muscle) axis (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y) strength (meta-data muscle "strength") image-name (read-string (meta-data muscle "muscle")) - image - (ImageToAwt/convert - (.getImage (.loadTexture (asset-manager) image-name)) - false false 0) - fibers (muscle-fiber-values image) + image (load-image image-name) + fibers (muscle-profile image) fiber-integral (reductions + fibers) force-index (vec (map @@ -67,14 +79,13 @@ (let [pool-index (min n (count fibers))] (.applyTorque control (.mult axis (force-index n))))))) - -(defn enable-muscles - "Must be called on a creature after RigidBodyControls have been - created." +(defn movement! + "Endow the creature with the power of movement. Returns a sequence + of functions, each of which accept an integer value and will + activate their corresponding muscle." [#^Node creature] - (let [muscles (creature-muscles creature)] - (for [muscle muscles] - (single-muscle creature muscle)))) + (for [muscle (muscles creature)] + (movement-fn creature muscle))) #+end_src diff -r 11bd5f0625ad -r f1b078375484 org/test-creature.org --- a/org/test-creature.org Sat Feb 04 07:09:40 2012 -0700 +++ b/org/test-creature.org Sat Feb 04 07:20:12 2012 -0700 @@ -185,7 +185,7 @@ prop (proprioception! creature) prop-debug (proprioception-debug-window) - muscle-fns (enable-muscles creature) + muscle-fns (movement! creature) ;; dream fix-display (runonce (fn [world] (add-camera! world (.getCamera world) no-op)))