internal void Init(List <Tuple <PotentialBase, RigidQuadrupletType> > pot_rigids_pairs) { enabled = true; m_PotentialRigidbodiesPairs = pot_rigids_pairs; // setting ignore collision foreach (Tuple <PotentialBase, RigidQuadrupletType> pot_rigids_pair in m_PotentialRigidbodiesPairs) { RigidQuadrupletType rigid_quadruplet = pot_rigids_pair.Item2; Collider collider_i = rigid_quadruplet.Item1.GetComponent <Collider>(); Collider collider_l = rigid_quadruplet.Item4.GetComponent <Collider>(); Physics.IgnoreCollision(collider_i, collider_l); } }
private void FixedUpdate() { foreach (Tuple <PotentialBase, RigidQuadrupletType> pot_rigids_pair in m_PotentialRigidbodiesPairs) { PotentialBase potential = pot_rigids_pair.Item1; RigidQuadrupletType rigid_quadruplet = pot_rigids_pair.Item2; Rigidbody rigid_i = rigid_quadruplet.Item1; Rigidbody rigid_j = rigid_quadruplet.Item2; Rigidbody rigid_k = rigid_quadruplet.Item3; Rigidbody rigid_l = rigid_quadruplet.Item4; Vector3 r_ji = rigid_i.position - rigid_j.position; Vector3 r_jk = rigid_k.position - rigid_j.position; Vector3 r_kj = -r_jk; Vector3 r_lk = rigid_k.position - rigid_l.position; Vector3 m = Vector3.Cross(r_ji, r_jk); Vector3 n = Vector3.Cross(r_jk, r_lk); float m_len = m.magnitude; float n_len = n.magnitude; float r_jk_len = r_jk.magnitude; float r_jk_rlensq = 1.0f / (r_jk_len * r_jk_len); float cos_phi = Mathf.Clamp(Vector3.Dot(m, n) / (m_len * n_len), -1.0f, 1.0f); float phi = Mathf.Sign(Vector3.Dot(r_ji, n)) * Mathf.Acos(cos_phi); float coef = potential.Derivative(phi); Vector3 Fi = coef * r_jk_len / (m_len * m_len) * m; Vector3 Fl = -coef * r_jk_len / (n_len * n_len) * n; float coef_ijk = Vector3.Dot(r_ji, r_jk) * r_jk_rlensq; float coef_jkl = Vector3.Dot(r_lk, r_jk) * r_jk_rlensq; rigid_i.AddForce(Fi); rigid_j.AddForce((coef_ijk - 1.0f) * Fi - coef_jkl * Fl); rigid_k.AddForce((coef_jkl - 1.0f) * Fl - coef_ijk * Fi); rigid_l.AddForce(Fl); } }
// This method generate InteractionManager for local of SceneBuilder by side effect. internal void GenerateLocalInteractionManagers( GameObject scene_builder, List <GameObject> base_particles, float timescale) { List <TomlTable> local_ffs = ForceFieldTable.Get <List <TomlTable> >("local"); foreach (TomlTable local_ff in local_ffs) { string interaction = local_ff.Get <string>("interaction"); string potential_str = local_ff.Get <string>("potential"); if (interaction == "BondLength") { var parameters = local_ff.Get <List <TomlTable> >("parameters"); var pot_rigids_pairs = new List <Tuple <PotentialBase, RigidPairType> >(); if (potential_str == "Harmonic") { foreach (TomlTable parameter in parameters) { var v0 = parameter.Get <float>("v0"); var k = parameter.Get <float>("k"); var potential = new HarmonicPotential(v0, k, timescale); List <int> indices = parameter.Get <List <int> >("indices"); Assert.AreEqual(indices.Count, 2, "The length of indices must be 2."); var rigid1 = base_particles[indices[0]].GetComponent <Rigidbody>(); var rigid2 = base_particles[indices[1]].GetComponent <Rigidbody>(); var rigid_pair = new RigidPairType(rigid1, rigid2); pot_rigids_pairs.Add(new Tuple <PotentialBase, RigidPairType>(potential, rigid_pair)); } } else if (potential_str == "GoContact") { foreach (TomlTable parameter in parameters) { var v0 = parameter.Get <float>("v0"); var k = parameter.Get <float>("k"); var potential = new GoContactPotential(v0, k, timescale); List <int> indices = parameter.Get <List <int> >("indices"); Assert.AreEqual(indices.Count, 2, "The length of indices must be 2."); var rigid1 = base_particles[indices[0]].GetComponent <Rigidbody>(); var rigid2 = base_particles[indices[1]].GetComponent <Rigidbody>(); var rigid_pair = new RigidPairType(rigid1, rigid2); pot_rigids_pairs.Add(new Tuple <PotentialBase, RigidPairType>(potential, rigid_pair)); } } BondLengthInteractionManager bli_manager = scene_builder.AddComponent <BondLengthInteractionManager>() as BondLengthInteractionManager; bli_manager.Init(pot_rigids_pairs); string potential_name = bli_manager.PotentialName(); Debug.Log($"BondLengthInteraction with {potential_name} initialization finished."); } else if (interaction == "BondAngle") { var parameters = local_ff.Get <List <TomlTable> >("parameters"); var pot_rigids_pairs = new List <Tuple <PotentialBase, RigidTripletType> >(); if (potential_str == "Harmonic") { foreach (TomlTable parameter in parameters) { var v0 = parameter.Get <float>("v0"); var k = parameter.Get <float>("k"); var potential = new HarmonicPotential(v0, k, timescale); List <int> indices = parameter.Get <List <int> >("indices"); Assert.AreEqual(indices.Count, 3, "The length of indices must be 3."); var rigid_i = base_particles[indices[0]].GetComponent <Rigidbody>(); var rigid_j = base_particles[indices[1]].GetComponent <Rigidbody>(); var rigid_k = base_particles[indices[2]].GetComponent <Rigidbody>(); var rigid_triplets = new RigidTripletType(rigid_i, rigid_j, rigid_k); pot_rigids_pairs.Add(new Tuple <PotentialBase, RigidTripletType>(potential, rigid_triplets)); } } BondAngleInteractionManager bai_manager = scene_builder.AddComponent <BondAngleInteractionManager>() as BondAngleInteractionManager; bai_manager.Init(pot_rigids_pairs); string potential_name = bai_manager.PotentialName(); Debug.Log($"BondAngleInteraciton with {potential_name} initialization finished."); } else if (interaction == "DihedralAngle") { var parameters = local_ff.Get <List <TomlTable> >("parameters"); var pot_rigids_pairs = new List <Tuple <PotentialBase, RigidQuadrupletType> >(); if (potential_str == "ClementiDihedral") { foreach (TomlTable parameter in parameters) { var v0 = parameter.Get <float>("v0"); var k1 = parameter.Get <float>("k1"); var k3 = parameter.Get <float>("k3"); var potential = new ClementiDihedralPotential(v0, k1, k3, timescale); List <int> indices = parameter.Get <List <int> >("indices"); Assert.AreEqual(indices.Count, 4, "The length of indices must be 4."); var rigid_i = base_particles[indices[0]].GetComponent <Rigidbody>(); var rigid_j = base_particles[indices[1]].GetComponent <Rigidbody>(); var rigid_k = base_particles[indices[2]].GetComponent <Rigidbody>(); var rigid_l = base_particles[indices[3]].GetComponent <Rigidbody>(); var rigid_quadruplet = new RigidQuadrupletType(rigid_i, rigid_j, rigid_k, rigid_l); pot_rigids_pairs.Add( new Tuple <PotentialBase, RigidQuadrupletType>(potential, rigid_quadruplet)); } } DihedralAngleInteractionManager dai_manager = scene_builder.AddComponent <DihedralAngleInteractionManager>() as DihedralAngleInteractionManager; dai_manager.Init(pot_rigids_pairs); string potential_name = dai_manager.PotentialName(); Debug.Log($"DihedralAngleInteraction with {potential_name} initialization finished"); } else { Debug.LogWarning($@" Unknown combination of local interaction {interaction} and forcefields {potential_str} is specified. This table will be ignored. Available combination is - Interaction: BondLength, Potential: Harmonic - Interaction: BondLength, Potential: GoContact - Interaction: BondAngle, Potential: Harmonic - Interaction: DihedralAngle, Potential: ClementiDihedral"); } } }