private void ReadBFID(BinaryReader br, M2Model model, int chunkSize) { List <uint> bfids = Enumerable.Range(0, chunkSize / 4).Select(x => br.ReadUInt32()).ToList(); bfids.RemoveAll(x => x == 0); model.BoneFileIds = bfids.ToArray(); }
public void Guess(M2Model model) { if (IsCharacter(model)) { return; } if (IsSky(model)) { return; } if (IsSpell(model)) { return; } if (IsTradeSkillNode(model)) { return; } if (HasSuffix(model)) { return; } if (IsCreature(model)) { return; } Console.WriteLine($"Directory not found :: {model.FileDataId} {model.InternalName}"); model.Directory = "/"; }
private bool HasSuffix(M2Model model) { string[] nameParts = model.InternalName.Split('_'); for (int i = 2; i > 0; i--) { if (nameParts.Length < i) { continue; } string suffix = string.Join("_", nameParts.Take(i)); if (SuffixMap.TryGetValue(suffix, out string dir)) { model.Directory = dir; return(true); } } var probableDir = SuffixMap.FirstOrDefault(x => model.InternalName.StartsWith(x.Key, Comp)); if (probableDir.Key != null && probableDir.Key.Length > 2) // skip small sufficies { model.Directory = probableDir.Value; return(true); } return(false); }
private void ReadTXID(BinaryReader br, M2Model model, int chunkSize) { var txids = Enumerable.Range(0, chunkSize / 4).Select(x => new Texture(br.ReadUInt32())).ToHashSet(); txids.RemoveWhere(x => x.FileDataId == 0); model.TextureFileIds = txids; }
private static void PrepareM2Info(MapDoodadDefinition def, M2Model model) { TerrainConstants.TilePositionToWorldPosition(ref def.Position); Matrix scaleMatrix; Matrix.CreateScale(def.Scale, out scaleMatrix); var rotateZ = Matrix.CreateRotationZ(MathHelper.ToRadians(def.OrientationB + 180)); var rotateY = Matrix.CreateRotationY(MathHelper.ToRadians(def.OrientationA)); var rotateX = Matrix.CreateRotationX(MathHelper.ToRadians(def.OrientationC)); var modelToWorld = Matrix.Multiply(scaleMatrix, rotateZ); modelToWorld = Matrix.Multiply(modelToWorld, rotateX); modelToWorld = Matrix.Multiply(modelToWorld, rotateY); def.ModelToWorld = modelToWorld; Matrix worldToModel; Matrix.Invert(ref modelToWorld, out worldToModel); def.WorldToModel = worldToModel; CalculateModelBounds(def, model); }
private void ReadLDV1(BinaryReader br, M2Model model) { br.ReadUInt16(); model.LodCount = br.ReadUInt16() - 1; br.ReadSingle(); br.ReadBytes(4); br.ReadUInt32(); }
//Load and setup model prefab private IEnumerator LoadPrefab(string modelfile) { bool done = false; DestroyImmediate(mesh); GameObject prefab = Resources.Load <GameObject>($"{modelsPath}{RacePath}{modelfile}_prefab"); mesh = Instantiate(prefab, gameObject.transform); yield return(null); M2Model m2 = GetComponentInChildren <M2Model>(); byte[] data = m2.data.bytes; byte[] skin = m2.skin.bytes; byte[] skel = m2.skel.bytes; loadBinaries = new Thread(() => { Model = m2.LoadModel(data, skin, skel); done = true; }); loadBinaries.Start(); yield return(null); activeGeosets = new List <int> { 0, 2301 }; while (loadBinaries.IsAlive) { yield return(null); } if (done) { LoadColors(); yield return(null); textures = new Texture2D[Model.Textures.Length]; if (Gender) { helper = new GilneanMale(Model, worgen); } else { helper = new GilneanFemale(Model, worgen); } yield return(null); time = new float[Model.TextureAnimations.Length]; frame = new int[Model.TextureAnimations.Length]; for (int i = 0; i < time.Length; i++) { time[i] = 0f; frame[i] = 0; yield return(null); } renderer = GetComponentInChildren <SkinnedMeshRenderer>(); animator = GetComponentInChildren <Animator>(); Change = true; Loaded = !loadBinaries.IsAlive; } gameObject.SetActive(false); }
public static M2Model ReadM2(MpqLibrarian librarian, string filePath, bool isWMOM2) { if (!librarian.FileExists(filePath)) { var altFilePath = Path.ChangeExtension(filePath, ".m2"); if (!librarian.FileExists(altFilePath)) { throw new Exception("File does not exist: " + filePath); } filePath = altFilePath; } var model = new M2Model(); using (var stream = librarian.OpenFile(filePath)) using (var br = new BinaryReader(stream)) { ReadHeader(br, model); ReadGlobalSequences(br, model); ReadAnimations(br, model); ReadAnimationLookup(br, model); ReadBones(br, model); ReadKeyBoneLookup(br, model); ReadVertices(br, model); ReadColors(br, model); ReadTextures(br, model); ReadTransparency(br, model); ReadUVAnimation(br, model); ReadTexReplace(br, model); ReadRenderFlags(br, model); ReadBoneLookupTable(br, model); ReadTexLookup(br, model); ReadTexUnits(br, model); ReadTransLookup(br, model); ReadUVAnimLookup(br, model); ReadBoundingTriangles(br, model, isWMOM2); ReadBoundingVertices(br, model); ReadBoundingNormals(br, model); ReadAttachments(br, model); ReadAttachLookups(br, model); ReadEvents(br, model); ReadLights(br, model); ReadCameras(br, model); ReadCameraLookup(br, model); ReadRibbonEmitters(br, model); ReadParticleEmitters(br, model); if (model.Header.HasUnknownFinalPart) { ReadOptionalSection(br, model); } } return(model); }
static void ReadHeader(BinaryReader br, M2Model model) { var header = model.Header = new ModelHeader(); header.Magic = br.ReadUInt32(); header.Version = br.ReadUInt32(); header.NameLength = br.ReadInt32(); header.NameOffset = br.ReadInt32(); header.GlobalModelFlags = (GlobalModelFlags)br.ReadUInt32(); br.ReadOffsetLocation(ref header.GlobalSequences); br.ReadOffsetLocation(ref header.Animations); br.ReadOffsetLocation(ref header.AnimationLookup); br.ReadOffsetLocation(ref header.Bones); br.ReadOffsetLocation(ref header.KeyBoneLookup); br.ReadOffsetLocation(ref header.Vertices); header.ViewCount = br.ReadUInt32(); br.ReadOffsetLocation(ref header.Colors); br.ReadOffsetLocation(ref header.Textures); br.ReadOffsetLocation(ref header.Transparency); br.ReadOffsetLocation(ref header.UVAnimation); br.ReadOffsetLocation(ref header.TexReplace); br.ReadOffsetLocation(ref header.RenderFlags); br.ReadOffsetLocation(ref header.BoneLookupTable); br.ReadOffsetLocation(ref header.TexLookup); br.ReadOffsetLocation(ref header.TexUnits); br.ReadOffsetLocation(ref header.TransLookup); br.ReadOffsetLocation(ref header.UVAnimLookup); header.VertexBox = br.ReadBoundingBox(); header.VertexRadius = br.ReadSingle(); header.BoundingBox = br.ReadBoundingBox(); header.BoundingRadius = br.ReadSingle(); br.ReadOffsetLocation(ref header.BoundingTriangles); br.ReadOffsetLocation(ref header.BoundingVertices); br.ReadOffsetLocation(ref header.BoundingNormals); br.ReadOffsetLocation(ref header.Attachments); br.ReadOffsetLocation(ref header.AttachLookup); br.ReadOffsetLocation(ref header.Events); br.ReadOffsetLocation(ref header.Lights); br.ReadOffsetLocation(ref header.Cameras); br.ReadOffsetLocation(ref header.CameraLookup); br.ReadOffsetLocation(ref header.RibbonEmitters); br.ReadOffsetLocation(ref header.ParticleEmitters); if (header.HasUnknownFinalPart) { br.ReadOffsetLocation(ref header.OptionalUnk); } br.BaseStream.Position = model.Header.NameOffset; //model.Name = Encoding.UTF8.GetString(br.ReadBytes(model.Header.NameLength)); model.Name = br.ReadCString(); }
private bool IsCreature(M2Model model) { if (Database.CreatureModelData.ContainsValue(model.FileDataId) || CreatureOverrides.Contains(model.FileDataId)) { model.Directory = $"creature/{model.InternalName}/".ToLowerInvariant(); return(true); } return(false); }
private bool IsSky(M2Model model) { if (Database.LightSkybox.Contains(model.FileDataId)) { model.Directory = "environments/stars/"; return(true); } return(false); }
private bool IsTradeSkillNode(M2Model model) { if (model.InternalName.IndexOf("HerbNode", Comp) > -1 || model.InternalName.IndexOf("MiningNode", Comp) > -1) { model.Directory = "world/skillactivated/tradeskillnodes/"; return(true); } return(false); }
private static TileModel TransformM2Model(MapDoodadDefinition definition, M2Model m2model) { var model = new TileModel { Vertices = new Vector3[m2model.BoundingVertices.Length] }; // Rotate var origin = new Vector3( (TerrainConstants.CenterPoint - definition.Position.X), definition.Position.Y, (TerrainConstants.CenterPoint - definition.Position.Z) ); for (var i = 0; i < model.Vertices.Length; i++) { // Reverse the previos coord transform for the rotation. var vector = TransformToIntermediateCoords(m2model.BoundingVertices[i]); // Create the rotation matrices var rotateX = Matrix.CreateRotationX(definition.OrientationC * RadiansPerDegree); var rotateY = Matrix.CreateRotationY((definition.OrientationB - 90) * RadiansPerDegree); var rotateZ = Matrix.CreateRotationZ(-definition.OrientationA * RadiansPerDegree); // Rotate the vector var rotatedVector = Vector3.Transform(vector, rotateY); rotatedVector = Vector3.Transform(rotatedVector, rotateZ); rotatedVector = Vector3.Transform(rotatedVector, rotateX); var finalVector = rotatedVector + origin; model.Vertices[i] = finalVector; } // Add the triangle indices to the model model.Triangles = new Index3[m2model.BoundingTriangles.Length]; for (var i = 0; i < m2model.BoundingTriangles.Length; i++) { var tri = m2model.BoundingTriangles[i]; model.Triangles[i] = new Index3 { Index0 = (short)tri[2], Index1 = (short)tri[1], Index2 = (short)tri[0] }; } // Calculate the boundingbox model.Bounds = new BoundingBox(model.Vertices); return(model); }
private static M2 TransformWMOM2(M2Model model, List <int> indices, DoodadDefinition modd) { var currentM2 = new M2(); currentM2.Vertices.Clear(); currentM2.Indices.Clear(); var origin = new Vector3(modd.Position.X, modd.Position.Y, modd.Position.Z); // Create the scalar var scalar = modd.Scale; var scaleMatrix = Matrix.CreateScale(scalar); // Create the rotations var quatX = modd.Rotation.X; var quatY = modd.Rotation.Y; var quatZ = modd.Rotation.Z; var quatW = modd.Rotation.W; var rotQuat = new Quaternion(quatX, quatY, quatZ, quatW); var rotMatrix = Matrix.CreateFromQuaternion(rotQuat); var compositeMatrix = Matrix.Multiply(scaleMatrix, rotMatrix); for (var i = 0; i < model.BoundingVertices.Length; i++) { // Scale and transform var basePosVector = model.BoundingVertices[i]; var baseNormVector = model.BoundingNormals[i]; //PositionUtil.TransformToXNACoordSystem(ref vertex.Position); // Scale //Vector3 scaledVector; //Vector3.Transform(ref vector, ref scaleMatrix, out scaledVector); // Rotate Vector3 rotatedPosVector; Vector3.Transform(ref basePosVector, ref compositeMatrix, out rotatedPosVector); Vector3 rotatedNormVector; Vector3.Transform(ref baseNormVector, ref compositeMatrix, out rotatedNormVector); rotatedNormVector.Normalize(); // Translate Vector3 finalPosVector; Vector3.Add(ref rotatedPosVector, ref origin, out finalPosVector); currentM2.Vertices.Add(finalPosVector); } currentM2.Indices.AddRange(indices); return(currentM2); }
static void ReadBoundingNormals(BinaryReader br, M2Model model) { var bnInfo = model.Header.BoundingVertices; model.BoundingNormals = new Vector3[bnInfo.Count]; br.BaseStream.Position = bnInfo.Offset; for (var i = 0; i < bnInfo.Count; i++) { model.BoundingNormals[i] = br.ReadVector3(); } }
private void ReadSFID(BinaryReader br, M2Model model) { var skinFileIds = Enumerable.Range(0, model.ViewCount).Select(x => br.ReadUInt32()).ToList(); skinFileIds.RemoveAll(x => x == 0); model.SkinFileIds = skinFileIds.ToArray(); var lodSkinFileIds = Enumerable.Range(0, model.LodCount).Select(x => br.ReadUInt32()).ToList(); lodSkinFileIds.RemoveAll(x => x == 0); model.LodSkinFileIds = lodSkinFileIds.ToArray(); }
static void ReadGlobalSequences(BinaryReader br, M2Model model) { var gsInfo = model.Header.GlobalSequences; model.GlobalSequenceTimestamps = new uint[gsInfo.Count]; br.BaseStream.Position = gsInfo.Offset; for (int i = 0; i < model.GlobalSequenceTimestamps.Length; i++) { model.GlobalSequenceTimestamps[i] = br.ReadUInt32(); } }
private static void WriteModel(BinaryWriter writer, M2Model m2Model) { if (m2Model == null) { Console.WriteLine("Cannot write null Model to file."); return; } writer.Write(m2FileType); writer.Write(m2Model.Header.BoundingBox); writer.Write(m2Model.BoundingVertices); writer.Write(m2Model.BoundingTriangles); }
public M2ViewModel(CModel cModel, IEventAggregator ea, IRegionManager regionManager) { MyCModel = cModel; _ea = ea; //モデルの生成 MyM2Model = new M2Model(MyCModel, _ea); _ea.GetEvent <LanguageChangeEvent>().Subscribe(ChangedLang); //TabItemのHeaderになる言葉を多言語設定の為Resoucesから取り出す Title = CModel.GetLocalizedValue <string>("TITLEM2"); _regionManager = regionManager; }
static M2 TransformM2(M2Model model, IEnumerable <int> indicies, MapDoodadDefinition mddf) { var currentM2 = new M2(); currentM2.Vertices.Clear(); currentM2.Indices.Clear(); var posX = (mddf.Position.X - TerrainConstants.CenterPoint) * -1; var posY = (mddf.Position.Y - TerrainConstants.CenterPoint) * -1; var origin = new Vector3(posX, posY, mddf.Position.Z); // Create the scale matrix used in the following loop. Matrix scaleMatrix; Matrix.CreateScale(mddf.Scale, out scaleMatrix); // Creation the rotations var rotateZ = Matrix.CreateRotationZ(MathHelper.ToRadians(mddf.OrientationB + 180)); var rotateY = Matrix.CreateRotationY(MathHelper.ToRadians(mddf.OrientationA)); var rotateX = Matrix.CreateRotationX(MathHelper.ToRadians(mddf.OrientationC)); var worldMatrix = Matrix.Multiply(scaleMatrix, rotateZ); worldMatrix = Matrix.Multiply(worldMatrix, rotateX); worldMatrix = Matrix.Multiply(worldMatrix, rotateY); for (var i = 0; i < model.BoundingVertices.Length; i++) { var position = model.BoundingVertices[i]; var normal = model.BoundingNormals[i]; // Scale and Rotate Vector3 rotatedPosition; Vector3.Transform(ref position, ref worldMatrix, out rotatedPosition); Vector3 rotatedNormal; Vector3.Transform(ref normal, ref worldMatrix, out rotatedNormal); rotatedNormal.Normalize(); // Translate Vector3 finalVector; Vector3.Add(ref rotatedPosition, ref origin, out finalVector); currentM2.Vertices.Add(finalVector); } currentM2.Indices.AddRange(indicies); return(currentM2); }
private static void CalculateModelsWMOSpaceBounds(DoodadDefinition def, M2Model model) { var wmoSpaceVecs = new List <Vector3>(model.BoundingVertices.Length); for (var j = 0; j < model.BoundingVertices.Length; j++) { Vector3 rotated; Vector3.Transform(ref model.BoundingVertices[j], ref def.ModelToWMO, out rotated); Vector3 final; Vector3.Add(ref rotated, ref def.Position, out final); wmoSpaceVecs.Add(final); } def.Extents = new BoundingBox(wmoSpaceVecs.ToArray()); }
private void ReadAFID(BinaryReader br, M2Model model, int chunkSize) { int count = chunkSize / 8; model.AnimFiles = new AnimInfo[count]; for (int i = 0; i < count; i++) { model.AnimFiles[i] = new AnimInfo() { AnimId = br.ReadUInt16(), SubAnimId = br.ReadUInt16(), AnimFileId = br.ReadUInt32(), }; } }
private bool IsSpell(M2Model model) { if (Database.SpellVisualKitAreaModel.Contains(model.FileDataId) /*|| Database.SpellVisualEffectName.Contains(model.FileDataId)*/) { model.Directory = "spells/"; return(true); } if (model.InternalName.StartsWith("SpellVisualPlaceholder", Comp)) { model.Suffix = "_" + model.FileDataId; model.Directory = "spells/"; return(true); } return(false); }
//Load the model from assets public IEnumerator LoadModel(string collectionfile, CASCHandler casc) { UnloadModel(); bool done = false; converter = new System.Drawing.ImageConverter(); this.casc = casc; GameObject prefab = Resources.Load <GameObject>($"{Path}{collectionfile}"); mesh = Instantiate(prefab, gameObject.transform); yield return(null); M2Model m2 = GetComponentInChildren <M2Model>(); byte[] data = m2.data.bytes; byte[] skin = m2.skin.bytes; byte[] skel = m2.skel.bytes; loadBinaries = new Thread(() => { Model = m2.LoadModel(data, skin, skel); done = true; }); loadBinaries.Start(); yield return(null); ActiveGeosets = new List <int>(); while (loadBinaries.IsAlive) { yield return(null); } if (done) { LoadColors(); yield return(null); textures = new Texture2D[Model.Textures.Length]; MatchBones(character); time = new float[Model.TextureAnimations.Length]; frame = new int[Model.TextureAnimations.Length]; for (int i = 0; i < time.Length; i++) { time[i] = 0f; frame[i] = 0; yield return(null); } Loaded = !loadBinaries.IsAlive; Change = true; } }
private bool IsCharacter(M2Model model) { Regex characterRegex = new Regex("(.*)(male|female)$", RegexOptions.Compiled | RegexOptions.IgnoreCase); var match = characterRegex.Match(model.InternalName); if (!match.Success) { return(false); } if (Enum.TryParse(typeof(Races), match.Groups[1].Value, true, out var race)) { model.Directory = $"character/{race}/{match.Groups[2].Value}/".ToLowerInvariant(); return(true); } return(false); }
private static void CalculateModelBounds(MapDoodadDefinition def, M2Model model) { var vecs = new List <Vector3>(model.BoundingVertices); for (int i = 0; i < model.BoundingVertices.Length; i++) { var vec = model.BoundingVertices[i]; Vector3 rotatedVec; Vector3.Transform(ref vec, ref def.ModelToWorld, out rotatedVec); Vector3 finalVec; Vector3.Add(ref rotatedVec, ref def.Position, out finalVec); vecs.Add(finalVec); } def.Extents = new BoundingBox(vecs.ToArray()); }
private void ReadMD20(BinaryReader br, M2Model model) { br.BaseStream.Position += 8; int nameSize = br.ReadInt32(); int nameOffset = br.ReadInt32(); br.BaseStream.Position += 52; model.ViewCount = br.ReadInt32(); br.BaseStream.Position = nameOffset + 8; model.InternalName = Encoding.UTF8.GetString(br.ReadBytes(nameSize - 1)); if (Database.ComponentModelFileData.TryGetValue(model.FileDataId, out var suffix)) { if (!model.InternalName.EndsWith(suffix, System.StringComparison.OrdinalIgnoreCase)) { model.Suffix = suffix; } } }
public static void Load(uint fileDataId, Vector3 position, Quaternion rotation, Vector3 scale) { var model = new M2Model { FileDataId = fileDataId, Position = position, Rotation = rotation, Scale = scale }; // Parse the M2 format M2Reader.ReadM2(fileDataId, model); // Parse the SKIN format. foreach (var skinFile in M2Reader.SkinFileIds) { SkinReader.ReadSkin(skinFile, model); } M2Data.EnqueuedModels.Enqueue(model); }
static void ReadBoundingTriangles(BinaryReader br, M2Model model, bool isWMOM2) { var btInfo = model.Header.BoundingTriangles; model.BoundingTriangles = new Index3[btInfo.Count / 3]; br.BaseStream.Position = btInfo.Offset; for (var i = 0; i < model.BoundingTriangles.Length; i++) { var index0 = br.ReadInt16(); var index1 = br.ReadInt16(); var index2 = br.ReadInt16(); model.BoundingTriangles[i] = new Index3 { Index0 = index2, Index1 = isWMOM2 ? index0 : index1, Index2 = isWMOM2 ? index1 : index0 }; } }
static void ReadVertices(BinaryReader br, M2Model model) { var vertInfo = model.Header.Vertices; model.Vertices = new ModelVertices[vertInfo.Count]; br.BaseStream.Position = vertInfo.Offset; for (int i = 0; i < vertInfo.Count; i++) { var mv = new ModelVertices { Position = br.ReadVector3(), BoneWeight = br.ReadBytes(4), BoneIndices = br.ReadBytes(4), Normal = br.ReadVector3(), TextureCoordinates = br.ReadVector2(), Float_1 = br.ReadSingle(), Float_2 = br.ReadSingle() }; model.Vertices[i] = mv; } }
private static void CalculateModelBounds(MapDoodadDefinition def, M2Model model) { var vecs = new List<Vector3>(model.BoundingVertices); for (var i = 0; i < model.BoundingVertices.Length; i++) { var vec = model.BoundingVertices[i]; Vector3 rotatedVec; Vector3.Transform(ref vec, ref def.ModelToWorld, out rotatedVec); Vector3 finalVec; Vector3.Add(ref rotatedVec, ref def.Position, out finalVec); vecs.Add(finalVec); } def.Extents = new BoundingBox(vecs.ToArray()); }