org.fxyz3d.shapes.complex.cloth.WeightedPoint Maven / Gradle / Ivy
The newest version!
/**
* WeightedPoint.java
*
* Copyright (c) 2013-2016, F(X)yz
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of F(X)yz, any associated website, nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL F(X)yz BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.fxyz3d.shapes.complex.cloth;
import java.util.HashMap;
import org.fxyz3d.geometry.Point3D;
/**
*
* @author Jason Pollastrini aka jdub1581
*/
public class WeightedPoint {
private final ClothMesh parent;
public double mass = 0;
public Point3D position,
oldPosition,
anchorPosition,
force;
private final HashMap constraints = new HashMap<>();
private boolean anchored = false,
forceAffected = true;
/*==========================================================================
Constructors
*/
private WeightedPoint() {
this.parent = null;
}
public WeightedPoint(ClothMesh parent) {
this(parent, 0.1, 0, 0, 0, false);
}
public WeightedPoint(ClothMesh parent, double mass) {
this(parent, mass, 0, 0, 0, false);
}
public WeightedPoint(ClothMesh parent, double mass, double x, double y, double z) {
this(parent, mass, x, y, z, false);
}
public WeightedPoint(ClothMesh parent, double mass, double x, double y, double z, boolean anchored) {
this.position = new Point3D((float) x, (float) y, (float) z);
this.oldPosition = new Point3D((float) x, (float) y, (float) z);
this.anchorPosition = new Point3D(0, 0, 0);
this.force = new Point3D(0, 0, 0);
this.parent = parent;
this.mass = mass;
this.anchored = anchored;
}
/*==========================================================================
Constraints
*/
public final void attatchTo(WeightedPoint other, double linkDistance, double stiffness) {
attatchTo(this, other, linkDistance, stiffness);
}
public final void attatchTo(WeightedPoint self, WeightedPoint other, double linkDistance, double stiffness) {
Link pl = new Link(self, other, linkDistance, stiffness);
addConstraint(other, (Constraint) pl);
}
//==========================================================================
public HashMap getConstraints() {
return constraints;
}
public void addConstraint(WeightedPoint other, Constraint constraint) {
this.constraints.put(other, constraint);
}
public void addConstraint(Constraint c){
this.constraints.put(this, c);
}
public void removeConstraint(Constraint pl) {
}
public void clearConstraints() {
constraints.clear();
}
/*==========================================================================
Updating
*/
public void solveConstraints() {
constraints.values().parallelStream().forEach(Constraint::solve);
}
public void updatePhysics(double dt, double t) {
synchronized (this) {
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);
clearForces();
//log.log(Level.INFO, "\n Velocity: {0}", vel);
}
}
/*==========================================================================
Variable's Getters / setters
*/
public double getMass() {
return mass;
}
public void setMass(double mass) {
this.mass = mass;
}
/*==========================================================================
Positions
*/
public final Point3D getPosition() {
return new Point3D(position.x, position.y, position.z);
}
public void setPosition(Point3D pos) {
position.x = pos.x;
position.y = pos.y;
position.z = pos.z;
}
public void setPosition(double x, double y, double z) {
position.x = (float) x;
position.y = (float) y;
position.z = (float) z;
}
//==========================================================================
public Point3D getOldPosition() {
return oldPosition;
}
public void setOldPosition(Point3D oldPosition) {
this.oldPosition.x = oldPosition.x;
this.oldPosition.y = oldPosition.y;
this.oldPosition.z = oldPosition.z;
}
public void setOldPosition(float x, float y, float z) {
this.oldPosition.x = x;
this.oldPosition.y = y;
this.oldPosition.z = z;
}
public void setOldPosition(double x, double y, double z) {
this.oldPosition.x = (float) x;
this.oldPosition.y = (float) y;
this.oldPosition.z = (float) z;
}
//==========================================================================
public boolean isAnchored() {
return anchored;
}
public void setAnchored(boolean anchored) {
this.anchored = anchored;
if (anchored) {
setAnchorPosition(new Point3D(position.x, position.y, position.z));
} else {
setAnchorPosition(null);
}
}
public Point3D getAnchorPosition() {
return anchorPosition;
}
public void setAnchorPosition(Point3D anchorPosition) {
this.anchorPosition = anchorPosition;
}
/*==========================================================================
Forces
*/
public Point3D getForce() {
return force;
}
private void setForce(Point3D p) {
this.force = p;
}
public void applyForce(Point3D force) {
if (isForceAffected()) {
this.force.x += force.x;
this.force.y += force.y;
this.force.z += force.z;
}
}
public void clearForces() {
setForce(new Point3D(0, 0, 0));
}
public boolean isForceAffected() {
return forceAffected;
}
public void setForceAffected(boolean forceAffected) {
this.forceAffected = forceAffected;
}
/*==========================================================================
*/
@Override
public String toString() {
return "WeightedPoint: ".concat(position.toString());
}
}//End WeightedPoint========================================================