[squeak-dev] Re: Cleaning up SqueakMap

Squeak List squeaklist at yahoo.com
Sat May 15 09:32:00 UTC 2010


Sean,

"Sure we'd like to know how to load it :)"... 

well, i spelled out exactly what i did in a message 2 the group.

and, it bounced back:

"
Your mail to 'Squeak-dev' with the subject
    Re: [squeak-dev] Re: Cleaning up SqueakMap
Is being held until the list moderator can review it for approval.
The reason it is being held:
    Message body is too big: 131288 bytes with a limit of 100 KB
"

which is (maybe) because i found the Avatar.cs.gz code and i attached it to the email. and i also attached a .txt version. yahoo mail says it is under 100kb... 

yet, it "bounces back"...

"Message body is too big: 131288 bytes with a limit of 100 KB" .... uh....???? whatever...

+++++++

ok, so here is the same thing minus the  Avatar.cs.gz file: i will try with only the "text version" of  Avatar.cs.gz attached... :

Sean,

this is what i did on an amd dual processor machine running windows vista 32 bit:


From Scratch:

1)setup/install fresh Squeak 4.1.

2) tell it to update via trunk. 

3) update - to update number: 10145 (2nite).

(btw, sidenote: updating a fresh install leaves what looks like a "rectangle just sitting there with no indication what it is"... but it is a a SystemProgressMorph... and i just delete it. but is that intentional, that there is "a blank white rectangle just sitting there with no indication what it is" after updating? i am guessing that it is not...)

4) purge undo records and collect garbage.

5) save and quit squeak - rename if desired...

6) download: http://wiki.squeak.org/squeak/uploads/651/Speech.sar ---- AS A .ZIP FILE. which happens automatically in my Windows Vista/IE8 system... 
this isnt really important if you are familiar/comfortable working with .sar files, but it is how i got this to work 1st :) ---- download it into the same directory as where the freshly updated 4.1 Squeak is.

7) extract Speech.zip into the same folder that contains the squeak image, sources, etc... it will add 7 new .st files...

8) re-open the freshly updated squeak and open FileList.

9) highlight and "Install" 

IN THIS ORDER:

Speech-TTS.st

(which again leaves what looks like a "rectangle just sitting there with no indication what it is"... same as above... just move it out of the way or delete it... same for below...)

Speech-Support.st

Speech-Phonetics.st

Speech-Phoneme Recognizer.st

Speech-Events.st

Speech-Gestures.st

Speech-Klatt.st

10) close FileList (and any remaining "rectangle(s) just sitting there with no indication what it is"...)...

11) purge undo records and collect garbage.

12) open a workspace and DO IT:   

Speaker manWithHead say: 'this code is ancient'

or for "closer to the avatar look" link below: 

Speaker manWithEditor say: 'this looks more like the avatar link below'

check out the "test" and "new head" buttons...

13) in Browser, check out the Category:Speech-TTS / Class: Speaker / Class side "examples" and "examples-others"... or whatever else may be of interest :)

--- 

i found the following, but do not remember ever seeing it in squeak (it, the link and images, reminds me of JUN):
http://translate.googleusercontent.com/translate_c?hl=en&sl=ja&u=http://languagegame.org:8888/zoo/160.version%3Fid%3D116&prev=/search%3Fq%3DAvatarBuilder%2Bnew%2BopenInWorld%26hl%3Den%26sa%3DG&rurl=translate.google.com&usg=ALkJrhj5aBZ8N0sXMcEJapxwWGgi6MDnfw

1 - 13 above are more like South Park faces - imo...

---

re: 6 and 7 above, that was just the quickest way for "me" to get it to work.

actually, all of it was the quickest way for "me" to get it to work...

and this .sar is on squeakmap (under "Speech") - but it will not install correctly unless you do something similar to the above.

however, i am impressed that the examples work in 4.1 without altering the actual code. 

yes, it seems that squeakmap will not install it correctly from what i have seen so far... and i did not find any tutorial that walked me through how to install code which i could not predict would work in the latest and greatest (4.1)... also, i have not made or ran any tests beyond the above: my only tests of interest were the above 2 examples. i like it very much when "examples" actually work. 

if you look in the "install" folder (in the same directory as the fresh squeak install - if you did as above), and open up the "preamble": it does not even show all 7 classes... and i was using these Classes/code before 2003 - more like 2001 when i found them interesting and useful... i have no idea who: [ 3/19/2003 bkv ] is... but it (the SPEECH Classes and their "south park style") was working very well before 2003 (more like 2001 when i was using this) - which is interesting, since the attached avatar code begins with:
"
From Squeak3.2alpha of 10 October 2001 [latest update: #4599] on 21 December 2001 at 3:00:40 pm ....
"
- yet, at least from the tiny bit i have checked  is working in 2010.
---

i found: Avatar.cs.gz  - and am attaching it (and a text version).   

not particularly interested in trying to figure out what "its" install problems are ATM :) 



that's it for now.

ken


      
-------------- next part --------------
'From Squeak3.2alpha of 10 October 2001 [latest update: #4599] on 21 December 2001 at 3:00:40 pm'!
"Change Set:		Avatar
Date:			21 December 2001
Author:			Luciano

This change set contains an animated face based on Waters' muscle model. Each avatar has a set of control parameters for facial muscles, eyeballs, eyelids, and mouth.
Try:
	AvatarBuilder new openInWorld
"!

Object subclass: #Avatar
	instanceVariableNames: 'muscles jaw leftEye rightEye '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Kernel'!

!Avatar commentStamp: '<historical>' prior: 0!
My instances are 3D avatars based on the Waters' muscle model. Each avatar has a set of control parameters for facial muscles, eyeballs, eyelids, and mouth.

[1] Waters, K. "A muscle model for animating three-dimensional facial expression.", IEEE Computer Graphics, 21(4)!

Object subclass: #AvatarBuilder
	instanceVariableNames: 'avatar vertices faces faceMesh leftEyeballMesh rightEyeballMesh eyeballTexture '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Kernel'!
AvatarBuilder class
	instanceVariableNames: ''!
AlignmentMorph subclass: #AvatarControlMorph
	instanceVariableNames: 'avatar head scene left right '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Support'!
Object subclass: #Eye
	instanceVariableNames: 'mesh center rotation upperEyelid lowerEyelid '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Kernel'!
Eye class
	instanceVariableNames: ''!
Object subclass: #Eyelid
	instanceVariableNames: 'mesh indices angle direction '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Kernel'!
Eyelid class
	instanceVariableNames: ''!
Morph subclass: #Head3DMorph
	instanceVariableNames: 'scene head queue '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Support'!
Head3DMorph class
	instanceVariableNames: ''!
Object subclass: #Jaw
	instanceVariableNames: 'mesh indices angle '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Kernel'!
Jaw class
	instanceVariableNames: ''!
Object subclass: #Muscle
	instanceVariableNames: 'mesh name head tail zone start end clamp contraction indices directions '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Kernel'!

!Muscle commentStamp: '<historical>' prior: 0!
My instances model facial muscles that deform a B3DIndexedMesh.!

Muscle class
	instanceVariableNames: ''!
Object subclass: #SphincterMuscle
	instanceVariableNames: 'name center axis1 axis2 axis3 zone contraction indices directions '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Kernel'!
SphincterMuscle class
	instanceVariableNames: ''!
SimpleSliderMorph subclass: #UpdatingSimpleSliderMorph
	instanceVariableNames: 'getValueSelector '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Support'!
Object subclass: #Viseme
	instanceVariableNames: 'contractions '
	classVariableNames: ''
	poolDictionaries: ''
	category: 'Avatars-Kernel'!
Viseme class
	instanceVariableNames: ''!

!AdvancedB3DSceneMorph methodsFor: 'accessing' stamp: 'len 1/15/2001 21:43'!
scene: aScene
	super scene: ("self updateSceneWithDefaults:" aScene).
	self updateUpVectorForCamera: self scene defaultCamera.
	self updateHeadlight.
	self changed! !

!AdvancedB3DSceneMorph methodsFor: 'private' stamp: 'len 1/15/2001 21:32'!
updateSceneWithDefaults: myScene
	| headLight mat |
	myScene lights at: 'Ambient1' put: (B3DAmbientLight color: (Color gray: 0.2)).
	headLight := B3DSpotLight new.
	headLight position: myScene defaultCamera position.
	headLight target: myScene defaultCamera target.
	headLight lightColor: (B3DMaterialColor color: (Color gray: 0.7)).
	headLight attenuation: (B3DLightAttenuation constant: 1.0 linear: 0.0 squared: 0.0).
	headLight minAngle: 80.
	headLight maxAngle: 90.
	myScene lights at: '$HeadLight$' put: headLight copy.
	mat := B3DMaterial new.
	mat diffusePart: (Color gray: 0.25).
	mat ambientPart: (Color gray: 0.01).
	myScene objects do: [:o|
		o material: mat].
	^myScene! !


!Avatar methodsFor: 'accessing' stamp: 'len 9/11/1999 03:41'!
jaw
	^ jaw! !

!Avatar methodsFor: 'accessing' stamp: 'len 1/29/2001 11:49'!
jaw: aJaw
	jaw _ aJaw! !

!Avatar methodsFor: 'accessing' stamp: 'len 2/27/2000 21:36'!
leftEye
	^ leftEye! !

!Avatar methodsFor: 'accessing' stamp: 'len 1/29/2001 11:49'!
leftEye: anEye
	leftEye _ anEye! !

!Avatar methodsFor: 'accessing' stamp: 'len 1/29/2001 12:00'!
muscles
	^ muscles! !

