//------- public Verlet(Plant.InitPoint[] init_data, Transform parent) { _parent = parent; // init from init data //-------------------------------------------------- _points = new Point[init_data.Length]; for (int i = 0; i < init_data.Length; ++i) { if (init_data[i].parent < 0) { init_data[i].is_fixed = true; } // transform init_data[i].pos *= Plant.SCALE; _points[i] = new Point(); _points[i].curr_mat.SetTRS(init_data[i].pos, Quaternion.identity, Vector3.one); _points[i].prev_mat = _points[i].curr_mat; _points[i].is_fixed = init_data[i].is_fixed; } BetterList <ConstraintPosition> new_const_pos = new BetterList <ConstraintPosition>(); for (int i = 0; i < init_data.Length; ++i) { if (init_data[i].parent >= 0) { ConstraintPosition cp = new ConstraintPosition(); cp.index_0 = i; cp.index_1 = init_data[i].parent; new_const_pos.Add(cp); } } _pos_constraints = new ConstraintPosition[0]; if (new_const_pos.size > 0) { _pos_constraints = new_const_pos.ToArray(); } BetterList <ConstraintSoft> new_const_soft = new BetterList <ConstraintSoft>(); for (int i = 0; i < init_data.Length; ++i) { if (init_data[i].soft_clamp) { ConstraintSoft cs = new ConstraintSoft(); cs.index_0 = i; cs.index_parent = init_data[i].parent; cs.min_dist = init_data[i].soft_min * Plant.SCALE; cs.max_dist = init_data[i].soft_max * Plant.SCALE; new_const_soft.Add(cs); } } _soft_constraints = new ConstraintSoft[0]; if (new_const_soft.size > 0) { _soft_constraints = new_const_soft.ToArray(); } //-------------------------------------------------- for (int i = 0; i < _pos_constraints.Length; ++i) { Vector3 p0 = _points[_pos_constraints[i].index_0].curr_mat.GetColumn(3); Vector3 p1 = _points[_pos_constraints[i].index_1].curr_mat.GetColumn(3); float d = Vector3.Distance(p0, p1); _pos_constraints[i].rest_length = d; } for (int i = 0; i < _soft_constraints.Length; ++i) { Vector3 p0 = _points[_soft_constraints[i].index_0].curr_mat.GetColumn(3); Vector3 p1 = _points[_soft_constraints[i].index_parent].curr_mat.GetColumn(3); Vector3 offset = p0 - p1; _soft_constraints[i].target_offset = offset; } }
/// <summary> /// Resets the field storing constraint information and the logical position to OutsideConstraint. /// </summary> public void ResetConstraintData() { CurrentConstraintStart = -1; CurrentParameters.Clear(); CurrentConstraintName = string.Empty; IsMasked = false; LogicalPosition = ConstraintPosition.OutsideConstraint; }
void SatisfyConstraints() { const int numIterations = 5; for (int i = 0; i < numIterations; i++) { // Constraint (avoids) if (PlantManager.Exists) { for (int a = 0; a < PlantManager.Instance._avoids.Count; ++a) { PlantAvoid pa = PlantManager.Instance._avoids[a]; // points for (int v = 0; v < _points.Length; v++) { Vector3 pos = _parent.position + GetPointPos(v); Vector3 dist = pos - pa.transform.position; float r = pa.radius + Plant.SCALE * 0.3f; if (dist.magnitude < r) { pos = (pa.transform.position + (dist.normalized * r)) - _parent.position; _points[v].curr_mat.SetColumn(3, new Vector4(pos.x, pos.y, pos.z, 1f)); } } // segments for (int v = 0; v < _pos_constraints.Length; v++) { int i0 = _pos_constraints[v].index_0; int i1 = _pos_constraints[v].index_1; Vector3 p0 = _parent.position + GetPointPos(i0); Vector3 p1 = _parent.position + GetPointPos(i1); Vector3 closest = UtilMath.ClosestPointOnLineSegment3D(p0, p1, pa.transform.position); Vector3 dist = closest - pa.transform.position; float r = pa.radius + Plant.SCALE * 0.1f; if (dist.magnitude < r) { dist = (dist.normalized * r) - dist; // set point p0 = GetPointPos(i0) + dist; p1 = GetPointPos(i1) + dist; SetPointPos(i0, p0); SetPointPos(i1, p1); // force //float multi = 1f - (dist.magnitude / pa.radius); //Vector3 push = (dist.normalized * pa.radius) * multi; //_angle_constraint_force[i0] += push; //_angle_constraint_force[i1] += push; } } } } // Constraint (floor) for (int v = 0; v < _points.Length; v++) { Vector3 cp = _points[v].curr_mat.GetColumn(3); if (cp.y + _parent.position.y < 0f) { _points[v].curr_mat.SetColumn(3, new Vector4(cp.x, -_parent.position.y, cp.z, 1f)); } } for (int k = 0; k < _pos_constraints.Length; k++) { ConstraintPosition c = _pos_constraints[k]; // positions constraint Vector3 p0 = _points[c.index_0].curr_mat.GetColumn(3); Vector3 p1 = _points[c.index_1].curr_mat.GetColumn(3); Vector3 delta = p1 - p0; float len = delta.magnitude; float diff = (len - c.rest_length) / len; //p0 += delta * 0.5f * diff; //p1 -= delta * 0.5f * diff; // mass change // push child more than parent p0 += delta * 0.8f * diff; p1 -= delta * 0.2f * diff; _points[c.index_0].curr_mat.SetColumn(3, new Vector4(p0.x, p0.y, p0.z, 1f)); _points[c.index_1].curr_mat.SetColumn(3, new Vector4(p1.x, p1.y, p1.z, 1f)); if (_points[c.index_0].is_fixed) { _points[c.index_0].curr_mat = _points[c.index_0].prev_mat; } if (_points[c.index_1].is_fixed) { _points[c.index_1].curr_mat = _points[c.index_1].prev_mat; } } } }
/// <summary> /// Initializes a new instance of the ParserContext class with the specified constraint string. /// </summary> /// <param name="constraintString">The constraint string to parse.</param> /// <param name="dataType">The data type of the parameter.</param> internal ParserContext(string constraintString, ParameterDataType dataType) { ConstraintString = constraintString; DataType = dataType; Constraints = new List<Constraint>(); LogicalPosition = ConstraintPosition.OutsideConstraint; CurrentConstraintStart = -1; StringPosition = -1; CurrentParameters = new List<string>(); CurrentConstraintName = string.Empty; IsMasked = false; CurrentParameter = new StringBuilder(); CurrentCharacter = char.MinValue; StringLength = constraintString.Length; }