示例#1
0
    public void GenerateFromCatsButtonClickHandler()
    {
        if (_openedFile == null)
        {
            return;
        }

        UpdateChanges();

        var res = new Dictionary <string, Dictionary <string, BoneData> >();

        foreach (var catsVisemeMixerDataElement in _catsVisemeMixerData)
        {
            var blendshapeBoneChangesWithIntensity = catsVisemeMixerDataElement.Value
                                                     .Select(x => new BlendShapeUtility.BlendshapeBoneChangesWithIntensity()
            {
                BlendShapeBoneChanges = ConvertBlendshapeBonesToFile(_blendshapeData[x.Key].Bones),
                Intensity             = x.Value
            })
                                                     .ToArray();

            res.Add(catsVisemeMixerDataElement.Key, ConvertBlendshapeBonesFromFile(BlendShapeUtility.MixBlendshapeBoneChanges(blendshapeBoneChangesWithIntensity)));
        }

        foreach (var resItem in res)
        {
            _blendshapeData[resItem.Key].Bones = resItem.Value;
        }

        // Если меняем на этот же блендшейп, то обновлять ненужно, т.к. смысл этой операции наоборот из измененного состояния обновить отображение (иначе получится затирание данных)
        SelectBlendshape(_selectedblendShapeName, false);
    }
示例#2
0
    private void UpdateChanges()
    {
        UpdateBonesToSelectedBlendshape();

        // Если сейчас выбран basic блендшейп - запекаем в _basicVertexPositions измененные вершины на основании него
        if (_selectedblendShapeName == WowVrcFileData.BlendshapeData.basicBlendshapeName)
        {
            var basicVertexChanges = BlendShapeUtility.BakeBlendShape(
                _character.WowObject.GlobalPosition,
                _character.WowObject.MainMesh.Vertices,
                _character.WowObject.Bones,
                ConvertBlendshapeBonesToFile(_blendshapeData[WowVrcFileData.BlendshapeData.basicBlendshapeName].Bones),
                1f);

            _defaultVertexPositions.CopyTo(_basicVertexPositions, 0);
            _defaultVertexNormals.CopyTo(_basicVertexNormals, 0);
            foreach (var basicVertexChange in basicVertexChanges)
            {
                _basicVertexPositions[basicVertexChange.Key] = new Vector3(basicVertexChange.Value.Position.X, basicVertexChange.Value.Position.Y, basicVertexChange.Value.Position.Z);
                _basicVertexNormals[basicVertexChange.Key]   = new Vector3(basicVertexChange.Value.Normal.X, basicVertexChange.Value.Normal.Y, basicVertexChange.Value.Normal.Z);
            }
        }
    }
        public static bool ExportToFbx(this WowVrcFile file, string exportDirectory, bool prepareForVRChat, float scale, out string warnings)
        {
            var exporter = new WowModelExporter();

            WowObject characterWowObject;

            var opts = file.GetOpts();

            if (opts != null)
            {
                characterWowObject = exporter.LoadCharacter(WhViewerOptions.FromJson(opts), scale);
            }
            else
            {
                var manualHeader = file.GetManualHeader();
                if (manualHeader == null)
                {
                    throw new System.InvalidOperationException();
                }

                characterWowObject = exporter.LoadCharacter(manualHeader.Race, manualHeader.Gender, manualHeader.ItemIds, scale);
            }

            // ToDo: после запекания идет привязка на текущие индексы вершин. Если вершины будут перестроены, надо тут тоже обновить индексы
            var bakedBlendshapes = new List <BlendShapeUtility.BakedBlendshape>();

            if (file.Blendshapes != null)
            {
                foreach (var blendshape in file.Blendshapes)
                {
                    if (blendshape.Bones.Length > 0)
                    {
                        if (blendshape.Name == WowVrcFileData.BlendshapeData.basicBlendshapeName)
                        {
                            var basicBakedBlendshape = BlendShapeUtility.BakeBlendShape(characterWowObject.GlobalPosition, characterWowObject.MainMesh.Vertices, characterWowObject.Bones, blendshape.Bones, scale);

                            foreach (var basicBakedBlendshapeElement in basicBakedBlendshape)
                            {
                                characterWowObject.MainMesh.Vertices[basicBakedBlendshapeElement.Key].Position = new Vec3(basicBakedBlendshapeElement.Value.Position.X, basicBakedBlendshapeElement.Value.Position.Y, basicBakedBlendshapeElement.Value.Position.Z);
                                characterWowObject.MainMesh.Vertices[basicBakedBlendshapeElement.Key].Normal   = new Vec3(basicBakedBlendshapeElement.Value.Normal.X, basicBakedBlendshapeElement.Value.Normal.Y, basicBakedBlendshapeElement.Value.Normal.Z);
                            }
                        }
                        else
                        {
                            bakedBlendshapes.Add(new BlendShapeUtility.BakedBlendshape
                            {
                                BlendshapeName = blendshape.Name,
                                Changes        = BlendShapeUtility.BakeBlendShape(characterWowObject.GlobalPosition, characterWowObject.MainMesh.Vertices, characterWowObject.Bones, blendshape.Bones, scale)
                            });
                        }
                    }
                }
            }

            if (prepareForVRChat)
            {
                warnings = PrepareForVRChatUtility.PrepareObject(characterWowObject, bakedBlendshapes, scale,
                                                                 true, true, true, true, true, true);
            }
            else
            {
                warnings = null;
            }

            var fbxExporter = new Exporter();

            return(fbxExporter.ExportWowObject(characterWowObject, bakedBlendshapes, exportDirectory, false));
        }