!Avatar methodsFor: 'accessing' stamp: 'len 1/29/2001 12:00'!
muscles: aCollection
	muscles _ aCollection! !

!Avatar methodsFor: 'accessing' stamp: 'len 2/27/2000 21:36'!
rightEye
	^ rightEye! !

!Avatar methodsFor: 'accessing' stamp: 'len 1/30/2001 17:01'!
rightEye: anEye
	rightEye _ anEye! !

!Avatar methodsFor: 'actions' stamp: 'len 1/29/2001 12:31'!
relax
	jaw relax.
	self muscles do: [ :each | each relax]! !


!AvatarBuilder methodsFor: 'initialization' stamp: 'len 1/13/2001 04:00'!
initialize
	self initializeVertices.
	self initializeFaces! !

!AvatarBuilder methodsFor: 'initialization' stamp: 'len 1/13/2001 18:37'!
initializeFaces
	| facesStream p1 p2 p3 p4 half |

	facesStream _ WriteStream on: (B3DIndexedTriangleArray new: self facesData size).

	half _ vertices size // 2.

	"Read in the faces"
	self facesData do: [ :words |
		p1 _ words at: 1.
		p2 _ words at: 2.
		p3 _ words at: 3.
		p4 _ words at: 4.
		p1 = 1000
			ifTrue: [facesStream
						nextPut: (B3DIndexedTriangle with: p2 with: p3 with: p4);
						nextPut: (B3DIndexedTriangle with: p3+half with: p2+half with: p4+half)]
			ifFalse: [facesStream
						nextPut: (B3DIndexedTriangle with: p1 with: p2 with: p3);
						nextPut: (B3DIndexedTriangle with: p2+half with: p1+half with: p3+half);
						nextPut: (B3DIndexedTriangle with: p1 with: p3 with: p4);
						nextPut: (B3DIndexedTriangle with: p3+half with: p1+half with: p4+half)]].

	"Create the faces array"
	faces _ facesStream contents! !

!AvatarBuilder methodsFor: 'initialization' stamp: 'len 1/13/2001 18:37'!
initializeVertices
	| count entry |
	count _ self halfVerticesData size.
	vertices _ B3DVector3Array new: count * 2.
	1 to: count do: [ :index |
		entry _ self halfVerticesData at: index.
		vertices
			at: index put: (B3DVector3 x: entry first y: entry second z: entry third);
			at: count + index put: (B3DVector3 x: entry first negated y: entry second z: entry third)]! !

!AvatarBuilder methodsFor: 'private-face' stamp: 'len 1/29/2001 12:35'!
faceMesh
	^ faceMesh ifNil: [faceMesh _ B3DIndexedTriangleMesh new
						vertices: vertices;
						faces: faces;
						texCoords: self textureCoordinates;
						faceNormals; vertexNormals; yourself]! !

!AvatarBuilder methodsFor: 'private-face' stamp: 'len 1/13/2001 18:54'!
facesData
	^ #((1 2 5 4) (2 3 6 5) (7 4 5 8) (8 5 6 9) (1000 11 8 9) (10 7 8 11) (6 3 14 13) (9 6 13 12) (1000 11 9 12) (11 12 17 18) (12 13 16 17) (13 14 15 16) (16 15 25 24) (1000 16 24 23) (17 16 23 22) (18 17 22 21) (1000 19 11 18) (20 19 18 21) (24 25 26 27) (23 24 27 28) (22 23 28 29) (21 22 29 30) (32 20 21 31) (31 21 30 35) (35 30 29 36) (29 28 37 36) (28 27 38 37) (27 26 39 38) (38 39 40 41) (37 38 41 42) (36 37 42 43) (35 36 43 44) (34 31 35 44) (33 32 31 34) (45 33 34 46) (46 34 44 47) (47 44 43 48) (48 43 42 49) (42 41 50 49) (41 40 51 50) (50 51 64 63) (49 50 63 62) (48 49 62 61) (1000 47 48 61) (63 64 65 66) (66 65 77 76) (67 66 76 75) (62 63 66 67) (73 67 75 74) (68 62 67 73) (60 61 62 68) (52 47 61 60) (53 46 47 52) (54 45 46 53) (55 54 53 56) (1000 58 55 56) (1000 58 56 57) (56 53 52 57) (1000 58 57 59) (57 52 60 59) (58 59 69 70) (59 60 68 69) (70 69 72 71) (69 68 73 72) (1000 72 73 74) (1000 58 146 55) (146 145 54 55) (145 144 45 54) (1000 144 142 45) (142 141 33 45) (141 98 32 33) (98 97 20 32) (97 89 19 20) (1000 89 87 19) (1000 19 87 11) (87 88 10 11) (87 85 86 88) (1000 87 84 85) (84 81 82 85) (85 82 83 86) (81 80 79 82) (82 79 78 83) (89 90 84 87) (90 91 81 84) (91 92 80 81) (94 93 92 91) (1000 95 94 91) (96 95 91 90) (97 96 90 89) (98 99 96 97) (99 100 95 96) (100 101 102 95) (102 103 94 95) (103 104 93 94) (106 105 104 103) (1000 102 106 103) (1000 107 106 102) (1000 109 101 100) (1000 110 109 100) (111 110 100 112) (111 117 118 110) (110 118 108 109) (118 119 107 109) (119 120 106 107) (120 121 105 106) (123 122 121 120) (124 123 120 119) (117 124 119 118) (115 116 117 111) (113 112 100 99) (141 113 99 98) (114 115 111 112) (1000 114 112 113) (116 125 124 117) (1000 124 127 123) (127 128 122 123) (126 129 128 127) (125 126 127 124) (131 130 129 126) (132 131 126 125) (115 132 125 116) (134 135 130 131) (133 134 131 132) (133 132 115 114) (139 114 113 140) (140 113 141 142) (1000 143 140 142) (1000 144 143 142) (1000 148 144 145) (170 148 145 146) (1000 147 170 146) (147 171 169 170) (169 149 148 170) (149 150 144 148) (150 151 143 144) (151 152 140 143) (152 153 139 140) (139 138 133 114) (1000 153 138 139) (138 137 134 133) (137 136 135 134) (156 157 136 137) (155 156 137 138) (154 155 138 153) (1000 152 154 153) (159 158 157 156) (160 159 156 155) (161 160 155 154) (163 162 161 154) (164 163 154 152) (165 164 152 151) (166 165 151 150) (167 166 150 149) (169 168 167 149) (171 174 168 169) (174 177 178 168) (168 178 179 167) (179 180 166 167) (180 181 165 166) (181 182 164 165) (182 183 163 164) (183 184 162 163) (1000 184 185 162) (185 186 161 162) (186 187 160 161) (187 188 159 160) (188 189 158 159) (191 190 189 188) (192 191 188 187) (193 192 187 186) (194 193 186 185) (214 193 194 195) (214 207 192 193) (208 207 214 213) (213 214 195 196) (212 213 196 197) (211 212 197 198) (200 211 198 199) (178 200 199 179) (177 201 200 178) (201 210 211 200) (210 209 212 211) (209 208 213 212) (206 191 192 207) (205 206 207 208) (204 205 208 209) (203 204 209 210) (202 203 210 201) (176 202 201 177) (1000 174 176 177) (1000 191 215 190) (215 228 229 190) (228 231 230 229) (231 242 243 230) (232 241 242 231) (232 231 228 227) (227 228 215 216) (216 215 191 206) (217 216 206 205) (226 227 216 217) (233 232 227 226) (240 241 232 233) (239 240 233 234) (234 233 226 225) (225 226 217 218) (218 217 205 204) (219 218 204 203) (224 225 218 219) (235 234 225 224) (238 239 234 235) (237 238 235 236) (236 235 224 223) (223 224 219 220) (221 220 202 176) (220 219 203 202) (1000 175 237 236) (1000 175 236 223) (175 223 220 221) (222 221 176 174) (1000 222 174 171) (175 221 222 173) (173 222 171 172) (1000 172 171 147) (244 245 194 185) (245 246 195 194) (246 247 196 195) (247 248 197 196) (248 249 198 197) (249 250 199 198) (250 251 179 199) (179 251 252 180) (181 180 252 253) (182 181 253 254) (183 182 254 255) (184 183 255 256) (185 184 256 244) "(1000 153 138 139)")! !

