Mercurial > cortex
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 |