/**
* Copyright 2013 The Loon Authors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
* use this file except in compliance with the License. You may obtain a copy of
* the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations under
* the License.
*/
package loon.physics;
import loon.core.geom.Vector2f;
public class PSpringJoint extends PJoint {
private Vector2f anchor1;
private Vector2f anchor2;
private PBody b1;
private PBody b2;
private float damp;
private float dist;
private float force;
private Vector2f localAnchor1;
private Vector2f localAnchor2;
private float mass;
private Vector2f normal;
private Vector2f relAnchor1;
private Vector2f relAnchor2;
private float str;
public PSpringJoint(PBody b1, PBody b2, float rel1x, float rel1y,
float rel2x, float rel2y, float distance, float strength,
float damping) {
this.b1 = b1;
this.b2 = b2;
str = strength;
damp = damping;
localAnchor1 = new Vector2f(rel1x, rel1y);
localAnchor2 = new Vector2f(rel2x, rel2y);
b1.mAng.transpose().mulEqual(localAnchor1);
b2.mAng.transpose().mulEqual(localAnchor2);
dist = distance;
anchor1 = b1.mAng.mul(localAnchor1).add(b1.pos);
anchor2 = b2.mAng.mul(localAnchor2).add(b2.pos);
normal = anchor1.sub(anchor2);
normal.normalize();
type = PJointType.SPRING_JOINT;
}
public Vector2f getAnchorPoint1() {
return anchor1.clone();
}
public Vector2f getAnchorPoint2() {
return anchor2.clone();
}
public PBody getBody1() {
return b1;
}
public PBody getBody2() {
return b2;
}
public float getDamping() {
return damp;
}
public float getDistance() {
return dist;
}
public Vector2f getRelativeAnchorPoint1() {
return relAnchor1.clone();
}
public Vector2f getRelativeAnchorPoint2() {
return relAnchor2.clone();
}
public float getStrength() {
return str;
}
void preSolve(float dt) {
relAnchor1 = b1.mAng.mul(localAnchor1);
relAnchor2 = b2.mAng.mul(localAnchor2);
anchor1.set(relAnchor1.x + b1.pos.x, relAnchor1.y + b1.pos.y);
anchor2.set(relAnchor2.x + b2.pos.x, relAnchor2.y + b2.pos.y);
normal = anchor2.sub(anchor1);
float over = dist - normal.length();
normal.normalize();
mass = PTransformer.calcEffectiveMass(b1, b2, relAnchor1, relAnchor2,
normal);
float k = mass * 1000F * str;
force = -over * k;
force += PTransformer.calcRelativeVelocity(b1, b2, relAnchor1,
relAnchor2).dot(normal)
* damp * -(float) Math.sqrt(k * mass) * 2.0F;
force *= dt;
b1.applyImpulse(normal.x * force, normal.y * force, anchor1.x,
anchor1.y);
b2.applyImpulse(normal.x * -force, normal.y * -force, anchor2.x,
anchor2.y);
}
public void setDamping(float damping) {
damp = damping;
}
public void setDistance(float distance) {
dist = distance;
}
public void setRelativeAnchorPoint1(float relx, float rely) {
localAnchor1.set(relx, rely);
b1.mAng.transpose().mulEqual(localAnchor1);
}
public void setRelativeAnchorPoint2(float relx, float rely) {
localAnchor2.set(relx, rely);
b2.mAng.transpose().mulEqual(localAnchor2);
}
public void setStrength(float strength) {
str = strength;
}
void solvePosition() {
}
void solveVelocity(float f) {
}
void update() {
relAnchor1 = b1.mAng.mul(localAnchor1);
relAnchor2 = b2.mAng.mul(localAnchor2);
anchor1.set(relAnchor1.x + b1.pos.x, relAnchor1.y + b1.pos.y);
anchor2.set(relAnchor2.x + b2.pos.x, relAnchor2.y + b2.pos.y);
if (b1.rem || b2.rem || b1.fix && b2.fix){
rem = true;
}
}
}