protected override void UpdateTempComponent(BrushTarget target, BrushSettings settings) { if (tempComponent != null) { ((OverlayRenderer)tempComponent).SetWeights(target.GetAllWeights(), settings.strength); } }
/// <summary> /// Update the temporary component with new weigths and strengh /// </summary> /// <param name="target">Target object containing the temporary component</param> /// <param name="settings">Current brush settings</param> protected virtual void UpdateTempComponent(BrushTarget target, BrushSettings settings) { if (!Util.IsValid(target)) { return; } tempComponent.SetWeights(target.GetAllWeights(), settings.strength); }
protected override void UpdateTempComponent(BrushTarget target, BrushSettings settings) { if (!Util.IsValid(target)) { return; } EditableObjectData data; if (m_EditableObjectsData.TryGetValue(target.editableObject, out data)) { if (data.TempComponent != null) { ((OverlayRenderer)data.TempComponent).SetWeights(target.GetAllWeights(), settings.strength); } } }
// Called whenever the brush is moved. Note that @target may have a null editableObject. internal override void OnBrushMove(BrushTarget target, BrushSettings settings) { base.OnBrushMove(target, settings); if (!Util.IsValid(target) || !m_LikelySupportsTextureBlending || meshAttributes.Length == 0) { return; } bool invert = settings.isUserHoldingControl; float[] weights; if (paintMode == PaintMode.Brush) { weights = target.GetAllWeights(); } else if (paintMode == PaintMode.Flood) { weights = new float[m_VertexCount]; for (int i = 0; i < m_VertexCount; i++) { weights[i] = 1f; } } else { weights = new float[m_VertexCount]; int[] indices = target.editableObject.editMesh.GetTriangles(); int index = 0; float weightTarget = 1f; foreach (PolyRaycastHit hit in target.raycastHits) { if (hit.triangle > -1) { index = hit.triangle * 3; m_FillModeEdges[0].x = indices[index + 0]; m_FillModeEdges[0].y = indices[index + 1]; m_FillModeEdges[1].x = indices[index + 1]; m_FillModeEdges[1].y = indices[index + 2]; m_FillModeEdges[2].x = indices[index + 2]; m_FillModeEdges[2].y = indices[index + 0]; for (int i = 0; i < 3; i++) { if (m_TriangleLookup.TryGetValue(m_FillModeEdges[i], out m_FillModeAdjacentTriangles)) { for (int n = 0; n < m_FillModeAdjacentTriangles.Count; n++) { index = m_FillModeAdjacentTriangles[n] * 3; weights[indices[index]] = weightTarget; weights[indices[index + 1]] = weightTarget; weights[indices[index + 2]] = weightTarget; } } } } } } int mask = meshAttributes[selectedAttributeIndex].mask; splat_current.LerpWeights(splat_cache, invert ? splat_erase : splat_target, mask, weights); splat_current.Apply(target.editableObject.editMesh); target.editableObject.ApplyMeshAttributes(); }
// Called whenever the brush is moved. Note that @target may have a null editableObject. internal override void OnBrushMove(BrushTarget target, BrushSettings settings) { base.OnBrushMove(target, settings); if (!Util.IsValid(target) || !m_EditableObjectsData.ContainsKey(target.editableObject)) { return; } bool invert = settings.isUserHoldingControl; PolyMesh mesh = target.editableObject.editMesh; int vertexCount = mesh.vertexCount; float[] weights = target.GetAllWeights(); var data = m_EditableObjectsData[target.editableObject]; var vertexColorInfo = data.MeshVertexColors; switch (paintMode) { case PaintMode.Flood: for (int i = 0; i < vertexCount; i++) { vertexColorInfo.Colors[i] = invert? s_WhiteColor : vertexColorInfo.TargetColors[i]; } break; case PaintMode.Fill: System.Array.Copy(vertexColorInfo.OriginalColors, vertexColorInfo.Colors, vertexCount); int[] indices = target.editableObject.editMesh.GetTriangles(); int index = 0; foreach (PolyRaycastHit hit in target.raycastHits) { if (hit.triangle > -1) { index = hit.triangle * 3; vertexColorInfo.Colors[indices[index + 0]] = invert ? s_WhiteColor : vertexColorInfo.TargetColors[indices[index + 0]]; vertexColorInfo.Colors[indices[index + 1]] = invert ? s_WhiteColor : vertexColorInfo.TargetColors[indices[index + 1]]; vertexColorInfo.Colors[indices[index + 2]] = invert ? s_WhiteColor : vertexColorInfo.TargetColors[indices[index + 2]]; m_FillModeEdges[0].x = indices[index + 0]; m_FillModeEdges[0].y = indices[index + 1]; m_FillModeEdges[1].x = indices[index + 1]; m_FillModeEdges[1].y = indices[index + 2]; m_FillModeEdges[2].x = indices[index + 2]; m_FillModeEdges[2].y = indices[index + 0]; for (int i = 0; i < 3; i++) { if (data.TriangleLookup.TryGetValue(m_FillModeEdges[i], out m_FillModeAdjacentTriangles)) { for (int n = 0; n < m_FillModeAdjacentTriangles.Count; n++) { index = m_FillModeAdjacentTriangles[n] * 3; vertexColorInfo.Colors[indices[index + 0]] = invert ? s_WhiteColor : vertexColorInfo.TargetColors[indices[index + 0]]; vertexColorInfo.Colors[indices[index + 1]] = invert ? s_WhiteColor : vertexColorInfo.TargetColors[indices[index + 1]]; vertexColorInfo.Colors[indices[index + 2]] = invert ? s_WhiteColor : vertexColorInfo.TargetColors[indices[index + 2]]; } } } } } break; default: { for (int i = 0; i < vertexCount; i++) { vertexColorInfo.Colors[i] = Util.Lerp(vertexColorInfo.OriginalColors[i], invert ? vertexColorInfo.EraseColors[i] : vertexColorInfo.TargetColors[i], mask, weights[i]); } break; } } target.editableObject.editMesh.colors = vertexColorInfo.Colors; target.editableObject.ApplyMeshAttributes(MeshChannel.Color); }
/// <summary> /// Draw scene gizmos. Base implementation draws the brush preview. /// </summary> /// <param name="target">Current target Object</param> /// <param name="settings">Current brush settings</param> internal virtual void DrawGizmos(BrushTarget target, BrushSettings settings) { UpdateBrushGizmosColor(); foreach (PolyRaycastHit hit in target.raycastHits) { PolyHandles.DrawBrush(hit.position, hit.normal, settings, target.localToWorldMatrix, innerColor, outerColor); } #if Z_DEBUG #if Z_DRAW_WEIGHTS || DRAW_PER_VERTEX_ATTRIBUTES float[] w = target.GetAllWeights(); #endif #if Z_DRAW_WEIGHTS Mesh m = target.mesh; Vector3[] v = m.vertices; GUIContent content = new GUIContent("", ""); Handles.BeginGUI(); for (int i = 0; i < v.Length; i++) { if (w[i] < .0001f) { continue; } content.text = w[i].ToString("F2"); GUI.Label(HandleUtility.WorldPointToSizedRect(target.transform.TransformPoint(v[i]), content, EditorStyles.label), content); } Handles.EndGUI(); #endif #if DRAW_PER_VERTEX_ATTRIBUTES Mesh m = target.editableObject.editMesh; Color32[] colors = m.colors; Vector4[] tangents = m.tangents; List <Vector4> uv0 = m.uv0; List <Vector4> uv1 = m.uv1; List <Vector4> uv2 = m.uv2; List <Vector4> uv3 = m.uv3; int vertexCount = m.vertexCount; Vector3[] verts = m.vertices; GUIContent gc = new GUIContent(""); List <List <int> > common = MeshUtility.GetCommonVertices(m); System.Text.StringBuilder sb = new System.Text.StringBuilder(); Handles.BeginGUI(); foreach (List <int> l in common) { if (w[l[0]] < .001) { continue; } Vector3 v = target.transform.TransformPoint(verts[l[0]]); if (colors != null) { sb.AppendLine("color: " + colors[l[0]].ToString("F2")); } if (tangents != null) { sb.AppendLine("tangent: " + tangents[l[0]].ToString("F2")); } if (uv0 != null && uv0.Count == vertexCount) { sb.AppendLine("uv0: " + uv0[l[0]].ToString("F2")); } if (uv1 != null && uv1.Count == vertexCount) { sb.AppendLine("uv1: " + uv1[l[0]].ToString("F2")); } if (uv2 != null && uv2.Count == vertexCount) { sb.AppendLine("uv2: " + uv2[l[0]].ToString("F2")); } if (uv3 != null && uv3.Count == vertexCount) { sb.AppendLine("uv3: " + uv3[l[0]].ToString("F2")); } gc.text = sb.ToString(); sb.Remove(0, sb.Length); // @todo .NET 4.0 GUI.Label(HandleUtility.WorldPointToSizedRect(v, gc, EditorStyles.label), gc); } Handles.EndGUI(); #endif #endif }
// Called whenever the brush is moved. Note that @target may have a null editableObject. internal override void OnBrushMove(BrushTarget target, BrushSettings settings) { base.OnBrushMove(target, settings); if (!Util.IsValid(target) || !m_LikelySupportsTextureBlending || meshAttributes.Length == 0) { return; } if (!m_EditableObjectsData.ContainsKey(target.editableObject)) { return; } var data = m_EditableObjectsData[target.editableObject]; if (!data.CacheMaterials.Contains(m_MainCacheMaterials[m_CurrentMeshACIndex])) { return; } bool invert = settings.isUserHoldingControl; float[] weights; if (m_PaintMode == PaintMode.Brush) { weights = target.GetAllWeights(); } else if (m_PaintMode == PaintMode.Flood) { weights = new float[data.VertexCount]; for (int i = 0; i < data.VertexCount; i++) { weights[i] = 1f; } } else { weights = new float[data.VertexCount]; int[] indices = target.editableObject.editMesh.GetTriangles(); int index = 0; float weightTarget = 1f; foreach (PolyRaycastHit hit in target.raycastHits) { if (hit.triangle > -1) { index = hit.triangle * 3; m_FillModeEdges[0].x = indices[index + 0]; m_FillModeEdges[0].y = indices[index + 1]; m_FillModeEdges[1].x = indices[index + 1]; m_FillModeEdges[1].y = indices[index + 2]; m_FillModeEdges[2].x = indices[index + 2]; m_FillModeEdges[2].y = indices[index + 0]; for (int i = 0; i < 3; i++) { if (data.TriangleLookup.TryGetValue(m_FillModeEdges[i], out m_FillModeAdjacentTriangles)) { for (int n = 0; n < m_FillModeAdjacentTriangles.Count; n++) { index = m_FillModeAdjacentTriangles[n] * 3; weights[indices[index]] = weightTarget; weights[indices[index + 1]] = weightTarget; weights[indices[index + 2]] = weightTarget; } } } } } } int mask = meshAttributes[selectedAttributeIndex].mask; if (data.SplatCurrent == null) { RebuildCaches(data); } data.SplatCurrent.LerpWeights(data.SplatCache, invert ? data.SplatErase : data.SplatTarget, mask, weights); data.SplatCurrent.Apply(target.editableObject.editMesh); target.editableObject.ApplyMeshAttributes(); }
/// <summary> /// Calculates the per-vertex weight for each raycast hit and fills in brush target weights. /// </summary> /// <param name="target"></param> /// <param name="settings"></param> /// <param name="tool"></param> /// <param name="bMode"></param> internal static void CalculateWeightedVertices(BrushTarget target, BrushSettings settings, BrushTool tool = BrushTool.None, BrushMode bMode = null) { if (target == null || settings == null) { return; } if (target.editableObject == null) { return; } bool uniformScale = Math.VectorIsUniform(target.transform.lossyScale); float scale = uniformScale ? 1f / target.transform.lossyScale.x : 1f; PolyMesh mesh = target.editableObject.visualMesh; Transform transform = target.transform; int vertexCount = mesh.vertexCount; Vector3[] vertices = mesh.vertices; if (!uniformScale) { // As we only increase size only when it's needed, always make sure to // use the vertexCount variable in loop statements and not the buffer length. if (s_WorldBuffer.Length < vertexCount) { System.Array.Resize <Vector3>(ref s_WorldBuffer, vertexCount); } for (int i = 0; i < vertexCount; i++) { s_WorldBuffer[i] = transform.TransformPoint(vertices[i]); } vertices = s_WorldBuffer; } AnimationCurve curve = settings.falloffCurve; float radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f); Vector3 hitPosition = Vector3.zero; PolyRaycastHit hit; if (tool == BrushTool.Texture && mesh.subMeshCount > 1) { var mode = bMode as BrushModeTexture; int[] submeshIndices = mesh.subMeshes[mode.m_CurrentMeshACIndex].indexes; for (int n = 0; n < target.raycastHits.Count; n++) { hit = target.raycastHits[n]; hit.SetVertexCount(vertexCount); for (int i = 0; i < vertexCount; i++) { hit.weights[i] = 0f; } hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position); for (int i = 0; i < submeshIndices.Length; i++) { int currentIndex = submeshIndices[i]; float dist = (hitPosition - vertices[currentIndex]).magnitude; float delta = radius - dist; if (delta >= 0) { float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp(delta / falloff_mag, 0f, 1f)), 0f, 1f); hit.weights[currentIndex] = weight; } } } } else { int[][] common = PolyMeshUtility.GetCommonVertices(mesh); Vector3 buf = Vector3.zero; for (int n = 0; n < target.raycastHits.Count; n++) { hit = target.raycastHits[n]; hit.SetVertexCount(vertexCount); hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position); for (int i = 0; i < common.Length; i++) { int[] commonItem = common[i]; int commonArrayCount = commonItem.Length; Math.Subtract(vertices[commonItem[0]], hitPosition, ref buf); float sqrDist = buf.sqrMagnitude; if (sqrDist > radius * radius) { for (int j = 0; j < commonArrayCount; j++) { hit.weights[commonItem[j]] = 0f; } } else { float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp((radius - Mathf.Sqrt(sqrDist)) / falloff_mag, 0f, 1f)), 0f, 1f); for (int j = 0; j < commonArrayCount; j++) { hit.weights[commonItem[j]] = weight; } } } } } target.GetAllWeights(true); }
/// <summary> /// Calculates the per-vertex weight for each raycast hit and fills in brush target weights. /// </summary> /// <param name="target"></param> /// <param name="settings"></param> /// <param name="tool"></param> /// <param name="bMode"></param> internal static void CalculateWeightedVertices(BrushTarget target, BrushSettings settings, BrushTool tool = BrushTool.None, BrushMode bMode = null) { //null checks if (target == null || settings == null) { return; } if (target.editableObject == null) { return; } bool uniformScale = PolyMath.VectorIsUniform(target.transform.lossyScale); float scale = uniformScale ? 1f / target.transform.lossyScale.x : 1f; PolyMesh mesh = target.editableObject.visualMesh; if (tool == BrushTool.Texture && mesh.subMeshCount > 1) { var mode = bMode as BrushModeTexture; int[] submeshIndices = mesh.subMeshes[mode.currentMeshACIndex].indexes; //List<List<int>> common = PolyMeshUtility.GetCommonVertices(mesh); Transform transform = target.transform; int vertexCount = mesh.vertexCount; Vector3[] vertices = mesh.vertices; if (!uniformScale) { Vector3[] world = new Vector3[vertexCount]; for (int i = 0; i < vertexCount; i++) { world[i] = transform.TransformPoint(vertices[i]); } vertices = world; } AnimationCurve curve = settings.falloffCurve; float radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f); Vector3 hitPosition = Vector3.zero; PolyRaycastHit hit; for (int n = 0; n < target.raycastHits.Count; n++) { hit = target.raycastHits[n]; hit.SetVertexCount(vertexCount); for (int i = 0; i < vertexCount; i++) { hit.weights[i] = 0f; } hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position); for (int i = 0; i < submeshIndices.Length; i++) { int currentIndex = submeshIndices[i]; float dist = (hitPosition - vertices[currentIndex]).magnitude; float delta = radius - dist; if (delta >= 0) { float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp(delta / falloff_mag, 0f, 1f)), 0f, 1f); hit.weights[currentIndex] = weight; } } } } else { List <List <int> > common = PolyMeshUtility.GetCommonVertices(mesh); Transform transform = target.transform; int vertexCount = mesh.vertexCount; Vector3[] vertices = mesh.vertices; if (!uniformScale) { Vector3[] world = new Vector3[vertexCount]; for (int i = 0; i < vertexCount; i++) { world[i] = transform.TransformPoint(vertices[i]); } vertices = world; } AnimationCurve curve = settings.falloffCurve; float radius = settings.radius * scale, falloff_mag = Mathf.Max((radius - radius * settings.falloff), 0.00001f); Vector3 hitPosition = Vector3.zero; PolyRaycastHit hit; for (int n = 0; n < target.raycastHits.Count; n++) { hit = target.raycastHits[n]; hit.SetVertexCount(vertexCount); hitPosition = uniformScale ? hit.position : transform.TransformPoint(hit.position); for (int i = 0; i < common.Count; i++) { int commonArrayCount = common[i].Count; float sqrDist = (hitPosition - vertices[common[i][0]]).sqrMagnitude; if (sqrDist > radius * radius) { for (int j = 0; j < commonArrayCount; j++) { hit.weights[common[i][j]] = 0f; } } else { float weight = Mathf.Clamp(curve.Evaluate(1f - Mathf.Clamp((radius - Mathf.Sqrt(sqrDist)) / falloff_mag, 0f, 1f)), 0f, 1f); for (int j = 0; j < commonArrayCount; j++) { hit.weights[common[i][j]] = weight; } } } } } target.GetAllWeights(true); }