comparison org/movement.org @ 180:f1b078375484

refactored movement
author Robert McIntyre <rlm@mit.edu>
date Sat, 04 Feb 2012 07:20:12 -0700
parents 2cbdd7034c6c
children 0f1c7921d967
comparison
equal deleted inserted replaced
179:11bd5f0625ad 180:f1b078375484
4 #+description: muscles for a simulated creature 4 #+description: muscles for a simulated creature
5 #+keywords: simulation, jMonkeyEngine3, clojure 5 #+keywords: simulation, jMonkeyEngine3, clojure
6 #+SETUPFILE: ../../aurellem/org/setup.org 6 #+SETUPFILE: ../../aurellem/org/setup.org
7 #+INCLUDE: ../../aurellem/org/level-0.org 7 #+INCLUDE: ../../aurellem/org/level-0.org
8 8
9
10 Surprisingly enough, terristerial creatures only move by using torque
11 applied about their joints. There's not a single straight line of
12 force in the human body at all! (A straight line of force would
13 correspond to some sort of jet or rocket propulseion.)
14
15
16 Here's how motor-control/ proprioception will work: Each muscle is
17 defined by a 1-D array of numbers (the "motor pool") each of which
18 represent muscle fibers. A muscle also has a scalar :strength factor
19 which determines how strong the muscle as a whole is. The effector
20 function for a muscle takes a number < (count motor-pool) and that
21 number is said to "activate" all the muscle fibers whose index is
22 lower than the number. Each fiber will apply force in proportion to
23 its value in the array. Lower values cause less force. The lower
24 values can be put at the "beginning" of the 1-D array to simulate the
25 layout of actual human muscles, which are capable of more percise
26 movements when exerting less force.
27
9 #+name: movement 28 #+name: movement
10 #+begin_src clojure 29 #+begin_src clojure
11 (ns cortex.movement 30 (ns cortex.movement
31 "Give simulated creatures defined in special blender files the power
32 to move around in a simulated environment."
33 {:author "Robert McIntyre"}
12 (:use (cortex world util sense body)) 34 (:use (cortex world util sense body))
13 (:import jme3tools.converters.ImageToAwt) 35 (:use clojure.contrib.def)
14 (:import java.awt.image.BufferedImage)) 36 (:import java.awt.image.BufferedImage)
37 (:import com.jme3.scene.Node)
38 (:import com.jme3.math.Vector3f)
39 (:import com.jme3.bullet.control.RigidBodyControl))
15 40
16 (cortex.import/mega-import-jme3) 41 (defn muscle-profile
17 42 "Return a vector where each entry is the strength of the \"motor
18 ;; here's how motor-control/ proprioception will work: Each muscle is 43 pool\" at that part in the muscle."
19 ;; defined by a 1-D array of numbers (the "motor pool") each of which 44 [#^BufferedImage profile]
20 ;; represent muscle fibers. A muscle also has a scalar :strength
21 ;; factor which determines how strong the muscle as a whole is.
22 ;; The effector function for a muscle takes a number < (count
23 ;; motor-pool) and that number is said to "activate" all the muscle
24 ;; fibers whose index is lower than the number. Each fiber will apply
25 ;; force in proportion to its value in the array. Lower values cause
26 ;; less force. The lower values can be put at the "beginning" of the
27 ;; 1-D array to simulate the layout of actual human muscles, which are
28 ;; capable of more percise movements when exerting less force.
29
30 (defn muscle-fiber-values
31 "get motor pool strengths"
32 [#^BufferedImage image]
33 (vec 45 (vec
34 (let [width (.getWidth image)] 46 (let [width (.getWidth profile)]
35 (for [x (range width)] 47 (for [x (range width)]
36 (- 255 48 (- 255
37 (bit-and 49 (bit-and
38 0x0000FF 50 0x0000FF
39 (.getRGB image x 0))))))) 51 (.getRGB profile x 0)))))))
40 52
41 (defn creature-muscles 53 (defvar
42 "Return the children of the creature's \"muscles\" node." 54 ^{:arglists '([creature])}
43 [#^Node creature] 55 muscles
44 (if-let [muscle-node (.getChild creature "muscles")] 56 (sense-nodes "muscles")
45 (seq (.getChildren muscle-node)) 57 "Return the children of the creature's \"muscles\" node.")
46 (do (println-repl "could not find muscles node") [])))
47 58
48 (defn single-muscle [#^Node parts #^Node muscle] 59 (defn movement-fn
60 "Returns a function which when called with a integer value inside a
61 running simulation, will cause movement in the creature according
62 to the muscle's position and strength profile"
63 [#^Node parts #^Node muscle]
49 (let [target (closest-node parts muscle) 64 (let [target (closest-node parts muscle)
50 axis 65 axis
51 (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y) 66 (.mult (.getWorldRotation muscle) Vector3f/UNIT_Y)
52 strength (meta-data muscle "strength") 67 strength (meta-data muscle "strength")
53 image-name (read-string (meta-data muscle "muscle")) 68 image-name (read-string (meta-data muscle "muscle"))
54 image 69 image (load-image image-name)
55 (ImageToAwt/convert 70 fibers (muscle-profile image)
56 (.getImage (.loadTexture (asset-manager) image-name))
57 false false 0)
58 fibers (muscle-fiber-values image)
59 fiber-integral (reductions + fibers) 71 fiber-integral (reductions + fibers)
60 force-index (vec 72 force-index (vec
61 (map 73 (map
62 #(float (* strength (/ % (last 74 #(float (* strength (/ % (last
63 fiber-integral)))) 75 fiber-integral))))
65 control (.getControl target RigidBodyControl)] 77 control (.getControl target RigidBodyControl)]
66 (fn [n] 78 (fn [n]
67 (let [pool-index (min n (count fibers))] 79 (let [pool-index (min n (count fibers))]
68 (.applyTorque control (.mult axis (force-index n))))))) 80 (.applyTorque control (.mult axis (force-index n)))))))
69 81
70 82 (defn movement!
71 (defn enable-muscles 83 "Endow the creature with the power of movement. Returns a sequence
72 "Must be called on a creature after RigidBodyControls have been 84 of functions, each of which accept an integer value and will
73 created." 85 activate their corresponding muscle."
74 [#^Node creature] 86 [#^Node creature]
75 (let [muscles (creature-muscles creature)] 87 (for [muscle (muscles creature)]
76 (for [muscle muscles] 88 (movement-fn creature muscle)))
77 (single-muscle creature muscle))))
78 89
79 90
80 #+end_src 91 #+end_src
81 92
82 93