STEAM GROUP
Blender Source Tools BleST
STEAM GROUP
Blender Source Tools BleST
273
IN-GAME
1,624
ONLINE
Founded
8 November, 2013
All Discussions > Help > Topic Details
Bad Company 5 Jan, 2024 @ 10:54pm
Help with Shape keys/flexes in .QC file
I've been trying to port a model from blender to SFM for a while now. The models are in .smd format and I've been trying to program the flex/shape keys with the head model's .VTA file.

Here's what it looks like:
$model "Modelname" "Body_Mesh.smd" $model flextest "Head_Mesh.smd" { flexfile "Head_Mesh.vta"{ defaultflex frame 0 flexpair "closeeyeL" 1 frame 1 flexpair "closeeyeR" 1 frame 2 flexpair "closebotheyes" 1 frame 3 flexpair "eyeshrink1L" 1 frame 4 flexpair "eyeshrink1R" 1 frame 5 flexpair "eyeshrink1" 1 frame 6 flexpair "eyeexpand1L" 1 frame 7 flexpair "eyeexpand1R" 1 frame 8 flexpair "eyeexpand1" 1 frame 9 flexpair "MouthA" 1 frame 10 flexpair "MouthO" 1 frame 11 flexpair "MouthE" 1 frame 12 flexpair "Mouth1" 1 frame 13 flexpair "smile" 1 frame 14 flexpair "eyebrows1L" 1 frame 15 flexpair "eyebrows1R" 1 frame 16 flexpair "eyebrows1" 1 frame 17 flexpair "eyebrows2L" 1 frame 18 flexpair "eyebrows2R" 1 frame 19 flexpair "eyebrows2" 1 frame 20 flexpair "eyebrows3L" 1 frame 21 flexpair "eyebrows3R" 1 frame 22 flexpair "eyebrows3" 1 frame 23 flexpair "eyebrows4L" 1 frame 24 flexpair "eyebrows4R" 1 frame 25 flexpair "eyebrows4" 1 frame 26 } flexcontroller closeeyeL range -1 1 "closeeyeL" flexcontroller closeeyeR range -1 1 "closeeyeR" flexcontroller closebotheyes range -1 1 "closebotheyes" flexcontroller eyeshrink1L range -1 1 "eyeshrink1.L" flexcontroller eyeshrink1R range -1 1 "eyeshrink1R" flexcontroller eyeshrink1 range -1 1 "eyeshrink1" flexcontroller eyeexpand1L range -1 1 "eyeexpand1L" flexcontroller eyeexpand1R range -1 1 "eyeexpand1R" flexcontroller eyeexpand1 range -1 1 "eyeexpand1" flexcontroller MouthA range -1 1 "MouthA" flexcontroller MouthO range -1 1 "MouthO" flexcontroller MouthE range -1 1 "MouthE" flexcontroller Mouth1 range -1 1 "Mouth1" flexcontroller smile range -1 1 "smile" flexcontroller eyebrows1L range -1 1 "eyebrows1L" flexcontroller eyebrows1R range -1 1 "eyebrows1R" flexcontroller eyebrows1 range -1 1 "eyebrows1" flexcontroller eyebrows2L range -1 1 "eyebrows2L" flexcontroller eyebrows2R range -1 1 "eyebrows2R" flexcontroller eyebrows2 range -1 1 "eyebrows2" flexcontroller eyebrows3L range -1 1 "eyebrows3L" flexcontroller eyebrows3R range -1 1 "eyebrows3R" flexcontroller eyebrows3 range -1 1 "eyebrows3" flexcontroller eyebrows4L range -1 1 "eyebrows4L" flexcontroller eyebrows4R range -1 1 "eyebrows4R" flexcontroller eyebrows4 range -1 1 "eyebrows4" %closeeyeL = closeeyeL %closeeyeR = closeeyeR %closebotheyes = closebotheyes %eyeshrink1L = eyeshrink1L %eyeshrink1R = eyeshrink1R %eyeshrink1 = eyeshrink1 %eyeexpand1L = eyeexpand1L %eyeexpand1R = eyeexpand1R %eyeexpand1 = eyeexpand1 %MouthA = MouthA %MouthO = MouthO %MouthE = MouthE %Mouth1 = Mouth1 %smile = smile %eyebrows1L = eyebrows1L %eyebrows1R = eyebrows1R %eyebrows1 = eyebrows1 %eyebrows2L = eyebrows2L %eyebrows2R = eyebrows2R %eyebrows2 = eyebrows2 %eyebrows3L = eyebrows3L %eyebrows3R = eyebrows3R %eyebrows3 = eyebrows3 %eyebrows4L = eyebrows4L %eyebrows4R = eyebrows4R %eyebrows4 = eyebrows4 }