!AvatarBuilder methodsFor: 'private-face' stamp: 'len 1/13/2001 02:34'!
halfVerticesData
	^ #((0 -2.28 8.875) (0 -2.456 8.98) (0 -2.701 9.005) (-0.509 -2.23 8.865) (-0.577 -2.414 8.962) (-0.585 -2.67 8.987) (-1.027 -2.201 8.544) (-1.135 -2.372 8.658) (-1.182 -2.556 8.657) (-1.57 -2.221 8.025) (-1.805 -2.354 8.037) (-1.151 -3.134 8.433) (-0.565 -3.181 8.583) (0 -3.216 8.631) (0 -3.545 8.64) (-0.582 -3.517 8.557) (-1.158 -3.443 8.329) (-1.999 -2.568 7.895) (-2.121 -2.222 7.917) (-2.395 -2.073 7.692) (-2.213 -2.797 7.639) (-1.358 -3.775 8.198) (-0.837 -3.88 8.52) (-0.59 -3.91 8.645) (0 -3.914 8.646) (0 -4.564 8.583) (-0.7 -4.532 8.584) (-1.058 -4.461 8.459) (-1.579 -4.29 8.085) (-1.995 -3.66 7.538) (-2.572 -2.969 7.1) (-2.746 -1.859 7.124) (-2.99 -1.69 6.64) (-2.751 -3.033 6.688) (-2.147 -4.156 7.145) (-1.62 -4.77 7.945) (-1.081 -4.944 8.281) (-0.699 -4.994 8.36) (0 -5.021 8.36) (0 -5.412 7.852) (-0.602 -5.444 7.853) (-0.99 -5.418 7.854) (-1.597 -5.169 7.416) (-2.342 -4.202 6.524) (-3.374 -1.344 5.866) (-3.118 -3.043 5.708) (-2.559 -4.377 5.351) (-1.6 -5.205 6.353) (-0.945 -5.501 6.834) (-0.542 -5.601 7.067) (0 -5.636 7.068) (-3.232 -3.283 3.861) (-3.686 -2.281 4.257) (-3.797 -0.831 4.703) (-4.136 -0.236 3.398) (-4.093 -1.041 3.153) (-3.959 -1.66 2.889) (-4.295 0.021 2.17) (-3.485 -2.252 2.286) (-2.74 -3.866 3.388) (-2.315 -4.57 4.819) (-0.966 -5.443 4.589) (-0.556 -5.511 4.589) (0 -5.553 4.589) (0 -7.061 3.726) (-0.436 -6.971 3.553) (-0.926 -6.872 3.196) (-2.414 -4.428 2.801) (-3.12 -3.336 1.701) (-3.204 -2.934 1.002) (-3.12 -5.511 0.149) (-3.119 -5.51 0.702) (-2.343 -6.297 1.993) (-2.389 -6.885 1.708) (-1.053 -8.199 2.359) (-0.336 -8.622 2.554) (0 -8.714 2.559) (0 -2.278 8.878) (0 -2.064 9.078) (0 -1.83 9.119) (-0.484 -1.72 9.116) (-0.512 -2.003 9.07) (-0.521 -2.231 8.876) (-1.17 -1.928 9) (-1.083 -2.093 8.703) (-1.032 -2.198 8.549) (-1.773 -2.057 8.299) (-1.572 -2.217 8.022) (-2.039 -1.735 8.072) (-1.285 -1.456 8.655) (-0.456 -1.314 8.986) (0 -1.461 8.92) (0 -0.71 8.876) (-0.237 -0.648 8.971) (-0.446 -0.648 8.971) (-1.316 -0.911 8.428) (-2.206 -1.333 7.855) (-2.274 -1.067 7.654) (-1.276 -0.534 8.239) (-0.753 -0.441 8.58) (-0.534 -0.074 8.714) (-0.191 -0.056 9.15) (-0.171 -0.426 9.051) (0 -0.441 9.053) (0 -0.232 9.57) (-0.168 -0.224 9.57) (-0.56 0.058 9.376) (-0.767 0.046 9.042) (-0.843 -0.128 8.806) (-0.978 -0.276 8.684) (-1.091 -0.204 8.513) (-0.905 -0.325 8.292) (-1.32 -0.188 8.01) (-0.895 0.194 8.202) (-1.002 0.217 8.462) (-1.077 0.307 8.703) (-1.017 0.325 8.904) (-0.9 0.099 9.033) (-0.574 0.252 9.485) (-0.118 -0.099 9.722) (0 -0.098 9.723) (0 0.512 9.855) (-0.158 0.508 9.82) (-0.587 0.55 9.557) (-0.66 0.776 9.277) (-0.242 1.137 9.532) (-0.208 0.854 9.713) (0 0.862 9.749) (0 1.192 9.559) (0 1.445 9.385) (-0.25 1.387 9.361) (-0.495 1.19 9.132) (-0.526 1.443 8.894) (-0.284 1.74 9.158) (0 1.817 9.2) (0 2.18 8.995) (-0.322 2.1 8.927) (-0.667 1.571 8.598) (-1.312 0.849 8.093) (-2.093 0.282 7.775) (-2.327 -0.805 7.56) (-3.108 -0.078 7.267) (-3.182 0.649 7.412) (-3.805 0.868 6.79) (-4.108 1.022 5.942) (-4.36 1.772 4.387) (-4.187 2.611 4.596) (-4.028 1.464 6.118) (-3.708 2.236 6.211) (-3.359 1.693 6.896) (-2.876 1.352 7.271) (-2.1 1.207 7.559) (-1.337 1.263 8.027) (-1.27 1.664 7.809) (-0.723 2.023 8.332) (-0.357 2.487 8.669) (0 2.608 8.699) (0 2.909 8.46) (-0.392 2.825 8.42) (-0.623 2.411 8.173) (-0.853 2.189 7.76) (-1.119 2.259 7.352) (-1.46 1.887 7.332) (-2.095 1.531 7.388) (-2.765 1.605 7.294) (-3.156 1.949 6.974) (-3.399 2.397 6.443) (-3.657 2.603 6.413) (-3.904 2.477 5.99) (-4.092 1.936 5.653) (-3.994 2.776 5.641) (-4.121 3.106 4.611) (-4.105 3.756 4.772) (-3.883 2.972 6.298) (-3.928 4.609 5.06) (-3.866 3.453 6.724) (-3.788 3.26 6.846) (-3.556 2.93 6.956) (-3.201 2.669 6.903) (-3.001 2.353 7.274) (-2.571 2.177 7.578) (-2.113 2.147 7.561) (-1.602 2.246 7.687) (-1.21 2.404 7.438) (-0.967 2.609 7.023) (-0.638 2.684 7.661) (-0.584 3.052 8.055) (-0.431 3.211 8.189) (0 3.262 8.208) (0 3.664 8.101) (-0.487 3.639 8.101) (-0.76 3.42 7.947) (-0.829 3.21 7.554) (-1.006 2.963 7.129) (-1.309 3.29 7.37) (-1.772 3.474 7.615) (-2.268 3.493 7.824) (-2.704 3.315 7.781) (-3.129 3.065 7.391) (-3.421 3.337 7.438) (-3.624 3.65 7.348) (-3.73 3.872 7.238) (-3.285 4.274 7.783) (-2.569 4.558 8.182) (-1.841 4.676 8.353) (-1.067 4.327 8.469) (-1.15 4.072 8.222) (-1.853 4.265 8.296) (-2.509 4.191 8.259) (-3.195 3.97 7.895) (-2.963 3.637 7.879) (-2.381 3.83 8.1) (-1.782 3.85 8.071) (-1.227 3.657 8.072) (-0.45 4.377 8.175) (-0.991 4.862 8.093) (-1.731 5.054 7.962) (-2.474 4.937 7.775) (-3.17 4.658 7.356) (-3.605 4.334 6.861) (-3.89 3.957 6.326) (-3.941 3.197 5.815) (-3.59 5.23 6.286) (-3.102 5.495 6.831) (-2.33 5.69 7.264) (-1.576 5.648 7.632) (-0.888 5.445 7.804) (-0.406 5.084 7.869) (0 4.67 7.912) (0 6.172 7.196) (-0.354 6.247 7.229) (-0.746 6.328 7.263) (-1.426 6.432 7.212) (-2.244 6.373 6.969) (-3.105 6.092 6.495) (-3.639 5.648 5.945) (-3.562 6.154 5.544) (-3.109 6.63 5.986) (-2.176 7.198 6.426) (-1.281 7.365 6.6) (-0.547 7.488 6.717) (-0.286 7.51 6.75) (0 7.522 6.764) (-0.973 2.625 7.123) (-1.041 2.87 7.229) (-1.295 3.155 7.47) (-1.693 3.288 7.715) (-2.196 3.267 7.924) (-2.545 3.146 7.881) (-2.856 2.944 7.491) (-3.091 2.634 7.003) (-2.846 2.481 7.474) (-2.383 2.398 7.878) (-2.012 2.37 7.961) (-1.574 2.388 7.987) (-1.197 2.479 7.638))! !

!AvatarBuilder methodsFor: 'private-face' stamp: 'len 1/13/2001 03:01'!
mimeEncodedTextureJPEG
	^ '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'! !

!AvatarBuilder methodsFor: 'private-face' stamp: 'len 1/13/2001 20:29'!
texture
	^ (JPEGReadWriter on: (Base64MimeConverter mimeDecodeToBytes: self mimeEncodedTextureJPEG readStream)) nextImage asTexture flipVertically interpolate: true; wrap: true! !

!AvatarBuilder methodsFor: 'private-face' stamp: 'len 9/23/1999 02:45'!
texture2
	| r1 answer |
	Utilities informUser: 'Choose a rectangle with interesting stuff'
		during: [r1 _ Rectangle originFromUser: 128 at 128.
				Sensor waitNoButton].
	answer _ (B3DTexture fromDisplay: r1) asFormOfDepth: 32.
	answer _ answer asTexture.
	answer wrap: true; interpolate: true; envMode: 0.
	^ answer! !

!AvatarBuilder methodsFor: 'private-face' stamp: 'len 9/23/1999 03:02'!
texture3
	| answer |
	answer _ (self texture asFormOfDepth: 16) asFormOfDepth: 8.
	answer _ answer asTexture.
	answer wrap: true; interpolate: true; envMode: 0.
	^ answer! !

!AvatarBuilder methodsFor: 'private-face' stamp: 'len 1/25/2001 18:14'!
texture4
	^ (ImageReadWriter formFromFileNamed: 'face/katia3.png') asTexture flipVertically interpolate: true; wrap: true! !

!AvatarBuilder methodsFor: 'private-face' stamp: 'len 1/29/2001 12:23'!
textureCoordinates
	| minX maxX minY maxY tex x y vertex |
	minX _ minY _ 1000000.0.
	maxX _ maxY _ -1000000.0.
	vertices do: [ :each |
		minX _ minX min: each x.
		minY _ minY min: each y.
		maxX _ maxX max: each x.
		maxY _ maxY max: each y].
	tex _ B3DTexture2Array new: vertices size.
	1 to: vertices size do: [ :index |
		vertex _ vertices at: index.
		x _ vertex x - minX / (maxX - minX).
		y _ vertex y - minY / (maxY - minY).
		tex at: index put: x @ y].
	^ tex! !

