private void AddS3DMesh(Model3DGroup group, Node obj, Node.Submesh submesh, bool force) { try { var geom = new MeshGeometry3D(); int[] indcs = obj.Indices.Data; Vertex[] vrtcs = obj.Vertices.Data; var iList = ModelFunctions.GetTriangleList(indcs, submesh.FaceStart * 3, submesh.FaceLength * 3, 3); int min = iList.Min(); int max = iList.Max(); for (int i = 0; i < iList.Count; i++) { iList[i] -= min; } var vArray = new Vertex[(max - min) + 1]; Array.Copy(ModelFunctions.DeepClone(vrtcs), min, vArray, 0, (max - min) + 1); foreach (var vertex in vArray) { if (vertex == null) { continue; } VertexValue pos, tex, norm; vertex.TryGetValue("position", 0, out pos); vertex.TryGetValue("texcoords", 0, out tex); var texSize = (obj._2F01 != null) ? obj._2F01.unkC0 : 1; geom.Positions.Add(new Point3D(pos.Data.x, pos.Data.y, pos.Data.z)); geom.TextureCoordinates.Add(new System.Windows.Point(tex.Data.x * texSize, tex.Data.y * texSize)); if (vertex.TryGetValue("normal", 0, out norm)) { geom.Normals.Add(new Vector3D(norm.Data.x, norm.Data.y, norm.Data.z)); } } foreach (var index in iList) { geom.TriangleIndices.Add(index); } GeometryModel3D modeld = new GeometryModel3D(geom, shaders[submesh.MaterialIndex + 1]) { BackMaterial = shaders[submesh.MaterialIndex + 1] }; group.Children.Add(modeld); } catch (Exception ex) { if (!force) { throw ex; } } }
private void AddMesh(Model3DGroup group, render_model.ModelSection part, render_model.ModelSection.Submesh submesh, bool force) { try { var geom = new MeshGeometry3D(); var iList = ModelFunctions.GetTriangleList(part.Indices, submesh.FaceIndex, submesh.FaceCount, mode.IndexInfoList[part.FacesIndex].FaceFormat); int min = iList.Min(); int max = iList.Max(); for (int i = 0; i < iList.Count; i++) { iList[i] -= min; } var vArray = new Vertex[(max - min) + 1]; Array.Copy(part.Vertices.ToArray(), min, vArray, 0, (max - min) + 1); foreach (var vertex in vArray) { if (vertex == null) { continue; } VertexValue pos, tex, norm; vertex.TryGetValue("position", 0, out pos); vertex.TryGetValue("texcoords", 0, out tex); geom.Positions.Add(new Point3D(pos.Data.x, pos.Data.y, pos.Data.z)); geom.TextureCoordinates.Add(new System.Windows.Point(tex.Data.x, 1f - tex.Data.y)); if (vertex.TryGetValue("normal", 0, out norm)) { geom.Normals.Add(new Vector3D(norm.Data.x, norm.Data.y, norm.Data.z)); } } foreach (var index in iList) { geom.TriangleIndices.Add(index); } GeometryModel3D modeld = new GeometryModel3D(geom, shaders[submesh.ShaderIndex]) { BackMaterial = shaders[submesh.ShaderIndex] }; group.Children.Add(modeld); } catch (Exception ex) { if (!force) { throw ex; } } }
private void AddS3DMesh(Model3DGroup group, Node obj, Node.Submesh submesh, bool force) { try { var pObj = (obj._2901 == null) ? obj : atpl.ObjectByID(obj._2901.InheritID); var iOffset = (obj._2901 == null) ? 0 : obj._2901.IndexOffset; var vOffset = (obj._2901 == null) ? 0 : obj._2901.VertexOffset; var geom = new MeshGeometry3D(); var iList = ModelFunctions.GetTriangleList(pObj.Indices.Data, (iOffset + submesh.FaceStart) * 3, submesh.FaceLength * 3, 3); var vArray = new Vertex[submesh.VertLength]; Array.Copy(pObj.Vertices.Data, (vOffset + submesh.VertStart), vArray, 0, submesh.VertLength); foreach (var vertex in vArray) { if (vertex == null) { continue; } VertexValue pos, tex, norm; vertex.TryGetValue("position", 0, out pos); vertex.TryGetValue("texcoords", 0, out tex); var texSize = (obj._2F01 != null) ? obj._2F01.unkC0 : 1; geom.Positions.Add(new Point3D(pos.Data.x, pos.Data.y, pos.Data.z)); geom.TextureCoordinates.Add(new System.Windows.Point(tex.Data.x * texSize, tex.Data.y * texSize)); if (vertex.TryGetValue("normal", 0, out norm)) { geom.Normals.Add(new Vector3D(norm.Data.x, norm.Data.y, norm.Data.z)); } } foreach (var index in iList) { geom.TriangleIndices.Add(index); } GeometryModel3D modeld = new GeometryModel3D(geom, shaders[submesh.MaterialIndex + 1]) { //BackMaterial = shaders[submesh.MaterialIndex + 1] }; group.Children.Add(modeld); } catch (Exception ex) { if (!force) { throw ex; } } }
public override void LoadRaw() { if (RawLoaded) { return; } var bb = BoundingBoxes[0]; var IH = (Halo1PC.CacheFile.CacheIndexHeader)cache.IndexHeader; var reader = cache.Reader; for (int i = 0; i < ModelSections.Count; i++) { var section = ModelSections[i]; List <int> tIndices = new List <int>(); List <Vertex> tVertices = new List <Vertex>(); for (int j = 0; j < section.Submeshes.Count; j++) { var submesh = (Halo1PC.gbxmodel.ModelSection.Submesh)section.Submeshes[j]; #region Read Indices submesh.FaceIndex = tIndices.Count; var strip = new List <int>(); reader.SeekTo(submesh.FaceOffset + IH.vertDataOffset + IH.indexDataOffset); for (int k = 0; k < submesh.FaceCount; k++) { strip.Add(reader.ReadUInt16() + tVertices.Count); } strip = ModelFunctions.GetTriangleList(strip.ToArray(), 0, strip.Count, 5); strip.Reverse(); submesh.FaceCount = strip.Count; tIndices.AddRange(strip); #endregion #region Read Vertices reader.SeekTo(submesh.VertOffset + IH.vertDataOffset); for (int k = 0; k < submesh.VertexCount; k++) { var v = new Vertex() { FormatName = "Halo1PC_Skinned" }; var position = new RealQuat(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); var normal = new RealQuat(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); var binormal = new RealQuat(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); var tangent = new RealQuat(reader.ReadSingle(), reader.ReadSingle(), reader.ReadSingle()); var texcoord = new RealQuat(reader.ReadSingle() * uScale, 1f - reader.ReadSingle() * vScale); var nodes = (Flags.Values[1]) ? new RealQuat(submesh.LocalNodes[reader.ReadInt16()], submesh.LocalNodes[reader.ReadInt16()], 0, 0) : new RealQuat(reader.ReadInt16(), reader.ReadInt16(), 0, 0); var weights = new RealQuat(reader.ReadSingle(), reader.ReadSingle(), 0, 0); v.Values.Add(new VertexValue(position, VertexValue.ValueType.Float32_3, "position", 0)); v.Values.Add(new VertexValue(normal, VertexValue.ValueType.Float32_3, "normal", 0)); v.Values.Add(new VertexValue(binormal, VertexValue.ValueType.Float32_3, "binormal", 0)); v.Values.Add(new VertexValue(tangent, VertexValue.ValueType.Float32_3, "tangent", 0)); v.Values.Add(new VertexValue(texcoord, VertexValue.ValueType.Float32_2, "texcoords", 0)); v.Values.Add(new VertexValue(nodes, VertexValue.ValueType.Int16_N2, "blendindices", 0)); v.Values.Add(new VertexValue(weights, VertexValue.ValueType.Float32_2, "blendweight", 0)); tVertices.Add(v); bb.XBounds.Min = Math.Min(bb.XBounds.Min, position.x); bb.XBounds.Max = Math.Max(bb.XBounds.Max, position.x); bb.YBounds.Min = Math.Min(bb.YBounds.Min, position.y); bb.YBounds.Max = Math.Max(bb.YBounds.Max, position.y); bb.ZBounds.Min = Math.Min(bb.ZBounds.Min, position.z); bb.ZBounds.Max = Math.Max(bb.ZBounds.Max, position.z); } #endregion } section.Indices = tIndices.ToArray(); section.Vertices = tVertices.ToArray(); IndexInfoList.Add(new IndexBufferInfo() { FaceFormat = 3 }); VertInfoList.Add(new VertexBufferInfo() { VertexCount = section.TotalVertexCount }); } RawLoaded = true; }
private void LoadSections() { for (int x = 0; x < sbsp.ModelSections.Count; x++) { try { var part = sbsp.ModelSections[x]; if (part.Submeshes.Count == 0) { sectList.Add(null); continue; } var group = new Model3DGroup(); var verts = part.Vertices; for (int i = 0; i < part.Submeshes.Count; i++) { var submesh = part.Submeshes[i]; var geom = new MeshGeometry3D(); var iList = ModelFunctions.GetTriangleList(part.Indices, submesh.FaceIndex, submesh.FaceCount, sbsp.IndexInfoList[part.FacesIndex].FaceFormat); int min = iList.Min(); int max = iList.Max(); for (int j = 0; j < iList.Count; j++) { iList[j] -= min; } var vArray = new Vertex[(max - min) + 1]; Array.Copy(verts, min, vArray, 0, (max - min) + 1); foreach (var vertex in vArray) { VertexValue pos, tex, norm; vertex.TryGetValue("position", 0, out pos); vertex.TryGetValue("texcoords", 0, out tex); geom.Positions.Add(new Point3D(pos.Data.x, pos.Data.y, pos.Data.z)); geom.TextureCoordinates.Add(new System.Windows.Point(tex.Data.x, 1f - tex.Data.y)); if (vertex.TryGetValue("normal", 0, out norm)) { geom.Normals.Add(new Vector3D(norm.Data.x, norm.Data.y, norm.Data.z)); } } foreach (var index in iList) { geom.TriangleIndices.Add(index); } GeometryModel3D modeld = new GeometryModel3D(geom, shaders[submesh.ShaderIndex]) { //BackMaterial = shaders[submesh.ShaderIndex] }; group.Children.Add(modeld); } sectList.Add(group); } catch { sectList.Add(null); } } }
protected void LoadModelExtras() { var mode = this; #region Mesh Merging foreach (var reg in mode.Regions) { foreach (var perm in reg.Permutations) { if (perm.PieceCount < 2) { continue; } var firstPart = mode.ModelSections[perm.PieceIndex]; if (firstPart.Submeshes.Count == 0) { continue; } var verts = firstPart.Vertices.ToList(); var indices = firstPart.Indices.ToList(); for (int i = 1; i < perm.PieceCount; i++) { var nextPart = mode.ModelSections[perm.PieceIndex + i]; foreach (var mesh in nextPart.Submeshes) { firstPart.Submeshes.Add(mesh); mesh.FaceIndex += indices.Count; } for (int j = 0; j < nextPart.Indices.Length; j++) { nextPart.Indices[j] += verts.Count; } verts.AddRange(nextPart.Vertices); indices.AddRange(nextPart.Indices); nextPart.UnloadRaw(); //save memory seeing as it wont be used now } firstPart.Vertices = verts.ToArray(); firstPart.Indices = indices.ToArray(); } } #endregion #region Mesh Splitting if (mode.InstancedGeometryIndex == -1) { return; } var part = mode.ModelSections[mode.InstancedGeometryIndex]; var list = new List <mode.ModelSection>(); for (int i = 0; i < part.Submeshes.Count; i++) { var submesh = part.Submeshes[i]; for (int j = submesh.SubsetIndex; j < (submesh.SubsetIndex + submesh.SubsetCount); j++) { var set = part.Subsets[j]; var vList = ModelFunctions.GetTriangleList(part.Indices, set.FaceIndex, set.FaceCount, mode.IndexInfoList[part.FacesIndex].FaceFormat); var newStrip = vList.ToArray(); var min = vList.Min(); var max = vList.Max(); //adjust faces to start at 0, seeing as //we're going to use a new set of vertices for (int k = 0; k < newStrip.Length; k++) { newStrip[k] -= min; } var verts = new Vertex[(max - min) + 1]; for (int k = 0; k < verts.Length; k++) //need to deep clone in case the vertices need to be { verts[k] = (Vertex)ModelFunctions.DeepClone(part.Vertices[k + min]); //transformed, so it doesnt transform all instances } #region Make new instances var newPart = new mode.ModelSection() { Vertices = verts, Indices = newStrip, Submeshes = new List <mode.ModelSection.Submesh>(), Subsets = new List <mode.ModelSection.Subset>(), VertexFormat = 1, OpaqueNodesPerVertex = part.OpaqueNodesPerVertex, NodeIndex = mode.GeomInstances[j].NodeIndex, VertsIndex = mode.VertInfoList.Count, FacesIndex = mode.IndexInfoList.Count }; mode.VertInfoList.Add(new mode.VertexBufferInfo() { VertexCount = verts.Length //dont need the rest }); mode.IndexInfoList.Add(new mode.IndexBufferInfo() { FaceFormat = 3 //dont need the rest }); var newMesh = new mode.ModelSection.Submesh() { SubsetCount = 1, SubsetIndex = 0, FaceIndex = 0, FaceCount = newStrip.Length, ShaderIndex = submesh.ShaderIndex, VertexCount = verts.Length }; var newSet = new mode.ModelSection.Subset() { SubmeshIndex = 0, FaceIndex = 0, FaceCount = newStrip.Length, VertexCount = verts.Length }; #endregion newPart.Submeshes.Add(newMesh); newPart.Subsets.Add(newSet); list.Add(newPart); } } //clear raw to save memory seeing as it wont be used anymore mode.ModelSections[mode.InstancedGeometryIndex].UnloadRaw(); mode.ModelSections.AddRange(list.ToArray()); var newRegion = new mode.Region() { Name = "Instances", Permutations = new List <mode.Region.Permutation>() }; for (int i = 0; i < list.Count; i++) { var newPerm = new mode.Region.Permutation() { Name = mode.GeomInstances[i].Name, PieceIndex = mode.InstancedGeometryIndex + i + 1, PieceCount = 1 }; newRegion.Permutations.Add(newPerm); } for (int i = 0; i < newRegion.Permutations.Count; i++) { var modelPart = mode.ModelSections[newRegion.Permutations[i].PieceIndex]; var instance = mode.GeomInstances[i]; //negative scale flips the faces after transform, fix it if (instance.TransformScale < 0) { Array.Reverse(modelPart.Indices); } for (int j = 0; j < modelPart.Vertices.Length; j++) { var vert = modelPart.Vertices[j]; VertexValue p, n, v, w; vert.TryGetValue("position", 0, out p); vert.TryGetValue("normal", 0, out n); p.Data *= instance.TransformScale; p.Data.Point3DTransform(instance.TransformMatrix); n.Data *= instance.TransformScale; n.Data.Vector3DTransform(instance.TransformMatrix); if (vert.TryGetValue("blendindices", 0, out v)) { v.Data = new Vector(instance.NodeIndex, 0, 0, 0); } else { vert.Values.Add(new VertexValue(new Vector(instance.NodeIndex, 0, 0, 0), VertexValue.ValueType.Int8_N4, "blendindices", 0)); } if (vert.TryGetValue("blendweight", 0, out w)) { w.Data = new Vector(instance.NodeIndex, 0, 0, 0); } else { vert.Values.Add(new VertexValue(new Vector(1, 0, 0, 0), VertexValue.ValueType.Int8_N4, "blendweight", 0)); } } } mode.Regions.Add(newRegion); #endregion }