public void ExecuteSoft(SoftSelection softSel, Quaternion modelRotOff) { softSel.Prepare(); Vector3 modelPivotPos = m_Pivot.ModelPos; Mesh m = m_Mesh.mesh; //Vector3[] cachedVertsArray = softSel.CachedVertPos; //Vector3[] vertsArray = (Vector3[])cachedVertsArray.Clone(); Vector3[] vertsArray = m.vertices; VLst softSelIdxLst = softSel.GetEffectVerts(); for (int i = 0; i < softSelIdxLst.Count; ++i) { int vidx = softSelIdxLst[i]; float percentage = softSel.GetPercentage(vidx); Vector3 offVec = vertsArray[vidx] - modelPivotPos; Quaternion percModelRotoff = Quaternion.Slerp(Quaternion.identity, modelRotOff, percentage); // interpolated rotation Vector3 transOff = percModelRotoff * offVec; vertsArray[vidx] = transOff + modelPivotPos; } UndoMesh.SetVertices(m, vertsArray); }
private Vector3[] m_CachedVertPos; //used in dragging handle, cache the starting position of verts #endregion "data" #region "public method" // public method public void Init(EditableMesh m, MeshSelection sel, Pivotor p) { m_Mesh = m; m_Selection = sel; m_Pivot = p; Dbg.Assert(m_Pivot != null, "SoftSelection.Init: pivotor is null"); m_Range = 1f; m_Cont = new _Data[m.mesh.vertexCount]; for (int i = 0; i < m_Cont.Length; ++i) { m_Cont[i] = new _Data(); } m_EffectVertIdxLst = new VLst(); m_Mode = Mode.Off; m_PrepareMode = PrepareMode.Always; // atten curve var res = (SoftSelectionRes)AssetDatabase.LoadAssetAtPath(SOFTSEL_ATTEN_CURVE_PATH, typeof(SoftSelectionRes)); if (res == null) { res = ScriptableObject.CreateInstance <SoftSelectionRes>(); AssetDatabase.CreateAsset(res, SOFTSEL_ATTEN_CURVE_PATH); res = (SoftSelectionRes)AssetDatabase.LoadAssetAtPath(SOFTSEL_ATTEN_CURVE_PATH, typeof(SoftSelectionRes)); Dbg.Assert(res != null, "SoftSelection.Init: failed to create curve asset for SoftSelection"); } m_Atten = res.attenCurve; MeshManipulator.evtHandleDraggingStateChanged += this._OnHandleDraggingStateChanged; }
public void Prepare() { if (m_PrepareMode == PrepareMode.Stop) { return; } else if (m_PrepareMode == PrepareMode.OnlyOnce) { m_PrepareMode = PrepareMode.Stop; } m_CachedVertPos = m_Mesh.mesh.vertices; //cache as starting pos, useful when dynamically change range VLst selectedVerts = m_Selection.GetVertices(); //1. set the initial effect percentage Reset(); //1.1 set the seeds for (int i = 0; i < selectedVerts.Count; ++i) { int vidx = selectedVerts[i]; m_Cont[vidx].AsSeed(); } //2. calculate nearest distance for every vert, _CalcDist(selectedVerts); //3. calc the percentage _CalcPercentage(); }
public void ExecuteWorld(VLst vertIdxLst, Vector3 worldFrom, Vector3 worldTo) { Transform meshTr = m_Mesh.transform; Vector3 localStartPos = meshTr.InverseTransformPoint(worldFrom); Vector3 localNewPos = meshTr.InverseTransformPoint(worldTo); Vector3 localOff = localNewPos - localStartPos; Execute(vertIdxLst, localOff); }
public void ExecuteWorld(VLst vertIdxLst, Quaternion worldFrom, Quaternion worldTo) { Quaternion localFrom; Quaternion localTo; _CalcLocalRotations(ref worldFrom, ref worldTo, out localFrom, out localTo); Quaternion localOff = localTo * Quaternion.Inverse(localFrom); Execute(vertIdxLst, localOff); }
/// <summary> /// move specified verts by offset /// </summary> /// <param name="vertIdxLst">the list containing index to all affected verts</param> /// <param name="modelSpaceOffset">the offset in model's local space</param> public void Execute(VLst vertIdxLst, Vector3 modelSpaceOffset) { Mesh m = m_Mesh.mesh; Vector3[] vertsArray = m.vertices; for (int i = 0; i < vertIdxLst.Count; ++i) { int vidx = vertIdxLst[i]; vertsArray[vidx] += modelSpaceOffset; } UndoMesh.SetVertices(m, vertsArray); }
public void ExecuteWorldSoft(SoftSelection softSel, Vector3 worldFrom, Vector3 worldTo, Vector3 worldPivotPos) { //Dbg.Log("ScaleVerts.ExecuteWorldSoft: from: {0}, to: {1}, revert: {2}", worldFrom.ToString("F3"), worldTo.ToString("F3"), bRevert); Vector3 worldScaleDelta = V3Ext.DivideComp(worldTo, worldFrom); //when I say "world", it's not bound to be global orientation Matrix4x4 mat, matI; _GetMatrices(out mat, out matI); //Vector3 localPivotPos = m_Pivot.ModelPos; //this will accumulate errors Vector3 localPivotPos = m_Tr.InverseTransformPoint(worldPivotPos); softSel.Prepare(); // apply change to verts Mesh m = m_Mesh.mesh; Vector3[] cachedVertsArray = softSel.CachedVertPos; Vector3[] vertsArray = (Vector3[])cachedVertsArray.Clone(); VLst softSelIdxLst = softSel.GetEffectVerts(); //Vector3[] curVertArray = MeshCache.Instance.vertices; //Dbg.Log("modelPivotPos = {0}, {1}", localPivotPos.ToString("F3"), Misc.ListToString(softSelIdxLst, idx => { return curVertArray[idx].ToString("F3"); } )); // apply scaling for (int i = 0; i < softSelIdxLst.Count; ++i) { int vidx = softSelIdxLst[i]; Vector3 off = vertsArray[vidx] - localPivotPos; // calc scale mat Vector3 percScale; float percentage = softSel.GetPercentage(vidx); percScale = Vector3.Lerp(Vector3.one, worldScaleDelta, percentage); Matrix4x4 matScalePerc = Matrix4x4.Scale(percScale); Matrix4x4 combinedMat = (mat * matScalePerc * matI); Vector3 newOff = combinedMat.MultiplyPoint(off); vertsArray[vidx] = localPivotPos + newOff; //Dbg.Log("newOff={0}, off={1}, verts={2}, mat=\n{3}", newOff.ToString("F6"), off.ToString("F6"), vertsArray[vidx].ToString("F6"), combinedMat.ToString("F8")); } // apply to mesh UndoMesh.SetVertices(m, vertsArray); //Dbg.Log("======================="); }
/// <summary> /// rotate selected verts by rotation /// </summary> /// <param name="vertIdxLst">the list containing index to all affected verts</param> /// <param name="modelPivotPos">the position of pivot in local space</param> /// <param name="modelRotOff">the rotation in model's local space</param> public void Execute(VLst vertIdxLst, Quaternion modelRotOff) { Vector3 modelPivotPos = m_Pivot.ModelPos; Mesh m = m_Mesh.mesh; Vector3[] vertsArray = m.vertices; for (int i = 0; i < vertIdxLst.Count; ++i) { int vidx = vertIdxLst[i]; Vector3 offVec = vertsArray[vidx] - modelPivotPos; Vector3 transOff = modelRotOff * offVec; vertsArray[vidx] = transOff + modelPivotPos; } UndoMesh.SetVertices(m, vertsArray); }
/// <summary> /// calculate for each vert, the minimum distance to a seed vert /// </summary> private void _CalcDist(VLst selectedVerts) { Transform meshTr = m_Mesh.transform; Mesh m = m_Mesh.mesh; Vector3[] oriVerts = m.vertices; //original verts pos // generate the transformed verts Vector3[] verts = new Vector3[oriVerts.Length]; //the verts transformed by matrix for (int i = 0; i < m.vertexCount; ++i) { verts[i] = meshTr.TransformPoint(oriVerts[i]); } // calc distances int found = 0; for (int i = 0; i < m_Cont.Length; ++i) { _Data lhs = m_Cont[i]; if (lhs.percentage == 1f) { continue; } Vector3 lhsPos = verts[i]; for (int j = 0; j < selectedVerts.Count; ++j) { int seedVertIdx = selectedVerts[j]; Vector3 seedPos = verts[seedVertIdx]; float d = Vector3.Distance(seedPos, lhsPos); lhs.dist = Mathf.Min(lhs.dist, d); } if (lhs.dist < m_Range) { ++found; } } //Dbg.Log("SoftSelection._CalcDist: found {0}", found); }
private void _UpdatePivotRot() { VLst vlst = m_Selection.GetVertices(); // rotation switch (m_Orient) { case Orientation.Global: { m_WorldRot = Quaternion.identity; } break; case Orientation.Normal: { List <Vector3> nLst = MeshUtil.GetVertNormal(m_EditMesh.mesh, vlst); if (nLst == null) { //no normal m_WorldRot = m_MeshTr.rotation; } else { //has normal Vector3 total = nLst.Aggregate((sum, cur) => { return(sum + cur); }); Vector3 newModelNormal = total.normalized; newModelNormal = newModelNormal == Vector3.zero ? (Vector3.forward) : (newModelNormal); Vector3 newWorldNormal = m_MeshTr.TransformDirection(newModelNormal); m_WorldRot = Quaternion.LookRotation(newWorldNormal); } } break; case Orientation.Local: { m_WorldRot = m_EditMesh.transform.rotation; } break; default: Dbg.LogErr("Pivotor._UpdatePivot: unexpected orientation: {0}", m_Orient); break; } }
/// <summary> /// move specified verts by offset /// the base shape is cached in softSel /// </summary> public void ExecuteSoft(SoftSelection softSel, Vector3 modelSpaceOffset) { softSel.Prepare(); // will do calculation IF NEEDED Mesh m = m_Mesh.mesh; Vector3[] cachedVertsArray = softSel.CachedVertPos; Vector3[] vertsArray = (Vector3[])cachedVertsArray.Clone(); VLst softSelIdxLst = softSel.GetEffectVerts(); for (int i = 0; i < softSelIdxLst.Count; ++i) { int vidx = softSelIdxLst[i]; float percentage = softSel.GetPercentage(vidx); vertsArray[vidx] += modelSpaceOffset * percentage; } UndoMesh.SetVertices(m, vertsArray); }
private void _UpdatePivotPos_Midian() { // position VLst vlst = m_Selection.GetVertices(); { List <Vector3> posLst = MeshUtil.GetVertPos(m_EditMesh.mesh, vlst); Vector3 total = Vector3.zero; Vector3 modelPivotPos = Vector3.zero; if (posLst.Count > 0) { total = posLst.Aggregate((sum, cur) => { return(sum + cur); }); modelPivotPos = total / posLst.Count; } else { modelPivotPos = Vector3.zero; } m_WorldPos = m_MeshTr.TransformPoint(modelPivotPos); //Dbg.Log("m_WorldPos = {0}", m_WorldPos); } }
/// <summary> /// scale specified verts based on pivot (parameter in world space) /// a affine transformation(?) /// </summary> /// <param name="vertIdxLst">the list containing index to all affected verts</param> /// <param name="worldScaleDelta">the scale info in world space</param> public void ExecuteWorld(VLst vertIdxLst, Vector3 worldFrom, Vector3 worldTo, Vector3 worldPivotPos) { Vector3 worldScaleDelta = V3Ext.DivideComp(worldTo, worldFrom); //when I say "world", it's not bound to be global orientation Matrix4x4 combinedMat = _CalcCombinedMat(ref worldScaleDelta); //Vector3 localPivotPos = m_Pivot.ModelPos; //this will accumulate errors Vector3 localPivotPos = m_Tr.InverseTransformPoint(worldPivotPos); // apply change to verts Mesh m = m_Mesh.mesh; Vector3[] vertsArray = m.vertices; for (int i = 0; i < vertIdxLst.Count; ++i) { int vidx = vertIdxLst[i]; Vector3 off = vertsArray[vidx] - localPivotPos; Vector3 newOff = combinedMat.MultiplyPoint(off); vertsArray[vidx] = localPivotPos + newOff; //Dbg.Log("newOff={0}, off={1}, verts={2}, mat=\n{3}", newOff.ToString("F6"), off.ToString("F6"), vertsArray[vidx].ToString("F6"), combinedMat.ToString("F8")); } // apply to mesh UndoMesh.SetVertices(m, vertsArray); }