!AvatarBuilder methodsFor: 'private-eyes' stamp: 'len 1/24/2001 16:54'!
eyeballFaces
	| faceList vtx m1 m2 baseDir vtxList dir lastVtx nextVtx face verticalSteps latitudeSteps latitudeVertices |
	verticalSteps _ 12.
	latitudeSteps _ 6.
	faceList _ WriteStream on: (Array new: verticalSteps * latitudeSteps).
	"<--- vertex construction --->"
	m1 _ (B3DRotation angle: 360.0 / verticalSteps axis: 0 at -1@0) asMatrix4x4.
	m2 _ (B3DRotation angle: 90.0 / latitudeSteps axis: 0 at 0@-1) asMatrix4x4.
	baseDir _ 0 at 1@0.
	vtxList _ Array new: verticalSteps + 1.
	0 to: verticalSteps do:[:i|
		i = verticalSteps ifTrue:[baseDir _ 0 at -1@0]. "Make closed for sure"
		latitudeVertices _ Array new: latitudeSteps + 1.
		vtxList at: i+1 put: latitudeVertices.
		dir _ baseDir.
		0 to: latitudeSteps do:[:j|
			vtx _ B3DSimpleMeshVertex new.
			vtx position: dir * self eyeballRadius; normal: dir.
			vtx texCoord: (dir x + 1 / 2.0) @ (dir y + 1 / 2.0).
			latitudeVertices at: j+1 put: vtx.
			dir _ (m1 localPointToGlobal: dir) normalized.
		].
		baseDir _ (m2 localPointToGlobal: baseDir) normalized.
	].
	"<--- face construction --->"
	"Construct first round separately as triangles"
	lastVtx _ vtxList at: 1.
	nextVtx _ vtxList at: 2.
	1 to: latitudeSteps do:[:i|
		face _ B3DSimpleMeshFace new: 3.
		face at: 1 put: (lastVtx at: i).
		face at: 2 put: (nextVtx at: i+1).
		face at: 3 put: (nextVtx at: i).
		faceList nextPut: face].
	"Construct the next rounds as quads"
	2 to: verticalSteps do:[:i|
		lastVtx _ vtxList at: i.
		nextVtx _ vtxList at: i+1.
		1 to: latitudeSteps do:[:j|
			face _ B3DSimpleMeshFace new: 4.
			face at: 1 put: (lastVtx at: j).
			face at: 2 put: (lastVtx at: j+1).
			face at: 3 put: (nextVtx at: j+1).
			face at: 4 put: (nextVtx at: j).
			faceList nextPut: face]].
	^faceList contents! !

!AvatarBuilder methodsFor: 'private-eyes' stamp: 'len 1/15/2001 20:45'!
eyeballMesh
	^ (B3DSimpleMesh withAll: self eyeballFaces) asIndexedMesh! !

!AvatarBuilder methodsFor: 'private-eyes' stamp: 'len 1/15/2001 20:44'!
eyeballRadius
	^ 1.35! !

!AvatarBuilder methodsFor: 'private-eyes' stamp: 'len 1/29/2001 12:39'!
eyeballTexture
	^ eyeballTexture ifNil: [eyeballTexture _ (PNGReadWriter on: (Base64MimeConverter mimeDecodeToBytes: self mimeEncodedEyeballTexturePNG readStream)) nextImage asTexture interpolate: true; wrap: true]! !

!AvatarBuilder methodsFor: 'private-eyes' stamp: 'len 1/24/2001 09:45'!
leftEyeballCenter
	| right |
	right _ self rightEyeballCenter.
	^ right copy x: right x negated! !

!AvatarBuilder methodsFor: 'private-eyes' stamp: 'len 1/29/2001 12:34'!
leftEyeballMesh
	^ leftEyeballMesh ifNil: [leftEyeballMesh _ self eyeballMesh translateBy: self leftEyeballCenter]! !

!AvatarBuilder methodsFor: 'private-eyes' stamp: 'len 1/15/2001 20:47'!
mimeEncodedEyeballTexturePNG
	^ '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'! !

!AvatarBuilder methodsFor: 'private-eyes' stamp: 'len 1/24/2001 09:50'!
rightEyeballCenter
	^ 2.0 at 2.8@6.33! !

!AvatarBuilder methodsFor: 'private-eyes' stamp: 'len 1/29/2001 12:34'!
rightEyeballMesh
	^ rightEyeballMesh ifNil: [rightEyeballMesh _ self eyeballMesh translateBy: self rightEyeballCenter]! !

!AvatarBuilder methodsFor: 'scene' stamp: 'len 8/10/2001 20:37'!
faceObject
	^ B3DSceneObject new
		geometry: self faceMesh;
		texture: self texture;
		material: self material! !

!AvatarBuilder methodsFor: 'scene' stamp: 'len 8/10/2001 20:38'!
leftEyeballObject
	^ B3DSceneObject new
		geometry: self leftEyeballMesh;
		texture: self eyeballTexture;
		material: self material! !

!AvatarBuilder methodsFor: 'scene' stamp: 'len 8/10/2001 20:58'!
light
	^ B3DPositionalLight new
		lightColor: self lightColor;
		position: self lightPosition;
		attenuation: (B3DLightAttenuation constant: 1.0 linear: 0.0 squared: 0.0);
		yourself! !

!AvatarBuilder methodsFor: 'scene' stamp: 'len 9/23/1999 01:59'!
lightColor
	^ B3DMaterialColor new
		ambientPart: (B3DColor4 r: 0.0 g: 0.0 b: 0.0 a: 1.0);
		diffusePart: (B3DColor4 r: 0.5 g: 0.5 b: 0.5 a: 1.0);
		specularPart: (B3DColor4 r: 0.8 g: 0.8 b: 0.8 a: 0.8);
		yourself! !

!AvatarBuilder methodsFor: 'scene' stamp: 'len 8/10/2001 20:59'!
lightPosition
	^ B3DVector3 x: 0 y: 0 z: 30! !

!AvatarBuilder methodsFor: 'scene' stamp: 'len 8/10/2001 21:00'!
material
	^ B3DMaterial new
		specularPart: Color white;
		ambientPart: Color white;
		diffusePart: Color white;
		emission: Color white;
		shininess: 20.0;
		yourself! !

!AvatarBuilder methodsFor: 'scene' stamp: 'len 8/10/2001 20:41'!
material2
	^ B3DMaterial new
		specularPart: (B3DColor4 r: 0.9 g: 0.9 b: 0.9 a: 0.9);
		ambientPart: (B3DColor4 r: 0.9 g: 0.9 b: 0.9 a: 0.9);
		emission: (B3DColor4 r: 0.5 g: 0.5 b: 0.5 a: 1.0);
		shininess: 20.0;
		yourself! !

!AvatarBuilder methodsFor: 'scene' stamp: 'len 8/10/2001 20:38'!
rightEyeballObject
	^ B3DSceneObject new
		geometry: self rightEyeballMesh;
		texture: self eyeballTexture;
		material: self material! !

!AvatarBuilder methodsFor: 'scene' stamp: 'len 1/29/2001 12:37'!
scene
	| answer camera |
	answer _ B3DScene new.
	answer objects add: self faceObject; add: self leftEyeballObject; add: self rightEyeballObject.
	camera _ B3DCamera new.
	camera position: 0 at 0@30.
	camera fov: 15.
	answer defaultCamera: camera.
	answer lights add: (B3DAmbientLight color: Color white).
	answer lights add: self light.
	^ answer! !

!AvatarBuilder methodsFor: 'building' stamp: 'len 1/29/2001 12:17'!
avatar
	avatar ifNil: [self buildAvatar].
	^ avatar! !

!AvatarBuilder methodsFor: 'building' stamp: 'len 1/29/2001 12:17'!
buildAvatar
	avatar _ Avatar new.
	self buildJaw; buildLeftEye; buildRightEye; buildMuscles! !

!AvatarBuilder methodsFor: 'building' stamp: 'len 1/29/2001 12:18'!
buildJaw
	avatar jaw: (Jaw new mesh: self faceMesh; indices: (1 to: 59), (257 to: 256 + 58))! !

!AvatarBuilder methodsFor: 'building' stamp: 'len 2/9/2001 10:45'!
buildLeftEye
	avatar leftEye:
		(Eye new
			mesh: self leftEyeballMesh;
			center: self leftEyeballCenter;
			upperEyelid: (Eyelid upper mesh: self faceMesh; indices: (245 to: 251));
			lowerEyelid: (Eyelid lower mesh: self faceMesh; indices: (251 to: 256)))! !

!AvatarBuilder methodsFor: 'building' stamp: 'len 1/29/2001 12:20'!
buildMuscles
	| muscles |
	muscles _ Dictionary new.
	self muscles do: [ :each | muscles at: each name put: each].
	avatar muscles: muscles! !

!AvatarBuilder methodsFor: 'building' stamp: 'len 2/9/2001 10:46'!
buildRightEye
	avatar rightEye:
		(Eye new
			mesh: self rightEyeballMesh;
			center: self rightEyeballCenter;
			upperEyelid: (Eyelid upper mesh: self faceMesh; indices: (256+245 to: 256+251));
			lowerEyelid: (Eyelid lower mesh: self faceMesh; indices: (256+251 to: 256+256)))! !

