补充:关于乱窜的,主要是大腿乱窜大腿一旦移动到限制就会乱窜
补充:Vector3的起始点在模型背后,目前是mixamorigLeftUpLeg大腿这一块会出现乱窜
我正在尝试为我的 ik 驱动的 fbx 角色模型的四肢添加约束,希望防止模型做出反人类的行为。 我目前正在尝试使用Vector3来约束ik链,但我不知道Vector3如何作用于模型。 我对限制了解不多。 以下是我的 ik 链值中的约束:
leftLeg: {
target: '左腿控制_L',
effector: 'mixamorigLeftFoot',
links: [
{
name: 'mixamorigLeftLeg',
rotationMin: new THREE.Vector3(-Math.PI / 1.2, 0, 0), // 不允许向前弯曲,也不允许围绕Y轴和Z轴的旋转
rotationMax: new THREE.Vector3(0, 0, 0) // 允许向后弯曲90度,不允许围绕Y轴和Z轴的旋转
},
{
name: 'mixamorigLeftUpLeg',
rotationMin: new THREE.Vector3(-Math.PI / 1.5, -Math.PI, -Math.PI),
rotationMax: new THREE.Vector3(Math.PI / 1.7, Math.PI, -Math.PI/2)
}
]
},

为什么当触及 Vector3 约束时它会鬼畜和乱窜?
补充代码
function loadModel(modelPath = '/static/resources/models/pg_ik_Modify_parent.fbx') {
console.log(upload_file_name)
const loader = new FBXLoader();
loader.load(modelPath, function (pg) {
// 将模型的初始位置设置为 (x, y, z)
pg.rotation.set(0, 0.7, 0);
pg.position.set(0, -100, 0);
scene.add(pg);
console.log(scene);
pg.traverse(function (child) {
if (child.isMesh) {
// 检查子对象是否有材质和贴图
const material = child.material;
if (material && material.map) {
console.log(material.map.name);
textureFileName = material.map.name
} else {
console.log('此子对象没有贴图。');
}
}
if (child.isSkinnedMesh) {
skinnedMesh = child; // 确保这一行成功找到了网格
// 找到skinnedMesh后,再将pg添加到场景中
scene.add(pg);
IKsolvers = setupIKSolvers(skinnedMesh, limbIKData); // 现在可以初始化IKsolvers
// 创建并添加表示本地轴的辅助对象
const axesHelper2 = new THREE.AxesHelper(50); // 长度为5的轴辅助对象
pg.add(axesHelper2); // 将辅助对象添加到立方体上
// 使用新的创建控制器的方法
rootbones.右手控制_R = pg.getObjectByName('右手控制_R');
rootbones.左手控制_L = pg.getObjectByName('左手控制_L');
rootbones.右腿控制_R = pg.getObjectByName('右腿控制_R');
rootbones.左腿控制_L = pg.getObjectByName('左腿控制_L');
transformControls = createTransformControl('右手控制_R');
transformControls2 = createTransformControl('左手控制_L');
transformControls3 = createTransformControl('右腿控制_R');
transformControls4 = createTransformControl('左腿控制_L');
}
}
);
});
}
function createTransformControl(boneName) {
let control = new TransformControls(camera, renderer.domElement);
control.size = 0.75;
control.attach(rootbones[boneName]);
scene.add(control);
control.setMode('translate');
// 添加鼠标事件监听器,用于开启和关闭IK更新
control.addEventListener('mouseDown', () => {
controls.enabled = false;
shouldUpdateIK = true;
});
control.addEventListener('mouseUp', () => {
controls.enabled = true;
shouldUpdateIK = false;
});
return control;
}
const limbIKData = {
leftArm: {
target: '左手控制_L',
effector: 'mixamorigLeftHand',
links: [
{
name: 'mixamorigLeftForeArm',
rotationMin: new THREE.Vector3(-Math.PI / 20, -Math.PI / 8, -1), // 限制小臂向下的旋转范围,防止反折
rotationMax: new THREE.Vector3(Math.PI / 1.8, Math.PI / 2, 1) // 保持其他轴向的旋转范围不变
},
{
name: 'mixamorigLeftArm',
rotationMin: new THREE.Vector3(-Math.PI / 2, -Math.PI / 8, -1), // 减小向上和内侧旋转的范围
rotationMax: new THREE.Vector3(Math.PI / 2, Math.PI / 2, 1) // 保持向下和向外的旋转范围不变
}
]
},
rightArm: {
target: '右手控制_R',
effector: 'mixamorigRightHand',
links: [
{
name: 'mixamorigRightForeArm',
rotationMin: new THREE.Vector3(-Math.PI / 20, -Math.PI / 8, -1), // 限制小臂向下的旋转范围,防止反折
rotationMax: new THREE.Vector3(Math.PI / 1.8, Math.PI / 2, 1) // 保持其他轴向的旋转范围不变
},
{
name: 'mixamorigRightArm',
rotationMin: new THREE.Vector3(-Math.PI / 2, -Math.PI / 8, -1), // 减小向上和内侧旋转的范围
rotationMax: new THREE.Vector3(Math.PI / 2, Math.PI / 2, 1) // 保持向下和向外的旋转范围不变
}
]
},
leftLeg: {
target: '左腿控制_L',
effector: 'mixamorigLeftFoot',
links: [
{
name: 'mixamorigLeftLeg',
rotationMin: new THREE.Vector3(-Math.PI / 1.2, 0, 0), // 不允许向前弯曲,也不允许围绕Y轴和Z轴的旋转
rotationMax: new THREE.Vector3(0, 0, 0) // 允许向后弯曲90度,不允许围绕Y轴和Z轴的旋转
},
{
name: 'mixamorigLeftUpLeg',
rotationMin: new THREE.Vector3(-Math.PI , -Math.PI / 2, -Math.PI), // 不允许向前弯曲,也不允许围绕Y轴和Z轴的旋转
rotationMax: new THREE.Vector3(Math.PI , Math.PI / 2, Math.PI) // 允许向后弯曲90度,不允许围绕Y轴和Z轴的旋转
}
]
},
// rotationMin: new THREE.Vector3(-Math.PI / 1.5, -Math.PI, -Math.PI), // 不允许向前弯曲,也不允许围绕Y轴和Z轴的旋转
// rotationMax: new THREE.Vector3(Math.PI / 1.7, Math.PI, -Math.PI / 2) // 允许向后弯曲90度,不允许围绕Y轴和Z轴的旋转
rightLeg: {
target: '右腿控制_R',
effector: 'mixamorigRightFoot',
links: [
{
name: 'mixamorigRightLeg',
rotationMin: new THREE.Vector3(-Math.PI / 1.2, 0, 0), // 不允许向前弯曲,也不允许围绕Y轴和Z轴的旋转
rotationMax: new THREE.Vector3(0, 0, 0) // 允许向后弯曲90度,不允许围绕Y轴和Z轴的旋转
},
{
name: 'mixamorigRightUpLeg',
rotationMin: new THREE.Vector3(-Math.PI, -Math.PI / 2, -Math.PI), // 不允许向前弯曲,也不允许围绕Y轴和Z轴的旋转
rotationMax: new THREE.Vector3(Math.PI, Math.PI / 2, Math.PI) // 允许向后弯曲90度,不允许围绕Y轴和Z轴的旋转
}
]
}
//rotationMin: new THREE.Vector3(-Math.PI / 2, -Math.PI / 20, Math.PI / 2), // 不允许向前弯曲,也不允许围绕Y轴和Z轴的旋转
//rotationMax: new THREE.Vector3(Math.PI / 2, Math.PI / 20, Math.PI * 1.5) // 允许向后弯曲90度,不允许围绕Y轴和Z轴的旋转
// 更多的肢体可以按照此格式继续添加
};
function setupIKSolvers(skinnedMesh, limbIKData) {
const IKsolvers = {};
for (const limbName in limbIKData) {
const limb = limbIKData[limbName];
const boneArray = skinnedMesh.skeleton.bones;
const targetBone = boneArray.find(bone => bone.name === limb.target);
const effectorBone = boneArray.find(bone => bone.name === limb.effector);
if (!targetBone || !effectorBone) {
console.error(`IK setup error: Target or effector bone not found for ${limbName}.`);
continue;
}
const links = limb.links.map(link => {
const linkBone = boneArray.find(bone => bone.name === link.name);
if (!linkBone) {
console.error(`IK setup error: Link bone not found: ${link.name}.`);
return null;
}
const linkData = {
index: boneArray.indexOf(linkBone)
};
// 仅当旋转最小和最大约束存在时才添加到链环节
if (link.rotationMin) {
linkData.rotationMin = link.rotationMin;
}
if (link.rotationMax) {
linkData.rotationMax = link.rotationMax;
}
return linkData;
}).filter(link => link !== null);
if (links.length !== limb.links.length) {
console.error(`IK setup error: Not all link bones found for ${limbName}.`);
continue;
}
const ik = {
target: boneArray.indexOf(targetBone),
effector: boneArray.indexOf(effectorBone),
links: links,
};
// 在这里,你需要一个支持旋转约束的IK解算器。这可能需要对CCDIKSolver进行扩展或使用其他支持约束的解算器
IKsolvers[limbName] = new CCDIKSolver(skinnedMesh, [ik]);
const ccdikhelper = new CCDIKHelper(skinnedMesh, [ik], 0.01);
scene.add(ccdikhelper);
}
return IKsolvers;
}