public void OpenFileButtonClickHandler() { var fileName = WowVrcFileDialogs.Open(); if (fileName == null) { return; } if (_character != null) { Destroy(_character.Root); _character = null; } _openedFile = WowVrcFile.Open(fileName); _openedFilePath = fileName; _character = new CharacterBuilder(StandardShader).Build(_openedFile, true); _character.Root.transform.Rotate(new Vector3(0, 180, 0)); _characterMesh = _character.Root.transform.GetSelfOrChildByName("character").gameObject.GetComponent <SkinnedMeshRenderer>().sharedMesh; _characterBonesRoot = _character.Root.transform.GetSelfOrChildByName("ROOT").gameObject; _defaultVertexPositions = new Vector3[_characterMesh.vertices.Length]; _characterMesh.vertices.CopyTo(_defaultVertexPositions, 0); _defaultVertexNormals = new Vector3[_characterMesh.vertices.Length]; _characterMesh.normals.CopyTo(_defaultVertexNormals, 0); _basicVertexPositions = new Vector3[_characterMesh.vertices.Length]; _characterMesh.vertices.CopyTo(_basicVertexPositions, 0); _basicVertexNormals = new Vector3[_characterMesh.vertices.Length]; _characterMesh.normals.CopyTo(_basicVertexNormals, 0); SetBoneListboxItems(); ClearBlendshapes(); GetBlendshapesFromFile(); SelectBlendshape(WowVrcFileData.BlendshapeData.basicBlendshapeName, false); }
public Character Build(WowVrcFile file, bool ignoreItemsAndMount = false) { WowObject characterWowObject; var opts = file.GetOpts(); if (opts != null) { if (ignoreItemsAndMount) { opts = opts.GetCopy(); opts.items = null; opts.mount = null; } characterWowObject = _exporter.LoadCharacter(WhViewerOptions.FromJson(opts)); } else { var manualHeader = file.GetManualHeader(); if (manualHeader == null) { throw new System.InvalidOperationException(); } characterWowObject = _exporter.LoadCharacter(manualHeader.Race, manualHeader.Gender, ignoreItemsAndMount ? null : manualHeader.ItemIds); } // ToDo: грузить все итемы тоже. в viseme editor оно использоваться не будет так как будет передаваться ignoreItems = true, но возможно где-то понадобится var res = new Character() { WowObject = characterWowObject, Root = CreateCharacterGameObjects(characterWowObject) }; return(res); }
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)); }