!AvatarBuilder methodsFor: 'building' stamp: 'len 1/30/2001 17:08'!
muscles
	^ #(leftAngularDepressor leftFrontalisInner leftFrontalisMajor leftFrontalisOuter leftInnerLabiNasi leftLabiNasi leftLateralCorigator leftSecondaryFrontalis leftZygomaticMajor rightAngularDepressor rightFrontalisInner rightFrontalisMajor rightFrontalisOuter rightInnerLabiNasi rightLabiNasi rightLateralCorigator rightSecondaryFrontalis rightZygomaticMajor) collect: [ :each | (Muscle perform: each) mesh: self faceMesh]! !

!AvatarBuilder methodsFor: 'building' stamp: 'len 2/9/2001 11:29'!
openInWorld
	"
	AvatarBuilder new openInWorld
	"
	| answer controlMorph sceneMorph |
	answer _ self avatar.
	controlMorph _ AvatarControlMorph new avatar: answer.
	controlMorph scene: (sceneMorph _ B3DSceneExplorerMorph new scene: self scene; switchRotationStatus).
	controlMorph openInWorld.
	sceneMorph openInWorld.
	^ answer! !


!AvatarBuilder class methodsFor: 'instance creation' stamp: 'len 1/13/2001 04:03'!
new
	^ super new initialize! !


