Skip to content

BSFaceGenNiNode::SkinSingleGeometry_1403d8840 on 1.5.97

DaymareOn edited this page Mar 13, 2023 · 4 revisions

Summary: find in the given BSGeometry the existing bones mentioned in the given BSTriShape, set them into the BSTrishape, and declare the BSFaceGenNiNode as their parent.

This function is called by SkinAllGeometry for each TriShape child of the BSFaceGenNiNode. It is called by another function too, documented here.

In this function:

if we have a skinData for the skinInstance of the TriShape child, we get the NiAVObject bones of the skinInstance, the number of bones declared in the skinData, and the BSFaceGenModelExtraData of the TriShape.
Then, for each bone,

  • we get the bone name in the BSFaceGenModelExtraData, and we look into the given BSGeometry for the NiAVObject bone that has that name.
  • We set this bone in the skin instance bones, and the related World transform too.

void BSFaceGenNiNode::SkinSingleGeometry
(BSFaceGenNiNode *this,BSGeometry *a_geometry,BSTriShape *thischild_as_trishape)
{
BSFaceGenModelExtraData *childExtraData;
BSFixedString *boneName;
char *boneHasValue;
NiAVObject *boneFoundInGeometry;
uint boneIndex;
longlong boneOffset;
uint bonesNb;
NiSkinInstance *childSkin;
NiAVObject **childSkinBones;
NiSkinData *childSkinData;

if (((thischild_as_trishape != (BSTriShape *)0x0) &&
(childSkin = (thischild_as_trishape->skinInstance)._ptr, childSkin != (NiSkinInstance *)0x0))
&& (childSkinData = (childSkin->skinData)._ptr, childSkinData != (NiSkinData *)0x0)) {
childSkinBones = childSkin->bones;
bonesNb = childSkinData->bones;
if ((childSkinBones != (NiAVObject **)0x0) && (bonesNb != 0)) {
boneIndex = 0;
if (bonesNb != 0) {
boneOffset = 0;
do {
The DAT contains the looked name.
Why is this operation in the loop rather than outside?!
childExtraData =
(BSFaceGenModelExtraData *)
GetExtraData_140c60ad0(thischild_as_trishape,(longlong *)&DAT_142f07cb0);
if ((childExtraData == (BSFaceGenModelExtraData *)0x0) || (MaxNumber < boneIndex)) {
When no extra data or too many bone names
boneName = (BSFixedString *)FUN_140132d60();
}
else {
Nominal case
boneName = childExtraData->bones + boneIndex;
}
boneHasValue = BSFixedString::HasValue_140c28fe0(boneName);
if ((int)boneHasValue == 0) {
boneFoundInGeometry =
(NiAVObject *)
(*(code *)a_geometry->vtable->getObjectByName)
(a_geometry,*(longlong *)(boneOffset + (longlong)childSkinBones) + 0x10);
}
else {
boneFoundInGeometry =
(NiAVObject *)(*(code *)a_geometry->vtable->getObjectByName)(a_geometry,boneName);
}
if (boneFoundInGeometry != (NiAVObject *)0x0) {
*(NiAVObject **)(boneOffset + (longlong)childSkin->bones) = boneFoundInGeometry;
*(NiTransform **)(boneOffset + (longlong)childSkin->boneWorldTransforms) =
&boneFoundInGeometry->world;
}
boneIndex = boneIndex + 1;
boneOffset = boneOffset + 8;
} while (boneIndex < bonesNb);
}
childSkin->rootParent = (NiAVObject *)this;
}
}
return;
}