Add faceFollow, fix face contour rendering, add default eyes/ears

Three changesets bundled together:

- faceFollow (Camera/Neck) for the ARKit-blendshape face: it can now
  rotate with the mapped Body_Neck joint's own local axes instead of
  always billboarding toward the camera.

- Fixed a real correctness bug: the face was rendering as isolated
  dots. Verified against OpenPose's own published keypoint diagrams
  and source (FACE_PAIRS_RENDER_GPU, 63 pairs) that it should render
  connected jaw/eyebrow/nose/eye/mouth contour lines; full_limb_data()
  was also silently dropping face limbs entirely. Both fixed.

- Default eyes/ears: most rigs (HumanIK included) have no
  REye/LEye/REar/LEar joints, only Head/Nose, leaving those 4 slots
  permanently invisible. They now get a synthetic head-relative
  position when unmapped but Body_Nose is mapped, anchored at and
  rotating with the Nose joint's own orientation (not the camera) --
  toggleable via useDefaultEyesEars, always overridden by an explicit
  joint mapping. Also drops the RShoulder->REar / LShoulder->LEar
  lines from BODY_25 and COCO connectivity by request (a
  detection-robustness quirk of OpenPose's original network, not real
  anatomy) so ears stay leaf points -- a disclosed, deliberate
  deviation from upstream's otherwise-verbatim connectivity.