Crowbar keeps giving me an error telling me that "closeeyeL" is an unknown flex, even the it exists in the .VTA file. I checked if there was a typo, there was none and it still gives me an error. Before anyone asks "why don't you just export to .DMX?" I would've if I knew how to reduce the vertex's bone influences or weight links, as it's called in Blender, without destroying the model. I already tried exporting it to DMX, by removing the vertex groups and the flexes worked but the model was broken.

Can anyone help me here, PLZ?
< >
Showing 1-2 of 2 comments
Bad Company 5 Jan, 2024 @ 11:00pm 
Okay so, I tried using the weight cull threshold when exporting, and this time it exported into DMX with no issues so far. I still would like to know how to make the flex keys work for .smd.
Zappy 6 Jan, 2024 @ 6:58am 
Originally posted by Bad Company:
$model flextest "Head_Mesh.smd" { flexfile "Head_Mesh.vta"{ flexpair "closeeyeL" 1 frame 1 } flexcontroller closeeyeL range -1 1 "closeeyeL" %closeeyeL = closeeyeL }
Here, I've isolated 5 lines of text in the QC file. In order, they...

- Load the "Head_Mesh.smd" file as a mesh, with the internal name "flextest". (The internal name is the name of its body group in Source Filmmaker.)
- Load the "Head_Mesh.vta" file to add vertex "shape keys" (flexes) to the above mesh.
- Split the first shape key in the VTA file into two internal flexes in the model. You supplied the name "closeeyeL", so the resulting internal flexes will be named "closeeyeLL" and "closeeyeLR", respectively. The one suffixed with "L" only affects the left side of the model, and likewise for "R" and the right side - there's a 1-unit-wide area of "smoothing" between the two on the middle of the model.
- Create a "flex controller" (controller) (the slider that you interact with in Source Filmmaker to control the flex). The controller "group" name is unused, so we'll ignore the first "closeeyeL". You specify a slider range from -1 to 1, but you'd usually only want it to range from 0 to 1 (or -45 to 45 for eyes_updown and eyes_rightleft). The name of the controller is "closeeyeL", so that's the name of the slider that you'll see in Source Filmmaker.
- Attempt to assign an internal flex named "closeeyeL" to a controller named "closeeyeL" - but you don't have an internal flex with that name! The closest are "closeeyeLL" and "closeeyeLR", since you split the VTA's shape key into a separate internal flex for each side.

Given that you seem to have "L" and "R" shape keys in the VTA, you probably meant to use "Flex" to load them as-is, not "FlexPair" to auto-split each of them further. You'll probably want to do something like this instead:
$Model flextest "Head_Mesh.smd" { FlexFile "Head_Mesh.vta"{ Flex "closeeyeL" Frame 1 Flex "closeeyeR" Frame 2 Flex "closebotheyes" Frame 3 } FlexController X "right_closeeye" "left_closeeye" "closebotheyes" %closeeyeL = left_closeeye %closeeyeR = right_closeeye %closebotheyes = closebotheyes }
Here, I use "Flex" instead of "FlexPair", to load flexes as-is without splitting them and giving them extra suffixes. Then, I use a single "FlexController" line to create all controllers. The controllers don't need to have the same names as the internal flexes - I name the controllers "right_closeeye" and "left_closeeye" to make a single stereo slider in Source Filmmaker (it's important to make the "right_" and "left_" controllers in that order). Then, I assign "closeeyeL" and "closeeyeR" to the stereo "closeeye" controllers, and assign "closebotheyes" to a non-stereo controller named "closebotheyes". (You can also use math to combine all three flexes into a single stereo slider, blending between the "side-only" and "combined" flexes based on how active each of them are.)


Originally posted by Bad Company:
defaultflex frame 0
"DefaultFlex" is used to automatically activate a certain flex when no other flexes are active. Frame 0 of a VTA is the original shape, so "DefaultFlex Frame 0" is useless - feel free to delete this line.


Originally posted by Bad Company:
- "closeeyeL" is an unknown flex, even the it exists in the .VTA file. -
Technically, VTA shape keys don't have names, only frame numbers. The "closeeyeL" in the VTA is just a "comment", ignored by StudioMDL (the model compiler).

You could have the first shape key in Blender called "Foo" and export it as a VTA. "Foo" will now be frame 1 of the VTA file. Then, you can use "Flex Bar Frame 1" in the QC to load frame 1 of the VTA. Frame 1 of the VTA will now be a flex named "Bar" in the model. Then, you can use "FlexController X Baz" to create a controller, and use "%Bar = Qux" to assign it. "Bar" is now controlled by a "Qux" slider.
Last edited by Zappy; 6 Jan, 2024 @ 6:59am
< >
Showing 1-2 of 2 comments
Per page: 1530 50

All Discussions > Help > Topic Details