/// <summary> /// Get the tangents applied to the mesh, or create and cache them if not yet initialized. /// </summary> /// <returns>The tangents applied to the MeshFilter.sharedMesh. If the tangents array length does not match the vertex count, null is returned.</returns> public Vector4[] GetTangents() { if (!HasArrays(MeshArrays.Tangent)) Normals.CalculateTangents(this); return tangents.ToArray(); }
/// <summary> /// Collects coincident vertices and returns a rotation calculated from the average normal and bitangent. /// </summary> /// <param name="mesh">The target mesh.</param> /// <param name="indices">Vertex indices to consider in the rotation calculations.</param> /// <returns>A rotation calculated from the average normal of each vertex.</returns> public static Quaternion GetRotation(ProBuilderMesh mesh, IEnumerable <int> indices) { if (!mesh.HasArrays(MeshArrays.Normal)) { Normals.CalculateNormals(mesh); } if (!mesh.HasArrays(MeshArrays.Tangent)) { Normals.CalculateTangents(mesh); } var normals = mesh.normalsInternal; var tangents = mesh.tangentsInternal; var nrm = Vector3.zero; var tan = Vector4.zero; float count = 0; foreach (var index in indices) { var n = normals[index]; var t = tangents[index]; nrm.x += n.x; nrm.y += n.y; nrm.z += n.z; tan.x += t.x; tan.y += t.y; tan.z += t.z; tan.w += t.w; count++; } nrm.x /= count; nrm.y /= count; nrm.z /= count; tan.x /= count; tan.y /= count; tan.z /= count; tan.w /= count; if (nrm == Vector3.zero || tan == Vector4.zero) { return(mesh.transform.rotation); } var bit = Vector3.Cross(nrm, tan * tan.w); return(mesh.transform.rotation * Quaternion.LookRotation(nrm, bit)); }
void RefreshTangents() { Normals.CalculateTangents(this); mesh.tangents = m_Tangents; }