All verified against real Maya (2022/2023/2024), not just logic:
rotation math checked exact, explicit-mapping-overrides-fallback
checked, shoulder-ear removal checked against full_limb_data() output,
rendered test scenes visually confirmed against OpenPose's own
reference diagrams.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-07-14 10:12:10 +08:00
parent 417ff72850
commit 67b3deedbd
14 changed files with 471 additions and 178 deletions
+31 -23
View File
@@ -1,6 +1,6 @@
//Maya ASCII 2024 scene
//Name: openpose_arkit_face_test.ma
//Last modified: Tue, Jul 14, 2026 08:25:25 AM
//Last modified: Tue, Jul 14, 2026 10:10:17 AM
//Codeset: 950
requires maya "2024";
requires -nodeType "openposeCharacter" "openposeRenderer.py" "1.0.0";
@@ -10,14 +10,14 @@ fileInfo "product" "Maya 2024";
fileInfo "version" "2024";
fileInfo "cutIdentifier" "202310181224-69282f2959";
fileInfo "osv" "Windows 10 Pro v2009 (Build: 19045)";
fileInfo "UUID" "93C6E059-4B38-C365-F7D5-0FAD491D0DEB";
fileInfo "UUID" "85DD57C5-4B97-1CDE-6FD5-BFA49225A98F";
createNode transform -s -n "persp";
rename -uid "D6BB12A4-4481-B70D-81F9-22BC50DBF6A2";
rename -uid "E3491364-4B97-48C1-5E9B-578A13404F49";
setAttr ".v" no;
setAttr ".t" -type "double3" 28 21 28 ;
setAttr ".r" -type "double3" -27.938352729602379 44.999999999999972 -5.172681101354183e-14 ;
createNode camera -s -n "perspShape" -p "persp";
rename -uid "3B79812D-4CE2-EF69-FD29-D3819FB20809";
rename -uid "DD6D6127-4073-909D-6E02-1997E2D93C26";
setAttr -k off ".v" no;
setAttr ".fl" 34.999999999999993;
setAttr ".coi" 44.82186966202994;
@@ -26,12 +26,12 @@ createNode camera -s -n "perspShape" -p "persp";
setAttr ".man" -type "string" "persp_mask";
setAttr ".hc" -type "string" "viewSet -p %camera";
createNode transform -s -n "top";
rename -uid "7D9B1797-4CCF-180D-3705-9C9C4F956631";
rename -uid "035B1CE2-4DC2-F418-C617-688208D299F4";
setAttr ".v" no;
setAttr ".t" -type "double3" 0 1000.1 0 ;
setAttr ".r" -type "double3" -90 0 0 ;
createNode camera -s -n "topShape" -p "top";
rename -uid "02429A50-43C6-9AEF-C9A9-0EA56778BABE";
rename -uid "6E8EE682-497D-652E-715F-158DADC66B84";
setAttr -k off ".v" no;
setAttr ".rnd" no;
setAttr ".coi" 1000.1;
@@ -42,11 +42,11 @@ createNode camera -s -n "topShape" -p "top";
setAttr ".hc" -type "string" "viewSet -t %camera";
setAttr ".o" yes;
createNode transform -s -n "front";
rename -uid "E313E787-411D-6315-E6D5-878346B7C7C7";
rename -uid "53AD066A-4DDC-4765-95C1-9AB82429A5A2";
setAttr ".v" no;
setAttr ".t" -type "double3" 0 0 1000.1 ;
createNode camera -s -n "frontShape" -p "front";
rename -uid "CEB81F55-4481-E767-A275-09ACF3D57563";
rename -uid "2E5CFEDD-476C-0A25-F6B8-38A03B0877F8";
setAttr -k off ".v" no;
setAttr ".rnd" no;
setAttr ".coi" 1000.1;
@@ -57,12 +57,12 @@ createNode camera -s -n "frontShape" -p "front";
setAttr ".hc" -type "string" "viewSet -f %camera";
setAttr ".o" yes;
createNode transform -s -n "side";
rename -uid "23726E62-4236-BA09-5DDB-A8B4AB6467DE";
rename -uid "A10C8B41-4A98-FACA-5E06-7B8508956AA9";
setAttr ".v" no;
setAttr ".t" -type "double3" 1000.1 0 0 ;
setAttr ".r" -type "double3" 0 90 0 ;
createNode camera -s -n "sideShape" -p "side";
rename -uid "0EF9B535-4F25-E296-6FE9-17897B0CD5F8";
rename -uid "72EA7ED6-4C2B-4DE3-569A-D2B1A7BFABE4";
setAttr -k off ".v" no;
setAttr ".rnd" no;
setAttr ".coi" 1000.1;
@@ -72,21 +72,27 @@ createNode camera -s -n "sideShape" -p "side";
setAttr ".man" -type "string" "side_mask";
setAttr ".hc" -type "string" "viewSet -s %camera";
setAttr ".o" yes;
createNode joint -n "Head";
rename -uid "10AD57B3-4A53-D241-702A-E4B87D617D75";
setAttr ".t" -type "double3" 0 150 0 ;
createNode joint -n "Neck";
rename -uid "98591D1D-4B4C-6895-14DE-4AB34B1EA03A";
setAttr ".t" -type "double3" 0 140 0 ;
setAttr ".mnrl" -type "double3" -360 -360 -360 ;
setAttr ".mxrl" -type "double3" 360 360 360 ;
createNode joint -n "Head" -p "Neck";
rename -uid "9A0315AF-4863-056E-3EDE-E493010F290C";
setAttr ".t" -type "double3" 0 10 0 ;
setAttr ".mnrl" -type "double3" -360 -360 -360 ;
setAttr ".mxrl" -type "double3" 360 360 360 ;
createNode transform -n "transform1";
rename -uid "AC0B13DC-4C96-222F-1C95-D881328B821A";
rename -uid "64FBC6C8-4532-92E7-B69C-14806ED14FDA";
createNode openposeCharacter -n "openposeCharacter_ARKitFace" -p "transform1";
rename -uid "91BF3ED3-4092-9E34-128B-1C98376C9C10";
rename -uid "99770FC8-4339-FCCF-4911-D5A1DE12F05B";
setAttr -k off ".v";
setAttr -s 2 ".tj";
setAttr ".fsrc" 1;
setAttr -s 52 ".bsw";
setAttr -s 52 ".bsw";
createNode transform -n "faceControl";
rename -uid "BEF04EC7-4C59-6B22-48FA-208B994FD89B";
rename -uid "6B4BD06A-44E7-A162-C911-A6860437F938";
addAttr -ci true -sn "eyeBlinkLeft" -ln "eyeBlinkLeft" -min 0 -max 1 -at "float";
addAttr -ci true -sn "eyeLookDownLeft" -ln "eyeLookDownLeft" -min 0 -max 1 -at "float";
addAttr -ci true -sn "eyeLookInLeft" -ln "eyeLookInLeft" -min 0 -max 1 -at "float";
@@ -194,25 +200,25 @@ createNode transform -n "faceControl";
setAttr -k on ".noseSneerRight";
setAttr -k on ".tongueOut";
createNode lightLinker -s -n "lightLinker1";
rename -uid "6F41ABE6-4FC9-CBA9-3A4A-3C88AFFEDA05";
rename -uid "6D455AD6-40A9-F99D-5089-B0A48DE96155";
setAttr -s 2 ".lnk";
setAttr -s 2 ".slnk";
createNode displayLayerManager -n "layerManager";
rename -uid "C5E3AE68-4041-3C21-D33D-2DBCA8E53402";
rename -uid "89D07F4B-4D2B-38E3-1982-E49382568D7B";
createNode displayLayer -n "defaultLayer";
rename -uid "7E1F3A70-4A01-B94C-04B6-24ABE836AECA";
rename -uid "FE3D0295-4D3E-B21D-61C6-E48A8F983B9A";
setAttr ".ufem" -type "stringArray" 0 ;
createNode renderLayerManager -n "renderLayerManager";
rename -uid "E2FC1CAE-4BC5-8835-9145-E2AFED84D0D6";
rename -uid "D3652996-4893-A8CF-67F1-B39C47121B22";
createNode renderLayer -n "defaultRenderLayer";
rename -uid "711E2B13-42DB-052A-1562-1C99F88A0E30";
rename -uid "7B692699-4A43-99A7-033B-D8AB3ECF5B0E";
setAttr ".g" yes;
createNode script -n "uiConfigurationScriptNode";
rename -uid "F0132003-4E9D-D0A6-A39C-F6958ABF910E";
rename -uid "C885E9DA-4CD9-2E2D-D858-D7960EC8BBFF";
setAttr ".b" -type "string" "// Maya Mel UI Configuration File.\n// No UI generated in batch mode.\n";
setAttr ".st" 3;
createNode script -n "sceneConfigurationScriptNode";
rename -uid "5E8354DD-4768-B99B-F133-489A3680AEB2";
rename -uid "D790ABD8-4269-6467-7F7B-0B99D3F4D4A4";
setAttr ".b" -type "string" "playbackOptions -min 1 -max 120 -ast 1 -aet 200 ";
setAttr ".st" 6;
select -ne :time1;
@@ -259,7 +265,9 @@ select -ne :defaultColorMgtGlobals;
select -ne :hardwareRenderGlobals;
setAttr ".ctrs" 256;
setAttr ".btrs" 512;
connectAttr "Neck.s" "Head.is";
connectAttr "Head.msg" "openposeCharacter_ARKitFace.tj[0]";
connectAttr "Neck.msg" "openposeCharacter_ARKitFace.tj[1]";
connectAttr "faceControl.eyeBlinkLeft" "openposeCharacter_ARKitFace.bsw[0]";
connectAttr "faceControl.eyeLookDownLeft" "openposeCharacter_ARKitFace.bsw[1]";
connectAttr "faceControl.eyeLookInLeft" "openposeCharacter_ARKitFace.bsw[2]";