public void BuildModel(int modelIndex) { _srModel = _srFile.Models[modelIndex]; String modelName = _objectName + "-" + modelIndex.ToString(); #region Materials ProgressStage = "Model " + modelIndex.ToString() + " - Creating Materials"; Thread.Sleep(500); for (int materialIndex = 0; materialIndex < _srModel.MaterialCount; materialIndex++) { Material material = new Material(); Color colorDiffuse = Color.FromArgb((int)unchecked (_srModel.Materials[materialIndex].colour)); material.Diffuse = colorDiffuse; material.TextureFileName = GetTextureName(_srModel, materialIndex); Materials.Add(material); progressLevel += _srModel.IndexCount / _srModel.Groups.Length; } #endregion #region Groups for (int groupIndex = 0; groupIndex < _srModel.Groups.Length; groupIndex++) { ProgressStage = "Model " + modelIndex.ToString() + " - Creating Group " + groupIndex.ToString(); Thread.Sleep(100); Tree srGroup = _srModel.Groups[groupIndex]; String groupName = String.Format("{0}-{1}-group-{2}", _objectName, modelIndex, groupIndex); if (srGroup != null && srGroup.mesh != null && srGroup.mesh.indexCount > 0 && srGroup.mesh.polygonCount > 0) { Node group = new Node(); SRMeshParser meshParser = new SRMeshParser(_objectName, _srFile); meshParser.BuildMesh(modelIndex, groupIndex, 0); foreach (SubMesh subMesh in meshParser.SubMeshes) { // If the mesh parser knew the total submeshes for the model, // then this could be done inside BuildMesh. subMesh.MeshIndex = Meshes.Count; group.SubMeshIndices.Add(SubMeshes.Count); SubMeshes.Add(subMesh); } Meshes.Add(meshParser.Mesh); group.Name = groupName; Groups.Add(group); } } #endregion ModelName = modelName; if (_srFile.Asset == CDC.Asset.Unit) { Model = new Unit(this); } else { Model = new Physical(this); } }
public Model(IModelParser modelParser) { Name = modelParser.ModelName; Materials.AddRange(modelParser.Materials); Meshes.AddRange(modelParser.Meshes); SubMeshes.AddRange(modelParser.SubMeshes); Root.Nodes.AddRange(modelParser.Groups); Root.Name = modelParser.ModelName; }
public void BuildModel(RenderResource resource, int modelIndex, CDC.Objects.ExportOptions options) { _srModel = _srFile.Models[modelIndex]; String modelName = _objectName + "-" + modelIndex.ToString(); #region Materials for (int materialIndex = 0; materialIndex < _srModel.MaterialCount; materialIndex++) { Material material = new Material(); material.Visible = _srModel.Materials[materialIndex].visible; // Breaks early SR1 builds. //material.BlendMode = _srModel.Materials[materialIndex].blendMode; //int sortPush = unchecked((sbyte)_srModel.Materials[materialIndex].sortPush); //sortPush = 128 - sortPush; //material.DepthBias = (1.0f / 100000.0f) * sortPush; // Maybe use a hack for warpgates WARPGATE_DrawWarpGateRim indicates tree 3 should have lower priority. Color colorDiffuse = Color.FromArgb((int)unchecked (_srModel.Materials[materialIndex].colour)); material.Diffuse = colorDiffuse; material.TextureFileName = CDC.Objects.Models.SRModel.GetTextureName(_srModel, materialIndex, options); Materials.Add(material); } #endregion #region Groups for (int groupIndex = 0; groupIndex < _srModel.Groups.Length; groupIndex++) { Tree srGroup = _srModel.Groups[groupIndex]; String groupName = String.Format("{0}-{1}-group-{2}", _objectName, modelIndex, groupIndex); if (srGroup != null && srGroup.mesh != null && srGroup.mesh.indexCount > 0 && srGroup.mesh.polygonCount > 0) { ModelNode group = new ModelNode(); SRMeshParser meshParser = new SRMeshParser(_objectName, _srFile); meshParser.BuildMesh(resource, modelIndex, groupIndex, 0); foreach (SubMesh subMesh in meshParser.SubMeshes) { // If the mesh parser knew the total submeshes for the model, // then this could be done inside BuildMesh. subMesh.MeshIndex = Meshes.Count; group.SubMeshIndices.Add(SubMeshes.Count); SubMeshes.Add(subMesh); } Meshes.Add(meshParser.Mesh); group.Name = groupName; Groups.Add(group); } } #endregion ModelName = modelName; Model = new Model(this); }
public void MergeSubMeshes() { var submesh = new ObjSubMesh(this); submesh.PositionFaces = SubMeshes.SelectMany(i => i.PositionFaces).ToList(); submesh.NormalFaces = SubMeshes.SelectMany(i => i.NormalFaces).ToList(); submesh.TexCoordFaces = SubMeshes.SelectMany(i => i.TexCoordFaces).ToList(); SubMeshes.Clear(); SubMeshes.Add(submesh); }
internal void Read(EndianBinaryReader reader, MeshSection section = null) { uint signature = reader.ReadUInt32(); reader.SeekCurrent(4); int subMeshCount, materialCount; long subMeshesOffset, materialsOffset; // X stores submesh/material count before the bounding sphere if (section?.Format == BinaryFormat.X) { subMeshCount = reader.ReadInt32(); materialCount = reader.ReadInt32(); BoundingSphere = reader.ReadBoundingSphere(); subMeshesOffset = reader.ReadOffset(); materialsOffset = reader.ReadOffset(); } else { BoundingSphere = reader.ReadBoundingSphere(); subMeshCount = reader.ReadInt32(); subMeshesOffset = reader.ReadOffset(); materialCount = reader.ReadInt32(); materialsOffset = reader.ReadOffset(); } SubMeshes.Capacity = subMeshCount; for (int i = 0; i < subMeshCount; i++) { reader.ReadAtOffset(subMeshesOffset + i * SubMesh.GetByteSize(section?.Format ?? BinaryFormat.DT), () => { var submesh = new SubMesh(); submesh.Read(reader, section); SubMeshes.Add(submesh); }); } Materials.Capacity = materialCount; for (int i = 0; i < materialCount; i++) { reader.ReadAtOffset(materialsOffset + i * Material.BYTE_SIZE, () => { var material = new Material(); material.Read(reader); Materials.Add(material); }); } }
private void Start() { childMeshRenderers = new List <SubMeshes>(); Diago.GetComponentInChildren <Renderer>().enabled = false; // testBtn = testBtn.GetComponent<Button>(); // testBtn.onClick.AddListener(sendOutput); // foreach (var item in GetComponentsInChildren <MeshRenderer>()) { SubMeshes mesh = new SubMeshes(); mesh.meshRenderer = item; mesh.originalPosition = item.transform.position; mesh.explodedPosition = item.bounds.center * 1.7f; childMeshRenderers.Add(mesh); } }
/// <summary> /// Checks whether the ray intersects the mesh or not /// </summary> /// <param name="src"></param> /// <param name="dir"></param> /// <returns></returns> public bool Intersect(Vector3 src, Vector3 dir) { if (SubMeshes.Length > 0) { // 1. Ray if (SubMeshes.Any(m => m.Intersect(src, dir))) { return(true); } } if (Mesh != null && Mesh.Intersect(src, dir)) { return(true); } return(false); }
public ushort CreateFreshSubMesh(ushort vertsToReserve, ushort trisToReserve) { // create custom List<> implementation with NativeArray that supports growth without assignment! SubMesh subMesh = new SubMesh((ushort)Verts.Count, (ushort)Tris.Count, vertsToReserve, trisToReserve); lastVert += vertsToReserve; lastTri += trisToReserve; SubMeshes.Add(subMesh); for (int i = 0; i < vertsToReserve; i++) { Verts.Add(Vector3.zero); // this is multiple assignment! BAD! Normals.Add(Vector3.up); TextureUVs.Add(Vector2.zero); SubmaterialUVs.Add(Vector2.zero); } for (int i = 0; i < trisToReserve; i++) { Tris.Add(0); // more evil multiple assignment! } return((ushort)(SubMeshes.Count + SubMeshBaseIdx - 1)); }
protected override YAMLMappingNode ExportYAMLRoot() { #warning TODO: provide for null values YAMLMappingNode node = base.ExportYAMLRoot(); node.AddSerializedVersion(SerializedVersion); node.Add("m_SubMeshes", SubMeshes.ExportYAML()); node.Add("m_Shapes", Shapes.ExportYAML()); node.Add("m_BindPose", BindPoses.ExportYAML()); #warning ??? node.Add("m_BoneNames", YAMLSequenceNode.Empty); node.Add("m_BoneNameHashes", BoneNameHashes.ExportYAML(false)); #warning ??? node.Add("m_RootBoneName", YAMLScalarNode.Empty); node.Add("m_RootBoneNameHash", RootBoneNameHash); node.Add("m_MeshCompression", MeshCompression); node.Add("m_IsReadable", IsReadable); node.Add("m_KeepVertices", KeepVertices); node.Add("m_KeepIndices", KeepIndices); node.Add("m_IndexBuffer", IndexBuffer.ExportYAML()); node.Add("m_Skin", Skin.ExportYAML()); node.Add("m_VertexData", VertexData.ExportYAML()); node.Add("m_CompressedMesh", CompressedMesh.ExportYAML()); node.Add("m_LocalAABB", LocalAABB.ExportYAML()); node.Add("m_MeshUsageFlags", MeshUsageFlags); if (IsReadCollision) { node.Add("m_BakedConvexCollisionMesh", CollisionData.BakedConvexCollisionMesh.ExportYAML()); node.Add("m_BakedTriangleCollisionMesh", CollisionData.BakedTriangleCollisionMesh.ExportYAML()); } else { node.Add("m_BakedConvexCollisionMesh", ArrayExtensions.EmptyBytes.ExportYAML()); node.Add("m_BakedTriangleCollisionMesh", ArrayExtensions.EmptyBytes.ExportYAML()); } #warning ??? node.Add("m_MeshOptimized", 0); return(node); }
protected override YAMLMappingNode ExportYAMLRoot(IAssetsExporter exporter) { #warning TODO: values acording to read version (current 2017.3.0f3) YAMLMappingNode node = base.ExportYAMLRoot(exporter); node.AddSerializedVersion(GetSerializedVersion(exporter.Version)); node.Add("m_SubMeshes", SubMeshes.ExportYAML(exporter)); node.Add("m_Shapes", Shapes.ExportYAML(exporter)); node.Add("m_BindPose", BindPoses.ExportYAML(exporter)); #warning ??? node.Add("m_BoneNames", YAMLSequenceNode.Empty); node.Add("m_BoneNameHashes", IsReadBoneNameHashes(exporter.Version) ? BoneNameHashes.ExportYAML(false) : YAMLSequenceNode.Empty); #warning ??? node.Add("m_RootBoneName", YAMLScalarNode.Empty); node.Add("m_RootBoneNameHash", RootBoneNameHash); node.Add("m_MeshCompression", MeshCompression); node.Add("m_IsReadable", IsReadable); node.Add("m_KeepVertices", KeepVertices); node.Add("m_KeepIndices", KeepIndices); node.Add("m_IndexBuffer", IsReadIndexBuffer(exporter.Version) ? IndexBuffer.ExportYAML() : YAMLSequenceNode.Empty); node.Add("m_Skin", Skin.ExportYAML(exporter)); node.Add("m_VertexData", VertexData.ExportYAML(exporter)); node.Add("m_CompressedMesh", CompressedMesh.ExportYAML(exporter)); node.Add("m_LocalAABB", LocalAABB.ExportYAML(exporter)); node.Add("m_MeshUsageFlags", MeshUsageFlags); if (IsReadCollision(exporter.Version)) { node.Add("m_BakedConvexCollisionMesh", CollisionData.BakedConvexCollisionMesh.ExportYAML()); node.Add("m_BakedTriangleCollisionMesh", CollisionData.BakedTriangleCollisionMesh.ExportYAML()); } else { node.Add("m_BakedConvexCollisionMesh", ArrayExtensions.EmptyBytes.ExportYAML()); node.Add("m_BakedTriangleCollisionMesh", ArrayExtensions.EmptyBytes.ExportYAML()); } #warning ??? node.Add("m_MeshOptimized", 0); return(node); }
public void BuildModel(RenderResource resource) { Material materialA = new Material(); materialA.Visible = true; Color colorDiffuseA = Color.FromArgb(unchecked ((int)0xFF0000FF)); materialA.Diffuse = colorDiffuseA; materialA.TextureFileName = ""; Materials.Add(materialA); Material materialB = new Material(); materialB.Visible = true; Color colorDiffuseB = Color.FromArgb(unchecked ((int)0xFF00FF00)); materialB.Diffuse = colorDiffuseB; materialB.TextureFileName = ""; Materials.Add(materialB); ModelNode group = new ModelNode(); group.Name = "group"; MeshParser meshParser = new MeshParser(ModelName); meshParser.BuildMesh(resource); foreach (SubMesh subMesh in meshParser.SubMeshes) { // If the mesh parser knew the total submeshes for the model, // then this could be done inside BuildMesh. subMesh.MeshIndex = Meshes.Count; group.SubMeshIndices.Add(SubMeshes.Count); SubMeshes.Add(subMesh); } Meshes.Add(meshParser.Mesh); Groups.Add(group); Model = new Model(this); }
/// <summary> /// Add a quad to the mesh /// </summary> /// <param name="vertices">List of vertices of the quad (order is important!).</param> /// <param name="color">Color to apply to all 4 vertices</param> /// <param name="subMesh">Which submesh the quad belongs to</param> /// <param name="normal">normal of each vertex</param> public void AddQuad(Vector3[] vertices, Color32 color, SubMeshes subMesh, Vector3 normal) { if (!CheckVerticeCount(4, vertices.Length)) { return; } for (int i = 0; i < 4; i++) { _Vertices.Add(vertices[i]); _Colors.Add(color); _Normals.Add(normal); } int vertCount = _Vertices.Count; _Triangles[(int)subMesh].Add(vertCount - 4); _Triangles[(int)subMesh].Add(vertCount - 3); _Triangles[(int)subMesh].Add(vertCount - 1); _Triangles[(int)subMesh].Add(vertCount - 1); _Triangles[(int)subMesh].Add(vertCount - 3); _Triangles[(int)subMesh].Add(vertCount - 2); }
internal void Read(EndianBinaryReader reader, ObjectSection section = null) { reader.SeekCurrent(4); BoundingSphere = reader.ReadBoundingSphere(); int subMeshCount = reader.ReadInt32(); long subMeshesOffset = reader.ReadOffset(); var attributes = ( VertexFormatAttribute )reader.ReadUInt32(); int stride = reader.ReadInt32(); int vertexCount = reader.ReadInt32(); var elemItems = reader.ReadUInt32s(section?.Format == BinaryFormat.X ? 49 : 28); Name = reader.ReadString(StringBinaryFormat.FixedLength, 64); SubMeshes.Capacity = subMeshCount; for (int i = 0; i < subMeshCount; i++) { reader.ReadAtOffset(subMeshesOffset + i * SubMesh.GetByteSize(section?.Format ?? BinaryFormat.DT), () => { var subMesh = new SubMesh(); subMesh.Read(reader, section); SubMeshes.Add(subMesh); }); } // Modern Format if (section != null) { ReadVertexAttributesModern(); } else { ReadVertexAttributesClassic(); } void ReadVertexAttributesClassic() { Vector4[] boneWeights = null; Vector4[] boneIndices = null; for (int i = 0; i < 28; i++) { var attribute = ( VertexFormatAttribute )(1 << i); reader.ReadAtOffsetIf((attributes & attribute) != 0, elemItems[i], () => { switch (attribute) { case VertexFormatAttribute.Vertex: Vertices = reader.ReadVector3s(vertexCount); break; case VertexFormatAttribute.Normal: Normals = reader.ReadVector3s(vertexCount); break; case VertexFormatAttribute.Tangent: Tangents = reader.ReadVector4s(vertexCount); break; case VertexFormatAttribute.UVChannel1: UVChannel1 = reader.ReadVector2s(vertexCount); break; case VertexFormatAttribute.UVChannel2: UVChannel2 = reader.ReadVector2s(vertexCount); break; case VertexFormatAttribute.Color: Colors = reader.ReadColors(vertexCount); break; case VertexFormatAttribute.BoneWeight: boneWeights = reader.ReadVector4s(vertexCount); break; case VertexFormatAttribute.BoneIndex: boneIndices = reader.ReadVector4s(vertexCount); break; default: Console.WriteLine("Unhandled vertex format element: {0}", attribute); break; } }); } if (boneWeights != null && boneIndices != null) { BoneWeights = new BoneWeight[vertexCount]; for (int i = 0; i < vertexCount; i++) { var weight4 = boneWeights[i]; var index4 = Vector4.Divide(boneIndices[i], 3); var boneWeight = new BoneWeight { Weight1 = weight4.X, Weight2 = weight4.Y, Weight3 = weight4.Z, Weight4 = weight4.W, Index1 = ( int )index4.X, Index2 = ( int )index4.Y, Index3 = ( int )index4.Z, Index4 = ( int )index4.W }; boneWeight.Validate(); BoneWeights[i] = boneWeight; } } } void ReadVertexAttributesModern() { uint dataOffset = elemItems[section.Format == BinaryFormat.X ? 27 : 13]; uint attributeFlags = elemItems[section.Format == BinaryFormat.X ? 42 : 21]; if (attributeFlags == 2 || attributeFlags == 4) { Vertices = new Vector3[vertexCount]; Normals = new Vector3[vertexCount]; Tangents = new Vector4[vertexCount]; UVChannel1 = new Vector2[vertexCount]; UVChannel2 = new Vector2[vertexCount]; Colors = new Color[vertexCount]; if (attributeFlags == 4) { BoneWeights = new BoneWeight[vertexCount]; } bool hasTangents = false; bool hasUVChannel2 = false; bool hasColors = false; var vertexReader = section.VertexData.Reader; for (int i = 0; i < vertexCount; i++) { vertexReader.SeekBegin(section.VertexData.DataOffset + dataOffset + stride * i); Vertices[i] = vertexReader.ReadVector3(); Normals[i] = vertexReader.ReadVector3(VectorBinaryFormat.Int16); vertexReader.SeekCurrent(2); Tangents[i] = vertexReader.ReadVector4(VectorBinaryFormat.Int16); UVChannel1[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half); UVChannel2[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half); Colors[i] = vertexReader.ReadColor(VectorBinaryFormat.Half); if (attributeFlags == 4) { var boneWeight = new BoneWeight { Weight1 = vertexReader.ReadUInt16() / 32767f, Weight2 = vertexReader.ReadUInt16() / 32767f, Weight3 = vertexReader.ReadUInt16() / 32767f, Weight4 = vertexReader.ReadUInt16() / 32767f, Index1 = vertexReader.ReadByte() / 3, Index2 = vertexReader.ReadByte() / 3, Index3 = vertexReader.ReadByte() / 3, Index4 = vertexReader.ReadByte() / 3 }; boneWeight.Validate(); BoneWeights[i] = boneWeight; } // Normalize normal because precision Normals[i] = Vector3.Normalize(Normals[i]); // Checks to get rid of useless data after reading if (Tangents[i] != Vector4.Zero) { hasTangents = true; } if (UVChannel1[i] != UVChannel2[i]) { hasUVChannel2 = true; } if (!Colors[i].Equals(Color.White)) { hasColors = true; } } if (!hasTangents) { Tangents = null; } if (!hasUVChannel2) { UVChannel2 = null; } if (!hasColors) { Colors = null; } } if (Tangents != null) { for (int i = 0; i < Tangents.Length; i++) { int direction = Math.Sign(Tangents[i].W); var tangent = Vector3.Normalize(new Vector3(Tangents[i].X, Tangents[i].Y, Tangents[i].Z)); Tangents[i] = new Vector4(tangent, direction); } } } }
/// <summary> /// Returns the submesh for this face based on material info. /// </summary> /// <param name='f'>The face to find a submesh for.</param> public KeyValuePair <IntermediateMaterial, List <int> > FindOrCreateSubMesh(Face f) { ExternalReference externalRef = null; if (Header.Parent != null) { externalRef = Header.Parent as ExternalReference; } // Fetch palettes MaterialPalette mp = null; if (f.MaterialIndex != -1) { if (externalRef != null) { externalRef.Header.MaterialPalettes.TryGetValue(f.MaterialIndex, out mp); } if (mp == null) { Header.MaterialPalettes.TryGetValue(f.MaterialIndex, out mp); } if (mp == null) { Log.WriteError("Could not find material palette: " + f.MaterialIndex); } } TexturePalette mainTex = null; if (f.TexturePattern != -1) { if (externalRef != null) { externalRef.Header.TexturePalettes.TryGetValue(f.TexturePattern, out mainTex); } if (mainTex == null) { Header.TexturePalettes.TryGetValue(f.TexturePattern, out mainTex); } if (mainTex == null) { Log.WriteError("Could not find texture pattern: " + f.TexturePattern); } } TexturePalette detailTex = null; if (f.DetailTexturePattern != -1) { if (externalRef != null) { externalRef.Header.TexturePalettes.TryGetValue(f.DetailTexturePattern, out detailTex); } if (mainTex == null) { Header.TexturePalettes.TryGetValue(f.DetailTexturePattern, out detailTex); } if (mainTex == null) { Log.WriteError("Could not find detail texture pattern: " + f.DetailTexturePattern); } } // Check locally foreach (KeyValuePair <IntermediateMaterial, List <int> > mesh in SubMeshes) { if (mesh.Key.Equals(mp, mainTex, detailTex, f.Transparency, f.LightMode)) { return(mesh); } } // Create a new submesh IntermediateMaterial im = Header.MaterialBank.FindOrCreateMaterial(f); KeyValuePair <IntermediateMaterial, List <int> > newMesh = new KeyValuePair <IntermediateMaterial, List <int> >(im, new List <int>()); SubMeshes.Add(newMesh); return(newMesh); }
protected override YAMLMappingNode ExportYAMLRoot(IExportContainer container) { YAMLMappingNode node = base.ExportYAMLRoot(container); node.AddSerializedVersion(ToSerializedVersion(container.ExportVersion)); if (HasLODData(container.ExportVersion)) { node.Add(LODDataName, LODData.ExportYAML(container)); } else { if (HasUse16bitIndices(container.ExportVersion)) { node.Add(Use16BitIndicesName, Use16BitIndices); } if (IsIndexBufferFirst(container.ExportVersion)) { node.Add(IndexBufferName, IndexBuffer.ExportYAML()); } node.Add(SubMeshesName, SubMeshes.ExportYAML(container)); } if (HasBlendShapes(container.ExportVersion)) { if (HasBlendChannels(container.ExportVersion)) { node.Add(ShapesName, Shapes.ExportYAML(container)); } else { node.Add(ShapesName, BlendShapes.ExportYAML(container)); node.Add(ShapeVerticesName, ShapeVertices.ExportYAML(container)); } } if (HasBindPose(container.ExportVersion)) { if (IsBindPoseFirst(container.ExportVersion)) { node.Add(BindPoseName, BindPose.ExportYAML(container)); } } if (HasBoneNameHashes(container.ExportVersion)) { node.Add(BoneNameHashesName, BoneNameHashes.ExportYAML(true)); node.Add(RootBoneNameHashName, RootBoneNameHash); } if (HasBonesAABB(container.ExportVersion)) { node.Add(BonesAABBName, BonesAABB.ExportYAML(container)); node.Add(VariableBoneCountWeightsName, VariableBoneCountWeights.ExportYAML(container)); } if (HasMeshCompression(container.ExportVersion)) { node.Add(MeshCompressionName, (byte)MeshCompression); } if (HasStreamCompression(container.ExportVersion)) { node.Add(StreamCompressionName, StreamCompression); } if (HasIsReadable(container.ExportVersion)) { node.Add(IsReadableName, IsReadable); node.Add(KeepVerticesName, KeepVertices); node.Add(KeepIndicesName, KeepIndices); } if (HasIndexFormat(container.ExportVersion)) { node.Add(IndexFormatName, (int)IndexFormat); } if (!HasLODData(container.ExportVersion)) { if (!IsIndexBufferFirst(container.ExportVersion)) { node.Add(IndexBufferName, IndexBuffer.ExportYAML()); } } if (HasVertexData(container.ExportVersion)) { if (!IsOnlyVertexData(container.ExportVersion)) { if (MeshCompression != MeshCompression.Off) { node.Add(VerticesName, Vertices.ExportYAML(container)); } } } else { node.Add(VerticesName, Vertices.ExportYAML(container)); } if (HasSkin(container.ExportVersion)) { node.Add(SkinName, Skin.ExportYAML(container)); } if (HasBindPose(container.ExportVersion)) { if (!IsBindPoseFirst(container.ExportVersion)) { node.Add(BindPoseName, BindPose.ExportYAML(container)); } } if (HasVertexData(container.ExportVersion)) { if (IsOnlyVertexData(container.ExportVersion)) { node.Add(VertexDataName, VertexData.ExportYAML(container)); } else { if (MeshCompression == MeshCompression.Off) { node.Add(VertexDataName, VertexData.ExportYAML(container)); } else { node.Add(UVName, UV.ExportYAML(container)); node.Add(UV1Name, UV1.ExportYAML(container)); node.Add(TangentsName, Tangents.ExportYAML(container)); node.Add(NormalsName, Normals.ExportYAML(container)); node.Add(ColorsName, Colors.ExportYAML(container)); } } } else { node.Add(UVName, UV.ExportYAML(container)); if (HasUV1(container.ExportVersion)) { node.Add(UV1Name, UV1.ExportYAML(container)); } if (HasTangentSpace(container.ExportVersion)) { node.Add(TangentSpaceName, Tangents.ExportYAML(container)); } else { node.Add(TangentsName, Tangents.ExportYAML(container)); node.Add(NormalsName, Normals.ExportYAML(container)); } } if (HasCompressedMesh(container.ExportVersion)) { node.Add(CompressedMeshName, CompressedMesh.ExportYAML(container)); } node.Add(LocalAABBName, LocalAABB.ExportYAML(container)); if (!HasVertexData(container.ExportVersion)) { node.Add(ColorsName, Colors.ExportYAML(container)); } if (HasCollisionTriangles(container.ExportVersion)) { node.Add(CollisionTrianglesName, CollisionTriangles.ExportYAML(true)); node.Add(CollisionVertexCountName, CollisionVertexCount); } if (HasMeshUsageFlags(container.ExportVersion)) { node.Add(MeshUsageFlagsName, MeshUsageFlags); } if (HasCollision(container.ExportVersion)) { node.Add(BakedConvexCollisionMeshName, CollisionData.BakedConvexCollisionMesh.ExportYAML()); node.Add(BakedTriangleCollisionMeshName, CollisionData.BakedTriangleCollisionMesh.ExportYAML()); } if (HasMeshMetrics(container.ExportVersion)) { node.Add(MeshMetricsName + "[0]", MeshMetrics[0]); node.Add(MeshMetricsName + "[1]", MeshMetrics[1]); } if (HasMeshOptimization(container.ExportVersion, container.ExportFlags)) { if (IsMeshOptimizationFlags(container.ExportVersion)) { node.Add(MeshOptimizationFlagsName, (int)MeshOptimizationFlags); } else { node.Add(MeshOptimizedName, MeshOptimized); } } if (HasStreamData(container.ExportVersion)) { StreamingInfo streamData = new StreamingInfo(true); node.Add(StreamDataName, streamData.ExportYAML(container)); } return(node); }
public void Push(SkinnedMeshRenderer renderer) { var mesh = renderer.sharedMesh; if (mesh == null) { Debug.LogWarningFormat("{0} has no mesh", renderer.name); return; } Renderers.Add(renderer); var indexOffset = Positions.Count; var boneIndexOffset = Bones.Count; Positions.AddRange(mesh.vertices); Normals.AddRange(mesh.normals); UV.AddRange(mesh.uv); Tangents.AddRange(mesh.tangents); if (mesh.vertexCount == mesh.boneWeights.Length) { BoneWeights.AddRange(mesh.boneWeights.Select(x => AddBoneIndexOffset(x, boneIndexOffset)).ToArray()); } else { BoneWeights.AddRange(Enumerable.Range(0, mesh.vertexCount).Select(x => new BoneWeight()).ToArray()); } BindPoses.AddRange(mesh.bindposes); Bones.AddRange(renderer.bones); for (int i = 0; i < mesh.subMeshCount; ++i) { var indices = mesh.GetIndices(i).Select(x => x + indexOffset); var mat = renderer.sharedMaterials[i]; var sameMaterialSubMeshIndex = SubMeshes.FindIndex(x => ReferenceEquals(x.Material, mat)); if (sameMaterialSubMeshIndex >= 0) { SubMeshes[sameMaterialSubMeshIndex].Indices.AddRange(indices); } else { SubMeshes.Add(new SubMesh { Indices = indices.ToList(), Material = mat, }); } } for (int i = 0; i < mesh.blendShapeCount; ++i) { var positions = (Vector3[])mesh.vertices.Clone(); var normals = (Vector3[])mesh.normals.Clone(); var tangents = mesh.tangents.Select(x => (Vector3)x).ToArray(); mesh.GetBlendShapeFrameVertices(i, 0, positions, normals, tangents); BlendShapes.Add(new BlendShape { VertexOffset = indexOffset, FrameWeight = mesh.GetBlendShapeFrameWeight(i, 0), Name = mesh.GetBlendShapeName(i), Positions = positions, Normals = normals, Tangents = tangents, }); } }
public override void Write(AssetWriter writer) { base.Write(writer); if (HasLODData(writer.Version)) { LODData.Write(writer); } else { if (HasUse16bitIndices(writer.Version)) { writer.Write(Use16BitIndices); } if (IsIndexBufferFirst(writer.Version)) { IndexBuffer.Write(writer); writer.AlignStream(AlignType.Align4); } SubMeshes.Write(writer); } if (HasBlendShapes(writer.Version)) { if (HasBlendChannels(writer.Version)) { Shapes.Write(writer); } else { BlendShapes.Write(writer); writer.AlignStream(AlignType.Align4); ShapeVertices.Write(writer); } } if (HasBindPose(writer.Version)) { if (IsBindPoseFirst(writer.Version)) { BindPose.Write(writer); } } if (HasBoneNameHashes(writer.Version)) { BoneNameHashes.Write(writer); writer.Write(RootBoneNameHash); } if (HasBonesAABB(writer.Version)) { BonesAABB.Write(writer); VariableBoneCountWeights.Write(writer); } if (HasMeshCompression(writer.Version)) { writer.Write((byte)MeshCompression); } if (HasStreamCompression(writer.Version)) { writer.Write(StreamCompression); } if (HasIsReadable(writer.Version)) { writer.Write(IsReadable); writer.Write(KeepVertices); writer.Write(KeepIndices); } if (IsAlignFlags(writer.Version)) { writer.AlignStream(AlignType.Align4); } if (HasIndexFormat(writer.Version)) { if (IsIndexFormatCondition(writer.Version)) { if (MeshCompression == MeshCompression.Off) { writer.Write((int)IndexFormat); } } else { writer.Write((int)IndexFormat); } } if (!HasLODData(writer.Version)) { if (!IsIndexBufferFirst(writer.Version)) { IndexBuffer.Write(writer); writer.AlignStream(AlignType.Align4); } } if (HasVertexData(writer.Version)) { if (!IsOnlyVertexData(writer.Version)) { if (MeshCompression != MeshCompression.Off) { Vertices.Write(writer); } } } else { Vertices.Write(writer); } if (HasSkin(writer.Version)) { Skin.Write(writer); } if (HasBindPose(writer.Version)) { if (!IsBindPoseFirst(writer.Version)) { BindPose.Write(writer); } } if (HasVertexData(writer.Version)) { if (IsOnlyVertexData(writer.Version)) { VertexData.Write(writer); } else { if (MeshCompression == MeshCompression.Off) { VertexData.Write(writer); } else { UV.Write(writer); UV1.Write(writer); Tangents.Write(writer); Normals.Write(writer); Colors.Write(writer); } } } else { UV.Write(writer); if (HasUV1(writer.Version)) { UV1.Write(writer); } if (HasTangentSpace(writer.Version)) { TangentSpace.Write(writer); } else { Tangents.Write(writer); Normals.Write(writer); } } if (IsAlignVertex(writer.Version)) { writer.AlignStream(AlignType.Align4); } if (HasCompressedMesh(writer.Version)) { CompressedMesh.Write(writer); } LocalAABB.Write(writer); if (!HasVertexData(writer.Version)) { Colors.Write(writer); } if (HasCollisionTriangles(writer.Version)) { CollisionTriangles.Write(writer); writer.Write(CollisionVertexCount); } if (HasMeshUsageFlags(writer.Version)) { writer.Write(MeshUsageFlags); } if (HasCollision(writer.Version)) { CollisionData.Write(writer); } if (HasMeshMetrics(writer.Version)) { writer.Write(MeshMetrics[0]); writer.Write(MeshMetrics[1]); } #if UNIVERSAL if (HasMeshOptimization(writer.Version, writer.Flags)) { if (IsMeshOptimizationFlags(writer.Version)) { writer.Write((int)MeshOptimizationFlags); } else { writer.Write(MeshOptimized); } } #endif if (HasStreamData(writer.Version)) { writer.AlignStream(AlignType.Align4); StreamData.Write(writer); } }
internal void Read(EndianBinaryReader reader, ObjectSection section = null) { reader.SeekCurrent(4); // Unused flags BoundingSphere = reader.ReadBoundingSphere(); int subMeshCount = reader.ReadInt32(); long subMeshesOffset = reader.ReadOffset(); var vertexFormat = ( VertexFormatAttributes )reader.ReadUInt32(); int vertexSize = reader.ReadInt32(); int vertexCount = reader.ReadInt32(); var attributeOffsets = reader.ReadOffsets(20); Flags = ( MeshFlags )reader.ReadInt32(); uint attributeFlags = reader.ReadUInt32(); reader.SkipNulls(6 * sizeof(uint)); Name = reader.ReadString(StringBinaryFormat.FixedLength, 64); reader.ReadAtOffset(subMeshesOffset, () => { SubMeshes.Capacity = subMeshCount; for (int i = 0; i < subMeshCount; i++) { var subMesh = new SubMesh(); subMesh.Read(reader, section); SubMeshes.Add(subMesh); } }); // Modern Format if ((vertexFormat & VertexFormatAttributes.UsesModernStorage) != 0) { ReadVertexAttributesModern(); } else { ReadVertexAttributesClassic(); } void ReadVertexAttributesClassic() { Vector4[] boneWeights = null; Vector4[] boneIndices = null; for (int i = 0; i < attributeOffsets.Length; i++) { var attribute = ( VertexFormatAttributes )(1 << i); reader.ReadAtOffsetIf((vertexFormat & attribute) != 0, attributeOffsets[i], () => { switch (attribute) { case VertexFormatAttributes.Position: Positions = reader.ReadVector3s(vertexCount); break; case VertexFormatAttributes.Normal: Normals = reader.ReadVector3s(vertexCount); break; case VertexFormatAttributes.Tangent: Tangents = reader.ReadVector4s(vertexCount); break; case VertexFormatAttributes.TexCoord0: TexCoords0 = reader.ReadVector2s(vertexCount); break; case VertexFormatAttributes.TexCoord1: TexCoords1 = reader.ReadVector2s(vertexCount); break; case VertexFormatAttributes.TexCoord2: TexCoords2 = reader.ReadVector2s(vertexCount); break; case VertexFormatAttributes.TexCoord3: TexCoords3 = reader.ReadVector2s(vertexCount); break; case VertexFormatAttributes.Color0: Colors0 = reader.ReadColors(vertexCount); break; case VertexFormatAttributes.Color1: Colors1 = reader.ReadColors(vertexCount); break; case VertexFormatAttributes.BoneWeight: boneWeights = reader.ReadVector4s(vertexCount); break; case VertexFormatAttributes.BoneIndex: boneIndices = reader.ReadVector4s(vertexCount); break; default: Console.WriteLine("Unhandled vertex format element: {0}", attribute); break; } }); } if (boneWeights == null || boneIndices == null) { return; } BoneWeights = new BoneWeight[vertexCount]; for (int i = 0; i < vertexCount; i++) { var weight4 = boneWeights[i]; var index4 = Vector4.Divide(boneIndices[i], 3); var boneWeight = new BoneWeight { Weight1 = weight4.X, Weight2 = weight4.Y, Weight3 = weight4.Z, Weight4 = weight4.W, Index1 = ( int )index4.X, Index2 = ( int )index4.Y, Index3 = ( int )index4.Z, Index4 = ( int )index4.W }; boneWeight.Validate(); BoneWeights[i] = boneWeight; } } void ReadVertexAttributesModern() { Positions = new Vector3[vertexCount]; Normals = new Vector3[vertexCount]; Tangents = new Vector4[vertexCount]; TexCoords0 = new Vector2[vertexCount]; TexCoords1 = new Vector2[vertexCount]; if (attributeFlags == 10) { TexCoords2 = new Vector2[vertexCount]; TexCoords3 = new Vector2[vertexCount]; } else if (attributeFlags == 6) { TexCoords2 = new Vector2[vertexCount]; } Colors0 = new Color[vertexCount]; if (attributeFlags == 4) { BoneWeights = new BoneWeight[vertexCount]; } bool hasTangents = false; EndianBinaryReader vertexReader; long baseOffset; if (section != null) { vertexReader = section.VertexData.Reader; baseOffset = section.VertexData.DataOffset; } else { vertexReader = reader; baseOffset = reader.BaseOffset; } long current = reader.Position; for (int i = 0; i < vertexCount; i++) { vertexReader.SeekBegin(baseOffset + attributeOffsets[13] + vertexSize * i); Positions[i] = vertexReader.ReadVector3(); Normals[i] = vertexReader.ReadVector3(VectorBinaryFormat.Int16); vertexReader.SeekCurrent(2); Tangents[i] = vertexReader.ReadVector4(VectorBinaryFormat.Int16); TexCoords0[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half); TexCoords1[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half); if (attributeFlags == 10) { TexCoords2[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half); TexCoords3[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half); } else if (attributeFlags == 6) { TexCoords2[i] = vertexReader.ReadVector2(VectorBinaryFormat.Half); } Colors0[i] = vertexReader.ReadColor(VectorBinaryFormat.Half); if (attributeFlags == 4) { var boneWeight = new BoneWeight { Weight1 = vertexReader.ReadUInt16() / 32767f, Weight2 = vertexReader.ReadUInt16() / 32767f, Weight3 = vertexReader.ReadUInt16() / 32767f, Weight4 = vertexReader.ReadUInt16() / 32767f, Index1 = vertexReader.ReadByte() / 3, Index2 = vertexReader.ReadByte() / 3, Index3 = vertexReader.ReadByte() / 3, Index4 = vertexReader.ReadByte() / 3 }; boneWeight.Validate(); BoneWeights[i] = boneWeight; } // Normalize normal because precision Normals[i] = Vector3.Normalize(Normals[i]); // Checks to get rid of useless data after reading if (Tangents[i] != Vector4.Zero) { hasTangents = true; } } if (!hasTangents) { Tangents = null; } reader.SeekBegin(current); } if (Tangents == null) { return; } for (int i = 0; i < Tangents.Length; i++) { int direction = Math.Sign(Tangents[i].W); var tangent = Vector3.Normalize(new Vector3(Tangents[i].X, Tangents[i].Y, Tangents[i].Z)); Tangents[i] = new Vector4(tangent, direction); } }
public MeshIntegrationResult Integrate(MeshEnumerateOption onlyBlendShapeRenderers) { var mesh = new Mesh(); if (Positions.Count > ushort.MaxValue) { Debug.LogFormat("exceed 65535 vertices: {0}", Positions.Count); mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; } mesh.vertices = Positions.ToArray(); mesh.normals = Normals.ToArray(); mesh.uv = UV.ToArray(); mesh.tangents = Tangents.ToArray(); mesh.boneWeights = BoneWeights.ToArray(); mesh.subMeshCount = SubMeshes.Count; for (var i = 0; i < SubMeshes.Count; ++i) { mesh.SetIndices(SubMeshes[i].Indices.ToArray(), MeshTopology.Triangles, i); } mesh.bindposes = BindPoses.ToArray(); // blendshape switch (onlyBlendShapeRenderers) { case MeshEnumerateOption.OnlyWithBlendShape: { AddBlendShapesToMesh(mesh); mesh.name = INTEGRATED_MESH_WITH_BLENDSHAPE_NAME; break; } case MeshEnumerateOption.All: { AddBlendShapesToMesh(mesh); mesh.name = INTEGRATED_MESH_ALL_NAME; break; } case MeshEnumerateOption.OnlyWithoutBlendShape: { mesh.name = INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME; break; } } // meshName var meshNode = new GameObject(); switch (onlyBlendShapeRenderers) { case MeshEnumerateOption.OnlyWithBlendShape: { meshNode.name = INTEGRATED_MESH_WITH_BLENDSHAPE_NAME; break; } case MeshEnumerateOption.OnlyWithoutBlendShape: { meshNode.name = INTEGRATED_MESH_WITHOUT_BLENDSHAPE_NAME; break; } case MeshEnumerateOption.All: { meshNode.name = INTEGRATED_MESH_ALL_NAME; break; } } var integrated = meshNode.AddComponent <SkinnedMeshRenderer>(); integrated.sharedMesh = mesh; integrated.sharedMaterials = SubMeshes.Select(x => x.Material).ToArray(); integrated.bones = Bones.ToArray(); Result.IntegratedRenderer = integrated; Result.MeshMap.Integrated = mesh; return(Result); }
public void Push(MeshRenderer renderer) { var meshFilter = renderer.GetComponent <MeshFilter>(); if (meshFilter == null) { Debug.LogWarningFormat("{0} has no mesh filter", renderer.name); return; } var mesh = meshFilter.sharedMesh; if (mesh == null) { Debug.LogWarningFormat("{0} has no mesh", renderer.name); return; } Result.SourceMeshRenderers.Add(renderer); Result.MeshMap.Sources.Add(mesh); var indexOffset = Positions.Count; var boneIndexOffset = Bones.Count; Positions.AddRange(mesh.vertices .Select(x => renderer.transform.TransformPoint(x)) ); Normals.AddRange(mesh.normals .Select(x => renderer.transform.TransformVector(x)) ); UV.AddRange(mesh.uv); Tangents.AddRange(mesh.tangents .Select(t => { var v = renderer.transform.TransformVector(t.x, t.y, t.z); return(new Vector4(v.x, v.y, v.z, t.w)); }) ); var self = renderer.transform; var bone = self.parent; if (bone == null) { Debug.LogWarningFormat("{0} is root gameobject.", self.name); return; } var bindpose = bone.worldToLocalMatrix; BoneWeights.AddRange(Enumerable.Range(0, mesh.vertices.Length) .Select(x => new BoneWeight() { boneIndex0 = Bones.Count, weight0 = 1, }) ); BindPoses.Add(bindpose); Bones.Add(bone); for (int i = 0; i < mesh.subMeshCount && i < renderer.sharedMaterials.Length; ++i) { var indices = mesh.GetIndices(i).Select(x => x + indexOffset); var mat = renderer.sharedMaterials[i]; var sameMaterialSubMeshIndex = SubMeshes.FindIndex(x => ReferenceEquals(x.Material, mat)); if (sameMaterialSubMeshIndex >= 0) { SubMeshes[sameMaterialSubMeshIndex].Indices.AddRange(indices); } else { SubMeshes.Add(new SubMesh { Indices = indices.ToList(), Material = mat, }); } } }
public void BuildMesh(RenderResource resource) { float v = 1.2f; float h = 1.0f; BasicVertex[] vertices = { new BasicVertex { X = 0, Y = v, Z = 0 }, new BasicVertex { X = -h, Y = 0, Z = h }, new BasicVertex { X = -h, Y = 0, Z = -h }, new BasicVertex { X = h, Y = 0, Z = -h }, new BasicVertex { X = h, Y = 0, Z = h }, new BasicVertex { X = 0, Y = -v, Z = 0 } }; _vertexList.AddRange(vertices); int[] indices = { 0, 1, 2, 5, 3, 2, 0, 3, 4, 5, 1, 4, 5, 2, 1, 0, 2, 3, 5, 4, 3, 0, 4, 1 }; _indexList.AddRange(indices); Technique = "DefaultRender"; Mesh = new MeshPCT(resource, this); SubMesh subMeshA = new SubMesh { Name = MeshName + "-0", MaterialIndex = 0, indexCount = 12, startIndexLocation = 0, baseVertexLocation = 0 }; SubMeshes.Add(subMeshA); SubMesh subMeshB = new SubMesh { Name = MeshName + "-1", MaterialIndex = 1, indexCount = 12, startIndexLocation = 12, baseVertexLocation = 0 }; SubMeshes.Add(subMeshB); }