internal static void PlanarProject(ProBuilderMesh mesh, int textureGroup, AutoUnwrapSettings unwrapSettings) { var worldSpace = unwrapSettings.useWorldSpace; var trs = (Transform)null; var faces = mesh.facesInternal; // Get a projection direction by averaging the normals of all selected faces var projectionDirection = Vector3.zero; for (int f = 0, fc = faces.Length; f < fc; ++f) { if (faces[f].textureGroup != textureGroup) { continue; } var nrm = Math.Normal(mesh, faces[f]); projectionDirection += nrm; } if (worldSpace) { trs = mesh.transform; projectionDirection = trs.TransformDirection(projectionDirection); } var axis = VectorToProjectionAxis(projectionDirection); var prj = GetTangentToAxis(axis); var u = Vector3.Cross(projectionDirection, prj); var v = Vector3.Cross(u, projectionDirection); u.Normalize(); v.Normalize(); var positions = mesh.positionsInternal; var textures = mesh.texturesInternal; for (int f = 0, fc = faces.Length; f < fc; ++f) { if (faces[f].textureGroup != textureGroup) { continue; } var indexes = faces[f].distinctIndexesInternal; for (int i = 0, ic = indexes.Length; i < ic; ++i) { var p = worldSpace ? trs.TransformPoint(positions[indexes[i]]) : positions[indexes[i]]; textures[indexes[i]].x = Vector3.Dot(u, p); textures[indexes[i]].y = Vector3.Dot(v, p); } } }
internal Face(IEnumerable <int> triangles, int submeshIndex, AutoUnwrapSettings u, int smoothing, int texture, int element, bool manualUVs) { SetIndexes(triangles); m_Uv = new AutoUnwrapSettings(u); m_SmoothingGroup = smoothing; textureGroup = texture; elementGroup = element; manualUV = manualUVs; m_SubmeshIndex = submeshIndex; }
/// <summary> /// Initialize a Face with a set of triangles and default values. /// </summary> /// <param name="indices">The new triangles array.</param> public Face(IEnumerable <int> indices) { SetIndexes(indices); m_Uv = AutoUnwrapSettings.tile; m_Material = BuiltinMaterials.defaultMaterial; m_SmoothingGroup = Smoothing.smoothingGroupNone; m_SubmeshIndex = 0; textureGroup = -1; elementGroup = 0; }
/// <summary> /// Initialize a Face with a set of triangles and default values. /// </summary> /// <param name="array">The new triangles array.</param> public Face(int[] array) { SetIndexes(array); m_Uv = AutoUnwrapSettings.tile; m_Material = BuiltinMaterials.defaultMaterial; m_SmoothingGroup = Smoothing.smoothingGroupNone; m_SubmeshIndex = 0; textureGroup = -1; elementGroup = 0; }
internal Face(int[] triangles, Material m, AutoUnwrapSettings u, int smoothing, int texture, int element, bool manualUVs) { SetIndexes(triangles); m_Uv = new AutoUnwrapSettings(u); m_Material = m; m_SmoothingGroup = smoothing; textureGroup = texture; elementGroup = element; manualUV = manualUVs; m_SubmeshIndex = 0; }
/// <summary> /// A copy constructor. /// </summary> /// <param name="unwrapSettings">The settings to copy to this new instance.</param> public AutoUnwrapSettings(AutoUnwrapSettings unwrapSettings) { m_UseWorldSpace = unwrapSettings.m_UseWorldSpace; m_FlipU = unwrapSettings.m_FlipU; m_FlipV = unwrapSettings.m_FlipV; m_SwapUV = unwrapSettings.m_SwapUV; m_Fill = unwrapSettings.m_Fill; m_Scale = unwrapSettings.m_Scale; m_Offset = unwrapSettings.m_Offset; m_Rotation = unwrapSettings.m_Rotation; m_Anchor = unwrapSettings.m_Anchor; }
internal static void ProjectTextureGroup(ProBuilderMesh mesh, int group, AutoUnwrapSettings unwrapSettings) { Projection.PlanarProject(mesh, group, unwrapSettings); foreach (var face in mesh.facesInternal) { if (face.textureGroup == group) { ApplyUVSettings(mesh.texturesInternal, face.distinctIndexesInternal, unwrapSettings); } } }
internal static void ProjectTextureGroup(ProBuilderMesh mesh, int group, AutoUnwrapSettings unwrapSettings) { Projection.PlanarProject(mesh, group, unwrapSettings); s_IndexBuffer.Clear(); foreach (var face in mesh.facesInternal) { if (face.textureGroup == group) { s_IndexBuffer.AddRange(face.distinctIndexesInternal); } } ApplyUVSettings(mesh.texturesInternal, s_IndexBuffer, unwrapSettings); }
internal void SetGroupUV(AutoUnwrapSettings settings, int group) { if (!IsValidTextureGroup(group)) { return; } foreach (var face in facesInternal) { if (face.textureGroup != group) { continue; } face.uv = settings; } }
internal static void PlanarProject(ProBuilderMesh mesh, int textureGroup, AutoUnwrapSettings unwrapSettings) { var worldSpace = unwrapSettings.useWorldSpace; var nrm = FindBestPlane(mesh, textureGroup).normal; var trs = (Transform)null; if (worldSpace) { trs = mesh.transform; nrm = trs.TransformDirection(nrm); } var axis = VectorToProjectionAxis(nrm); var prj = GetTangentToAxis(axis); var u = Vector3.Cross(nrm, prj); var v = Vector3.Cross(u, nrm); u.Normalize(); v.Normalize(); var faces = mesh.facesInternal; var positions = mesh.positionsInternal; var textures = mesh.texturesInternal; for (int f = 0, fc = faces.Length; f < fc; ++f) { if (faces[f].textureGroup != textureGroup) { continue; } var indexes = faces[f].distinctIndexesInternal; for (int i = 0, ic = indexes.Length; i < ic; ++i) { var p = worldSpace ? trs.TransformPoint(positions[indexes[i]]) : positions[indexes[i]]; textures[indexes[i]].x = Vector3.Dot(u, p); textures[indexes[i]].y = Vector3.Dot(v, p); } } }
/// <summary> /// Copies values from other to this face. /// </summary> /// <param name="other">The Face from which to copy properties.</param> public void CopyFrom(Face other) { if (other == null) { throw new ArgumentNullException("other"); } int len = other.indexesInternal.Length; m_Indexes = new int[len]; Array.Copy(other.indexesInternal, m_Indexes, len); m_SmoothingGroup = other.smoothingGroup; m_Uv = new AutoUnwrapSettings(other.uv); #pragma warning disable 618 m_Material = other.material; #pragma warning restore 618 manualUV = other.manualUV; elementGroup = other.elementGroup; m_SubmeshIndex = other.m_SubmeshIndex; InvalidateCache(); }
static void ApplyUVSettings(Vector2[] uvs, int[] indexes, AutoUnwrapSettings uvSettings) { int len = indexes.Length; switch (uvSettings.fill) { case AutoUnwrapSettings.Fill.Tile: break; case AutoUnwrapSettings.Fill.Fit: FitUVs(uvs, indexes); break; case AutoUnwrapSettings.Fill.Stretch: StretchUVs(uvs, indexes); break; } if (!uvSettings.useWorldSpace && uvSettings.anchor != AutoUnwrapSettings.Anchor.None) { ApplyUVAnchor(uvs, indexes, uvSettings.anchor); } // Apply transform last, so that fill and justify don't override it. if (uvSettings.scale.x != 1f || uvSettings.scale.y != 1f || uvSettings.rotation != 0f) { Vector2 center = Bounds2D.Center(uvs, indexes); for (int i = 0; i < len; i++) { uvs[indexes[i]] = uvs[indexes[i]].ScaleAroundPoint(center, uvSettings.scale); uvs[indexes[i]] = uvs[indexes[i]].RotateAroundPoint(center, uvSettings.rotation); } } if (uvSettings.flipU || uvSettings.flipV || uvSettings.swapUV) { for (int i = 0; i < len; i++) { float u = uvs[indexes[i]].x, v = uvs[indexes[i]].y; if (uvSettings.flipU) { u = -u; } if (uvSettings.flipV) { v = -v; } if (!uvSettings.swapUV) { uvs[indexes[i]].x = u; uvs[indexes[i]].y = v; } else { uvs[indexes[i]].x = v; uvs[indexes[i]].y = u; } } } for (int i = 0; i < indexes.Length; i++) { uvs[indexes[i]].x -= uvSettings.offset.x; uvs[indexes[i]].y -= uvSettings.offset.y; } }
static void ApplyUVSettings(Vector2[] uvs, IList <int> indexes, AutoUnwrapSettings uvSettings) { int len = indexes.Count; Bounds2D bounds = new Bounds2D(uvs, indexes); switch (uvSettings.fill) { case AutoUnwrapSettings.Fill.Tile: break; case AutoUnwrapSettings.Fill.Fit: var max = Mathf.Max(bounds.size.x, bounds.size.y); ScaleUVs(uvs, indexes, new Vector2(max, max), bounds); bounds.center /= max; break; case AutoUnwrapSettings.Fill.Stretch: ScaleUVs(uvs, indexes, bounds.size, bounds); bounds.center /= bounds.size; break; } // Apply transform last, so that fill and justify don't override it. if (uvSettings.scale.x != 1f || uvSettings.scale.y != 1f || uvSettings.rotation != 0f) { // apply an offset to the positions relative to UV scale before rotation or scale is applied so that // UVs remain static in UV space Vector2 scaledCenter = bounds.center * uvSettings.scale; Vector2 delta = bounds.center - scaledCenter; Vector2 center = scaledCenter; for (int i = 0; i < len; i++) { uvs[indexes[i]] -= delta; uvs[indexes[i]] = uvs[indexes[i]].ScaleAroundPoint(center, uvSettings.scale); uvs[indexes[i]] = uvs[indexes[i]].RotateAroundPoint(center, uvSettings.rotation); } } if (!uvSettings.useWorldSpace && uvSettings.anchor != AutoUnwrapSettings.Anchor.None) { ApplyUVAnchor(uvs, indexes, uvSettings.anchor); } if (uvSettings.flipU || uvSettings.flipV || uvSettings.swapUV) { for (int i = 0; i < len; i++) { float u = uvs[indexes[i]].x, v = uvs[indexes[i]].y; if (uvSettings.flipU) { u = -u; } if (uvSettings.flipV) { v = -v; } if (!uvSettings.swapUV) { uvs[indexes[i]].x = u; uvs[indexes[i]].y = v; } else { uvs[indexes[i]].x = v; uvs[indexes[i]].y = u; } } } for (int i = 0; i < indexes.Count; i++) { uvs[indexes[i]].x -= uvSettings.offset.x; uvs[indexes[i]].y -= uvSettings.offset.y; } }