!AvatarControlMorph methodsFor: 'initialization' stamp: 'len 2/9/2001 11:39'!
avatar: anAvatar
	| slider |
	avatar _ anAvatar.
	anAvatar muscles keys asSortedCollection do: [ :each |
		slider _ self newSliderForMuscle: (anAvatar muscles at: each).
		((each beginsWith: 'Left') ifTrue: [left] ifFalse: [right]) addMorphBack: slider].
	left addMorph: (self newSliderFor: anAvatar leftEye upperEyelid setter: #angle: getter: #angle max: 5.0).
	left addMorph: (self newSliderFor: anAvatar leftEye lowerEyelid setter: #angle: getter: #angle max: 5.0).
	left addMorph: (self newSliderFor: anAvatar leftEye setter: #rotationY: getter: #rotationY min: -16.0 max: 16.0).
	left addMorph: (self newSliderFor: anAvatar leftEye setter: #rotationX: getter: #rotationX min: -30.0 max: 30.0).
	right addMorph: (self newSliderFor: anAvatar rightEye upperEyelid setter: #angle: getter: #angle max: 5.0).
	right addMorph: (self newSliderFor: anAvatar rightEye lowerEyelid setter: #angle: getter: #angle max: 5.0).
	right addMorph: (self newSliderFor: anAvatar rightEye setter: #rotationY: getter: #rotationY min: -16.0 max: 16.0).
	right addMorph: (self newSliderFor: anAvatar rightEye setter: #rotationX: getter: #rotationX min: -30.0 max: 30.0).
	self addMorphBack: (self newSliderForJaw: anAvatar jaw)! !

!AvatarControlMorph methodsFor: 'initialization' stamp: 'len 12/21/2001 14:33'!
initialize
	| sliders |
	super initialize.
	self layoutInset: 0.
	self color: (Color r: 0.452 g: 0.452 b: 0.645).
	self listDirection: #topToBottom; hResizing: #shrinkWrap; vResizing: #shrinkWrap.
	left _ AlignmentMorph newColumn color: self color.
	right _ AlignmentMorph newColumn color: self color.
	sliders _ AlignmentMorph newRow.
	sliders addMorph: left; addMorph: right.
	self addMorph: sliders.
	self addMorph: (SimpleButtonMorph new target: self; borderColor: Color black; label: 'play expression...'; actWhen: #buttonDown; actionSelector: #playExpression)! !

!AvatarControlMorph methodsFor: 'initialization' stamp: 'len 12/21/2001 14:28'!
newSlider
	| r |
	r _ AlignmentMorph newColumn.
	r color: self color; borderWidth: 0; layoutInset: 0.
	r hResizing: #spaceFill; vResizing: #rigid; extent: 5 at 20; wrapCentering: #center; cellPositioning: #topCenter.
	^ r! !

!AvatarControlMorph methodsFor: 'initialization' stamp: 'len 2/9/2001 11:40'!
newSliderFor: anObject setter: setter getter: getter max: max
	^ self newSliderFor: anObject setter: setter getter: getter min: 0 max: max! !

!AvatarControlMorph methodsFor: 'initialization' stamp: 'len 12/21/2001 14:30'!
newSliderFor: anObject setter: setter getter: getter min: min max: max
	| r slider m |
	r _ self newSlider.

	m _ UpdatingStringMorph new
		target: anObject; getSelector: #yourself;
		width: 200; step.
	r addMorphBack: m.

	slider _ UpdatingSimpleSliderMorph new
		color: (Color r: 0.839 g: 0.548 b: 0.355);
		extent: 200 at 2;
		target: anObject;
		actionSelector: setter;
		getValueSelector: getter;
		minVal: min;
		maxVal: max;
		adjustToValue: (anObject perform: getter).
	r addMorphBack: slider.

	^ r! !

!AvatarControlMorph methodsFor: 'initialization' stamp: 'len 12/21/2001 14:30'!
newSliderForJaw: aJaw
	| r slider m |
	r _ self newSlider.

	m _ UpdatingStringMorph new
		target: aJaw; getSelector: #yourself;
		width: 400; step.
	r addMorphBack: m.

	slider _ UpdatingSimpleSliderMorph new
		color: (Color r: 0.839 g: 0.548 b: 0.355);
		extent: 400 at 2;
		target: aJaw;
		actionSelector: #angle:;
		getValueSelector: #angle;
		maxVal: 10;
		adjustToValue: aJaw angle.
	r addMorphBack: slider.

	^ r! !

!AvatarControlMorph methodsFor: 'initialization' stamp: 'len 12/21/2001 14:31'!
newSliderForMuscle: aMuscle
	| r slider m |
	r _ self newSlider.
	m _ UpdatingStringMorph new
		target: aMuscle; getSelector: #yourself;
		width: 200; step.
	r addMorphBack: m.

	slider _ UpdatingSimpleSliderMorph new
		color: (Color r: 0.839 g: 0.548 b: 0.355);
		extent: 200 at 2;
		target: aMuscle;
		actionSelector: #contraction:;
		getValueSelector: #contraction;
		maxVal: aMuscle clamp;
		adjustToValue: aMuscle contraction.
	r addMorphBack: slider.

	^ r! !

!AvatarControlMorph methodsFor: 'initialization' stamp: 'len 2/9/2001 11:26'!
scene: aMorph
	scene _ aMorph! !

!AvatarControlMorph methodsFor: 'accessing' stamp: 'len 1/29/2001 11:54'!
avatar
	^ avatar! !

!AvatarControlMorph methodsFor: 'menu' stamp: 'len 1/29/2001 11:55'!
playAngerExpression
	Viseme anger playOn: avatar! !

!AvatarControlMorph methodsFor: 'menu' stamp: 'len 1/29/2001 11:57'!
playDisgustExpression
	Viseme disgust playOn: avatar! !

!AvatarControlMorph methodsFor: 'menu' stamp: 'len 9/28/1999 01:51'!
playExpression
	"Invoke a menu of playing an expression."

	| aMenu |
	aMenu _ CustomMenu new.
	aMenu addList:	#(
		('neutral'		playNeutralExpression)
		('anger'		playAngerExpression)
		('digust'		playDisgustExpression)
		('fear'		playFearExpression)
		('happiness'		playHappinessExpression)
		('sadness'	playSadnessExpression)
		('surprise'	playSurpriseExpression)).
	aMenu invokeOn: self defaultSelection: nil! !

!AvatarControlMorph methodsFor: 'menu' stamp: 'len 1/29/2001 11:58'!
playFearExpression
	Viseme fear playOn: avatar! !

!AvatarControlMorph methodsFor: 'menu' stamp: 'len 1/29/2001 11:58'!
playHappinessExpression
	Viseme happiness playOn: avatar! !

!AvatarControlMorph methodsFor: 'menu' stamp: 'len 1/29/2001 11:58'!
playNeutralExpression
	avatar relax! !

!AvatarControlMorph methodsFor: 'menu' stamp: 'len 1/29/2001 11:58'!
playSadnessExpression
	Viseme sadness playOn: avatar! !

!AvatarControlMorph methodsFor: 'menu' stamp: 'len 2/9/2001 11:41'!
playSurpriseExpression
	Viseme surprise playOn: avatar! !

!AvatarControlMorph methodsFor: 'stepping and presenter' stamp: 'len 2/9/2001 11:37'!
step
	self flag: #hack.
	scene changed! !

!AvatarControlMorph methodsFor: 'stepping and presenter' stamp: 'len 2/9/2001 11:34'!
stepTime
	^ 0! !


!Eye methodsFor: 'initialization' stamp: 'len 2/9/2001 11:00'!
initialize
	rotation _ 0 at 0! !

!Eye methodsFor: 'accessing' stamp: 'len 2/1/2001 22:54'!
center: aVector3
	center _ aVector3! !

!Eye methodsFor: 'accessing' stamp: 'len 2/28/2000 23:53'!
lowerEyelid
	^ lowerEyelid! !

!Eye methodsFor: 'accessing' stamp: 'len 1/29/2001 12:03'!
lowerEyelid: anEyelid
	lowerEyelid _ anEyelid! !

!Eye methodsFor: 'accessing' stamp: 'len 1/29/2001 12:01'!
mesh: aB3DIndexedMesh
	mesh _ aB3DIndexedMesh! !

!Eye methodsFor: 'accessing' stamp: 'len 2/9/2001 11:11'!
rotate: anglePoint
	| xform |
	rotation _ rotation + anglePoint.

	xform _ B3DMatrix4x4 withOffset: center negated.
	xform _ xform composedWithGlobal: (B3DRotation angle: anglePoint x negated axis: 0 at 1@0) asMatrix4x4.
	xform _ xform composedWithGlobal: (B3DRotation angle: anglePoint y axis: 1 at 0@0) asMatrix4x4.
	xform _ xform composedWithGlobal: (B3DMatrix4x4 withOffset: center).
	mesh transformBy: xform! !

!Eye methodsFor: 'accessing' stamp: 'len 2/1/2001 18:29'!
rotation
	^ rotation! !

!Eye methodsFor: 'accessing' stamp: 'len 2/9/2001 11:03'!
rotation: aPoint
	self rotate: aPoint - rotation! !

!Eye methodsFor: 'accessing' stamp: 'len 2/9/2001 10:59'!
rotationX
	^ self rotation x! !

!Eye methodsFor: 'accessing' stamp: 'len 2/9/2001 10:59'!
rotationX: angle
	self rotation: angle @ self rotation y! !

!Eye methodsFor: 'accessing' stamp: 'len 2/9/2001 10:59'!
rotationY
	^ self rotation y! !

!Eye methodsFor: 'accessing' stamp: 'len 2/9/2001 10:59'!
rotationY: angle
	self rotation: self rotation x @ angle! !

!Eye methodsFor: 'accessing' stamp: 'len 2/28/2000 23:53'!
upperEyelid
	^ upperEyelid! !

!Eye methodsFor: 'accessing' stamp: 'len 1/29/2001 12:04'!
upperEyelid: anEyelid
	upperEyelid _ anEyelid! !


!Eye class methodsFor: 'instance creation' stamp: 'len 2/9/2001 11:00'!
new
	^ super new initialize! !


!Eyelid methodsFor: 'as yet unclassified' stamp: 'len 1/29/2001 12:03'!
activateWith: value
	| radians cos sin vertices vertex y z |
	radians _ (value * direction) degreesToRadians.
	cos _ radians cos.
	sin _ radians sin.
	vertices _ mesh vertices.
	self indices do: [ :each |
		vertex _ vertices at: each.
		y _ vertex y.
		z _ vertex z.
		vertex y: cos * y - (sin * z).
		vertex z: sin * y + (cos * z).
		vertices at: each put: vertex].
	self triggerEvent: #activated! !

!Eyelid methodsFor: 'as yet unclassified' stamp: 'len 2/28/2000 23:59'!
angle
	^ angle! !

!Eyelid methodsFor: 'as yet unclassified' stamp: 'len 2/28/2000 23:58'!
angle: aNumber
	self activateWith: aNumber - self angle.
	angle _ aNumber! !

!Eyelid methodsFor: 'as yet unclassified' stamp: 'len 2/28/2000 23:57'!
direction
	^ direction! !

!Eyelid methodsFor: 'as yet unclassified' stamp: 'len 2/28/2000 23:57'!
direction: oneOrMinusOne
	direction _ oneOrMinusOne! !

!Eyelid methodsFor: 'as yet unclassified' stamp: 'len 2/28/2000 23:55'!
indices
	^ indices! !

!Eyelid methodsFor: 'as yet unclassified' stamp: 'len 2/28/2000 23:55'!
indices: aCollection
	indices _ aCollection! !

!Eyelid methodsFor: 'as yet unclassified' stamp: 'len 2/28/2000 23:57'!
initialize
	angle _ 0! !

!Eyelid methodsFor: 'as yet unclassified' stamp: 'len 1/29/2001 12:04'!
mesh: aB3DIndexedMesh
	mesh _ aB3DIndexedMesh! !


!Eyelid class methodsFor: 'instance creation' stamp: 'len 2/29/2000 00:26'!
lower
	^ self new direction: -1! !

!Eyelid class methodsFor: 'instance creation' stamp: 'len 2/28/2000 23:56'!
new
	^ super new initialize! !

!Eyelid class methodsFor: 'instance creation' stamp: 'len 2/29/2000 00:26'!
upper
	^ self new direction: 1! !


!Head3DMorph methodsFor: 'initialization' stamp: 'len 2/17/2000 07:55'!
initialize
	super initialize.
	self extent: 140 @ 100.
	self color: Color red.
	queue _ SharedQueue new! !

!Head3DMorph methodsFor: 'accessing' stamp: 'len 2/28/2000 00:45'!
articulate: aPhoneme
	aPhoneme isVowel ifTrue: [self head jaw angle: 2.5] ifFalse: [self head jaw angle: 0].
	self changed! !

!Head3DMorph methodsFor: 'accessing' stamp: 'len 2/28/2000 00:45'!
head
	^ head! !

!Head3DMorph methodsFor: 'accessing' stamp: 'len 2/28/2000 00:45'!
head: aHead
	head _ aHead! !

!Head3DMorph methodsFor: 'accessing' stamp: 'len 2/17/2000 07:55'!
playEvent: event at: time
	self queue nextPut: time -> event! !

!Head3DMorph methodsFor: 'accessing' stamp: 'len 2/17/2000 07:56'!
queue
	^ queue! !

!Head3DMorph methodsFor: 'accessing' stamp: 'len 9/23/1999 02:21'!
scene
	^ scene! !

!Head3DMorph methodsFor: 'accessing' stamp: 'len 9/23/1999 02:21'!
scene: aB3DScene
	scene _ aB3DScene! !

!Head3DMorph methodsFor: 'drawing' stamp: 'len 9/26/1999 17:55'!
drawOn: aCanvas
	aCanvas asBalloonCanvas render: self.
	aCanvas frameRectangle: self bounds color: self color! !

!Head3DMorph methodsFor: 'drawing' stamp: 'len 2/17/2000 01:13'!
pickVertexAt: aPoint
	| aRenderer answer |
	aRenderer _ (B3DRenderEngine defaultForPlatformOn: nil) new.
	aRenderer viewport: (self bounds insetBy: 1 at 1).
	aRenderer clearDepthBuffer.
	aRenderer loadIdentity.
	aRenderer _ aRenderer asPickerAt: aPoint.
	self scene renderOn: aRenderer.
	self halt.
	aRenderer finish.
	answer _ aRenderer topMostVertex.
	aRenderer destroy.
	^ answer! !

!Head3DMorph methodsFor: 'drawing' stamp: 'len 9/23/1999 02:22'!
renderOn: aRenderer
	aRenderer viewport: (self bounds insetBy: 1 at 1).
	aRenderer clearDepthBuffer.
	aRenderer loadIdentity.
	self scene renderOn: aRenderer! !

!Head3DMorph methodsFor: 'menus' stamp: 'len 2/16/2000 23:37'!
addCustomMenuItems: aCustomMenu hand: aHandMorph
	"Add morph-specific items to the given menu which was invoked by the given hand."

	super addCustomMenuItems: aCustomMenu hand: aHandMorph.
	aCustomMenu add: 'open muscle controls' action: #openMuscleControls! !

!Head3DMorph methodsFor: 'menus' stamp: 'len 1/13/2001 00:55'!
openMuscleControls
	self head openControlMorph! !

!Head3DMorph methodsFor: 'stepping and presenter' stamp: 'len 2/17/2000 07:56'!
step
	| now |
	super step.
	now _ Time millisecondClockValue.
	[queue isEmpty not and: [now >= queue peek key]]
		whileTrue: [queue next value actOn: self].
"	self face lips updateShape"! !


!Head3DMorph class methodsFor: 'examples' stamp: 'len 1/29/2001 11:36'!
example
	| builder |
	builder _ AvatarBuilder example.
	^ self new scene: builder scene; head: builder face! !


!Jaw methodsFor: 'initialization' stamp: 'len 9/11/1999 03:43'!
initialize
	angle _ 0.0! !

!Jaw methodsFor: 'accessing' stamp: 'len 9/11/1999 03:35'!
angle
	^ angle! !

!Jaw methodsFor: 'accessing' stamp: 'len 2/17/2000 07:12'!
angle: aNumber
	self activateWith: aNumber - self angle.
	angle _ aNumber! !

!Jaw methodsFor: 'accessing' stamp: 'len 9/11/1999 03:40'!
indices
	^ indices! !

!Jaw methodsFor: 'accessing' stamp: 'len 9/11/1999 03:40'!
indices: aCollection
	indices _ aCollection! !

!Jaw methodsFor: 'accessing' stamp: 'len 1/29/2001 12:06'!
mesh: aB3DIndexedMesh
	mesh _ aB3DIndexedMesh! !

!Jaw methodsFor: 'accessing' stamp: 'len 9/20/1999 01:17'!
rotate: aNumber
	self angle: self angle + aNumber! !

!Jaw methodsFor: 'activation' stamp: 'len 2/17/2000 07:12'!
activate
	self activateWith: self angle! !

!Jaw methodsFor: 'activation' stamp: 'len 1/29/2001 12:05'!
activateWith: value
	| radians cos sin vertices vertex y z |
	radians _ value * Float pi / 180.0.
	cos _ radians cos.
	sin _ radians sin.
	vertices _ mesh vertices.
	self indices do: [ :each |
		vertex _ vertices at: each.
		y _ vertex y.
		z _ vertex z.
		vertex y: cos * y - (sin * z).
		vertex z: sin * y + (cos * z).
		vertices at: each put: vertex].
	self triggerEvent: #activated! !

!Jaw methodsFor: 'activation' stamp: 'len 9/11/1999 03:35'!
relax
	self angle: 0.0! !


!Jaw class methodsFor: 'instance creation' stamp: 'len 9/11/1999 03:43'!
new
	^ super new initialize! !


!Muscle methodsFor: 'initialization' stamp: 'len 9/20/1999 01:21'!
initialize
	contraction _ 0.0! !

!Muscle methodsFor: 'accessing-private' stamp: 'len 9/26/1999 18:08'!
clamp: aNumber
	clamp _ aNumber! !

!Muscle methodsFor: 'accessing-private' stamp: 'len 9/9/1999 01:53'!
end: aFloat
	end _ aFloat! !

!Muscle methodsFor: 'accessing-private' stamp: 'len 9/9/1999 02:12'!
head: aB3DVector3
	head _ aB3DVector3! !

!Muscle methodsFor: 'accessing-private' stamp: 'len 9/9/1999 01:43'!
name: aString
	name _ aString! !

!Muscle methodsFor: 'accessing-private' stamp: 'len 9/9/1999 01:53'!
start: aFloat
	start _ aFloat! !

!Muscle methodsFor: 'accessing-private' stamp: 'len 9/9/1999 01:46'!
tail: aB3DVector3
	tail _ aB3DVector3! !

!Muscle methodsFor: 'accessing-private' stamp: 'len 9/9/1999 01:54'!
zone: aFloat
	zone _ aFloat! !

!Muscle methodsFor: 'accessing' stamp: 'len 9/26/1999 18:07'!
clamp
	^ clamp! !

!Muscle methodsFor: 'accessing' stamp: 'len 9/20/1999 01:19'!
contract: aNumber
	self contraction: self contraction + aNumber! !

!Muscle methodsFor: 'accessing' stamp: 'len 9/9/1999 01:53'!
contraction
	^ contraction! !

!Muscle methodsFor: 'accessing' stamp: 'len 2/17/2000 07:11'!
contraction: aNumber
	self activateWith: aNumber - self contraction.
	contraction _ aNumber! !

!Muscle methodsFor: 'accessing' stamp: 'len 9/9/1999 01:53'!
end
	^ end! !

!Muscle methodsFor: 'accessing' stamp: 'len 9/9/1999 01:44'!
head
	"Answer the head of the muscle vector."
	^ head! !

!Muscle methodsFor: 'accessing' stamp: 'len 1/29/2001 12:09'!
length
	"Answer the distance from the head to the tail."
	^ (tail - head) length! !

!Muscle methodsFor: 'accessing' stamp: 'len 1/29/2001 11:30'!
mesh: aB3DIndexedMesh
	mesh _ aB3DIndexedMesh! !

!Muscle methodsFor: 'accessing' stamp: 'len 1/29/2001 11:30'!
name
	^ name! !

!Muscle methodsFor: 'accessing' stamp: 'len 9/9/1999 01:53'!
start
	^ start! !

!Muscle methodsFor: 'accessing' stamp: 'len 9/9/1999 01:44'!
tail
	"Answer the tail of the muscle vector."
	^ tail! !

!Muscle methodsFor: 'accessing' stamp: 'len 9/9/1999 01:47'!
zone
	"Answer the zone of influence of the receiver."
	^ zone! !

!Muscle methodsFor: 'activation' stamp: 'len 2/17/2000 07:09'!
activate
	self activateWith: self contraction! !

!Muscle methodsFor: 'activation' stamp: 'len 1/29/2001 11:31'!
activateWith: val
	| index direction vertices |
	indices ifNil: [self computeIndicesAndDirections].
	vertices _ mesh vertices.
	1 to: indices size do: [ :each |
		index _ indices at: each.
		direction _ directions at: each.
		vertices at: index put: (vertices at: index) + (direction * val)]! !

!Muscle methodsFor: 'activation' stamp: 'len 1/29/2001 12:09'!
computeIndicesAndDirections
	| thet vertex vblen cosa cosv newv newp total proportion convertion vb va neutralVertices |
	neutralVertices _ mesh vertices.
	convertion _ 180 / Float pi.
	thet _ (zone / convertion) cos.
	total _ end - start.
	self length > 0 ifFalse: [^ self].
	va _ self normalizedDirection.
	indices _ OrderedCollection new.
	directions _ OrderedCollection new.
	1 to: neutralVertices size do: [ :each |
		vertex _ neutralVertices at: each.
		"Find the length of muscle head to the mesh node."
		vb _ vertex - head.
		vblen _ vb length.
		vblen > 0.0
			ifTrue: [cosa _ (vb dot: va) / vblen.
					cosa > thet
						ifTrue: [vblen <= end
									ifTrue: [cosv _ 1.0 - (cosa / thet).
											vblen >= start
												ifTrue: [proportion _ vblen - start / total.
														newv _ (proportion * 90 / convertion) cos.
														newp _ vb * cosv * newv]
												ifFalse: [newp _ vb * cosv].
											indices add: each.
											directions add: newp]]]].
	indices _ indices asArray.
	directions _ directions asArray! !

!Muscle methodsFor: 'activation' stamp: 'len 1/29/2001 12:09'!
normalizedDirection
	^ (tail - head) safelyNormalized! !

!Muscle methodsFor: 'activation' stamp: 'len 9/10/1999 03:29'!
relax
	self contraction: 0.0! !

!Muscle methodsFor: 'printing' stamp: 'len 9/26/1999 18:47'!
printOn: aStream
	aStream nextPutAll: self name; nextPutAll: ' ('; print: (self contraction roundTo: 0.01); nextPut: $)! !


!Muscle class methodsFor: 'instance creation' stamp: 'len 9/26/1999 18:07'!
fromArray: anArray
	| head tail |
	head _ anArray at: 3.
	tail _ anArray at: 2.
	^ self new
		name: (anArray at: 1);
		head: (B3DVector3 x: head first y: head second z: head third);
		tail: (B3DVector3 x: tail first y: tail second z: tail third);
		start: (anArray at: 4);
		end: (anArray at: 5);
		zone: (anArray at: 6);
		clamp: (anArray at: 7)! !

!Muscle class methodsFor: 'instance creation' stamp: 'len 9/20/1999 01:21'!
new
	^ super new initialize! !

!Muscle class methodsFor: 'examples' stamp: 'len 2/27/2000 21:50'!
exampleMuscles
	^ #(leftAngularDepressor leftFrontalisInner leftFrontalisMajor leftFrontalisOuter leftInnerLabiNasi leftLabiNasi leftLateralCorigator leftSecondaryFrontalis leftZygomaticMajor rightAngularDepressor rightFrontalisInner rightFrontalisMajor rightFrontalisOuter rightInnerLabiNasi rightLabiNasi rightLateralCorigator rightSecondaryFrontalis rightZygomaticMajor) collect: [ :each | self perform: each]! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:04'!
leftAngularDepressor
	^ self fromArray:
		#(LeftAngularDepressor
		(-1.5700 -2.2210 8.0250)
		(-2.5590 -4.2770 5.3510)
		0.3 4.5 65.0 1.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:04'!
leftFrontalisInner
	^ self fromArray:
		#(LeftFrontalisInner
		(-0.4870 3.6390 8.1010)
		(-0.3540 6.2470 7.2290)
		0.1 3.6 35.0 4.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:04'!
leftFrontalisMajor
	^ self fromArray:
		#(LeftFrontalisMajor
		(-2.3810 3.8300 8.0000)
		(-2.2440 6.3630 6.9690)
		0.1 3.7 65.0 0.5)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:05'!
leftFrontalisOuter
	^ self fromArray:
		#(LeftFrontalisOuter
		(-3.0950 3.9700 7.8950)
		(-3.6390 5.6480 5.9450)
		0.1 3.5 45.0 2.5)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:05'!
leftInnerLabiNasi
	^ self fromArray:
		#(LeftInnerLabiNasi
		(-1.0020 0.2170 8.4620)
		(-0.6380 2.0840 7.6610)
		0.1 4.5 35.0 1.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:05'!
leftLabiNasi
	^ self fromArray:
		#(LeftLabiNasi
		(-1.7760 -0.8340 8.2390)
		(-1.5600 1.8870 7.3320)
		0.1 5.2 35.0 3.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:05'!
leftLateralCorigator
	^ self fromArray:
		#(LeftLateralCorigator
		(-1.1700 4.6580 7.3560)
		(0.0000 3.2620 8.2080)
		0.5 3.0 45.0 3.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:05'!
leftSecondaryFrontalis
	^ self fromArray:
		#(LeftSecondaryFrontalis
		(-0.5840 3.0520 8.0550)
		(-0.9910 4.8620 8.0930)
		0.1 4.8 45.0 1.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:05'!
leftZygomaticMajor
	^ self fromArray:
		#(LeftZygomaticMajor
		(-1.5700	-2.2210	7.8200)
		(-3.8050	0.8680	6.6000)
		0.1 4.8 45.0 1.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:05'!
rightAngularDepressor
	^ self fromArray:
		#(RightAngularDepressor
		(1.5700 -2.2210 8.0250)
		(2.5590 -4.2770 5.3510)
		0.3 4.5 65.0 1.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:06'!
rightFrontalisInner
	^ self fromArray:
		#(RightFrontalisInner
		(0.4870 3.6390 8.1010)
		(0.3540 6.2470 7.2290)
		0.1 3.6 35.0 4.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:06'!
rightFrontalisMajor
	^ self fromArray:
		#(RightFrontalisMajor
		(2.3810 3.8300 8.0000)
		(2.2440 6.3630 6.9690)
		0.1 3.7 65.0 0.5)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:06'!
rightFrontalisOuter
	^ self fromArray:
		#(RightFrontalisOuter
		(3.0950 3.9700 7.8950)
		(3.6390 5.6480 5.9450)
		0.1 3.5 45.0 2.5)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:06'!
rightInnerLabiNasi
	^ self fromArray:
		#(RightInnerLabiNasi
		(1.0020 0.2170 8.4620)
		(0.6380 2.0840 7.6610)
		0.1 4.5 35.0 1.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:06'!
rightLabiNasi
	^ self fromArray:
		#(RightLabiNasi
		(1.7760 -0.8340 8.2390)
		(1.5600 1.8870 7.3320)
		0.1 5.2 35.0 3.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:06'!
rightLateralCorigator
	^ self fromArray:
		#(RightLateralCorigator
		(1.1700 4.6580 7.3560)
		(0.0000 3.2620 8.2080)
		0.5 3.0 45.0 3.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:06'!
rightSecondaryFrontalis
	^ self fromArray:
		#(RightSecondaryFrontalis
		(0.5840 3.0520 8.0550)
		(0.9910 4.8620 8.0930)
		0.1 4.8 45.0 1.0)! !

!Muscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:07'!
rightZygomaticMajor
	^ self fromArray:
		#(RightZygomaticMajor
		(1.5700 -2.2210 7.8200)
		(3.8050 0.8680 6.6000)
		0.1 4.8 45.0 1.0)! !


!SphincterMuscle class methodsFor: 'examples' stamp: 'len 1/13/2001 02:20'!
obicularisOris
	^ self new! !


!UpdatingSimpleSliderMorph methodsFor: 'accessing' stamp: 'len 9/28/1999 01:28'!
getValueSelector: aSymbol
	getValueSelector _ aSymbol asSymbol! !

!UpdatingSimpleSliderMorph methodsFor: 'stepping and presenter' stamp: 'len 9/28/1999 01:27'!
step
	super step.
	(target notNil and: [getValueSelector notNil]) ifTrue: [self adjustToValue: (target perform: getValueSelector)]! !

!UpdatingSimpleSliderMorph methodsFor: 'stepping and presenter' stamp: 'len 9/29/1999 03:52'!
stepTime
	^ 750! !


!Viseme methodsFor: 'initialization' stamp: 'len 1/29/2001 11:45'!
initialize
	contractions _ Dictionary new! !

!Viseme methodsFor: 'accessing' stamp: 'len 1/29/2001 11:45'!
at: muscleName
	^ contractions at: muscleName! !

!Viseme methodsFor: 'accessing' stamp: 'len 1/29/2001 11:45'!
at: muscleName put: aNumber
	^ contractions at: muscleName put: aNumber! !

!Viseme methodsFor: 'playing' stamp: 'len 1/29/2001 11:45'!
playOn: anAvatar
	contractions associationsDo: [ :assoc | (anAvatar muscles at: assoc key) contraction: assoc value]! !


!Viseme class methodsFor: 'instance creation' stamp: 'len 9/10/1999 03:06'!
new
	^ super new initialize! !

!Viseme class methodsFor: 'examples' stamp: 'len 1/13/2001 02:00'!
anger
	^ self new
		at: #LeftZygomaticMajor put: 0.00;
		at: #RightZygomaticMajor put: 0.00;
		at: #LeftAngularDepressor put: 0.70;
		at: #RightAngularDepressor put: 0.60;
		at: #LeftFrontalisInner put: 0.20;
		at: #RightFrontalisInner put: 0.00;
		at: #LeftFrontalisMajor put: 0.10;
		at: #RightFrontalisMajor put: 0.00;
		at: #LeftFrontalisOuter put: 2.00;
		at: #RightFrontalisOuter put: 2.00;
		at: #LeftLabiNasi put: 1.80;
		at: #RightLabiNasi put: 1.90;
		at: #LeftInnerLabiNasi put: 1.20;
		at: #RightInnerLabiNasi put: 1.10;
		at: #LeftLateralCorigator put: 1.40;
		at: #RightLateralCorigator put: 1.30;
		at: #LeftSecondaryFrontalis put: 0.20;
		at: #RightSecondaryFrontalis put: 0.30;
		yourself! !

!Viseme class methodsFor: 'examples' stamp: 'len 1/13/2001 02:00'!
disgust
	^ self new
		at: #LeftZygomaticMajor put: 0.80;
		at: #RightZygomaticMajor put: 0.10;
		at: #LeftAngularDepressor put: 0.00;
		at: #RightAngularDepressor put: 0.50;
		at: #LeftFrontalisInner put: 0.20;
		at: #RightFrontalisInner put: 0.00;
		at: #LeftFrontalisMajor put: 0.00;
		at: #RightFrontalisMajor put: 0.00;
		at: #LeftFrontalisOuter put: 0.40;
		at: #RightFrontalisOuter put: 1.70;
		at: #LeftLabiNasi put: 1.10;
		at: #RightLabiNasi put: 2.00;
		at: #LeftInnerLabiNasi put: 0.70;
		at: #RightInnerLabiNasi put: 0.20;
		at: #LeftLateralCorigator put: 2.30;
		at: #RightLateralCorigator put: 2.40;
		at: #LeftSecondaryFrontalis put: 0.00;
		at: #RightSecondaryFrontalis put: 0.00;
		yourself! !

!Viseme class methodsFor: 'examples' stamp: 'len 1/13/2001 02:01'!
fear
	^ self new
		at: #LeftZygomaticMajor put: 0.60;
		at: #RightZygomaticMajor put: 0.50;
		at: #LeftAngularDepressor put: 0.50;
		at: #RightAngularDepressor put: 0.50;
		at: #LeftFrontalisInner put: 0.20;
		at: #RightFrontalisInner put: 0.20;
		at: #LeftFrontalisMajor put: 0.60;
		at: #RightFrontalisMajor put: 0.50;
		at: #LeftFrontalisOuter put: 0.20;
		at: #RightFrontalisOuter put: 0.20;
		at: #LeftLabiNasi put: 0.20;
		at: #RightLabiNasi put: 0.20;
		at: #LeftInnerLabiNasi put: 0.10;
		at: #RightInnerLabiNasi put: 0.10;
		at: #LeftLateralCorigator put: 0.20;
		at: #RightLateralCorigator put: 0.20;
		at: #LeftSecondaryFrontalis put: 0.40;
		at: #RightSecondaryFrontalis put: 0.30;
		yourself! !

!Viseme class methodsFor: 'examples' stamp: 'len 1/13/2001 02:02'!
happiness
	^ self new
		at: #LeftZygomaticMajor put: 1.10;
		at: #RightZygomaticMajor put: 1.00;
		at: #LeftAngularDepressor put: 0.00;
		at: #RightAngularDepressor put: 0.00;
		at: #LeftFrontalisInner put: 0.80;
		at: #RightFrontalisInner put: 0.90;
		at: #LeftFrontalisMajor put: 0.20;
		at: #RightFrontalisMajor put: 0.20;
		at: #LeftFrontalisOuter put: 0.10;
		at: #RightFrontalisOuter put: 0.30;
		at: #LeftLabiNasi put: 0.00;
		at: #RightLabiNasi put: 0.00;
		at: #LeftInnerLabiNasi put: 0.00;
		at: #RightInnerLabiNasi put: 0.00;
		at: #LeftLateralCorigator put: 0.00;
		at: #RightLateralCorigator put: 0.00;
		at: #LeftSecondaryFrontalis put: 0.00;
		at: #RightSecondaryFrontalis put: 0.00;
		yourself! !

!Viseme class methodsFor: 'examples' stamp: 'len 1/13/2001 02:03'!
sadness
	^ self new
		at: #LeftZygomaticMajor put: 0.00;
		at: #RightZygomaticMajor put: 0.00;
		at: #LeftAngularDepressor put: 0.70;
		at: #RightAngularDepressor put: 0.70;
		at: #LeftFrontalisInner put: 3.10;
		at: #RightFrontalisInner put: 3.90;
		at: #LeftFrontalisMajor put: 0.00;
		at: #RightFrontalisMajor put: 0.00;
		at: #LeftFrontalisOuter put: 0.00;
		at: #RightFrontalisOuter put: 0.00;
		at: #LeftLabiNasi put: 0.20;
		at: #RightLabiNasi put: 0.70;
		at: #LeftInnerLabiNasi put: 0.20;
		at: #RightInnerLabiNasi put: 0.20;
		at: #LeftLateralCorigator put: 0.00;
		at: #RightLateralCorigator put: 0.00;
		at: #LeftSecondaryFrontalis put: 0.00;
		at: #RightSecondaryFrontalis put: 0.00;
		yourself! !

!Viseme class methodsFor: 'examples' stamp: 'len 1/13/2001 02:04'!
surprise
	^ self new
		at: #LeftZygomaticMajor put: 0.20;
		at: #RightZygomaticMajor put: 0.20;
		at: #LeftAngularDepressor put: 0.40;
		at: #RightAngularDepressor put: 0.40;
		at: #LeftFrontalisInner put: 1.40;
		at: #RightFrontalisInner put: 0.90;
		at: #LeftFrontalisMajor put: 0.50;
		at: #RightFrontalisMajor put: 0.40;
		at: #LeftFrontalisOuter put: 0.20;
		at: #RightFrontalisOuter put: 0.70;
		at: #LeftLabiNasi put: 0.00;
		at: #RightLabiNasi put: 0.00;
		at: #LeftInnerLabiNasi put: 0.00;
		at: #RightInnerLabiNasi put: 0.10;
		at: #LeftLateralCorigator put: 0.00;
		at: #RightLateralCorigator put: 0.00;
		at: #LeftSecondaryFrontalis put: 0.50;
		at: #RightSecondaryFrontalis put: 0.60;
		yourself! ! 


More information about the Squeak-dev mailing list