// Static API // Rewrites data in mesh to ensure that it only contains valid particle quads. internal static void FilterMesh(Mesh mesh, WarningCallback callback) { ParticleMesh src = ParticleMesh.FromMesh(mesh); ParticleMesh dst = new ParticleMesh(); // ClassifyQuad wants at least 6 indices (2 triangles) to examine int limit = src.TriangleCount - 6; int iiVert = 0; while (iiVert < limit) { switch (src.ClassifyQuad(iiVert, callback)) { case ParticleMesh.QuadType.FullParticle: dst.AppendQuad(src, iiVert); iiVert += 6; break; case ParticleMesh.QuadType.Degenerate: iiVert += 6; break; case ParticleMesh.QuadType.LatterHalfParticle: iiVert += 3; break; case ParticleMesh.QuadType.Unknown: default: iiVert += 1; break; } } dst.CopyToMesh(mesh); }
internal void AppendQuad(ParticleMesh rhs, int iiVert) { // Valid particles are contiguous ranges of 4 verts and 6 indices, // and the first index refers to the first vert. int rv0 = rhs.m_triangles[iiVert]; int indexOffset = m_vertices.Count - rv0; bool hasNormals = rhs.m_normals != null && rhs.m_normals.Count > 0; bool hasTangents = rhs.m_tangents != null && rhs.m_tangents.Count > 0; for (int iv = 0; iv < 4; ++iv) { m_vertices.Add(rhs.m_vertices[rv0 + iv]); if (hasNormals) { m_normals.Add(rhs.m_normals[rv0 + iv]); } m_uv0.Add(rhs.m_uv0[rv0 + iv]); m_uv1.Add(rhs.m_uv1[rv0 + iv]); m_colors.Add(rhs.m_colors[rv0 + iv]); if (hasTangents) { m_tangents.Add(rhs.m_tangents[rv0 + iv]); } } for (int ii = 0; ii < 6; ++ii) { m_triangles.Add(rhs.m_triangles[iiVert + ii] + indexOffset); } }
internal void AppendQuad(ParticleMesh rhs, int iiVert) { int rv0 = rhs.m_triangles[iiVert]; int indexOffset = m_vertices.Count - rv0; bool hasNormals = rhs.m_normals != null && rhs.m_normals.Count > 0; bool hasTangents = rhs.m_tangents != null && rhs.m_tangents.Count > 0; // Assume IsValidParticle, and therefore [v0, v0+6) should be copied for (int i = 0; i < 6; ++i) { m_vertices.Add(rhs.m_vertices [rv0 + i]); if (hasNormals) { m_normals.Add(rhs.m_normals [rv0 + i]); } m_uv0.Add(rhs.m_uv0 [rv0 + i]); m_uv1.Add(rhs.m_uv1 [rv0 + i]); m_colors.Add(rhs.m_colors [rv0 + i]); if (hasTangents) { m_tangents.Add(rhs.m_tangents[rv0 + i]); } m_triangles.Add(rhs.m_triangles[iiVert + i] + indexOffset); } }
// Try to find a Tilt Brush material using the imported models's material name Material OnAssignMaterialModel(Material material, Renderer renderer) { // Ignore models that aren't Tilt Brush - generated FBXs if (!IsTiltBrush) { return(null); } // For now, don't be strict about versions, because we can do an okay job on TB7 fbx files BrushDescriptor desc = GetDescriptorForStroke(material.name); if (desc != null) { // This is a stroke mesh and needs postprocessing. if (renderer.GetComponent <MeshFilter>() != null) { var mesh = renderer.GetComponent <MeshFilter>().sharedMesh; CollapseUvs(mesh); if (m_Info.tiltBrushVersion < new Version { major = 10 }) { // Old versions of TB use linear lighting ConvertSrgbToLinear(mesh); } if (m_Info.tiltBrushVersion.Value.major >= 12) { // Pre-TB12, Tilt Brush did unit conversion but not coord system conversion // when exporting texcoords with Position semantics. TB12 fixes this, so now // texcoord Position data are in fbx coordinates rather than Unity coordinates. // However, this means we need to convert from fbx -> Unity coords on import, // since Unity only takes care of mesh.vertices, tangents, normals, binormals. PerformTexcoordCoordinateConversion(desc, mesh, 0); PerformTexcoordCoordinateConversion(desc, mesh, 1); } if (desc.m_IsParticle) { // Would like to do this in OnPreprocessModel, but we don't yet // know whether it's a particle mesh. var importer = assetImporter as ModelImporter; if (importer != null && importer.optimizeMesh) { // Should never get here any more. LogWarningWithContext("Disabling optimizeMesh and reimporting. Tilt Brush particle meshes must have optimizeMesh=false."); importer.optimizeMesh = false; importer.SaveAndReimport(); } ParticleMesh.FilterMesh(mesh, s => LogWarningWithContext(s, renderer)); } } return(desc.m_Material); } else { return(null); } }
private static ParticleMesh FromMesh(Mesh mesh) { var ret = new ParticleMesh { m_sourceMesh = mesh, m_vertices = mesh.vertices.ToList(), m_normals = mesh.normals.ToList(), m_colors = mesh.colors32.ToList(), m_tangents = mesh.tangents.ToList(), m_triangles = mesh.triangles.ToList() }; mesh.GetUVs(0, ret.m_uv0); mesh.GetUVs(1, ret.m_uv1); return(ret); }
// Try to find a Tilt Brush material using the imported models's material name Material OnAssignMaterialModel(Material material, Renderer renderer) { // Ignore models that aren't Tilt Brush - generated FBXs if (!IsTiltBrush) { return(null); } // For now, don't be strict about versions, because we can do an okay job on TB7 fbx files BrushDescriptor desc = GetDescriptorForStroke(material.name); if (desc != null) { // This is a stroke mesh and needs postprocessing. if (renderer.GetComponent <MeshFilter>() != null) { var mesh = renderer.GetComponent <MeshFilter>().sharedMesh; CollapseUvs(mesh); if (m_Info.tiltBrushVersion < new Version { major = 10 }) { // Old versions of TB use linear lighting ConvertSrgbToLinear(mesh); } if (desc.m_IsParticle) { // Would like to do this in OnPreprocessModel, but we don't yet // know whether it's a particle mesh. var importer = assetImporter as ModelImporter; if (importer != null && importer.optimizeMesh) { // Should never get here any more. LogWarningWithContext("Disabling optimizeMesh and reimporting. Tilt Brush particle meshes must have optimizeMesh=false."); importer.optimizeMesh = false; importer.SaveAndReimport(); } ParticleMesh.FilterMesh(mesh, s => LogWarningWithContext(s, renderer)); } } return(desc.m_Material); } else { return(null); } }
// Try to find a Tilt Brush material using the imported models's material name Material OnAssignMaterialModel(Material material, Renderer renderer) { // Ignore models that aren't Tilt Brush - generated FBXs if (!IsSupportedTiltBrushFbx(assetPath)) { return(null); } BrushDescriptor desc = GetDescriptorForStroke(material.name); if (desc != null) { // This is a stroke mesh and needs postprocessing. if (renderer.GetComponent <MeshFilter>() != null) { var mesh = renderer.GetComponent <MeshFilter>().sharedMesh; CollapseUvs(mesh); if (desc.m_IsParticle) { // Would like to do this in OnPreprocessModel, but we don't yet // know whether it's a particle mesh. var importer = assetImporter as ModelImporter; if (importer != null && importer.optimizeMesh) { LogWarningWithContext("Disabling optimizeMesh and reimporting. Tilt Brush particle meshes must have optimizeMesh=false."); importer.optimizeMesh = false; importer.SaveAndReimport(); } ParticleMesh.FilterMesh(mesh, s => LogWarningWithContext(s, renderer)); } } return(desc.m_Material); } else { return(null); } }
// Try to find a Tilt Brush material using the imported models's material name. Material OnAssignMaterialModel(Material material, Renderer renderer) { // This gets called once for each (Renderer, Material) pair. // However, Unity passes a fresh Material every time, even if two FbxNodes use the // same FbxMaterial. Therefore we can't distinguish between "two unique materials with // the same name" and "one material being used multiple times". // Therefore we have to rely on the exporter using distinct names. // Ignore models that aren't Tilt Brush - generated FBXs if (!IsTiltBrush) { return(null); } // For now, don't be strict about versions, because we can do an okay job on TB7 fbx files BrushDescriptor desc = GetDescriptorForStroke(material.name); if (desc != null) { if (IsTemplateDescriptor(desc)) { // Replace shader with our own so we get culling and so on. // First 32 characters are the guid and underscore material.name = material.name.Substring(33); material.shader = desc.m_Material.shader; // Our shaders don't use "_MainTex", so we need to find the correct property name. SetFirstShaderTexture(material, material.mainTexture); // If we return null, Unity will ignore our material mutations. // If we return the material, Unity complains it's not an asset instead of making it one // and embedding it in the fbx. // So create one explicitly. return(GetOrCreateAsset(material, this.assetPath)); } // This is a stroke mesh and needs postprocessing. if (renderer.GetComponent <MeshFilter>() != null) { var mesh = renderer.GetComponent <MeshFilter>().sharedMesh; CollapseUvs(mesh); if (m_Info.tiltBrushVersion < new Version { major = 10 }) { // Old versions of TB use linear lighting ConvertSrgbToLinear(mesh); } if (m_Info.tiltBrushVersion.Value.major >= 12) { // Pre-TB12, Tilt Brush did unit conversion but not coord system conversion // when exporting texcoords with Position semantics. TB12 fixes this, so now // texcoord Position data are in fbx coordinates rather than Unity coordinates. // However, this means we need to convert from fbx -> Unity coords on import, // since Unity only takes care of mesh.vertices, tangents, normals, binormals. PerformTexcoordCoordinateConversion(desc, mesh, 0); PerformTexcoordCoordinateConversion(desc, mesh, 1); } if (m_Info.tiltBrushVersion.Value.major < 14 && desc.m_Guid == new Guid("e8ef32b1-baa8-460a-9c2c-9cf8506794f5")) { // Pre-TB14, Tilt Brush hadn't set the "Z is distance" semantic and texcoord0.z // ended up in decimeters FixupHypercolorTexcoord(desc, mesh); } if (desc.m_IsParticle) { // Would like to do this in OnPreprocessModel, but we don't yet // know whether it's a particle mesh. var importer = assetImporter as ModelImporter; #if UNITY_2019_1_OR_NEWER if (importer != null && importer.optimizeMeshVertices) { // Should never get here any more. LogWarningWithContext("Disabling optimizeMesh and reimporting. Tilt Brush particle meshes must have importer.optimizeMeshVertices = false."); importer.optimizeMeshVertices = false; importer.SaveAndReimport(); } #else if (importer != null && importer.optimizeMesh) { // Should never get here any more. LogWarningWithContext("Disabling optimizeMesh and reimporting. Tilt Brush particle meshes must have optimizeMesh=false."); importer.optimizeMesh = false; importer.SaveAndReimport(); } #endif ParticleMesh.FilterMesh(mesh, s => LogWarningWithContext(s, renderer)); } } return(desc.m_Material); } else { return(null); } }