JavaFX弹簧物理学
我试图通过创建可拖动的圆圈,用JavaFX创建一个类似spring的行为。当我拖动一个圆圈时,其他圆圈应跟随并模拟弹性 我创建了一个样板模板,其中包含3个圆圈,它们可以通过鼠标拖动。动画正在运行,当然,所有动画都显示为静止,因为当前速度为0。我只需要知道如何计算附着粒子的角度和速度 如果有人能帮助我,那就太好了 代码如下:JavaFX弹簧物理学,javafx,physics,Javafx,Physics,我试图通过创建可拖动的圆圈,用JavaFX创建一个类似spring的行为。当我拖动一个圆圈时,其他圆圈应跟随并模拟弹性 我创建了一个样板模板,其中包含3个圆圈,它们可以通过鼠标拖动。动画正在运行,当然,所有动画都显示为静止,因为当前速度为0。我只需要知道如何计算附着粒子的角度和速度 如果有人能帮助我,那就太好了 代码如下: import java.util.ArrayList; import java.util.List; import javafx.animation.AnimationTi
import java.util.ArrayList;
import java.util.List;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.StrokeType;
import javafx.stage.Stage;
public class PhysicsTest extends Application {
List<Particle> particles = new ArrayList<>();
List<Spring> springs = new ArrayList<>();
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) {
Group root = new Group();
// create particles
Particle pRed = new Particle(Color.RED, 100, 100);
Particle pBlue = new Particle(Color.BLUE, 400, 200);
Particle pGreen = new Particle(Color.GREEN, 100, 300);
// red -> blue
Line lineRedBlue = new Line(100, 100, 500, 500);
lineRedBlue.setStroke(Color.BLACK);
lineRedBlue.setStrokeWidth(5);
// green -> blue
Line lineGreenBlue = new Line(100, 100, 500, 500);
lineGreenBlue.setStroke(Color.BLACK);
lineGreenBlue.setStrokeWidth(5);
// line binding
// line 1 -> 2
lineRedBlue.startXProperty().bind(pRed.centerXProperty());
lineRedBlue.startYProperty().bind(pRed.centerYProperty());
lineRedBlue.endXProperty().bind(pBlue.centerXProperty());
lineRedBlue.endYProperty().bind(pBlue.centerYProperty());
// line 3 -> 2
lineGreenBlue.startXProperty().bind(pGreen.centerXProperty());
lineGreenBlue.startYProperty().bind(pGreen.centerYProperty());
lineGreenBlue.endXProperty().bind(pBlue.centerXProperty());
lineGreenBlue.endYProperty().bind(pBlue.centerYProperty());
MouseGestures mg = new MouseGestures();
mg.makeDraggable(pRed);
mg.makeDraggable(pBlue);
mg.makeDraggable(pGreen);
root.getChildren().addAll(pRed, pBlue, pGreen, lineRedBlue, lineGreenBlue);
// add to list
particles.add( pRed);
particles.add( pBlue);
particles.add( pGreen);
// add springs
Spring s1 = new Spring( pRed, pBlue, 10, 0.5);
springs.add( s1);
Spring s2 = new Spring( pGreen, pBlue, 10, 0.5);
springs.add( s2);
primaryStage.setScene(new Scene(root, 1024, 768));
primaryStage.show();
// animate
startAnimation();
}
private void startAnimation() {
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
// move particles
for (Particle p : particles) {
if (!p.selected) {
p.move();
}
}
// apply springs
for (Spring s : springs) {
s.update();
}
// move particles to new location
for (Particle p : particles) {
p.updateLocation();
}
}
};
timer.start();
}
/**
* The spring constraint and calculation. Updates particle
*/
public class Spring {
Particle p1;
Particle p2;
double length; // length it tries to obtain
double strength; // how quickly it tries to reach that length
public Spring( Particle p1, Particle p2, double length, double strength) {
this.p1 = p1;
this.p2 = p2;
this.length = length;
this.strength = strength;
}
public void update() {
double dx = p1.getCenterX() - p2.getCenterX();
double dy = p1.getCenterY() - p2.getCenterY();
double dist = Math.hypot(dx, dy);
double theta = Math.atan2(dy, dx);
double force = (length - dist) * strength;
// System.out.println( dist + ", " + Math.toDegrees( theta) + ", " + force);
// what's supposed to happen here?
p1.angle = ... // <===
p1.speed = ... // <===
p2.angle = ... // <===
p2.speed = ... // <===
}
}
/**
* The particle itself
*/
public class Particle extends Circle {
double x;
double y;
double angle = 0.0;
double speed = 0.0;
double mass = 1;
boolean selected = false;
public Particle(Color color, double x, double y) {
super(x, y, 50);
this.x = x;
this.y = y;
setFill(color.deriveColor(1, 1, 1, 0.5));
setStroke(color);
setStrokeWidth(2);
setStrokeType(StrokeType.OUTSIDE);
}
public void move() {
x += Math.sin( angle) * speed;
y += Math.cos( angle) * speed;
}
public void updateLocation() {
setCenterX( x);
setCenterY( y);
}
}
/**
* Allow movement of objects via mouse.
*/
public class MouseGestures {
double orgSceneX, orgSceneY;
double orgTranslateX, orgTranslateY;
public void makeDraggable( Node node) {
node.setOnMousePressed(circleOnMousePressedEventHandler);
node.setOnMouseDragged(circleOnMouseDraggedEventHandler);
node.setOnMouseReleased(circleOnMouseReleasedEventHandler);
}
EventHandler<MouseEvent> circleOnMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
orgSceneX = t.getSceneX();
orgSceneY = t.getSceneY();
Particle p = ((Particle) (t.getSource()));
p.selected = true;
orgTranslateX = p.getCenterX();
orgTranslateY = p.getCenterY();
}
};
EventHandler<MouseEvent> circleOnMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
Particle p = ((Particle) (t.getSource()));
p.selected = false;
};
};
EventHandler<MouseEvent> circleOnMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
double offsetX = t.getSceneX() - orgSceneX;
double offsetY = t.getSceneY() - orgSceneY;
double newTranslateX = orgTranslateX + offsetX;
double newTranslateY = orgTranslateY + offsetY;
Particle p = ((Particle) (t.getSource()));
p.x = newTranslateX;
p.y = newTranslateY;
}
};
}
}
import java.util.ArrayList;
导入java.util.List;
导入javafx.animation.AnimationTimer;
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.scene.Group;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.paint.Color;
导入javafx.scene.shape.Circle;
导入javafx.scene.shape.Line;
导入javafx.scene.shape.StrokeType;
导入javafx.stage.stage;
公共类PhysicTest扩展了应用程序{
列表粒子=新的ArrayList();
列表弹簧=新的ArrayList();
公共静态void main(字符串[]args){
发射(args);
}
@凌驾
公共无效开始(阶段primaryStage){
组根=新组();
//创建粒子
粒子pRed=新粒子(颜色:红色,100100);
粒子pBlue=新粒子(颜色:蓝色,400200);
粒子绿色=新粒子(颜色为绿色,100300);
//红色->蓝色
lineRedBlue=新行(100100500500);
lineRedBlue.setStroke(颜色:黑色);
lineRedBlue.设置行程宽度(5);
//绿色->蓝色
lineGreenBlue=新线(100100500500);
线条绿蓝色。设定行程(颜色。黑色);
蓝绿色线条。设置行程宽度(5);
//线装订
//生产线1->2
lineRedBlue.startXProperty().bind(pRed.centerXProperty());
lineRedBlue.startYProperty().bind(pRed.centerYProperty());
lineRedBlue.endXProperty().bind(pBlue.centerXProperty());
lineRedBlue.endYProperty().bind(pBlue.centerYProperty());
//第3行->第2行
lineGreenBlue.startXProperty().bind(pGreen.centerXProperty());
lineGreenBlue.startYProperty().bind(pGreen.centerYProperty());
lineGreenBlue.endXProperty().bind(pBlue.centerXProperty());
lineGreenBlue.endYProperty().bind(pBlue.centerYProperty());
MouseGestures mg=新的MouseGestures();
mg.makeDraggable(pRed);
mg.makeDraggable(pBlue);
mg.makeDraggable(pGreen);
root.getChildren().addAll(pRed、pBlue、pGreen、lineRedBlue、lineGreenBlue);
//添加到列表中
粒子。添加(pRed);
添加颗粒(pBlue);
粒子。添加(绿色);
//添加弹簧
弹簧s1=新弹簧(pRed,pBlue,10,0.5);
弹簧。添加(s1);
弹簧s2=新弹簧(绿色,蓝色,10,0.5);
弹簧。添加(s2);
设置场景(新场景(根,1024768));
primaryStage.show();
//生动活泼
startAnimation();
}
私有void startAnimation(){
AnimationTimer=新的AnimationTimer(){
@凌驾
公共无效句柄(长){
//移动粒子
对于(粒子p:粒子){
如果(!p.selected){
p、 move();
}
}
//施加弹簧
用于(弹簧s:弹簧){
s、 更新();
}
//将粒子移动到新位置
对于(粒子p:粒子){
p、 updateLocation();
}
}
};
timer.start();
}
/**
*弹簧约束和计算。更新粒子
*/
公共课春季{
粒子p1;
颗粒p2;
double length;//它尝试获取的长度
双倍力量;//它达到这个长度的速度有多快
公共弹簧(粒子p1、粒子p2、双倍长度、双倍强度){
这是1.p1=p1;
这是p2=p2;
这个长度=长度;
力量=力量;
}
公共无效更新(){
双dx=p1.getCenterX()-p2.getCenterX();
双dy=p1.getCenterY()-p2.getCenterY();
双距离=数学形波(dx,dy);
双θ=Math.atan2(dy,dx);
双力=(长度-距离)*强度;
//System.out.println(dist+“,”+数学toDegrees(θ)+“,”+力);
//这里会发生什么?
p1.angle=…/首先,我建议不要在粒子中使用角度和速度,而是使用Point2D作为运动矢量:
public class Particle extends Circle {
double x;
double y;
Point2D vector = new Point2D(0, 0);
这简化了以后的更新计算
然后您可以按如下方式进行程序更新:
public void update() {
double dx = p1.getCenterX() - p2.getCenterX();
double dy = p1.getCenterY() - p2.getCenterY();
double dist = Math.hypot(dx, dy);
double theta = Math.atan2(dy, dx);
double force = (length - dist) * strength;
// System.out.println( dist + ", " + Math.toDegrees( theta) + ", " + force);
Point2D p1v = new Point2D(force*Math.cos(theta)/p1.mass/10000, force*Math.sin(theta)/p1.mass/10000);
Point2D p2v = new Point2D(-force*Math.cos(theta)/p2.mass/10000, -force*Math.sin(theta)/p2.mass/10000);
p1.vector = p1.vector.add(p1v);
p2.vector = p2.vector.add(p2v);
}
这忽略了任何碰撞,但将提供一个公平的物理模型。好的,添加一个阻尼和一个不可压缩的弹簧:
import java.util.ArrayList;
import java.util.List;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.StrokeType;
import javafx.stage.Stage;
public class SpringField extends Application {
MouseGestures mg = new MouseGestures();
double damping = 0.995;
double speedo = 0.001;
List<Particle> particles = new ArrayList<>();
List<Spring> springs = new ArrayList<>();
public static void main(String[] args) {
launch(args);
}
Particle addParticle(Group parent, Paint p, double x, double y, double mass) {
Particle particle = new Particle(p, x, y, mass);
mg.makeDraggable(particle);
particles.add(particle);
parent.getChildren().add(particle);
return particle;
}
void addSpring(Group parent, Particle p1, Particle p2, double length, double strength) {
Spring spring = new Spring(parent, p1, p2, length, strength);
springs.add(spring);
}
@Override
public void start(Stage primaryStage) {
Group root = new Group();
// create particles
Particle pRed = addParticle(root, Color.RED, 300, 100, 10);
Particle pBlue = addParticle(root, Color.BLUE, 600, 200, 1);
Particle pGreen = addParticle(root, Color.GREEN, 300, 300, 1);
// add springs
addSpring(root, pRed, pBlue, 100, 0.5);
addSpring(root, pGreen, pBlue, 100, 0.5);
addSpring(root, pGreen, pRed, 100, 0.5);
primaryStage.setScene(new Scene(root, 1024, 768));
primaryStage.show();
// animate
startAnimation();
}
private void startAnimation() {
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
// move particles
for (Particle p : particles) {
if (!p.selected) {
p.move();
}
}
// apply springs
for (Spring s : springs) {
s.update();
}
// move particles to new location
for (Particle p : particles) {
p.updateLocation();
}
}
};
timer.start();
}
/**
* The spring constraint and calculation. Updates particle
*/
public class Spring {
Particle p1;
Particle p2;
double length; // length it tries to obtain
double strength; // how quickly it tries to reach that length
public Spring(Group parent, Particle p1, Particle p2, double length, double strength) {
this.p1 = p1;
this.p2 = p2;
this.length = length;
this.strength = strength;
Line lineRedBlue = new Line(100, 100, 500, 500);
lineRedBlue.setStroke(Color.BLACK);
lineRedBlue.setStrokeWidth(5);
lineRedBlue.startXProperty().bind(p1.centerXProperty());
lineRedBlue.startYProperty().bind(p1.centerYProperty());
lineRedBlue.endXProperty().bind(p2.centerXProperty());
lineRedBlue.endYProperty().bind(p2.centerYProperty());
parent.getChildren().add(lineRedBlue);
}
public void update() {
double stop = 1.0;
double dx = p1.getCenterX() - p2.getCenterX();
double dy = p1.getCenterY() - p2.getCenterY();
double dist = Math.hypot(dx, dy);
double theta = Math.atan2(dy, dx);
double force = (length - dist) * strength;
if (force > 0) { force *= 4; stop = 0.9; }
// System.out.println( dist + ", " + Math.toDegrees( theta) + ", " + force);
Point2D p1v = new Point2D(force*Math.cos(theta)*speedo/p1.mass, force*Math.sin(theta)*speedo/p1.mass);
Point2D p2v = new Point2D(-force*Math.cos(theta)*speedo/p2.mass, -force*Math.sin(theta)*speedo/p2.mass);
p1.vector = p1.vector.add(p1v).multiply(stop);
p2.vector = p2.vector.add(p2v).multiply(stop);
}
}
/**
* The particle itself
*/
public class Particle extends Circle {
double x;
double y;
Point2D vector = new Point2D(0, 0);
double mass = 1;
boolean selected = false;
public Particle(Paint color, double x, double y, double mass) {
super(x, y, 50);
this.x = x;
this.y = y;
this.mass = mass;
setFill(color);
setStroke(color);
setStrokeWidth(2);
setStrokeType(StrokeType.OUTSIDE);
}
public void move() {
x += vector.getX();
y += vector.getY();
vector = vector.multiply(damping);
}
public void updateLocation() {
setCenterX( x);
setCenterY( y);
}
}
/**
* Allow movement of objects via mouse.
*/
public class MouseGestures {
double orgSceneX, orgSceneY;
double orgTranslateX, orgTranslateY;
public void makeDraggable( Node node) {
node.setOnMousePressed(circleOnMousePressedEventHandler);
node.setOnMouseDragged(circleOnMouseDraggedEventHandler);
node.setOnMouseReleased(circleOnMouseReleasedEventHandler);
}
EventHandler<MouseEvent> circleOnMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
orgSceneX = t.getSceneX();
orgSceneY = t.getSceneY();
Particle p = ((Particle) (t.getSource()));
p.selected = true;
orgTranslateX = p.getCenterX();
orgTranslateY = p.getCenterY();
}
};
EventHandler<MouseEvent> circleOnMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
Particle p = ((Particle) (t.getSource()));
p.selected = false;
};
};
EventHandler<MouseEvent> circleOnMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
double offsetX = t.getSceneX() - orgSceneX;
double offsetY = t.getSceneY() - orgSceneY;
double newTranslateX = orgTranslateX + offsetX;
double newTranslateY = orgTranslateY + offsetY;
Particle p = ((Particle) (t.getSource()));
p.x = newTranslateX;
p.y = newTranslateY;
}
};
}
}
import java.util.ArrayList;
导入java.util.List;
导入javafx.animation.AnimationTimer;
导入javafx.application.application;
导入javafx.event.EventHandler;
导入javafx.geometry.Point2D;
导入javafx.scene.Group;
导入javafx.scene.Node;
导入javafx.scene.scene;
导入javafx.scene.input.MouseEvent;
导入javafx.scene.paint.Color;
导入javafx.scene.paint.paint;
导入javafx.scene.shape.Circle;
导入javafx.scene.shape.Line;
导入javafx.scene.shape.StrokeType;
导入javafx.stage.stage;
公共类SpringField扩展了应用程序{
MouseGestures mg=新的MouseGestures();
双阻尼=0.995;
双speedo=0.001;
列表粒子=新的ArrayList();
列表弹簧=新的ArrayList();
公共静态void main(字符串[]args){
发射(args);
}
粒子添加粒子(组父对象、绘制p、双x、双y、双质量){
粒子
import java.util.ArrayList;
import java.util.List;
import javafx.animation.AnimationTimer;
import javafx.application.Application;
import javafx.event.EventHandler;
import javafx.geometry.Point2D;
import javafx.scene.Group;
import javafx.scene.Node;
import javafx.scene.Scene;
import javafx.scene.input.MouseEvent;
import javafx.scene.paint.Color;
import javafx.scene.paint.Paint;
import javafx.scene.shape.Circle;
import javafx.scene.shape.Line;
import javafx.scene.shape.StrokeType;
import javafx.stage.Stage;
public class SpringField extends Application {
MouseGestures mg = new MouseGestures();
double damping = 0.995;
double speedo = 0.001;
List<Particle> particles = new ArrayList<>();
List<Spring> springs = new ArrayList<>();
public static void main(String[] args) {
launch(args);
}
Particle addParticle(Group parent, Paint p, double x, double y, double mass) {
Particle particle = new Particle(p, x, y, mass);
mg.makeDraggable(particle);
particles.add(particle);
parent.getChildren().add(particle);
return particle;
}
void addSpring(Group parent, Particle p1, Particle p2, double length, double strength) {
Spring spring = new Spring(parent, p1, p2, length, strength);
springs.add(spring);
}
@Override
public void start(Stage primaryStage) {
Group root = new Group();
// create particles
Particle pRed = addParticle(root, Color.RED, 300, 100, 10);
Particle pBlue = addParticle(root, Color.BLUE, 600, 200, 1);
Particle pGreen = addParticle(root, Color.GREEN, 300, 300, 1);
// add springs
addSpring(root, pRed, pBlue, 100, 0.5);
addSpring(root, pGreen, pBlue, 100, 0.5);
addSpring(root, pGreen, pRed, 100, 0.5);
primaryStage.setScene(new Scene(root, 1024, 768));
primaryStage.show();
// animate
startAnimation();
}
private void startAnimation() {
AnimationTimer timer = new AnimationTimer() {
@Override
public void handle(long now) {
// move particles
for (Particle p : particles) {
if (!p.selected) {
p.move();
}
}
// apply springs
for (Spring s : springs) {
s.update();
}
// move particles to new location
for (Particle p : particles) {
p.updateLocation();
}
}
};
timer.start();
}
/**
* The spring constraint and calculation. Updates particle
*/
public class Spring {
Particle p1;
Particle p2;
double length; // length it tries to obtain
double strength; // how quickly it tries to reach that length
public Spring(Group parent, Particle p1, Particle p2, double length, double strength) {
this.p1 = p1;
this.p2 = p2;
this.length = length;
this.strength = strength;
Line lineRedBlue = new Line(100, 100, 500, 500);
lineRedBlue.setStroke(Color.BLACK);
lineRedBlue.setStrokeWidth(5);
lineRedBlue.startXProperty().bind(p1.centerXProperty());
lineRedBlue.startYProperty().bind(p1.centerYProperty());
lineRedBlue.endXProperty().bind(p2.centerXProperty());
lineRedBlue.endYProperty().bind(p2.centerYProperty());
parent.getChildren().add(lineRedBlue);
}
public void update() {
double stop = 1.0;
double dx = p1.getCenterX() - p2.getCenterX();
double dy = p1.getCenterY() - p2.getCenterY();
double dist = Math.hypot(dx, dy);
double theta = Math.atan2(dy, dx);
double force = (length - dist) * strength;
if (force > 0) { force *= 4; stop = 0.9; }
// System.out.println( dist + ", " + Math.toDegrees( theta) + ", " + force);
Point2D p1v = new Point2D(force*Math.cos(theta)*speedo/p1.mass, force*Math.sin(theta)*speedo/p1.mass);
Point2D p2v = new Point2D(-force*Math.cos(theta)*speedo/p2.mass, -force*Math.sin(theta)*speedo/p2.mass);
p1.vector = p1.vector.add(p1v).multiply(stop);
p2.vector = p2.vector.add(p2v).multiply(stop);
}
}
/**
* The particle itself
*/
public class Particle extends Circle {
double x;
double y;
Point2D vector = new Point2D(0, 0);
double mass = 1;
boolean selected = false;
public Particle(Paint color, double x, double y, double mass) {
super(x, y, 50);
this.x = x;
this.y = y;
this.mass = mass;
setFill(color);
setStroke(color);
setStrokeWidth(2);
setStrokeType(StrokeType.OUTSIDE);
}
public void move() {
x += vector.getX();
y += vector.getY();
vector = vector.multiply(damping);
}
public void updateLocation() {
setCenterX( x);
setCenterY( y);
}
}
/**
* Allow movement of objects via mouse.
*/
public class MouseGestures {
double orgSceneX, orgSceneY;
double orgTranslateX, orgTranslateY;
public void makeDraggable( Node node) {
node.setOnMousePressed(circleOnMousePressedEventHandler);
node.setOnMouseDragged(circleOnMouseDraggedEventHandler);
node.setOnMouseReleased(circleOnMouseReleasedEventHandler);
}
EventHandler<MouseEvent> circleOnMousePressedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
orgSceneX = t.getSceneX();
orgSceneY = t.getSceneY();
Particle p = ((Particle) (t.getSource()));
p.selected = true;
orgTranslateX = p.getCenterX();
orgTranslateY = p.getCenterY();
}
};
EventHandler<MouseEvent> circleOnMouseReleasedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
Particle p = ((Particle) (t.getSource()));
p.selected = false;
};
};
EventHandler<MouseEvent> circleOnMouseDraggedEventHandler = new EventHandler<MouseEvent>() {
@Override
public void handle(MouseEvent t) {
double offsetX = t.getSceneX() - orgSceneX;
double offsetY = t.getSceneY() - orgSceneY;
double newTranslateX = orgTranslateX + offsetX;
double newTranslateY = orgTranslateY + offsetY;
Particle p = ((Particle) (t.getSource()));
p.x = newTranslateX;
p.y = newTranslateY;
}
};
}
}
/**
*
* @author Jason Pollastrini aka jdub1581
*/
@FunctionalInterface
public interface Constraint {
public void solve();
public default void solve(int iter){
IntStream.range(0, iter).parallel().forEach(i->{solve();});
}
}
public void solve() {
// calculate the distance between the two PointMasss
Point3D diff = new Point3D(
p1.getPosition().getX() - p2.getPosition().getX(),
p1.getPosition().getY() - p2.getPosition().getY(),
p1.getPosition().getZ() - p2.getPosition().getZ()
);
double d = diff.magnitude();
double difference = (distance - d) / d;
double im1 = 1 / p1.getMass();
double im2 = 1 / p2.getMass();
double scalarP1 = (im1 / (im1 + im2)) * stiffness;
double scalarP2 = stiffness - scalarP1;
p1.position.x = (float) (p1.getPosition().x + diff.x * scalarP1 * difference);
p1.position.y = (float) (p1.getPosition().y + diff.y * scalarP1 * difference);
p1.position.z = (float) (p1.getPosition().z + diff.z * scalarP1 * difference);
p2.position.x = (float) (p2.getPosition().x - diff.x * scalarP2 * difference);
p2.position.y = (float) (p2.getPosition().y - diff.y * scalarP2 * difference);
p2.position.z = (float) (p2.getPosition().z - diff.z * scalarP2 * difference);
}
public void solveConstraints() {
constraints.values().parallelStream().forEach((Constraint c) -> {
c.solve();
});
}
public void updatePhysics(double dt, double t) {
if (isAnchored()) {
setPosition(getAnchorPosition());
return;
}
Point3D vel = new Point3D(
(position.x - oldPosition.x),
(position.y - oldPosition.y),
(position.z - oldPosition.z)
);
float dtSq = (float) (dt * dt);
// calculate the next position using Verlet Integration
Point3D next = new Point3D(
position.x + vel.x + (((force.x / (float) (mass)) * 0.5f) * dtSq),
position.y + vel.y + (((force.y / (float) (mass)) * 0.5f) * dtSq),
position.z + vel.z + (((force.z / (float) (mass)) * 0.5f) * dtSq)
);
// reset variables
setOldPosition(position);
setPosition(next);
setForce(new Point3D(0, 0, 0));
}