private void UpdateMesh() { MeshData.SetData(GFLXMeshBufferHelper.CreateVertexDataBuffer(this)); ParentModel.UpdateVertexData(true); }
private void ImportModel(GFLXModelImporter importer, List <STGenericMaterial> importedMaterials, List <STGenericObject> importedMeshes, STSkeleton skeleton) { Model.Model.Groups.Clear(); Model.Model.Meshes.Clear(); List <string> textures = Model.Textures.ToList(); foreach (var mat in importedMaterials) { } var meshes = GeneratePolygonGroups(importedMeshes, importedMaterials, textures, importer.Settings); //Once mesh groups are merged search for bone nodes //The bone section is basically a node tree //Which contains nodes for meshes //We need to remove the original and replace with new ones //Then index these in our mesh groups if (importer.ImportNewBones) { //Clear the original bones and nodes Model.Skeleton.bones.Clear(); Model.Model.Bones.Clear(); List <int> SkinningIndices = new List <int>(); foreach (var genericBone in skeleton.bones) { var scale = genericBone.Scale; var trans = genericBone.Position; var rot = genericBone.EulerRotation; Bone bone = new Bone(); bone.Name = genericBone.Text; bone.BoneType = 0; bone.Parent = genericBone.parentIndex; bone.Zero = 0; bone.Visible = false; bone.Scale = new GFMDLStructs.Vector3(scale.X, scale.Y, scale.Z); bone.Rotation = new GFMDLStructs.Vector3(rot.X, rot.Y, rot.Z); bone.Translation = new GFMDLStructs.Vector3(trans.X, trans.Y, trans.Z); bone.RadiusStart = new GFMDLStructs.Vector3(0, 0, 0); bone.RadiusEnd = new GFMDLStructs.Vector3(0, 0, 0); Model.Model.Bones.Add(bone); } } int originIndex = int.MaxValue; //Go through each bone and remove the original mesh node List <STBone> bonesToRemove = new List <STBone>(); for (int i = 0; i < Model.Skeleton.bones.Count; i++) { //Reset bone as rigid var node = (GFLXBone)Model.Skeleton.bones[i]; node.Bone.RigidCheck = new BoneRigidData() { Unknown1 = 0 }; if (node.Bone.BoneType == 1) { node.Bone.BoneType = 0; } int index = Model.Skeleton.bones.IndexOf(node); if (node.Text == "Origin") { originIndex = index; } //Check if the bone is rigged to any meshes and use skinning for (int m = 0; m < meshes.Count; m++) { if (meshes[m].vertices.Any(x => x.boneNames.Contains(node.Text))) { node.Bone.BoneType = 1; node.Bone.RigidCheck = null; } } if (Model.GenericMeshes.Any(x => x.Text == node.Text)) { bonesToRemove.Add(node); Model.Model.Bones.Remove(node.Bone); } /* if (Model.Model.CollisionGroups?.Count != 0) * { * var collisionGroups = Model.Model.CollisionGroups; * for (int c = 0; c < collisionGroups.Count; c++) * { * if (collisionGroups[c].BoneIndex == i) * { * * } * } * }*/ } foreach (var bone in bonesToRemove) { Model.Skeleton.bones.Remove(bone); } bonesToRemove.Clear(); Model.Model.CollisionGroups = new List <CollisionGroup>(); List <int> skinningIndices = Model.GenerateSkinningIndices(); //Set an empty bone with rigging if there is no rigging if (importer.Settings.MeshSettings.Any(x => x.HasBoneIndices) && skinningIndices.Count == 0) { var node = (GFLXBone)Model.Skeleton.bones[0]; node.Bone.RigidCheck = null; node.Bone.BoneType = 1; skinningIndices.Add(0); } List <string> unmappedBones = new List <string>(); foreach (var mesh in meshes) { var setting = importer.Settings.MeshSettings[meshes.IndexOf(mesh)]; for (int i = 0; i < mesh.vertices.Count; i++) { if (setting.SetNormalsToColorChannel2) { mesh.vertices[i].col2 = new OpenTK.Vector4( mesh.vertices[i].nrm.X * 0.5f + 0.5f, mesh.vertices[i].nrm.Y * 0.5f + 0.5f, mesh.vertices[i].nrm.Z * 0.5f + 0.5f, 1); } //Single bind if no bones are mapped but setting is enabled if (setting.HasBoneIndices && mesh.vertices[i].boneNames.Count == 0) { mesh.vertices[i].boneIds.Add(skinningIndices.FirstOrDefault()); mesh.vertices[i].boneWeights.Add(1); } if (importer.RotationY != 0) { var transform = OpenTK.Matrix4.CreateRotationX(OpenTK.MathHelper.DegreesToRadians(importer.RotationY)); mesh.vertices[i].pos = OpenTK.Vector3.TransformPosition(mesh.vertices[i].pos, transform); mesh.vertices[i].nrm = OpenTK.Vector3.TransformPosition(mesh.vertices[i].nrm, transform); } if (importer.Settings.FlipUVsVertical) { mesh.vertices[i].uv0 = new Vector2(0, 1) - mesh.vertices[i].uv0; mesh.vertices[i].uv1 = new Vector2(0, 1) - mesh.vertices[i].uv1; mesh.vertices[i].uv2 = new Vector2(0, 1) - mesh.vertices[i].uv2; } if (importer.Settings.OptmizeZeroWeights) { float[] weightsA = new float[4]; int MaxWeight = 255; for (int j = 0; j < 4; j++) { if (mesh.vertices[i].boneWeights.Count < j + 1) { weightsA[j] = 0; MaxWeight = 0; } else { int weight = (int)(mesh.vertices[i].boneWeights[j] * 255); if (mesh.vertices[i].boneWeights.Count == j + 1) { weight = MaxWeight; } if (weight >= MaxWeight) { weight = MaxWeight; MaxWeight = 0; } else { MaxWeight -= weight; } weightsA[j] = weight / 255f; } } mesh.vertices[i].boneWeights = weightsA.ToList(); } for (int j = 0; j < mesh.vertices[i].boneNames?.Count; j++) { string boneName = mesh.vertices[i].boneNames[j]; int boneIndex = Model.Model.Bones.IndexOf(Model.Model.Bones.Where(p => p.Name == boneName).FirstOrDefault()); if (boneIndex != -1 && skinningIndices.IndexOf(boneIndex) != -1) { mesh.vertices[i].boneIds.Add(boneIndex); } else { if (!unmappedBones.Contains(boneName)) { unmappedBones.Add(boneName); } } } } } //Adjust materials if necessary if (importer.Settings.ResetUVTransform) { foreach (var mat in Model.GenericMaterials) { foreach (var param in mat.ValueParams) { if (param.Key.Contains("UVScale")) { param.Value.Value = 1; } if (param.Key.Contains("UVTranslate")) { param.Value.Value = 0; } if (param.Key.Contains("ColorBaseU")) { param.Value.Value = 0; } if (param.Key.Contains("ColorBaseV")) { param.Value.Value = 0; } } } } //Now add brand new mesh nodes foreach (var mesh in meshes) { int index = meshes.IndexOf(mesh); var setting = importer.Settings.MeshSettings[index]; Bone bone = new Bone(); bone.Name = mesh.ObjectName; bone.BoneType = 0; bone.Parent = 0; bone.Zero = 0; bone.Visible = false; bone.Scale = new GFMDLStructs.Vector3(1, 1, 1); bone.Rotation = new GFMDLStructs.Vector3(0, 0, 0); bone.Translation = new GFMDLStructs.Vector3(0, 0, 0); bone.RadiusStart = new GFMDLStructs.Vector3(0, 0, 0); bone.RadiusEnd = new GFMDLStructs.Vector3(0, 0, 0); // bone.RigidCheck = new BoneRigidData(); Model.Model.Bones.Add(bone); int NodeIndex = Model.Model.Bones.IndexOf(bone); //Now create the associated group var group = new Group(); group.Bounding = Model.GenerateBoundingBox(mesh); group.BoneIndex = (uint)NodeIndex; group.MeshIndex = (uint)index; group.Layer = 0; Model.Model.Groups.Add(group); //Now create our mesh data var meshData = new Mesh(); Model.Model.Meshes.Add(meshData); if (setting.HasTangents || setting.HasBitangents) { try { mesh.CalculateTangentBitangent(false); } catch { } } //Add attributes based on settings IList <MeshAttribute> attributes = new List <MeshAttribute>(); attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.Position, BufferFormat = (uint)setting.PositionFormat, ElementCount = 3, }); if (setting.HasNormals) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.Normal, BufferFormat = (uint)setting.NormalFormat, ElementCount = 4, }); } if (setting.HasTangents) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.Tangents, BufferFormat = (uint)setting.TangentsFormat, ElementCount = 4, }); } if (setting.HasTexCoord1) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.UV1, BufferFormat = (uint)setting.TexCoord1Format, ElementCount = 2, }); } if (setting.HasTexCoord2) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.UV2, BufferFormat = (uint)setting.TexCoord2Format, ElementCount = 2, }); } if (setting.HasTexCoord3) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.UV3, BufferFormat = (uint)setting.TexCoord3Format, ElementCount = 2, }); } if (setting.HasTexCoord4) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.UV4, BufferFormat = (uint)setting.TexCoord4Format, ElementCount = 2, }); } if (setting.HasColor1) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.Color1, BufferFormat = (uint)setting.Color1Format, ElementCount = 4, }); } if (setting.HasColor2) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.Color2, BufferFormat = (uint)setting.Color2Format, ElementCount = 4, }); } if (setting.HasBoneIndices) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.BoneID, BufferFormat = (uint)setting.BoneIndexFormat, ElementCount = 4, }); } if (setting.HasWeights) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.BoneWeight, BufferFormat = (uint)setting.BoneWeightFormat, ElementCount = 4, }); } if (setting.HasBitangents) { attributes.Add(new MeshAttribute() { VertexType = (uint)VertexType.Bitangent, BufferFormat = (uint)setting.BitangentnFormat, ElementCount = 4, }); } meshData.Attributes = attributes; meshData.SetData(GFLXMeshBufferHelper.CreateVertexDataBuffer(mesh, skinningIndices, attributes)); //Lastly add the polygon groups foreach (var poly in mesh.PolygonGroups) { List <ushort> faces = new List <ushort>(); for (int f = 0; f < poly.faces.Count; f++) { faces.Add((ushort)poly.faces[f]); } if (poly.MaterialIndex < 0) { poly.MaterialIndex = 0; } meshData.Polygons = new List <MeshPolygon>(); meshData.Polygons.Add(new MeshPolygon() { MaterialIndex = (uint)poly.MaterialIndex, Faces = faces, }); } } if (unmappedBones.Count > 0) { STErrorDialog.Show($"{unmappedBones.Count} bone(s) are not present in the boneset and are unmapped!", "GFBMDL Importer", string.Join("\n", unmappedBones.ToArray())); } Console.WriteLine($""); //Generate bounding box Model.GenerateBoundingBox(); ReloadModel(Model.Model); Model.UpdateVertexData(true); }
public void LoadFile(Model model, GFBMDL file, GFBMDL_Render Renderer) { Model = model; ParentFile = file; Renderer.Meshes.Clear(); for (int m = 0; m < Model.Materials?.Count; m++) { GenericMaterials.Add(new GFLXMaterialData(this, Model.Materials[m])); } List <int> SkinningIndices = new List <int>(); for (int b = 0; b < Model.Bones?.Count; b++) { var bone = Model.Bones[b]; Skeleton.bones.Add(new GFLXBone(this, bone)); if (bone.RigidCheck == null) { SkinningIndices.Add(b); } } Skeleton.reset(); Skeleton.update(); for (int g = 0; g < Model.Groups?.Count; g++) { var group = Model.Groups[g]; var mesh = Model.Meshes[g]; OpenTK.Matrix4 transform = OpenTK.Matrix4.Identity; GFLXMesh genericMesh = new GFLXMesh(this, group, mesh); genericMesh.Checked = true; genericMesh.ImageKey = "model"; genericMesh.SelectedImageKey = "model"; int boneIndex = (int)group.BoneIndex; if (boneIndex < Skeleton.bones.Count && boneIndex > 0) { genericMesh.BoneIndex = boneIndex; transform = Skeleton.bones[boneIndex].Transform; genericMesh.Text = Skeleton.bones[boneIndex].Text; } // if (group.MeshID < Skeleton.bones.Count && group.MeshID > 0) // genericMesh.Text = Skeleton.bones[(int)group.MeshID].Text; Renderer.Meshes.Add(genericMesh); GenericMeshes.Add(genericMesh); //Load the vertex data genericMesh.Transform = transform; genericMesh.vertices = GFLXMeshBufferHelper.LoadVertexData(mesh, transform, SkinningIndices); genericMesh.FlipUvsVertical(); //Load faces for (int p = 0; p < mesh.Polygons?.Count; p++) { var poly = mesh.Polygons[p]; var polygonGroup = new STGenericPolygonGroup(); polygonGroup.MaterialIndex = (int)poly.MaterialIndex; genericMesh.PolygonGroups.Add(polygonGroup); if (GenericMaterials.Count > poly.MaterialIndex) { polygonGroup.Material = GenericMaterials[(int)poly.MaterialIndex]; } for (int f = 0; f < poly.Faces?.Count; f++) { polygonGroup.faces.Add((int)poly.Faces[f]); } } } }