コード例 #1
0
        /// <summary>
        /// Смешивает изменения блендшейпов между собой с разной интенсивностью, получая новый блендшейп
        /// Используется для генерирования визем для vrchat на основании нескольких ключевых визем (аналогично cats плагину для блендера)
        /// </summary>
        public static WowVrcFileData.BlendshapeData.BoneData[] MixBlendshapeBoneChanges(BlendshapeBoneChangesWithIntensity[] blendshapeBoneChangesWithIntensity)
        {
            // <имя_кости, list<tuple<локальное изменение трансформа кости, интенсивность изменения>>>
            var changes = new Dictionary <string, List <Tuple <WowTransform, float> > >();

            foreach (var blendshapeBoneChangesWithIntensityItem in blendshapeBoneChangesWithIntensity)
            {
                foreach (var boneChange in blendshapeBoneChangesWithIntensityItem.BlendShapeBoneChanges)
                {
                    List <Tuple <WowTransform, float> > transforms;

                    if (!changes.ContainsKey(boneChange.Name))
                    {
                        transforms = new List <Tuple <WowTransform, float> >();
                        changes[boneChange.Name] = transforms;
                    }
                    else
                    {
                        transforms = changes[boneChange.Name];
                    }

                    transforms.Add(new Tuple <WowTransform, float>(boneChange.LocalTransform, blendshapeBoneChangesWithIntensityItem.Intensity));
                }
            }

            return(changes
                   .Select(change =>
            {
                var transform = new WowTransform
                {
                    position = new Vec3(0, 0, 0),
                    rotation = Quat.Create(),
                    scale = new Vec3(1, 1, 1)
                };

                foreach (var transformWithIntensity in change.Value)
                {
                    var position = Vec3.Lerp(new Vec3(0, 0, 0), transformWithIntensity.Item1.position, transformWithIntensity.Item2);

                    transform.position.X += position.X;
                    transform.position.Y += position.Y;
                    transform.position.Z += position.Z;

                    var rotation = Quat.Slerp(Quat.Create(), transformWithIntensity.Item1.rotation, transformWithIntensity.Item2);

                    transform.rotation = Quat.Multiply(transform.rotation, rotation);

                    var scale = Vec3.Lerp(new Vec3(1, 1, 1), transformWithIntensity.Item1.scale, transformWithIntensity.Item2);

                    transform.scale.X *= scale.X;
                    transform.scale.Y *= scale.Y;
                    transform.scale.Z *= scale.Z;
                }

                return new WowVrcFileData.BlendshapeData.BoneData
                {
                    Name = change.Key,
                    LocalTransform = transform
                };
            })
                   .ToArray());
        }
コード例 #2
0
        private static void RotateShoulderAttachments(WowObject characterWowObject, string attachmentBoneName, string upperArmBoneName, float rotationAngle)
        {
            var shoulderAttachment = characterWowObject.FindBoneByName(attachmentBoneName);
            var upperArm           = characterWowObject.FindBoneByName(upperArmBoneName);

            if (shoulderAttachment != null && upperArm != null)
            {
                var change = new WowVrcFileData.BlendshapeData.BoneData[] { new WowVrcFileData.BlendshapeData.BoneData()
                                                                            {
                                                                                LocalTransform = new WowTransform()
                                                                                {
                                                                                    position = new Vec3(),
                                                                                    rotation = Quat.RotateY(Quat.Create(), rotationAngle),
                                                                                    scale    = new Vec3(1f, 1f, 1f)
                                                                                },
                                                                                Name = upperArmBoneName
                                                                            } };

                foreach (var obj in shoulderAttachment.AttachedWowObjects)
                {
                    foreach (var mesh in obj.Meshes)
                    {
                        var basicBakedBlendshape = BlendShapeUtility.BakeBlendShape(obj.GlobalPosition, mesh.Vertices, characterWowObject.Bones, change, 1f);

                        foreach (var basicBakedBlendshapeElement in basicBakedBlendshape)
                        {
                            mesh.Vertices[basicBakedBlendshapeElement.Key].Position = new Vec3(basicBakedBlendshapeElement.Value.Position.X, basicBakedBlendshapeElement.Value.Position.Y, basicBakedBlendshapeElement.Value.Position.Z);
                            mesh.Vertices[basicBakedBlendshapeElement.Key].Normal   = new Vec3(basicBakedBlendshapeElement.Value.Normal.X, basicBakedBlendshapeElement.Value.Normal.Y, basicBakedBlendshapeElement.Value.Normal.Z);
                        }
                    }
                }
            }
        }