diff --git a/day3/libs/mathematik/library/mathematik.jar b/day3/libs/mathematik/library/mathematik.jar new file mode 100755 index 0000000..e078d13 Binary files /dev/null and b/day3/libs/mathematik/library/mathematik.jar differ diff --git a/day3/libs/mathematik/src/mathematik/BSpline.java b/day3/libs/mathematik/src/mathematik/BSpline.java new file mode 100755 index 0000000..e3cdcad --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/BSpline.java @@ -0,0 +1,89 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.util.Vector; + + +/** + * b-spline source code from: Tim Lambert 'nice page on curves, splines etc.' + * http://www.cse.unsw.edu.au/~lambert/splines/ + */ +public abstract class BSpline { + + /* the basis function for a cubic B spline */ + private static float b(int i, float t) { + switch (i) { + case -2: + return (((-t + 3) * t - 3) * t + 1) / 6; + case -1: + return (((3 * t - 6) * t) * t + 4) / 6; + case 0: + return (((-3 * t + 3) * t + 3) * t + 1) / 6; + case 1: + return (t * t * t) / 6; + } + return 0; //we only get here if an invalid i is specified + } + + + /* evaluate a point on the B spline */ + private static Vector3f p(Vector thePoints, int i, float t) { + Vector3f p = new Vector3f(); + for (int j = -2; j <= 1; j++) { + p.x += b(j, t) * thePoints.get(i + j).x; + p.y += b(j, t) * thePoints.get(i + j).y; + p.z += b(j, t) * thePoints.get(i + j).z; + } + return p; + } + + public static Vector curve(Vector thePoints, int theSteps, Vector theResult) { + for (int i = 2; i < thePoints.size() - 1; i++) { + for (int j = 1; j <= theSteps; j++) { + theResult.add(p(thePoints, i, j / (float) theSteps)); + } + } + return theResult; + } + + public static Vector curve(Vector thePoints, int theSteps) { + return curve(thePoints, theSteps, new Vector()); + } + + public static Vector closeCurve(Vector thePoints) { + /* copy points */ + Vector myClosedPoints = new Vector(); + for (int i = 0; i < thePoints.size(); i++) { + myClosedPoints.add(thePoints.get(i)); + } + + /* repeat first three points */ + if (thePoints.size() > 2) { + myClosedPoints.add(thePoints.get(0)); + myClosedPoints.add(thePoints.get(1)); + myClosedPoints.add(thePoints.get(2)); + } + return myClosedPoints; + } +} diff --git a/day3/libs/mathematik/src/mathematik/Intersection.java b/day3/libs/mathematik/src/mathematik/Intersection.java new file mode 100755 index 0000000..6b8fb54 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Intersection.java @@ -0,0 +1,916 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +/** + * beware this is not really in good shape. i ll read my linear algebra book and + * fix this class. someday. hopefully. + */ +public final class Intersection + implements Serializable, + Mathematik { + + private static final long serialVersionUID = -5392974339890719551L; + + private static final Vector3f h = new Vector3f(); + + private static final Vector3f s = new Vector3f(); + + private static final Vector3f q = new Vector3f(); + + private static final Vector3f _myTempEdge1 = new Vector3f(); + + private static final Vector3f _myTempEdge2 = new Vector3f(); + + private static final Vector3f _myTempNormal = new Vector3f(); + + private static final Vector3f pvec = new Vector3f(); + + private static final Vector3f tvec = new Vector3f(); + + private static final Vector3f qvec = new Vector3f(); + + public static boolean intersectRayPlane(final Ray3f theRay, + final Plane3f thePlane, + final Vector3f theResult, + final boolean doPlanar, + final boolean quad) { + Vector3f diff = mathematik.Util.sub(theRay.origin, thePlane.origin); // mathematik.Util.sub(theRay.origin, v0); + Vector3f edge1 = thePlane.vectorA; // mathematik.Util.sub(v1, v0); + Vector3f edge2 = thePlane.vectorB; // mathematik.Util.sub(v2, v0); + + Vector3f norm = thePlane.normal; //new Vector3f(); + + if (thePlane.normal == null) { + thePlane.updateNormal(); + norm = thePlane.normal; + } + + float dirDotNorm = theRay.direction.dot(norm); + float sign; + if (dirDotNorm > EPSILON) { + sign = 1; + } else if (dirDotNorm < EPSILON) { + sign = -1f; + dirDotNorm = -dirDotNorm; + } else { + // ray and triangle are parallel + return false; + } + + Vector3f myCross; + myCross = new Vector3f(); + myCross.cross(diff, edge2); + float dirDotDiffxEdge2 = sign * theRay.direction.dot(myCross); + if (dirDotDiffxEdge2 > 0.0f) { + myCross = new Vector3f(); + myCross.cross(edge1, diff); + float dirDotEdge1xDiff = sign * theRay.direction.dot(myCross); + if (dirDotEdge1xDiff >= 0.0f) { + if (!quad ? dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm : dirDotEdge1xDiff <= dirDotNorm) { + float diffDotNorm = -sign * diff.dot(norm); + if (diffDotNorm >= 0.0f) { + // ray intersects triangle + // if storage vector is null, just return true, + if (theResult == null) { + return true; + } + // else fill in. + float inv = 1f / dirDotNorm; + float t = diffDotNorm * inv; + if (!doPlanar) { + theResult.set(theRay.origin); + theResult.add(theRay.direction.x * t, + theRay.direction.y * t, + theRay.direction.z * t); + } else { + // these weights can be used to determine + // interpolated values, such as texture coord. + // eg. texcoord s,t at intersection point: + // s = w0*s0 + w1*s1 + w2*s2; + // t = w0*t0 + w1*t1 + w2*t2; + float w1 = dirDotDiffxEdge2 * inv; + float w2 = dirDotEdge1xDiff * inv; + //float w0 = 1.0f - w1 - w2; + theResult.set(t, w1, w2); + } + return true; + } + } + } + } + return false; + } + +// /** +// * @deprecated not in good state. +// * @param v0 first point of the triangle. +// * @param v1 second point of the triangle. +// * @param v2 third point of the triangle. +// * @param store storage vector - if null, no intersection is calc'd +// * @param doPlanar true if we are calcing planar results. +// * @param quad +// * @return true if ray intersects triangle +// */ +// public static boolean intersectRayTriangle(final Ray3f theRay, +// final Vector3f v0, +// final Vector3f v1, +// final Vector3f v2, +// final Vector3f store, +// final boolean doPlanar, +// final boolean quad) { +// Vector3f diff = mathematik.Util.sub(theRay.origin, v0); +// Vector3f edge1 = mathematik.Util.sub(v1, v0); +// Vector3f edge2 = mathematik.Util.sub(v2, v0); +// Vector3f norm = new Vector3f(); +// norm.cross(edge1, edge2); +// +// float dirDotNorm = theRay.direction.dot(norm); +// float sign; +// if (dirDotNorm > EPSILON) { +// sign = 1; +// } else if (dirDotNorm < EPSILON) { +// sign = -1f; +// dirDotNorm = -dirDotNorm; +// } else { +// // ray and triangle are parallel +// return false; +// } +// +// Vector3f myCross; +// myCross = new Vector3f(); +// myCross.cross(diff, edge2); +// float dirDotDiffxEdge2 = sign * theRay.direction.dot(myCross); +// if (dirDotDiffxEdge2 > 0.0f) { +// myCross = new Vector3f(); +// myCross.cross(edge1, diff); +// float dirDotEdge1xDiff = sign * theRay.direction.dot(myCross); +// if (dirDotEdge1xDiff >= 0.0f) { +// if (!quad ? dirDotDiffxEdge2 + dirDotEdge1xDiff <= dirDotNorm : dirDotEdge1xDiff <= dirDotNorm) { +// float diffDotNorm = -sign * diff.dot(norm); +// if (diffDotNorm >= 0.0f) { +// // ray intersects triangle +// // if storage vector is null, just return true, +// if (store == null) { +// return true; +// } +// // else fill in. +// float inv = 1f / dirDotNorm; +// float t = diffDotNorm * inv; +// if (!doPlanar) { +// store.set(theRay.origin); +// store.add(theRay.direction.x * t, +// theRay.direction.y * t, +// theRay.direction.z * t); +// } else { +// // these weights can be used to determine +// // interpolated values, such as texture coord. +// // eg. texcoord s,t at intersection point: +// // s = w0*s0 + w1*s1 + w2*s2; +// // t = w0*t0 + w1*t1 + w2*t2; +// float w1 = dirDotDiffxEdge2 * inv; +// float w2 = dirDotEdge1xDiff * inv; +// //float w0 = 1.0f - w1 - w2; +// store.set(t, w1, w2); +// } +// return true; +// } +// } +// } +// } +// return false; +// } + /* + * Practical Analysis of Optimized Ray-Triangle Intersection + * Tomas Moeller + * Department of Computer Engineering, Chalmers University of Technology, Sweden. + * + * code rewritten to do tests on the sign of the determinant + * the division is before the test of the sign of the det + * and one CROSS has been moved out from the if-else if-else + * from -- http://www.cs.lth.se/home/Tomas_Akenine_Moller/raytri/raytri.c + */ + public static boolean intersectRayTriangle(final Vector3f orig, + final Vector3f dir, + final Vector3f vert0, + final Vector3f vert1, + final Vector3f vert2, + float[] result) { + final int T = 0; + final int U = 1; + final int V = 2; + Vector3f edge1; + Vector3f edge2; + Vector3f tvec; + Vector3f pvec; + Vector3f qvec; + float det; + float inv_det; + + /* find vectors for two edges sharing vert0 */ + edge1 = mathematik.Util.sub(vert1, vert0); + edge2 = mathematik.Util.sub(vert2, vert0); + + /* begin calculating determinant - also used to calculate U parameter */ + pvec = mathematik.Util.cross(dir, edge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + det = edge1.dot(pvec); + + /* calculate distance from vert0 to ray origin */ + tvec = mathematik.Util.sub(orig, vert0); + inv_det = 1.0f / det; + + qvec = mathematik.Util.cross(tvec, edge1); + + if (det > EPSILON) { + result[U] = tvec.dot(pvec); + if (result[U] < 0.0f || result[U] > det) { + return false; + } + + /* calculate V parameter and test bounds */ + result[V] = dir.dot(qvec); + if (result[V] < 0.0f || result[U] + result[V] > det) { + return false; + } + + } else if (det < -EPSILON) { + /* calculate U parameter and test bounds */ + result[U] = tvec.dot(pvec); + if (result[U] > 0.0f || result[U] < det) { + return false; + } + + /* calculate V parameter and test bounds */ + result[V] = dir.dot(qvec); + if (result[V] > 0.0f || result[U] + result[V] < det) { + return false; + } + } else { + return false; /* ray is parallell to the plane of the triangle */ + } + + result[T] = edge2.dot(qvec) * inv_det; + result[U] *= inv_det; + result[V] *= inv_det; + + return true; + } + + /** + * grabbed from Xith + * + * @todo not sure whether this is for ray-plane or line-plane intersection. + * but i think it s for latter, hence the method name. + * + * @param thePlane Plane3f + * @param theRay Ray3f + * @param theIntersectionPoint Vector3f + * @return float + */ + public static float intersectLinePlane(final Ray3f theRay, + final Plane3f thePlane, + final Vector3f theIntersectionPoint) { + double time = 0; + _myTempNormal.cross(thePlane.vectorA, thePlane.vectorB); + double denom = _myTempNormal.dot(theRay.direction); + + if (denom == 0) { + System.err.println("### ERROR @ Intersection / NEGATIVE_INFINITY"); + return Float.NEGATIVE_INFINITY; + } + + double numer = _myTempNormal.dot(theRay.origin); + double D = -(thePlane.origin.dot(_myTempNormal)); + time = -((numer + D) / denom); + + if (theIntersectionPoint != null) { + theIntersectionPoint.set(theRay.direction); + theIntersectionPoint.scale((float) time); + theIntersectionPoint.add(theRay.origin); + } + + return (float) time; + } + +// /** +// * @deprecated this method might contain errors. +// * @param theRay Ray3f +// * @param thePlane Plane3f +// * @param theResult Vector3f +// * @param theCullingFlag boolean +// * @return float +// */ +// public static float intersectRayTriangle(final Ray3f theRay, +// final Plane3f thePlane, +// final Vector3f theResult, +// final boolean theCullingFlag) { +// float a; +// float f; +// float u; +// float v; +// float t; +// +// _myTempEdge1.set(thePlane.vectorA); +// _myTempEdge2.set(thePlane.vectorB); +// +// h.cross(theRay.direction, _myTempEdge2); +// +// a = _myTempEdge1.dot(h); +// if (a > -EPSILON && a < EPSILON) { +// return Float.NaN; +// } +// if (theCullingFlag) { +// // u +// s.sub(theRay.origin, +// thePlane.origin); +// u = s.dot(h); +// if (u < 0.0f || u > a) { +// return Float.NaN; +// } +// // v +// v = theRay.direction.dot(q); +// if (v < 0.0f || u + v > a) { +// return Float.NaN; +// } +// // t +// q.cross(s, +// _myTempEdge1); +// t = _myTempEdge2.dot(q); +// // invert +// f = 1.0f / a; +// u *= f; +// v *= f; +// t *= f; +// } else { +// f = 1f / a; +// // u +// s.sub(theRay.origin, +// thePlane.origin); +// u = f * s.dot(h); +// if (u < 0.0f || u > 1.0f) { +// return Float.NaN; +// } +// // v +// q.cross(s, +// _myTempEdge1); +// v = f * theRay.direction.dot(q); +// if (v < 0.0 || u + v > 1.0) { +// return Float.NaN; +// } +// // t +// t = _myTempEdge2.dot(q) * f; +// } +// // result +// theResult.scale(t, +// theRay.direction); +// theResult.add(theRay.origin); +// +// return t; +// } + /** + * @deprecated this method might contain errors. + * @param theRayOrigin Vector3f + * @param theRayDirection Vector3f + * @param thePlanePointA Vector3f + * @param thePlanePointB Vector3f + * @param thePlanePointC Vector3f + * @param theResult Vector3f + * @return boolean + */ + public static boolean intersectRayPlane(final Vector3f theRayOrigin, + final Vector3f theRayDirection, + final Vector3f thePlanePointA, + final Vector3f thePlanePointB, + final Vector3f thePlanePointC, + final Vector3f theResult) { + float a; + float f; + float u; + float v; + float t; + + _myTempEdge1.sub(thePlanePointB, + thePlanePointA); + _myTempEdge2.sub(thePlanePointC, + thePlanePointA); + h.cross(theRayDirection, + _myTempEdge2); + + a = _myTempEdge1.dot(h); + if (a > -EPSILON && a < EPSILON) { + return false; // parallel + } + // u + s.sub(theRayOrigin, + thePlanePointA); + u = s.dot(h); + // v + v = theRayDirection.dot(q); + // t + q.cross(s, + _myTempEdge1); + t = _myTempEdge2.dot(q); + // invert + f = 1.0f / a; + u *= f; + v *= f; + t *= f; + + // result + theResult.scale(t, + theRayDirection); + theResult.add(theRayOrigin); + + return true; + } + + /** + * @deprecated this method might contain errors. + * @param theRay Ray3f + * @param thePlane Plane3f + * @param theResult Vector3f + * @return boolean + */ + public static boolean intersectRayPlane(final Ray3f theRay, + final Plane3f thePlane, + final Vector3f theResult) { + float a; + float f; + float u; + float v; + float t; + + _myTempEdge1.set(thePlane.vectorA); + _myTempEdge2.set(thePlane.vectorB); + h.cross(theRay.direction, + _myTempEdge2); + + a = _myTempEdge1.dot(h); + if (a > -EPSILON && a < EPSILON) { + return false; // parallel + } + // u + s.sub(theRay.origin, + thePlane.origin); + u = s.dot(h); + // v + v = theRay.direction.dot(q); + // t + q.cross(s, + _myTempEdge1); + t = _myTempEdge2.dot(q); + // invert + f = 1.0f / a; + u *= f; + v *= f; + t *= f; + + // result + theResult.scale(t, + theRay.direction); + theResult.add(theRay.origin); + + return true; + } + + /** + * @deprecated this method might contain errors. + * @param theRay Ray3f + * @param thePlane Plane3f + * @return float + */ + public static float intersectRayPlane(final Ray3f theRay, + final Plane3f thePlane) { + float a; + float f; + float u; + float v; + float t; + + _myTempEdge1.set(thePlane.vectorA); + _myTempEdge2.set(thePlane.vectorB); + h.cross(theRay.direction, _myTempEdge2); + + a = _myTempEdge1.dot(h); + if (a > -EPSILON && a < EPSILON) { + return Float.NaN; // parallel + } + // u + s.sub(theRay.origin, + thePlane.origin); + u = s.dot(h); + // v + v = theRay.direction.dot(q); + // t + q.cross(s, + _myTempEdge1); + t = _myTempEdge2.dot(q); + // invert + f = 1.0f / a; + u *= f; + v *= f; + t *= f; + + return t; + } + + /** + * Fast, Minimum Storage Ray-Triangle Intersection by Tomas Moeller & Ben + * Trumbore http://jgt.akpeters.com/papers/MollerTrumbore97/code.html + * + * @param theRayOrigin Vector3f + * @param theRayDirection Vector3f + * @param theVertex0 Vector3f + * @param theVertex1 Vector3f + * @param theVertex2 Vector3f + * @param theResult Result + * @param theCullingFlag boolean + * @return boolean + */ + public static boolean intersectRayTriangle(final Vector3f theRayOrigin, + final Vector3f theRayDirection, + final Vector3f theVertex0, + final Vector3f theVertex1, + final Vector3f theVertex2, + final IntersectionResult theResult, + final boolean theCullingFlag) { + + float det; + float inv_det; + + /* find vectors for two edges sharing vert0 */ + _myTempEdge1.sub(theVertex1, theVertex0); + _myTempEdge2.sub(theVertex2, theVertex0); + + /* begin calculating determinant - also used to calculate U parameter */ + pvec.cross(theRayDirection, _myTempEdge2); + + /* if determinant is near zero, ray lies in plane of triangle */ + det = _myTempEdge1.dot(pvec); + + if (theCullingFlag) { /* define TEST_CULL if culling is desired */ + if (det < EPSILON) { + return false; + } + /* calculate distance from vert0 to ray origin */ + tvec.sub(theRayOrigin, theVertex0); + + /* calculate U parameter and test bounds */ + theResult.u = tvec.dot(pvec); + if (theResult.u < 0.0f || theResult.u > det) { + return false; + } + + /* prepare to test V parameter */ + qvec.cross(tvec, _myTempEdge1); + + /* calculate V parameter and test bounds */ + theResult.v = theRayDirection.dot(qvec); + if (theResult.v < 0.0f || theResult.u + theResult.v > det) { + return false; + } + + /* calculate t, scale parameters, ray intersects triangle */ + theResult.t = _myTempEdge2.dot(qvec); + inv_det = 1.0f / det; + theResult.t *= inv_det; + theResult.u *= inv_det; + theResult.v *= inv_det; + } else { /* the non-culling branch */ + if (det > -EPSILON && det < EPSILON) { + return false; + } + inv_det = 1.0f / det; + + /* calculate distance from vert0 to ray origin */ + tvec.sub(theRayOrigin, theVertex0); + + /* calculate U parameter and test bounds */ + theResult.u = tvec.dot(pvec) * inv_det; + if (theResult.u < 0.0f || theResult.u > 1.0f) { + return false; + } + + /* prepare to test V parameter */ + qvec.cross(tvec, _myTempEdge1); + + /* calculate V parameter and test bounds */ + theResult.v = theRayDirection.dot(qvec) * inv_det; + if (theResult.v < 0.0f || theResult.u + theResult.v > 1.0f) { + return false; + } + + /* calculate t, ray intersects triangle */ + theResult.t = _myTempEdge2.dot(qvec) * inv_det; + } + return true; + } + + public static class IntersectionResult { + + public float t; + + public float u; + + public float v; + + } + + public static float intersectRayTriangle(final Vector3f theRayOrigin, + final Vector3f theRayDirection, + final Vector3f thePlanePointA, + final Vector3f thePlanePointB, + final Vector3f thePlanePointC, + final Vector3f theResult, + final boolean theCullingFlag) { + float a; + float f; + float u; + float v; + float t; + + _myTempEdge1.sub(thePlanePointB, + thePlanePointA); + _myTempEdge2.sub(thePlanePointC, + thePlanePointA); + + h.cross(theRayDirection, + _myTempEdge2); + + a = _myTempEdge1.dot(h); + if (a > -EPSILON && a < EPSILON) { + return Float.NaN; + } + if (theCullingFlag) { + // u + s.sub(theRayOrigin, + thePlanePointA); + u = s.dot(h); + if (u < 0.0f || u > a) { + return Float.NaN; + } + // v + v = theRayDirection.dot(q); + if (v < 0.0f || u + v > a) { + return Float.NaN; + } + // t + q.cross(s, + _myTempEdge1); + t = _myTempEdge2.dot(q); + // invert + f = 1.0f / a; + u *= f; + v *= f; + t *= f; + } else { + f = 1f / a; + // u + s.sub(theRayOrigin, + thePlanePointA); + u = f * s.dot(h); + if (u < 0.0f || u > 1.0f) { + return Float.NaN; + } + // v + q.cross(s, + _myTempEdge1); + v = f * theRayDirection.dot(q); + if (v < 0.0 || u + v > 1.0) { + return Float.NaN; + } + // t + t = _myTempEdge2.dot(q) * f; + } + // result + theResult.scale(t, + theRayDirection); + theResult.add(theRayOrigin); + + return t; + } + + /** + * http://local.wasp.uwa.edu.au/~pbourke/geometry/sphereline/raysphere.c + * Calculate the intersection of a ray and a sphere The line segment is + * defined from p1 to p2 The sphere is of radius r and centered at sc There + * are potentially two points of intersection given by p = p1 + mu1 (p2 - + * p1) p = p1 + mu2 (p2 - p1) Return FALSE if the ray doesn't intersect the + * sphere. + */ + public static boolean RaySphere(Vector3f p1, + Vector3f p2, + Vector3f sc, + float r) { + float a, b, c; + float bb4ac; + Vector3f dp = new Vector3f(); + + dp.x = p2.x - p1.x; + dp.y = p2.y - p1.y; + dp.z = p2.z - p1.z; + a = dp.x * dp.x + dp.y * dp.y + dp.z * dp.z; + b = 2 * (dp.x * (p1.x - sc.x) + dp.y * (p1.y - sc.y) + dp.z * (p1.z - sc.z)); + c = sc.x * sc.x + sc.y * sc.y + sc.z * sc.z; + c += p1.x * p1.x + p1.y * p1.y + p1.z * p1.z; + c -= 2 * (sc.x * p1.x + sc.y * p1.y + sc.z * p1.z); + c -= r * r; + bb4ac = b * b - 4 * a * c; + if (Math.abs(a) < EPSILON || bb4ac < 0) { + return false; + } + +// float mu1 = ( -b + (float) Math.sqrt(bb4ac)) / (2 * a); +// float mu2 = ( -b - (float) Math.sqrt(bb4ac)) / (2 * a); +// +// Vector3f myP1 = new Vector3f(dp); +// myP1.scale(mu1); +// myP1.add(p1); +// +// Vector3f myP2 = new Vector3f(dp); +// myP2.scale(mu2); +// myP2.add(p1); + + return true; + } + /** + * from paul bourke ( + * http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline2d/ ) + * + */ + public static final int COINCIDENT = 0; + + public static final int PARALLEL = 1; + + public static final int INTERESECTING = 2; + + public static final int NOT_INTERESECTING = 3; + + public static int lineLineIntersect(Vector2f aBegin, Vector2f aEnd, + Vector2f bBegin, Vector2f bEnd, + Vector2f theIntersection) { + float denom = ((bEnd.y - bBegin.y) * (aEnd.x - aBegin.x)) + - ((bEnd.x - bBegin.x) * (aEnd.y - aBegin.y)); + + float nume_a = ((bEnd.x - bBegin.x) * (aBegin.y - bBegin.y)) + - ((bEnd.y - bBegin.y) * (aBegin.x - bBegin.x)); + + float nume_b = ((aEnd.x - aBegin.x) * (aBegin.y - bBegin.y)) + - ((aEnd.y - aBegin.y) * (aBegin.x - bBegin.x)); + + if (denom == 0.0f) { + if (nume_a == 0.0f && nume_b == 0.0f) { + return COINCIDENT; + } + return PARALLEL; + } + + float ua = nume_a / denom; + float ub = nume_b / denom; + + if (ua >= 0.0f && ua <= 1.0f && ub >= 0.0f && ub <= 1.0f) { + if (theIntersection != null) { + // Get the intersection point. + theIntersection.x = aBegin.x + ua * (aEnd.x - aBegin.x); + theIntersection.y = aBegin.y + ua * (aEnd.y - aBegin.y); + } + return INTERESECTING; + } + + return NOT_INTERESECTING; + } + + /** + * from paul bourke ( + * http://local.wasp.uwa.edu.au/~pbourke/geometry/lineline3d/ ) + * + * Calculate the line segment PaPb that is the shortest route between two + * lines P1P2 and P3P4. Calculate also the values of mua and mub where Pa = + * P1 + mua (P2 - P1) Pb = P3 + mub (P4 - P3) Return FALSE if no solution + * exists. + * + */ + public static boolean lineLineIntersect(Vector3f p1, Vector3f p2, Vector3f p3, Vector3f p4, + Vector3f pa, Vector3f pb, + float[] theResult) { + + final Vector3f p13 = mathematik.Util.sub(p1, p3); + final Vector3f p43 = mathematik.Util.sub(p4, p3); + if (Math.abs(p43.x) < EPSILON && Math.abs(p43.y) < EPSILON && Math.abs(p43.z) < EPSILON) { + return false; + } + + final Vector3f p21 = mathematik.Util.sub(p2, p1); + if (Math.abs(p21.x) < EPSILON && Math.abs(p21.y) < EPSILON && Math.abs(p21.z) < EPSILON) { + return false; + } + + final float d1343 = p13.x * p43.x + p13.y * p43.y + p13.z * p43.z; + final float d4321 = p43.x * p21.x + p43.y * p21.y + p43.z * p21.z; + final float d1321 = p13.x * p21.x + p13.y * p21.y + p13.z * p21.z; + final float d4343 = p43.x * p43.x + p43.y * p43.y + p43.z * p43.z; + final float d2121 = p21.x * p21.x + p21.y * p21.y + p21.z * p21.z; + + final float denom = d2121 * d4343 - d4321 * d4321; + if (Math.abs(denom) < EPSILON) { + return false; + } + final float numer = d1343 * d4321 - d1321 * d4343; + + final float mua = numer / denom; + final float mub = (d1343 + d4321 * mua) / d4343; + + pa.x = p1.x + mua * p21.x; + pa.y = p1.y + mua * p21.y; + pa.z = p1.z + mua * p21.z; + pb.x = p3.x + mub * p43.x; + pb.y = p3.y + mub * p43.y; + pb.z = p3.z + mub * p43.z; + + if (theResult != null) { + theResult[0] = mua; + theResult[1] = mub; + } + return true; + } + + public static Vector3f[] intersectRaySpherePoints(Vector3f pSphereCenter, + float pSphereRadius, + Vector3f pRayDirection, + Vector3f pRayOrigin) { + // Solve quadratic equation + float a = pRayDirection.lengthSquared(); + if (a == 0.0) { + return null; + } + float b = 2.0f * (pRayOrigin.dot(pRayDirection) - pRayDirection.dot(pSphereCenter)); + Vector3f tempDiff = mathematik.Util.sub(pSphereCenter, pRayOrigin); + float c = tempDiff.lengthSquared() - (pSphereRadius * pSphereRadius); + float disc = b * b - 4 * a * c; + if (disc < 0.0f) { + return null; + } + int numIntersections; + if (disc == 0.0f) { + numIntersections = 1; + } else { + numIntersections = 2; + } + + // Atleast one intersection + Vector3f[] points = new Vector3f[numIntersections]; + float t0; + float t1 = 0.0f; + t0 = ((0.5f * (-1.0f * b + (float) Math.sqrt(disc))) / a); + if (numIntersections == 2) { + t1 = ((0.5f * (-1.0f * b - (float) Math.sqrt(disc))) / a); + } + // point 1 of intersection + points[0] = new Vector3f(pRayDirection); + points[0].scale(t0); + points[0].add(pRayOrigin); + if (numIntersections == 2) { + points[1] = new Vector3f(pRayDirection); + points[1].scale(t1); + points[1].add(pRayOrigin); + } + return points; + } + + public static void main(String[] args) { + Vector3f myP1 = new Vector3f(); + Vector3f myP2 = new Vector3f(10, 10, 10); + Vector3f myP3 = new Vector3f(10, 0, 0); + Vector3f myP4 = new Vector3f(0, 10, 10); + Vector3f myPA = new Vector3f(); + Vector3f myPB = new Vector3f(); + lineLineIntersect(myP1, myP2, myP3, myP4, myPA, myPB, null); + System.out.println(myPA); + System.out.println(myPB); + } +} diff --git a/day3/libs/mathematik/src/mathematik/Linef.java b/day3/libs/mathematik/src/mathematik/Linef.java new file mode 100755 index 0000000..659b9c8 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Linef.java @@ -0,0 +1,52 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +public class Linef + implements Serializable { + + private static final long serialVersionUID = -1748179277316146123L; + + public T p1; + + public T p2; + + public Linef(Class theClass) { + try { + p1 = theClass.newInstance(); + p2 = theClass.newInstance(); + } catch (IllegalAccessException ex) { + ex.printStackTrace(); + } catch (InstantiationException ex) { + ex.printStackTrace(); + } + } + + /* + * Linef myLine = new Linef (Vector2f.class); + * Linef myLine3f = new Linef (Vector3f.class); + */ +} diff --git a/day3/libs/mathematik/src/mathematik/Mathematik.java b/day3/libs/mathematik/src/mathematik/Mathematik.java new file mode 100755 index 0000000..c239077 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Mathematik.java @@ -0,0 +1,29 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +public interface Mathematik { + + float EPSILON = 0.00001f; + +} diff --git a/day3/libs/mathematik/src/mathematik/Matrix3f.java b/day3/libs/mathematik/src/mathematik/Matrix3f.java new file mode 100755 index 0000000..83e7d1e --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Matrix3f.java @@ -0,0 +1,619 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +/** + * a 3x3 matrix. + * + * rotation + * + * rxx ryx rzx rxy ryy rzy rxz ryy rzz + * + * scale + * + * sx 0 0 0 sy 0 0 0 sz + * + * + * also read 'The Matrix and Quaternions FAQ' at + * http://www.flipcode.com/documents/matrfaq.html + * + */ +package mathematik; + + +import java.io.Serializable; + + +public class Matrix3f + implements Serializable { + + private static final long serialVersionUID = 104839874874759581L; + + public static final int IDENTITY = 1; + + public float xx; + + public float xy; + + public float xz; + + public float yx; + + public float yy; + + public float yz; + + public float zx; + + public float zy; + + public float zz; + + private final float[] _myArrayRepresentation = new float[9]; + + private final float[] _myArray4fRepresentation = new float[16]; + + public Matrix3f() { + xx = 0.0f; + xy = 0.0f; + xz = 0.0f; + yx = 0.0f; + yy = 0.0f; + yz = 0.0f; + zx = 0.0f; + zy = 0.0f; + zz = 0.0f; + } + + public Matrix3f(Matrix3f theMatrix) { + set(theMatrix); + } + + public Matrix3f(int theType) { + switch (theType) { + case IDENTITY: + setIdentity(); + break; + } + } + + private void set(float xx, + float yx, + float zx, + float xy, + float yy, + float zy, + float xz, + float yz, + float zz) { + this.xx = xx; + this.xy = xy; + this.xz = xz; + this.yx = yx; + this.yy = yy; + this.yz = yz; + this.zx = zx; + this.zy = zy; + this.zz = zz; + } + + public final void set(float[] _myArrayRepresentation) { + xx = _myArrayRepresentation[0]; + yx = _myArrayRepresentation[1]; + zx = _myArrayRepresentation[2]; + xy = _myArrayRepresentation[3]; + yy = _myArrayRepresentation[4]; + zy = _myArrayRepresentation[5]; + xz = _myArrayRepresentation[6]; + yz = _myArrayRepresentation[7]; + zz = _myArrayRepresentation[8]; + } + + public final void set(Matrix3f theMatrix) { + xx = theMatrix.xx; + xy = theMatrix.xy; + xz = theMatrix.xz; + yx = theMatrix.yx; + yy = theMatrix.yy; + yz = theMatrix.yz; + zx = theMatrix.zx; + zy = theMatrix.zy; + zz = theMatrix.zz; + } + + public void setIdentity() { + xx = 1.0f; + xy = 0.0f; + xz = 0.0f; + yx = 0.0f; + yy = 1.0f; + yz = 0.0f; + zx = 0.0f; + zy = 0.0f; + zz = 1.0f; + } + + public final void setZero() { + xx = 0.0f; + xy = 0.0f; + xz = 0.0f; + yx = 0.0f; + yy = 0.0f; + yz = 0.0f; + zx = 0.0f; + zy = 0.0f; + zz = 0.0f; + } + + public void add(float theValue) { + xx += theValue; + xy += theValue; + xz += theValue; + yx += theValue; + yy += theValue; + yz += theValue; + zx += theValue; + zy += theValue; + zz += theValue; + } + + public void add(Matrix3f theMatrixA, + Matrix3f theMatrixB) { + xx = theMatrixA.xx + theMatrixB.xx; + xy = theMatrixA.xy + theMatrixB.xy; + xz = theMatrixA.xz + theMatrixB.xz; + yx = theMatrixA.yx + theMatrixB.yx; + yy = theMatrixA.yy + theMatrixB.yy; + yz = theMatrixA.yz + theMatrixB.yz; + zx = theMatrixA.zx + theMatrixB.zx; + zy = theMatrixA.zy + theMatrixB.zy; + zz = theMatrixA.zz + theMatrixB.zz; + } + + public void add(Matrix3f theMatrix) { + xx += theMatrix.xx; + xy += theMatrix.xy; + xz += theMatrix.xz; + yx += theMatrix.yx; + yy += theMatrix.yy; + yz += theMatrix.yz; + zx += theMatrix.zx; + zy += theMatrix.zy; + zz += theMatrix.zz; + } + + public void sub(Matrix3f theMatrixA, + Matrix3f theMatrixB) { + xx = theMatrixA.xx - theMatrixB.xx; + xy = theMatrixA.xy - theMatrixB.xy; + xz = theMatrixA.xz - theMatrixB.xz; + yx = theMatrixA.yx - theMatrixB.yx; + yy = theMatrixA.yy - theMatrixB.yy; + yz = theMatrixA.yz - theMatrixB.yz; + zx = theMatrixA.zx - theMatrixB.zx; + zy = theMatrixA.zy - theMatrixB.zy; + zz = theMatrixA.zz - theMatrixB.zz; + } + + public void sub(Matrix3f theMatrix) { + xx -= theMatrix.xx; + xy -= theMatrix.xy; + xz -= theMatrix.xz; + yx -= theMatrix.yx; + yy -= theMatrix.yy; + yz -= theMatrix.yz; + zx -= theMatrix.zx; + zy -= theMatrix.zy; + zz -= theMatrix.zz; + } + + public void transpose() { + + /* + * NOTE if the matrix is a rotation matrix ie the determinant is 1, the + * transpose is equivalent to the invers of the matrix. + */ + + float mySwap = yx; + yx = xy; + xy = mySwap; + mySwap = zx; + zx = xz; + xz = mySwap; + mySwap = zy; + zy = yz; + yz = mySwap; + } + + public void transpose(Matrix3f theMatrix) { + if (this != theMatrix) { + xx = theMatrix.xx; + xy = theMatrix.yx; + xz = theMatrix.zx; + yx = theMatrix.xy; + yy = theMatrix.yy; + yz = theMatrix.zy; + zx = theMatrix.xz; + zy = theMatrix.yz; + zz = theMatrix.zz; + } else { + transpose(); + } + } + + public final float determinant() { + return xx * (yy * zz - yz * zy) + xy * (yz * zx - yx * zz) + xz * (yx * zy - yy * zx); + } + + public final void invert() { + float myDeterminant = determinant(); + if (myDeterminant == 0.0) { + return; + } + myDeterminant = 1 / myDeterminant; + set(yy * zz - zy * yz, + zx * yz - yx * zz, + yx * zy - zx * yy, + zy * xz - xy * zz, + xx * zz - zx * xz, + zx * xy - xx * zy, + xy * yz - yy * xz, + yx * xz - xx * yz, + xx * yy - yx * xy); + multiply(myDeterminant); + } + + public final void setXAxis(Vector3f theVector) { + xx = theVector.x; + yx = theVector.y; + zx = theVector.z; + } + + public final void setYAxis(Vector3f theVector) { + xy = theVector.x; + yy = theVector.y; + zy = theVector.z; + } + + public final void setZAxis(Vector3f theVector) { + xz = theVector.x; + yz = theVector.y; + zz = theVector.z; + } + + public final void getXAxis(Vector3f theVector) { + theVector.x = xx; + theVector.y = yx; + theVector.z = zx; + } + + public final void getYAxis(Vector3f theVector) { + theVector.x = xy; + theVector.y = yy; + theVector.z = zy; + } + + public final void getZAxis(Vector3f theVector) { + theVector.x = xz; + theVector.y = yz; + theVector.z = zz; + } + + public final Vector3f getXAxis() { + return new Vector3f(xx, yx, zx); + } + + public final Vector3f getYAxis() { + return new Vector3f(xy, yy, zy); + } + + public final Vector3f getZAxis() { + return new Vector3f(xz, yz, zz); + } + + public final void setXRotation(float theRadians) { + float sin = (float) Math.sin(theRadians); + float cos = (float) Math.cos(theRadians); + + xx = 1.0f; + yx = 0.0f; + zx = 0.0f; + + xy = 0.0f; + yy = cos; + zy = sin; + + xz = 0.0f; + yz = -sin; + zz = cos; + } + + public final void setYRotation(float theRadians) { + + /** + * @todo check why these differ from 'the matrix and quaternions faq' + * + * cos 0 sin(!) 0 1 0 -sin(!) 0 cos + * + */ + float sin = (float) Math.sin(theRadians); + float cos = (float) Math.cos(theRadians); + + xx = cos; + yx = 0.0f; + zx = -sin; + + xy = 0.0f; + yy = 1.0f; + zy = 0.0f; + + xz = sin; + yz = 0.0f; + zz = cos; + } + + public final void setZRotation(float theRadians) { + float sin = (float) Math.sin(theRadians); + float cos = (float) Math.cos(theRadians); + + xx = cos; + yx = sin; + zx = 0.0f; + + xy = -sin; + yy = cos; + zy = 0.0f; + + xz = 0.0f; + yz = 0.0f; + zz = 1.0f; + } + + public final void setXYZRotation(Vector3f theRotation) { + setXYZRotation(theRotation.x, + theRotation.y, + theRotation.z); + } + + public final void setXYZRotation(float theX, + float theY, + float theZ) { + /* using radiants */ + final float a = (float) Math.cos(theX); + final float b = (float) Math.sin(theX); + final float c = (float) Math.cos(theY); + final float d = (float) Math.sin(theY); + final float e = (float) Math.cos(theZ); + final float f = (float) Math.sin(theZ); + + final float ad = a * d; + final float bd = b * d; + + xx = c * e; + yx = bd * e + a * f; + zx = -ad * e + b * f; + + xy = -c * f; + yy = -bd * f + a * e; + zy = ad * f + b * e; + + xz = d; + yz = -b * c; + zz = a * c; + } + + public final void setRotation(final Vector4f theRotation) { + final float u = theRotation.x; + final float v = theRotation.y; + final float w = theRotation.z; + + final float rcos = (float) Math.cos(theRotation.w); + final float rsin = (float) Math.sin(theRotation.w); + + xx = rcos + u * u * (1 - rcos); + yx = w * rsin + v * u * (1 - rcos); + zx = -v * rsin + w * u * (1 - rcos); + + xy = -w * rsin + u * v * (1 - rcos); + yy = rcos + v * v * (1 - rcos); + zy = u * rsin + w * v * (1 - rcos); + + xz = v * rsin + u * w * (1 - rcos); + yz = -u * rsin + v * w * (1 - rcos); + zz = rcos + w * w * (1 - rcos); + } + + public final void multiply(float theValue) { + xx *= theValue; + xy *= theValue; + xz *= theValue; + yx *= theValue; + yy *= theValue; + yz *= theValue; + zx *= theValue; + zy *= theValue; + zz *= theValue; + } + + public final void multiply(Matrix3f theMatrix) { + float tmp1 = xx * theMatrix.xx + xy * theMatrix.yx + xz * theMatrix.zx; + float tmp2 = xx * theMatrix.xy + xy * theMatrix.yy + xz * theMatrix.zy; + float tmp3 = xx * theMatrix.xz + xy * theMatrix.yz + xz * theMatrix.zz; + float tmp4 = yx * theMatrix.xx + yy * theMatrix.yx + yz * theMatrix.zx; + float tmp5 = yx * theMatrix.xy + yy * theMatrix.yy + yz * theMatrix.zy; + float tmp6 = yx * theMatrix.xz + yy * theMatrix.yz + yz * theMatrix.zz; + float tmp7 = zx * theMatrix.xx + zy * theMatrix.yx + zz * theMatrix.zx; + float tmp8 = zx * theMatrix.xy + zy * theMatrix.yy + zz * theMatrix.zy; + float tmp9 = zx * theMatrix.xz + zy * theMatrix.yz + zz * theMatrix.zz; + xx = tmp1; + xy = tmp2; + xz = tmp3; + yx = tmp4; + yy = tmp5; + yz = tmp6; + zx = tmp7; + zy = tmp8; + zz = tmp9; + } + + public final void transform(Vector3f theVector) { + theVector.set(xx * theVector.x + yx * theVector.y + zx * theVector.z, + xy * theVector.x + yy * theVector.y + zy * theVector.z, + theVector.z = xz * theVector.x + yz * theVector.y + zz * theVector.z); + } + + public void setScale(Vector3f theScale) { + xx = theScale.x; + yx = 0.0f; + zx = 0.0f; + + xy = 0.0f; + yy = theScale.y; + zy = 0.0f; + + xz = 0.0f; + yz = 0.0f; + zz = theScale.z; + } + + public final float[] toArray() { + _myArrayRepresentation[0] = xx; + _myArrayRepresentation[1] = yx; + _myArrayRepresentation[2] = zx; + _myArrayRepresentation[3] = xy; + _myArrayRepresentation[4] = yy; + _myArrayRepresentation[5] = zy; + _myArrayRepresentation[6] = xz; + _myArrayRepresentation[7] = yz; + _myArrayRepresentation[8] = zz; + return _myArrayRepresentation; + } + + public final float[] toArray4f() { + /* so that opengl can understand it */ + _myArray4fRepresentation[0] = xx; + _myArray4fRepresentation[1] = yx; + _myArray4fRepresentation[2] = zx; + _myArray4fRepresentation[3] = 0; + _myArray4fRepresentation[4] = xy; + _myArray4fRepresentation[5] = yy; + _myArray4fRepresentation[6] = zy; + _myArray4fRepresentation[7] = 0; + _myArray4fRepresentation[8] = xz; + _myArray4fRepresentation[9] = yz; + _myArray4fRepresentation[10] = zz; + _myArray4fRepresentation[11] = 0; + _myArray4fRepresentation[12] = 0; + _myArray4fRepresentation[13] = 0; + _myArray4fRepresentation[14] = 0; + _myArray4fRepresentation[15] = 1; + return _myArray4fRepresentation; + } + + public String toString() { + return xx + ", " + yx + ", " + zx + "\n" + xy + ", " + yy + ", " + zy + "\n" + xz + ", " + yz + ", " + zz; + } + + public static void main(String[] args) { + Matrix3f myMatrix; + + { + /* invert and transpose */ + + System.out.println("### invert and transpose\n"); + + myMatrix = new Matrix3f(Matrix3f.IDENTITY); + myMatrix.setXYZRotation(new Vector3f(0.2f, 0.3f, 0.4f)); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.transpose(); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.transpose(); + System.out.println(myMatrix); + System.out.println(); + + myMatrix = new Matrix3f(Matrix3f.IDENTITY); + myMatrix.setXYZRotation(new Vector3f(0.2f, 0.3f, 0.4f)); + + myMatrix.invert(); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.invert(); + System.out.println(myMatrix); + System.out.println(); + } + + { + /* x */ + + myMatrix = new Matrix3f(Matrix3f.IDENTITY); + + System.out.println("### rotation x\n"); + + myMatrix.setXYZRotation(new Vector3f(0.2f, 0.0f, 0.0f)); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.setXRotation(0.2f); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.setRotation(new Vector4f(1, 0, 0, 0.2f)); + System.out.println(myMatrix); + System.out.println(); + + /* y */ + + System.out.println("### rotation y\n"); + + myMatrix.setXYZRotation(new Vector3f(0.0f, 0.3f, 0.0f)); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.setYRotation(0.3f); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.setRotation(new Vector4f(0, 1, 0, 0.3f)); + System.out.println(myMatrix); + System.out.println(); + + /* z */ + + System.out.println("### rotation z\n"); + + myMatrix.setXYZRotation(new Vector3f(0.0f, 0.0f, 0.4f)); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.setZRotation(0.4f); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.setRotation(new Vector4f(0, 0, 1, 0.4f)); + System.out.println(myMatrix); + System.out.println(); + } + } +} diff --git a/day3/libs/mathematik/src/mathematik/Matrix4f.java b/day3/libs/mathematik/src/mathematik/Matrix4f.java new file mode 100755 index 0000000..9456358 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Matrix4f.java @@ -0,0 +1,433 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +/** + * a more general 4x4 matrix. + * + * xx yx zx wx xy yy zy wy xz yz zz wz xw yw zw ww + * + * also read 'The Matrix and Quaternions FAQ' at + * http://www.flipcode.com/documents/matrfaq.html + */ +package mathematik; + + +import java.io.Serializable; + + +public class Matrix4f + implements Serializable { + + private static final long serialVersionUID = -1088603850006298206L; + + public float xx; + + public float xy; + + public float xz; + + public float xw; + + public float yx; + + public float yy; + + public float yz; + + public float yw; + + public float zx; + + public float zy; + + public float zz; + + public float zw; + + public float wx; + + public float wy; + + public float wz; + + public float ww; + + private final float[] _myArrayRepresentation = new float[16]; + + public Matrix4f() { + } + + public Matrix4f(TransformMatrix4f theTransformMatrix) { + xx = theTransformMatrix.rotation.xx; + yx = theTransformMatrix.rotation.yx; + zx = theTransformMatrix.rotation.zx; + wx = 0; + + xy = theTransformMatrix.rotation.xy; + yy = theTransformMatrix.rotation.yy; + zy = theTransformMatrix.rotation.zy; + wy = 0; + + xz = theTransformMatrix.rotation.xz; + yz = theTransformMatrix.rotation.yz; + zz = theTransformMatrix.rotation.zz; + wz = 0; + + xw = theTransformMatrix.translation.x; + yw = theTransformMatrix.translation.y; + zw = theTransformMatrix.translation.z; + ww = 1; + } + + public Matrix4f(Matrix4f theTransformMatrix) { + xx = theTransformMatrix.xx; + yx = theTransformMatrix.yx; + zx = theTransformMatrix.zx; + wx = theTransformMatrix.wx; + + xy = theTransformMatrix.xy; + yy = theTransformMatrix.yy; + zy = theTransformMatrix.zy; + wy = theTransformMatrix.wy; + + xz = theTransformMatrix.xz; + yz = theTransformMatrix.yz; + zz = theTransformMatrix.zz; + wz = theTransformMatrix.wz; + + xw = theTransformMatrix.xw; + yw = theTransformMatrix.yw; + zw = theTransformMatrix.zw; + ww = theTransformMatrix.ww; + } + + public Matrix4f(float[] theMatrix) { + set(theMatrix); + } + + public Matrix4f(double[] theMatrix) { + set(theMatrix); + } + + public Matrix4f(float xx, + float yx, + float zx, + float wx, + float xy, + float yy, + float zy, + float wy, + float xz, + float yz, + float zz, + float wz, + float xw, + float yw, + float zw, + float ww) { + this.xx = xx; + this.xy = xy; + this.xz = xz; + this.xw = xw; + + this.yx = yx; + this.yy = yy; + this.yz = yz; + this.yw = yw; + + this.zx = zx; + this.zy = zy; + this.zz = zz; + this.zw = zw; + + this.wx = wx; + this.wy = wy; + this.wz = wz; + this.ww = ww; + } + + public void set(float[] theMatrix) { + xx = theMatrix[0]; + yx = theMatrix[1]; + zx = theMatrix[2]; + wx = theMatrix[3]; + + xy = theMatrix[4]; + yy = theMatrix[5]; + zy = theMatrix[6]; + wy = theMatrix[7]; + + xz = theMatrix[8]; + yz = theMatrix[9]; + zz = theMatrix[10]; + wz = theMatrix[11]; + + xw = theMatrix[12]; + yw = theMatrix[13]; + zw = theMatrix[14]; + ww = theMatrix[15]; + } + + public void set(double[] theMatrix) { + xx = (float) theMatrix[0]; + yx = (float) theMatrix[1]; + zx = (float) theMatrix[2]; + wx = (float) theMatrix[3]; + + xy = (float) theMatrix[4]; + yy = (float) theMatrix[5]; + zy = (float) theMatrix[6]; + wy = (float) theMatrix[7]; + + xz = (float) theMatrix[8]; + yz = (float) theMatrix[9]; + zz = (float) theMatrix[10]; + wz = (float) theMatrix[11]; + + xw = (float) theMatrix[12]; + yw = (float) theMatrix[13]; + zw = (float) theMatrix[14]; + ww = (float) theMatrix[15]; + } + + public void set(float xx, + float yx, + float zx, + float wx, + float xy, + float yy, + float zy, + float wy, + float xz, + float yz, + float zz, + float wz, + float xw, + float yw, + float zw, + float ww) { + this.xx = xx; + this.xy = xy; + this.xz = xz; + this.xw = xw; + + this.yx = yx; + this.yy = yy; + this.yz = yz; + this.yw = yw; + + this.zx = zx; + this.zy = zy; + this.zz = zz; + this.zw = zw; + + this.wx = wx; + this.wy = wy; + this.wz = wz; + this.ww = ww; + } + + public void invert() { + float myDeterminant = determinant(); + if (myDeterminant == 0.0) { + return; + } + myDeterminant = 1 / myDeterminant; + set(yy * (zz * ww - zw * wz) + yz * (zw * wy - zy * ww) + yw * (zy * wz - zz * wy), + zy * (xz * ww - xw * wz) + zz * (xw * wy - xy * ww) + zw * (xy * wz - xz * wy), + wy * (xz * yw - xw * yz) + wz * (xw * yy - xy * yw) + ww * (xy * yz - xz * yy), + xy * (yw * zz - yz * zw) + xz * (yy * zw - yw * zy) + xw * (yz * zy - yy * zz), + yz * (zx * ww - zw * wx) + yw * (zz * wx - zx * wz) + yx * (zw * wz - zz * ww), + zz * (xx * ww - xw * wx) + zw * (xz * wx - xx * wz) + zx * (xw * wz - xz * ww), + wz * (xx * yw - xw * yx) + ww * (xz * yx - xx * yz) + wx * (xw * yz - xz * yw), + xz * (yw * zx - yx * zw) + xw * (yx * zz - yz * zx) + xx * (yz * zw - yw * zz), + yw * (zx * wy - zy * wx) + yx * (zy * ww - zw * wy) + yy * (zw * wx - zx * ww), + zw * (xx * wy - xy * wx) + zx * (xy * ww - xw * wy) + zy * (xw * wx - xx * ww), + ww * (xx * yy - xy * yx) + wx * (xy * yw - xw * yy) + wy * (xw * yx - xx * yw), + xw * (yy * zx - yx * zy) + xx * (yw * zy - yy * zw) + xy * (yx * zw - yw * zx), + yx * (zz * wy - zy * wz) + yy * (zx * wz - zz * wx) + yz * (zy * wx - zx * wy), + zx * (xz * wy - xy * wz) + zy * (xx * wz - xz * wx) + zz * (xy * wx - xx * wy), + wx * (xz * yy - xy * yz) + wy * (xx * yz - xz * yx) + wz * (xy * yx - xx * yy), + xx * (yy * zz - yz * zy) + xy * (yz * zx - yx * zz) + xz * (yx * zy - yy * zx)); + + multiply(myDeterminant); + } + + public void multiply(float scalar) { + xx *= scalar; + xy *= scalar; + xz *= scalar; + xw *= scalar; + yx *= scalar; + yy *= scalar; + yz *= scalar; + yw *= scalar; + zx *= scalar; + zy *= scalar; + zz *= scalar; + zw *= scalar; + wx *= scalar; + wy *= scalar; + wz *= scalar; + ww *= scalar; + } + + public final void multiply(Matrix4f theMatrix) { + multiply(this, + theMatrix); + } + + public final void multiply(Matrix4f theA, + Matrix4f theB) { + /** + * @todo here we still have an ugly bug :( + */ + set(theA.xx * theB.xx + theA.yx * theB.xy + theA.zx * theB.xz + theA.wx * theB.xw, + theA.xx * theB.yx + theA.yx * theB.yy + theA.zx * theB.yz + theA.wx * theB.yw, + theA.xx * theB.zx + theA.yx * theB.zy + theA.zx * theB.zz + theA.wx * theB.zw, + theA.xx * theB.wx + theA.yx * theB.wy + theA.zx * theB.wz + theA.wx * theB.ww, + theA.xy * theB.xx + theA.yy * theB.xy + theA.zy * theB.xz + theA.wy * theB.xw, + theA.xy * theB.yx + theA.yy * theB.yy + theA.zy * theB.yz + theA.wy * theB.yw, + theA.xy * theB.zx + theA.yy * theB.zy + theA.zy * theB.zz + theA.wy * theB.zw, + theA.xy * theB.wx + theA.yy * theB.wy + theA.zy * theB.wz + theA.wy * theB.ww, + theA.xz * theB.xx + theA.yz * theB.xy + theA.zz * theB.xz + theA.wz * theB.xw, + theA.xz * theB.yx + theA.yz * theB.yy + theA.zz * theB.yz + theA.wz * theB.yw, + theA.xz * theB.zx + theA.yz * theB.zy + theA.zz * theB.zz + theA.wz * theB.zw, + theA.xz * theB.wx + theA.yz * theB.wy + theA.zz * theB.wz + theA.wz * theB.ww, + theA.xw * theB.xx + theA.yw * theB.xy + theA.zw * theB.xz + theA.ww * theB.xw, + theA.xw * theB.yx + theA.yw * theB.yy + theA.zw * theB.yz + theA.ww * theB.yw, + theA.xw * theB.zx + theA.yw * theB.zy + theA.zw * theB.zz + theA.ww * theB.zw, + theA.xw * theB.wx + theA.yw * theB.wy + theA.zw * theB.wz + theA.ww * theB.ww); + } + + public float determinant() { + /** + * @todo check if this is correct + */ + return (xx * yy - xy * yx) * (zz * ww - zw * wz) - (xx * yz - xz * yx) * (zy * ww - zw * wy) + + (xx * yw - xw * yx) * (zy * wz - zz * wy) + (xy * yz - xz * yy) * (zx * ww - zw * wx) + - (xy * yw - xw * yy) * (zx * wz - zz * wx) + (xz * yw - xw * yz) * (zx * wy - zy * wx); + } + + public final void transform(Vector3f theResult) { + theResult.set(xx * theResult.x + xy * theResult.y + xz * theResult.z + xw, + yx * theResult.x + yy * theResult.y + yz * theResult.z + yw, + zx * theResult.x + zy * theResult.y + zz * theResult.z + zw); + } + + public final void transform(Vector4f theVector) { + theVector.set(xx * theVector.x + xy * theVector.y + xz * theVector.z + xw * theVector.w, + yx * theVector.x + yy * theVector.y + yz * theVector.z + yw * theVector.w, + zx * theVector.x + zy * theVector.y + zz * theVector.z + zw * theVector.w, + wx * theVector.x + wy * theVector.y + wz * theVector.z + ww * theVector.w); + } + + public float[] toArray() { + /* opengl format */ + _myArrayRepresentation[0] = xx; + _myArrayRepresentation[1] = yx; + _myArrayRepresentation[2] = zx; + _myArrayRepresentation[3] = wx; + + _myArrayRepresentation[4] = xy; + _myArrayRepresentation[5] = yy; + _myArrayRepresentation[6] = zy; + _myArrayRepresentation[7] = wy; + + _myArrayRepresentation[8] = xz; + _myArrayRepresentation[9] = yz; + _myArrayRepresentation[10] = zz; + _myArrayRepresentation[11] = wz; + + _myArrayRepresentation[12] = wx; + _myArrayRepresentation[13] = wy; + _myArrayRepresentation[14] = wz; + _myArrayRepresentation[15] = ww; + return _myArrayRepresentation; + } + + public final void transpose() { + float swap = yx; + yx = xy; + xy = swap; + swap = zx; + zx = xz; + xz = swap; + swap = wx; + wx = xw; + xw = swap; + swap = zy; + zy = yz; + yz = swap; + swap = wy; + wy = yw; + yw = swap; + swap = wz; + wz = zw; + zw = swap; + } + + public String toString() { + return xx + ", " + yx + ", " + zx + ", " + wx + "\n" + xy + ", " + yy + ", " + zy + ", " + wy + "\n" + xz + + ", " + yz + ", " + zz + ", " + wz + "\n" + xw + ", " + yw + ", " + zw + ", " + ww; + } + + public static void main(String[] args) { + TransformMatrix4f myTransMatrix = new TransformMatrix4f(TransformMatrix4f.IDENTITY); + myTransMatrix.rotation.setXYZRotation(new Vector3f(0.2f, 0.3f, 0.4f)); + myTransMatrix.translation.set(2, + 3, + 4); + + System.out.println("### transform matrix\n"); + + System.out.println(myTransMatrix); + System.out.println(); + + Matrix4f myMatrix = new Matrix4f(myTransMatrix); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.invert(); + System.out.println(myMatrix); + System.out.println(); + + myMatrix.invert(); + System.out.println(myMatrix); + System.out.println(); + + /* transform */ + Vector3f myVector3f = new Vector3f(5, 8, 7); + Vector4f myVector4f = new Vector4f(5, 8, 7, 1); + Vector3f myVectorOther3f = new Vector3f(5, 8, 7); + + System.out.println(); + + myMatrix.transform(myVector3f); + System.out.println(myVector3f); + + myMatrix.transform(myVector4f); + System.out.println(myVector4f); + + myTransMatrix.transform(myVectorOther3f); + System.out.println(myVectorOther3f); + } +} diff --git a/day3/libs/mathematik/src/mathematik/PerlinNoise.java b/day3/libs/mathematik/src/mathematik/PerlinNoise.java new file mode 100755 index 0000000..f327a02 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/PerlinNoise.java @@ -0,0 +1,178 @@ +package mathematik; + + +import java.util.Random; + + +public abstract class PerlinNoise { + + ////////////////////////////////////////////////////////////// + // PERLIN NOISE + // [toxi 040903] + // octaves and amplitude amount per octave are now user controlled + // via the noiseDetail() function. + // [toxi 030902] + // cleaned up code and now using bagel's cosine table to speed up + // [toxi 030901] + // implementation by the german demo group farbrausch + // as used in their demo "art": http://www.farb-rausch.de/fr010src.zip + static final int PERLIN_YWRAPB = 4; + + static final int PERLIN_YWRAP = 1 << PERLIN_YWRAPB; + + static final int PERLIN_ZWRAPB = 8; + + static final int PERLIN_ZWRAP = 1 << PERLIN_ZWRAPB; + + static final int PERLIN_SIZE = 4095; + + static int perlin_octaves = 4; // default to medium smooth + + static float perlin_amp_falloff = 0.5f; // 50% reduction/octave + + // [toxi 031112] + // new vars needed due to recent change of cos table in PGraphics + static int perlin_TWOPI, perlin_PI; + + static float[] perlin_cosTable; + + static float[] perlin; + + static Random perlinRandom; + + public static int SEED = 0; + + /** + * Computes the Perlin noise function value at point x. + */ + public static float noise(float x) { + // is this legit? it's a dumb way to do it (but repair it later) + return noise(x, 0f, 0f); + } + + /** + * Computes the Perlin noise function value at the point x, y. + */ + public static float noise(float x, float y) { + return noise(x, y, 0f); + } + + public static float noise(float x, float y, float z) { + if (perlin == null) { + if (perlinRandom == null) { + perlinRandom = new Random(SEED); + } + perlin = new float[PERLIN_SIZE + 1]; + for (int i = 0; i < PERLIN_SIZE + 1; i++) { + perlin[i] = perlinRandom.nextFloat(); //(float)Math.random(); + } + // [toxi 031112] + // noise broke due to recent change of cos table in PGraphics + // this will take care of it + perlin_cosTable = cosLUT; + perlin_TWOPI = perlin_PI = SINCOS_LENGTH; + perlin_PI >>= 1; + } + + if (x < 0) { + x = -x; + } + if (y < 0) { + y = -y; + } + if (z < 0) { + z = -z; + } + + int xi = (int) x, yi = (int) y, zi = (int) z; + float xf = (float) (x - xi); + float yf = (float) (y - yi); + float zf = (float) (z - zi); + float rxf, ryf; + + float r = 0; + float ampl = 0.5f; + + float n1, n2, n3; + + for (int i = 0; i < perlin_octaves; i++) { + int of = xi + (yi << PERLIN_YWRAPB) + (zi << PERLIN_ZWRAPB); + + rxf = noise_fsc(xf); + ryf = noise_fsc(yf); + + n1 = perlin[of & PERLIN_SIZE]; + n1 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n1); + n2 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; + n2 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n2); + n1 += ryf * (n2 - n1); + + of += PERLIN_ZWRAP; + n2 = perlin[of & PERLIN_SIZE]; + n2 += rxf * (perlin[(of + 1) & PERLIN_SIZE] - n2); + n3 = perlin[(of + PERLIN_YWRAP) & PERLIN_SIZE]; + n3 += rxf * (perlin[(of + PERLIN_YWRAP + 1) & PERLIN_SIZE] - n3); + n2 += ryf * (n3 - n2); + + n1 += noise_fsc(zf) * (n2 - n1); + + r += n1 * ampl; + ampl *= perlin_amp_falloff; + xi <<= 1; + xf *= 2; + yi <<= 1; + yf *= 2; + zi <<= 1; + zf *= 2; + + if (xf >= 1.0f) { + xi++; + xf--; + } + if (yf >= 1.0f) { + yi++; + yf--; + } + if (zf >= 1.0f) { + zi++; + zf--; + } + } + return r; + } + + // [toxi 031112] + // now adjusts to the size of the cosLUT used via + // the new variables, defined above + private static float noise_fsc(float i) { + // using bagel's cosine table instead + return 0.5f * (1.0f - perlin_cosTable[(int) (i * perlin_PI) % perlin_TWOPI]); + } + // precalculate sin/cos lookup tables [toxi] + // circle resolution is determined from the actual used radii + // passed to ellipse() method. this will automatically take any + // scale transformations into account too + // [toxi 031031] + // changed table's precision to 0.5 degree steps + // introduced new vars for more flexible code + static final protected float sinLUT[]; + + static final protected float cosLUT[]; + + static final protected float SINCOS_PRECISION = 0.5f; + + static final protected int SINCOS_LENGTH = (int) (360f / SINCOS_PRECISION); + + static final float DEG_TO_RAD = (float) Math.PI / 180.0f; + + static final float RAD_TO_DEG = 180.0f / (float) Math.PI; + + static { + sinLUT = new float[SINCOS_LENGTH]; + cosLUT = new float[SINCOS_LENGTH]; + for (int i = 0; i < SINCOS_LENGTH; i++) { + sinLUT[i] = (float) Math.sin(i * DEG_TO_RAD * SINCOS_PRECISION); + cosLUT[i] = (float) Math.cos(i * DEG_TO_RAD * SINCOS_PRECISION); + } + } +} diff --git a/day3/libs/mathematik/src/mathematik/Plane3f.java b/day3/libs/mathematik/src/mathematik/Plane3f.java new file mode 100755 index 0000000..1fd877f --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Plane3f.java @@ -0,0 +1,87 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +public class Plane3f + implements Serializable { + + private static final long serialVersionUID = 2390391570305327484L; + + public Vector3f origin; + + public Vector3f vectorA; + + public Vector3f vectorB; + + /** + * these fields are not used by default and left uninitialized 'null' + */ + public Vector3f normal; + + public float d = Float.NaN; + + public Plane3f() { + origin = new Vector3f(); + vectorA = new Vector3f(); + vectorB = new Vector3f(); + } + + public Plane3f(Vector3f theOrigin, + Vector3f theVectorA, + Vector3f theVectorB) { + origin = theOrigin; + vectorA = theVectorA; + vectorB = theVectorB; + } + + public void updateNormal() { + if (normal == null) { + normal = new Vector3f(); + } + Util.calculateNormal(vectorA, vectorB, normal); + } + + public void updateD() { + if (normal != null) { + d = -normal.dot(origin); + } + } +// private float intersection(Vector3f a, Vector3f b) { +// /* +// * updateNormal(); +// * updateD(); +// */ +// +// float u = normal.x * a.x + +// normal.y * a.y + +// normal.z * a.z + +// d; +// u /= normal.x * (a.x - b.x) + +// normal.y * (a.y - b.y) + +// normal.z * (a.z - b.z); +// return u; +// } +} diff --git a/day3/libs/mathematik/src/mathematik/Quaternion.java b/day3/libs/mathematik/src/mathematik/Quaternion.java new file mode 100755 index 0000000..1bac311 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Quaternion.java @@ -0,0 +1,89 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +public class Quaternion { + + public float w; + + public float x; + + public float y; + + public float z; + + public Quaternion() { + reset(); + } + + public Quaternion(float theW, float theX, float theY, float theZ) { + w = theW; + x = theX; + y = theY; + z = theZ; + } + + public void reset() { + w = 1.0f; + x = 0.0f; + y = 0.0f; + z = 0.0f; + } + + public void set(float theW, Vector3f theVector3f) { + w = theW; + x = theVector3f.x; + y = theVector3f.y; + z = theVector3f.z; + } + + public void set(Quaternion theQuaternion) { + w = theQuaternion.w; + x = theQuaternion.x; + y = theQuaternion.y; + z = theQuaternion.z; + } + + public void multiply(Quaternion theA, Quaternion theB) { + w = theA.w * theB.w - theA.x * theB.x - theA.y * theB.y - theA.z * theB.z; + x = theA.w * theB.x + theA.x * theB.w + theA.y * theB.z - theA.z * theB.y; + y = theA.w * theB.y + theA.y * theB.w + theA.z * theB.x - theA.x * theB.z; + z = theA.w * theB.z + theA.z * theB.w + theA.x * theB.y - theA.y * theB.x; + } + + public Vector4f getVectorAndAngle() { + final Vector4f theResult = new Vector4f(); + + float s = (float) Math.sqrt(1.0f - w * w); + if (s < Mathematik.EPSILON) { + s = 1.0f; + } + + theResult.w = (float) Math.acos(w) * 2.0f; + theResult.x = x / s; + theResult.y = y / s; + theResult.z = z / s; + + return theResult; + } +} diff --git a/day3/libs/mathematik/src/mathematik/Random.java b/day3/libs/mathematik/src/mathematik/Random.java new file mode 100755 index 0000000..5873716 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Random.java @@ -0,0 +1,154 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +/** + * generate random numbers.
+ * note that if different types are requested the random generator moves on + * anyway. + */ +public class Random + implements Serializable { + + private static final long serialVersionUID = -5871934750136232555L; + + private static final java.util.Random _mySeedGenerator = new java.util.Random(System.currentTimeMillis()); + + private final java.util.Random myRandomNumberGenerator; + + private static final Random _myInstance; + + static { + _myInstance = new Random(); + } + + public static float FLOAT(float theStart, float theEnd) { + return _myInstance.getFloat(theStart, theEnd); + } + + public static float INT(int theStart, int theEnd) { + return _myInstance.getInt(theStart, theEnd); + } + + public Random() { + this(_mySeedGenerator.nextLong()); + } + + public Random(long theSeed) { + myRandomNumberGenerator = new java.util.Random(theSeed); + } + + public void setSeed(long theSeed) { + myRandomNumberGenerator.setSeed(theSeed); + } + + /** + * return a random int value from theStart to theEnd, including both values. + * + * @param theStart int + * @param theEnd int + * @return int + */ + public int getInt(int theStart, + int theEnd) { + int myDiff = (theEnd + 1) - theStart; + return myRandomNumberGenerator.nextInt(myDiff) + theStart; + } + + public int getInt() { + return myRandomNumberGenerator.nextInt(); + } + + /** + * return a random float value from theStart to theEnd, excluding both + * values. + * + * @param theStart float + * @param theEnd float + * @return float + */ + public float getFloat(float theStart, + float theEnd) { + final float myDiff = theEnd - theStart; + final float myRandomValue = myRandomNumberGenerator.nextFloat() * myDiff; + return myRandomValue + theStart; + } + + public float getFloat() { + return myRandomNumberGenerator.nextFloat(); + } + +// public static float getFloat(float theStart, +// float theEnd) { +// return _mySeedGenerator.getFloat(theStart, theEnd); +// } + public Vector3f getVector3f(float theStart, float theEnd) { + return new Vector3f(getFloat(theStart, theEnd), + getFloat(theStart, theEnd), + getFloat(theStart, theEnd)); + } + + public static void main(String[] args) { + long myTime; + Random myRandom; + + myRandom = new Random(); + System.out.println(myRandom.getFloat(20, 100)); + System.out.println(myRandom.getFloat(20, 100)); + System.out.println(myRandom.getFloat(20, 100)); + System.out.println(myRandom.getFloat(20, 100)); + System.out.println("***"); + + myRandom = new Random(); + System.out.println(myRandom.getFloat(20, 100)); + System.out.println(myRandom.getInt(20, 100)); + System.out.println(myRandom.getFloat(20, 100)); + System.out.println(myRandom.getFloat(20, 100)); + System.out.println("***"); + + /* use this random generator */ + myTime = System.currentTimeMillis(); + myRandom = new Random(0); + for (int i = 0; i < 50000000; i++) { + float myValue = myRandom.getFloat(20, 100); + if (myValue < 20 || myValue > 100) { + System.out.println(i + "ERROR"); + } + } + System.out.println("DONE: " + (System.currentTimeMillis() - myTime)); + + /* use maths random generator */ + myTime = System.currentTimeMillis(); + for (int i = 0; i < 50000000; i++) { + float myValue = (float) Math.random() * (100 - 20) + 20; + if (myValue < 20 || myValue > 100) { + System.out.println(i + "ERROR"); + } + } + System.out.println("DONE: " + (System.currentTimeMillis() - myTime)); + + } +} diff --git a/day3/libs/mathematik/src/mathematik/Ray3f.java b/day3/libs/mathematik/src/mathematik/Ray3f.java new file mode 100755 index 0000000..745ea73 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Ray3f.java @@ -0,0 +1,51 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +public class Ray3f + implements Serializable { + + private static final long serialVersionUID = -1748179277316146625L; + + public Vector3f origin; + + public Vector3f direction; + + public Ray3f() { + origin = new Vector3f(); + direction = new Vector3f(); + } + + public Ray3f(Vector3f theOrigin, + Vector3f theDirection) { + origin = theOrigin; + direction = theDirection; + } + + public String toString() { + return "origin + " + origin + " / " + " direction " + direction; + } +} diff --git a/day3/libs/mathematik/src/mathematik/Rayf.java b/day3/libs/mathematik/src/mathematik/Rayf.java new file mode 100755 index 0000000..0e15ad2 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Rayf.java @@ -0,0 +1,60 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +/** + * @deprecated + */ +public class Rayf + implements Serializable, Vectorf { + + private static final long serialVersionUID = -1748179277316146234L; + + public T origin; + + public T direction; + + public Rayf(Class theClass) { + try { + origin = theClass.newInstance(); + direction = theClass.newInstance(); + } catch (IllegalAccessException ex) { + ex.printStackTrace(); + } catch (InstantiationException ex) { + ex.printStackTrace(); + } + } + + public Rayf(T theOrigin, + T theDirection) { + origin = theOrigin; + direction = theDirection; + } + + public String toString() { + return "origin + " + origin + " / " + " direction " + direction; + } +} diff --git a/day3/libs/mathematik/src/mathematik/Rectangle3f.java b/day3/libs/mathematik/src/mathematik/Rectangle3f.java new file mode 100755 index 0000000..02dfbce --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Rectangle3f.java @@ -0,0 +1,47 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +public class Rectangle3f + implements Serializable { + + private static final long serialVersionUID = -7295490882726338294L; + + public Vector3f origin; + + public Vector3f scale; + + public Rectangle3f() { + origin = new Vector3f(); + scale = new Vector3f(); + } + + public Rectangle3f(Vector3f theOrigin, + Vector3f theScale) { + origin = theOrigin; + scale = theScale; + } +} diff --git a/day3/libs/mathematik/src/mathematik/Rotation.java b/day3/libs/mathematik/src/mathematik/Rotation.java new file mode 100755 index 0000000..3000443 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Rotation.java @@ -0,0 +1,156 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +/* + * write the current rotation into the result transformation matrix. + * if the velocity sampler is enabled the velocity will averaged + * to avoid jerky turning. + */ +/** + * @todo the sampling would be more accurate if the delta time would also be + * taken into account when updating the sampler. + */ +package mathematik; + + +public class Rotation { + + private Vector3f[] _myVelocitySampler; + + private final Vector3f _myUpVector; + + private final Vector3f _myCurrentAverageVelocity; + + private final Vector3f _myAverageVelocity; + + private int _myVelocitySamplerPosition; + + private final Vector3f _myTempUpVector; + + private final Vector3f _myTempSideVector; + + private final Vector3f _myTempForwardVector; + + public Rotation() { + this(1); + } + + public Rotation(final int theVelocitySamplerSize) { + _myVelocitySamplerPosition = 0; + setVelocitySamplerSize(theVelocitySamplerSize); + _myUpVector = new Vector3f(0, 0, 1); + _myAverageVelocity = new Vector3f(); + _myCurrentAverageVelocity = new Vector3f(); + _myTempUpVector = new Vector3f(); + _myTempSideVector = new Vector3f(); + _myTempForwardVector = new Vector3f(); + } + + public void setVelocitySamplerSize(final int theVelocitySamplerSize) { + _myVelocitySampler = new Vector3f[theVelocitySamplerSize]; + for (int i = 0; i < _myVelocitySampler.length; ++i) { + _myVelocitySampler[i] = new Vector3f(); + } + } + + public void flattenVelocitySampler(final Vector3f theVelocity) { + for (int i = 0; i < _myVelocitySampler.length; i++) { + add(theVelocity); + } + } + + public void add(final Vector3f theVelocity) { + _myVelocitySamplerPosition++; + _myVelocitySamplerPosition %= _myVelocitySampler.length; + _myAverageVelocity.sub(_myVelocitySampler[_myVelocitySamplerPosition]); + _myVelocitySampler[_myVelocitySamplerPosition].set(theVelocity); + _myAverageVelocity.add(theVelocity); + _myCurrentAverageVelocity.set(_myAverageVelocity); + _myCurrentAverageVelocity.scale(1.0f / (float) _myVelocitySampler.length); + } + + public void set(final Vector3f theVelocity, + final TransformMatrix4f theResult) { + if (_myVelocitySampler.length == 1) { + pointAt(theVelocity, theResult); + } else { + add(theVelocity); + pointAt(_myCurrentAverageVelocity, theResult); + } + } + + public void set(final TransformMatrix4f theResult) { + pointAt(_myCurrentAverageVelocity, theResult); + } + + public void set(final Matrix3f theResult) { + pointAt(_myCurrentAverageVelocity, theResult); + } + + /** + * @deprecated use 'set' instead. + * @param theVelocity Vector3f + * @param theResult TransformMatrix4f + */ + public void setRotationMatrix(final Vector3f theVelocity, + final TransformMatrix4f theResult) { + set(theVelocity, theResult); + } + + public Vector3f getAverageVelocity() { + return _myCurrentAverageVelocity; + } + + public void setUpVector(final Vector3f theUpVector) { + _myUpVector.set(theUpVector); + } + + public void setUpVectorByAngle(final float roll) { + /** + * @todo this is not thought through... + */ + _myUpVector.x = (float) Math.sin(roll); + _myUpVector.z = -(float) Math.cos(roll); + _myUpVector.y = 0; + } + + private void pointAt(final Vector3f theForwardVector, + final Matrix3f theResult) { + /* get sideVector */ + _myTempSideVector.cross(_myUpVector, theForwardVector); + _myTempSideVector.normalize(); + /* get 'real' upVector */ + _myTempUpVector.cross(_myTempSideVector, theForwardVector); + _myTempUpVector.normalize(); + /* get forwardVector */ + _myTempForwardVector.set(theForwardVector); + _myTempForwardVector.normalize(); + /* fill transformation matrix */ + theResult.setXAxis(_myTempForwardVector); + theResult.setYAxis(_myTempSideVector); + theResult.setZAxis(_myTempUpVector); + } + + private void pointAt(final Vector3f theForwardVector, + final TransformMatrix4f theResult) { + pointAt(theForwardVector, theResult.rotation); + } +} diff --git a/day3/libs/mathematik/src/mathematik/TransformMatrix4f.java b/day3/libs/mathematik/src/mathematik/TransformMatrix4f.java new file mode 100755 index 0000000..f040b2b --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/TransformMatrix4f.java @@ -0,0 +1,333 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +/** + * + * special form of a 4x4 matrix. first of all the way we represent the matrix in + * this class is similar to the way opengl handles the row column issue. + * + * transform matrix -- r = rotation, t = translation + * + * rxx rxy rxz 0 ryx ryy ryz 0 rzx rzy rzz 0 tx ty tz 1 + * + * the transform matrix is special in the way that is a 3x3 matrix for rotation + * and scale and a translation vector. the remaining four values a constants. + * + * this is the way opengl specifies a 4x4 matrix and also the way 'toArray' + * returns an array. + * + * m[0] m[4] m[8] m[12] + * + * m[1] m[5] m[9] m[13] + * + * M=( ) + * + * m[2] m[6] m[10] m[14] + * + * m[3] m[7] m[11] m[15] + * + * + * here is an excerpt from the glMultMatrix man page. + * + * "In many computer languages 4x4 arrays are represented in row-major order. + * The transformations just described represent these matrices in column-major + * order. The order of the multiplication is important. For example, if the + * current transformation is a rotation, and glMultMatrix is called with a + * translation matrix, the translation is done directly on the coordinates to be + * transformed, while the rotation is done on the results of that translation." + * + * also read 'The Matrix and Quaternions FAQ' at + * http://www.flipcode.com/documents/matrfaq.html + */ +public class TransformMatrix4f + implements Serializable { + + public static int IDENTITY = 1; + + public Matrix3f rotation; + + public Vector3f translation; + + private static final long serialVersionUID = 2946060493174800199L; + + private static final float ZERO = 0; + + private static final float ONE = 1; + + private final float[] _myArrayRepresentation = new float[16]; + + public TransformMatrix4f() { + translation = new Vector3f(); + rotation = new Matrix3f(); + } + + public TransformMatrix4f(int theType) { + translation = new Vector3f(); + rotation = new Matrix3f(theType); + toArray(); + } + + public TransformMatrix4f(TransformMatrix4f theMatrix4f) { + this(); + set(theMatrix4f); + toArray(); + } + + public TransformMatrix4f(float[] theMatrixArray) { + this(); + set(theMatrixArray); + toArray(); + } + + public final void setIdentity() { + translation.set(0, + 0, + 0); + rotation.setIdentity(); + } + + public final void setRotationIdentity() { + rotation.setIdentity(); + } + + public final void setZero() { + translation.set(0, + 0, + 0); + rotation.setZero(); + } + + public final float determinant() { + float d = rotation.xx + * ((rotation.yy * rotation.zz * ONE + rotation.yz * translation.z * ZERO + + translation.y * rotation.zy * ZERO) + - translation.y * rotation.zz * ZERO - rotation.yy * translation.z * ZERO - rotation.yz + * rotation.zy * ONE); + d -= rotation.xy + * ((rotation.yx * rotation.zz * ONE + rotation.yz * translation.z * ZERO + + translation.y * rotation.zx * ZERO) + - translation.y * rotation.zz * ZERO - rotation.yx * translation.z * ZERO - rotation.yz + * rotation.zx * ONE); + d += rotation.xz + * ((rotation.yx * rotation.zy * ONE + rotation.yy * translation.z * ZERO + + translation.y * rotation.zx * ZERO) + - translation.y * rotation.zy * ZERO - rotation.yx * translation.z * ZERO - rotation.yy + * rotation.zx * ONE); + d -= translation.x + * ((rotation.yx * rotation.zy * ZERO + rotation.yy * rotation.zz * ZERO + rotation.yz * rotation.zx * ZERO) + - rotation.yz * rotation.zy * ZERO - rotation.yx * rotation.zz * ZERO - rotation.yy + * rotation.zx * ZERO); + return d; + } + + public final void set(TransformMatrix4f mat) { + rotation.set(mat.rotation); + translation.set(mat.translation); + } + + public final void set(float[] theArrayRepresentation) { + rotation.xx = theArrayRepresentation[0]; + rotation.yx = theArrayRepresentation[1]; + rotation.zx = theArrayRepresentation[2]; + /* 3 */ + rotation.xy = theArrayRepresentation[4]; + rotation.yy = theArrayRepresentation[5]; + rotation.zy = theArrayRepresentation[6]; + /* 7 */ + rotation.xz = theArrayRepresentation[8]; + rotation.yz = theArrayRepresentation[9]; + rotation.zz = theArrayRepresentation[10]; + /* 11 */ + translation.x = theArrayRepresentation[12]; + translation.y = theArrayRepresentation[13]; + translation.z = theArrayRepresentation[14]; + /* 15 */ + } + + public final void multiply(float theValue) { + rotation.xx *= theValue; + rotation.xy *= theValue; + rotation.xz *= theValue; + translation.x *= theValue; + rotation.yx *= theValue; + rotation.yy *= theValue; + rotation.yz *= theValue; + translation.y *= theValue; + rotation.zx *= theValue; + rotation.zy *= theValue; + rotation.zz *= theValue; + translation.z *= theValue; + } + + public final void multiply(float theValue, + TransformMatrix4f theMatrix4f) { + rotation.xx = theMatrix4f.rotation.xx * theValue; + rotation.xy = theMatrix4f.rotation.xy * theValue; + rotation.xz = theMatrix4f.rotation.xz * theValue; + translation.x = theMatrix4f.translation.x * theValue; + rotation.yx = theMatrix4f.rotation.yx * theValue; + rotation.yy = theMatrix4f.rotation.yy * theValue; + rotation.yz = theMatrix4f.rotation.yz * theValue; + translation.y = theMatrix4f.translation.y * theValue; + rotation.zx = theMatrix4f.rotation.zx * theValue; + rotation.zy = theMatrix4f.rotation.zy * theValue; + rotation.zz = theMatrix4f.rotation.zz * theValue; + translation.z = theMatrix4f.translation.z * theValue; + } + + public final void multiply(TransformMatrix4f theMatrix4f) { + float tmp1 = rotation.xx * theMatrix4f.rotation.xx + rotation.xy * theMatrix4f.rotation.yx + + rotation.xz * theMatrix4f.rotation.zx + translation.x * TransformMatrix4f.ZERO; + float tmp2 = rotation.xx * theMatrix4f.rotation.xy + rotation.xy * theMatrix4f.rotation.yy + + rotation.xz * theMatrix4f.rotation.zy + translation.x * TransformMatrix4f.ZERO; + float tmp3 = rotation.xx * theMatrix4f.rotation.xz + rotation.xy * theMatrix4f.rotation.yz + + rotation.xz * theMatrix4f.rotation.zz + translation.x * TransformMatrix4f.ZERO; + float tmp4 = rotation.xx * theMatrix4f.translation.x + rotation.xy * theMatrix4f.translation.y + + rotation.xz * theMatrix4f.translation.z + translation.x * TransformMatrix4f.ONE; + + float tmp5 = rotation.yx * theMatrix4f.rotation.xx + rotation.yy * theMatrix4f.rotation.yx + + rotation.yz * theMatrix4f.rotation.zx + translation.y * TransformMatrix4f.ZERO; + float tmp6 = rotation.yx * theMatrix4f.rotation.xy + rotation.yy * theMatrix4f.rotation.yy + + rotation.yz * theMatrix4f.rotation.zy + translation.y * TransformMatrix4f.ZERO; + float tmp7 = rotation.yx * theMatrix4f.rotation.xz + rotation.yy * theMatrix4f.rotation.yz + + rotation.yz * theMatrix4f.rotation.zz + translation.y * TransformMatrix4f.ZERO; + float tmp8 = rotation.yx * theMatrix4f.translation.x + rotation.yy * theMatrix4f.translation.y + + rotation.yz * theMatrix4f.translation.z + translation.y * TransformMatrix4f.ONE; + + float tmp9 = rotation.zx * theMatrix4f.rotation.xx + rotation.zy * theMatrix4f.rotation.yx + + rotation.zz * theMatrix4f.rotation.zx + translation.z * TransformMatrix4f.ZERO; + float tmp10 = rotation.zx * theMatrix4f.rotation.xy + rotation.zy * theMatrix4f.rotation.yy + + rotation.zz * theMatrix4f.rotation.zy + translation.z * TransformMatrix4f.ZERO; + float tmp11 = rotation.zx * theMatrix4f.rotation.xz + rotation.zy * theMatrix4f.rotation.yz + + rotation.zz * theMatrix4f.rotation.zz + translation.z * TransformMatrix4f.ZERO; + float tmp12 = rotation.zx * theMatrix4f.translation.x + rotation.zy * theMatrix4f.translation.y + + rotation.zz * theMatrix4f.translation.z + translation.z * TransformMatrix4f.ONE; + + /* + float temp13 = m30 * in2.m00 + + m31 * in2.m10 + + m32 * in2.m20 + + m33 * in2.m30; + float temp14 = m30 * in2.m01 + + m31 * in2.m11 + + m32 * in2.m21 + + m33 * in2.m31; + float temp15 = m30 * in2.m02 + + m31 * in2.m12 + + m32 * in2.m22 + + m33 * in2.m32; + float temp16 = m30 * in2.m03 + + m31 * in2.m13 + + m32 * in2.m23 + + m33 * in2.m33; + */ + + rotation.xx = tmp1; + rotation.xy = tmp2; + rotation.xz = tmp3; + translation.x = tmp4; + rotation.yx = tmp5; + rotation.yy = tmp6; + rotation.yz = tmp7; + translation.y = tmp8; + rotation.zx = tmp9; + rotation.zy = tmp10; + rotation.zz = tmp11; + translation.z = tmp12; + } + + public final void transform(Vector3f theResult) { + /** + * @todo check if this is right... + */ + theResult.set(rotation.xx * theResult.x + + rotation.xy * theResult.y + + rotation.xz * theResult.z + + translation.x, + rotation.yx * theResult.x + + rotation.yy * theResult.y + + rotation.yz * theResult.z + + translation.y, + rotation.zx * theResult.x + + rotation.zy * theResult.y + + rotation.zz * theResult.z + + translation.z); + } + + public final float[] toArray() { + /* so that opengl can understand it */ + _myArrayRepresentation[0] = rotation.xx; + _myArrayRepresentation[1] = rotation.yx; + _myArrayRepresentation[2] = rotation.zx; + _myArrayRepresentation[3] = ZERO; + _myArrayRepresentation[4] = rotation.xy; + _myArrayRepresentation[5] = rotation.yy; + _myArrayRepresentation[6] = rotation.zy; + _myArrayRepresentation[7] = ZERO; + _myArrayRepresentation[8] = rotation.xz; + _myArrayRepresentation[9] = rotation.yz; + _myArrayRepresentation[10] = rotation.zz; + _myArrayRepresentation[11] = ZERO; + _myArrayRepresentation[12] = translation.x; + _myArrayRepresentation[13] = translation.y; + _myArrayRepresentation[14] = translation.z; + _myArrayRepresentation[15] = ONE; + return _myArrayRepresentation; + } + + public String toString() { + return rotation.xx + ", " + rotation.yx + ", " + rotation.zx + ", " + "0.0" + "\n" + rotation.xy + ", " + + rotation.yy + ", " + rotation.zy + ", " + "0.0" + "\n" + rotation.xz + ", " + rotation.yz + ", " + + rotation.zz + ", " + "0.0" + "\n" + translation.x + ", " + translation.y + ", " + translation.z + + ", " + "1.0"; + } + + public static void main(String[] args) { + /* multiplying matrices */ + TransformMatrix4f myScaleMatrix = new TransformMatrix4f(TransformMatrix4f.IDENTITY); + myScaleMatrix.rotation.setXAxis(new Vector3f(2, 0, 0)); + myScaleMatrix.rotation.setYAxis(new Vector3f(0, 2, 0)); + myScaleMatrix.rotation.setZAxis(new Vector3f(0, 0, 2)); + + TransformMatrix4f myTranslateMatrix = new TransformMatrix4f(TransformMatrix4f.IDENTITY); + myTranslateMatrix.translation.set(2, + 3, + 4); + + myScaleMatrix.multiply(myScaleMatrix); + myScaleMatrix.multiply(myTranslateMatrix); + System.out.println(myScaleMatrix); + + /* transform position */ + System.out.println("\n### translate"); + System.out.println(myTranslateMatrix); + System.out.println(); + Vector3f myVector = new Vector3f(10, 5, 7); + myTranslateMatrix.transform(myVector); + System.out.println(myVector); + } +} diff --git a/day3/libs/mathematik/src/mathematik/Util.java b/day3/libs/mathematik/src/mathematik/Util.java new file mode 100755 index 0000000..da88373 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Util.java @@ -0,0 +1,931 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.util.Vector; + + +/** + * + * a loose collection of linear algebra methods that are not connected to a + * specific class. + * + */ +public class Util { + + public static final Vector3f AXIS_X = new Vector3f(1, 0, 0); + + public static final Vector3f AXIS_Y = new Vector3f(0, 1, 0); + + public static final Vector3f AXIS_Z = new Vector3f(0, 0, 1); + + public static final float areaTriangle(final Vector3f v0, + final Vector3f v1, + final Vector3f v2) { + final Vector3f myAB = sub(v1, v0); + final Vector3f myAC = sub(v2, v0); + final Vector3f myCross = cross(myAB, myAC); + return 0.5f * myCross.magnitude(); + } + + public float length(Vector3f theVector3f) { + return theVector3f.length(); + } + + public static final boolean isPointInTriangle(final Vector3f v0, + final Vector3f v1, + final Vector3f v2, + final Vector3f thePoint) { +// // Compute vectors +// v0 = C - A +// v1 = B - A +// v2 = P - A + + Vector3f v00 = new Vector3f(v2); + v00.sub(v0); + + Vector3f v01 = new Vector3f(v1); + v01.sub(v0); + + Vector3f v02 = new Vector3f(thePoint); + v02.sub(v0); + + // Compute dot products + + float dot00 = v00.dot(v00); + float dot01 = v00.dot(v01); + float dot02 = v00.dot(v02); + float dot11 = v01.dot(v01); + float dot12 = v01.dot(v02); + + // Compute barycentric coordinates + float invDenom = 1 / (dot00 * dot11 - dot01 * dot01); + float u = (dot11 * dot02 - dot01 * dot12) * invDenom; + float v = (dot00 * dot12 - dot01 * dot02) * invDenom; + + // Check if point is in triangle + return (u > 0) && (v > 0) && (u + v < 1); + } + + + /* contain */ + public static final boolean contains(final Vector3f thePosition, + final WorldAxisAlignedBoundingBox theWorldAlignedBox) { + return (contains(thePosition.x, theWorldAlignedBox.position.x, theWorldAlignedBox.scale.x) + && contains(thePosition.y, theWorldAlignedBox.position.y, theWorldAlignedBox.scale.y) + && contains(thePosition.z, theWorldAlignedBox.position.z, theWorldAlignedBox.scale.z)); + } + + public static final boolean contains(final float theTestValue, + final float theContainerValue, + final float theRange) { + return (theTestValue > theContainerValue - theRange * 0.5f + && theTestValue < theContainerValue + theRange * 0.5f); + } + + public static boolean insidePolygon(Vector2f thePoint, Vector2f[] thePolygon) { + float x = thePoint.x; + float y = thePoint.y; + + int c = 0; + for (int i = 0, j = thePolygon.length - 1; i < thePolygon.length; j = i++) { + if ((((thePolygon[i].y <= y) && (y < thePolygon[j].y)) + || ((thePolygon[j].y <= y) && (y < thePolygon[i].y))) + && (x < (thePolygon[j].x - thePolygon[i].x) * (y - thePolygon[i].y) + / (thePolygon[j].y - thePolygon[i].y) + thePolygon[i].x)) { + c = (c + 1) % 2; + } + } + return c == 1; + } + + public static final boolean insidePolygon(final Vector2f thePoint, final Vector thePolygon) { + float x = thePoint.x; + float y = thePoint.y; + + int c = 0; + for (int i = 0, j = thePolygon.size() - 1; i < thePolygon.size(); j = i++) { + if ((((thePolygon.get(i).y <= y) && (y < thePolygon.get(j).y)) + || ((thePolygon.get(j).y <= y) && (y < thePolygon.get(i).y))) + && (x < (thePolygon.get(j).x - thePolygon.get(i).x) * (y - thePolygon.get(i).y) + / (thePolygon.get(j).y - thePolygon.get(i).y) + thePolygon.get(i).x)) { + c = (c + 1) % 2; + } + } + return c == 1; + } + + public static final boolean inside2DPolygon(final Vector3f thePoint, final Vector thePolygon) { + float x = thePoint.x; + float y = thePoint.y; + + int c = 0; + for (int i = 0, j = thePolygon.size() - 1; i < thePolygon.size(); j = i++) { + if ((((thePolygon.get(i).y <= y) && (y < thePolygon.get(j).y)) + || ((thePolygon.get(j).y <= y) && (y < thePolygon.get(i).y))) + && (x < (thePolygon.get(j).x - thePolygon.get(i).x) * (y - thePolygon.get(i).y) + / (thePolygon.get(j).y - thePolygon.get(i).y) + thePolygon.get(i).x)) { + c = (c + 1) % 2; + } + } + return c == 1; + } + private static final Vector3f _myTempMin = new Vector3f(); + + private static final Vector3f _myTempMax = new Vector3f(); + + public static void updateBoundingBox(final WorldAxisAlignedBoundingBox theWorldAxisAlignedBoundingBox, + final Vector3f[] myVectors) { + + if (myVectors == null || myVectors.length == 0) { + return; + } + + /* get minimum and maximum */ + _myTempMin.set(myVectors[0]); + _myTempMax.set(myVectors[0]); + + for (int i = 1; i < myVectors.length; i++) { + /* minimum */ + if (_myTempMin.x > myVectors[i].x) { + _myTempMin.x = myVectors[i].x; + } + if (_myTempMin.y > myVectors[i].y) { + _myTempMin.y = myVectors[i].y; + } + if (_myTempMin.z > myVectors[i].z) { + _myTempMin.z = myVectors[i].z; + } + /* maximum */ + if (_myTempMax.x < myVectors[i].x) { + _myTempMax.x = myVectors[i].x; + } + if (_myTempMax.y < myVectors[i].y) { + _myTempMax.y = myVectors[i].y; + } + if (_myTempMax.z < myVectors[i].z) { + _myTempMax.z = myVectors[i].z; + } + } + + /* create world aligned boundingbox */ + /* bb position */ + theWorldAxisAlignedBoundingBox.position.sub(_myTempMax, _myTempMin); + theWorldAxisAlignedBoundingBox.position.scale(0.5f); + theWorldAxisAlignedBoundingBox.position.add(_myTempMin); + /* bb scale */ + theWorldAxisAlignedBoundingBox.scale.sub(_myTempMax, _myTempMin); + theWorldAxisAlignedBoundingBox.scale.x = Math.abs(theWorldAxisAlignedBoundingBox.scale.x); + theWorldAxisAlignedBoundingBox.scale.y = Math.abs(theWorldAxisAlignedBoundingBox.scale.y); + theWorldAxisAlignedBoundingBox.scale.z = Math.abs(theWorldAxisAlignedBoundingBox.scale.z); + } + /* transforms */ + private static final Vector3f _myTempForwardVector = new Vector3f(); + + private static final Vector3f _myTempSideVector = new Vector3f(); + + private static final Vector3f _myTempUpVector = new Vector3f(); + + public static void pointAt(final TransformMatrix4f theResult, + final Vector3f theUpVector, + final Vector3f thePointAtPosition) { + + pointAt(theResult, + theResult.translation, + theUpVector, + thePointAtPosition); + +// /* forward */ +// _myTempForwardVector.sub(theResult.translation, thePointAtPosition); +// _myTempForwardVector.normalize(); +// +// /* side */ +// _myTempSideVector.cross(theUpVector, _myTempForwardVector); +// _myTempSideVector.normalize(); +// +// /* up */ +// _myTempUpVector.cross(_myTempForwardVector, _myTempSideVector); +// _myTempUpVector.normalize(); +// +// if (!_myTempSideVector.isNaN() && +// !_myTempUpVector.isNaN() && +// !_myTempForwardVector.isNaN()) { +// theResult.rotation.setXAxis(_myTempSideVector); +// theResult.rotation.setYAxis(_myTempUpVector); +// theResult.rotation.setZAxis(_myTempForwardVector); +// } + } + + public static void pointAt(final TransformMatrix4f theResult, + final Vector3f thePosition, + final Vector3f theUpVector, + final Vector3f thePointAtPosition) { + /* forward */ + _myTempForwardVector.sub(thePosition, thePointAtPosition); + _myTempForwardVector.normalize(); + + /* side */ + _myTempSideVector.cross(theUpVector, _myTempForwardVector); + _myTempSideVector.normalize(); + + /* up */ + _myTempUpVector.cross(_myTempForwardVector, _myTempSideVector); + _myTempUpVector.normalize(); + + if (!_myTempSideVector.isNaN() + && !_myTempUpVector.isNaN() + && !_myTempForwardVector.isNaN()) { + theResult.rotation.setXAxis(_myTempSideVector); + theResult.rotation.setYAxis(_myTempUpVector); + theResult.rotation.setZAxis(_myTempForwardVector); + } + } + + public static void pointAlong(final TransformMatrix4f theResult, + final Vector3f theForwardVector, + final Vector3f theUpVector) { + /* forward */ + _myTempForwardVector.set(theForwardVector); + _myTempForwardVector.normalize(); + + /* side */ + _myTempSideVector.cross(theUpVector, _myTempForwardVector); + _myTempSideVector.normalize(); + + /* up */ + _myTempUpVector.cross(_myTempForwardVector, _myTempSideVector); + _myTempUpVector.normalize(); + + if (!_myTempSideVector.isNaN() + && !_myTempUpVector.isNaN() + && !_myTempForwardVector.isNaN()) { + theResult.rotation.setXAxis(_myTempSideVector); + theResult.rotation.setYAxis(_myTempUpVector); + theResult.rotation.setZAxis(_myTempForwardVector); + } + } + + public static final void toLocalSpace(TransformMatrix4f theLocalSpace, Vector3f theLocalResult) { + theLocalResult.sub(theLocalSpace.translation); + theLocalSpace.rotation.transform(theLocalResult); + } + + public static final float bilinearInterp(final float x, final float y, + final float q00, + final float q10, + final float q01, + final float q11) { + return q00 * (1 - x) * (1 - y) + + q10 * x * (1 - y) + + q01 * (1 - x) * y + + q11 * x * y; + } + /* normal */ + private static final Vector3f TMP_BA = new Vector3f(); + + private static final Vector3f TMP_BC = new Vector3f(); + + /** + * calculate a normal from a set of three vectors. + * + * @param pointA + * @param pointB + * @param pointC + * @param theResultNormal + */ + public static final void calculateNormal(final Vector3f pointA, + final Vector3f pointB, + final Vector3f pointC, + final Vector3f theResultNormal) { + TMP_BA.sub(pointB, pointA); + TMP_BC.sub(pointC, pointB); + + theResultNormal.cross(TMP_BA, TMP_BC); + theResultNormal.normalize(); + } + + /** + * + * @param theVectorAB Vector3f + * @param theVectorBC Vector3f + * @param theResultNormal Vector3f + */ + public static void calculateNormal(final Vector3f theVectorAB, + final Vector3f theVectorBC, + final Vector3f theResultNormal) { + theResultNormal.cross(theVectorAB, theVectorBC); + theResultNormal.normalize(); + } + + /** + * + * @param pointA Vector3f + * @param pointB Vector3f + * @param pointC Vector3f + * @return Vector3f + */ + public static Vector3f createNormal(final Vector3f pointA, + final Vector3f pointB, + final Vector3f pointC) { + final Vector3f myResultNormal = new Vector3f(); + calculateNormal(pointA, + pointB, + pointC, + myResultNormal); + return myResultNormal; + } + + /** + * + * @param theVectorAB Vector3f + * @param theVectorBC Vector3f + * @return Vector3f + */ + public static Vector3f createNormal(final Vector3f theVectorAB, + final Vector3f theVectorBC) { + final Vector3f myResultNormal = new Vector3f(); + calculateNormal(theVectorAB, + theVectorBC, + myResultNormal); + return myResultNormal; + } + + public static void createNormals(float[] theVertices, float[] theNormals) { + final int NUMBER_OF_VERTEX_COMPONENTS = 3; + final int myNumberOfPoints = 3; + for (int i = 0; i < theVertices.length; + i += (myNumberOfPoints * NUMBER_OF_VERTEX_COMPONENTS)) { + Vector3f a = new Vector3f(theVertices[i + 0], theVertices[i + 1], theVertices[i + 2]); + Vector3f b = new Vector3f(theVertices[i + 3], theVertices[i + 4], theVertices[i + 5]); + Vector3f c = new Vector3f(theVertices[i + 6], theVertices[i + 7], theVertices[i + 8]); + Vector3f myNormal = new Vector3f(); + mathematik.Util.calculateNormal(a, b, c, myNormal); + + theNormals[i + 0] = myNormal.x; + theNormals[i + 1] = myNormal.y; + theNormals[i + 2] = myNormal.z; + + theNormals[i + 3] = myNormal.x; + theNormals[i + 4] = myNormal.y; + theNormals[i + 5] = myNormal.z; + + theNormals[i + 6] = myNormal.x; + theNormals[i + 7] = myNormal.y; + theNormals[i + 8] = myNormal.z; + } + } + /* distance */ + private static final Vector3f _myTempVector = new Vector3f(); + + /** + * return the distance between to points defined by two vectors. + * + * @param theVectorA Vector3f + * @param theVectorB Vector3f + * @return float + */ + public static final float distance(Vector3f theVectorA, Vector3f theVectorB) { + _myTempVector.set(theVectorA); + return _myTempVector.distance(theVectorB); + } + + + /* add */ + /** + * add two vectors and return the result in a new instance. + * + * @param theVectorA Vector4f + * @param theVectorB Vector4f + * @return Vector4f + */ + public static final Vector4f add(Vector4f theVectorA, Vector4f theVectorB) { + return new Vector4f(theVectorA.w + theVectorB.w, + theVectorA.x + theVectorB.x, + theVectorA.y + theVectorB.y, + theVectorA.z + theVectorB.z); + } + + /** + * add two vectors and return the result in a new instance. + * + * @param theVectorA Vector3f + * @param theVectorB Vector3f + * @return Vector3f + */ + public static final Vector3f add(Vector3f theVectorA, Vector3f theVectorB) { + return new Vector3f(theVectorA.x + theVectorB.x, theVectorA.y + theVectorB.y, theVectorA.z + theVectorB.z); + } + + /** + * add two vectors and return the result in a new instance. + * + * @param theVectorA Vector2f + * @param theVectorB Vector2f + * @return Vector2f + */ + public static final Vector2f add(Vector2f theVectorA, Vector2f theVectorB) { + return new Vector2f(theVectorA.x + theVectorB.x, + theVectorA.y + theVectorB.y); + } + + /** + * add two vectors and return the result in a new instance. + * + * @param theVectorA Vector3i + * @param theVectorB Vector3i + * @return Vector3i + */ + public static final Vector3i add(Vector3i theVectorA, Vector3i theVectorB) { + return new Vector3i(theVectorA.x + theVectorB.x, theVectorA.y + theVectorB.y, theVectorA.z + theVectorB.z); + } + + /** + * add two vectors and return the result in a new instance. + * + * @param theVectorA Vector2i + * @param theVectorB Vector2i + * @return Vector2i + */ + public static final Vector2i add(Vector2i theVectorA, Vector2i theVectorB) { + return new Vector2i(theVectorA.x + theVectorB.x, theVectorA.y + theVectorB.y); + } + + + /* sub */ + /** + * subtract two vectors and return the result in a new instance. + * + * @param theVectorA Vector4f + * @param theVectorB Vector4f + * @return Vector4f + */ + public static final Vector4f sub(Vector4f theVectorA, Vector4f theVectorB) { + return new Vector4f(theVectorA.w - theVectorB.w, theVectorA.x - theVectorB.x, theVectorA.y - theVectorB.y, + theVectorA.z - theVectorB.z); + } + + /** + * subtract two vectors and return the result in a new instance. + * + * @param theVectorA Vector3f + * @param theVectorB Vector3f + * @return Vector3f + */ + public static final Vector3f sub(Vector3f theVectorA, Vector3f theVectorB) { + return new Vector3f(theVectorA.x - theVectorB.x, theVectorA.y - theVectorB.y, theVectorA.z - theVectorB.z); + } + + /** + * subtract two vectors and return the result in a new instance. + * + * @param theVectorA Vector2f + * @param theVectorB Vector2f + * @return Vector2f + */ + public static final Vector2f sub(Vector2f theVectorA, Vector2f theVectorB) { + return new Vector2f(theVectorA.x - theVectorB.x, theVectorA.y - theVectorB.y); + } + + /** + * subtract two vectors and return the result in a new instance. + * + * @param theVectorA Vector3i + * @param theVectorB Vector3i + * @return Vector3i + */ + public static final Vector3i sub(Vector3i theVectorA, Vector3i theVectorB) { + return new Vector3i(theVectorA.x - theVectorB.x, + theVectorA.y - theVectorB.y, + theVectorA.z - theVectorB.z); + } + + /** + * subtract two vectors and return the result in a new instance. + * + * @param theVectorA Vector2i + * @param theVectorB Vector2i + * @return Vector2i + */ + public static final Vector2i sub(Vector2i theVectorA, Vector2i theVectorB) { + return new Vector2i(theVectorA.x - theVectorB.x, + theVectorA.y - theVectorB.y); + } + + /** + * return the cross between two vectors in a new vector. + * + * @param theVectorA Vector3f + * @param theVectorB Vector3f + * @return Vector3f + */ + public static final Vector3f cross(Vector3f theVectorA, Vector3f theVectorB) { + final Vector3f myVector = new Vector3f(); + myVector.cross(theVectorA, theVectorB); + return myVector; + } + + /** + * return a normalized vector in a new vector. + * + * @param theVector Vector3f + * @return Vector3f + */ + public static final Vector3f normalized(Vector3f theVector) { + final Vector3f myVector = new Vector3f(theVector); + myVector.normalize(); + return myVector; + } + + /** + * + * @param theVectorA Vector2f + * @param theValue float + * @return Vector2f + */ + public static final Vector2f scale(Vector2f theVectorA, float theValue) { + return new Vector2f(theVectorA.x * theValue, + theVectorA.y * theValue); + } + + public static final Vector3f scale(Vector3f theVectorA, float theValue) { + return new Vector3f(theVectorA.x * theValue, + theVectorA.y * theValue, + theVectorA.z * theValue); + } + + public static final Vector3f scale(Vector3f theVectorA, Vector3f theValue) { + return new Vector3f(theVectorA.x * theValue.x, + theVectorA.y * theValue.y, + theVectorA.z * theValue.z); + } + + public static final Vector4f scale(Vector4f theVectorA, float theValue) { + return new Vector4f(theVectorA.x * theValue, + theVectorA.y * theValue, + theVectorA.z * theValue, + theVectorA.w * theValue); + } + + public static final float clamp(float theValue, float theMin, float theMax) { + if (theValue > theMax) { + theValue = theMax; + } + if (theValue < theMin) { + theValue = theMin; + } + return theValue; + } + + public static final float normalize(float theValue, float theStart, float theEnd) { + return (theValue - theStart) / (theEnd - theStart); + } + + public static final float map(float theValue, float theInStart, float theInEnd, float theOutStart, float theOutEnd) { + return theOutStart + (theOutEnd - theOutStart) * ((theValue - theInStart) / (theInEnd - theInStart)); + } + + public static Vector2f parseVector2f(String theString) { + String splitter; + if (contains(theString, ",")) { + splitter = ","; + } else { + throw new IllegalArgumentException(); + } + String[] coords = theString.split(splitter); + return new Vector2f(Float.parseFloat(coords[0]), + Float.parseFloat(coords[1])); + } + + public static Vector3f parseVector3f(String theString) { + String splitter; + if (contains(theString, ",")) { + splitter = ","; + } else { + throw new IllegalArgumentException(); + } + String[] coords = theString.split(splitter); + return new Vector3f(Float.parseFloat(coords[0]), + Float.parseFloat(coords[1]), + Float.parseFloat(coords[2])); + } + + public static boolean contains(String theString, CharSequence theContainedString) { + return theString.indexOf(theContainedString.toString()) > -1; + } + + /** + * the following point rotation methods are from the famous paul bourke. + * read more on his website at + * + * http://local.wasp.uwa.edu.au/~pbourke/geometry/rotate/ + * + */ + /** + * Rotate a point p by angle theta around an arbitrary axis r Return the + * rotated point. Positive angles are anticlockwise looking down the axis + * towards the origin. Assume right hand coordinate system. + * + * @param p Vector3f + * @param theta double + * @param theAxis Vector3f + * @return Vector3f + */ + public static Vector3f rotatePoint(Vector3f p, + double theta, + Vector3f theAxis) { + Vector3f myR = new Vector3f(); + Vector3f q = new Vector3f(); + double costheta, sintheta; + + myR.normalize(theAxis); + + costheta = Math.cos(theta); + sintheta = Math.sin(theta); + + q.x += (costheta + (1 - costheta) * myR.x * myR.x) * p.x; + q.x += ((1 - costheta) * myR.x * myR.y - myR.z * sintheta) * p.y; + q.x += ((1 - costheta) * myR.x * myR.z + myR.y * sintheta) * p.z; + + q.y += ((1 - costheta) * myR.x * myR.y + myR.z * sintheta) * p.x; + q.y += (costheta + (1 - costheta) * myR.y * myR.y) * p.y; + q.y += ((1 - costheta) * myR.y * myR.z - myR.x * sintheta) * p.z; + + q.z += ((1 - costheta) * myR.x * myR.z - myR.y * sintheta) * p.x; + q.z += ((1 - costheta) * myR.y * myR.z + myR.x * sintheta) * p.y; + q.z += (costheta + (1 - costheta) * myR.z * myR.z) * p.z; + + return q; + } + + + /* + * Rotate a point p by angle theta around an arbitrary line segment p1-p2 + * Return the rotated point. + * Positive angles are anticlockwise looking down the axis towards the origin. + * Assume right hand coordinate system. + */ + public static Vector3f rotatePoint(Vector3f p, + double theta, + Vector3f p1, + Vector3f p2) { + Vector3f r = new Vector3f(); + Vector3f q = new Vector3f(); + Vector3f myP = new Vector3f(); + double costheta, sintheta; + + myP.set(p); + + r.x = p2.x - p1.x; + r.y = p2.y - p1.y; + r.z = p2.z - p1.z; + myP.x -= p1.x; + myP.y -= p1.y; + myP.z -= p1.z; + + r.normalize(); + + costheta = Math.cos(theta); + sintheta = Math.sin(theta); + + q.x += (costheta + (1 - costheta) * r.x * r.x) * myP.x; + q.x += ((1 - costheta) * r.x * r.y - r.z * sintheta) * myP.y; + q.x += ((1 - costheta) * r.x * r.z + r.y * sintheta) * myP.z; + + q.y += ((1 - costheta) * r.x * r.y + r.z * sintheta) * myP.x; + q.y += (costheta + (1 - costheta) * r.y * r.y) * myP.y; + q.y += ((1 - costheta) * r.y * r.z - r.x * sintheta) * myP.z; + + q.z += ((1 - costheta) * r.x * r.z - r.y * sintheta) * myP.x; + q.z += ((1 - costheta) * r.y * r.z + r.x * sintheta) * myP.y; + q.z += (costheta + (1 - costheta) * r.z * r.z) * myP.z; + + q.x += p1.x; + q.y += p1.y; + q.z += p1.z; + + return q; + } + + /** + * + * DistancePointLine Unit Test Copyright (c) 2002, All rights reserved + * + * Damian Coventry Tuesday, 16 July 2002 + * + * Implementation of theory by Paul Bourke + * + * @param thePoint Vector3f + * @param theLineStart Vector3f + * @param theLineEnd Vector3f + * @return float + */ + public static float distancePointLineSegment(final Vector3f thePoint, + final Vector3f theLineStart, + final Vector3f theLineEnd) { + final float u = distancePointLineU(thePoint, theLineStart, theLineEnd); + + if (u < 0.0f || u > 1.0f) { + return -1; // closest point does not fall within the line segment + } + + final Vector3f myIntersection = new Vector3f(); + myIntersection.x = theLineStart.x + u * (theLineEnd.x - theLineStart.x); + myIntersection.y = theLineStart.y + u * (theLineEnd.y - theLineStart.y); + myIntersection.z = theLineStart.z + u * (theLineEnd.z - theLineStart.z); + + return thePoint.distance(myIntersection); + } + + public static float distancePointLine(final Vector3f thePoint, + final Vector3f theLineStart, + final Vector3f theLineEnd) { + final float u = distancePointLineU(thePoint, theLineStart, theLineEnd); + final Vector3f myIntersection = new Vector3f(); + myIntersection.x = theLineStart.x + u * (theLineEnd.x - theLineStart.x); + myIntersection.y = theLineStart.y + u * (theLineEnd.y - theLineStart.y); + myIntersection.z = theLineStart.z + u * (theLineEnd.z - theLineStart.z); + + return thePoint.distance(myIntersection); + } + + public static float distancePointLineU(final Vector3f thePoint, + final Vector3f theLineStart, + final Vector3f theLineEnd) { + final float myLineMagnitude = theLineStart.distance(theLineEnd); + final float u = (((thePoint.x - theLineStart.x) * (theLineEnd.x - theLineStart.x)) + + ((thePoint.y - theLineStart.y) * (theLineEnd.y - theLineStart.y)) + + ((thePoint.z - theLineStart.z) * (theLineEnd.z - theLineStart.z))) + / (myLineMagnitude * myLineMagnitude); + + return u; + } + + public static float random(float theStart, + float theEnd) { + final float myDiff = theEnd - theStart; + final float myRandomValue = (float) Math.random() * myDiff; + return myRandomValue + theStart; + } + public static final int CLOCKWISE = 1; + + public static final int COUNTERCLOCKWISE = -1; + + /** + * adapted from genius paul bourke + * http://debian.fmi.uni-sofia.bg/~sergei/cgsr/docs/clockwise.htm + * + * Return the clockwise status of a curve, clockwise or counterclockwise n + * vertices making up curve p return 0 for incomputables eg: colinear points + * CLOCKWISE == 1 COUNTERCLOCKWISE == -1 It is assumed that - the polygon is + * closed - the last point is not repeated. - the polygon is simple (does + * not intersect itself or have holes) + */ + public static int isClockWise(final Vector mPoints) { + + if (mPoints.size() < 3) { + return (0); + } + + int mCount = 0; + for (int i = 0; i < mPoints.size(); i++) { + final Vector2f p1 = mPoints.get(i); + final Vector2f p2 = mPoints.get((i + 1) % mPoints.size()); + final Vector2f p3 = mPoints.get((i + 2) % mPoints.size()); + float z; + z = (p2.x - p1.x) * (p3.y - p2.y); + z -= (p2.y - p1.y) * (p3.x - p2.x); + if (z < 0) { + mCount--; + } else if (z > 0) { + mCount++; + } + } + if (mCount > 0) { + return (COUNTERCLOCKWISE); + } else if (mCount < 0) { + return (CLOCKWISE); + } else { + return (0); + } + } + + public static int isClockWise2D(final Vector mPoints) { + + if (mPoints.size() < 3) { + return (0); + } + + int mCount = 0; + for (int i = 0; i < mPoints.size(); i++) { + final Vector3f p1 = mPoints.get(i); + final Vector3f p2 = mPoints.get((i + 1) % mPoints.size()); + final Vector3f p3 = mPoints.get((i + 2) % mPoints.size()); + float z; + z = (p2.x - p1.x) * (p3.y - p2.y); + z -= (p2.y - p1.y) * (p3.x - p2.x); + if (z < 0) { + mCount--; + } else if (z > 0) { + mCount++; + } + } + if (mCount > 0) { + return (COUNTERCLOCKWISE); + } else if (mCount < 0) { + return (CLOCKWISE); + } else { + return (0); + } + } + public static final int CONVEX = 1; + + public static final int CONCAVE = -1; + + /** + * adapted from genius paul bourke + * http://debian.fmi.uni-sofia.bg/~sergei/cgsr/docs/clockwise.htm + * + * Return whether a polygon in 2D is concave or convex return 0 for + * incomputables eg: colinear points CONVEX == 1 CONCAVE == -1 It is assumed + * that the polygon is simple (does not intersect itself or have holes) + */ + public static int isConvex(final Vector mPoints) { + int flag = 0; + double z; + + if (mPoints.size() < 3) { + return (0); + } + + for (int i = 0; i < mPoints.size(); i++) { + final Vector2f p1 = mPoints.get(i); + final Vector2f p2 = mPoints.get((i + 1) % mPoints.size()); + final Vector2f p3 = mPoints.get((i + 2) % mPoints.size()); + z = (p2.x - p1.x) * (p3.y - p2.y); + z -= (p2.y - p1.y) * (p3.x - p2.x); + if (z < 0) { + flag |= 1; + } else if (z > 0) { + flag |= 2; + } + if (flag == 3) { + return (CONCAVE); + } + } + if (flag != 0) { + return (CONVEX); + } else { + return (0); + } + } + + public static int isConvex2D(final Vector mPoints) { + int flag = 0; + double z; + + if (mPoints.size() < 3) { + return (0); + } + + for (int i = 0; i < mPoints.size(); i++) { + final Vector3f p1 = mPoints.get(i); + final Vector3f p2 = mPoints.get((i + 1) % mPoints.size()); + final Vector3f p3 = mPoints.get((i + 2) % mPoints.size()); + z = (p2.x - p1.x) * (p3.y - p2.y); + z -= (p2.y - p1.y) * (p3.x - p2.x); + if (z < 0) { + flag |= 1; + } else if (z > 0) { + flag |= 2; + } + if (flag == 3) { + return (CONCAVE); + } + } + if (flag != 0) { + return (CONVEX); + } else { + return (0); + } + } +} diff --git a/day3/libs/mathematik/src/mathematik/Vector2f.java b/day3/libs/mathematik/src/mathematik/Vector2f.java new file mode 100755 index 0000000..a474c8f --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Vector2f.java @@ -0,0 +1,330 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +public class Vector2f + implements Serializable, Vectorf { + + private static final long serialVersionUID = -4652533170291767614L; + + public float x; + + public float y; + +// private float[] _myArrayRepresentation = new float[2]; + private static final float ALMOST_THRESHOLD = 0.001f; + + public Vector2f() { + x = 0.0f; + y = 0.0f; + } + + public Vector2f(float theX, + float theY) { + set(theX, + theY); + } + + public Vector2f(double theX, + double theY) { + set(theX, + theY); + } + + public Vector2f(float[] theVector) { + set(theVector); + } + + public Vector2f(double[] theVector) { + set(theVector); + } + + public Vector2f(int[] theVector) { + set(theVector); + } + + public Vector2f(Vector2f theVector) { + set(theVector); + } + + public Vector2f(Vector3f theVector) { + set(theVector.x, theVector.y); + } + + public Object clone() { + return cloneVector(); + } + + public Vector2f cloneVector() { + return new Vector2f(x, y); + } + + public final Vector2f set(float theX, + float theY) { + x = theX; + y = theY; + return this; + } + + public final Vector2f set(double theX, + double theY) { + x = (float) theX; + y = (float) theY; + return this; + } + + public final Vector2f set(float[] theVector) { + x = theVector[0]; + y = theVector[1]; + return this; + } + + public final Vector2f set(double[] theVector) { + x = (float) theVector[0]; + y = (float) theVector[1]; + return this; + } + + public final Vector2f set(int[] theVector) { + x = theVector[0]; + y = theVector[1]; + return this; + } + + public final Vector2f set(Vector2f theVector) { + x = theVector.x; + y = theVector.y; + return this; + } + + public Vector2f add(Vector2f theVectorA, + Vector2f theVectorB) { + x = theVectorA.x + theVectorB.x; + y = theVectorA.y + theVectorB.y; + return this; + } + + public Vector2f add(final int theX, final int theY) { + x += theX; + y += theY; + return this; + } + + public Vector2f add(final float theX, final float theY) { + x += theX; + y += theY; + return this; + } + + public Vector2f add(final double theX, final double theY) { + x += theX; + y += theY; + return this; + } + + public Vector2f add(Vector2f theVector) { + x += theVector.x; + y += theVector.y; + return this; + } + + public Vector2f sub(Vector2f theVectorA, + Vector2f theVectorB) { + x = theVectorA.x - theVectorB.x; + y = theVectorA.y - theVectorB.y; + return this; + } + + public Vector2f sub(Vector2f theVector) { + x -= theVector.x; + y -= theVector.y; + return this; + } + + public Vector2f sub(float theX, float theY) { + x -= theX; + y -= theY; + return this; + } + + public Vector2f scale(float theScalar, + Vector2f theVector) { + x = theScalar * theVector.x; + y = theScalar * theVector.y; + return this; + } + + public Vector2f scale(float theScalar) { + x *= theScalar; + y *= theScalar; + return this; + } + + public Vector2f scale(Vector2f theVector) { + x *= theVector.x; + y *= theVector.y; + return this; + } + + public Vector2f scale(float theXScalar, float theYScalar) { + x *= theXScalar; + y *= theYScalar; + return this; + } + + public float direction() { + return (float) Math.atan2(y, x); + } + + public float dot(Vector2f theVector) { + return x * theVector.x + y * theVector.y; + } + + public Vector2f cross(Vector2f theVector) { + x = theVector.y; + y = -theVector.x; + return this; + } + + public Vector2f cross() { + final float myX = y; + y = -x; + x = myX; + return this; + } + + public float length() { + return (float) Math.sqrt(x * x + y * y); + } + + public float lengthSquared() { + return x * x + y * y; + } + + public Vector2f normalize(Vector2f theVector) { + float inverseMag = 1.0f / (float) Math.sqrt(theVector.x * theVector.x + theVector.y * theVector.y); + x = theVector.x * inverseMag; + y = theVector.y * inverseMag; + return this; + } + + public Vector2f normalize() { + float inverseMag = 1.0f / (float) Math.sqrt(x * x + y * y); + x *= inverseMag; + y *= inverseMag; + return this; + } + + public float angle(Vector2f theVector) { + float d = dot(theVector) / (length() * theVector.length()); + if (d < -1.0f) { + d = -1.0f; + } + if (d > 1.0f) { + d = 1.0f; + } + return (float) Math.acos(d); + } + + public Vector2f rotate(float theRadians) { + final float myX = (float) (x * Math.cos(theRadians) - y * Math.sin(theRadians)); + final float myY = (float) (y * Math.cos(theRadians) + x * Math.sin(theRadians)); + x = myX; + y = myY; + return this; + } + + public final float distanceSquared(Vector2f thePoint) { + float dx = x - thePoint.x; + float dy = y - thePoint.y; + return dx * dx + dy * dy; + } + + public float distance(Vector2f thePoint) { + float dx = x - thePoint.x; + float dy = y - thePoint.y; + return (float) Math.sqrt(dx * dx + dy * dy); + } + + public float[] toArray() { + final float[] _myArrayRepresentation = new float[2]; + _myArrayRepresentation[0] = x; + _myArrayRepresentation[1] = y; + return _myArrayRepresentation; + } + + public boolean isNaN() { + if (Float.isNaN(x) || Float.isNaN(y)) { + return true; + } else { + return false; + } + } + + public boolean equals(Vector2f theVector) { + if (x == theVector.x && y == theVector.y) { + return true; + } else { + return false; + } + } + + public int hashCode() { + int hash = 5; + hash = 73 * hash + Float.floatToIntBits(this.x); + hash = 73 * hash + Float.floatToIntBits(this.y); + return hash; + } + + public boolean equals(final Object theVector) { + if (!(theVector instanceof Vector2f)) { + return false; + } + return equals((Vector2f) theVector); + } + + /** + * Returns true if both x and y are zero + * + * @return boolean, true if the vector is zero + */ + public boolean equalsZero() { + return x == 0 && y == 0; + } + + public boolean almost(Vector2f theVector) { + if (Math.abs(x - theVector.x) < ALMOST_THRESHOLD + && Math.abs(y - theVector.y) < ALMOST_THRESHOLD) { + return true; + } else { + return false; + } + } + + public String toString() { + return "(" + x + ", " + y + ")"; + } +} diff --git a/day3/libs/mathematik/src/mathematik/Vector2i.java b/day3/libs/mathematik/src/mathematik/Vector2i.java new file mode 100755 index 0000000..13c5105 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Vector2i.java @@ -0,0 +1,123 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +public class Vector2i + implements Serializable { + + private static final long serialVersionUID = 1578087698419866994L; + + public int x; + + public int y; + + public Vector2i() { + x = 0; + y = 0; + } + + public Vector2i(int theX, + int theY) { + set(theX, + theY); + } + + public Vector2i(Vector2i theVector) { + set(theVector); + } + + public Vector2i(int[] theVector) { + set(theVector); + } + + public void set(int theX, + int theY) { + x = theX; + y = theY; + } + + public void set(Vector2i theVector) { + x = theVector.x; + y = theVector.y; + } + + public void set(int[] theVector) { + x = theVector[0]; + y = theVector[1]; + } + + public final void sub(final Vector2i theVectorA, + final Vector2i theVectorB) { + x = theVectorA.x - theVectorB.x; + y = theVectorA.y - theVectorB.y; + } + + public final void sub(final Vector2i theVector) { + x -= theVector.x; + y -= theVector.y; + } + + public final void sub(final int theX, final int theY) { + x -= theX; + y -= theY; + } + + public final void add(final Vector2i theVectorA, + final Vector2i theVectorB) { + x = theVectorA.x + theVectorB.x; + y = theVectorA.y + theVectorB.y; + } + + public final void add(final Vector2i theVector) { + x += theVector.x; + y += theVector.y; + } + + public final void add(final int theX, final int theY) { + x += theX; + y += theY; + } + + public final void scale(float theScalar, + Vector2i theVector) { + x = (int) (theScalar * theVector.x); + y = (int) (theScalar * theVector.y); + } + + public final void scale(float theScalar) { + x *= theScalar; + y *= theScalar; + } + + public final void scale(Vector2i theVector) { + x *= theVector.x; + y *= theVector.y; + } + + public final String toString() { + return "(" + x + ", " + y + ")"; + } +} diff --git a/day3/libs/mathematik/src/mathematik/Vector3f.java b/day3/libs/mathematik/src/mathematik/Vector3f.java new file mode 100755 index 0000000..bb8057b --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Vector3f.java @@ -0,0 +1,629 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; +import java.util.Random; + + +public class Vector3f + implements Cloneable, Serializable, Comparable, Vectorf { + + private static final long serialVersionUID = -1021495605082676516L; + + /** + * Utility for random + */ + static final Random generator = new Random(); + + /** + * The x coordinate of the vector + */ + public float x; + + /** + * The y coordinate of the vector + */ + public float y; + + /** + * The z coordinate of the vector + */ + public float z; + +// /** +// * float array for returning an array representation of the vector +// */ +// private float[] _myArrayRepresentation = new float[3]; + /** + * threshold to maintain the minimal difference between two vectors before + * they are almost the same + */ + private static final float ALMOST_THRESHOLD = 0.001f; + + /** + * Initializes a new vector. x, y, and z are set to zero. + */ + public Vector3f() { + x = 0.0f; + y = 0.0f; + z = 0.0f; + } + + /** + * Creates a new vector with the given coordinates. Inserted double values + * are casted to floats + * + * @param theX int, float or double: x coord of the new vector + * @param theY int, float or double: y coord of the new vector + * @param theZ int, float or double: z coord of the new vector + */ + public Vector3f(float theX, float theY, float theZ) { + set(theX, theY, theZ); + } + + public Vector3f(double theX, double theY, double theZ) { + set(theX, theY, theZ); + } + + public Vector3f(float theX, float theY) { + set(theX, theY); + } + + public Vector3f(double theX, double theY) { + set(theX, theY); + } + + public Vector3f(float[] theVector) { + set(theVector); + } + + public Vector3f(double[] theVector) { + set(theVector); + } + + public Vector3f(int[] theVector) { + set(theVector); + } + + public Vector3f(Vector3f theVector) { + set(theVector); + } + + public Vector3f(Vector2f theVector) { + set(theVector); + } + + public Vector3f(Vector3i theVector) { + set(theVector); + } + + public Vector3f(Vector2i theVector) { + set(theVector); + } + + public Vector3f(String theVector) { + set(theVector); + } + + public final Vector3f set(float theX, float theY, float theZ) { + x = theX; + y = theY; + z = theZ; + return this; + } + + public final Vector3f set(double theX, double theY, double theZ) { + x = (float) theX; + y = (float) theY; + z = (float) theZ; + return this; + } + + public final Vector3f set(float theX, float theY) { + x = theX; + y = theY; + return this; + } + + public final Vector3f set(double theX, double theY) { + x = (float) theX; + y = (float) theY; + return this; + } + + public final Vector3f set(float[] theVector) { + x = theVector[0]; + y = theVector[1]; + z = theVector[2]; + return this; + } + + public final Vector3f set(double[] theVector) { + x = (float) theVector[0]; + y = (float) theVector[1]; + z = (float) theVector[2]; + return this; + } + + public final Vector3f set(int[] theVector) { + x = theVector[0]; + y = theVector[1]; + z = theVector[2]; + return this; + } + + public final Vector3f set(Vector3f theVector) { + x = theVector.x; + y = theVector.y; + z = theVector.z; + return this; + } + + public final Vector3f set(Vector2f theVector) { + x = theVector.x; + y = theVector.y; + return this; + } + + public final Vector3f set(Vector3i theVector) { + x = theVector.x; + y = theVector.y; + z = theVector.z; + return this; + } + + public final Vector3f set(Vector2i theVector) { + x = theVector.x; + y = theVector.y; + return this; + } + + public final Vector3f set(String theVectorString) { + theVectorString = theVectorString.replace("(", ""); + theVectorString = theVectorString.replace(")", ""); + theVectorString = theVectorString.replaceAll(" ", ""); + String[] myComponents = theVectorString.split(","); + + try { + x = Float.parseFloat(myComponents[0]); + } catch (Exception ex) { + } + try { + y = Float.parseFloat(myComponents[1]); + } catch (Exception ex1) { + } + try { + z = Float.parseFloat(myComponents[2]); + } catch (Exception ex2) { + } + return this; + } + + public Vector3f add(Vector3f theVectorA, Vector3f theVectorB) { + x = theVectorA.x + theVectorB.x; + y = theVectorA.y + theVectorB.y; + z = theVectorA.z + theVectorB.z; + return this; + } + + public Vector3f add(Vector3f theVector) { + x += theVector.x; + y += theVector.y; + z += theVector.z; + return this; + } + + public Vector3f add(float theX, float theY) { + x += theX; + y += theY; + return this; + } + + public Vector3f add(float theX, float theY, float theZ) { + x += theX; + y += theY; + z += theZ; + return this; + } + + public Vector3f sub(Vector3f theVectorA, Vector3f theVectorB) { + x = theVectorA.x - theVectorB.x; + y = theVectorA.y - theVectorB.y; + z = theVectorA.z - theVectorB.z; + return this; + } + + public Vector3f sub(Vector3f theVector) { + x -= theVector.x; + y -= theVector.y; + z -= theVector.z; + return this; + } + + /** + * Use this method to negate a vector. The result of the negation is vector + * with the same magnitude but opposite direction. Mathematically the + * negation is the additive inverse of the vector. The sum of a value and + * its additive inerse is always zero. + * + * @shortdesc Use this method to negate a vector. + * @related scale ( ) + */ + public Vector3f negate() { + scale(-1); + return this; + } + + /** + * Use this method to scale a vector. To scale a vector each of its + * coordinates is multiplied with the given scalar. The result is a vector + * that is parallel with its origin, with a different length and possibly + * opposite direction.
+ * You can also scale a vector with another vector, in this case each coord + * of the vector is multiplied with related coord of the given vector.
+ * Another possibillity is to set and scale the vector, this means the + * vector is set to the given vector multiplied with the given scalar. + * + * @param theScalar float or int: the value the vector is scaled with + * @related divide ( ) + * @related negate ( ) + */ + public Vector3f scale(final float theScalar) { + x *= theScalar; + y *= theScalar; + z *= theScalar; + return this; + } + + /** + * + * @param theVector Vector3f: vector with the value each coord is scaled + * with + */ + public Vector3f scale(final Vector3f theVector) { + x *= theVector.x; + y *= theVector.y; + z *= theVector.z; + return this; + } + + /** + * + * @param theX float + * @param theY float + * @param theZ float + */ + public Vector3f scale(float theX, float theY, float theZ) { + x *= theX; + y *= theY; + z *= theZ; + return this; + } + + /** + * @param theScalar float or int: value the given vector is scaled with + * @param theVector Vector3f: vector the vector is set to + */ + public Vector3f scale(final float theScalar, final Vector3f theVector) { + x = theScalar * theVector.x; + y = theScalar * theVector.y; + z = theScalar * theVector.z; + return this; + } + + /** + * Dividing is nearly the the same as scaling, except + * + * @param theDivisor + */ + public Vector3f divide(final float theDivisor) { + x /= theDivisor; + y /= theDivisor; + z /= theDivisor; + return this; + } + + public Vector3f divide(final Vector3f theVector) { + x /= theVector.x; + y /= theVector.y; + z /= theVector.z; + return this; + } + + public float lengthSquared() { + return x * x + y * y + z * z; + } + + /** + * Use this method to calculate the length of a vector, the length of a + * vector is also known as its magnitude. Vectors have a magnitude and a + * direction. These values are not explicitly expressed in the vector so + * they have to be computed. + * + * @return float: the length of the vector + * @shortdesc Calculates the length of the vector. + */ + public float length() { + return (float) Math.sqrt(lengthSquared()); + } + + public float magnitude() { + return length(); + } + + /** + * Sets this vector to the cross product of two given vectors. The cross + * product returns a vector standing vertical on the two vectors. + * + * @param theVectorA + * @param theVectorB + */ + public Vector3f cross(final Vector3f theVectorA, final Vector3f theVectorB) { + return set(theVectorA.cross(theVectorB)); + } + + /** + * Returns the cross product of two vectors. The cross product returns a + * vector standing vertical on the two vectors. + * + * @param i_vector the other vector + * @return the cross product + */ + public Vector3f cross(final Vector3f theVector) { + return new Vector3f(y * theVector.z - z * theVector.y, + z * theVector.x - x * theVector.z, + x * theVector.y - y * theVector.x); + } + + /** + * Returns the dot product of two vectors. The dot product is the cosinus of + * the angle between two vectors + * + * @param theVector, the other vector + * @return float, dot product of two vectors + */ + public float dot(Vector3f theVector) { + return x * theVector.x + y * theVector.y + z * theVector.z; + } + + /** + * Sets the vector to the given one and norms it to the length of 1 + * + */ + public Vector3f normalize(Vector3f theVector) { + set(theVector); + normalize(); + return this; + } + + /** + * Norms the vector to the length of 1 + * + */ + public Vector3f normalize() { + float inverseMag = 1.0f / (float) Math.sqrt(x * x + y * y + z * z); + x *= inverseMag; + y *= inverseMag; + z *= inverseMag; + return this; + } + + /** + * Interpolates between this vector and the given vector by a given blend + * value. The blend value has to be between 0 and 1. A blend value 0 would + * change nothing, a blend value 1 would set this vector to the given one. + * + * @param blend float, blend value for interpolation + * @param i_vector Vector3f, other vector for interpolation + */ + public void interpolate(final float blend, final Vector3f i_vector) { + x = x + blend * (i_vector.x - x); + y = y + blend * (i_vector.y - y); + z = z + blend * (i_vector.z - z); + } + + /** + * Sets a position randomly distributed inside a sphere of unit radius + * centered at the origin. Orientation will be random and length will range + * between 0 and 1 + */ + public void randomize() { + x = generator.nextFloat() * 2.0F - 1.0F; + y = generator.nextFloat() * 2.0F - 1.0F; + z = generator.nextFloat() * 2.0F - 1.0F; + normalize(); + } + + public float angle(Vector3f theVector) { + float d = dot(theVector) / (length() * theVector.length()); + /** + * @todo check these lines. + */ + if (d < -1.0f) { + d = -1.0f; + } + if (d > 1.0f) { + d = 1.0f; + } + return (float) Math.acos(d); + } + + public float distanceSquared(Vector3f thePoint) { + float dx = x - thePoint.x; + float dy = y - thePoint.y; + float dz = z - thePoint.z; + return dx * dx + dy * dy + dz * dz; + } + + public float distance(Vector3f thePoint) { + float dx = x - thePoint.x; + float dy = y - thePoint.y; + float dz = z - thePoint.z; + return (float) Math.sqrt(dx * dx + dy * dy + dz * dz); + } + + public float distanceL1(Vector3f thePoint) { + return Math.abs(x - thePoint.x) + Math.abs(y - thePoint.y) + + Math.abs(z - thePoint.z); + } + + public Vector3f min(Vector3f theMin) { + if (x < theMin.x) { + x = theMin.x; + } + if (y < theMin.y) { + y = theMin.y; + } + if (z < theMin.z) { + z = theMin.z; + } + return this; + } + + public Vector3f min(float theX, float theY, float theZ) { + if (x < theX) { + x = theX; + } + if (y < theY) { + y = theY; + } + if (z < theZ) { + z = theZ; + } + return this; + } + + public Vector3f max(Vector3f theMax) { + if (x > theMax.x) { + x = theMax.x; + } + if (y > theMax.y) { + y = theMax.y; + } + if (z > theMax.z) { + z = theMax.z; + } + return this; + } + + public Vector3f max(float theX, float theY, float theZ) { + if (x > theX) { + x = theX; + } + if (y > theY) { + y = theY; + } + if (z > theZ) { + z = theZ; + } + return this; + } + + public float[] toArray() { + final float[] _myArrayRepresentation = new float[3]; + _myArrayRepresentation[0] = x; + _myArrayRepresentation[1] = y; + _myArrayRepresentation[2] = z; + return _myArrayRepresentation; + } + + public boolean isNaN() { + if (Float.isNaN(x) || Float.isNaN(y) || Float.isNaN(z)) { + return true; + } else { + return false; + } + } + + public boolean equals(final Vector3f theVector) { + if (x == theVector.x && y == theVector.y && z == theVector.z) { + return true; + } else { + return false; + } + } + + public int hashCode() { + int hash = 7; + hash = 17 * hash + Float.floatToIntBits(this.x); + hash = 17 * hash + Float.floatToIntBits(this.y); + hash = 17 * hash + Float.floatToIntBits(this.z); + return hash; + } + + public boolean equals(final Object theVector) { + if (!(theVector instanceof Vector3f)) { + return false; + } + return equals((Vector3f) theVector); + } + + public boolean almost(final Vector3f theVector) { + if (Math.abs(x - theVector.x) < ALMOST_THRESHOLD + && Math.abs(y - theVector.y) < ALMOST_THRESHOLD + && Math.abs(z - theVector.z) < ALMOST_THRESHOLD) { + return true; + } else { + return false; + } + } + + public Object clone() { + try { + return super.clone(); + } catch (CloneNotSupportedException e) { + // this shouldn t happen, since we are Cloneable + throw new InternalError(); + } + } + + public String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } + public static final int X = 0; + + public static final int Y = 1; + + public static final int Z = 2; + + public static final int LENGTH = 3; + + public static int COMPARE_TYPE = LENGTH; + + public int compareTo(Vector3f theVector3f) { + if (COMPARE_TYPE == LENGTH) { + final float myLengthSquared = lengthSquared(); + final float myOtherLengthSquared = theVector3f.lengthSquared(); + return myLengthSquared > myOtherLengthSquared ? 1 : (myLengthSquared < myOtherLengthSquared ? -1 : 0); + } else if (COMPARE_TYPE == X) { + return x > theVector3f.x ? 1 : (x < theVector3f.x ? -1 : 0); + } else if (COMPARE_TYPE == Y) { + return y > theVector3f.y ? 1 : (y < theVector3f.y ? -1 : 0); + } else if (COMPARE_TYPE == Z) { + return z > theVector3f.z ? 1 : (z < theVector3f.z ? -1 : 0); + } else { + return 0; + } + } +} diff --git a/day3/libs/mathematik/src/mathematik/Vector3i.java b/day3/libs/mathematik/src/mathematik/Vector3i.java new file mode 100755 index 0000000..fe47752 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Vector3i.java @@ -0,0 +1,86 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +public class Vector3i + implements Serializable, Comparable { + + private static final long serialVersionUID = -1207335169644019377L; + + public int x; + + public int y; + + public int z; + + public Vector3i() { + x = 0; + y = 0; + z = 0; + } + + public Vector3i(int theX, int theY, int theZ) { + set(theX, theY, theZ); + } + + public Vector3i(Vector3i theVector) { + set(theVector); + } + + public Vector3i(int[] theVector) { + set(theVector); + } + + public void set(int theX, int theY, int theZ) { + x = theX; + y = theY; + z = theZ; + } + + public void set(Vector3i theVector) { + x = theVector.x; + y = theVector.y; + z = theVector.z; + } + + public void set(int[] theVector) { + x = theVector[0]; + y = theVector[1]; + z = theVector[2]; + } + + public final String toString() { + return "(" + x + ", " + y + ", " + z + ")"; + } + + public final float lengthSquared() { + return x * x + y * y + z * z; + } + + public int compareTo(Vector3i theVector3i) { + return (int) (lengthSquared() - theVector3i.lengthSquared()); + } +} diff --git a/day3/libs/mathematik/src/mathematik/Vector4f.java b/day3/libs/mathematik/src/mathematik/Vector4f.java new file mode 100755 index 0000000..da10aa8 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Vector4f.java @@ -0,0 +1,307 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +import java.io.Serializable; + + +public class Vector4f + implements Serializable, Vectorf { + + private static final long serialVersionUID = 5083919691492230155L; + + public float w; + + public float x; + + public float y; + + public float z; + + private static final float ALMOST_THRESHOLD = 0.001f; + + public Vector4f() { + x = 0; + y = 0; + z = 0; + w = 0; + } + + public Vector4f(float theX, + float theY, + float theZ, + float theW) { + set(theX, + theY, + theZ, + theW); + } + + public Vector4f(double theX, + double theY, + double theZ, + double theW) { + set(theX, + theY, + theZ, + theW); + } + + public Vector4f(float theX, + float theY, + float theZ) { + set(theX, + theY, + theZ); + } + + public Vector4f(double theX, + double theY, + double theZ) { + set(theX, + theY, + theZ); + } + + public Vector4f(float theX, + float theY) { + set(theX, + theY); + } + + public Vector4f(double theX, + double theY) { + set(theX, + theY); + } + + public Vector4f(float[] theVector) { + set(theVector); + } + + public Vector4f(double[] theVector) { + set(theVector); + } + + public Vector4f(Vector4f theVector) { + set(theVector); + } + + public Vector4f(Vector3f theVector) { + set(theVector); + } + + public Vector4f(Vector2f theVector) { + set(theVector); + } + + public final void set(float theX, + float theY, + float theZ, + float theW) { + x = theX; + y = theY; + z = theZ; + w = theW; + } + + public final void set(double theX, + double theY, + double theZ, + double theW) { + x = (float) theX; + y = (float) theY; + z = (float) theZ; + w = (float) theW; + } + + public final void set(float theX, + float theY, + float theZ) { + x = theX; + y = theY; + z = theZ; + } + + public final void set(double theX, + double theY, + double theZ) { + x = (float) theX; + y = (float) theY; + z = (float) theZ; + } + + public final void set(float theX, + float theY) { + x = theX; + y = theY; + } + + public final void set(double theX, + double theY) { + x = (float) theX; + y = (float) theY; + } + + public final void set(float[] theVector) { + w = theVector[0]; + x = theVector[1]; + y = theVector[2]; + z = theVector[3]; + } + + public final void set(double[] theVector) { + w = (float) theVector[0]; + x = (float) theVector[1]; + y = (float) theVector[2]; + z = (float) theVector[3]; + } + + public final void set(Vector4f theVector) { + x = theVector.x; + y = theVector.y; + z = theVector.z; + w = theVector.w; + } + + public final void set(Vector3f theVector) { + x = theVector.x; + y = theVector.y; + z = theVector.z; + } + + public final void set(Vector2f theVector) { + x = theVector.x; + y = theVector.y; + } + + public final void add(Vector4f theVectorA, + Vector4f theVectorB) { + w = theVectorA.w + theVectorB.w; + x = theVectorA.x + theVectorB.x; + y = theVectorA.y + theVectorB.y; + z = theVectorA.z + theVectorB.z; + } + + public final void add(Vector4f theVector) { + w += theVector.w; + x += theVector.x; + y += theVector.y; + z += theVector.z; + } + + public final void sub(Vector4f theVectorA, + Vector4f theVectorB) { + w = theVectorA.w - theVectorB.w; + x = theVectorA.x - theVectorB.x; + y = theVectorA.y - theVectorB.y; + z = theVectorA.z - theVectorB.z; + } + + public final void sub(Vector4f theVector) { + w -= theVector.w; + x -= theVector.x; + y -= theVector.y; + z -= theVector.z; + } + + public final void scale(float theScalar, + Vector4f theVector) { + w = theScalar * theVector.w; + x = theScalar * theVector.x; + y = theScalar * theVector.y; + z = theScalar * theVector.z; + } + + public final void scale(float theScalar) { + w *= theScalar; + x *= theScalar; + y *= theScalar; + z *= theScalar; + } + + public final float lengthSquared() { + return w * w + x * x + y * y + z * z; + } + + public final float length() { + return (float) Math.sqrt(w * w + x * x + y * y + z * z); + } + + public final float dot(Vector4f theVector) { + return x * theVector.x + y * theVector.y + z * theVector.z + w * theVector.w; + } + + public void normalize(Vector4f theVector) { + set(theVector); + normalize(); + } + + public final void normalize() { + final float d = 1 / length(); + x *= d; + y *= d; + z *= d; + w *= d; + } + + public final float[] toArray() { + final float[] _myArrayRepresentation = new float[4]; + _myArrayRepresentation[0] = x; + _myArrayRepresentation[1] = y; + _myArrayRepresentation[2] = z; + _myArrayRepresentation[3] = w; + return _myArrayRepresentation; + } + + public final boolean isNaN() { + if (Float.isNaN(x) || Float.isNaN(y) || Float.isNaN(z) || Float.isNaN(w)) { + return true; + } else { + return false; + } + } + + public final boolean equals(Vector4f theVector) { + if (w == theVector.w && x == theVector.x && y == theVector.y && z == theVector.z) { + return true; + } else { + return false; + } + } + + public final boolean almost(Vector4f theVector) { + if (Math.abs(w) - Math.abs(theVector.w) < ALMOST_THRESHOLD + && Math.abs(x) - Math.abs(theVector.x) < ALMOST_THRESHOLD + && Math.abs(y) - Math.abs(theVector.y) < ALMOST_THRESHOLD + && Math.abs(z) - Math.abs(theVector.z) < ALMOST_THRESHOLD) { + return true; + } else { + return false; + } + } + + public final String toString() { + return "(" + x + ", " + y + ", " + z + ", " + w + ")"; + } +} diff --git a/day3/libs/mathematik/src/mathematik/Vectorf.java b/day3/libs/mathematik/src/mathematik/Vectorf.java new file mode 100755 index 0000000..d715b27 --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/Vectorf.java @@ -0,0 +1,26 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +public interface Vectorf { +} diff --git a/day3/libs/mathematik/src/mathematik/WorldAxisAlignedBoundingBox.java b/day3/libs/mathematik/src/mathematik/WorldAxisAlignedBoundingBox.java new file mode 100755 index 0000000..b96deee --- /dev/null +++ b/day3/libs/mathematik/src/mathematik/WorldAxisAlignedBoundingBox.java @@ -0,0 +1,37 @@ +/* + * Mathematik + * + * Copyright (C) 2012 Patrick Kochlik + Dennis Paul + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package mathematik; + + +public class WorldAxisAlignedBoundingBox { + + /** + * center of bounding box + */ + public Vector3f position = new Vector3f(); + + /** + * scale around the center + */ + public Vector3f scale = new Vector3f(); + +} diff --git a/day3/libs/teilchen/examples/Lesson00_Particle/Lesson00_Particle.pde b/day3/libs/teilchen/examples/Lesson00_Particle/Lesson00_Particle.pde new file mode 100755 index 0000000..a1b283a --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson00_Particle/Lesson00_Particle.pde @@ -0,0 +1,71 @@ +import mathematik.*; + +import processing.opengl.*; + +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; + +/** + * this sketch show how to create a particle system with a single particle in it. + */ + +Physics mPhysics; + +Particle mParticle; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system. */ + mPhysics = new Physics(); + + /* + * a physic-based particle system consists of a few components. + * + * 1 particles. + * there are different kinds of particles. for now we use a simple particle. + * + * 2 forces. + * there are all kinds of forces. one of the most obvious force is the gravitational force, + * but there all kinds of different forces like attractors and springs. forces usually + * affect all particles in the system. + * + * 3 behaviors + * a behavior is special kind of force. it is something like an internal force or a motor + * that only affects a single particle. a typical force is for example the 'seek force' + * which constantly pulls a particle into a certain direction. + * + * 4 integrators. + * integrators are used to integrate acceleration and velocity to calculate the new position. + * the most well-known is the 'euler' integrator, but there are also optimized versions like 'runge-kutta' + * or 'Midpoint' or even slightly different concepts like 'verlet'. + * + */ + + /* create a particle. note that the particle is automatically added to particle system */ + mParticle = mPhysics.makeParticle(); +} + +void draw() { + /* update the particle system to the next step. usually the time step is the duration of the las frame */ + final float mDeltaTime = 1.0 / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particle */ + background(255); + stroke(0, 127); + fill(0, 32); + ellipse(mParticle.position().x, mParticle.position().y, 12, 12); + + /* reset particle s position and velocity */ + if (mousePressed) { + mParticle.position().set(mouseX, mouseY); + mParticle.velocity().set(mouseX - pmouseX, mouseY - pmouseY); + mParticle.velocity().scale(10); + } +} + diff --git a/day3/libs/teilchen/examples/Lesson01_Gravity/Lesson01_Gravity.pde b/day3/libs/teilchen/examples/Lesson01_Gravity/Lesson01_Gravity.pde new file mode 100755 index 0000000..3d7e16e --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson01_Gravity/Lesson01_Gravity.pde @@ -0,0 +1,54 @@ +import processing.opengl.*; + +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Gravity; + +/** + * this sketch show how to create a particle system with a single particle in it. + */ + +Physics mPhysics; + +Particle mParticle; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a gravitational force */ + Gravity mGravity = new Gravity(); + /* the direction of the gravity is defined by the 'force' vector */ + mGravity.force().set(0, 30, 0); + /* forces, like gravity or any other force, can be added to the system. they will be automatically applied to all particles */ + mPhysics.add(mGravity); + + /* create a particle and add it to the system */ + mParticle = mPhysics.makeParticle(); +} + +void draw() { + /* update the particle system. this applies the gravity to the particle */ + final float mDeltaTime = 1.0 / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particle */ + background(255); + stroke(0, 127); + fill(0, 32); + ellipse(mParticle.position().x, mParticle.position().y, 12, 12); + + /* reset particle s position and velocity */ + if (mousePressed) { + mParticle.position().set(mouseX, mouseY); + mParticle.velocity().set(mouseX - pmouseX, mouseY - pmouseY); + mParticle.velocity().scale(10); + } +} + diff --git a/day3/libs/teilchen/examples/Lesson02_Particles/Lesson02_Particles.pde b/day3/libs/teilchen/examples/Lesson02_Particles/Lesson02_Particles.pde new file mode 100755 index 0000000..eacf47b --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson02_Particles/Lesson02_Particles.pde @@ -0,0 +1,58 @@ +import processing.opengl.*; + +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Gravity; + +/** + * this sketch shows how to create and handle multiple particles and remove individual particles. + */ + +Physics mPhysics; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a gravitational force and add it to the particle system */ + Gravity myGravity = new Gravity(0, 30, 0); + mPhysics.add(myGravity); +} + +void draw() { + if (mousePressed) { + /* create and add a particle to the system */ + Particle mParticle = mPhysics.makeParticle(); + /* set particle to mouse position with random velocity */ + mParticle.position().set(mouseX, mouseY); + mParticle.velocity().set(random(-20, 20), random(-50)); + } + + /* update the particle system */ + final float mDeltaTime = 1.0 / frameRate; + mPhysics.step(mDeltaTime); + + /* remove particles right before they hit the edge of the screen */ + for (int i = 0; i < mPhysics.particles().size(); i++) { + Particle mParticle = mPhysics.particles(i); + if (mParticle.position().y > height * 0.9f) { + mPhysics.particles().remove(i); + } + } + + /* draw all the particles in the system */ + background(255); + stroke(0, 127); + fill(0, 32); + for (int i = 0; i < mPhysics.particles().size(); i++) { + Particle mParticle = mPhysics.particles(i); + ellipse(mParticle.position().x, mParticle.position().y, 10, 10); + } +} + diff --git a/day3/libs/teilchen/examples/Lesson03_Attractors/Lesson03_Attractors.pde b/day3/libs/teilchen/examples/Lesson03_Attractors/Lesson03_Attractors.pde new file mode 100755 index 0000000..20e4526 --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson03_Attractors/Lesson03_Attractors.pde @@ -0,0 +1,88 @@ +import processing.opengl.*; + +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.Teleporter; +import teilchen.force.Attractor; +import teilchen.force.ViscousDrag; + +/** + * this sketch shows how to create and use attractors. + */ + +Physics mPhysics; + +Attractor mAttractor; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a viscous force that slows down all motion */ + ViscousDrag myDrag = new ViscousDrag(); + myDrag.coefficient = 0.75f; + mPhysics.add(myDrag); + + /* teleport particles from one edge of the screen to the other */ + Teleporter mTeleporter = new Teleporter(); + mTeleporter.min().set(0, 0); + mTeleporter.max().set(width, height); + mPhysics.add(mTeleporter); + + /* create some particles */ + for (int i = 0; i < 100; i++) { + Particle myParticle = mPhysics.makeParticle(); + myParticle.position().set(random(width), random(height)); + } + + /* create an attractor */ + mAttractor = new Attractor(); + mAttractor.radius(100); + mAttractor.strength(150); + mPhysics.add(mAttractor); +} + +void mousePressed() { + /* flip the direction of the attractors strength. */ + float myInvertedStrength = -1 * mAttractor.strength(); + /* a negative strength turns the attractor into a repulsor */ + mAttractor.strength(myInvertedStrength); +} + +void draw() { + /* set attractor to mouse position */ + mAttractor.position().set(mouseX, mouseY); + + /* update the particle system */ + final float mDeltaTime = 1.0 / frameRate; + mPhysics.step(mDeltaTime); + + /* draw */ + background(255); + + /* draw all the particles in particle system */ + fill(245); + stroke(164); + for (int i = 0; i < mPhysics.particles().size(); i++) { + Particle myParticle = mPhysics.particles(i); + ellipse(myParticle.position().x, myParticle.position().y, 12, 12); + } + + /* draw attractor. green if it is attracting and red if it is repelling */ + noStroke(); + if (mAttractor.strength() < 0) { + fill(255, 0, 0, 50); + } + else { + fill(0, 255, 0, 50); + } + ellipse(mAttractor.position().x, mAttractor.position().y, + mAttractor.radius(), mAttractor.radius()); +} + diff --git a/day3/libs/teilchen/examples/Lesson04_Deflectors/Lesson04_Deflectors.pde b/day3/libs/teilchen/examples/Lesson04_Deflectors/Lesson04_Deflectors.pde new file mode 100755 index 0000000..9c46e84 --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson04_Deflectors/Lesson04_Deflectors.pde @@ -0,0 +1,102 @@ +import processing.opengl.*; + +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.ShortLivedParticle; +import teilchen.force.Gravity; +import teilchen.force.PlaneDeflector; +import teilchen.force.ViscousDrag; + +/** + * this sketch shows + * 1 how to create and use plane deflectors + * 2 how to use 'ShortLivedParticle' + */ + +Physics mPhysics; + +PlaneDeflector mDeflector; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a deflector and add it to the particle system. + * the that defines the deflection area is defined by an + * origin and a normal. this also means that the plane s size + * is infinite. + * note that there is also a triangle delfector that is constraint + * by three points. + */ + mDeflector = new PlaneDeflector(); + /* set plane origin into the center of the screen */ + mDeflector.plane().origin.set(width / 2, height / 2, 0); + mDeflector.plane().normal.set(0, -1, 0); + /* the coefficient of restitution defines how hard particles bounce of the deflector */ + mDeflector.coefficientofrestitution(0.7f); + mPhysics.add(mDeflector); + + /* create gravitiy */ + Gravity myGravity = new Gravity(); + myGravity.force().y = 50; + mPhysics.add(myGravity); + + /* create drag */ + ViscousDrag myViscousDrag = new ViscousDrag(); + myViscousDrag.coefficient = 0.1f; + mPhysics.add(myViscousDrag); +} + +void draw() { + /* rotate deflector plane */ + if (mousePressed) { + final float myAngle = 2 * PI * (float)mouseX / width - PI; + mDeflector.plane().normal.set(sin(myAngle), -cos(myAngle), 0); + } + + /* create a special particle */ + ShortLivedParticle myNewParticle = new ShortLivedParticle(); + myNewParticle.position().set(mouseX, mouseY); + myNewParticle.velocity().set(0, random(100) + 50); + /* this particle is removed after a specific interval */ + myNewParticle.setMaxAge(4); + /* add particle manually to the particle system */ + mPhysics.add(myNewParticle); + + /* update physics */ + final float mDeltaTime = 1.0 / frameRate; + mPhysics.step(mDeltaTime); + + /* draw all the particles in the particle system */ + background(255); + for (int i = 0; i < mPhysics.particles().size(); i++) { + Particle myParticle = mPhysics.particles(i); + /* this special particle can tell you how much time it has to live. + * we map this information to its transparency. + */ + float myRatio = 1 - ((ShortLivedParticle)myParticle).ageRatio(); + stroke(0, 64 * myRatio); + fill(0, 32 * myRatio); + ellipse(myParticle.position().x, myParticle.position().y, 12, 12); + } + + /* draw deflector */ + stroke(0, 127); + line(mDeflector.plane().origin.x - mDeflector.plane().normal.y * -width, + mDeflector.plane().origin.y + mDeflector.plane().normal.x * -width, + mDeflector.plane().origin.x - mDeflector.plane().normal.y * width, + mDeflector.plane().origin.y + mDeflector.plane().normal.x * width); + + stroke(255, 0, 0, 127); + line(mDeflector.plane().origin.x, + mDeflector.plane().origin.y, + mDeflector.plane().origin.x + mDeflector.plane().normal.x * 20, + mDeflector.plane().origin.y + mDeflector.plane().normal.y * 20); +} + diff --git a/day3/libs/teilchen/examples/Lesson05_Spring/Lesson05_Spring.pde b/day3/libs/teilchen/examples/Lesson05_Spring/Lesson05_Spring.pde new file mode 100755 index 0000000..64d9e80 --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson05_Spring/Lesson05_Spring.pde @@ -0,0 +1,68 @@ +import processing.opengl.*; + +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; + +/** + * this sketch shows + * 1 how to create a viscous drag to slow motion eventually down. + * 2 how to create a spring that connects two particles. + */ + +Physics mPhysics; + +Spring mSpring; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a viscous force that slows down all motion; 0 means no slowing down. */ + ViscousDrag myDrag = new ViscousDrag(0.25f); + mPhysics.add(myDrag); + + /* create two particles that we can connect with a spring */ + Particle myA = mPhysics.makeParticle(); + myA.position().set(width / 2 - 50, height / 2); + + Particle myB = mPhysics.makeParticle(); + myB.position().set(width / 2 + 50, height / 2); + + /* create a spring force that connects two particles. + * note that there is more than one way to create a spring. + * in our case the restlength of the spring is defined by the + * particles current position. + */ + mSpring = mPhysics.makeSpring(myA, myB); +} + +void draw() { + /* set first particle to mouse position */ + if (mousePressed) { + mSpring.a().position().set(mouseX, mouseY); + } + + /* update the particle system */ + final float mDeltaTime = 1.0 / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particles and connecting line */ + background(255); + noFill(); + stroke(255, 0, 127, 64); + line(mSpring.a().position().x, mSpring.a().position().y, + mSpring.b().position().x, mSpring.b().position().y); + fill(245); + stroke(164); + ellipse(mSpring.a().position().x, mSpring.a().position().y, 12, 12); + ellipse(mSpring.b().position().x, mSpring.b().position().y, 12, 12); +} + diff --git a/day3/libs/teilchen/examples/Lesson06_Springs/Lesson06_Springs.pde b/day3/libs/teilchen/examples/Lesson06_Springs/Lesson06_Springs.pde new file mode 100755 index 0000000..8c8978b --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson06_Springs/Lesson06_Springs.pde @@ -0,0 +1,70 @@ +import processing.opengl.*; + +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Spring; + +/** + * this sketch shows + * 1 how to create a viscous drag to slow motion eventually down. + * 2 how to create a spring that connects two particles. + */ + +Physics mPhysics; + +Particle mRoot; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a particle to which we will connect springs */ + mRoot = mPhysics.makeParticle(width / 2, height / 2, 0.0); + /* we give the root particle a higher mass so it doesn t move as easily */ + mRoot.mass(30); +} + +void draw() { + /* create a particle at mouse position and connect it to the root particle through a spring */ + if (mousePressed) { + Particle mParticle = mPhysics.makeParticle(mouseX, mouseY, 0); + Spring mSpring = mPhysics.makeSpring(mRoot, mParticle); + /* restlength defines the desired length of the spring. in this case it is the distance between the two particles. */ + float mRestlength = mSpring.restlength(); + /* we modify the restlength to add a bit of energy into the system */ + mSpring.restlength(mRestlength * 1.5f); + } + + /* update the particle system */ + final float mDeltaTime = 1.0 / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particles and connecting line */ + background(255); + + /* draw springs */ + noFill(); + stroke(255, 0, 127, 64); + for (int i = 0; i < mPhysics.forces().size(); i++) { + if (mPhysics.forces().get(i) instanceof Spring) { + Spring mSSpring = (Spring)mPhysics.forces().get(i); + line(mSSpring.a().position().x, mSSpring.a().position().y, + mSSpring.b().position().x, mSSpring.b().position().y); + } + } + /* draw particles */ + fill(245); + stroke(164); + for (int i = 0; i < mPhysics.particles().size(); i++) { + ellipse(mPhysics.particles().get(i).position().x, + mPhysics.particles().get(i).position().y, + 12, 12); + } +} + diff --git a/day3/libs/teilchen/examples/Lesson07_StableQuads/Lesson07_StableQuads.pde b/day3/libs/teilchen/examples/Lesson07_StableQuads/Lesson07_StableQuads.pde new file mode 100755 index 0000000..9c28370 --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson07_StableQuads/Lesson07_StableQuads.pde @@ -0,0 +1,83 @@ +import processing.opengl.*; + +import mathematik.*; + +import teilchen.Physics; +import teilchen.force.Gravity; +import teilchen.force.ViscousDrag; +import teilchen.util.DrawLib; +import teilchen.Particle; +import teilchen.constraint.Box; +import teilchen.integration.RungeKutta; +import teilchen.util.StableSpringQuad; + +Physics mPhysics; + +Particle mRoot; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(60); + + mPhysics = new Physics(); + /* we use 'runge kutta' as it is more stable for this application */ + mPhysics.setInegratorRef(new RungeKutta()); + + Gravity myGravity = new Gravity(); + myGravity.force().y = 98.1f; + mPhysics.add(myGravity); + + /* add drag to smooth the spring interaction */ + mPhysics.add(new ViscousDrag(0.2f)); + + /* add a container */ + Box myBox = new Box(); + myBox.min().set(0, 0, 0); + myBox.max().set(width, height, 0); + mPhysics.add(myBox); + + /* create root */ + Particle a = mPhysics.makeParticle(0, 0); + Particle b = mPhysics.makeParticle(100, 0); + Particle c = mPhysics.makeParticle(100, 100); + Particle d = mPhysics.makeParticle(0, 100); + + new StableSpringQuad(mPhysics, d, c, mPhysics.makeParticle(100, 200), mPhysics.makeParticle(0, 200)); + + /* create stable quad from springs */ + /* first the edge-springs ... */ + final float mySpringConstant = 100; + final float mySpringDamping = 5; + mPhysics.makeSpring(a, b, mySpringConstant, mySpringDamping); + mPhysics.makeSpring(b, c, mySpringConstant, mySpringDamping); + mPhysics.makeSpring(c, d, mySpringConstant, mySpringDamping); + mPhysics.makeSpring(d, a, mySpringConstant, mySpringDamping).restlength(); + /* ... then the diagonal-springs */ + mPhysics.makeSpring(a, c, mySpringConstant, mySpringDamping); + mPhysics.makeSpring(b, d, mySpringConstant, mySpringDamping).restlength(); + + /* define 'a' as root particle for mouse interaction */ + mRoot = a; + mRoot.fixed(true); +} + +void draw() { + + /* handle particles */ + if (mousePressed) { + mRoot.fixed(true); + mRoot.position().set(mouseX, mouseY); + } + else { + mRoot.fixed(false); + } + + mPhysics.step(1f / frameRate); + + /* draw */ + background(255); + DrawLib.drawSprings(g, mPhysics, color(255, 0, 127, 64)); + DrawLib.drawParticles(g, mPhysics, 12, color(164), color(245)); +} + diff --git a/day3/libs/teilchen/examples/Lesson08_Sticks/Lesson08_Sticks.pde b/day3/libs/teilchen/examples/Lesson08_Sticks/Lesson08_Sticks.pde new file mode 100755 index 0000000..220abd7 --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson08_Sticks/Lesson08_Sticks.pde @@ -0,0 +1,71 @@ +import processing.opengl.*; + +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.Stick; +import teilchen.force.Gravity; +import teilchen.integration.Verlet; + +Physics mPhysics; + +Particle[] mParticles; + +void setup() { + size(640, 480, OPENGL); + frameRate(60); + smooth(); + + mPhysics = new Physics(); + /* increase the number of iterations for contraints in each step. this can greatly relaxes tensions in the system. */ + mPhysics.contraint_iterations_per_steps = 5; + + /* add gravity for extra fun */ + mPhysics.add(new Gravity()); + + /* we chose verlet integration as it integrates much more nicely with sticks ( and constraints in general ) */ + Verlet myVerlet = new Verlet(); + myVerlet.damping(0.99f); + mPhysics.setInegratorRef(myVerlet); + + /* setup sticks to form a whip */ + mParticles = new Particle[16]; + float mSegmentLength = 20.0; + /* create root */ + for (int x = 0; x < mParticles.length; x++) { + mParticles[x] = mPhysics.makeParticle(x * mSegmentLength, 0, 0, 0.1f); + if (x > 0) { + Stick myStick = new Stick(mParticles[x - 1], + mParticles[x], + mSegmentLength); + /* damp the stick to release tensions from the system */ + myStick.damping(0.99f); + mPhysics.add(myStick); + } + } + + /* fix root particle so it can stick to the mouse later */ + mParticles[0].fixed(true); +} + +void draw() { + /* stick root particle to mouse */ + mParticles[0].position().set(mouseX, mouseY); + + /* update */ + mPhysics.step(1.0 / frameRate); + + /* draw sticks with descending stroke weight */ + background(255); + stroke(0, 192); + for (int x = 1; x < mParticles.length; x++) { + Particle p1 = mParticles[x - 1]; + Particle p2 = mParticles[x]; + final float mStrokeWeight = 4.0 * (1.0 - (float)x / mParticles.length); + strokeWeight(mStrokeWeight); + line(p1.position().x, p1.position().y, p1.position().z, + p2.position().x, p2.position().y, p2.position().z); + } +} + diff --git a/day3/libs/teilchen/examples/Lesson09_Cloth/Lesson09_Cloth.pde b/day3/libs/teilchen/examples/Lesson09_Cloth/Lesson09_Cloth.pde new file mode 100755 index 0000000..cea0c57 --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson09_Cloth/Lesson09_Cloth.pde @@ -0,0 +1,113 @@ +import processing.opengl.*; + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.IConstraint; +import teilchen.constraint.Stick; +import teilchen.force.Attractor; +import teilchen.force.Gravity; +import teilchen.integration.Verlet; + + +Physics mPhysics; + +Particle[][] mParticles; + +final int GRID_WIDTH = 32; + +final int GRID_HEIGHT = 16; + +Attractor mAttractor; + +void setup() { + size(640, 480, OPENGL); + frameRate(60); + + mPhysics = new Physics(); + mPhysics.contraint_iterations_per_steps = 5; + + Verlet myVerlet = new Verlet(); + myVerlet.damping(0.9f); + mPhysics.setInegratorRef(myVerlet); + mPhysics.add(new Gravity(new Vector3f(0, 1000f, 0))); + + mAttractor = new Attractor(); + mAttractor.strength(-15000); + mAttractor.radius(300); + mPhysics.add(mAttractor); + + mParticles = new Particle[GRID_WIDTH][GRID_HEIGHT]; + + /* setup cloth */ + float mGridStepX = ((float)width / GRID_WIDTH); + float mGridStepY = (((float)height * 0.5f) / GRID_HEIGHT); + for (int y = 0; y < GRID_HEIGHT; y++) { + for (int x = 0; x < GRID_WIDTH; x++) { + mParticles[x][y] = mPhysics.makeParticle(); + mParticles[x][y].position().set((x + 0.5f) * mGridStepX, + y * mGridStepY, + random(0, 1)); + mParticles[x][y].old_position().set(mParticles[x][y].position()); + mParticles[x][y].mass(0.1f); + + final float DAMPING = 0.9f; + if (y > 0) { + Stick myStick = new Stick(mParticles[x][y - 1], + mParticles[x][y], + mGridStepY); + myStick.damping(DAMPING); + mPhysics.add(myStick); + } + if (x > 0) { + Stick myStick = new Stick(mParticles[x - 1][y], + mParticles[x][y], + mGridStepX); + myStick.damping(DAMPING); + mPhysics.add(myStick); + } + if (x > 0 && y > 0) { + Stick myStick1 = new Stick(mParticles[x - 1][y - 1], + mParticles[x][y], + new Vector3f(mGridStepX, mGridStepY).length()); + mPhysics.add(myStick1); + Stick myStick2 = new Stick(mParticles[x][y - 1], + mParticles[x - 1][y], + new Vector3f(mGridStepX, mGridStepY).length()); + mPhysics.add(myStick2); + } + } + } + + /* fix first row */ + for (int x = 0; x < mParticles.length; x++) { + mParticles[x][0].fixed(true); + } +} + +void draw() { + + /* update */ + mAttractor.position().set(mouseX, mouseY, 50); + mPhysics.step(1.0 / frameRate); + + background(255); + + /* draw sticks */ + stroke(0, 127); + + for (int i = 0; i < mPhysics.constraints().size(); i++) { + IConstraint mConstraint = mPhysics.constraints().get(i); + if (mConstraint instanceof Stick) { + final Stick myStick = (Stick)mConstraint; + line(myStick.a().position().x, + myStick.a().position().y, + myStick.a().position().z, + myStick.b().position().x, + myStick.b().position().y, + myStick.b().position().z); + } + } +} + diff --git a/day3/libs/teilchen/examples/Lesson10_Behaviors/Lesson10_Behaviors.pde b/day3/libs/teilchen/examples/Lesson10_Behaviors/Lesson10_Behaviors.pde new file mode 100755 index 0000000..c9fa95d --- /dev/null +++ b/day3/libs/teilchen/examples/Lesson10_Behaviors/Lesson10_Behaviors.pde @@ -0,0 +1,73 @@ +import mathematik.*; + +import teilchen.BehaviorParticle; +import teilchen.Physics; +import teilchen.behavior.Arrival; + + +/** + * this sketch shows how to assign an 'arrival' behavior to a particle. + */ +Physics mPhysics; + +BehaviorParticle mParticle; + +Arrival mArrival; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(120); + colorMode(RGB, 1.0f); + noFill(); + + /* physics */ + mPhysics = new Physics(); + + /* create particles */ + mParticle = mPhysics.makeParticle(BehaviorParticle.class); + mParticle.maximumInnerForce(100); + + /* create arrival behavior */ + mArrival = new Arrival(); + mArrival.breakforce(mParticle.maximumInnerForce() * 0.25f); + mArrival.breakradius(mParticle.maximumInnerForce() * 0.25f); + mParticle.behaviors().add(mArrival); +} + +void draw() { + + /* set the arrival position to the mouse position */ + mArrival.position().set(mouseX, mouseY); + + /* update particle system */ + mPhysics.step(1.0f / frameRate); + + /* draw behavior particle */ + background(1); + stroke(0, 0.5f); + if (mArrival.arriving()) { + /* color particle red while it is arriving */ + stroke(1, 0, 0, 0.5f); + } + if (mArrival.arrived()) { + /* color particle green when it has arrived */ + stroke(0, 1, 0, 0.5f); + } + + line(mParticle.position().x, + mParticle.position().y, + mParticle.position().x + mParticle.velocity().x, + mParticle.position().y + mParticle.velocity().y); + fill(1); + ellipse(mParticle.position().x, mParticle.position().y, 12, 12); + + /* draw arrival */ + stroke(0, 0.25f); + noFill(); + ellipse(mArrival.position().x, + mArrival.position().y, + mArrival.breakradius() * 2, + mArrival.breakradius() * 2); +} + diff --git a/day3/libs/teilchen/examples/LessonX01_Overlap/LessonX01_Overlap.pde b/day3/libs/teilchen/examples/LessonX01_Overlap/LessonX01_Overlap.pde new file mode 100755 index 0000000..e07a2f5 --- /dev/null +++ b/day3/libs/teilchen/examples/LessonX01_Overlap/LessonX01_Overlap.pde @@ -0,0 +1,69 @@ +import processing.opengl.*; +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Spring; +import teilchen.util.Overlap; + +/** + * this sketch is exactly like Lesson06_Springs, except that it also shows how to remove overlaps. + */ + +Physics mPhysics; + +Particle mRoot; + +static final float PARTICLE_RADIUS = 6; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + mPhysics = new Physics(); + mRoot = mPhysics.makeParticle(width / 2, height / 2, 0.0); + mRoot.mass(30); +} + +void draw() { + if (mousePressed) { + Particle mParticle = mPhysics.makeParticle(mouseX, mouseY, 0); + Spring mSpring = mPhysics.makeSpring(mRoot, mParticle); + float mRestlength = mSpring.restlength(); + mSpring.restlength(mRestlength * 1.5f); + + /* we define a radius for the particle so the particle has dimensions */ + mParticle.radius(PARTICLE_RADIUS); + } + + /* move overlapping particles away from each other */ + Overlap.resolveOverlap(mPhysics.particles()); + + /* update the particle system */ + final float mDeltaTime = 1.0 / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particles and connecting line */ + background(255); + + /* draw springs */ + noFill(); + stroke(255, 0, 127, 64); + for (int i = 0; i < mPhysics.forces().size(); i++) { + if (mPhysics.forces().get(i) instanceof Spring) { + Spring mSSpring = (Spring)mPhysics.forces().get(i); + line(mSSpring.a().position().x, mSSpring.a().position().y, + mSSpring.b().position().x, mSSpring.b().position().y); + } + } + /* draw particles */ + fill(245); + stroke(164); + for (int i = 0; i < mPhysics.particles().size(); i++) { + ellipse(mPhysics.particles().get(i).position().x, + mPhysics.particles().get(i).position().y, + PARTICLE_RADIUS * 2, PARTICLE_RADIUS * 2); + } +} + diff --git a/day3/libs/teilchen/examples/LessonX02_Collisions/LessonX02_Collisions.pde b/day3/libs/teilchen/examples/LessonX02_Collisions/LessonX02_Collisions.pde new file mode 100755 index 0000000..530f6f2 --- /dev/null +++ b/day3/libs/teilchen/examples/LessonX02_Collisions/LessonX02_Collisions.pde @@ -0,0 +1,91 @@ +import processing.opengl.*; + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.Box; +import teilchen.force.Gravity; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.util.CollisionManager; + +static final float PARTICLE_SIZE = 12; + +CollisionManager mCollision; + +Physics mPhysics; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + noFill(); + ellipseMode(CENTER); + + mCollision = new CollisionManager(); + mCollision.distancemode(CollisionManager.DISTANCE_MODE_FIXED); + mCollision.minimumDistance(50); + + mPhysics = new Physics(); + mPhysics.add(new ViscousDrag(0.85f)); + mPhysics.add(new Gravity()); + + Box myBox = new Box(); + myBox.min().set(50, 50, 0); + myBox.max().set(width - 50, height - 50, 0); + myBox.coefficientofrestitution(0.7f); + myBox.reflect(true); + mPhysics.add(myBox); + + /* create a first particle */ + final Particle myParticle = mPhysics.makeParticle(new Vector3f(mouseX, mouseY, 0), 10); + mCollision.collision().add(myParticle); +} + +void draw() { + /* create particles */ + if (mousePressed) { + final Particle myParticle = mPhysics.makeParticle(new Vector3f(mouseX, mouseY, 0), 10); + mCollision.collision().add(myParticle); + } + + /* collision handler */ + final float mDeltaTime = 1.0 / frameRate; + mCollision.createCollisionResolvers(); + mCollision.loop(mDeltaTime); + mPhysics.step(mDeltaTime); + + /* draw */ + background(255); + drawThings(); + + mCollision.removeCollisionResolver(); +} + +void drawThings() { + /* collision springs */ + noFill(); + stroke(255, 0, 127, 64); + for (int i = 0; i < mCollision.collision().forces().size(); ++i) { + if (mCollision.collision().forces().get(i) instanceof Spring) { + Spring mySpring = (Spring)mCollision.collision_forces().get(i); + line(mySpring.a().position().x, mySpring.a().position().y, mySpring.a().position().z, + mySpring.b().position().x, mySpring.b().position().y, mySpring.b().position().z); + } + } + + /* particles */ + fill(245); + stroke(164); + for (int i = 0; i < mPhysics.particles().size(); ++i) { + Particle myParticle = mPhysics.particles().get(i); + pushMatrix(); + translate(myParticle.position().x, myParticle.position().y, myParticle.position().z); + ellipse(0, 0, + PARTICLE_SIZE, + PARTICLE_SIZE); + popMatrix(); + } +} + diff --git a/day3/libs/teilchen/examples/LessonX03_ParticlesLeavingTrails/LessonX03_ParticlesLeavingTrails.pde b/day3/libs/teilchen/examples/LessonX03_ParticlesLeavingTrails/LessonX03_ParticlesLeavingTrails.pde new file mode 100755 index 0000000..a4bdca0 --- /dev/null +++ b/day3/libs/teilchen/examples/LessonX03_ParticlesLeavingTrails/LessonX03_ParticlesLeavingTrails.pde @@ -0,0 +1,131 @@ +import mathematik.Vector3f; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.ShortLivedParticle; +import teilchen.constraint.Box; +import teilchen.force.Attractor; +import teilchen.force.Gravity; +import teilchen.force.ViscousDrag; +import teilchen.util.ParticleTrail; + +import java.util.Vector; + +Physics mPhysics; + +Vector mTrails; + +Attractor mAttractor; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(60); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a gravitational force */ + Gravity myGravity = new Gravity(); + mPhysics.add(myGravity); + myGravity.force().y = 20; + + /* create drag */ + ViscousDrag myViscousDrag = new ViscousDrag(); + myViscousDrag.coefficient = 0.1f; + mPhysics.add(myViscousDrag); + + final float mBorder = 40; + Box mBox = new Box(new Vector3f(mBorder, mBorder, mBorder), new Vector3f(width - mBorder, height - mBorder, 100 - mBorder)); + mBox.reflect(true); + mPhysics.add(mBox); + + /* create an attractor */ + mAttractor = new Attractor(); + mAttractor.radius(200); + mAttractor.strength(-300); + mPhysics.add(mAttractor); + + + /* create trails and particles */ + mTrails = new Vector(); + for (int i = 0; i < 500; i++) { + Particle mParticle = mPhysics.makeParticle(); + mParticle.mass(2.0f); + ParticleTrail myParticleTrail = new ParticleTrail(mPhysics, mParticle, 0.2f, random(0.5f, 1)); + myParticleTrail.mass(0.5f); + mTrails.add(myParticleTrail); + } + resetParticles(width / 2, height / 2); +} + +void resetParticles(float x, float y) { + for (ParticleTrail myTrails : mTrails) { + myTrails.particle().position().set(x + random(-10, 10), y + random(-10, 10), 0); + myTrails.particle().velocity().set(random(-10, 10), random(-10, 10), random(-10, 10)); + myTrails.fragments().clear(); + } +} + +void draw() { + /* set attractor to mouse position */ + mAttractor.position().set(mouseX, mouseY); + + for (ParticleTrail myTrails : mTrails) { + myTrails.loop(1f / frameRate); + } + + mPhysics.step(1f / frameRate); + + background(255); + for (ParticleTrail myTrail : mTrails) { + drawTrail(myTrail); + } +} + +void drawTrail(ParticleTrail theTrail) { + + final Vector mFragments = theTrail.fragments(); + final Particle mParticle = theTrail.particle(); + + /* draw head */ + if (mFragments.size() > 1) { + fill(255, 0, 127); + noStroke(); + pushMatrix(); + translate(mParticle.position().x, + mParticle.position().y, + mParticle.position().z); + sphereDetail(4); + sphere(3); + popMatrix(); + } + + /* draw trail */ + for (int i = 0; i < mFragments.size() - 1; i++) { + if (mFragments.get(i) instanceof ShortLivedParticle) { + final float mRatio = 1.0f - ((ShortLivedParticle)mFragments.get(i)).ageRatio(); + stroke(127, mRatio * 255); + strokeWeight(mRatio * 3); + } + int j = (i + 1) % mFragments.size(); + line(mFragments.get(i).position().x, + mFragments.get(i).position().y, + mFragments.get(i).position().z, + mFragments.get(j).position().x, + mFragments.get(j).position().y, + mFragments.get(j).position().z); + } + if (!mFragments.isEmpty()) { + line(mFragments.lastElement().position().x, + mFragments.lastElement().position().y, + mFragments.lastElement().position().z, + mParticle.position().x, + mParticle.position().y, + mParticle.position().z); + } +} + +void mousePressed() { + resetParticles(mouseX, mouseY); +} + diff --git a/day3/libs/teilchen/examples/LessonX04_StickMan/LessonX04_StickMan.pde b/day3/libs/teilchen/examples/LessonX04_StickMan/LessonX04_StickMan.pde new file mode 100755 index 0000000..0a32d9c --- /dev/null +++ b/day3/libs/teilchen/examples/LessonX04_StickMan/LessonX04_StickMan.pde @@ -0,0 +1,146 @@ +import mathematik.*; + +import teilchen.test.cubicle.*; +import teilchen.integration.*; +import verhalten.*; +import teilchen.*; +import verhalten.view.*; +import teilchen.test.particle.behavior.*; +import teilchen.behavior.*; +import teilchen.demo.*; +import teilchen.test.particle.springs.*; +import teilchen.gestalt.test.*; +import teilchen.cubicle.*; +import verhalten.test.*; +import teilchen.force.flowfield.*; +import teilchen.test.particle.*; +import teilchen.gestalt.util.*; +import teilchen.constraint.*; +import teilchen.force.vectorfield.*; +import teilchen.force.*; +import teilchen.util.*; + +import mathematik.*; + +import teilchen.Physics; +import teilchen.force.Attractor; +import teilchen.force.Gravity; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.integration.RungeKutta; +import teilchen.util.Overlap; +import teilchen.util.StickMan; + + + +/** + * this demo shows some advanced use of particles, springs and attractors to create stickmen. + */ + +Physics mPhysics; + +Attractor mAttractor; + +Gravity mGravity; + +ViscousDrag mViscousDrag; + +StickMan[] mMyStickMan; + +void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(60); + noFill(); + + mPhysics = new Physics(); + mPhysics.setInegratorRef(new RungeKutta()); + + mGravity = new Gravity(); + mGravity.force().y = 20; + mPhysics.add(mGravity); + + mViscousDrag = new ViscousDrag(); + mViscousDrag.coefficient = 0.85f; + mPhysics.add(mViscousDrag); + + mAttractor = new Attractor(); + mAttractor.radius(500); + mAttractor.strength(0); + mAttractor.position().set(width / 2, height / 2); + mPhysics.add(mAttractor); + + mMyStickMan = new StickMan[20]; + for (int i = 0; i < mMyStickMan.length; i++) { + mMyStickMan[i] = new StickMan(mPhysics, random(0, width), random(0.3f, 0.6f)); + } +} + +void draw() { + + mPhysics.step(1f / 60f); + Overlap.resolveOverlap(mPhysics.particles()); + + /* constraint particles */ + for (int i = 0; i < mPhysics.particles().size(); i++) { + if (mPhysics.particles(i).position().y > height - 10) { + mPhysics.particles(i).position().y = height - 10; + } + if (mPhysics.particles(i).position().x > width) { + mPhysics.particles(i).position().x = width; + } + if (mPhysics.particles(i).position().x < 0) { + mPhysics.particles(i).position().x = 0; + } + } + + /* handle particles */ + if (mousePressed) { + mAttractor.position().set(mouseX, mouseY); + if (mouseButton == RIGHT) { + mAttractor.strength(-500); + mAttractor.radius(500); + } + else { + mAttractor.strength(500); + mAttractor.radius(100); + } + } + else { + mAttractor.strength(0); + } + + if (keyPressed) { + mGravity.force().y = -10; + } + else { + mGravity.force().y = 20; + } + + /* draw */ + background(255); + + /* draw springs */ + stroke(0, 20); + for (int i = 0; i < mPhysics.forces().size(); i++) { + if (mPhysics.forces(i) instanceof Spring) { + Spring mySpring = (Spring)mPhysics.forces(i); + line(mySpring.a().position().x, + mySpring.a().position().y, + mySpring.b().position().x, + mySpring.b().position().y); + } + } + + /* draw particles */ + for (int i = 0; i < mPhysics.particles().size(); i++) { + ellipse(mPhysics.particles(i).position().x, + mPhysics.particles(i).position().y, 5, 5); + } + + /* draw man */ + for (int i = 0; i < mMyStickMan.length; i++) { + mMyStickMan[i].draw(g); + } +} + diff --git a/day3/libs/teilchen/examples/LessonX05_AngleConstraints/LessonX05_AngleConstraints.pde b/day3/libs/teilchen/examples/LessonX05_AngleConstraints/LessonX05_AngleConstraints.pde new file mode 100755 index 0000000..89c51e9 --- /dev/null +++ b/day3/libs/teilchen/examples/LessonX05_AngleConstraints/LessonX05_AngleConstraints.pde @@ -0,0 +1,184 @@ +import mathematik.*; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.AngleConstraintStick; +import teilchen.constraint.Stick; +import teilchen.force.AngleConstraintSpring; +import teilchen.force.Gravity; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.integration.RungeKutta; + + +Physics mPhysics; + +Particle mParticleA; + +Particle mParticleB; + +Particle mParticleC; + +Particle mParticleD; + +AngleConstraintSpring mAngleConstraintABC; + +AngleConstraintStick mAngleConstraintBCD; + +void setup() { + size(640, 480); + frameRate(30); + smooth(); + + mPhysics = new Physics(); + mPhysics.setInegratorRef(new RungeKutta()); + + ViscousDrag myViscousDrag = new ViscousDrag(); + myViscousDrag.coefficient = 1f; + mPhysics.add(myViscousDrag); + + Gravity myGravity = new Gravity(); + myGravity.force().y = 50; + mPhysics.add(myGravity); + + /* particles */ + mParticleA = mPhysics.makeParticle(); + mParticleB = mPhysics.makeParticle(); + mParticleC = mPhysics.makeParticle(); + mParticleD = mPhysics.makeParticle(); + + mParticleA.position().set(width / 2 + 50, height / 3); + mParticleB.position().set(width / 2, height - height / 1.75f); + mParticleC.position().set(width / 2, height - height / 4); + mParticleD.position().set(width / 2, height - height / 8); + + mParticleA.radius(7); + mParticleB.radius(3); + mParticleC.radius(10); + mParticleD.radius(2); + + mParticleB.fixed(true); + + /* springs */ + Spring mSpringAB = new Spring(mParticleA, mParticleB); + mSpringAB.strength(250); + mSpringAB.damping(10); + mPhysics.add(mSpringAB); + + Spring mSpringBC = new Spring(mParticleB, mParticleC); + mSpringBC.strength(250); + mSpringBC.damping(10); + mPhysics.add(mSpringBC); + + Stick mSpringCD = new Stick(mParticleC, mParticleD); + mSpringCD.damping(1); + mPhysics.add(mSpringCD); + + /* angle constraint */ + mAngleConstraintABC = new AngleConstraintSpring(mParticleA, mParticleB, mParticleC); + mAngleConstraintABC.min_angle(PI * 0.5f); + mAngleConstraintABC.damping(1); + mAngleConstraintABC.strength(200); + mPhysics.add(mAngleConstraintABC); + + mAngleConstraintBCD = new AngleConstraintStick(mParticleB, mParticleC, mParticleD); + mAngleConstraintBCD.min_angle(PI * 0.8f); + mAngleConstraintBCD.damping(0.5f); + mPhysics.add(mAngleConstraintBCD); +} + +void draw() { + /* attach particle to mouse */ + if (mousePressed) { + mParticleA.position().set(mouseX, mouseY); + } + + /* apply constraints */ + mAngleConstraintABC.pre_step(); + mAngleConstraintBCD.pre_step(); + draw_physics(); + + mPhysics.step(1f / frameRate); + + /* remove contraints */ + mAngleConstraintABC.post_step(); + mAngleConstraintBCD.post_step(); +} + +void draw_physics() { + background(255); + + drawSprings(); + drawSticks(); + drawParticles(); +} + +void drawSprings() { + for (int i = 0; i < mPhysics.forces().size(); i++) { + if (mPhysics.forces(i) instanceof Spring) { + final Spring mSpring = (Spring)mPhysics.forces(i); + if (mSpring instanceof AngleConstraintSpring) { + strokeWeight(1); + if (mSpring.active()) { + stroke(255, 0, 0, 64); + } + else { + stroke(255, 0, 0, 16); + } + } + else { + strokeWeight(3); + stroke(0, 128); + } + line(mSpring.a(), mSpring.b()); + } + } + strokeWeight(1); +} + +void drawSticks() { + for (int i = 0; i < mPhysics.constraints().size(); i++) { + if (mPhysics.constraints(i) instanceof Stick) { + final Stick mStick = (Stick)mPhysics.constraints(i); + if (mStick instanceof AngleConstraintStick) { + strokeWeight(1); + if (mStick.active()) { + stroke(0, 127, 255, 64); + } + else { + stroke(0, 127, 255, 16); + } + } + else { + strokeWeight(3); + stroke(0, 128); + } + line(mStick.a(), mStick.b()); + } + } + strokeWeight(1); +} + +void drawParticles() { + stroke(0); + fill(92); + drawParticle(mParticleA); + fill(127); + drawParticle(mParticleB); + fill(192); + drawParticle(mParticleC); + fill(64); + drawParticle(mParticleD); +} + +void drawParticle(Particle p) { + ellipse(p.position().x, + p.position().y, + p.radius() * 2, p.radius() * 2); +} + +void line(Particle p1, Particle p2) { + line(p1.position().x, p1.position().y, + p2.position().x, p2.position().y); +} + diff --git a/day3/libs/teilchen/examples/LessonX06_Ducklings/LessonX06_Ducklings.pde b/day3/libs/teilchen/examples/LessonX06_Ducklings/LessonX06_Ducklings.pde new file mode 100755 index 0000000..bcdc2c6 --- /dev/null +++ b/day3/libs/teilchen/examples/LessonX06_Ducklings/LessonX06_Ducklings.pde @@ -0,0 +1,145 @@ +import mathematik.*; + +import processing.opengl.*; + +import teilchen.BehaviorParticle; +import teilchen.Physics; +import teilchen.behavior.Arrival; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.util.CollisionManager; + +/** + * this demo shows how to add behaviors to particles. in this example the + * arrival behavior. + */ + +Physics mPhysics; + +ArrayList mDucklings; + +CollisionManager mCollision; + +void setup() { + size(640, 480, OPENGL); + frameRate(60); + smooth(); + colorMode(RGB, 1.0f); + + /* physics */ + mPhysics = new Physics(); + + ViscousDrag myViscousDrag = new ViscousDrag(); + myViscousDrag.coefficient = 0.25f; + mPhysics.add(myViscousDrag); + + mCollision = new CollisionManager(); + mCollision.minimumDistance(25); + + /* ducklings */ + mDucklings = new ArrayList(); + for (int i = 0; i < 13; i++) { + final Duckling mDuckling = new Duckling(); + if (!mDucklings.isEmpty()) { + mDuckling.arrival.setPositionRef(mDucklings.get(mDucklings.size()-1).particle.position()); + } + mCollision.collision().add(mDuckling.particle); + mDucklings.add(mDuckling); + } +} + + +void draw() { + final float mDeltaTime = 1.0f / frameRate; + background(1); + + /* update particles */ + mCollision.createCollisionResolvers(); + mCollision.loop(mDeltaTime); + mPhysics.step(mDeltaTime); + + drawCollisionSprings(); + mCollision.removeCollisionResolver(); + + mDucklings.get(0).arrival.oversteer(!mousePressed); + mDucklings.get(0).arrival.position().set(mouseX, mouseY); + + /* draw */ + for (int i=0; i < mDucklings.size(); i++) { + Duckling mDuckling = mDucklings.get(i); + drawParticle(mDuckling); + } + + /* draw arrival */ + stroke(0, 0.25f); + noFill(); + ellipse(mDucklings.get(0).arrival.position().x, + mDucklings.get(0).arrival.position().y, + 20, 20); +} + +void drawParticle(Duckling pDuckling) { + final BehaviorParticle mParticle = pDuckling.particle; + final Arrival mArrival = pDuckling.arrival; + + /* draw particle */ + stroke(0, 0.5f); + noFill(); + if (mArrival.arriving()) { + stroke(1, 0, 0, 0.5f); + } + if (mArrival.arrived()) { + stroke(0, 1, 0, 0.5f); + } + ellipse(mParticle.position().x, mParticle.position().y, + mParticle.radius() * 2, mParticle.radius() * 2); + + /* - */ + pushMatrix(); + translate(mParticle.position().x, + mParticle.position().y); + + /* draw velocity */ + stroke(1, 0, 0, 0.5f); + line(0, 0, mParticle.velocity().x, mParticle.velocity().y); + + /* draw break force */ + stroke(0, 0.5f, 1, 0.5f); + line(0, 0, mArrival.force().x, mArrival.force().y); + + /* - */ + popMatrix(); +} + +void drawCollisionSprings() { + stroke(0, 1, 0, 0.25f); + for (int i = 0; i < mCollision.collision().forces().size(); ++i) { + if (mCollision.collision().forces().get(i) instanceof Spring) { + Spring mySpring = (Spring) mCollision.collision_forces().get(i); + line(mySpring.a().position().x, mySpring.a().position().y, mySpring.a().position().z, + mySpring.b().position().x, mySpring.b().position().y, mySpring.b().position().z); + } + } +} + +class Duckling { + + BehaviorParticle particle; + + Arrival arrival; + + Duckling() { + /* create particles */ + particle = mPhysics.makeParticle(BehaviorParticle.class); + particle.position().set(random(width), random(height)); + particle.maximumInnerForce(random(50, 150)); + particle.radius(random(6, 10)); + + arrival = new Arrival(); + arrival.breakforce(random(12, 28)); + arrival.breakradius(random(45, 55)); + + particle.behaviors().add(arrival); + } +} + diff --git a/day3/libs/teilchen/library/teilchen.jar b/day3/libs/teilchen/library/teilchen.jar new file mode 100755 index 0000000..60b9ff9 Binary files /dev/null and b/day3/libs/teilchen/library/teilchen.jar differ diff --git a/day3/libs/teilchen/src/teilchen/BasicParticle.java b/day3/libs/teilchen/src/teilchen/BasicParticle.java new file mode 100755 index 0000000..3eba915 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/BasicParticle.java @@ -0,0 +1,142 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen; + + +import java.io.Serializable; + +import mathematik.Vector3f; + + +public class BasicParticle + implements Particle, Serializable { + + private boolean mFixed; + + private float mAge; + + private float mMass; + + private Vector3f mPosition; + + private final Vector3f mOldPosition; + + private final Vector3f mVelocity; + + private final Vector3f mForce; + + private boolean mTagged; + + private boolean mStill; + + private float mRadius; + + private static final long serialVersionUID = 3737917975116369338L; + + public BasicParticle() { + mPosition = new Vector3f(); + mOldPosition = new Vector3f(); + mVelocity = new Vector3f(); + mForce = new Vector3f(); + mMass = 1; + mFixed = false; + mAge = 0; + mTagged = false; + mStill = false; + mRadius = 0; + } + + public boolean fixed() { + return mFixed; + } + + public void fixed(boolean theFixed) { + mFixed = theFixed; + } + + public float age() { + return mAge; + } + + public void age(float theAge) { + mAge = theAge; + } + + public float mass() { + return mMass; + } + + public void mass(float theMass) { + mMass = theMass; + } + + public Vector3f position() { + return mPosition; + } + + public Vector3f old_position() { + return mOldPosition; + } + + public void setPositionRef(Vector3f thePosition) { + mPosition = thePosition; + } + + public Vector3f velocity() { + return mVelocity; + } + + public Vector3f force() { + return mForce; + } + + public boolean dead() { + return false; + } + + public void accumulateInnerForce(final float theDeltaTime) { + } + + public boolean tagged() { + return mTagged; + } + + public void tag(boolean theTag) { + mTagged = theTag; + } + + public boolean still() { + return mStill; + } + + public void still(boolean theStill) { + mStill = theStill; + } + + public float radius() { + return mRadius; + } + + public void radius(float theRadius) { + mRadius = theRadius; + } +} diff --git a/day3/libs/teilchen/src/teilchen/BehaviorParticle.java b/day3/libs/teilchen/src/teilchen/BehaviorParticle.java new file mode 100755 index 0000000..090966e --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/BehaviorParticle.java @@ -0,0 +1,72 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen; + + +import java.util.Vector; + +import teilchen.behavior.IBehavior; + + +public class BehaviorParticle + extends BasicParticle + implements IBehaviorParticle { + + private final Vector mBehaviors; + + private float mMaximumInnerForce; + + private static final long serialVersionUID = 2735849326244271321L; + + public BehaviorParticle() { + mBehaviors = new Vector(); + mMaximumInnerForce = 50; + } + + public void accumulateInnerForce(final float theDeltaTime) { + for (final IBehavior mBehavior : mBehaviors) { + if (mBehavior != null) { + mBehavior.update(theDeltaTime, this); + force().add(mBehavior.force()); + } + } + /* clamp to maximum force */ + if (maximumInnerForce() > 0) { + final float mForceLength = force().length(); + if (mForceLength > maximumInnerForce()) { + force().scale(maximumInnerForce() / mForceLength); + } + } + } + + public float maximumInnerForce() { + return mMaximumInnerForce; + } + + public void maximumInnerForce(float theForce) { + mMaximumInnerForce = theForce; + } + + public Vector behaviors() { + return mBehaviors; + } +} diff --git a/day3/libs/teilchen/src/teilchen/ConditionalParticle.java b/day3/libs/teilchen/src/teilchen/ConditionalParticle.java new file mode 100755 index 0000000..1fbf024 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/ConditionalParticle.java @@ -0,0 +1,33 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen; + + +public abstract class ConditionalParticle + extends BasicParticle { + + public boolean dead() { + return !condition(); + } + + public abstract boolean condition(); +} diff --git a/day3/libs/teilchen/src/teilchen/IBehaviorParticle.java b/day3/libs/teilchen/src/teilchen/IBehaviorParticle.java new file mode 100755 index 0000000..9e0f2fb --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/IBehaviorParticle.java @@ -0,0 +1,36 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen; + + +import java.util.Vector; + + +public interface IBehaviorParticle + extends Particle { + + float maximumInnerForce(); + + void maximumInnerForce(float theForce); + + Vector behaviors(); +} diff --git a/day3/libs/teilchen/src/teilchen/IConnection.java b/day3/libs/teilchen/src/teilchen/IConnection.java new file mode 100755 index 0000000..cdd30ca --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/IConnection.java @@ -0,0 +1,30 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen; + + +public interface IConnection { + + Particle a(); + + Particle b(); +} diff --git a/day3/libs/teilchen/src/teilchen/Particle.java b/day3/libs/teilchen/src/teilchen/Particle.java new file mode 100755 index 0000000..37b8e39 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/Particle.java @@ -0,0 +1,70 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen; + + +import mathematik.Vector3f; + +import teilchen.util.SpatialEntity; + + +public interface Particle + extends SpatialEntity { + + boolean fixed(); + + void fixed(boolean theFixed); + + float age(); + + void age(float theAge); + + float mass(); + + void mass(float theMass); + + Vector3f position(); + + Vector3f old_position(); + + void setPositionRef(Vector3f thePosition); + + Vector3f velocity(); + + Vector3f force(); + + boolean dead(); + + boolean tagged(); + + void tag(boolean theTag); + + void accumulateInnerForce(final float theDeltaTime); + + float radius(); + + void radius(float theRadius); + + boolean still(); + + void still(boolean theStill); +} diff --git a/day3/libs/teilchen/src/teilchen/Physics.java b/day3/libs/teilchen/src/teilchen/Physics.java new file mode 100755 index 0000000..b5edc01 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/Physics.java @@ -0,0 +1,374 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen; + +import mathematik.Vector3f; + +import teilchen.constraint.IConstraint; +import teilchen.force.IForce; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.integration.IIntegrator; +import teilchen.integration.Midpoint; +import teilchen.integration.Verlet; + +import java.util.Collection; +import java.util.Iterator; +import java.util.Vector; +import teilchen.integration.RungeKutta; + +public class Physics { + + private final Vector mParticles; + + private final Vector mForces; + + private final Vector mConstraints; + + private IIntegrator mIntegrator; + + private static final float EPSILON = 0.001f; + + public boolean HINT_OPTIMIZE_STILL = true; + + public boolean HINT_REMOVE_DEAD = true; + + public boolean HINT_RECOVER_NAN = true; + + public int contraint_iterations_per_steps = 1; + + public static boolean HINT_UPDATE_OLD_POSITION = true; + + public Physics() { + mParticles = new Vector(); + mForces = new Vector(); + mConstraints = new Vector(); + mIntegrator = new Midpoint(); + } + + + /* particles */ + public void add(Particle theParticle) { + mParticles.add(theParticle); + } + + public void add(Collection theParticles) { + mParticles.addAll(theParticles); + } + + public void remove(Particle theParticle) { + mParticles.remove(theParticle); + } + + public void remove(Collection theParticles) { + + mParticles.removeAll(theParticles); + } + + public Vector particles() { + return mParticles; + } + + public Particle particles(final int theIndex) { + return mParticles.get(theIndex); + } + + public BasicParticle makeParticle() { + BasicParticle myParticle = new BasicParticle(); + mParticles.add(myParticle); + return myParticle; + } + + public BasicParticle makeParticle(final Vector3f thePosition) { + BasicParticle myParticle = makeParticle(); + myParticle.setPositionRef(thePosition); + myParticle.old_position().set(myParticle.position()); + return myParticle; + } + + public BasicParticle makeParticle(final float x, final float y) { + BasicParticle myParticle = makeParticle(); + myParticle.position().set(x, y); + myParticle.old_position().set(myParticle.position()); + return myParticle; + } + + public BasicParticle makeParticle(final float x, final float y, final float z) { + BasicParticle myParticle = makeParticle(); + myParticle.position().set(x, y, z); + myParticle.old_position().set(myParticle.position()); + return myParticle; + } + + public BasicParticle makeParticle(final float x, final float y, final float z, final float pMass) { + BasicParticle myParticle = makeParticle(); + myParticle.position().set(x, y, z); + myParticle.mass(pMass); + myParticle.old_position().set(myParticle.position()); + return myParticle; + } + + public BasicParticle makeParticle(final Vector3f thePosition, final float pMass) { + BasicParticle myParticle = makeParticle(); + myParticle.setPositionRef(thePosition); + myParticle.old_position().set(myParticle.position()); + myParticle.mass(pMass); + return myParticle; + } + + public T makeParticle(Class theParticleClass) { + T myParticle; + try { + myParticle = theParticleClass.newInstance(); + mParticles.add(myParticle); + } catch (Exception ex) { + System.err.println(ex); + myParticle = null; + } + return myParticle; + } + + public void removeTags() { + for (final Particle myParticle : mParticles) { + myParticle.tag(false); + } + } + + + /* forces */ + public void add(IForce theForce) { + if (theForce instanceof ViscousDrag && mIntegrator instanceof Verlet) { + System.err.println( + "### WARNING / 'viscous drag' might have no effect with 'verlet' integration. use 'Verlet.damping(float theDamping)' instead."); + } + mForces.add(theForce); + } + + public void addForces(final Vector theForces) { + mForces.addAll(theForces); + } + + public void remove(IForce theForce) { + mForces.remove(theForce); + } + + public Vector forces() { + return mForces; + } + + public IForce forces(final int theIndex) { + return mForces.get(theIndex); + } + + public void applyForces(final float theDeltaTime) { + /* accumulate inner forces */ + synchronized (mParticles) { + final Iterator iter = mParticles.iterator(); + while (iter.hasNext()) { + final Particle myParticle = iter.next(); + if (!myParticle.fixed()) { + /* accumulate inner forces */ + myParticle.accumulateInnerForce(theDeltaTime); + } + } + } + + /* add new forces to each particle */ + synchronized (mForces) { + Iterator iter = mForces.iterator(); + while (iter.hasNext()) { + final IForce mForce = iter.next(); + if (mForce.active()) { + mForce.apply(theDeltaTime, this); + } + } + } + } + + public T makeForce(Class theForceClass) { + T myForce; + try { + myForce = theForceClass.newInstance(); + mForces.add(myForce); + } catch (Exception ex) { + System.err.println(ex); + myForce = null; + } + return myForce; + } + + public Spring makeSpring(final Particle theA, final Particle theB) { + Spring mySpring = new Spring(theA, theB); + mForces.add(mySpring); + return mySpring; + } + + public Spring makeSpring(final Particle theA, + final Particle theB, + final float theRestLength) { + Spring mySpring = new Spring(theA, theB, theRestLength); + mForces.add(mySpring); + return mySpring; + } + + public Spring makeSpring(final Particle theA, + final Particle theB, + final float theSpringConstant, + final float theSpringDamping) { + Spring mySpring = new Spring(theA, theB, theSpringConstant, theSpringDamping); + mForces.add(mySpring); + return mySpring; + } + + public Spring makeSpring(final Particle theA, + final Particle theB, + final float theSpringConstant, + final float theSpringDamping, + final float theRestLength) { + Spring mySpring = new Spring(theA, theB, theSpringConstant, theSpringDamping, theRestLength); + mForces.add(mySpring); + return mySpring; + } + + + /* constraints */ + public void add(final IConstraint theConstraint) { + mConstraints.add(theConstraint); + } + + public void addConstraints(final Vector theConstraints) { + mConstraints.addAll(theConstraints); + } + + public void remove(final IConstraint theConstraint) { + mConstraints.remove(theConstraint); + } + + public Vector constraints() { + return mConstraints; + } + + public IConstraint constraints(final int theIndex) { + return mConstraints.get(theIndex); + } + + + /* integration */ + public void setInegratorRef(IIntegrator theIntegrator) { + mIntegrator = theIntegrator; + } + + public IIntegrator getIntegrator() { + return mIntegrator; + } + + public void loop(final float theDeltaTime, final int theIterations) { + for (int i = 0; i < theIterations; i++) { + step(theDeltaTime / (float) theIterations); + } + } + + public void step(final float theDeltaTime) { + prepareParticles(theDeltaTime); + handleForces(); + integrate(theDeltaTime); + handleParticles(theDeltaTime); + handleContraints(); + } + + protected synchronized void integrate(float theDeltaTime) { + mIntegrator.step(theDeltaTime, this); + } + + protected synchronized void handleForces() { + synchronized (mForces) { + final Iterator iter = mForces.iterator(); + while (iter.hasNext()) { + final IForce myForce = iter.next(); + if (myForce.dead()) { + iter.remove(); + } + } + } + } + + protected synchronized void handleContraints() { + synchronized (mConstraints) { + for (int i = 0; i < contraint_iterations_per_steps; i++) { + final Iterator iter = mConstraints.iterator(); + while (iter.hasNext()) { + final IConstraint myContraint = iter.next(); + myContraint.apply(this); + } + } + } + } + + protected synchronized void handleParticles(float theDeltaTime) { + synchronized (mParticles) { + final Iterator iter = mParticles.iterator(); + while (iter.hasNext()) { + final Particle myParticle = iter.next(); + /* clear force */ + myParticle.force().set(0, 0, 0); + /* age particle */ + myParticle.age(myParticle.age() + theDeltaTime); + /* remove dead */ + if (HINT_REMOVE_DEAD) { + if (myParticle.dead()) { + iter.remove(); + } + } + /* recover NAN */ + if (HINT_RECOVER_NAN) { + if (myParticle.position().isNaN()) { + if (myParticle.old_position().isNaN()) { + myParticle.position().set(0, 0, 0); + } else { + myParticle.position().set(myParticle.old_position()); + } + } + if (myParticle.velocity().isNaN()) { + myParticle.velocity().set(0, 0, 0); + } + } + /* still */ + if (HINT_OPTIMIZE_STILL) { + final float mySpeed = myParticle.velocity().lengthSquared(); + myParticle.still(mySpeed > -EPSILON && mySpeed < EPSILON); + } + } + } + } + + protected synchronized void prepareParticles(float theDeltaTime) { + synchronized (mParticles) { + final Iterator iter = mParticles.iterator(); + while (iter.hasNext()) { + final Particle myParticle = iter.next(); + if (HINT_UPDATE_OLD_POSITION) { + myParticle.old_position().set(myParticle.position()); + } + } + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/ShortLivedParticle.java b/day3/libs/teilchen/src/teilchen/ShortLivedParticle.java new file mode 100755 index 0000000..fcb6557 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/ShortLivedParticle.java @@ -0,0 +1,49 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen; + + +public class ShortLivedParticle + extends BasicParticle { + + private float _myMaxAge; + + public ShortLivedParticle(float theMaxAge) { + _myMaxAge = theMaxAge; + } + + public ShortLivedParticle() { + this(1); + } + + public void setMaxAge(float theMaxAge) { + _myMaxAge = theMaxAge; + } + + public float ageRatio() { + return Math.min(age() / _myMaxAge, 1); + } + + public boolean dead() { + return age() >= _myMaxAge; + } +} diff --git a/day3/libs/teilchen/src/teilchen/VectorfieldParticle.java b/day3/libs/teilchen/src/teilchen/VectorfieldParticle.java new file mode 100755 index 0000000..737dc3b --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/VectorfieldParticle.java @@ -0,0 +1,48 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen; + + +import mathematik.Vector3i; + + +public class VectorfieldParticle + extends BasicParticle { + + private Vector3i _myLastUnit; + + public VectorfieldParticle() { + super(); + _myLastUnit = new Vector3i(); + } + + public void setLastUnit(Vector3i theUnit) { + _myLastUnit = theUnit; + } + + public Vector3i getLastUnit() { + return _myLastUnit; + } + + public void accumulateInnerForce(final float theDeltaTime) { + } +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Alignment.java b/day3/libs/teilchen/src/teilchen/behavior/Alignment.java new file mode 100755 index 0000000..253c209 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Alignment.java @@ -0,0 +1,107 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import mathematik.Vector3f; + +import teilchen.IBehaviorParticle; +import teilchen.behavior.Util.ProximityStructure; +import java.io.Serializable; +import java.util.Vector; + + +public class Alignment + implements IBehavior, + Serializable { + + private static final long serialVersionUID = -4953599448151741585L; + + private float mProximity; + + private float mWeight; + + private final Vector3f mForce; + + private Vector mNeighbors; + + public Alignment() { + mProximity = 100.0f; + mWeight = 1.0f; + mForce = new Vector3f(); + } + + public void update(float theDeltaTime, IBehaviorParticle pParent) { + mForce.set(0, 0, 0); + if (mNeighbors != null) { + Vector mCloseNeighbors = ProximityStructure.findProximityEntities(pParent, mNeighbors, mProximity); + findCommonVelocity(mCloseNeighbors, mForce); + mForce.scale(weight()); + } + } + + private static void findCommonVelocity(Vector mCloseNeighbors, final Vector3f pForce) { + /* find away vector */ + pForce.set(0, 0, 0); + if (!mCloseNeighbors.isEmpty()) { + /** + * @todo the vectors could be weighted according to distance: 1.0 - + * distance ( for example ) + */ + for (ProximityStructure p : mCloseNeighbors) { + pForce.add(p.particle.velocity()); + } + pForce.scale(1.0f / mCloseNeighbors.size()); + pForce.normalize(); + if (pForce.isNaN()) { + pForce.set(0, 0, 0); + } + } + } + + public void neighbors(final Vector pNeighbors) { + /** + * @todo well is this OK? + */ + mNeighbors = (Vector) pNeighbors; + } + + public Vector3f force() { + return mForce; + } + + public float weight() { + return mWeight; + } + + public void weight(float pWeight) { + mWeight = pWeight; + } + + public float proximity() { + return mProximity; + } + + public void proximity(float thePrivacyRadius) { + mProximity = thePrivacyRadius; + } +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Arrival.java b/day3/libs/teilchen/src/teilchen/behavior/Arrival.java new file mode 100755 index 0000000..0dedfa2 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Arrival.java @@ -0,0 +1,159 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import mathematik.Vector3f; +import teilchen.IBehaviorParticle; + + +public class Arrival + implements IBehavior, Verhalten { + + static final long serialVersionUID = 6897889750581191781L; + + private Vector3f mSeekPosition; + + private final Vector3f mForce; + + private float mWeight; + + private float mBreakRadius; + + private float mBreakForce; + + private boolean mIsArriving; + + private boolean mHasArrived; + + private boolean mOverSteer; + + public Arrival() { + mBreakRadius = 50.0f; + mBreakForce = 50.0f; + mForce = new Vector3f(); + mSeekPosition = new Vector3f(); + mWeight = 1; + mIsArriving = false; + mHasArrived = false; + mOverSteer = true; + } + + public boolean arriving() { + return mIsArriving; + } + + public boolean arrived() { + return mHasArrived; + } + + public boolean oversteer() { + return mOverSteer; + } + + public void oversteer(boolean pOverSteer) { + mOverSteer = pOverSteer; + } + + public Vector3f position() { + return mSeekPosition; + } + + public void setPositionRef(final Vector3f pPoint) { + mSeekPosition = pPoint; + } + + public void breakforce(float pBreakForce) { + mBreakForce = pBreakForce; + } + + public float breakforce() { + return mBreakForce; + } + + public void breakradius(float pOutterRadius) { + mBreakRadius = pOutterRadius; + } + + public float breakradius() { + return mBreakRadius; + } + + public void update(float theDeltaTime, IBehaviorParticle pParent) { + mForce.sub(mSeekPosition, pParent.position()); + final float myDistanceToArrivalPoint = mForce.length(); + + /* get direction */ + if (myDistanceToArrivalPoint < mBreakRadius) { + mIsArriving = true; + final float mSpeed = pParent.velocity().length(); + final float MIN_ACCEPTABLE_SPEED = 10.0f; + if (mSpeed < MIN_ACCEPTABLE_SPEED) { + /* sleep */ + mForce.set(0, 0, 0); + mHasArrived = true; + } else { + /* break */ + final boolean USE_WEIGHTED_BREAK_FORCE = true; + if (USE_WEIGHTED_BREAK_FORCE) { + final float mRatio = myDistanceToArrivalPoint / mBreakRadius; + + final Vector3f mBreakForceVector = new Vector3f(pParent.velocity()); + mBreakForceVector.scale(-mBreakForce); + mBreakForceVector.scale(1.0f - mRatio); + + final Vector3f mSteerForce = new Vector3f(mForce); + mSteerForce.scale(pParent.maximumInnerForce() / myDistanceToArrivalPoint); + mSteerForce.scale(mRatio); + + mForce.add(mBreakForceVector, mSteerForce); + } else { + mForce.set(pParent.velocity().x * -mBreakForce, + pParent.velocity().y * -mBreakForce, + pParent.velocity().z * -mBreakForce); + } + mHasArrived = false; + } + } else { + /* outside of the outter radius continue 'seeking' */ + mForce.scale(pParent.maximumInnerForce() / myDistanceToArrivalPoint); + if (mOverSteer) { + mForce.sub(mForce, pParent.velocity()); + } + mIsArriving = false; + mHasArrived = false; + } + mForce.scale(weight()); + } + + public Vector3f force() { + return mForce; + } + + public float weight() { + return mWeight; + } + + public void weight(float pWeight) { + mWeight = pWeight; + } +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Cohesion.java b/day3/libs/teilchen/src/teilchen/behavior/Cohesion.java new file mode 100755 index 0000000..8d760a4 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Cohesion.java @@ -0,0 +1,111 @@ + +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import mathematik.Vector3f; + +import teilchen.IBehaviorParticle; +import teilchen.behavior.Util.ProximityStructure; +import java.io.Serializable; +import java.util.Vector; + + +public class Cohesion + implements IBehavior, + Serializable { + + private static final long serialVersionUID = -4953599448151741585L; + + private float mProximity; + + private float mWeight; + + private final Vector3f mForce; + + private Vector mNeighbors; + + public Cohesion() { + mProximity = 100.0f; + mWeight = 1.0f; + mForce = new Vector3f(); + } + + public void update(float theDeltaTime, IBehaviorParticle pParent) { + mForce.set(0, 0, 0); + if (mNeighbors != null) { + Vector mCloseNeighbors = ProximityStructure.findProximityEntities(pParent, mNeighbors, mProximity); + findTowardsVector(mCloseNeighbors, mForce); + mForce.scale(weight()); + } + } + + private static void findTowardsVector(Vector mCloseNeighbors, final Vector3f pForce) { + /* find away vector */ + if (!mCloseNeighbors.isEmpty()) { + pForce.set(0, 0, 0); + /** + * @todo the vectors could be weighted according to distance: 1.0 - + * distance ( for example ) + */ + for (ProximityStructure p : mCloseNeighbors) { + final Vector3f mTowardsVector = mathematik.Util.scale(p.distanceVec, -1.0f); + pForce.add(mTowardsVector); + } + pForce.scale(1.0f / mCloseNeighbors.size()); + pForce.normalize(); + if (pForce.isNaN()) { + pForce.set(0, 0, 0); + } + } else { + pForce.set(0, 0, 0); + } + } + + public void neighbors(final Vector pNeighbors) { + /** + * @todo well is this OK? + */ + mNeighbors = (Vector) pNeighbors; + } + + public Vector3f force() { + return mForce; + } + + public float weight() { + return mWeight; + } + + public void weight(float pWeight) { + mWeight = pWeight; + } + + public float proximity() { + return mProximity; + } + + public void proximity(float thePrivacyRadius) { + mProximity = thePrivacyRadius; + } +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Flee.java b/day3/libs/teilchen/src/teilchen/behavior/Flee.java new file mode 100755 index 0000000..0d5d829 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Flee.java @@ -0,0 +1,77 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import mathematik.Vector3f; + +import teilchen.IBehaviorParticle; + + +public class Flee + implements IBehavior, Verhalten { + + static final long serialVersionUID = -6530887943347815188L; + + private Vector3f mFleePosition; + + private Vector3f mForce; + + private float mWeight = 1; + + public Flee() { + mFleePosition = new Vector3f(); + mForce = new Vector3f(); + } + + public Vector3f position() { + return mFleePosition; + } + + public void setPositionRef(final Vector3f thePoint) { + mFleePosition = thePoint; + } + + public void update(float theDeltaTime, IBehaviorParticle theParent) { + mForce.sub(theParent.position(), mFleePosition); + final float myDistanceToPoint = mForce.length(); + if (myDistanceToPoint > SMALLEST_ACCEPTABLE_DISTANCE) { + mForce.scale(theParent.maximumInnerForce() / myDistanceToPoint); + mForce.sub(mForce, theParent.velocity()); + mForce.scale(weight()); + } else { + mForce.set(0, 0, 0); + } + } + + public Vector3f force() { + return mForce; + } + + public float weight() { + return mWeight; + } + + public void weight(float theWeight) { + mWeight = theWeight; + } +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/IBehavior.java b/day3/libs/teilchen/src/teilchen/behavior/IBehavior.java new file mode 100755 index 0000000..af0fa37 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/IBehavior.java @@ -0,0 +1,42 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import java.io.Serializable; + +import mathematik.Vector3f; + +import teilchen.IBehaviorParticle; + + +public interface IBehavior + extends Serializable { + + void update(float theDeltaTime, final IBehaviorParticle pParent); + + Vector3f force(); + + float weight(); + + void weight(float theWeight); +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Motor.java b/day3/libs/teilchen/src/teilchen/behavior/Motor.java new file mode 100755 index 0000000..17366cd --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Motor.java @@ -0,0 +1,127 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import mathematik.Vector3f; + +import teilchen.IBehaviorParticle; + + +public class Motor + implements IBehavior, + Verhalten { + + static final long serialVersionUID = -3781170603537691466L; + + private Vector3f mDirection; + + private float mStrength; + + private final Vector3f mForce; + + private float mWeight; + + private boolean mAutoNormalizeDirection; + + private boolean mActive; + + private boolean mAutoUpdateDirection; + + public final Vector3f AUTO_RECOVER_DIRECTION; + + public Motor() { + mDirection = new Vector3f(1, 0, 0); + mForce = new Vector3f(); + mActive = true; + mStrength = 1; + mWeight = 1; + mAutoUpdateDirection = false; + mAutoNormalizeDirection = true; + AUTO_RECOVER_DIRECTION = new Vector3f(); + AUTO_RECOVER_DIRECTION.randomize(); + AUTO_RECOVER_DIRECTION.z = 0; + } + + public boolean active() { + return mActive; + } + + public void active(boolean pActive) { + mActive = pActive; + } + + public float strength() { + return mStrength; + } + + public void strength(final float theStrength) { + mStrength = theStrength; + } + + public Vector3f direction() { + return mDirection; + } + + public void setDirectionRef(final Vector3f theDirection) { + mDirection = theDirection; + } + + public void auto_update_direction(boolean pAutoUpdateDirection) { + mAutoUpdateDirection = pAutoUpdateDirection; + } + + public void auto_normalize_direction(boolean pAutoNormalizeDirection) { + mAutoNormalizeDirection = pAutoNormalizeDirection; + } + + public void update(float theDeltaTime, IBehaviorParticle pParent) { + if (mActive) { + if (mAutoUpdateDirection) { + if (pParent.velocity().length() > 0.0f) { + mDirection.set(pParent.velocity()); + } else { + mDirection.set(AUTO_RECOVER_DIRECTION); + } + } + if (mAutoNormalizeDirection) { + mDirection.normalize(); + } + mForce.scale(mStrength, mDirection); + mForce.scale(mWeight, mForce); + } else { + mForce.set(0, 0, 0); + } + } + + public Vector3f force() { + return mForce; + } + + public float weight() { + return mWeight; + } + + public void weight(float theWeight) { + mWeight = theWeight; + } +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Seek.java b/day3/libs/teilchen/src/teilchen/behavior/Seek.java new file mode 100755 index 0000000..d3f64cd --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Seek.java @@ -0,0 +1,96 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import mathematik.Vector3f; + +import teilchen.IBehaviorParticle; + + +public class Seek + implements IBehavior, Verhalten { + + static final long serialVersionUID = -3781170603537691477L; + + private Vector3f mSeekPosition; + + private Vector3f mForce; + + private float mWeight = 1; + + private float mDistanceToPoint; + + private boolean mOverSteer; + + public Seek() { + mSeekPosition = new Vector3f(); + mForce = new Vector3f(); + mOverSteer = false; + } + + public boolean oversteer() { + return mOverSteer; + } + + public void oversteer(boolean pOverSteer) { + mOverSteer = pOverSteer; + } + + public Vector3f position() { + return mSeekPosition; + } + + public void setPositionRef(final Vector3f thePoint) { + mSeekPosition = thePoint; + } + + public float distancetopoint() { + return mDistanceToPoint; + } + + public void update(float theDeltaTime, IBehaviorParticle theParent) { + mForce.sub(mSeekPosition, theParent.position()); + mDistanceToPoint = mForce.length(); + if (mDistanceToPoint > SMALLEST_ACCEPTABLE_DISTANCE) { + mForce.scale(theParent.maximumInnerForce() / mDistanceToPoint); + if (mOverSteer) { + mForce.sub(mForce, theParent.velocity()); + } + mForce.scale(weight()); + } else { + mForce.set(0, 0, 0); + } + } + + public Vector3f force() { + return mForce; + } + + public float weight() { + return mWeight; + } + + public void weight(float theWeight) { + mWeight = theWeight; + } +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Separation.java b/day3/libs/teilchen/src/teilchen/behavior/Separation.java new file mode 100755 index 0000000..90d6279 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Separation.java @@ -0,0 +1,110 @@ + +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import mathematik.Vector3f; + +import teilchen.IBehaviorParticle; +import teilchen.behavior.Util.ProximityStructure; +import java.io.Serializable; +import java.util.Vector; + + +public class Separation + implements IBehavior, + Serializable { + + private static final long serialVersionUID = -4953599448151741585L; + + private float mProximity; + + private float mWeight; + + private final Vector3f mForce; + + private Vector mNeighbors; + + public Separation() { + mProximity = 100.0f; + mWeight = 1.0f; + mForce = new Vector3f(); + } + + public void update(float theDeltaTime, IBehaviorParticle pParent) { + mForce.set(0, 0, 0); + if (mNeighbors != null) { + Vector mCloseNeighbors = ProximityStructure.findProximityEntities(pParent, mNeighbors, mProximity); + findAwayVector(mCloseNeighbors, mForce); + mForce.scale(weight()); + } + } + + private static void findAwayVector(Vector mCloseNeighbors, final Vector3f pForce) { + /* find away vector */ + if (!mCloseNeighbors.isEmpty()) { + pForce.set(0, 0, 0); + /** + * @todo the vectors could be weighted according to distance: 1.0 - + * distance ( for example ) + */ + for (ProximityStructure p : mCloseNeighbors) { + pForce.add(p.distanceVec); + } + pForce.scale(1.0f / mCloseNeighbors.size()); + pForce.normalize(); + if (pForce.isNaN()) { + pForce.set(0, 0, 0); + } + } else { + pForce.set(0, 0, 0); + } + } + + public void neighbors(final Vector pNeighbors) { + /** + * @todo well is this OK? + */ + mNeighbors = (Vector) pNeighbors; + } + + public Vector3f force() { + return mForce; + } + + public float weight() { + return mWeight; + } + + public void weight(float pWeight) { + mWeight = pWeight; + } + + public float proximity() { + return mProximity; + } + + public void proximity(float thePrivacyRadius) { + mProximity = thePrivacyRadius; + } +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Steering.java b/day3/libs/teilchen/src/teilchen/behavior/Steering.java new file mode 100755 index 0000000..ee609d9 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Steering.java @@ -0,0 +1,91 @@ + +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + +import mathematik.Vector3f; +import teilchen.IBehaviorParticle; + +public class Steering implements IBehavior, + Verhalten { + + private final Vector3f mForce; + private final Vector3f mUPVector; + + private float mWeight; + + private float mSteering = 0.0f; + + private boolean mActive = true; + + public Steering() { + mForce = new Vector3f(); + mUPVector = new Vector3f(0, 0, -1); + mWeight = 1; + } + + public void update(float theDeltaTime, IBehaviorParticle pParent) { + if (mActive) { + /* 2D warning -- ignoring z-axis for now */ + Vector3f mDirection = new Vector3f(pParent.velocity()); + if (mDirection.lengthSquared() > 0) { + mDirection.normalize(); + mDirection = mathematik.Util.cross(mDirection, mUPVector); + mDirection.scale(mSteering); + mForce.set(mDirection); + } else { + mForce.set(0, 0, 0); + } + } else { + mForce.set(0, 0, 0); + } + } + + public float steering_strength() { + return mSteering; + } + + public void steering_strength(float pSteering) { + mSteering = pSteering; + } + + public Vector3f force() { + return mForce; + } + + public Vector3f upvector() { + return mUPVector; + } + + public float weight() { + return mWeight; + } + + public void weight(float pWeight) { + mWeight = pWeight; + } + + public void active(boolean pActive) { + mActive = pActive; + } + +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Util.java b/day3/libs/teilchen/src/teilchen/behavior/Util.java new file mode 100755 index 0000000..a9bcbfd --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Util.java @@ -0,0 +1,66 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import mathematik.Vector3f; + +import teilchen.IBehaviorParticle; +import teilchen.Particle; + +import java.util.Vector; + + +public class Util { + + public static class ProximityStructure { + + public final Particle particle; + + public final Vector3f distanceVec; + + public final float distance; + + public ProximityStructure(Particle pP, Vector3f pDistanceVec, float pDistance) { + particle = pP; + distanceVec = pDistanceVec; + distance = pDistance; + } + + public static Vector findProximityEntities(IBehaviorParticle pParentEntity, + Vector pNeighborsEntity, + float pProximity) { + /* find neighbors in proximity */ + Vector mCloseNeighbors = new Vector(); + for (IBehaviorParticle p : pNeighborsEntity) { + if (!p.equals(pParentEntity)) { /* exclude self */ + final Vector3f mDistanceVec = mathematik.Util.sub(pParentEntity.position(), p.position()); + final float mDistance = mDistanceVec.length(); + if (mDistance <= pProximity) { + mCloseNeighbors.add(new ProximityStructure(p, mDistanceVec, mDistance)); + } + } + } + return mCloseNeighbors; + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Verhalten.java b/day3/libs/teilchen/src/teilchen/behavior/Verhalten.java new file mode 100755 index 0000000..f03f369 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Verhalten.java @@ -0,0 +1,33 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import java.io.Serializable; + + +public interface Verhalten + extends Serializable { + + float SMALLEST_ACCEPTABLE_DISTANCE = 0.01f; + +} diff --git a/day3/libs/teilchen/src/teilchen/behavior/Wander.java b/day3/libs/teilchen/src/teilchen/behavior/Wander.java new file mode 100755 index 0000000..0346fdb --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/behavior/Wander.java @@ -0,0 +1,122 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.behavior; + + +import mathematik.Random; +import mathematik.Vector3f; + +import teilchen.IBehaviorParticle; + + +public class Wander + implements IBehavior { + + static final long serialVersionUID = 4957162698340669663L; + + private Vector3f mForce; + + private float mSteeringStrength; + + private float mSteeringOffset; + + private float mCurrentSteeringStrength; + + private Vector3f mUpVector; + + private float mWeight; + + private final Random mRandom; + + private boolean mActive; + + public Wander() { + mRandom = new Random(); + + mForce = new Vector3f(); + mSteeringStrength = 10f; + mSteeringOffset = 5f; + + mUpVector = new Vector3f(0, 0, 1); + + mWeight = 1; + mActive = true; + } + + public boolean active() { + return mActive; + } + + public void active(boolean pActive) { + mActive = pActive; + } + + public Vector3f force() { + return mForce; + } + + public float weight() { + return mWeight; + } + + public void weight(float theWeight) { + mWeight = theWeight; + } + + public void update(float pDeltaTime, IBehaviorParticle pParent) { + if (mActive && pParent.velocity().length() > 0) { + mCurrentSteeringStrength += mRandom.getFloat(-0.5f, 0.5f) * mSteeringOffset; + mCurrentSteeringStrength = Math.max(Math.min(mCurrentSteeringStrength, mSteeringStrength), -mSteeringStrength); + + final Vector3f mWanderTarget = mathematik.Util.cross(mUpVector, pParent.velocity()); + mWanderTarget.normalize(); + mWanderTarget.scale(mCurrentSteeringStrength); + if (mWanderTarget.isNaN()) { + mForce.set(0, 0, 0); + } else { + mForce.scale(mWeight, mWanderTarget); + } + } else { + mForce.set(0, 0, 0); + } + } + + public Vector3f upvector() { + return mUpVector; + } + + public float steeringstrength() { + return mSteeringStrength; + } + + public void steeringstrength(final float theSteeringStrength) { + mSteeringStrength = theSteeringStrength; + } + + public float steeringoffset() { + return mSteeringOffset; + } + + public void steeringoffset(final float theSteeringOffset) { + mSteeringOffset = theSteeringOffset; + } +} diff --git a/day3/libs/teilchen/src/teilchen/constraint/AngleConstraintStick.java b/day3/libs/teilchen/src/teilchen/constraint/AngleConstraintStick.java new file mode 100755 index 0000000..c2a6162 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/constraint/AngleConstraintStick.java @@ -0,0 +1,79 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.constraint; + + +import mathematik.Vector3f; + +import teilchen.Particle; + + +public class AngleConstraintStick + extends Stick { + + private final Particle mParticleA; + + private final Particle mParticleB; + + private final Particle mParticleC; + + private float mMinAngle; + + /** + * + * particles are connected like this: A -- B -- C + * + * @param pParticleA + * @param pParticleB + * @param pParticleC + */ + public AngleConstraintStick(Particle pParticleA, Particle pParticleB, Particle pParticleC) { + super(pParticleA, pParticleC); + mParticleA = pParticleA; + mParticleB = pParticleB; + mParticleC = pParticleC; + mMinAngle = Float.MAX_VALUE; + } + + public void min_angle(float pAngle) { + mMinAngle = pAngle; + } + + public void pre_step() { + Vector3f ab = mathematik.Util.sub(mParticleA.position(), mParticleB.position()); + Vector3f cb = mathematik.Util.sub(mParticleC.position(), mParticleB.position()); + final float mCurrentAngle = ab.angle(cb); + + if (mCurrentAngle < mMinAngle) { + final float b = ab.length(); + final float c = cb.length(); + // a = sqrt ( b*b + c*c - 2bc*cosA ) + final float mDistance = (float) Math.sqrt(b * b + c * c - 2 * b * c * (float) Math.cos(mMinAngle)); + restlength(mDistance); + active(true); + } + } + + public void post_step() { + active(false); + } +} diff --git a/day3/libs/teilchen/src/teilchen/constraint/Angular.java b/day3/libs/teilchen/src/teilchen/constraint/Angular.java new file mode 100755 index 0000000..01004be --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/constraint/Angular.java @@ -0,0 +1,221 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.constraint; + + +import mathematik.Util; +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; + + +/** + * @todo it probably pays of two check if we deal with a 2D or 3D constraint. it + * s just checking components once and then saving a lot of time. + */ +public class Angular + implements IConstraint { + + protected boolean mActive = true; + + private final Particle _myA; + + private final Particle _myB; + + private final Particle _myC; + + private final Vector3f _myTempA = new Vector3f(); + + private final Vector3f _myTempB = new Vector3f(); + + private float _myMinimumAngle; + + private float _myMaximumAngle; + + private final Vector3f _myTempNormal; + + public boolean OK; + + private static final double EPSILON = 0.001; + + private static final double _myStrength = 1; + + public Angular(Particle theA, Particle theB, Particle theC, + float theMinimumAngle, float theMaximumAngle) { + _myA = theA; + _myB = theB; + _myC = theC; + _myTempNormal = new Vector3f(); + range(theMinimumAngle, theMaximumAngle); + } + + public Angular(Particle theA, Particle theB, Particle theC) { + this(theA, + theB, + theC, + 0, 0); + } + + public void range(float theMinimumAngle, float theMaximumAngle) { + _myMinimumAngle = theMinimumAngle; + _myMaximumAngle = theMaximumAngle; + sortAngles(); + } + + public float minimumAngle() { + return _myMinimumAngle; + } + + public float maximumAngle() { + return _myMaximumAngle; + } + + private void sortAngles() { + final float myMaximumAngle = _myMaximumAngle; + final float myMinimumAngle = _myMinimumAngle; + _myMaximumAngle = Math.max(myMaximumAngle, myMinimumAngle); + _myMinimumAngle = Math.min(myMaximumAngle, myMinimumAngle); + } + + public void apply(Physics theParticleSystem) { + + if (!mActive) { + return; + } + + /** + * @todo test for special case: a and c are in the same place. + */ + _myTempA.sub(_myB.position(), _myA.position()); + _myTempB.sub(_myB.position(), _myC.position()); + + _myTempA.normalize(); + _myTempB.normalize(); + + /** + * @todo check for special cases! like angle being 0 etc. + */ + /** + * @todo check if the range exceeds PI. + */ + if (_myMinimumAngle < Math.PI && _myMaximumAngle > Math.PI) { + System.out.println("### WARNING split range and check twice."); + } + + float myCosinusAngle = _myTempA.dot(_myTempB); + if (myCosinusAngle > 1) { + System.out.println("### WARNING myCosinusAngle > 1: " + myCosinusAngle); + myCosinusAngle = 1; + } + + final float myTempCosMaximumAngle = (float) Math.cos(_myMaximumAngle); + final float myTempCosMinimumAngle = (float) Math.cos(_myMinimumAngle); + final float myCosMaximumAngle = Math.max(myTempCosMinimumAngle, myTempCosMaximumAngle); + final float myCosMinimumAngle = Math.min(myTempCosMinimumAngle, myTempCosMaximumAngle); + + calculateNormal(_myTempA, _myTempB); + final boolean myLeftSide = checkForHemisphere(_myTempA, _myTempB); + double myCurrentAngle = 0; + + /** + * @todo until i the split is implemented agular constraints only work + * for one side. + */ + OK = myLeftSide; + + if (myLeftSide) { + if (myCosinusAngle < myCosMinimumAngle || myCosinusAngle > myCosMaximumAngle) { + myCurrentAngle = Math.acos(myCosinusAngle); + OK = false; + } else { + OK = true; + } + } else { + myCurrentAngle = 2 * Math.PI - Math.acos(myCosinusAngle); + } + + if (!OK) { + final double myTheta; + if (myCurrentAngle > _myMaximumAngle) { + myTheta = _myMaximumAngle - myCurrentAngle; + } else if (myCosinusAngle < _myMinimumAngle) { + myTheta = -1 * (myCurrentAngle - _myMinimumAngle); + } else { + System.out.println("### WARNING puzzled."); + myTheta = 0; + } + + correctAngle(myTheta); + } + } + + private void calculateNormal(Vector3f myVectorA, Vector3f myVectorB) { + _myTempNormal.cross(myVectorA, myVectorB); + _myTempNormal.normalize(); + if (_myTempNormal.isNaN()) { + _myTempNormal.set(0, 0, 1); + System.out.println("### WARNING can t find normal."); + } + } + + private void correctAngle(double theTheta) { + if (theTheta < -EPSILON || theTheta > EPSILON) { + + Vector3f myOtherPointOnAxis = Util.add(_myB.position(), _myTempNormal); + + Vector3f myRotatedPointA = Util.rotatePoint(_myA.position(), theTheta * -0.5 * _myStrength, + _myB.position(), + myOtherPointOnAxis); + _myA.position().set(myRotatedPointA); + + Vector3f myRotatedPointB = Util.rotatePoint(_myC.position(), theTheta * 0.5 * _myStrength, + _myB.position(), + myOtherPointOnAxis); + _myC.position().set(myRotatedPointB); + + System.out.println("correct " + Math.toDegrees(theTheta) + " / " + _myTempNormal); + } + } + + private boolean checkForHemisphere(Vector3f myVectorA, Vector3f myVectorB) { + /* special case thus easy to find the direction */ + if (myVectorA.z == 0 && myVectorB.z == 0) { + return _myTempNormal.z > 0; + } else { + /** + * @todo do it the hard way and create a matrix from the two vectors + * and transform the cross vector into local space + */ + System.out.println("### WARNING calculate for 3D plane / not implemented."); + return true; + } + } + + public boolean active() { + return mActive; + } + + public void active(boolean theActiveState) { + mActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/constraint/Box.java b/day3/libs/teilchen/src/teilchen/constraint/Box.java new file mode 100755 index 0000000..85fa0fe --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/constraint/Box.java @@ -0,0 +1,179 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.constraint; + + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.integration.Verlet; + + +public class Box + implements IConstraint { + + protected boolean mActive = true; + + private final Vector3f _myMin; + + private final Vector3f _myMax; + + private boolean _myReflectFlag; + + private float _myCoefficientOfRestitution; + + private boolean _myTeleport; + + public Box(final Vector3f theMin, final Vector3f theMax) { + _myMin = theMin; + _myMax = theMax; + _myReflectFlag = true; + _myCoefficientOfRestitution = 1.0f; + _myTeleport = false; + } + + public Box() { + this(new Vector3f(), new Vector3f()); + } + + public void telelport(boolean theTeleportState) { + _myTeleport = theTeleportState; + } + + public void reflect(boolean theReflectState) { + _myReflectFlag = theReflectState; + } + + public Vector3f min() { + return _myMin; + } + + public Vector3f max() { + return _myMax; + } + private static final Vector3f[] _myNormals; + + static { + _myNormals = new Vector3f[6]; + _myNormals[0] = new Vector3f(-1, 0, 0); + _myNormals[1] = new Vector3f(0, -1, 0); + _myNormals[2] = new Vector3f(0, 0, -1); + _myNormals[3] = new Vector3f(1, 0, 0); + _myNormals[4] = new Vector3f(0, 1, 0); + _myNormals[5] = new Vector3f(0, 0, 1); + } + + public void coefficientofrestitution(float theCoefficientOfRestitution) { + _myCoefficientOfRestitution = theCoefficientOfRestitution; + } + + public float coefficientofrestitution() { + return _myCoefficientOfRestitution; + } + + public void apply(final Physics theParticleSystem) { + + if (!mActive) { + return; + } + + for (final Particle myParticle : theParticleSystem.particles()) { + if (_myTeleport) { + if (myParticle.position().x > _myMax.x) { + myParticle.position().x = _myMin.x; + } + if (myParticle.position().y > _myMax.y) { + myParticle.position().y = _myMin.y; + } + if (myParticle.position().z > _myMax.z) { + myParticle.position().z = _myMin.z; + } + if (myParticle.position().x < _myMin.x) { + myParticle.position().x = _myMax.x; + } + if (myParticle.position().y < _myMin.y) { + myParticle.position().y = _myMax.y; + } + if (myParticle.position().z < _myMin.z) { + myParticle.position().z = _myMax.z; + } + } else { + /** + * @todo to do this properly we would need to add the normals + * and normalize them. maybe later. + */ + int myTag = -1; + final Vector3f myPosition = new Vector3f(myParticle.position()); + if (myParticle.position().x > _myMax.x) { + myParticle.position().x = _myMax.x; + myTag = 0; + } + if (myParticle.position().y > _myMax.y) { + myParticle.position().y = _myMax.y; + myTag = 1; + } + if (myParticle.position().z > _myMax.z) { + myParticle.position().z = _myMax.z; + myTag = 2; + } + if (myParticle.position().x < _myMin.x) { + myParticle.position().x = _myMin.x; + myTag = 3; + } + if (myParticle.position().y < _myMin.y) { + myParticle.position().y = _myMin.y; + myTag = 4; + } + if (myParticle.position().z < _myMin.z) { + myParticle.position().z = _myMin.z; + myTag = 5; + } + if (myTag >= 0) { + if (_myReflectFlag) { + if (theParticleSystem.getIntegrator() instanceof Verlet) { + final Vector3f myDiff = mathematik.Util.sub(myPosition, myParticle.position()); + teilchen.util.Util.reflect(myDiff, _myNormals[myTag], _myCoefficientOfRestitution); +// System.out.println("### reflect " + _myNormals[myTag]); +// System.out.println("myDiff " + myDiff); + myParticle.old_position().sub(myDiff); + } else { + teilchen.util.Util.reflectVelocity(myParticle, + _myNormals[myTag], + _myCoefficientOfRestitution); + } + } else { + myParticle.velocity().set(0, 0, 0); + } + } + } + } + } + + public boolean active() { + return mActive; + } + + public void active(boolean theActiveState) { + mActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/constraint/IConstraint.java b/day3/libs/teilchen/src/teilchen/constraint/IConstraint.java new file mode 100755 index 0000000..5c93a8c --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/constraint/IConstraint.java @@ -0,0 +1,35 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.constraint; + + +import teilchen.Physics; + + +public interface IConstraint { + + void apply(final Physics theParticleSystem); + + boolean active(); + + void active(boolean theActiveState); +} diff --git a/day3/libs/teilchen/src/teilchen/constraint/ReflectBox.java b/day3/libs/teilchen/src/teilchen/constraint/ReflectBox.java new file mode 100755 index 0000000..0f560d2 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/constraint/ReflectBox.java @@ -0,0 +1,221 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.constraint; + + +import java.util.Vector; + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.integration.Verlet; + + +public class ReflectBox + implements IConstraint { + + protected boolean mActive = true; + + private final Vector3f _myMin; + + private final Vector3f _myMax; + + private float _myCoefficientOfRestitution; + + private float _myEpsilon; + + public boolean NEGATIVE_X = true; + + public boolean NEGATIVE_Y = true; + + public boolean NEGATIVE_Z = true; + + public boolean POSITIV_X = true; + + public boolean POSITIV_Y = true; + + public boolean POSITIV_Z = true; + + public ReflectBox(final Vector3f theMin, final Vector3f theMax) { + _myMin = theMin; + _myMax = theMax; + _myCoefficientOfRestitution = 1.0f; + _myEpsilon = 0.001f; + } + + public ReflectBox() { + this(new Vector3f(), new Vector3f()); + } + + public void epsilon(final float theEpsilon) { + _myEpsilon = theEpsilon; + } + + public Vector3f min() { + return _myMin; + } + + public Vector3f max() { + return _myMax; + } + private static final Vector3f[] _myNormals; + + static { + _myNormals = new Vector3f[6]; + _myNormals[0] = new Vector3f(-1, 0, 0); + _myNormals[1] = new Vector3f(0, -1, 0); + _myNormals[2] = new Vector3f(0, 0, -1); + _myNormals[3] = new Vector3f(1, 0, 0); + _myNormals[4] = new Vector3f(0, 1, 0); + _myNormals[5] = new Vector3f(0, 0, 1); + } + + public void coefficientofrestitution(float theCoefficientOfRestitution) { + _myCoefficientOfRestitution = theCoefficientOfRestitution; + } + + public float coefficientofrestitution() { + return _myCoefficientOfRestitution; + } + + public void apply(final Physics theParticleSystem) { + if (!(theParticleSystem.getIntegrator() instanceof Verlet)) { + System.out.println("### WARNING @ " + getClass().getSimpleName() + " / only works with verlet integrator."); + } + apply(theParticleSystem.particles()); + } + + public void apply(final Vector theParticles) { + apply(theParticles, null); + } + + public void apply(final Vector theParticles, final Vector theCollisionParticles) { + if (!mActive) { + return; + } + + for (final Particle myParticle : theParticles) { + final Vector3f myPositionBeforeCollision = new Vector3f(myParticle.position()); + final Vector3f p = myParticle.position(); + final Vector3f p_old = myParticle.old_position(); + final float r = myParticle.radius(); + /** + * @todo we should weight the deflection normal + */ + if (p.x + r > _myMax.x + || p.y + r > _myMax.y + || p.z + r > _myMax.z + || p.x - r < _myMin.x + || p.y - r < _myMin.y + || p.z - r < _myMin.z) { + int myNumberOfCollisions = 0; + final Vector3f myDeflectionNormal = new Vector3f(); + if (POSITIV_X) { + if (p.x + r > _myMax.x) { + final float myBorderDiff = _myMax.x - p_old.x - r; + p.x = p_old.x + myBorderDiff; + myDeflectionNormal.add(_myNormals[0]); + myNumberOfCollisions++; + } + } + + if (POSITIV_Y) { + if (p.y + r > _myMax.y) { + final float myBorderDiff = _myMax.y - p_old.y - r; + p.y = p_old.y + myBorderDiff; + myDeflectionNormal.add(_myNormals[1]); + myNumberOfCollisions++; + } + } + + if (POSITIV_Z) { + if (p.z + r > _myMax.z) { + final float myBorderDiff = _myMax.z - p_old.z - r; + p.z = p_old.z + myBorderDiff; + myDeflectionNormal.add(_myNormals[2]); + myNumberOfCollisions++; + } + } + + if (NEGATIVE_X) { + if (p.x - r < _myMin.x) { + final float myBorderDiff = _myMin.x - p_old.x + r; + p.x = p_old.x + myBorderDiff; + myDeflectionNormal.add(_myNormals[3]); + myNumberOfCollisions++; + } + } + + if (NEGATIVE_Y) { + if (p.y - r < _myMin.y) { + final float myBorderDiff = _myMin.y - p_old.y + r; + p.y = p_old.y + myBorderDiff; + myDeflectionNormal.add(_myNormals[4]); + myNumberOfCollisions++; + } + } + + if (NEGATIVE_Z) { + if (p.z - r < _myMin.z) { + final float myBorderDiff = _myMin.z - p_old.z + r; + p.z = p_old.z + myBorderDiff; + myDeflectionNormal.add(_myNormals[5]); + myNumberOfCollisions++; + } + } + + if (myNumberOfCollisions > 0) { + /* remember collided particles */ + if (theCollisionParticles != null) { + theCollisionParticles.add(myParticle); + } + /* room for optimization / we don t need to reflect twice. */ + final float mySpeed = myPositionBeforeCollision.distanceSquared(myParticle.old_position()); + if (mySpeed > _myEpsilon) { + final Vector3f myDiffAfterCollision = mathematik.Util.sub(myPositionBeforeCollision, + myParticle.position()); + final Vector3f myDiffBeforeCollision = mathematik.Util.sub(myParticle.old_position(), + myParticle.position()); + myDeflectionNormal.scale(1.0f / (float) myNumberOfCollisions); + teilchen.util.Util.reflect(myDiffAfterCollision, myDeflectionNormal, + _myCoefficientOfRestitution); + teilchen.util.Util.reflect(myDiffBeforeCollision, myDeflectionNormal, 1); + + if (!myParticle.old_position().isNaN() && !myParticle.position().isNaN()) { + myParticle.old_position().add(myParticle.position(), myDiffBeforeCollision); + myParticle.position().add(myDiffAfterCollision); + } + } + } + } + } + } + + public boolean active() { + return mActive; + } + + public void active(boolean theActiveState) { + mActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/constraint/Stick.java b/day3/libs/teilchen/src/teilchen/constraint/Stick.java new file mode 100755 index 0000000..f20bbdb --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/constraint/Stick.java @@ -0,0 +1,158 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.constraint; + + +import mathematik.Vector3f; + +import teilchen.IConnection; +import teilchen.Particle; +import teilchen.Physics; + + +public class Stick + implements IConstraint, + IConnection { + + protected final Particle mA; + + protected final Particle mB; + + protected float mRestLength; + + protected final Vector3f mTempDistanceVector; + + protected final Vector3f mTempVector; + + protected boolean mOneWay; + + protected float mDamping; + + protected boolean mActive = true; + + protected static final float EPSILON = 0.0001f; + + public Stick(Particle theA, Particle theB) { + this(theA, + theB, + theA.position().distance(theB.position())); + } + + public Stick(final Particle theA, + final Particle theB, + final float theRestLength) { + mRestLength = theRestLength; + mA = theA; + mB = theB; + mTempDistanceVector = new Vector3f(); + mTempVector = new Vector3f(); + mOneWay = false; + mDamping = 1f; + } + + public void setRestLengthByPosition() { + mRestLength = mA.position().distance(mB.position()); + } + + public float damping() { + return mDamping; + } + + public void damping(float theDamping) { + mDamping = theDamping; + } + + public float restlength() { + return mRestLength; + } + + public void restlength(float theRestLength) { + mRestLength = theRestLength; + } + + public final Particle a() { + return mA; + } + + public final Particle b() { + return mB; + } + + public void setOneWay(boolean theOneWayState) { + mOneWay = theOneWayState; + } + + public void apply(Physics theParticleSystem) { + if (!mActive) { + return; + } + if (mA.fixed() && mB.fixed()) { + return; + } + mTempDistanceVector.sub(mA.position(), mB.position()); + final float myDistanceSquared = mTempDistanceVector.lengthSquared(); + if (myDistanceSquared > 0) { + final float myDistance = (float) Math.sqrt(myDistanceSquared); + final float myDifference = mRestLength - myDistance; + if (myDifference > EPSILON || myDifference < -EPSILON) { + if (!mOneWay) { + final float myDifferenceScale = mDamping * 0.5f * myDifference / myDistance; + mTempVector.scale(myDifferenceScale, mTempDistanceVector); + if (mA.fixed()) { + mB.position().sub(mTempVector); + mB.position().sub(mTempVector); + } else if (mB.fixed()) { + mA.position().add(mTempVector); + mA.position().add(mTempVector); + } else { + mA.position().add(mTempVector); + mB.position().sub(mTempVector); + } + } else { + final float myDifferenceScale = myDifference / myDistance; + mTempVector.scale(myDifferenceScale, mTempDistanceVector); + mB.position().sub(mTempVector); + } + } + } else { + if (mA.fixed()) { + mB.position().set(mA.position()); + mB.position().x += mRestLength; + } else if (mB.fixed()) { + mA.position().set(mB.position()); + mA.position().x += mRestLength; + } else { + mB.position().set(mA.position()); + mA.position().x -= mRestLength / 2; + mB.position().x += mRestLength / 2; + } + } + } + + public boolean active() { + return mActive; + } + + public void active(boolean theActiveState) { + mActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/constraint/Teleporter.java b/day3/libs/teilchen/src/teilchen/constraint/Teleporter.java new file mode 100755 index 0000000..d3e2704 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/constraint/Teleporter.java @@ -0,0 +1,90 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.constraint; + + +import mathematik.Vector3f; +import teilchen.Particle; +import teilchen.Physics; + + +public class Teleporter + implements IConstraint { + + protected boolean mActive = true; + + private final Vector3f mMin; + + private final Vector3f mMax; + + public Teleporter() { + this(new Vector3f(), new Vector3f()); + } + + public Teleporter(final Vector3f pMin, final Vector3f pMax) { + mMin = new Vector3f(pMin); + mMax = new Vector3f(pMax); + } + + public Vector3f max() { + return mMax; + } + + public Vector3f min() { + return mMin; + } + + public void apply(Physics theParticleSystem) { + if (!mActive) { + return; + } + + for (final Particle mParticle : theParticleSystem.particles()) { + if (mParticle.position().x > mMax.x) { + mParticle.position().x -= Math.abs(mMax.x - mMin.x); + } + if (mParticle.position().y > mMax.y) { + mParticle.position().y -= Math.abs(mMax.y - mMin.y); + } + if (mParticle.position().z > mMax.z) { + mParticle.position().z -= Math.abs(mMax.z - mMin.z); + } + if (mParticle.position().x < mMin.x) { + mParticle.position().x += Math.abs(mMax.x - mMin.x); + } + if (mParticle.position().y < mMin.y) { + mParticle.position().y += Math.abs(mMax.y - mMin.y); + } + if (mParticle.position().z < mMin.z) { + mParticle.position().z += Math.abs(mMax.z - mMin.z); + } + } + } + + public boolean active() { + return mActive; + } + + public void active(boolean theActiveState) { + mActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/cubicle/CubicleAtom.java b/day3/libs/teilchen/src/teilchen/cubicle/CubicleAtom.java new file mode 100755 index 0000000..f765e00 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/cubicle/CubicleAtom.java @@ -0,0 +1,67 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.cubicle; + + +import java.util.Vector; + +import mathematik.Vector3i; + + +/* + * container class for ICubicleEntity representing one cube in the world. + */ +public class CubicleAtom { + + private Vector mContainer; + + private final Vector3i mPosition; + + public CubicleAtom(int x, int y, int z) { + mContainer = new Vector(); + mPosition = new Vector3i(x, y, z); + } + + public Vector3i position() { + return mPosition; + } + + public void add(ICubicleEntity theEntity) { + mContainer.add(theEntity); + } + + public boolean remove(ICubicleEntity theEntity) { + return mContainer.remove(theEntity); + } + + public void clear() { + mContainer.clear(); + } + + public int size() { + return mContainer.size(); + } + + public Vector data() { + return mContainer; + } +} diff --git a/day3/libs/teilchen/src/teilchen/cubicle/CubicleEntity.java b/day3/libs/teilchen/src/teilchen/cubicle/CubicleEntity.java new file mode 100755 index 0000000..b21aa49 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/cubicle/CubicleEntity.java @@ -0,0 +1,61 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.cubicle; + + +import mathematik.Vector3f; +import mathematik.Vector3i; + + +public class CubicleEntity + implements ICubicleEntity { + + private Vector3i _myCubiclePosition; + + private final Vector3f _myPosition; + + public CubicleEntity() { + _myCubiclePosition = new Vector3i(); + _myPosition = new Vector3f(); + } + + public Vector3i cubicle() { + return _myCubiclePosition; + } + + public Vector3f position() { + return _myPosition; + } + + public boolean leaving(int theX, int theY, int theZ) { + if (theX == cubicle().x + && theY == cubicle().y + && theZ == cubicle().z) { + return false; + } + return true; + } + + public boolean isActive() { + return true; + } +} diff --git a/day3/libs/teilchen/src/teilchen/cubicle/CubicleParticle.java b/day3/libs/teilchen/src/teilchen/cubicle/CubicleParticle.java new file mode 100755 index 0000000..072e33f --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/cubicle/CubicleParticle.java @@ -0,0 +1,63 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.cubicle; + + +import mathematik.Vector3f; +import mathematik.Vector3i; + +import teilchen.BasicParticle; + + +public class CubicleParticle + extends BasicParticle implements ICubicleEntity { + + private final Vector3i _myCubiclePosition; + + private final Vector3f _myPosition; + + public CubicleParticle() { + _myCubiclePosition = new Vector3i(); + _myPosition = new Vector3f(); + } + + public Vector3i cubicle() { + return _myCubiclePosition; + } + + public Vector3f position() { + return _myPosition; + } + + public boolean leaving(int theX, int theY, int theZ) { + if (theX == cubicle().x + && theY == cubicle().y + && theZ == cubicle().z) { + return false; + } + return true; + } + + public boolean isActive() { + return !fixed(); + } +} diff --git a/day3/libs/teilchen/src/teilchen/cubicle/CubicleWorld.java b/day3/libs/teilchen/src/teilchen/cubicle/CubicleWorld.java new file mode 100755 index 0000000..5d5026a --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/cubicle/CubicleWorld.java @@ -0,0 +1,302 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.cubicle; + + +import mathematik.TransformMatrix4f; +import mathematik.Vector3f; +import mathematik.Vector3i; + +import java.util.Iterator; +import java.util.Vector; + + +/* + * cubicle world handles entities and queries about a cubicles state. + */ +public class CubicleWorld { + + public static final int OFF_WORLD = -1; + + private CubicleAtom[][][] mWorld; + + private CubicleAtom mOffWorld; + + private TransformMatrix4f mTransform; + + private Vector3f mScale; + + private Vector mEntites; + + public CubicleWorld(Vector3i theNumberOfAtoms) { + this(theNumberOfAtoms.x, theNumberOfAtoms.y, theNumberOfAtoms.z); + } + + public CubicleWorld(int theNumberOfXAtoms, + int theNumberOfYAtoms, + int theNumberOfZAtoms) { + initializeAtoms(theNumberOfXAtoms, theNumberOfYAtoms, theNumberOfZAtoms); + mTransform = new TransformMatrix4f(TransformMatrix4f.IDENTITY); + mScale = new Vector3f(1, 1, 1); + mEntites = new Vector(); + } + + private void initializeAtoms(int theNumberOfXAtoms, + int theNumberOfYAtoms, + int theNumberOfZAtoms) { + mWorld = new CubicleAtom[theNumberOfXAtoms][theNumberOfYAtoms][theNumberOfZAtoms]; + for (int x = 0; x < mWorld.length; x++) { + for (int y = 0; y < mWorld[x].length; y++) { + for (int z = 0; z < mWorld[x][y].length; z++) { + mWorld[x][y][z] = new CubicleAtom(x, y, z); + } + } + } + mOffWorld = new CubicleAtom(OFF_WORLD, OFF_WORLD, OFF_WORLD); + } + + public void update() { + Iterator myIterator = mEntites.iterator(); + while (myIterator.hasNext()) { + handleEntity(myIterator.next()); + } + } + + public void add(ICubicleEntity theEntity) { + mEntites.add(theEntity); + theEntity.cubicle().set(OFF_WORLD, OFF_WORLD, OFF_WORLD); + mOffWorld.add(theEntity); + } + + public boolean remove(ICubicleEntity theEntity) { + return removeFromCubicle(theEntity) && mEntites.remove(theEntity); + } + + public void handleEntity(ICubicleEntity theEntity) { + if (theEntity.isActive()) { + + /* transform entity position into cubicle world space */ + + final Vector3i myIndex = worldposition2index(theEntity.position()); + + /* handle entites position in cubicle grid */ + if (checkBounds(myIndex.x, myIndex.y, myIndex.z)) { + if (theEntity.leaving(myIndex.x, myIndex.y, myIndex.z)) { + /* remove from previous cubicles */ + if (!removeFromCubicle(theEntity)) { + System.err.println("### ERROR @ CubicleWorld / removing entity / inworld"); + } + /* add to current cubicle */ + mWorld[myIndex.x][myIndex.y][myIndex.z].add(theEntity); + /* store cubicle */ + theEntity.cubicle().set(myIndex.x, myIndex.y, myIndex.z); + } + } else { + if (theEntity.leaving(OFF_WORLD, OFF_WORLD, OFF_WORLD)) { + /* remove from cubicles */ + if (!removeFromCubicle(theEntity)) { + System.err.println("### ERROR @ CubicleWorld / removing entity / offworld"); + } + /* add to off world */ + mOffWorld.add(theEntity); + + /* store cubicle */ + theEntity.cubicle().set(OFF_WORLD, OFF_WORLD, OFF_WORLD); + } + } + } + } + + public Vector getLocalEntities(Vector3f thePosition) { + final Vector3i myIndex = worldposition2index(thePosition); + if (checkBounds(myIndex.x, myIndex.y, myIndex.z)) { + final CubicleAtom myCubicleAtom = getAtom(myIndex.x, myIndex.y, myIndex.z); + return myCubicleAtom.data(); + } + return null; + } + + public Vector getLocalEntities(ICubicleEntity theEntity) { + final Vector3i myIndex = theEntity.cubicle(); + return getAtom(myIndex.x, myIndex.y, myIndex.z).data(); + } + + public Vector getLocalEntities(Vector3f thePosition, int pExtraRadius) { + return getLocalEntities(thePosition, pExtraRadius, pExtraRadius, pExtraRadius); + } + + public Vector getLocalEntities(Vector3f thePosition, + int theXRadius, + int theYRadius, + int theZRadius) { + final Vector3i myIndex = worldposition2index(thePosition); + if (checkBounds(myIndex.x, myIndex.y, myIndex.z)) { + final Vector mAtoms = getAtoms(myIndex.x, + myIndex.y, + myIndex.z, + theXRadius, + theYRadius, + theZRadius); + final Vector mEntities = new Vector(); + for (CubicleAtom a : mAtoms) { + mEntities.addAll(a.data()); + } + return mEntities.isEmpty() ? null : mEntities; + } else { + return null; + } + } + + public Vector getLocalEntities(ICubicleEntity theEntity, + int theXRadius, + int theYRadius, + int theZRadius) { + final Vector3i myIndex = theEntity.cubicle(); + final Vector mAtoms = getAtoms(myIndex.x, + myIndex.y, + myIndex.z, + theXRadius, + theYRadius, + theZRadius); + final Vector mEntities = new Vector(); + for (CubicleAtom a : mAtoms) { + mEntities.addAll(a.data()); + } + return mEntities.isEmpty() ? null : mEntities; + } + + public Vector entities() { + return mEntites; + } + + public Vector3i worldposition2index(Vector3f thePosition) { + /* get position */ + final Vector3f myPosition = new Vector3f(thePosition); + + /* translation */ + myPosition.sub(mTransform.translation); + + /* rotation */ + mTransform.rotation.transform(myPosition); + + /* scale */ + myPosition.divide(mScale); + + /* round off */ + final Vector3i myIndex = new Vector3i((int) Math.floor(myPosition.x), + (int) Math.floor(myPosition.y), + (int) Math.floor(myPosition.z)); + return myIndex; + } + + private boolean removeFromCubicle(ICubicleEntity theEntity) { + if (theEntity.cubicle().x == OFF_WORLD + && theEntity.cubicle().y == OFF_WORLD + && theEntity.cubicle().z == OFF_WORLD) { + /* was stored in the offworld cubicle */ + return mOffWorld.remove(theEntity); + } else { + if (checkBounds(theEntity.cubicle().x, theEntity.cubicle().y, theEntity.cubicle().z)) { + /* was stored in a cubicle */ + return mWorld[theEntity.cubicle().x][theEntity.cubicle().y][theEntity.cubicle().z].remove(theEntity); + } else { + /* values were invalid */ + System.out.println("### WARNING @ CubicleWorld / couldn t remove entity"); + return false; + } + } + } + + private boolean checkBounds(int theX, + int theY, + int theZ) { + if (theX < mWorld.length && theX >= 0) { + if (theY < mWorld[theX].length && theY >= 0) { + if (theZ < mWorld[theX][theY].length && theZ >= 0) { + return true; + } + } + } + return false; + } + + public CubicleAtom getAtom(int theX, + int theY, + int theZ) { + if (checkBounds(theX, theY, theZ)) { + return mWorld[theX][theY][theZ]; + } else { + return mOffWorld; + } + } + + public Vector getAtoms(int theX, + int theY, + int theZ, + int theXRadius, + int theYRadius, + int theZRadius) { + Vector myAtoms = new Vector(); + for (int z = -theZRadius; z < theZRadius + 1; ++z) { + for (int y = -theYRadius; y < theYRadius + 1; ++y) { + for (int x = -theXRadius; x < theXRadius + 1; ++x) { + int myX = theX + x; + int myY = theY + y; + int myZ = theZ + z; + if (checkBounds(myX, myY, myZ) && mWorld[myX][myY][myZ].size() > 0) { + myAtoms.add(mWorld[myX][myY][myZ]); + } + } + } + } + return myAtoms; + } + + public Vector3f cellscale() { + return mScale; + } + + public TransformMatrix4f transform() { + return mTransform; + } + + public CubicleAtom[][][] getDataRef() { + return mWorld; + } + + public Vector getEntities() { + return mEntites; + } + + public CubicleAtom getOffWorldAtom() { + return mOffWorld; + } + + public void removeAll() { + final Iterator iter = mEntites.iterator(); + while (iter.hasNext()) { + final ICubicleEntity c = iter.next(); + removeFromCubicle(c); + iter.remove(); + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/cubicle/ICubicleEntity.java b/day3/libs/teilchen/src/teilchen/cubicle/ICubicleEntity.java new file mode 100755 index 0000000..dca7855 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/cubicle/ICubicleEntity.java @@ -0,0 +1,60 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.cubicle; + + +import mathematik.Vector3f; +import mathematik.Vector3i; + + +public interface ICubicleEntity { + + /** + * get reference to the cubicle id + * + * @return Vector3i + */ + Vector3i cubicle(); + + /** + * get reference to position vector + * + * @return Vector3f + */ + Vector3f position(); + + /** + * returns true if the new position don t match the previously stored + * position + * + * @return boolean + */ + boolean leaving(int theX, int theY, int theZ); + + /** + * entities can be temporarily removed from the process of being updated by + * the world. + * + * @return + */ + boolean isActive(); +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson00_Particle.java b/day3/libs/teilchen/src/teilchen/demo/Lesson00_Particle.java new file mode 100755 index 0000000..9b177b9 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson00_Particle.java @@ -0,0 +1,98 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.Physics; + + +/** + * this sketch show how to create a particle system with a single particle in + * it. + */ +public class Lesson00_Particle + extends PApplet { + + private Physics mPhysics; + + private Particle mParticle; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system. */ + mPhysics = new Physics(); + + /* + * a physic-based particle system consists of a few components. + * + * 1 particles. + * there are different kinds of particles. for now we use a simple particle. + * + * 2 forces. + * there are all kinds of forces. one of the most obvious force is the gravitational force, + * but there all kinds of different forces like attractors and springs. forces usually + * affect all particles in the system. + * + * 3 behaviors + * a behavior is special kind of force. it is something like an internal force or a motor + * that only affects a single particle. a typical force is for example the 'seek force' + * which constantly pulls a particle into a certain direction. + * + * 4 integrators. + * integrators are used to integrate acceleration and velocity to calculate the new position. + * the most well-known is the 'euler' integrator, but there are also optimized versions like 'runge-kutta' + * or 'Midpoint' or even slightly different concepts like 'verlet'. + * + */ + + /* create a particle. note that the particle is automatically added to particle system */ + mParticle = mPhysics.makeParticle(); + } + + public void draw() { + /* update the particle system to the next step. usually the time step is the duration of the las frame */ + final float mDeltaTime = 1.0f / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particle */ + background(255); + stroke(0, 127); + fill(0, 32); + ellipse(mParticle.position().x, mParticle.position().y, 12, 12); + + /* reset particle s position and velocity */ + if (mousePressed) { + mParticle.position().set(mouseX, mouseY); + mParticle.velocity().set(mouseX - pmouseX, mouseY - pmouseY); + mParticle.velocity().scale(10); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson00_Particle.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson01_Gravity.java b/day3/libs/teilchen/src/teilchen/demo/Lesson01_Gravity.java new file mode 100755 index 0000000..0c07366 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson01_Gravity.java @@ -0,0 +1,83 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Gravity; +import processing.core.PApplet; + + +/** + * this sketch show how to create a particle system with a single particle in + * it. + */ +public class Lesson01_Gravity + extends PApplet { + + private Physics mPhysics; + + private Particle mParticle; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a gravitational force */ + Gravity mGravity = new Gravity(); + /* the direction of the gravity is defined by the 'force' vector */ + mGravity.force().set(0, 30, 0); + /* forces, like gravity or any other force, can be added to the system. they will be automatically applied to all particles */ + mPhysics.add(mGravity); + + /* create a particle and add it to the system */ + mParticle = mPhysics.makeParticle(); + } + + public void draw() { + /* update the particle system. this applies the gravity to the particle */ + final float mDeltaTime = 1.0f / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particle */ + background(255); + stroke(0, 127); + fill(0, 32); + ellipse(mParticle.position().x, mParticle.position().y, 12, 12); + + /* reset particle s position and velocity */ + if (mousePressed) { + mParticle.position().set(mouseX, mouseY); + mParticle.velocity().set(mouseX - pmouseX, mouseY - pmouseY); + mParticle.velocity().scale(10); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson01_Gravity.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson02_Particles.java b/day3/libs/teilchen/src/teilchen/demo/Lesson02_Particles.java new file mode 100755 index 0000000..1473234 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson02_Particles.java @@ -0,0 +1,87 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Gravity; +import processing.core.PApplet; + + +/** + * this sketch shows how to create and handle multiple particles and remove + * individual particles. + */ +public class Lesson02_Particles + extends PApplet { + + private Physics mPhysics; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a gravitational force and add it to the particle system */ + Gravity myGravity = new Gravity(0, 30, 0); + mPhysics.add(myGravity); + } + + public void draw() { + if (mousePressed) { + /* create and add a particle to the system */ + Particle mParticle = mPhysics.makeParticle(); + /* set particle to mouse position with random velocity */ + mParticle.position().set(mouseX, mouseY); + mParticle.velocity().set(random(-20, 20), random(-50)); + } + + /* update the particle system */ + final float mDeltaTime = 1.0f / frameRate; + mPhysics.step(mDeltaTime); + + /* remove particles right before they hit the edge of the screen */ + for (int i = 0; i < mPhysics.particles().size(); i++) { + Particle mParticle = mPhysics.particles(i); + if (mParticle.position().y > height * 0.9f) { + mPhysics.particles().remove(i); + } + } + + /* draw all the particles in the system */ + background(255); + stroke(0, 127); + fill(0, 32); + for (int i = 0; i < mPhysics.particles().size(); i++) { + Particle mParticle = mPhysics.particles(i); + ellipse(mParticle.position().x, mParticle.position().y, 10, 10); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson02_Particles.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson03_Attractors.java b/day3/libs/teilchen/src/teilchen/demo/Lesson03_Attractors.java new file mode 100755 index 0000000..fd612a9 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson03_Attractors.java @@ -0,0 +1,116 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.Teleporter; +import teilchen.force.Attractor; +import teilchen.force.ViscousDrag; + + +/** + * this sketch shows how to create and use attractors. + */ +public class Lesson03_Attractors + extends PApplet { + + private Physics mPhysics; + + private Attractor mAttractor; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a viscous force that slows down all motion */ + ViscousDrag myDrag = new ViscousDrag(); + myDrag.coefficient = 0.75f; + mPhysics.add(myDrag); + + /* teleport particles from one edge of the screen to the other */ + Teleporter mTeleporter = new Teleporter(); + mTeleporter.min().set(0, 0); + mTeleporter.max().set(width, height); + mPhysics.add(mTeleporter); + + /* create some particles */ + for (int i = 0; i < 100; i++) { + Particle myParticle = mPhysics.makeParticle(); + myParticle.position().set(random(width), random(height)); + } + mPhysics.particles().firstElement().fixed(true); + + /* create an attractor */ + mAttractor = new Attractor(); + mAttractor.radius(100); + mAttractor.strength(150); + mPhysics.add(mAttractor); + } + + public void mousePressed() { + /* flip the direction of the attractors strength. */ + float myInvertedStrength = -1 * mAttractor.strength(); + /* a negative strength turns the attractor into a repulsor */ + mAttractor.strength(myInvertedStrength); + } + + public void draw() { + /* set attractor to mouse position */ + mAttractor.position().set(mouseX, mouseY); + + /* update the particle system */ + final float mDeltaTime = 1.0f / frameRate; + mPhysics.step(mDeltaTime); + + /* draw */ + background(255); + + /* draw all the particles in particle system */ + fill(245); + stroke(164); + for (int i = 0; i < mPhysics.particles().size(); i++) { + Particle myParticle = mPhysics.particles(i); + ellipse(myParticle.position().x, myParticle.position().y, 12, 12); + } + + /* draw attractor. green if it is attracting and red if it is repelling */ + noStroke(); + if (mAttractor.strength() < 0) { + fill(255, 0, 0, 50); + } else { + fill(0, 255, 0, 50); + } + ellipse(mAttractor.position().x, mAttractor.position().y, + mAttractor.radius(), mAttractor.radius()); + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson03_Attractors.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson04_Deflectors.java b/day3/libs/teilchen/src/teilchen/demo/Lesson04_Deflectors.java new file mode 100755 index 0000000..bb52e49 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson04_Deflectors.java @@ -0,0 +1,129 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.ShortLivedParticle; +import teilchen.force.Gravity; +import teilchen.force.PlaneDeflector; +import teilchen.force.ViscousDrag; + + +/** + * this sketch shows 1 how to create and use plane deflectors 2 how to use + * 'ShortLivedParticle' + */ +public class Lesson04_Deflectors + extends PApplet { + + private Physics mPhysics; + + private PlaneDeflector mDeflector; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a deflector and add it to the particle system. + * the that defines the deflection area is defined by an + * origin and a normal. this also means that the plane s size + * is infinite. + * note that there is also a triangle delfector that is constraint + * by three points. + */ + mDeflector = new PlaneDeflector(); + /* set plane origin into the center of the screen */ + mDeflector.plane().origin.set(width / 2, height / 2, 0); + mDeflector.plane().normal.set(0, -1, 0); + /* the coefficient of restitution defines how hard particles bounce of the deflector */ + mDeflector.coefficientofrestitution(0.7f); + mPhysics.add(mDeflector); + + /* create gravitiy */ + Gravity myGravity = new Gravity(); + myGravity.force().y = 50; + mPhysics.add(myGravity); + + /* create drag */ + ViscousDrag myViscousDrag = new ViscousDrag(); + myViscousDrag.coefficient = 0.1f; + mPhysics.add(myViscousDrag); + } + + public void draw() { + /* rotate deflector plane */ + if (mousePressed) { + final float myAngle = 2 * PI * (float) mouseX / width - PI; + mDeflector.plane().normal.set(sin(myAngle), -cos(myAngle), 0); + } + + /* create a special particle */ + ShortLivedParticle myNewParticle = new ShortLivedParticle(); + myNewParticle.position().set(mouseX, mouseY); + myNewParticle.velocity().set(0, random(100) + 50); + /* this particle is removed after a specific interval */ + myNewParticle.setMaxAge(4); + /* add particle manually to the particle system */ + mPhysics.add(myNewParticle); + + /* update physics */ + final float mDeltaTime = 1.0f / frameRate; + mPhysics.step(mDeltaTime); + + /* draw all the particles in the particle system */ + background(255); + for (int i = 0; i < mPhysics.particles().size(); i++) { + Particle myParticle = mPhysics.particles(i); + /* this special particle can tell you how much time it has to live. + * we map this information to its transparency. + */ + float myRatio = 1 - ((ShortLivedParticle) myParticle).ageRatio(); + stroke(0, 64 * myRatio); + fill(0, 32 * myRatio); + ellipse(myParticle.position().x, myParticle.position().y, 12, 12); + } + + /* draw deflector */ + stroke(0, 127); + line(mDeflector.plane().origin.x - mDeflector.plane().normal.y * -width, + mDeflector.plane().origin.y + mDeflector.plane().normal.x * -width, + mDeflector.plane().origin.x - mDeflector.plane().normal.y * width, + mDeflector.plane().origin.y + mDeflector.plane().normal.x * width); + + stroke(255, 0, 0, 127); + line(mDeflector.plane().origin.x, + mDeflector.plane().origin.y, + mDeflector.plane().origin.x + mDeflector.plane().normal.x * 20, + mDeflector.plane().origin.y + mDeflector.plane().normal.y * 20); + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson04_Deflectors.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson05_Spring.java b/day3/libs/teilchen/src/teilchen/demo/Lesson05_Spring.java new file mode 100755 index 0000000..530db78 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson05_Spring.java @@ -0,0 +1,95 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; + + +/** + * this sketch shows 1 how to create a viscous drag to slow motion eventually + * down. 2 how to create a spring that connects two particles. + */ +public class Lesson05_Spring + extends PApplet { + + private Physics mPhysics; + + private Spring mSpring; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a viscous force that slows down all motion; 0 means no slowing down. */ + ViscousDrag myDrag = new ViscousDrag(0.25f); + mPhysics.add(myDrag); + + /* create two particles that we can connect with a spring */ + Particle myA = mPhysics.makeParticle(); + myA.position().set(width / 2 - 50, height / 2); + + Particle myB = mPhysics.makeParticle(); + myB.position().set(width / 2 + 50, height / 2); + + /* create a spring force that connects two particles. + * note that there is more than one way to create a spring. + * in our case the restlength of the spring is defined by the + * particles current position. + */ + mSpring = mPhysics.makeSpring(myA, myB); + } + + public void draw() { + /* set first particle to mouse position */ + if (mousePressed) { + mSpring.a().position().set(mouseX, mouseY); + } + + /* update the particle system */ + final float mDeltaTime = 1.0f / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particles and connecting line */ + background(255); + noFill(); + stroke(255, 0, 127, 64); + line(mSpring.a().position().x, mSpring.a().position().y, + mSpring.b().position().x, mSpring.b().position().y); + fill(245); + stroke(164); + ellipse(mSpring.a().position().x, mSpring.a().position().y, 12, 12); + ellipse(mSpring.b().position().x, mSpring.b().position().y, 12, 12); + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson05_Spring.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson06_Springs.java b/day3/libs/teilchen/src/teilchen/demo/Lesson06_Springs.java new file mode 100755 index 0000000..b859e18 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson06_Springs.java @@ -0,0 +1,97 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Spring; +import processing.core.PApplet; + + +/** + * this sketch shows 1 how to create a viscous drag to slow motion eventually + * down. 2 how to create a spring that connects two particles. + */ +public class Lesson06_Springs + extends PApplet { + + private Physics mPhysics; + + private Particle mRoot; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a particle to which we will connect springs */ + mRoot = mPhysics.makeParticle(width / 2, height / 2, 0.0f); + /* we give the root particle a higher mass so it doesn t move as easily */ + mRoot.mass(30); + } + + public void draw() { + /* create a particle at mouse position and connect it to the root particle through a spring */ + if (mousePressed) { + Particle mParticle = mPhysics.makeParticle(mouseX, mouseY, 0); + Spring mSpring = mPhysics.makeSpring(mRoot, mParticle); + /* restlength defines the desired length of the spring. in this case it is the distance between the two particles. */ + float mRestlength = mSpring.restlength(); + /* we modify the restlength to add a bit of energy into the system */ + mSpring.restlength(mRestlength * 1.5f); + } + + /* update the particle system */ + final float mDeltaTime = 1.0f / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particles and connecting line */ + background(255); + + /* draw springs */ + noFill(); + stroke(255, 0, 127, 64); + for (int i = 0; i < mPhysics.forces().size(); i++) { + if (mPhysics.forces().get(i) instanceof Spring) { + Spring mSSpring = (Spring) mPhysics.forces().get(i); + line(mSSpring.a().position().x, mSSpring.a().position().y, + mSSpring.b().position().x, mSSpring.b().position().y); + } + } + /* draw particles */ + fill(245); + stroke(164); + for (int i = 0; i < mPhysics.particles().size(); i++) { + ellipse(mPhysics.particles().get(i).position().x, + mPhysics.particles().get(i).position().y, + 12, 12); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson06_Springs.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson07_StableQuads.java b/day3/libs/teilchen/src/teilchen/demo/Lesson07_StableQuads.java new file mode 100755 index 0000000..94d1819 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson07_StableQuads.java @@ -0,0 +1,111 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import teilchen.Physics; +import teilchen.force.Gravity; +import teilchen.force.ViscousDrag; +import teilchen.util.DrawLib; +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.constraint.Box; +import teilchen.integration.RungeKutta; +import teilchen.util.StableSpringQuad; + + +public class Lesson07_StableQuads + extends PApplet { + + private Physics mPhysics; + + private Particle mRoot; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(60); + + mPhysics = new Physics(); + /* we use 'runge kutta' as it is more stable for this application */ + mPhysics.setInegratorRef(new RungeKutta()); + + Gravity myGravity = new Gravity(); + myGravity.force().y = 98.1f; + mPhysics.add(myGravity); + + /* add drag to smooth the spring interaction */ + mPhysics.add(new ViscousDrag(0.2f)); + + /* add a container */ + Box myBox = new Box(); + myBox.min().set(0, 0, 0); + myBox.max().set(width, height, 0); + mPhysics.add(myBox); + + /* create root */ + Particle a = mPhysics.makeParticle(0, 0); + Particle b = mPhysics.makeParticle(100, 0); + Particle c = mPhysics.makeParticle(100, 100); + Particle d = mPhysics.makeParticle(0, 100); + + new StableSpringQuad(mPhysics, d, c, mPhysics.makeParticle(100, 200), mPhysics.makeParticle(0, 200)); + + /* create stable quad from springs */ + /* first the edge-springs ... */ + final float mySpringConstant = 100; + final float mySpringDamping = 5; + mPhysics.makeSpring(a, b, mySpringConstant, mySpringDamping); + mPhysics.makeSpring(b, c, mySpringConstant, mySpringDamping); + mPhysics.makeSpring(c, d, mySpringConstant, mySpringDamping); + mPhysics.makeSpring(d, a, mySpringConstant, mySpringDamping).restlength(); + /* ... then the diagonal-springs */ + mPhysics.makeSpring(a, c, mySpringConstant, mySpringDamping); + mPhysics.makeSpring(b, d, mySpringConstant, mySpringDamping).restlength(); + + /* define 'a' as root particle for mouse interaction */ + mRoot = a; + mRoot.fixed(true); + } + + public void draw() { + + /* handle particles */ + if (mousePressed) { + mRoot.fixed(true); + mRoot.position().set(mouseX, mouseY); + } else { + mRoot.fixed(false); + } + + mPhysics.step(1f / frameRate); + + /* draw */ + background(255); + DrawLib.drawSprings(g, mPhysics, color(255, 0, 127, 64)); + DrawLib.drawParticles(g, mPhysics, 12, color(164), color(245)); + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson07_StableQuads.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson08_Sticks.java b/day3/libs/teilchen/src/teilchen/demo/Lesson08_Sticks.java new file mode 100755 index 0000000..e2ddd9b --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson08_Sticks.java @@ -0,0 +1,100 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.Stick; +import teilchen.force.Gravity; +import teilchen.integration.Verlet; +import processing.core.PApplet; + + +public class Lesson08_Sticks + extends PApplet { + + private Physics mPhysics; + + private Particle[] mParticles; + + public void setup() { + size(640, 480, OPENGL); + frameRate(60); + smooth(); + + mPhysics = new Physics(); + /* increase the number of iterations for contraints in each step. this can greatly relaxes tensions in the system. */ + mPhysics.contraint_iterations_per_steps = 5; + + /* add gravity for extra fun */ + mPhysics.add(new Gravity()); + + /* we chose verlet integration as it integrates much more nicely with sticks ( and constraints in general ) */ + Verlet myVerlet = new Verlet(); + myVerlet.damping(0.99f); + mPhysics.setInegratorRef(myVerlet); + + /* setup sticks to form a whip */ + mParticles = new Particle[16]; + float mSegmentLength = 20.0f; + /* create root */ + for (int x = 0; x < mParticles.length; x++) { + mParticles[x] = mPhysics.makeParticle(x * mSegmentLength, 0, 0, 0.1f); + if (x > 0) { + Stick myStick = new Stick(mParticles[x - 1], + mParticles[x], + mSegmentLength); + /* damp the stick to release tensions from the system */ + myStick.damping(0.99f); + mPhysics.add(myStick); + } + } + + /* fix root particle so it can stick to the mouse later */ + mParticles[0].fixed(true); + } + + public void draw() { + /* stick root particle to mouse */ + mParticles[0].position().set(mouseX, mouseY); + + /* update */ + mPhysics.step(1.0f / frameRate); + + /* draw sticks with descending stroke weight */ + background(255); + stroke(0, 192); + for (int x = 1; x < mParticles.length; x++) { + Particle p1 = mParticles[x - 1]; + Particle p2 = mParticles[x]; + final float mStrokeWeight = 4.0f * (1.0f - (float) x / mParticles.length); + strokeWeight(mStrokeWeight); + line(p1.position().x, p1.position().y, p1.position().z, + p2.position().x, p2.position().y, p2.position().z); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson08_Sticks.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson09_Cloth.java b/day3/libs/teilchen/src/teilchen/demo/Lesson09_Cloth.java new file mode 100755 index 0000000..279284d --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson09_Cloth.java @@ -0,0 +1,141 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import mathematik.Vector3f; + +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.IConstraint; +import teilchen.constraint.Stick; +import teilchen.force.Attractor; +import teilchen.force.Gravity; +import teilchen.integration.Verlet; + + +public class Lesson09_Cloth + extends PApplet { + + private Physics mPhysics; + + private Particle[][] mParticles; + + private final int GRID_WIDTH = 32; + + private final int GRID_HEIGHT = 16; + + private Attractor mAttractor; + + public void setup() { + size(640, 480, OPENGL); + frameRate(60); + + mPhysics = new Physics(); + mPhysics.contraint_iterations_per_steps = 5; + + Verlet myVerlet = new Verlet(); + myVerlet.damping(0.9f); + mPhysics.setInegratorRef(myVerlet); + mPhysics.add(new Gravity(new Vector3f(0, 1000f, 0))); + + mAttractor = new Attractor(); + mAttractor.strength(-15000); + mAttractor.radius(300); + mPhysics.add(mAttractor); + + mParticles = new Particle[GRID_WIDTH][GRID_HEIGHT]; + + /* setup cloth */ + float mGridStepX = ((float) width / GRID_WIDTH); + float mGridStepY = (((float) height * 0.5f) / GRID_HEIGHT); + for (int y = 0; y < GRID_HEIGHT; y++) { + for (int x = 0; x < GRID_WIDTH; x++) { + mParticles[x][y] = mPhysics.makeParticle(); + mParticles[x][y].position().set((x + 0.5f) * mGridStepX, + y * mGridStepY, + random(0, 1)); + mParticles[x][y].old_position().set(mParticles[x][y].position()); + mParticles[x][y].mass(0.1f); + + final float DAMPING = 0.9f; + if (y > 0) { + Stick myStick = new Stick(mParticles[x][y - 1], + mParticles[x][y], + mGridStepY); + myStick.damping(DAMPING); + mPhysics.add(myStick); + } + if (x > 0) { + Stick myStick = new Stick(mParticles[x - 1][y], + mParticles[x][y], + mGridStepX); + myStick.damping(DAMPING); + mPhysics.add(myStick); + } + if (x > 0 && y > 0) { + Stick myStick1 = new Stick(mParticles[x - 1][y - 1], + mParticles[x][y], + new Vector3f(mGridStepX, mGridStepY).length()); + mPhysics.add(myStick1); + Stick myStick2 = new Stick(mParticles[x][y - 1], + mParticles[x - 1][y], + new Vector3f(mGridStepX, mGridStepY).length()); + mPhysics.add(myStick2); + } + } + } + + /* fix first row */ + for (int x = 0; x < mParticles.length; x++) { + mParticles[x][0].fixed(true); + } + } + + public void draw() { + + /* update */ + mAttractor.position().set(mouseX, mouseY, 50); + mPhysics.step(1.0f / frameRate); + + background(255); + + /* draw sticks */ + stroke(0, 127); + for (final IConstraint myIConstraint : mPhysics.constraints()) { + if (myIConstraint instanceof Stick) { + final Stick myStick = (Stick) myIConstraint; + line(myStick.a().position().x, + myStick.a().position().y, + myStick.a().position().z, + myStick.b().position().x, + myStick.b().position().y, + myStick.b().position().z); + } + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson09_Cloth.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson10_WanderBehavior.java b/day3/libs/teilchen/src/teilchen/demo/Lesson10_WanderBehavior.java new file mode 100755 index 0000000..c71a15a --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson10_WanderBehavior.java @@ -0,0 +1,96 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import processing.core.PApplet; +import teilchen.BehaviorParticle; +import teilchen.Physics; +import teilchen.behavior.Motor; +import teilchen.behavior.Wander; +import teilchen.force.ViscousDrag; + +import static processing.core.PConstants.OPENGL; +import static processing.core.PConstants.RGB; + + +/** + * this sketch shows how to assign an 'wander' behavior to a particle. + */ +public class Lesson10_WanderBehavior + extends PApplet { + + private Physics mPhysics; + + private BehaviorParticle mParticle; + + private Wander mWander; + + private Motor mMotor; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(120); + + /* physics */ + mPhysics = new Physics(); + mPhysics.add(new ViscousDrag()); + + /* create particles */ + mParticle = mPhysics.makeParticle(BehaviorParticle.class); + mParticle.position().set(width / 2, height / 2); + mParticle.maximumInnerForce(100); + mParticle.radius(10); + + /* create behavior */ + mWander = new Wander(); + mParticle.behaviors().add(mWander); + + /* a motor is required to push the particle forward - wander manipulats the direction the particle is pushed in */ + mMotor = new Motor(); + mMotor.auto_update_direction(true); /* the direction the motor pushes into is each step automatically set to the velocity */ + mMotor.strength(25); + mParticle.behaviors().add(mMotor); + } + + public void draw() { + /* update particle system */ + mPhysics.step(1.0f / frameRate); + + /* draw behavior particle */ + background(255); + + fill(1); + stroke(0, 127); + line(mParticle.position().x, + mParticle.position().y, + mParticle.position().x + mParticle.velocity().x, + mParticle.position().y + mParticle.velocity().y); + ellipse(mParticle.position().x, mParticle.position().y, + mParticle.radius() * 2, mParticle.radius() * 2); + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson10_WanderBehavior.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/Lesson11_ArrivalBehavior.java b/day3/libs/teilchen/src/teilchen/demo/Lesson11_ArrivalBehavior.java new file mode 100755 index 0000000..2b89189 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/Lesson11_ArrivalBehavior.java @@ -0,0 +1,103 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import processing.core.PApplet; +import teilchen.BehaviorParticle; +import teilchen.Physics; +import teilchen.behavior.Arrival; + + +/** + * this sketch shows how to assign an 'arrival' behavior to a particle. + */ +public class Lesson11_ArrivalBehavior + extends PApplet { + + private Physics mPhysics; + + private BehaviorParticle mParticle; + + private Arrival mArrival; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(120); + colorMode(RGB, 1.0f); + noFill(); + + /* physics */ + mPhysics = new Physics(); + + /* create particles */ + mParticle = mPhysics.makeParticle(BehaviorParticle.class); + mParticle.maximumInnerForce(100); + + /* create behavior */ + mArrival = new Arrival(); + mArrival.breakforce(mParticle.maximumInnerForce() * 0.25f); + mArrival.breakradius(mParticle.maximumInnerForce() * 0.25f); + mParticle.behaviors().add(mArrival); + } + + public void draw() { + + /* set the arrival position to the mouse position */ + mArrival.position().set(mouseX, mouseY); + + /* update particle system */ + mPhysics.step(1.0f / frameRate); + + /* draw behavior particle */ + background(1); + stroke(0, 0.5f); + if (mArrival.arriving()) { + /* color particle red while it is arriving */ + stroke(1, 0, 0, 0.5f); + } + if (mArrival.arrived()) { + /* color particle green when it has arrived */ + stroke(0, 1, 0, 0.5f); + } + + line(mParticle.position().x, + mParticle.position().y, + mParticle.position().x + mParticle.velocity().x, + mParticle.position().y + mParticle.velocity().y); + fill(1); + ellipse(mParticle.position().x, mParticle.position().y, 12, 12); + + /* draw arrival */ + stroke(0, 0.25f); + noFill(); + ellipse(mArrival.position().x, + mArrival.position().y, + mArrival.breakradius() * 2, + mArrival.breakradius() * 2); + } + + public static void main(String[] args) { + PApplet.main(new String[]{Lesson11_ArrivalBehavior.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/LessonX01_Overlap.java b/day3/libs/teilchen/src/teilchen/demo/LessonX01_Overlap.java new file mode 100755 index 0000000..4406974 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/LessonX01_Overlap.java @@ -0,0 +1,118 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import mathematik.Vector3f; + +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Gravity; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.util.Overlap; +import teilchen.util.Packing; + + +/** + * this sketch is exactly like Lesson06_Springs, except that it also shows how + * to resolveOverlap overlaps. + */ +public class LessonX01_Overlap + extends PApplet { + + private Physics mPhysics; + + private Particle mRoot; + + private static final float PARTICLE_RADIUS = 13; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + + mPhysics = new Physics(); + + /* create drag */ + mPhysics.add(new ViscousDrag()); + mPhysics.add(new Gravity(new Vector3f(0, 100f, 0))); + + + mRoot = mPhysics.makeParticle(width / 2, height / 2, 0.0f); + mRoot.mass(30); + mRoot.fixed(true); + mRoot.radius(PARTICLE_RADIUS); + } + + public void draw() { + if (mousePressed) { + Particle mParticle = mPhysics.makeParticle(mouseX, mouseY, 0); + mPhysics.makeSpring(mRoot, mParticle); + + /* + * we define a radius for the particle so the particle has + * dimensions + */ + mParticle.radius(random(PARTICLE_RADIUS / 2) + PARTICLE_RADIUS); + } + + + /* move overlapping particles away from each other */ + for (int i = 0; i < 10; i++) { + mRoot.position().set(width / 2, height / 2, 0.0f); // a bit of a 'hack' + Overlap.resolveOverlap(mPhysics.particles()); + } + + /* update the particle system */ + final float mDeltaTime = 1.0f / frameRate; + mPhysics.step(mDeltaTime); + + /* draw particles and connecting line */ + background(255); + + /* draw springs */ + noFill(); + stroke(255, 0, 127, 64); + for (int i = 0; i < mPhysics.forces().size(); i++) { + if (mPhysics.forces().get(i) instanceof Spring) { + Spring mSSpring = (Spring) mPhysics.forces().get(i); + line(mSSpring.a().position().x, mSSpring.a().position().y, + mSSpring.b().position().x, mSSpring.b().position().y); + } + } + /* draw particles */ + fill(255, 127); + stroke(164); + for (int i = 0; i < mPhysics.particles().size(); i++) { + ellipse(mPhysics.particles().get(i).position().x, + mPhysics.particles().get(i).position().y, + mPhysics.particles().get(i).radius() * 2, + mPhysics.particles().get(i).radius() * 2); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{LessonX01_Overlap.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/LessonX02_Collisions.java b/day3/libs/teilchen/src/teilchen/demo/LessonX02_Collisions.java new file mode 100755 index 0000000..e1080ab --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/LessonX02_Collisions.java @@ -0,0 +1,121 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import mathematik.Vector3f; +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.Box; +import teilchen.force.Gravity; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.util.CollisionManager; + + +public class LessonX02_Collisions + extends PApplet { + + private static final float PARTICLE_SIZE = 12; + + private CollisionManager mCollision; + + private Physics mPhysics; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(30); + noFill(); + ellipseMode(CENTER); + + mCollision = new CollisionManager(); + mCollision.distancemode(CollisionManager.DISTANCE_MODE_FIXED); + mCollision.minimumDistance(50); + + mPhysics = new Physics(); + mPhysics.add(new ViscousDrag(0.85f)); + mPhysics.add(new Gravity()); + + Box myBox = new Box(); + myBox.min().set(50, 50, 0); + myBox.max().set(width - 50, height - 50, 0); + myBox.coefficientofrestitution(0.7f); + myBox.reflect(true); + mPhysics.add(myBox); + + /* create a first particle */ + final Particle myParticle = mPhysics.makeParticle(new Vector3f(mouseX, mouseY, 0), 10); + mCollision.collision().add(myParticle); + } + + public void draw() { + /* create particles */ + if (mousePressed) { + final Particle myParticle = mPhysics.makeParticle(new Vector3f(mouseX, mouseY, 0), 10); + mCollision.collision().add(myParticle); + } + + /* collision handler */ + final float mDeltaTime = 1.0f / frameRate; + mCollision.createCollisionResolvers(); + mCollision.loop(mDeltaTime); + mPhysics.step(mDeltaTime); + + /* draw */ + background(255); + drawThings(); + + mCollision.removeCollisionResolver(); + } + + private void drawThings() { + /* collision springs */ + noFill(); + stroke(255, 0, 127, 64); + for (int i = 0; i < mCollision.collision().forces().size(); ++i) { + if (mCollision.collision().forces().get(i) instanceof Spring) { + Spring mySpring = (Spring) mCollision.collision_forces().get(i); + line(mySpring.a().position().x, mySpring.a().position().y, mySpring.a().position().z, + mySpring.b().position().x, mySpring.b().position().y, mySpring.b().position().z); + } + } + + /* particles */ + fill(245); + stroke(164); + for (int i = 0; i < mPhysics.particles().size(); ++i) { + Particle myParticle = mPhysics.particles().get(i); + pushMatrix(); + translate(myParticle.position().x, myParticle.position().y, myParticle.position().z); + ellipse(0, 0, + PARTICLE_SIZE, + PARTICLE_SIZE); + popMatrix(); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{LessonX02_Collisions.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/LessonX03_ParticlesLeavingTrails.java b/day3/libs/teilchen/src/teilchen/demo/LessonX03_ParticlesLeavingTrails.java new file mode 100755 index 0000000..fcc5e5d --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/LessonX03_ParticlesLeavingTrails.java @@ -0,0 +1,167 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import mathematik.Vector3f; +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.ShortLivedParticle; +import teilchen.constraint.Box; +import teilchen.force.Attractor; +import teilchen.force.Gravity; +import teilchen.force.ViscousDrag; +import teilchen.util.ParticleTrail; + +import java.util.Vector; + + +public class LessonX03_ParticlesLeavingTrails + extends PApplet { + + private Physics mPhysics; + + private Vector mTrails; + + private Attractor mAttractor; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(60); + + /* create a particle system */ + mPhysics = new Physics(); + + /* create a gravitational force */ + Gravity myGravity = new Gravity(); + mPhysics.add(myGravity); + myGravity.force().y = 20; + + /* create drag */ + ViscousDrag myViscousDrag = new ViscousDrag(); + myViscousDrag.coefficient = 0.1f; + mPhysics.add(myViscousDrag); + + final float mBorder = 40; + Box mBox = new Box(new Vector3f(mBorder, mBorder, mBorder), new Vector3f(width - mBorder, height - mBorder, 100 - mBorder)); + mBox.reflect(true); + mPhysics.add(mBox); + + /* create an attractor */ + mAttractor = new Attractor(); + mAttractor.radius(200); + mAttractor.strength(-300); + mPhysics.add(mAttractor); + + + /* create trails and particles */ + mTrails = new Vector(); + for (int i = 0; i < 500; i++) { + Particle mParticle = mPhysics.makeParticle(); + mParticle.mass(2.0f); + ParticleTrail myParticleTrail = new ParticleTrail(mPhysics, + mParticle, + 0.2f, + random(0.5f, 1)); + myParticleTrail.mass(0.5f); + mTrails.add(myParticleTrail); + } + resetParticles(width / 2, height / 2); + } + + private void resetParticles(float x, float y) { + for (ParticleTrail myTrails : mTrails) { + myTrails.particle().position().set(x + random(-10, 10), y + random(-10, 10), 0); + myTrails.particle().velocity().set(random(-10, 10), random(-10, 10), random(-10, 10)); + myTrails.fragments().clear(); + } + } + + public void draw() { + /* set attractor to mouse position */ + mAttractor.position().set(mouseX, mouseY); + + for (ParticleTrail myTrails : mTrails) { + myTrails.loop(1f / frameRate); + } + + mPhysics.step(1f / frameRate); + + background(255); + for (ParticleTrail myTrail : mTrails) { + drawTrail(myTrail); + } + } + + private void drawTrail(ParticleTrail theTrail) { + + final Vector mFragments = theTrail.fragments(); + final Particle mParticle = theTrail.particle(); + + /* draw head */ + if (mFragments.size() > 1) { + fill(255, 0, 127); + noStroke(); + pushMatrix(); + translate(mParticle.position().x, + mParticle.position().y, + mParticle.position().z); + sphereDetail(4); + sphere(3); + popMatrix(); + } + + /* draw trail */ + for (int i = 0; i < mFragments.size() - 1; i++) { + if (mFragments.get(i) instanceof ShortLivedParticle) { + final float mRatio = 1.0f - ((ShortLivedParticle) mFragments.get(i)).ageRatio(); + stroke(127, mRatio * 255); + strokeWeight(mRatio * 3); + } + int j = (i + 1) % mFragments.size(); + line(mFragments.get(i).position().x, + mFragments.get(i).position().y, + mFragments.get(i).position().z, + mFragments.get(j).position().x, + mFragments.get(j).position().y, + mFragments.get(j).position().z); + } + if (!mFragments.isEmpty()) { + line(mFragments.lastElement().position().x, + mFragments.lastElement().position().y, + mFragments.lastElement().position().z, + mParticle.position().x, + mParticle.position().y, + mParticle.position().z); + } + } + + public void mousePressed() { + resetParticles(mouseX, mouseY); + } + + public static void main(String[] args) { + PApplet.main(new String[]{LessonX03_ParticlesLeavingTrails.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/LessonX04_StickMan.java b/day3/libs/teilchen/src/teilchen/demo/LessonX04_StickMan.java new file mode 100755 index 0000000..935ee0e --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/LessonX04_StickMan.java @@ -0,0 +1,150 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import processing.core.PApplet; +import teilchen.Physics; +import teilchen.force.Attractor; +import teilchen.force.Gravity; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.integration.RungeKutta; +import teilchen.util.Overlap; +import teilchen.util.StickMan; + + +/** + * this demo shows some advanced use of particles, springs and attractors to + * create stickmen. + */ +public class LessonX04_StickMan + extends PApplet { + + private Physics mPhysics; + + private Attractor mAttractor; + + private Gravity mGravity; + + private ViscousDrag mViscousDrag; + + private StickMan[] mMyStickMan; + + public void setup() { + size(640, 480, OPENGL); + smooth(); + frameRate(60); + noFill(); + + mPhysics = new Physics(); + mPhysics.setInegratorRef(new RungeKutta()); + + mGravity = new Gravity(); + mGravity.force().y = 20; + mPhysics.add(mGravity); + + mViscousDrag = new ViscousDrag(); + mViscousDrag.coefficient = 0.85f; + mPhysics.add(mViscousDrag); + + mAttractor = new Attractor(); + mAttractor.radius(500); + mAttractor.strength(0); + mAttractor.position().set(width / 2, height / 2); + mPhysics.add(mAttractor); + + mMyStickMan = new StickMan[20]; + for (int i = 0; i < mMyStickMan.length; i++) { + mMyStickMan[i] = new StickMan(mPhysics, random(0, width), random(0.3f, 0.6f)); + } + } + + public void draw() { + + mPhysics.step(1f / 60f); + Overlap.resolveOverlap(mPhysics.particles()); + + /* constraint particles */ + for (int i = 0; i < mPhysics.particles().size(); i++) { + if (mPhysics.particles(i).position().y > height - 10) { + mPhysics.particles(i).position().y = height - 10; + } + if (mPhysics.particles(i).position().x > width) { + mPhysics.particles(i).position().x = width; + } + if (mPhysics.particles(i).position().x < 0) { + mPhysics.particles(i).position().x = 0; + } + } + + /* handle particles */ + if (mousePressed) { + mAttractor.position().set(mouseX, mouseY); + if (mouseButton == RIGHT) { + mAttractor.strength(-500); + mAttractor.radius(500); + } else { + mAttractor.strength(500); + mAttractor.radius(100); + } + } else { + mAttractor.strength(0); + } + + if (keyPressed) { + mGravity.force().y = -10; + } else { + mGravity.force().y = 20; + } + + /* draw */ + background(255); + + /* draw springs */ + stroke(0, 20); + for (int i = 0; i < mPhysics.forces().size(); i++) { + if (mPhysics.forces(i) instanceof Spring) { + Spring mySpring = (Spring) mPhysics.forces(i); + line(mySpring.a().position().x, + mySpring.a().position().y, + mySpring.b().position().x, + mySpring.b().position().y); + } + } + + /* draw particles */ + for (int i = 0; i < mPhysics.particles().size(); i++) { + ellipse(mPhysics.particles(i).position().x, + mPhysics.particles(i).position().y, 5, 5); + } + + /* draw man */ + for (int i = 0; i < mMyStickMan.length; i++) { + mMyStickMan[i].draw(g); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{LessonX04_StickMan.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/LessonX05_AngleConstraints.java b/day3/libs/teilchen/src/teilchen/demo/LessonX05_AngleConstraints.java new file mode 100755 index 0000000..95971bc --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/LessonX05_AngleConstraints.java @@ -0,0 +1,210 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import processing.core.PApplet; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.AngleConstraintStick; +import teilchen.constraint.Stick; +import teilchen.force.AngleConstraintSpring; +import teilchen.force.Gravity; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.integration.RungeKutta; + + +public class LessonX05_AngleConstraints + extends PApplet { + + private Physics mPhysics; + + private Particle mParticleA; + + private Particle mParticleB; + + private Particle mParticleC; + + private Particle mParticleD; + + private AngleConstraintSpring mAngleConstraintABC; + + private AngleConstraintStick mAngleConstraintBCD; + + public void setup() { + size(640, 480); + frameRate(30); + smooth(); + + mPhysics = new Physics(); + mPhysics.setInegratorRef(new RungeKutta()); + + ViscousDrag myViscousDrag = new ViscousDrag(); + myViscousDrag.coefficient = 1f; + mPhysics.add(myViscousDrag); + + Gravity myGravity = new Gravity(); + myGravity.force().y = 50; + mPhysics.add(myGravity); + + /* particles */ + mParticleA = mPhysics.makeParticle(); + mParticleB = mPhysics.makeParticle(); + mParticleC = mPhysics.makeParticle(); + mParticleD = mPhysics.makeParticle(); + + mParticleA.position().set(width / 2 + 50, height / 3); + mParticleB.position().set(width / 2, height - height / 1.75f); + mParticleC.position().set(width / 2, height - height / 4); + mParticleD.position().set(width / 2, height - height / 8); + + mParticleA.radius(7); + mParticleB.radius(3); + mParticleC.radius(10); + mParticleD.radius(2); + + mParticleB.fixed(true); + + /* springs */ + Spring mSpringAB = new Spring(mParticleA, mParticleB); + mSpringAB.strength(250); + mSpringAB.damping(10); + mPhysics.add(mSpringAB); + + Spring mSpringBC = new Spring(mParticleB, mParticleC); + mSpringBC.strength(250); + mSpringBC.damping(10); + mPhysics.add(mSpringBC); + + Stick mSpringCD = new Stick(mParticleC, mParticleD); + mSpringCD.damping(1); + mPhysics.add(mSpringCD); + + /* angle constraint */ + mAngleConstraintABC = new AngleConstraintSpring(mParticleA, mParticleB, mParticleC); + mAngleConstraintABC.min_angle(PI * 0.5f); + mAngleConstraintABC.damping(1); + mAngleConstraintABC.strength(200); + mPhysics.add(mAngleConstraintABC); + + mAngleConstraintBCD = new AngleConstraintStick(mParticleB, mParticleC, mParticleD); + mAngleConstraintBCD.min_angle(PI * 0.8f); + mAngleConstraintBCD.damping(0.5f); + mPhysics.add(mAngleConstraintBCD); + } + + public void draw() { + /* attach particle to mouse */ + if (mousePressed) { + mParticleA.position().set(mouseX, mouseY); + } + + /* apply constraints */ + mAngleConstraintABC.pre_step(); + mAngleConstraintBCD.pre_step(); + draw_physics(); + + mPhysics.step(1f / frameRate); + + /* remove contraints */ + mAngleConstraintABC.post_step(); + mAngleConstraintBCD.post_step(); + } + + private void draw_physics() { + background(255); + + drawSprings(); + drawSticks(); + drawParticles(); + } + + private void drawSprings() { + for (int i = 0; i < mPhysics.forces().size(); i++) { + if (mPhysics.forces(i) instanceof Spring) { + final Spring mSpring = (Spring) mPhysics.forces(i); + if (mSpring instanceof AngleConstraintSpring) { + strokeWeight(1); + if (mSpring.active()) { + stroke(255, 0, 0, 64); + } else { + stroke(255, 0, 0, 16); + } + } else { + strokeWeight(3); + stroke(0, 128); + } + line(mSpring.a(), mSpring.b()); + } + } + strokeWeight(1); + } + + private void drawSticks() { + for (int i = 0; i < mPhysics.constraints().size(); i++) { + if (mPhysics.constraints(i) instanceof Stick) { + final Stick mStick = (Stick) mPhysics.constraints(i); + if (mStick instanceof AngleConstraintStick) { + strokeWeight(1); + if (mStick.active()) { + stroke(0, 127, 255, 64); + } else { + stroke(0, 127, 255, 16); + } + } else { + strokeWeight(3); + stroke(0, 128); + } + line(mStick.a(), mStick.b()); + } + } + strokeWeight(1); + } + + private void drawParticles() { + stroke(0); + fill(92); + drawParticle(mParticleA); + fill(127); + drawParticle(mParticleB); + fill(192); + drawParticle(mParticleC); + fill(64); + drawParticle(mParticleD); + } + + private void drawParticle(Particle p) { + ellipse(p.position().x, + p.position().y, + p.radius() * 2, p.radius() * 2); + } + + private void line(Particle p1, Particle p2) { + line(p1.position().x, p1.position().y, + p2.position().x, p2.position().y); + } + + public static void main(String[] args) { + PApplet.main(new String[]{LessonX05_AngleConstraints.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/LessonX06_Ducklings.java b/day3/libs/teilchen/src/teilchen/demo/LessonX06_Ducklings.java new file mode 100755 index 0000000..7aa0fc3 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/LessonX06_Ducklings.java @@ -0,0 +1,173 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import processing.core.PApplet; +import teilchen.BehaviorParticle; +import teilchen.Physics; +import teilchen.behavior.Arrival; +import teilchen.force.Spring; +import teilchen.force.ViscousDrag; +import teilchen.util.CollisionManager; + +import java.util.Vector; + + +/** + * this demo shows how to add behaviors to particles. in this example the + * arrival behavior. + */ +public class LessonX06_Ducklings + extends PApplet { + + private Physics mPhysics; + + private Vector mDucklings; + + private CollisionManager mCollision; + + public void setup() { + size(640, 480, OPENGL); + frameRate(60); + smooth(); + colorMode(RGB, 1.0f); + + /* physics */ + mPhysics = new Physics(); + + ViscousDrag myViscousDrag = new ViscousDrag(); + myViscousDrag.coefficient = 0.25f; + mPhysics.add(myViscousDrag); + + mCollision = new CollisionManager(); + mCollision.minimumDistance(25); + + /* ducklings */ + mDucklings = new Vector(); + for (int i = 0; i < 13; i++) { + final Duckling mDuckling = new Duckling(); + if (!mDucklings.isEmpty()) { + mDuckling.arrival.setPositionRef(mDucklings.lastElement().particle.position()); + } + mCollision.collision().add(mDuckling.particle); + mDucklings.add(mDuckling); + } + } + + public void draw() { + final float mDeltaTime = 1.0f / frameRate; + background(1); + + /* update particles */ + mCollision.createCollisionResolvers(); + mCollision.loop(mDeltaTime); + mPhysics.step(mDeltaTime); + + drawCollisionSprings(); + mCollision.removeCollisionResolver(); + + mDucklings.firstElement().arrival.oversteer(!mousePressed); + mDucklings.firstElement().arrival.position().set(mouseX, mouseY); + + /* draw */ + for (Duckling mDuckling : mDucklings) { + drawParticle(mDuckling); + } + + /* draw arrival */ + stroke(0, 0.25f); + noFill(); + ellipse(mDucklings.firstElement().arrival.position().x, + mDucklings.firstElement().arrival.position().y, + 20, 20); + } + + private void drawParticle(Duckling pDuckling) { + final BehaviorParticle mParticle = pDuckling.particle; + final Arrival mArrival = pDuckling.arrival; + + /* draw particle */ + stroke(0, 0.5f); + noFill(); + if (mArrival.arriving()) { + stroke(1, 0, 0, 0.5f); + } + if (mArrival.arrived()) { + stroke(0, 1, 0, 0.5f); + } + ellipse(mParticle.position().x, mParticle.position().y, + mParticle.radius() * 2, mParticle.radius() * 2); + + /* - */ + pushMatrix(); + translate(mParticle.position().x, + mParticle.position().y); + + /* draw velocity */ + stroke(1, 0, 0, 0.5f); + line(0, 0, mParticle.velocity().x, mParticle.velocity().y); + + /* draw break force */ + stroke(0, 0.5f, 1, 0.5f); + line(0, 0, mArrival.force().x, mArrival.force().y); + + /* - */ + popMatrix(); + } + + private void drawCollisionSprings() { + stroke(0, 1, 0, 0.25f); + for (int i = 0; i < mCollision.collision().forces().size(); ++i) { + if (mCollision.collision().forces().get(i) instanceof Spring) { + Spring mySpring = (Spring) mCollision.collision_forces().get(i); + line(mySpring.a().position().x, mySpring.a().position().y, mySpring.a().position().z, + mySpring.b().position().x, mySpring.b().position().y, mySpring.b().position().z); + } + } + } + + class Duckling { + + BehaviorParticle particle; + + Arrival arrival; + + Duckling() { + /* create particles */ + particle = mPhysics.makeParticle(BehaviorParticle.class); + particle.position().set(random(width), random(height)); + particle.maximumInnerForce(random(50, 150)); + particle.radius(random(6, 10)); + + arrival = new Arrival(); + arrival.breakforce(random(12, 28)); + arrival.breakradius(random(45, 55)); + + particle.behaviors().add(arrival); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{LessonX06_Ducklings.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/LessonX07_CubicleWorld.java b/day3/libs/teilchen/src/teilchen/demo/LessonX07_CubicleWorld.java new file mode 100755 index 0000000..41cc56d --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/LessonX07_CubicleWorld.java @@ -0,0 +1,192 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import mathematik.Vector3f; +import mathematik.Vector3i; + +import processing.core.PApplet; +import teilchen.cubicle.CubicleWorld; +import teilchen.cubicle.ICubicleEntity; +import teilchen.util.CubicleWorldView; +import teilchen.util.DrawLib; + +import java.util.Vector; + + +public class LessonX07_CubicleWorld + extends PApplet { + + private final int WORLD_NUMBER_OF_CUBICLES = 15; + + private final float WORLD_CUBICLE_SCALE = 20; + + private final float WORLD_SCALE = WORLD_NUMBER_OF_CUBICLES * WORLD_CUBICLE_SCALE; + + private boolean showCubicles = true; + + private float mRotationZ = 0.1f; + + private Vector3f mPosition = new Vector3f(); + + private CubicleWorld mCubicleWorld; + + private CubicleWorldView mCubicleWorldView; + + public void setup() { + size(640, 480, OPENGL); + textFont(createFont("Courier", 11)); + hint(DISABLE_DEPTH_SORT); + hint(DISABLE_DEPTH_TEST); + + /* setup world */ + mCubicleWorld = new CubicleWorld(WORLD_NUMBER_OF_CUBICLES, WORLD_NUMBER_OF_CUBICLES, WORLD_NUMBER_OF_CUBICLES); + mCubicleWorld.cellscale().set(WORLD_CUBICLE_SCALE, WORLD_CUBICLE_SCALE, WORLD_CUBICLE_SCALE); + mCubicleWorld.transform().translation.set(-WORLD_SCALE / 2, -WORLD_SCALE / 2, -WORLD_SCALE / 2); + + mCubicleWorldView = new CubicleWorldView(mCubicleWorld); + mCubicleWorldView.color_empty = color(0, 1); + mCubicleWorldView.color_full = color(0, 4); + + mCubicleWorld.add(new MCubicleEntity()); + } + + public void draw() { + /* handle entities */ + if (frameRate > 30) { + addRandomEntities(2); + } + + mCubicleWorld.update(); + Vector mEntities = mCubicleWorld.getLocalEntities(mPosition, 1); + + /* draw things */ + background(255); + + pushMatrix(); + translate(width / 2, height / 2, 0); + + /* rotate */ + if (mousePressed) { + mRotationZ += (mouseX * 0.01f - mRotationZ) * 0.05f; + } else { + mPosition.x = mouseX - width / 2; + mPosition.y = mouseY - height / 2; + } + rotateX(THIRD_PI); + rotateZ(mRotationZ); + + /* draw cubicle world */ + if (showCubicles) { + stroke(0, 127); + noFill(); + mCubicleWorldView.draw(g); + } + + /* draw entities */ + int mNumberOfPointsSelected = 0; + stroke(0, 127, 255, 127); + noFill(); + if (mEntities != null) { + mNumberOfPointsSelected = mEntities.size(); + for (ICubicleEntity mEntity : mEntities) { + MCubicleEntity m = (MCubicleEntity) mEntity; + stroke(m.color); + DrawLib.cross3(g, mEntity.position(), 5.0f); + } + } + + /* draw crosshair */ + stroke(255, 0, 0, 63); + noFill(); + beginShape(LINES); + vertex(mPosition.x, -WORLD_SCALE / 2, 0); + vertex(mPosition.x, WORLD_SCALE / 2, 0); + vertex(-WORLD_SCALE / 2, mPosition.y, 0); + vertex(WORLD_SCALE / 2, mPosition.y, 0); + endShape(); + + /* draw selection sphere */ + stroke(255, 0, 0, 63); + noFill(); + translate(mPosition.x, mPosition.y, 0); + box(WORLD_CUBICLE_SCALE); + popMatrix(); + + fill(0); + noStroke(); + text("POINTS : " + mCubicleWorld.entities().size(), 10, 12); + text("SELECTED : " + mNumberOfPointsSelected, 10, 24); + text("FPS : " + frameRate, 10, 36); + } + + private void addRandomEntities(int pNumberParticles) { + for (int i = 0; i < pNumberParticles; i++) { + MCubicleEntity mEntity = new MCubicleEntity(); + mEntity.position().x = random(-WORLD_SCALE / 2, WORLD_SCALE / 2); + mEntity.position().y = random(-WORLD_SCALE / 2, WORLD_SCALE / 2); + mEntity.position().z = random(-WORLD_SCALE / 2, WORLD_SCALE / 2); + mCubicleWorld.add(mEntity); + } + } + + class MCubicleEntity + implements ICubicleEntity { + + int color = color(0, 127, random(0, 255), 127); + + private Vector3i mCubiclePosition; + + private final Vector3f mPosition; + + public MCubicleEntity() { + mCubiclePosition = new Vector3i(); + mPosition = new Vector3f(); + } + + public Vector3i cubicle() { + return mCubiclePosition; + } + + public Vector3f position() { + return mPosition; + } + + public boolean leaving(int theX, int theY, int theZ) { + if (theX == cubicle().x + && theY == cubicle().y + && theZ == cubicle().z) { + return false; + } + return true; + } + + public boolean isActive() { + return true; + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{LessonX07_CubicleWorld.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/demo/LessonX08_Schwarm.java b/day3/libs/teilchen/src/teilchen/demo/LessonX08_Schwarm.java new file mode 100755 index 0000000..41ca7c7 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/demo/LessonX08_Schwarm.java @@ -0,0 +1,174 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.demo; + + +import mathematik.Vector3f; +import processing.core.PApplet; +import processing.core.PGraphics; +import processing.core.PMatrix3D; +import teilchen.BehaviorParticle; +import teilchen.Physics; +import teilchen.behavior.Alignment; +import teilchen.behavior.Cohesion; +import teilchen.behavior.Motor; +import teilchen.behavior.Separation; +import teilchen.behavior.Wander; +import teilchen.constraint.Teleporter; +import teilchen.force.ViscousDrag; +import teilchen.util.Util; + +import java.util.Vector; + + +public class LessonX08_Schwarm + extends PApplet { + + private Physics mPhysics; + + private Vector mSwarmEntities; + + public void setup() { + size(640, 480, OPENGL); + frameRate(60); + smooth(); + rectMode(CENTER); + hint(DISABLE_DEPTH_TEST); + + /* physics */ + mPhysics = new Physics(); + + Teleporter mTeleporter = new Teleporter(); + mTeleporter.min().set(0, 0, height / -2); + mTeleporter.max().set(width, height, height / 2); + mPhysics.add(mTeleporter); + + ViscousDrag myViscousDrag = new ViscousDrag(); + mPhysics.add(myViscousDrag); + + /* setup entities */ + mSwarmEntities = new Vector(); + for (int i = 0; i < 60; i++) { + SwarmEntity mSwarmEntity = new SwarmEntity(); + mSwarmEntity.position().set(random(mTeleporter.min().x, mTeleporter.max().x), + random(mTeleporter.min().y, mTeleporter.max().y), + random(mTeleporter.min().z, mTeleporter.max().z)); + mSwarmEntities.add(mSwarmEntity); + mPhysics.add(mSwarmEntity); + } + } + + public void draw() { + final float mDeltaTime = 1.0f / frameRate; + + /* physics */ + mPhysics.step(mDeltaTime); + + /* entities */ + for (SwarmEntity s : mSwarmEntities) { + s.update(mDeltaTime); + } + + /* draw */ + background(255); + for (SwarmEntity s : mSwarmEntities) { + s.draw(g); + } + } + + private class SwarmEntity + extends BehaviorParticle { + + private Separation separation; + + private Alignment alignment; + + private Cohesion cohesion; + + private Wander wander; + + private Motor motor; + + public SwarmEntity() { + maximumInnerForce(random(100.0f, 1000.0f)); + radius(10f); + + separation = new Separation(); + separation.proximity(20); + separation.weight(50.0f); + behaviors().add(separation); + + alignment = new Alignment(); + alignment.proximity(30); + alignment.weight(30.0f); + behaviors().add(alignment); + + cohesion = new Cohesion(); + cohesion.proximity(100); + cohesion.weight(5.0f); + behaviors().add(cohesion); + + wander = new Wander(); + behaviors().add(wander); + + motor = new Motor(); + motor.auto_update_direction(true); + motor.strength(20.0f); + behaviors().add(motor); + } + + public void update(float theDeltaTime) { + separation.neighbors(mSwarmEntities); + alignment.neighbors(mSwarmEntities); + cohesion.neighbors(mSwarmEntities); + } + + private void draw(PGraphics g) { + pushMatrix(); + + translate(position().x, position().y, position().z); + + pushMatrix(); + + PMatrix3D p = new PMatrix3D(); + Util.pointAt(p, position(), new Vector3f(0, 1, 0), mathematik.Util.add(position(), velocity())); + applyMatrix(p); + + noStroke(); + fill(0); + scale(1, 0.25f, 3); + box(6); + + popMatrix(); + + /* velocity */ + stroke(0, 31); + line(0, 0, 0, velocity().x, velocity().y, velocity().z); + + popMatrix(); + } + } + + public static void main(String[] args) { + PApplet.main(new String[]{LessonX08_Schwarm.class.getName()}); + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/AngleConstraintSpring.java b/day3/libs/teilchen/src/teilchen/force/AngleConstraintSpring.java new file mode 100755 index 0000000..276f601 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/AngleConstraintSpring.java @@ -0,0 +1,101 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import mathematik.Vector3f; + +import teilchen.Particle; + + +public class AngleConstraintSpring + extends Spring { + + private final Particle mParticleA; + + private final Particle mParticleB; + + private final Particle mParticleC; + + private float mMinAngle; + + /** + * + * particles are connected like this: A -- B -- C + * + * @param pParticleA + * @param pParticleB + * @param pParticleC + */ + public AngleConstraintSpring(Particle pParticleA, Particle pParticleB, Particle pParticleC) { + super(pParticleA, pParticleC); + mParticleA = pParticleA; + mParticleB = pParticleB; + mParticleC = pParticleC; + mMinAngle = Float.MAX_VALUE; + } + + public void min_angle(float pAngle) { + mMinAngle = pAngle; + } + + public void pre_step() { + Vector3f ab = mathematik.Util.sub(mParticleA.position(), mParticleB.position()); + Vector3f cb = mathematik.Util.sub(mParticleC.position(), mParticleB.position()); + final float mCurrentAngle = ab.angle(cb); + + if (mCurrentAngle < mMinAngle) { + final int TINY_FACTOR_MODELL = 0; + final int TRIG_MODELL = 1; + final int MAX_DISTANCE_MODELL = 2; + + final int mModell = TRIG_MODELL; + + switch (mModell) { + case TINY_FACTOR_MODELL: { + final float TINY_FACTOR = 1.1f; + final float mDistance = mParticleA.position().distance(mParticleC.position()) * TINY_FACTOR; + restlength(mDistance); + } + break; + case TRIG_MODELL: { + // a = sqrt ( b*b + c*c - 2bc*cosA ) + final float b = ab.length(); + final float c = cb.length(); + final float mDistance = (float) Math.sqrt(b * b + c * c - 2 * b * c * (float) Math.cos(mMinAngle)); + restlength(mDistance); + } + break; + case MAX_DISTANCE_MODELL: { + final float mDistance = mParticleA.position().distance(mParticleB.position()) + mParticleC.position().distance(mParticleB.position()); + restlength(mDistance); + } + break; + } + active(true); + } + } + + public void post_step() { + active(false); + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/Attractor.java b/day3/libs/teilchen/src/teilchen/force/Attractor.java new file mode 100755 index 0000000..36d10e4 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/Attractor.java @@ -0,0 +1,114 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; + + +public class Attractor + implements IForce { + + protected Vector3f _myPosition; + + protected float _myStrength; + + protected float _myRadius; + + protected final Vector3f myTemp = new Vector3f(); + + private boolean _myActive; + + public Attractor() { + _myPosition = new Vector3f(); + _myRadius = 100; + _myStrength = 1; + _myActive = true; + } + + public Vector3f position() { + return _myPosition; + } + + public void setPositionRef(Vector3f thePosition) { + _myPosition = thePosition; + } + + public float strength() { + return _myStrength; + } + + public void strength(float theStrength) { + _myStrength = theStrength; + } + + public float radius() { + return _myRadius; + } + + public void radius(float theRadius) { + _myRadius = theRadius; + } + + public void apply(float theDeltaTime, Physics theParticleSystem) { + if (_myStrength != 0) { + for (final Particle myParticle : theParticleSystem.particles()) { + /* each particle */ + if (!myParticle.fixed()) { + myTemp.sub(_myPosition, myParticle.position()); + final float myDistance = fastInverseSqrt(1 / myTemp.lengthSquared()); + if (myDistance < _myRadius) { + float myFallOff = 1f - myDistance / _myRadius; + final float myForce = myFallOff * myFallOff * _myStrength; + myTemp.scale(myForce / myDistance); + if (!myParticle.fixed()) { + myParticle.force().add(myTemp); + } + } + } + } + } + } + + protected static float fastInverseSqrt(float v) { + final float half = 0.5f * v; + int i = Float.floatToIntBits(v); + i = 0x5f375a86 - (i >> 1); + v = Float.intBitsToFloat(i); + return v * (1.5f - half * v * v); + } + + public boolean dead() { + return false; + } + + public boolean active() { + return _myActive; + } + + public void active(boolean theActiveState) { + _myActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/DirectedAttractor.java b/day3/libs/teilchen/src/teilchen/force/DirectedAttractor.java new file mode 100755 index 0000000..ef4fad9 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/DirectedAttractor.java @@ -0,0 +1,63 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; + + +public class DirectedAttractor + extends Attractor { + + private final Vector3f myVectorA = new Vector3f(); + + private final Vector3f myVectorB = new Vector3f(); + + public DirectedAttractor() { + super(); + } + + public void apply(float theDeltaTime, Physics theParticleSystem) { + for (final Particle myParticle : theParticleSystem.particles()) { + /* each particle */ + if (!myParticle.fixed()) { + myTemp.sub(_myPosition, myParticle.position()); + + final float myDistance = fastInverseSqrt(1 / myTemp.lengthSquared()); + if (myDistance < _myRadius) { + + myVectorA.scale(1 / myDistance, myTemp); + myVectorB.normalize(myParticle.velocity()); + float myAngle = myVectorA.dot(myVectorB); + + float myFallOff = 1f - myDistance / _myRadius; + final float myForce = myAngle * myFallOff * myFallOff * _myStrength; + myTemp.scale(myForce / myDistance); + myParticle.force().add(myTemp); + } + } + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/Gravity.java b/day3/libs/teilchen/src/teilchen/force/Gravity.java new file mode 100755 index 0000000..d71a1d7 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/Gravity.java @@ -0,0 +1,74 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; + + +public class Gravity + implements IForce { + + private boolean _myActive; + + private Vector3f _myForce; + + public Gravity(final Vector3f theForce) { + _myActive = true; + _myForce = theForce; + } + + public Gravity() { + this(new Vector3f(0, 9.81f, 0)); + } + + public Gravity(float theX, float theY, float theZ) { + this(new Vector3f(theX, theY, theZ)); + } + + public Vector3f force() { + return _myForce; + } + + public void apply(final float theDeltaTime, final Physics theParticleSystem) { + for (final Particle myParticle : theParticleSystem.particles()) { + if (!myParticle.fixed()) { + myParticle.force().add(_myForce); + } + } + } + + public boolean dead() { + return false; + } + + public boolean active() { + return _myActive; + } + + public void active(boolean theActiveState) { + _myActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/IForce.java b/day3/libs/teilchen/src/teilchen/force/IForce.java new file mode 100755 index 0000000..b32c2e0 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/IForce.java @@ -0,0 +1,37 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import teilchen.Physics; + + +public interface IForce { + + void apply(final float theDeltaTime, final Physics theParticleSystem); + + boolean dead(); + + boolean active(); + + void active(boolean theActiveState); +} diff --git a/day3/libs/teilchen/src/teilchen/force/MuscleSpring.java b/day3/libs/teilchen/src/teilchen/force/MuscleSpring.java new file mode 100755 index 0000000..37b09ac --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/MuscleSpring.java @@ -0,0 +1,114 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import teilchen.Particle; +import teilchen.Physics; + + +public class MuscleSpring + extends Spring { + + private float mAmplitude = 1; + + private float mOffset = 0; + + private float mFrequency = 1; + + private float mInitialRestLength; + + private float mCurrentTime; + + private boolean mAutomaticContraction = true; + + public MuscleSpring(Particle theA, Particle theB) { + super(theA, theB); + mInitialRestLength = mRestLength; + } + + public MuscleSpring(final Particle theA, + final Particle theB, + final float theSpringConstant, + final float theSpringDamping, + final float theRestLength) { + super(theA, + theB, + theSpringConstant, + theSpringDamping, + theRestLength); + mInitialRestLength = mRestLength; + } + + public void setRestLengthByPosition() { + mInitialRestLength = mA.position().distance(mB.position()); + } + + public float restlength() { + return mInitialRestLength; + } + + public void restlength(float theRestLength) { + mInitialRestLength = theRestLength; + } + + public void frequency(final float theFrequency) { + mFrequency = theFrequency; + } + + public float frequency() { + return mFrequency; + } + + public void amplitude(final float theAmplitude) { + mAmplitude = theAmplitude; + } + + public float amplitude() { + return mAmplitude; + } + + /** + * set the offset of the contraction in radians. + * + * @param theOffset float + */ + public void offset(final float theOffset) { + mOffset = theOffset; + } + + public float offset() { + return mOffset; + } + + public void apply(final float theDeltaTime, final Physics theParticleSystem) { + + if (mAutomaticContraction) { + mCurrentTime += theDeltaTime; + + final float myOffset = (float) Math.sin(mCurrentTime * mFrequency + mOffset) * mAmplitude; + mRestLength = mInitialRestLength + myOffset; + } + + super.apply(theDeltaTime, theParticleSystem); + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/PlaneDeflector.java b/day3/libs/teilchen/src/teilchen/force/PlaneDeflector.java new file mode 100755 index 0000000..413404a --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/PlaneDeflector.java @@ -0,0 +1,160 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import mathematik.Plane3f; +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; + + +public class PlaneDeflector + implements IForce { + + private final Plane3f mPlane; + + private float mCoefficientOfRestitution; + + private final Vector3f _myTempDiff; + + private final Vector3f mTempReflectionVector; + + private final Vector3f mTempNormalComponent; + + private final Vector3f mTempTangentComponent; + + private boolean _myActive; + + public PlaneDeflector() { + mPlane = new Plane3f(); + mPlane.normal = new Vector3f(0, 1, 0); + mCoefficientOfRestitution = 1.0f; + + _myTempDiff = new Vector3f(); + mTempReflectionVector = new Vector3f(); + mTempNormalComponent = new Vector3f(); + mTempTangentComponent = new Vector3f(); + _myActive = true; + } + + public void apply(final float theDeltaTime, final Physics theParticleSystem) { + for (final Particle myParticle : theParticleSystem.particles()) { + if (!myParticle.fixed()) { + /* test if particle passed plane */ + if (testParticlePosition(myParticle, mPlane) < 0) { + + /* find intersection with plane */ + Vector3f myResult = new Vector3f(); + /** + * using the normal of the plane instead of the velocity of + * the particle. though less correct it seems to be more + * stable. + */ + final float myIntersectionResult = intersectLinePlane(myParticle.position(), + mPlane.normal, + mPlane, + myResult); + + /* remove particle from collision */ + if (myIntersectionResult != Float.NEGATIVE_INFINITY + && !myResult.isNaN()) { + myParticle.position().set(myResult); + } + + /* change direction */ + seperateComponents(myParticle, mPlane); + myParticle.velocity().set(mTempReflectionVector); + } + } + } + } + + public Plane3f plane() { + return mPlane; + } + + public void coefficientofrestitution(float theCoefficientOfRestitution) { + mCoefficientOfRestitution = theCoefficientOfRestitution; + } + + public float coefficientofrestitution() { + return mCoefficientOfRestitution; + } + + private final float testParticlePosition(Particle theParticle, Plane3f thePlane) { + _myTempDiff.sub(theParticle.position(), thePlane.origin); + _myTempDiff.normalize(); + final float myAngle = _myTempDiff.dot(thePlane.normal); + return myAngle; + } + + private final void seperateComponents(Particle theParticle, Plane3f thePlane) { + /* normal */ + mTempNormalComponent.set(thePlane.normal); + mTempNormalComponent.scale(thePlane.normal.dot(theParticle.velocity())); + /* tangent */ + mTempTangentComponent.sub(theParticle.velocity(), mTempNormalComponent); + /* negate normal */ + mTempNormalComponent.scale(-mCoefficientOfRestitution); + /* set reflection vector */ + mTempReflectionVector.add(mTempTangentComponent, mTempNormalComponent); + } + + private final float intersectLinePlane(final Vector3f theRayOrigin, + final Vector3f theRayDirection, + final Plane3f thePlane, + final Vector3f theIntersectionPoint) { + float myT; + final float myDenominator = thePlane.normal.dot(theRayDirection); + + if (myDenominator == 0) { + System.err.println("### ERROR @ Intersection / NEGATIVE_INFINITY"); + return Float.NEGATIVE_INFINITY; + } + + final float numer = thePlane.normal.dot(theRayOrigin); + final float D = -thePlane.origin.dot(thePlane.normal); + myT = -((numer + D) / myDenominator); + + if (theIntersectionPoint != null) { + theIntersectionPoint.set(theRayDirection); + theIntersectionPoint.scale((float) myT); + theIntersectionPoint.add(theRayOrigin); + } + + return myT; + } + + public boolean dead() { + return false; + } + + public boolean active() { + return _myActive; + } + + public void active(boolean theActiveState) { + _myActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/Spring.java b/day3/libs/teilchen/src/teilchen/force/Spring.java new file mode 100755 index 0000000..6d48a34 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/Spring.java @@ -0,0 +1,211 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import teilchen.IConnection; +import teilchen.Particle; +import teilchen.Physics; + + +public class Spring + implements IForce, + IConnection { + + protected float mSpringConstant; + + protected float mSpringDamping; + + protected float mRestLength; + + protected Particle mA; + + protected Particle mB; + + protected boolean mOneWay; + + protected boolean mActive; + + public Spring(Particle theA, Particle theB) { + this(theA, + theB, + 2.0f, 0.1f, + theA.position().distance(theB.position())); + } + + public Spring(Particle theA, Particle theB, float theRestLength) { + this(theA, + theB, + 2.0f, 0.1f, + theRestLength); + } + + public Spring(Particle theA, + Particle theB, + final float theSpringConstant, + final float theSpringDamping) { + this(theA, + theB, + theSpringConstant, + theSpringDamping, + theA.position().distance(theB.position())); + } + + public Spring(final Particle theA, + final Particle theB, + final float theSpringConstant, + final float theSpringDamping, + final float theRestLength) { + mSpringConstant = theSpringConstant; + mSpringDamping = theSpringDamping; + mRestLength = theRestLength; + mA = theA; + mB = theB; + mOneWay = false; + mActive = true; + } + + public void setRestLengthByPosition() { + mRestLength = mA.position().distance(mB.position()); + } + + public float restlength() { + return mRestLength; + } + + public void restlength(float theRestLength) { + mRestLength = theRestLength; + } + + public final Particle a() { + return mA; + } + + public final Particle b() { + return mB; + } + + public final Particle a(Particle theA) { + return mA = theA; + } + + public final Particle b(Particle theB) { + return mB = theB; + } + + public final float currentLength() { + return mA.position().distance(mB.position()); + } + + /** + * spring constant. + * + * @return float + */ + public final float strength() { + return mSpringConstant; + } + + /** + * spring constant. + * + * @param theSpringConstant float + */ + public final void strength(float theSpringConstant) { + mSpringConstant = theSpringConstant; + } + + public final float damping() { + return mSpringDamping; + } + + public final void damping(float theSpringDamping) { + mSpringDamping = theSpringDamping; + } + + public void setOneWay(boolean theOneWayState) { + mOneWay = theOneWayState; + } + + public void apply(final float theDeltaTime, final Physics theParticleSystem) { +// if (!mA.fixed() || !mB.fixed()) { + float a2bX = mA.position().x - mB.position().x; + float a2bY = mA.position().y - mB.position().y; + float a2bZ = mA.position().z - mB.position().z; + final float myInversDistance = fastInverseSqrt(a2bX * a2bX + a2bY * a2bY + a2bZ * a2bZ); + final float myDistance = 1.0F / myInversDistance; + + if (myDistance == 0.0F) { + a2bX = 0.0F; + a2bY = 0.0F; + a2bZ = 0.0F; + } else { + a2bX *= myInversDistance; + a2bY *= myInversDistance; + a2bZ *= myInversDistance; + } + + final float mSpringForce = -(myDistance - mRestLength) * mSpringConstant; + final float Va2bX = mA.velocity().x - mB.velocity().x; + final float Va2bY = mA.velocity().y - mB.velocity().y; + final float Va2bZ = mA.velocity().z - mB.velocity().z; + final float mDampingForce = -mSpringDamping * (a2bX * Va2bX + a2bY * Va2bY + a2bZ * Va2bZ); + final float r = mSpringForce + mDampingForce; + a2bX *= r; + a2bY *= r; + a2bZ *= r; + + if (mOneWay) { + if (!mB.fixed()) { + mB.force().add(-2 * a2bX, -2 * a2bY, -2 * a2bZ); + } + } else { + if (!mA.fixed()) { + mA.force().add(a2bX, a2bY, a2bZ); + } + if (!mB.fixed()) { + mB.force().add(-a2bX, -a2bY, -a2bZ); + } + } +// } + } + + protected static float fastInverseSqrt(float v) { + final float half = 0.5f * v; + int i = Float.floatToIntBits(v); + i = 0x5f375a86 - (i >> 1); + v = Float.intBitsToFloat(i); + return v * (1.5f - half * v * v); + } + + public boolean dead() { + return mA.dead() || mB.dead(); + } + + public boolean active() { + return mActive; + } + + public void active(boolean theActiveState) { + mActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/TearableSpring.java b/day3/libs/teilchen/src/teilchen/force/TearableSpring.java new file mode 100755 index 0000000..33c190a --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/TearableSpring.java @@ -0,0 +1,82 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import teilchen.Particle; +import teilchen.Physics; + + +public class TearableSpring + extends Spring { + + private boolean _myTornApart = false; + + private float _myTearDistance = -1; + + public TearableSpring(Particle theA, Particle theB) { + super(theA, + theB, + 2.0f, 0.1f, + theA.position().distance(theB.position())); + } + + public TearableSpring(final Particle theA, + final Particle theB, + final float theSpringConstant, + final float theSpringDamping, + final float theRestLength, + final float theTearDistance) { + super(theA, + theB, + theSpringConstant, + theSpringDamping, + theRestLength); + _myTearDistance = theTearDistance; + } + + public final float teardistance() { + return _myTearDistance; + } + + public final void teardistance(float theTearDistance) { + _myTearDistance = theTearDistance; + } + + public void apply(final float theDeltaTime, final Physics theParticleSystem) { + /* check if spring will tear */ + if (_myTearDistance > 0) { + final float myActualDistance = a().position().distance(b().position()); + if (myActualDistance > restlength() + _myTearDistance) { + _myTornApart = true; + } + } + /* apply force if spring is ok */ + if (!_myTornApart) { + super.apply(theDeltaTime, theParticleSystem); + } + } + + public boolean dead() { + return _myTornApart || super.dead(); + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/TriangleDeflector.java b/day3/libs/teilchen/src/teilchen/force/TriangleDeflector.java new file mode 100755 index 0000000..eea9271 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/TriangleDeflector.java @@ -0,0 +1,230 @@ +package teilchen.force; + +import mathematik.Intersection; +import mathematik.Intersection.IntersectionResult; +import mathematik.Vector3f; +import mathematik.WorldAxisAlignedBoundingBox; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.IConstraint; + +public class TriangleDeflector + implements IConstraint { + + private final Vector3f a; + + private final Vector3f b; + + private final Vector3f c; + + private final Vector3f mNormal; + + private float mCoefficientOfRestitution; + + private final Vector3f mTempReflectionVector; + + private final Vector3f mTempNormalComponent; + + private final Vector3f mTempTangentComponent; + + private final IntersectionResult mIntersectionResult; + + private final Vector3f mTempPointOfIntersection = new Vector3f(); + + private final WorldAxisAlignedBoundingBox mWorldAxisAlignedBoundingBox; + + private final Vector3f[] mVectorCollection; + + public boolean AUTO_UPDATE = true; + + private boolean mGotHit = false; + + private boolean mActive; + + public TriangleDeflector() { + a = new Vector3f(); + b = new Vector3f(); + c = new Vector3f(); + + /* hmmm. */ + mVectorCollection = new Vector3f[3]; + mVectorCollection[0] = a; + mVectorCollection[1] = b; + mVectorCollection[2] = c; + + mNormal = new Vector3f(); + mCoefficientOfRestitution = 1.0f; + + mTempReflectionVector = new Vector3f(); + mTempNormalComponent = new Vector3f(); + mTempTangentComponent = new Vector3f(); + mIntersectionResult = new IntersectionResult(); + mWorldAxisAlignedBoundingBox = new WorldAxisAlignedBoundingBox(); + + mActive = true; + } + + public Vector3f a() { + return a; + } + + public Vector3f b() { + return b; + } + + public Vector3f c() { + return c; + } + + public WorldAxisAlignedBoundingBox boundingbox() { + return mWorldAxisAlignedBoundingBox; + } + + public void updateProperties() { + mVectorCollection[0] = a; + mVectorCollection[1] = b; + mVectorCollection[2] = c; + mathematik.Util.calculateNormal(a, b, c, mNormal); + mathematik.Util.updateBoundingBox(mWorldAxisAlignedBoundingBox, mVectorCollection); + } + + private float mPreviousT = -1.0f; + + public void apply(Physics pParticleSystem) { +// public void apply(final float pDeltaTime, final Physics pParticleSystem) { + + /* update triangle properties -- maybe this is better not done automatically */ + if (AUTO_UPDATE) { + updateProperties(); + } + + mGotHit = false; + for (final Particle myParticle : pParticleSystem.particles()) { + if (!myParticle.fixed()) { + final boolean IGNORE_BOUNDING_BOX = true; + + /* adjust boundingbox width to particle velocity to avoid particle shooting through the boundingbox */ + final Vector3f myTempBoundingBoxScale = new Vector3f(mWorldAxisAlignedBoundingBox.scale); + if (!IGNORE_BOUNDING_BOX) { + if (myParticle.velocity().x > mWorldAxisAlignedBoundingBox.scale.x) { + mWorldAxisAlignedBoundingBox.scale.x = myParticle.velocity().x; + } + if (myParticle.velocity().y > mWorldAxisAlignedBoundingBox.scale.y) { + mWorldAxisAlignedBoundingBox.scale.y = myParticle.velocity().y; + } + if (myParticle.velocity().z > mWorldAxisAlignedBoundingBox.scale.z) { + mWorldAxisAlignedBoundingBox.scale.z = myParticle.velocity().z; + } + } + + /* only test if in bounding box */ + if (IGNORE_BOUNDING_BOX || mathematik.Util.contains(myParticle.position(), mWorldAxisAlignedBoundingBox)) { + final Vector3f mRay; + final int RAY_FROM_VELOCITY = 0; + final int RAY_FROM_NORMAL = 1; + final int RAY_FROM_OLD_POSITION = 2; + final int CREATE_RAY_FROM = RAY_FROM_OLD_POSITION; + + switch (CREATE_RAY_FROM) { + case RAY_FROM_VELOCITY: + mRay = myParticle.velocity(); + break; + case RAY_FROM_NORMAL: + mRay = mathematik.Util.scale(mNormal, -myParticle.velocity().length()); + break; + case RAY_FROM_OLD_POSITION: + mRay = mathematik.Util.sub(myParticle.position(), myParticle.old_position()); + break; + default: + mRay = new Vector3f(1, 0, 0); + break; + } + + if (mRay.isNaN()) { + break; + } + if (mRay.lengthSquared() == 0) { + break; + } + final boolean mSuccess = Intersection.intersectRayTriangle(myParticle.position(), + mRay, + a, b, c, + mIntersectionResult, + true); + /* is particle past plane. */ + if (mSuccess && mIntersectionResult.t <= 0 && mPreviousT > 0) { + mTempPointOfIntersection.set(mRay); + mTempPointOfIntersection.scale(mIntersectionResult.t); + mTempPointOfIntersection.add(myParticle.position()); + myParticle.position().set(mTempPointOfIntersection); + + /* reflect velocity i.e. change direction */ + seperateComponents(myParticle, mNormal); + myParticle.velocity().set(mTempReflectionVector); + + mGotHit = true; + myParticle.tag(true); + markParticle(myParticle); +// mPreviousT = 0.0f; /* ??? */ + + } + if (mSuccess) { + mPreviousT = mIntersectionResult.t; + } else { + mPreviousT = 0.0f; + } + + } + + /* reset boundingbox scale */ + if (!IGNORE_BOUNDING_BOX) { + mWorldAxisAlignedBoundingBox.scale.set(myTempBoundingBoxScale); + } + } + } + } + + protected void markParticle(Particle pParticle) { + } + + public boolean hit() { + return mGotHit; + } + + public void coefficientofrestitution(float pCoefficientOfRestitution) { + mCoefficientOfRestitution = pCoefficientOfRestitution; + } + + public float coefficientofrestitution() { + return mCoefficientOfRestitution; + } + + private void seperateComponents(Particle pParticle, Vector3f pNormal) { + /* normal */ + mTempNormalComponent.set(pNormal); + mTempNormalComponent.scale(pNormal.dot(pParticle.velocity())); + /* tangent */ + mTempTangentComponent.sub(pParticle.velocity(), mTempNormalComponent); + /* negate normal */ + mTempNormalComponent.scale(-mCoefficientOfRestitution); + /* set reflection vector */ + mTempReflectionVector.add(mTempTangentComponent, mTempNormalComponent); + } + + public Vector3f normal() { + return mNormal; + } + + public boolean dead() { + return false; + } + + public boolean active() { + return mActive; + } + + public void active(boolean pActiveState) { + mActive = pActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/TriangleDeflectorIndexed.java b/day3/libs/teilchen/src/teilchen/force/TriangleDeflectorIndexed.java new file mode 100755 index 0000000..6c546bb --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/TriangleDeflectorIndexed.java @@ -0,0 +1,40 @@ +package teilchen.force; + + +public class TriangleDeflectorIndexed + extends TriangleDeflector { + + private final int a_index; + + private final int b_index; + + private final int c_index; + + private final float[] _myVertices; + + public TriangleDeflectorIndexed(float[] theVertices, int theA, int theB, int theC) { + super(); + _myVertices = theVertices; + a_index = theA; + b_index = theB; + c_index = theC; + updateProperties(); + } + + public void updateProperties() { + updateVertices(); + super.updateProperties(); + } + + private void updateVertices() { + a().set(_myVertices[a_index + 0], + _myVertices[a_index + 1], + _myVertices[a_index + 2]); + b().set(_myVertices[b_index + 0], + _myVertices[b_index + 1], + _myVertices[b_index + 2]); + c().set(_myVertices[c_index + 0], + _myVertices[c_index + 1], + _myVertices[c_index + 2]); + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/ViscousDrag.java b/day3/libs/teilchen/src/teilchen/force/ViscousDrag.java new file mode 100755 index 0000000..a7877d1 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/ViscousDrag.java @@ -0,0 +1,72 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force; + + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.integration.Verlet; + + +public class ViscousDrag + implements IForce { + + public float coefficient; + + private boolean _myActive; + + public ViscousDrag(float theCoefficient) { + coefficient = theCoefficient; + _myActive = true; + } + + public ViscousDrag() { + this(1.0f); + } + + public final void apply(final float theDeltaTime, final Physics theParticleSystem) { + if (theParticleSystem.getIntegrator() instanceof Verlet) { + return; + } + if (coefficient != 0) { + for (final Particle myParticle : theParticleSystem.particles()) { + if (!myParticle.fixed()) { + myParticle.force().add(myParticle.velocity().x * -coefficient, + myParticle.velocity().y * -coefficient, + myParticle.velocity().z * -coefficient); + } + } + } + } + + public boolean dead() { + return false; + } + + public boolean active() { + return _myActive; + } + + public void active(boolean theActiveState) { + _myActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/flowfield/FlowField.java b/day3/libs/teilchen/src/teilchen/force/flowfield/FlowField.java new file mode 100755 index 0000000..d84e899 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/flowfield/FlowField.java @@ -0,0 +1,503 @@ +package teilchen.force.flowfield; + + +import java.util.Vector; +import mathematik.TransformMatrix4f; +import mathematik.Vector3f; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.IForce; + + +/* + * todo: + * make density switchable + * clean redundancies + */ +public class FlowField implements IForce { + + public int n = 100; // The size of the calculation grid + + private int _myGridSize = n + 2; // Extra grid space for boundary + + private int _myPixelSize = 10; // The size of each grid square on the screen + + // I unravelled the 1D arrays from Jos Stam's paper back to 2D arrays, as we don't have compile time macros in Java... + private float[][] u = new float[_myGridSize][_myGridSize]; + + private float[][] v = new float[_myGridSize][_myGridSize]; + + private float[][] uPrev = new float[_myGridSize][_myGridSize]; + + private float[][] vPrev = new float[_myGridSize][_myGridSize]; + + private float[][] dens = new float[_myGridSize][_myGridSize]; + + private float[][] densPrev = new float[_myGridSize][_myGridSize]; + + private float viscosity = 0.0001f; // Viscosity of fluid + + public float deltatime = 0.2f; // Rate of change + + private float diff = 0.0001f; // Degree of diffusion of density over time + + private int densityBrushSize = n / 10; // Size of the density area applied with the mouse + + public int velocityBrushSize = n / 20; // Ditto velocity + + private int lineSpacing = n / n; // Spacing between velocity and normal lines + + public boolean showHair = true; + + public boolean showVelocity = true; + + public boolean calculateDensity = true; + + public boolean calculateVelocity = true; + + private Vector3f _myScale; + + private TransformMatrix4f _myTransform; + + private Vector _myForces; + + public float forceScale = 1; + + public FlowField() { + n = 100; + init(); + } + + public FlowField(int theResolutionX, int theResolutionY, Vector3f theScale) { + n = theResolutionX; + init(); + _myScale.set(theScale); + } + + private void init() { + _myScale = new Vector3f(); + _myTransform = new TransformMatrix4f(); + _myForces = new Vector(); + _myGridSize = n + 2; + u = new float[_myGridSize][_myGridSize]; + v = new float[_myGridSize][_myGridSize]; + uPrev = new float[_myGridSize][_myGridSize]; + vPrev = new float[_myGridSize][_myGridSize]; + dens = new float[_myGridSize][_myGridSize]; + densPrev = new float[_myGridSize][_myGridSize]; + } + + public void reset() { + initVelocity(); + initDensity(); + } + + public void addForce(FlowFieldForce theForce) { + _myForces.add(theForce); + } + + private void updateForces() { + for (FlowFieldForce myForce : _myForces) { + myForce.applyForce(this); + } + } + + public Vector forces() { + return _myForces; + } + + public void setForce() { + initField(densPrev); + initField(uPrev); + initField(vPrev); + } + + public float[][] u() { + return u; + } + + public float[][] v() { + return v; + } + +//float[][] field, int x, int y, float s, float r + public void setForceArea(float[][] field, int x, int y, float s, float r) { + for (int i = (int) (clamp(x - r, 1, n)); i <= (int) (clamp(x + r, 1, n)); i++) { + int dx = x - i; + for (int j = (int) (clamp(y - r, 1, n)); j <= (int) (clamp(y + r, 1, n)); j++) { + int dy = y - j; + float f = 1 - ((float) Math.sqrt(dx * dx + dy * dy) / r); + field[i][j] += clamp(f, 0, 1) * s; + } + } + } + + public void setForce(float theX, float theY, Vector3f theStrength, float theRadius) { + int x = (int) (theX / _myScale.x * n); + int y = (int) (theY / _myScale.y * n); + for (int i = (int) (clamp(x - theRadius, 1, n)); i <= (int) (clamp(x + theRadius, 1, n)); i++) { + int dx = x - i; + for (int j = (int) (clamp(y - theRadius, 1, n)); j <= (int) (clamp(y + theRadius, 1, n)); j++) { + int dy = y - j; + float f = 1 - ((float) Math.sqrt(dx * dx + dy * dy) / theRadius); + u[i][j] += clamp(f, 0, 1) * theStrength.x; + v[i][j] += clamp(f, 0, 1) * theStrength.y; + } + } + } + +//public void calculateVelocity(float[][] u, float[][] v, float[][] u0, float[][] v0, float visc, float dt + public void calculateVelocity() { + + addSource(u, uPrev, deltatime); + addSource(v, vPrev, deltatime); + + float[][] tmp; + tmp = u; + u = uPrev; + uPrev = tmp; + tmp = v; + v = vPrev; + vPrev = tmp; + + diffuse(1, u, uPrev, viscosity, deltatime); + diffuse(2, v, vPrev, viscosity, deltatime); + + project(u, v, uPrev, vPrev); + + tmp = u; + u = uPrev; + uPrev = tmp; + tmp = v; + v = vPrev; + vPrev = tmp; + + advect(1, u, uPrev, uPrev, vPrev, deltatime); + advect(2, v, vPrev, uPrev, vPrev, deltatime); + + project(u, v, uPrev, vPrev); + } + +// public void calculateDensity(float[][] x, float[][] x0, float[][] u, float[][] v, float diff, float dt) { + public void calculateDensity() { + float[][] tmp; + + addSource(dens, densPrev, deltatime); + tmp = dens; + dens = densPrev; + densPrev = tmp; + diffuse(0, dens, densPrev, diff, deltatime); + tmp = dens; + dens = densPrev; + densPrev = tmp; + advect(0, dens, densPrev, u, v, deltatime); + } + + public void loop(final float theDeltaTime) { + updateForces(); + setForce(); + deltatime = theDeltaTime; + + if (calculateVelocity) { + calculateVelocity(); + } + if (calculateDensity) { + calculateDensity(); + } + } + +// public void draw(GLContext theRenderContext) { +// GL gl = ( theRenderContext).gl; +// float vu; +// float vv; +// +// gl.glPushMatrix(); +// JoglUtil.applyTransform(gl, +// _myTransformMode, +// transform, +// rotation, +// scale); +// +// material.begin(theRenderContext); +// +// for (int y = 1; y <= n; y++) { +// for (int x = 1; x <= n; x++) { +// if (showHair) { +// if ((x % lineSpacing) == 0 && (y % lineSpacing) == 0) { +// +// float myRatioX = x / (float) n; +// float myRatioY = y / (float) n; +// vu = u[x][y]; +// vv = v[x][y]; +// Vector2f myDirection = new Vector2f(vu, vv); +// float VIEW_VECTOR_LENGTH = myDirection.length(); +// float myAlpha = material.color.a * VIEW_VECTOR_LENGTH; +// gl.glLineWidth(10); +// +// float myTargetLength = VIEW_VECTOR_LENGTH; +// +// gl.glBegin(GL.GL_LINES); +// gl.glColor4f(material.color.r, material.color.g, material.color.b, 0); +// gl.glVertex3f(myRatioX, +// myRatioY, +// 0); +// +// myTargetLength = VIEW_VECTOR_LENGTH * 0.05f; +// gl.glColor4f(material.color.r, material.color.g, material.color.b, myAlpha); +// gl.glVertex3f(myRatioX + vu * myTargetLength, +// myRatioY + vv * myTargetLength, +// 0); +// gl.glEnd(); +// +// gl.glBegin(GL.GL_LINES); +// gl.glColor4f(material.color.r, material.color.g, material.color.b, myAlpha); +// gl.glVertex3f(myRatioX + vu * myTargetLength, +// myRatioY + vv * myTargetLength, +// 0); +// +// myTargetLength = VIEW_VECTOR_LENGTH * 0.6f; +// gl.glColor4f(material.color.r, material.color.g, material.color.b, 0); +// gl.glVertex3f(myRatioX + vu * myTargetLength, +// myRatioY + vv * myTargetLength, +// 0); +// gl.glEnd(); +// } +// } +// if (showVelocity) { +// if ((x % lineSpacing) == 0 && (y % lineSpacing) == 0) { +// +// float myRatioX = x / (float) n; +// float myRatioY = y / (float) n; +// vu = u[x][y]; +// vv = v[x][y]; +// Vector2f myDirection = new Vector2f(vu, vv); +// myDirection.normalize(); +// myDirection.scale(3); +// +// gl.glBegin(GL.GL_LINES); +// gl.glVertex3f(myRatioX, +// myRatioY, +// 0); +// gl.glVertex3f(myRatioX + vu, +// myRatioY + vv, +// 0); +// gl.glEnd(); +// } +// } +// } +// } +// gl.glPopMatrix(); +// material.end(theRenderContext); +// } + public Vector3f scale() { + return _myScale; + } + + public TransformMatrix4f transform() { + return _myTransform; + } + + public Vector3f position() { + return _myTransform.translation; + } + + private float clamp(float f, float minf, float maxf) { + return Math.max(Math.min(f, maxf), minf); + } + + private void initField(float[][] f) { + for (int i = 0; i < _myGridSize; i++) { + for (int j = 0; j < _myGridSize; j++) { + f[i][j] = 0.0f; + } + } + } + + private void initVelocity() { + initField(u); + initField(v); + initField(uPrev); + initField(vPrev); + } + + private void initDensity() { + initField(dens); + initField(densPrev); + } + + public Vector3f getForce(Vector3f thePosition) { + Vector3f myDeltaPos = new Vector3f(thePosition); + myDeltaPos.sub(position()); + float myRatioX = myDeltaPos.x / _myScale.x; + float myRatioY = myDeltaPos.y / _myScale.y; + if (myRatioX >= 0 && myRatioX <= 1 && myRatioY >= 0 && myRatioY <= 1) { + int myIndexX = (int) (myRatioX * (u.length - 1)); + int myIndexY = (int) (myRatioY * (v.length - 1)); + if (u[myIndexX] == null || v[myIndexY] == null) { + System.out.println(myIndexX + " " + myIndexY); + } + Vector3f myForce = new Vector3f(u()[myIndexX][myIndexY], v()[myIndexX][myIndexY], 0); + return myForce; + } + return new Vector3f(); + } + + private void addSource(float[][] x, float[][] s, float dt) { + for (int i = 0; i < _myGridSize; i++) { + for (int j = 0; j < _myGridSize; j++) { + x[i][j] += s[i][j] * dt; + } + } + } + + private void setBnd(int b, float[][] x) { +// for (int i = 1; i <= n; i++) { +// if (b == 1) { +// x[0][i] = -x[1][i]; +// } else { +// x[0][i] = x[1][i]; +// } +// if (b == 1) { +// x[n + 1][i] = -x[n][i]; +// } else { +// x[n + 1][i] = x[n][i]; +// } +// if (b == 2) { +// x[i][0] = -x[i][1]; +// } else { +// x[i][0] = x[i][1]; +// } +// if (b == 2) { +// x[i][n + 1] = -x[i][n]; +// } else { +// x[i][n + 1] = x[i][n]; +// } +// +// } +// x[0][0] = 0.5f * (x[1][0] + x[0][1]); +// x[0][n + 1] = 0.5f * (x[1][n + 1] + x[0][n]); +// x[n + 1][0] = 0.5f * (x[n][0] + x[n + 1][1]); +// x[n + 1][n + 1] = 0.5f * (x[n][n + 1] + x[n + 1][n]); + } + + private void diffuse(int b, float[][] x, float[][] x0, float diff, float dt) { + + int i, j, k; + float a = dt * diff * n * n; + + /* todo: why is it '20' */ +// for (k = 0; k < 20; k++) { + for (i = 1; i <= n; i++) { + for (j = 1; j <= n; j++) { + x[i][j] = (x0[i][j] + a * (x[i - 1][j] + x[i + 1][j] + x[i][j - 1] + x[i][j + 1])) / (1 + 4 * a); + } + } + setBnd(b, x); +// } + } + + private void project(float[][] u, float[][] v, float[][] p, float[][] div) { + int i; + int j; + int k; + float h; + + h = 1.0f / n; + /* todo check loop */ + for (i = 1; i <= n; i++) { + for (j = 1; j <= n; j++) { + div[i][j] = -0.5f * h * (u[i + 1][j] - u[i - 1][j] + v[i][j + 1] - v[i][j - 1]); + p[i][j] = 0; + } + } + setBnd(0, div); + setBnd(0, p); + + /* todo: why is it '20' */ + for (k = 0; k < 20; k++) { + for (i = 1; i <= n; i++) { + for (j = 1; j <= n; j++) { + p[i][j] = (div[i][j] + p[i - 1][j] + p[i + 1][j] + p[i][j - 1] + p[i][j + 1]) / 4; + } + } + setBnd(0, p); + } + + /* todo check loop */ + for (i = 1; i <= n; i++) { + for (j = 1; j <= n; j++) { + u[i][j] -= 0.5f * (p[i + 1][j] - p[i - 1][j]) / h; + v[i][j] -= 0.5f * (p[i][j + 1] - p[i][j - 1]) / h; + } + } + setBnd(1, u); + setBnd(2, v); + } + + private void advect(int b, float[][] d, float[][] d0, float[][] u, float[][] v, float dt) { + int i; + int j; + int i0; + int j0; + int i1; + int j1; + float x; + float y; + float s0; + float t0; + float s1; + float t1; + float dt0; + + dt0 = dt * n; + /* todo check loop */ + for (i = 1; i <= n; i++) { + for (j = 1; j <= n; j++) { + x = i - dt0 * u[i][j]; + y = j - dt0 * v[i][j]; + + x = Math.max(0.5f, x); + x = Math.min(n + 0.5f, x); + + i0 = (int) Math.floor(x); + i1 = i0 + 1; + + y = Math.max(0.5f, y); + y = Math.min(n + 0.5f, y); + + j0 = (int) Math.floor(y); + j1 = j0 + 1; + + s1 = x - i0; + s0 = 1 - s1; + t1 = y - j0; + t0 = 1 - t1; + + d[i][j] = s0 * (t0 * d0[i0][j0] + t1 * d0[i0][j1]) + + s1 * (t0 * d0[i1][j0] + t1 * d0[i1][j1]); + } + } + setBnd(b, d); + } + + public void apply(float theDeltaTime, Physics theParticleSystem) { + for (Particle myParticle : theParticleSystem.particles()) { + if (!myParticle.fixed()) { + Vector3f myForce = getForce(myParticle.position()); + myForce.scale(forceScale); + myParticle.force().add(myForce); + } + } + } + + public boolean dead() { + return false; + } + + public boolean active() { + return true; + } + + public void active(boolean theActiveState) { + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/flowfield/FlowFieldForce.java b/day3/libs/teilchen/src/teilchen/force/flowfield/FlowFieldForce.java new file mode 100755 index 0000000..314fff3 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/flowfield/FlowFieldForce.java @@ -0,0 +1,37 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force.flowfield; + + +import mathematik.Vector3f; + + +public abstract class FlowFieldForce { + + public Vector3f strength = new Vector3f(); + + public float range; + + public Vector3f position = new Vector3f(); + + public abstract void applyForce(FlowField theField); +} diff --git a/day3/libs/teilchen/src/teilchen/force/flowfield/FlowFieldForceMOUSE.java b/day3/libs/teilchen/src/teilchen/force/flowfield/FlowFieldForceMOUSE.java new file mode 100755 index 0000000..0f65833 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/flowfield/FlowFieldForceMOUSE.java @@ -0,0 +1,46 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force.flowfield; + + +import mathematik.Vector3f; + + +public class FlowFieldForceMOUSE extends FlowFieldForce { + + private Vector3f _myOldPosition; + + public FlowFieldForceMOUSE() { + _myOldPosition = new Vector3f(); + } + + public void setPosition(Vector3f thePosition) { + position.set(thePosition); + strength.set(thePosition); + strength.sub(_myOldPosition); + _myOldPosition.set(position); + } + + public void applyForce(FlowField theField) { + theField.setForce(position.x, position.y, strength, range); + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorField.java b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorField.java new file mode 100755 index 0000000..a5015b1 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorField.java @@ -0,0 +1,212 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force.vectorfield; + + +import mathematik.Vector3f; +import mathematik.Vector3i; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.VectorfieldParticle; +import teilchen.force.IForce; + + +public class VectorField + implements IForce { + + private VectorFieldUnit[][][] _myField; + + public float strength; + + private Vector3f _myPosition; + + private Vector3f _myScale; + + private boolean _myActive; + + public VectorField(VectorFieldGenerator theGenerator) { + /* init fields */ + strength = 1; + _myPosition = new Vector3f(); + _myScale = new Vector3f(1f, 1f, 1f); + _myField = theGenerator.data(); + _myActive = true; + } + + public VectorFieldUnit[][][] data() { + return _myField; + } + + public Vector3f getPosition() { + return _myPosition; + } + + public void setPosition(final Vector3f thePosition) { + _myPosition.set(thePosition); + for (int x = 0; x < _myField.length; x++) { + for (int y = 0; y < _myField[x].length; y++) { + for (int z = 0; z < _myField[x][y].length; z++) { + Vector3f myPosition = new Vector3f(x + * (_myScale.x / (float) _myField.length), + y * (_myScale.y / (float) _myField[x].length), + z * (_myScale.z / (float) _myField[x][y].length)); + _myField[x][y][z].getPosition().set(myPosition); + _myField[x][y][z].getPosition().add(thePosition); + } + } + } + } + + public final Vector3f getScale() { + return _myScale; + } + + public void setScale(final Vector3f theScale) { + _myScale.set(theScale); + for (int x = 0; x < _myField.length; x++) { + for (int y = 0; y < _myField[x].length; y++) { + for (int z = 0; z < _myField[x][y].length; z++) { + Vector3f myUnitScale = new Vector3f(_myScale.x + / (float) _myField.length, + _myScale.y / (float) _myField[x].length, + _myScale.z / (float) _myField[x][y].length); + _myField[x][y][z].setScale(myUnitScale); + Vector3f myPosition = new Vector3f(x + * (_myScale.x / (float) _myField.length), + y * (_myScale.y / (float) _myField[x].length), + z * (_myScale.z / (float) _myField[x][y].length)); + myPosition.add(_myPosition); + _myField[x][y][z].setPosition(myPosition); + } + } + } + } + +// public void setScale(final Vector3f theScale) { +// _myScale.set(theScale); +// for (int x = 0; x < _myField.length; x++) { +// for (int y = 0; y < _myField[x].length; y++) { +// for (int z = 0; z < _myField[x][y].length; z++) { +// Vector3f myUnitScale = new Vector3f(_myScale.x, +// _myScale.y, +// _myScale.z); +// _myField[x][y][z].setScale(myUnitScale); +// Vector3f myPosition = new Vector3f(x * +// (_myScale.x), +// y * (_myScale.y), +// z * (_myScale.z)); +// myPosition.add(_myPosition); +// _myField[x][y][z].setPosition(myPosition); +// } +// } +// } +//} + /* IForce */ + private Vector3f force(float theDeltaTime, VectorfieldParticle theParticle) { + if (isInBoundingBox(theParticle)) { + Vector3i myUnit = checkIfIsInside(theParticle, 1); + if (myUnit != null) { + Vector3f myAcceleration = new Vector3f(_myField[myUnit.x][ + myUnit.y][ + myUnit.z]. + getAcceleration()); + myAcceleration.scale(strength); + theParticle.setLastUnit(myUnit); + return myAcceleration; + } + for (int x = 0; x < _myField.length; x++) { + for (int y = 0; y < _myField[x].length; y++) { + for (int z = 0; z < _myField[x][y].length; z++) { + if (_myField[x][y][z].isInside(theParticle.position())) { + Vector3f myAcceleration = new Vector3f(_myField[x][ + y][z]. + getAcceleration()); + myAcceleration.scale(strength); + theParticle.setLastUnit(new Vector3i(x, y, z)); + return myAcceleration; + } + } + } + } + } + return new Vector3f(); + } + + private boolean isInBoundingBox(VectorfieldParticle theParticle) { + if (theParticle.position().x >= _myPosition.x + && theParticle.position().x <= _myPosition.x + _myScale.x + && theParticle.position().y >= _myPosition.y + && theParticle.position().y <= _myPosition.y + _myScale.y + && theParticle.position().z >= _myPosition.z + && theParticle.position().z <= _myPosition.z + _myScale.z) { + return true; + } + return false; + } + + private Vector3i checkIfIsInside(VectorfieldParticle theParticle, + int theRadius) { + Vector3i myUnit = new Vector3i(theParticle.getLastUnit()); + for (int x = myUnit.x - theRadius; x < myUnit.x + theRadius; x++) { + for (int y = myUnit.y - theRadius; y < myUnit.y + theRadius; y++) { + for (int z = myUnit.z - theRadius; z < myUnit.z + theRadius; z++) { + if (x >= 0 && x < _myField.length + && y >= 0 && y < _myField[x].length + && z >= 0 && z < _myField[x][y].length) { + if (_myField[x][y][z].isInside(theParticle.position())) { + return new Vector3i(x, y, z); + } + } + } + } + } + return null; + } + + public void apply(final float theDeltaTime, + final Physics theParticleSystem) { + /** + * @todo clean up force method + */ + for (final Particle myParticle : theParticleSystem.particles()) { + if (!myParticle.fixed()) { + if (myParticle instanceof VectorfieldParticle) { + myParticle.force().add(force(theDeltaTime, + (VectorfieldParticle) myParticle)); + } + } + } + } + + public boolean dead() { + return false; + } + + public boolean active() { + return _myActive; + } + + public void active(boolean theActiveState) { + _myActive = theActiveState; + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldGenerator.java b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldGenerator.java new file mode 100755 index 0000000..a8345af --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldGenerator.java @@ -0,0 +1,28 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force.vectorfield; + + +public interface VectorFieldGenerator { + + VectorFieldUnit[][][] data(); +} diff --git a/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldGeneratorAVERAGEUNITS.java b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldGeneratorAVERAGEUNITS.java new file mode 100755 index 0000000..59eff58 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldGeneratorAVERAGEUNITS.java @@ -0,0 +1,87 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force.vectorfield; + + +import mathematik.Vector3f; + + +public class VectorFieldGeneratorAVERAGEUNITS + implements VectorFieldGenerator { + + private VectorFieldUnit[][][] _myField; + + public VectorFieldGeneratorAVERAGEUNITS(int theSizeX, + int theSizeY, + int theSizeZ, + Vector3f[] theCoordinats, + Vector3f[] theAccelerations) { + /* populate field */ + _myField = new VectorFieldUnit[theSizeX][theSizeY][theSizeZ]; + for (int x = 0; x < theSizeX; x++) { + for (int y = 0; y < theSizeY; y++) { + for (int z = 0; z < theSizeZ; z++) { + Vector3f myPosition = new Vector3f(x + * (1f / (float) theSizeX), + y * (1f / (float) theSizeY), + z * (1f / (float) theSizeZ)); + Vector3f myScale = new Vector3f(1f + / (float) theSizeX, + 1f / (float) theSizeY, + 1f / (float) theSizeZ); + Vector3f myAcceleration = new Vector3f(1f, 1f, 1f); + VectorFieldUnit myUnit = new VectorFieldUnit(myPosition, + myScale, + myAcceleration); + _myField[x][y][z] = myUnit; + } + } + } + + float myMaxDistance = (float) Math.sqrt(2); + for (int x = 0; x < theSizeX; x++) { + for (int y = 0; y < theSizeY; y++) { + for (int z = 0; z < theSizeZ; z++) { + Vector3f myAcceleration = new Vector3f(); + VectorFieldUnit myUnit = _myField[x][y][z]; + for (int i = 0; i < theCoordinats.length; i++) { + Vector3f myDistance = new Vector3f(); + VectorFieldUnit myOtherUnit = _myField[ (int) theCoordinats[i].x][ (int) theCoordinats[i].y][ (int) theCoordinats[i].z]; + myDistance.set(myOtherUnit.getPosition()); + myDistance.sub(myUnit.getPosition()); + float myRatio = myMaxDistance - myDistance.length(); + Vector3f myTempAcceleration = new Vector3f(); + myTempAcceleration.set(theAccelerations[i]); + myTempAcceleration.scale(myRatio); + myAcceleration.add(myTempAcceleration); + } + myAcceleration.scale(1f / myMaxDistance); + myUnit.setAcceleration(myAcceleration); + } + } + } + } + + public VectorFieldUnit[][][] data() { + return _myField; + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldGeneratorRANDOM.java b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldGeneratorRANDOM.java new file mode 100755 index 0000000..a9e3b29 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldGeneratorRANDOM.java @@ -0,0 +1,65 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force.vectorfield; + + +import mathematik.Vector3f; + + +public class VectorFieldGeneratorRANDOM + implements VectorFieldGenerator { + + private VectorFieldUnit[][][] _myField; + + public VectorFieldGeneratorRANDOM(int theSizeX, + int theSizeY, + int theSizeZ) { + _myField = new VectorFieldUnit[theSizeX][theSizeY][theSizeZ]; + for (int x = 0; x < theSizeX; x++) { + for (int y = 0; y < theSizeY; y++) { + for (int z = 0; z < theSizeZ; z++) { + Vector3f myPosition = new Vector3f(x + * (1f / (float) theSizeX), + y * (1f / (float) theSizeY), + z * (1f / (float) theSizeZ)); + Vector3f myScale = new Vector3f(1f + / (float) theSizeX, + 1f / (float) theSizeY, + 1f / (float) theSizeZ); + Vector3f myAcceleration = new Vector3f((float) Math. + random() - 0.5f, + (float) Math.random() - 0.5f, + (float) Math.random() - 0.5f); + myAcceleration.normalize(); + VectorFieldUnit myUnit = new VectorFieldUnit(myPosition, + myScale, + myAcceleration); + _myField[x][y][z] = myUnit; + } + } + } + } + + public VectorFieldUnit[][][] data() { + return _myField; + } +} diff --git a/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldUnit.java b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldUnit.java new file mode 100755 index 0000000..860f6ef --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/force/vectorfield/VectorFieldUnit.java @@ -0,0 +1,80 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.force.vectorfield; + + +import mathematik.Vector3f; + + +public class VectorFieldUnit { + + private Vector3f _myPosition; + + private Vector3f _myScale; + + private Vector3f _myAcceleration; + + public VectorFieldUnit(final Vector3f thePosition, + final Vector3f theScale, + final Vector3f theAcceleration) { + _myPosition = new Vector3f(thePosition); + _myScale = new Vector3f(theScale); + _myAcceleration = new Vector3f(theAcceleration); + } + + public void setAcceleration(final Vector3f theAcceleration) { + _myAcceleration.set(theAcceleration); + } + + public Vector3f getAcceleration() { + return _myAcceleration; + } + + public Vector3f getPosition() { + return _myPosition; + } + + public void setPosition(final Vector3f thePosition) { + _myPosition.set(thePosition); + } + + public Vector3f getScale() { + return _myScale; + } + + public void setScale(final Vector3f theScale) { + _myScale.set(theScale); + } + + public boolean isInside(final Vector3f thePosition) { + if (thePosition.x >= _myPosition.x + && thePosition.x < _myPosition.x + _myScale.x + && thePosition.y >= _myPosition.y + && thePosition.y < _myPosition.y + _myScale.y + && thePosition.z >= _myPosition.z + && thePosition.z < _myPosition.z + _myScale.z) { + return true; + } else { + return false; + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/integration/Derivate3f.java b/day3/libs/teilchen/src/teilchen/integration/Derivate3f.java new file mode 100755 index 0000000..a4f627d --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/integration/Derivate3f.java @@ -0,0 +1,39 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.integration; + + +public final class Derivate3f { + + public float px; + + public float py; + + public float pz; + + public float vx; + + public float vy; + + public float vz; + +} diff --git a/day3/libs/teilchen/src/teilchen/integration/Euler.java b/day3/libs/teilchen/src/teilchen/integration/Euler.java new file mode 100755 index 0000000..62faaa6 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/integration/Euler.java @@ -0,0 +1,103 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.integration; + + +import java.util.Iterator; + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; + + +public class Euler + implements IIntegrator { + + private final Vector3f mTemp1; + + private final Vector3f mTemp2; + + public Euler() { + mTemp1 = new Vector3f(); + mTemp2 = new Vector3f(); + } + + public void step(final float theDeltaTime, final Physics theParticleSystem) { + + theParticleSystem.applyForces(theDeltaTime); + + synchronized (theParticleSystem.particles()) { + final Iterator myIterator = theParticleSystem.particles().iterator(); + while (myIterator.hasNext()) { + final Particle myParticle = myIterator.next(); + if (!myParticle.fixed()) { + integrate(theDeltaTime, myParticle); + } + } + } + } + + private void integrate(final float theDeltaTime, final Particle theParticle) { + mTemp1.set(theParticle.force()); + mTemp1.scale(theDeltaTime / theParticle.mass()); + + mTemp2.set(theParticle.velocity()); + mTemp2.scale(theDeltaTime); + + theParticle.velocity().add(mTemp1); + theParticle.position().add(mTemp2); + } +} + +/* this version scales better with the other integrators but is definitly slower */ +//import java.util.Vector; +// +//import particles.IParticle; +//import particles.ParticleSystem; +// +// +//public class Euler +// implements IIntegrator { +// +// private final Vector myK1 = new Vector (); +// +// public void step(final float theDeltaTime, final ParticleSystem theParticleSystem) { +// +// Util.checkContainerSize(theParticleSystem.particles().size(), myK1, Derivate3f.class); +// +// theParticleSystem.applyForces(theDeltaTime); +// Util.calculateDerivatives(theParticleSystem.particles(), myK1); +// for (int i = 0; i < theParticleSystem.particles().size(); i++) { +// Particle myParticle = theParticleSystem.particles().get(i); +// if (!myParticle.fixed()) { +// myParticle.position().x += myK1.get(i).px * theDeltaTime; +// myParticle.position().y += myK1.get(i).py * theDeltaTime; +// myParticle.position().z += myK1.get(i).pz * theDeltaTime; +// myParticle.velocity().x += myK1.get(i).vx * theDeltaTime; +// myParticle.velocity().y += myK1.get(i).vy * theDeltaTime; +// myParticle.velocity().z += myK1.get(i).vz * theDeltaTime; +// } +// } +// } +//} + diff --git a/day3/libs/teilchen/src/teilchen/integration/IIntegrator.java b/day3/libs/teilchen/src/teilchen/integration/IIntegrator.java new file mode 100755 index 0000000..7c170ad --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/integration/IIntegrator.java @@ -0,0 +1,110 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.integration; + + +import teilchen.Physics; + + +public interface IIntegrator { + + void step(final float theDeltaTime, final Physics theParticleSystem); +} +/** + * from paul bourke http://astronomy.swin.edu.au/~pbourke/modelling/solver/ + */ + +/* + // A 1st order 1D DE solver. + // Assumes the function is not time dependent. + // Parameters + // h - step size + // y0 - last value + // method - algorithm to use [0,5] + // fcn - evaluate the derivative of the field + + double Solver1D(double h, double y0, int method, double ( * fcn) (double)) { + double ynew; + double k1, k2, k3, k4, k5, k6; + + switch (method) { + case 0: // Euler method + k1 = h * ( * fcn) (y0); + ynew = y0 + k1; + break; + case 1: // Modified Euler + k1 = h * ( * fcn) (y0); + k2 = h * ( * fcn) (y0 + k1); + ynew = y0 + (k1 + k2) / 2; + break; + case 2: // Heuns method + k1 = h * ( * fcn) (y0); + k2 = h * ( * fcn) (y0 + 2 * k1 / 3); + ynew = y0 + k1 / 4 + 3 * k2 / 4; + break; + case 3: // Midpoint + k1 = h * ( * fcn) (y0); + k2 = h * ( * fcn) (y0 + k1 / 2); + ynew = y0 + k2; + break; + case 4: // 4'th order Runge-kutta + k1 = h * ( * fcn) (y0); + k2 = h * ( * fcn) (y0 + k1 / 2); + k3 = h * ( * fcn) (y0 + k2 / 2); + k4 = h * ( * fcn) (y0 + k3); + ynew = y0 + k1 / 6 + k2 / 3 + k3 / 3 + k4 / 6; + break; + case 5: // England 4'th order, six stage + k1 = h * ( * fcn) (y0); + k2 = h * ( * fcn) (y0 + k1 / 2); + k3 = h * ( * fcn) (y0 + (k1 + k2) / 4); + k4 = h * ( * fcn) (y0 - k2 + 2 * k3); + k5 = h * ( * fcn) (y0 + (7 * k1 + 10 * k2 + k4) / 27); + k6 = h * ( * fcn) (y0 + (28 * k1 - 125 * k2 + 546 * k3 + 54 * k4 - 378 * k5) / 625); + ynew = y0 + k1 / 6 + 4 * k3 / 6 + k4 / 6; + break; + } + + return (ynew); + } + */ + +/* example C program */ + +/* + int main(int argc, char * * argv) { + double t; + double dt = 0.1; // Step size + double T = 100; // Simulation duration + double y = 1; // Initial value + + for (t = 0; t < T; t += dt) { + printf("%g %g\n", t, y); + y = Solver1D(dt, y, MIDPOINT, (double ( * ) (double)) EvalFcn); + } + } + + // Sample derivative function + double EvalFcn(double x) { + return ( -0.05 * x); + } + */ diff --git a/day3/libs/teilchen/src/teilchen/integration/Midpoint.java b/day3/libs/teilchen/src/teilchen/integration/Midpoint.java new file mode 100755 index 0000000..8015e47 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/integration/Midpoint.java @@ -0,0 +1,70 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.integration; + + +import java.util.Vector; + +import teilchen.Particle; +import teilchen.Physics; + + +public class Midpoint + implements IIntegrator { + + private final Vector mK1 = new Vector(); + + public void step(final float theDeltaTime, final Physics theParticleSystem) { + + Util.checkContainerSize(theParticleSystem.particles().size(), mK1, Derivate3f.class); + + /* one */ + theParticleSystem.applyForces(theDeltaTime); + Util.calculateDerivatives(theParticleSystem.particles(), mK1); + for (int i = 0; i < theParticleSystem.particles().size(); i++) { + Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + myParticle.position().x += mK1.get(i).px * theDeltaTime / 2; + myParticle.position().y += mK1.get(i).py * theDeltaTime / 2; + myParticle.position().z += mK1.get(i).pz * theDeltaTime / 2; + myParticle.position().x += mK1.get(i).vx * theDeltaTime / 2; + myParticle.position().y += mK1.get(i).vy * theDeltaTime / 2; + myParticle.position().z += mK1.get(i).vz * theDeltaTime / 2; + } + } + + /* two */ + theParticleSystem.applyForces(theDeltaTime); + Util.calculateDerivatives(theParticleSystem.particles(), mK1); + for (int i = 0; i < theParticleSystem.particles().size(); i++) { + Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + myParticle.position().x += mK1.get(i).px * theDeltaTime; + myParticle.position().y += mK1.get(i).py * theDeltaTime; + myParticle.position().z += mK1.get(i).pz * theDeltaTime; + myParticle.velocity().x += mK1.get(i).vx * theDeltaTime; + myParticle.velocity().y += mK1.get(i).vy * theDeltaTime; + myParticle.velocity().z += mK1.get(i).vz * theDeltaTime; + } + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/integration/RungeKutta.java b/day3/libs/teilchen/src/teilchen/integration/RungeKutta.java new file mode 100755 index 0000000..de062b0 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/integration/RungeKutta.java @@ -0,0 +1,238 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.integration; + + +import java.util.Vector; + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; + + +public class RungeKutta + implements IIntegrator { + + private final Vector mOriginalPositions; + + private final Vector mOriginalVelocities; + + private final Vector mK1Forces; + + private final Vector mK1Velocities; + + private final Vector mK2Forces; + + private final Vector mK2Velocities; + + private final Vector mK3Forces; + + private final Vector mK3Velocities; + + private final Vector mK4Forces; + + private final Vector mK4Velocities; + + public RungeKutta() { + mOriginalPositions = new Vector(); + mOriginalVelocities = new Vector(); + mK1Forces = new Vector(); + mK1Velocities = new Vector(); + mK2Forces = new Vector(); + mK2Velocities = new Vector(); + mK3Forces = new Vector(); + mK3Velocities = new Vector(); + mK4Forces = new Vector(); + mK4Velocities = new Vector(); + } + + public void step(final float theDeltaTime, + final Physics theParticleSystem) { + + final int mySize = theParticleSystem.particles().size(); + Util.checkContainerSize(mySize, mOriginalPositions, Vector3f.class); + Util.checkContainerSize(mySize, mOriginalVelocities, Vector3f.class); + Util.checkContainerSize(mySize, mK1Forces, Vector3f.class); + Util.checkContainerSize(mySize, mK1Velocities, Vector3f.class); + Util.checkContainerSize(mySize, mK2Forces, Vector3f.class); + Util.checkContainerSize(mySize, mK2Velocities, Vector3f.class); + Util.checkContainerSize(mySize, mK3Forces, Vector3f.class); + Util.checkContainerSize(mySize, mK3Velocities, Vector3f.class); + Util.checkContainerSize(mySize, mK4Forces, Vector3f.class); + Util.checkContainerSize(mySize, mK4Velocities, Vector3f.class); + + /* save original position and velocities */ + for (int i = 0; i < theParticleSystem.particles().size(); ++i) { + final Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + mOriginalPositions.get(i).set(myParticle.position()); + mOriginalVelocities.get(i).set(myParticle.velocity()); + } + } + + /* get all the k1 values */ + theParticleSystem.applyForces(theDeltaTime); + + /* save the intermediate forces */ + for (int i = 0; i < theParticleSystem.particles().size(); ++i) { + final Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + mK1Forces.get(i).set(myParticle.force()); + mK1Velocities.get(i).set(myParticle.velocity()); + } + } + + /* get k2 values */ + for (int i = 0; i < theParticleSystem.particles().size(); ++i) { + final Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + final Vector3f originalPosition = mOriginalPositions.get(i); + final Vector3f k1Velocity = mK1Velocities.get(i); + + myParticle.position().x = originalPosition.x + k1Velocity.x * 0.5f * theDeltaTime; + myParticle.position().y = originalPosition.y + k1Velocity.y * 0.5f * theDeltaTime; + myParticle.position().z = originalPosition.z + k1Velocity.z * 0.5f * theDeltaTime; + + final Vector3f originalVelocity = mOriginalVelocities.get(i); + final Vector3f k1Force = mK1Forces.get(i); + + myParticle.velocity().x = originalVelocity.x + k1Force.x * 0.5f * theDeltaTime / myParticle.mass(); + myParticle.velocity().y = originalVelocity.y + k1Force.y * 0.5f * theDeltaTime / myParticle.mass(); + myParticle.velocity().z = originalVelocity.z + k1Force.z * 0.5f * theDeltaTime / myParticle.mass(); + } + } + + theParticleSystem.applyForces(theDeltaTime); + + /* save the intermediate forces */ + for (int i = 0; i < theParticleSystem.particles().size(); ++i) { + final Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + mK2Forces.get(i).set(myParticle.force()); + mK2Velocities.get(i).set(myParticle.velocity()); + } + } + + /* get k3 values */ + for (int i = 0; i < theParticleSystem.particles().size(); ++i) { + final Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + final Vector3f originalPosition = mOriginalPositions.get(i); + final Vector3f k2Velocity = mK2Velocities.get(i); + + myParticle.position().x = originalPosition.x + k2Velocity.x * 0.5f * theDeltaTime; + myParticle.position().y = originalPosition.y + k2Velocity.y * 0.5f * theDeltaTime; + myParticle.position().z = originalPosition.z + k2Velocity.z * 0.5f * theDeltaTime; + + final Vector3f originalVelocity = mOriginalVelocities.get(i); + final Vector3f k2Force = mK2Forces.get(i); + + myParticle.velocity().x = originalVelocity.x + k2Force.x * 0.5f * theDeltaTime / myParticle.mass(); + myParticle.velocity().y = originalVelocity.y + k2Force.y * 0.5f * theDeltaTime / myParticle.mass(); + myParticle.velocity().z = originalVelocity.z + k2Force.z * 0.5f * theDeltaTime / myParticle.mass(); + } + } + + theParticleSystem.applyForces(theDeltaTime); + + /* save the intermediate forces */ + for (int i = 0; i < theParticleSystem.particles().size(); ++i) { + final Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + (mK3Forces.get(i)).set(myParticle.force()); + (mK3Velocities.get(i)).set(myParticle.velocity()); + } + } + + /* get k4 values */ + for (int i = 0; i < theParticleSystem.particles().size(); ++i) { + final Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + final Vector3f originalPosition = mOriginalPositions.get(i); + final Vector3f k3Velocity = mK3Velocities.get(i); + + myParticle.position().x = originalPosition.x + k3Velocity.x * theDeltaTime; + myParticle.position().y = originalPosition.y + k3Velocity.y * theDeltaTime; + myParticle.position().z = originalPosition.z + k3Velocity.z * theDeltaTime; + + final Vector3f originalVelocity = mOriginalVelocities.get(i); + final Vector3f k3Force = mK3Forces.get(i); + + myParticle.velocity().x = originalVelocity.x + k3Force.x * theDeltaTime / myParticle.mass(); + myParticle.velocity().y = originalVelocity.y + k3Force.y * theDeltaTime / myParticle.mass(); + myParticle.velocity().z = originalVelocity.z + k3Force.z * theDeltaTime / myParticle.mass(); + } + } + + theParticleSystem.applyForces(theDeltaTime); + + /* save the intermediate forces */ + for (int i = 0; i < theParticleSystem.particles().size(); ++i) { + final Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + mK4Forces.get(i).set(myParticle.force()); + mK4Velocities.get(i).set(myParticle.velocity()); + } + } + + /* put them all together and what do you get? */ + for (int i = 0; i < theParticleSystem.particles().size(); ++i) { + final Particle myParticle = theParticleSystem.particles().get(i); + if (!myParticle.fixed()) { + /* update position */ + final Vector3f originalPosition = mOriginalPositions.get(i); + final Vector3f k1Velocity = mK1Velocities.get(i); + final Vector3f k2Velocity = mK2Velocities.get(i); + final Vector3f k3Velocity = mK3Velocities.get(i); + final Vector3f k4Velocity = mK4Velocities.get(i); + + myParticle.position().x = originalPosition.x + + theDeltaTime / 6.0f + * (k1Velocity.x + 2.0f * k2Velocity.x + 2.0f * k3Velocity.x + k4Velocity.x); + myParticle.position().y = originalPosition.y + + theDeltaTime / 6.0f + * (k1Velocity.y + 2.0f * k2Velocity.y + 2.0f * k3Velocity.y + k4Velocity.y); + myParticle.position().z = originalPosition.z + + theDeltaTime / 6.0f + * (k1Velocity.z + 2.0f * k2Velocity.z + 2.0f * k3Velocity.z + k4Velocity.z); + + /* update velocity */ + final Vector3f originalVelocity = mOriginalVelocities.get(i); + final Vector3f k1Force = mK1Forces.get(i); + final Vector3f k2Force = mK2Forces.get(i); + final Vector3f k3Force = mK3Forces.get(i); + final Vector3f k4Force = mK4Forces.get(i); + + myParticle.velocity().x = originalVelocity.x + + theDeltaTime / (6.0f * myParticle.mass()) + * (k1Force.x + 2.0f * k2Force.x + 2.0f * k3Force.x + k4Force.x); + myParticle.velocity().y = originalVelocity.y + + theDeltaTime / (6.0f * myParticle.mass()) + * (k1Force.y + 2.0f * k2Force.y + 2.0f * k3Force.y + k4Force.y); + myParticle.velocity().z = originalVelocity.z + + theDeltaTime / (6.0f * myParticle.mass()) + * (k1Force.z + 2.0f * k2Force.z + 2.0f * k3Force.z + k4Force.z); + } + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/integration/Util.java b/day3/libs/teilchen/src/teilchen/integration/Util.java new file mode 100755 index 0000000..1aa427a --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/integration/Util.java @@ -0,0 +1,62 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.integration; + + +import java.util.List; + +import teilchen.Particle; + + +public final class Util { + + public static final void checkContainerSize(final int theSize, + final List theContainer, + Class theClass) { + final int myDiff = theSize - theContainer.size(); + if (myDiff > 0) { + for (int i = 0; i < myDiff; i++) { + try { + theContainer.add(theClass.newInstance()); + } catch (Exception ex) { + System.err.println(ex); + } + } + } else if (myDiff < 0) { + for (int i = 0; i < myDiff; i++) { + theContainer.remove(myDiff + theSize); + } + } + } + + public static final void calculateDerivatives(final List theParticles, + final List theDerivates) { + for (int i = 0; i < theParticles.size(); i++) { + theDerivates.get(i).px = theParticles.get(i).velocity().x; + theDerivates.get(i).py = theParticles.get(i).velocity().y; + theDerivates.get(i).pz = theParticles.get(i).velocity().z; + theDerivates.get(i).vx = theParticles.get(i).force().x / theParticles.get(i).mass(); + theDerivates.get(i).vy = theParticles.get(i).force().y / theParticles.get(i).mass(); + theDerivates.get(i).vz = theParticles.get(i).force().z / theParticles.get(i).mass(); + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/integration/Verlet.java b/day3/libs/teilchen/src/teilchen/integration/Verlet.java new file mode 100755 index 0000000..9797334 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/integration/Verlet.java @@ -0,0 +1,115 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.integration; + + +import java.util.Iterator; + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; + + +public class Verlet + implements IIntegrator { + + private final Vector3f temp1; + + private final Vector3f temp2; + + private float _myDamping; + + public Verlet() { + this(1.0f); + } + + public Verlet(final float theDamping) { + _myDamping = theDamping; + temp1 = new Vector3f(); + temp2 = new Vector3f(); + } + + public float damping() { + return _myDamping; + } + + public void damping(float theDamping) { + _myDamping = theDamping; + } + + public void step(final float theDeltaTime, final Physics theParticleSystem) { + + theParticleSystem.applyForces(theDeltaTime); + + synchronized (theParticleSystem.particles()) { + final Iterator myIterator = theParticleSystem.particles().iterator(); + while (myIterator.hasNext()) { + final Particle myParticle = myIterator.next(); + if (!myParticle.fixed()) { + integrate(theDeltaTime, myParticle); + } + } + } + } + + private final void integrate(float theDeltaTime, Particle theParticle) { + final Vector3f myOldPosition = new Vector3f(theParticle.position()); + + /* + Physics simulation using Verlet integration + sgreen@nvidia.com 6/2002 + + based on Thomas Jakobsen's "Advanced Character Physics": + http://www.ioi.dk/Homepages/tj/publications/gdc2001.htm + + basic idea: + x' = x + v*dt + v' = v + a*dt + + x' = x + (v + a*dt) * dt + = x + v*dt + a*dt^2 + + v ~= (x - ox) / dt + + x' = x + (x - ox) + a*dt^2 + */ + + /* v ~= (x - ox) / dt */ + theParticle.velocity().sub(theParticle.position(), theParticle.old_position()); + theParticle.velocity().scale(1.0f / theDeltaTime); + + /* x' = x + (x - ox) + a*dt^2 */ + temp1.set(theParticle.force()); + temp1.scale(1.0f / theParticle.mass()); + temp1.scale(theDeltaTime * theDeltaTime); + temp2.sub(theParticle.position(), theParticle.old_position()); + + temp2.scale(_myDamping); + + theParticle.position().add(temp1); + theParticle.position().add(temp2); + + /* --- */ + theParticle.old_position().set(myOldPosition); + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/CollisionManager.java b/day3/libs/teilchen/src/teilchen/util/CollisionManager.java new file mode 100755 index 0000000..d01a044 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/CollisionManager.java @@ -0,0 +1,425 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.util; + + +import java.util.Vector; + +import mathematik.Random; +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.Stick; +import teilchen.cubicle.CubicleParticle; +import teilchen.cubicle.CubicleWorld; +import teilchen.cubicle.ICubicleEntity; +import teilchen.force.IForce; +import teilchen.force.Spring; + + +/** + * this manager uses it s own particle system. we could make it more integrated + * by using a shared physic world. this would of course make everthing more + * slower. + */ +public class CollisionManager { + + public boolean HINT_IGNORE_STILL_OR_FIXED = false; + + private float mCollisionSpringConstant; + + private float mCollisionSpringDamping; + + private final Physics mCollisionPhysics; + + private float mMinimumDistance; + + private Vector3f mResolveSamePosition; + + public enum ResolverType { +// COLLISION_STICK, COLLISION_SPRING, + + SPRING, STICK + + } + private final Random mRandom; + + private ResolverType mResolverType; + + private float mCollisionResolverIntervalCounter = 1; + + private float mCollisionResolverInterval = 0; + + private int mDistanceMode = DISTANCE_MODE_FIXED; + + public static final int DISTANCE_MODE_RADIUS = 0; + + public static final int DISTANCE_MODE_FIXED = 1; + + public CollisionManager() { + this(new Physics()); + } + + public CollisionManager(final Physics thePhysics) { + mCollisionPhysics = thePhysics; + mResolveSamePosition = new Vector3f(1, 1, 1); + mCollisionSpringConstant = 20.0f; + mCollisionSpringDamping = 1.0f; + mMinimumDistance = 20; + mResolverType = ResolverType.SPRING; + mRandom = new Random(); + } + + public void distancemode(int theDistanceMode) { + mDistanceMode = theDistanceMode; + } + + public void setResolverType(ResolverType theResolverType) { + mResolverType = theResolverType; + } + + public Vector3f resolveSamePosition() { + return mResolveSamePosition; + } + + public void springDamping(float theSpringDamping) { + mCollisionSpringDamping = theSpringDamping; + } + + public float springDamping() { + return mCollisionSpringDamping; + } + + public void springConstant(float theSpringConstant) { + mCollisionSpringConstant = theSpringConstant; + } + + public float springConstant() { + return mCollisionSpringConstant; + } + + public void minimumDistance(float theMinimumDistance) { + mMinimumDistance = theMinimumDistance; + } + + public float minimumDistance() { + return mMinimumDistance; + } + + public Physics collision() { + return mCollisionPhysics; + } + + public Vector collision_forces() { + return mCollisionPhysics.forces(); + } + + public void loop(float theDeltaTime) { + +// /* collision resolver */ +// if (mCollisionResolverIntervalCounter > mCollisionResolverInterval) { +// mCollisionResolverIntervalCounter = 0; +//// createCollisionResolvers(); +// } else { +// mCollisionResolverIntervalCounter += theDeltaTime; +// } + + /* physics */ + mCollisionPhysics.step(theDeltaTime); + +// /* remove collision resolver */ +// removeCollisionResolver(); + } + + public void autoloop(float theDeltaTime) { + /* collision resolver */ + if (mCollisionResolverIntervalCounter > mCollisionResolverInterval) { + mCollisionResolverIntervalCounter = 0; +// mCollisionResolverIntervalCounter -= mCollisionResolverInterval; +// mCollisionResolverIntervalCounter %= mCollisionResolverInterval; + createCollisionResolvers(); + } else { + mCollisionResolverIntervalCounter += theDeltaTime; + } + + /* physics */ + mCollisionPhysics.step(theDeltaTime); + + /* remove collision resolver */ + removeCollisionResolver(); + } + + public void removeCollisionResolver() { + mCollisionPhysics.forces().clear(); + mCollisionPhysics.constraints().clear(); + } + + public void createCollisionResolvers() { + for (int i = 0; i < mCollisionPhysics.particles().size(); i++) { + createCollisionResolver(mCollisionPhysics.particles().get(i), i); + } + } + + private void createCollisionResolver(final Particle theParticle, final int theStart) { + if (HINT_IGNORE_STILL_OR_FIXED) { + if (theParticle.fixed() || theParticle.still()) { + return; + } + } + for (int j = theStart; j < mCollisionPhysics.particles().size(); j++) { + Particle myOtherParticle = mCollisionPhysics.particles().get(j); + if (theParticle != myOtherParticle) { // && !myOtherParticle.fixed()) { + final float myDistance = theParticle.position().distance(myOtherParticle.position()); + final float myMinimumDistance = getMinimumDistance(theParticle, myOtherParticle); + if (myDistance < myMinimumDistance) { + if (theParticle.fixed() && myOtherParticle.fixed()) { +// continue; + } + /** + * because of the way we handle the collision resolver + * creation there is no need to check for multiple spring + * connections. + * checkSpringConnectionExistence(mCollisionPhysics.getForces(), + * myParticle, myOtherParticle); + */ + if (mResolverType == ResolverType.SPRING) { + Spring mySpring = new Spring(theParticle, + myOtherParticle, + mCollisionSpringConstant, + mCollisionSpringDamping, + myMinimumDistance); + mCollisionPhysics.add(mySpring); + } else if (mResolverType == ResolverType.STICK) { + Stick mySpring = new Stick(theParticle, + myOtherParticle, + myMinimumDistance); + mCollisionPhysics.add(mySpring); + } + + /* hack to prevent particles from being in the same place */ + if (myDistance < mathematik.Mathematik.EPSILON && myDistance > -mathematik.Mathematik.EPSILON) { + myOtherParticle.position().x += mRandom.getFloat(mResolveSamePosition.x * -0.5f, + mResolveSamePosition.x * 0.5f); + myOtherParticle.position().y += mRandom.getFloat(mResolveSamePosition.y * -0.5f, + mResolveSamePosition.y * 0.5f); + myOtherParticle.position().z += mRandom.getFloat(mResolveSamePosition.z * -0.5f, + mResolveSamePosition.z * 0.5f); + } + } + } + } + } + + public void createCollisionResolvers(final CubicleWorld theWorld) { + for (int i = 0; i < mCollisionPhysics.particles().size(); i++) { + final Particle myParticle = mCollisionPhysics.particles().get(i); + if (myParticle instanceof CubicleParticle) { + createCollisionResolver(theWorld, (CubicleParticle) myParticle); + } + } + } + + private void createCollisionResolver(final CubicleWorld theWorld, final CubicleParticle theParticle) { + if (HINT_IGNORE_STILL_OR_FIXED) { + if (theParticle.fixed() || theParticle.still()) { + return; + } + } + + final Vector myNeigbors = theWorld.getLocalEntities(theParticle); + if (myNeigbors.size() > 1) { + for (int j = 0; j < myNeigbors.size(); j++) { + final ICubicleEntity myEntity = myNeigbors.get(j); + if (myEntity instanceof Particle) { + final Particle myOtherParticle = (Particle) myEntity; + if (theParticle != myOtherParticle) { + final float myDistance = theParticle.position().distance(myOtherParticle.position()); + final float myMinimumDistance = getMinimumDistance(theParticle, myOtherParticle); + if (myDistance < myMinimumDistance) { + if (theParticle.fixed() && myOtherParticle.fixed()) { + continue; + } + /** + * because of the way we handle the collision + * resolver creation there is no need to check for + * multiple spring connections. + * checkSpringConnectionExistence(mCollisionPhysics.getForces(), + * myParticle, myOtherParticle); + */ + if (mResolverType == ResolverType.SPRING) { + Spring mySpring = new Spring(theParticle, + myOtherParticle, + mCollisionSpringConstant, + mCollisionSpringDamping, + myMinimumDistance); + mCollisionPhysics.add(mySpring); + } else if (mResolverType == ResolverType.STICK) { + Stick mySpring = new Stick(theParticle, + myOtherParticle, + myMinimumDistance); + mCollisionPhysics.add(mySpring); + } + + /* hack to prevent particles from being in the same place */ + if (myDistance < mathematik.Mathematik.EPSILON + && myDistance > -mathematik.Mathematik.EPSILON) { + myOtherParticle.position().x += mRandom.getFloat(mResolveSamePosition.x * -0.5f, + mResolveSamePosition.x * 0.5f); + myOtherParticle.position().y += mRandom.getFloat(mResolveSamePosition.y * -0.5f, + mResolveSamePosition.y * 0.5f); + myOtherParticle.position().z += mRandom.getFloat(mResolveSamePosition.z * -0.5f, + mResolveSamePosition.z * 0.5f); + } + } + } + } + } + } + } + + private float getMinimumDistance(Particle theParticle, Particle myOtherParticle) { + final float myMinimumDistance; + + if (mDistanceMode == DISTANCE_MODE_RADIUS) { + myMinimumDistance = theParticle.radius() + myOtherParticle.radius(); + } else { + myMinimumDistance = mMinimumDistance; + } + return myMinimumDistance; + } + + public static class CollisionSpring + extends Spring { + + public CollisionSpring(Particle theA, Particle theB) { + super(theA, + theB, + 2.0f, 0.1f, + theA.position().distance(theB.position())); + } + + public CollisionSpring(Particle theA, + Particle theB, + final float theSpringConstant, + final float theSpringDamping) { + super(theA, + theB, + theSpringConstant, + theSpringDamping, + theA.position().distance(theB.position())); + } + + public CollisionSpring(final Particle theA, + final Particle theB, + final float theSpringConstant, + final float theSpringDamping, + final float theRestLength) { + super(theA, + theB, + theSpringConstant, + theSpringDamping, + theRestLength); + } + + public void apply(final float theDeltaTime, final Physics theParticleSystem) { + if (!mA.fixed() || !mB.fixed()) { + float a2bX = mA.position().x - mB.position().x; + float a2bY = mA.position().y - mB.position().y; + float a2bZ = mA.position().z - mB.position().z; + final float myInversDistance = fastInverseSqrt(a2bX * a2bX + a2bY * a2bY + a2bZ * a2bZ); + final float myDistance = 1.0F / myInversDistance; + + if (myDistance < mRestLength) { + if (myDistance == 0.0F) { + a2bX = 0.0F; + a2bY = 0.0F; + a2bZ = 0.0F; + } else { + a2bX *= myInversDistance; + a2bY *= myInversDistance; + a2bZ *= myInversDistance; + } + + final float mSpringForce = -(myDistance - mRestLength) * mSpringConstant; + final float Va2bX = mA.velocity().x - mB.velocity().x; + final float Va2bY = mA.velocity().y - mB.velocity().y; + final float Va2bZ = mA.velocity().z - mB.velocity().z; + final float mDampingForce = -mSpringDamping * (a2bX * Va2bX + a2bY * Va2bY + a2bZ * Va2bZ); + final float r = mSpringForce + mDampingForce; + a2bX *= r; + a2bY *= r; + a2bZ *= r; + if (!mA.fixed()) { + mA.force().add(a2bX, a2bY, a2bZ); + } + + if (!mB.fixed()) { + mB.force().add(-a2bX, -a2bY, -a2bZ); + } + } + } + } + } + + public static class CollisionStick + extends Stick { + + public CollisionStick(Particle theA, Particle theB) { + super(theA, theB); + } + + public CollisionStick(final Particle theA, + final Particle theB, + final float theRestLength) { + super(theA, theB, theRestLength); + } + + public void apply(Physics theParticleSystem) { + if (!mA.fixed() || !mB.fixed()) { + mTempDistanceVector.sub(mA.position(), mB.position()); + final float myDistanceSquared = mTempDistanceVector.lengthSquared(); + if (myDistanceSquared > 0) { + if (myDistanceSquared < mRestLength * mRestLength) { + final float myDistance = (float) Math.sqrt(myDistanceSquared); + final float myDifference = mRestLength - myDistance; + if (myDifference > EPSILON || myDifference < -EPSILON) { + if (!mOneWay) { + final float myDifferenceScale = 0.5f * myDifference / myDistance; + mTempVector.scale(myDifferenceScale, mTempDistanceVector); + mA.position().add(mTempVector); + mB.position().sub(mTempVector); + } else { + final float myDifferenceScale = myDifference / myDistance; + mTempVector.scale(myDifferenceScale, mTempDistanceVector); + mB.position().sub(mTempVector); + } + } + } + } else { + mB.position().set(mA.position()); + mB.position().x += mRestLength; + } + } + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/CubicleWorldView.java b/day3/libs/teilchen/src/teilchen/util/CubicleWorldView.java new file mode 100755 index 0000000..74c4c9a --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/CubicleWorldView.java @@ -0,0 +1,86 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.util; + + +import mathematik.TransformMatrix4f; +import mathematik.Vector3f; + +import processing.core.PGraphics; +import teilchen.cubicle.CubicleAtom; +import teilchen.cubicle.CubicleWorld; + + +public class CubicleWorldView { + + private final CubicleWorld mCubicleWorld; + + public int color_full = -1; + + public int color_empty = -8421505; + + public CubicleWorldView(CubicleWorld theWorld) { + mCubicleWorld = theWorld; + } + + public void draw(PGraphics theParent) { + + /* collect data */ + final CubicleAtom[][][] myData = mCubicleWorld.getDataRef(); + final TransformMatrix4f myTransform = mCubicleWorld.transform(); + final Vector3f myScale = mCubicleWorld.cellscale(); + + /* draw world */ + theParent.pushMatrix(); + + /* rotation */ + float[] f = myTransform.toArray(); + theParent.translate(f[12], f[13], f[14]); + theParent.applyMatrix(f[0], f[1], f[2], f[3], + f[4], f[5], f[6], f[7], + f[8], f[9], f[10], f[11], + 0, 0, 0, f[15]); + + /* scale */ + theParent.scale(myScale.x, myScale.y, myScale.z); + for (int x = 0; x < myData.length; x++) { + for (int y = 0; y < myData[x].length; y++) { + for (int z = 0; z < myData[x][y].length; z++) { + CubicleAtom myCubicle = myData[x][y][z]; + theParent.pushMatrix(); + theParent.translate(x, y, z); + theParent.translate(mCubicleWorld.cellscale().x / 2 / myScale.x, + mCubicleWorld.cellscale().y / 2 / myScale.y, + mCubicleWorld.cellscale().z / 2 / myScale.z); + if (myCubicle.size() > 0) { + theParent.stroke(color_full); + } else { + theParent.stroke(color_empty); + } + theParent.box(1); + theParent.popMatrix(); + } + } + } + theParent.popMatrix(); + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/DrawLib.java b/day3/libs/teilchen/src/teilchen/util/DrawLib.java new file mode 100755 index 0000000..071252f --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/DrawLib.java @@ -0,0 +1,290 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.util; + + +import java.util.List; + +import mathematik.Vector3f; +import mathematik.WorldAxisAlignedBoundingBox; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Attractor; +import teilchen.force.IForce; +import teilchen.force.Spring; +import teilchen.force.TriangleDeflector; +import processing.core.PGraphics; + + +public class DrawLib { + + public static void drawAttractor(final PGraphics g, + final List theForces, + int theColor) { + for (final IForce myForce : theForces) { + if (myForce instanceof Attractor) { + draw(g, (Attractor) myForce, theColor); + } + } + } + + /** + * draw attractors. + * + * @param g PGraphics + * @param myAttractor Attractor + * @param theColor int + */ + public static void draw(final PGraphics g, final Attractor myAttractor, int theColor) { + g.sphereDetail(6); + g.noFill(); + g.stroke(theColor); + + g.pushMatrix(); + g.translate(myAttractor.position().x, + myAttractor.position().y, + myAttractor.position().z); + g.sphere(myAttractor.radius()); + g.popMatrix(); + } + + public static void drawParticles(final PGraphics g, + final Physics theParticleSystem, + float theSize, + int theColor) { + draw(g, + theParticleSystem.particles(), + theSize, + theColor); + } + + public static void drawParticles(final PGraphics g, + final Physics theParticleSystem, + float theSize, + int theStrokeColor, + int theFillColor) { + draw(g, + theParticleSystem.particles(), + theSize, + theStrokeColor, + theFillColor); + } + + public static void drawSprings(final PGraphics g, + final Physics theParticleSystem, + int theColor) { + /* draw springs */ + g.stroke(theColor); + for (int i = 0; i < theParticleSystem.forces().size(); i++) { + if (theParticleSystem.forces(i) instanceof Spring) { + Spring mySpring = (Spring) theParticleSystem.forces(i); + g.line(mySpring.a().position().x, + mySpring.a().position().y, + mySpring.b().position().x, + mySpring.b().position().y); + } + } + } + + /** + * draw particles. + * + * @param g PGraphics + * @param theParticles Vector + * @param theSize float + * @param theColor int + */ + public static void draw(final PGraphics g, + final List theParticles, + float theSize, + int theColor) { + g.stroke(theColor); + g.noFill(); + for (Particle myParticle : theParticles) { + g.pushMatrix(); + g.translate(myParticle.position().x, + myParticle.position().y, + myParticle.position().z); + g.ellipse(0, 0, theSize, theSize); + g.popMatrix(); + } + } + + /** + * draw particles. + * + * @param g PGraphics + * @param theParticles Vector + * @param theSize float + * @param theStrokeColor int + */ + public static void draw(final PGraphics g, + final List theParticles, + float theSize, + int theStrokeColor, + int theFillColor) { + g.stroke(theStrokeColor); + g.fill(theFillColor); + for (Particle myParticle : theParticles) { + g.pushMatrix(); + g.translate(myParticle.position().x, + myParticle.position().y, + myParticle.position().z); + g.ellipse(0, 0, theSize, theSize); + g.popMatrix(); + } + } + + /** + * draw triangle deflector with bounding box. + * + * @param g PGraphics + * @param theTriangleDeflector TriangleDeflector + * @param theTriangleColor int + * @param theBBColor int + * @param theNormalColor int + */ + public static void draw(final PGraphics g, + final TriangleDeflector theTriangleDeflector, + int theTriangleColor, + int theBBColor, + int theNormalColor) { + /* triangle */ + int myTriangleColor = theTriangleColor; + if (theTriangleDeflector.hit()) { + myTriangleColor = theBBColor; + } + draw(g, + theTriangleDeflector.a(), theTriangleDeflector.b(), theTriangleDeflector.c(), + myTriangleColor, + theNormalColor); + + /* bb */ + draw(g, + theTriangleDeflector.boundingbox(), + theBBColor); + } + + /** + * draw buunding box. + * + * @param g PGraphics + * @param theWorldAxisAlignedBoundingBox WorldAxisAlignedBoundingBox + * @param theColor int + */ + public static void draw(final PGraphics g, + final WorldAxisAlignedBoundingBox theWorldAxisAlignedBoundingBox, + int theColor) { + g.stroke(theColor); + g.pushMatrix(); + g.translate(theWorldAxisAlignedBoundingBox.position.x, + theWorldAxisAlignedBoundingBox.position.y, + theWorldAxisAlignedBoundingBox.position.z); + g.box(theWorldAxisAlignedBoundingBox.scale.x, + theWorldAxisAlignedBoundingBox.scale.y, + theWorldAxisAlignedBoundingBox.scale.z); + g.popMatrix(); + } + + /** + * draw a triangle with a normal + * + * @param g PGraphics + * @param a Vector3f + * @param b Vector3f + * @param c Vector3f + * @param theTriangleColor int + * @param theNormalColor int + */ + public static void draw(final PGraphics g, + final Vector3f a, final Vector3f b, final Vector3f c, + int theTriangleColor, int theNormalColor) { + g.stroke(theTriangleColor); + g.beginShape(PGraphics.TRIANGLES); + g.vertex(a.x, a.y, a.z); + g.vertex(b.x, b.y, b.z); + g.vertex(c.x, c.y, c.z); + g.endShape(); + g.noFill(); + + Vector3f myNormal = new Vector3f(); + mathematik.Util.calculateNormal(a, b, c, myNormal); + myNormal.scale(50); + + Vector3f myCenterOfMass = new Vector3f(); + myCenterOfMass.add(a); + myCenterOfMass.add(b); + myCenterOfMass.add(c); + myCenterOfMass.scale(1f / 3f); + + g.stroke(theNormalColor); + g.line(myCenterOfMass.x, + myCenterOfMass.y, + myCenterOfMass.z, + myCenterOfMass.x + myNormal.x, + myCenterOfMass.y + myNormal.y, + myCenterOfMass.z + myNormal.z); + } + + public static void cross2(final PGraphics g, + final Vector3f pPosition, + float pSize) { + g.line( + pPosition.x + pSize, + pPosition.y + pSize, + pPosition.z, + pPosition.x - pSize, + pPosition.y - pSize, + pPosition.z); + g.line( + pPosition.x + pSize, + pPosition.y - pSize, + pPosition.z, + pPosition.x - pSize, + pPosition.y + pSize, + pPosition.z); + } + + public static void cross3(final PGraphics g, + final Vector3f pPosition, + float pSize) { + g.line(pPosition.x - pSize, + pPosition.y, + pPosition.z, + pPosition.x + pSize, + pPosition.y, + pPosition.z); + g.line(pPosition.x, + pPosition.y - pSize, + pPosition.z, + pPosition.x, + pPosition.y + pSize, + pPosition.z); + g.line(pPosition.x, + pPosition.y, + pPosition.z - pSize, + pPosition.x, + pPosition.y, + pPosition.z + pSize); + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/Overlap.java b/day3/libs/teilchen/src/teilchen/util/Overlap.java new file mode 100755 index 0000000..6546866 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/Overlap.java @@ -0,0 +1,107 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.util; + + +import mathematik.Vector3f; + +import java.util.List; + + +public class Overlap { + + public static Vector3f RESOLVE_SAME_PLACE = new Vector3f(1, 0, 0); + + public static void resolveOverlap(E theEntityA, + E theEntityB) { + if (theEntityB == theEntityA) { + return; + } + + if (theEntityA.radius() == 0 || theEntityB.radius() == 0) { + return; + } + + final Vector3f mAB = mathematik.Util.sub(theEntityA.position(), theEntityB.position()); + final float myDistance = mAB.length(); + + if (myDistance > 0) { + float myOverlap = theEntityB.radius() + theEntityA.radius() - myDistance; + + if (myOverlap > 0) { + mAB.scale(0.5f * myOverlap / myDistance); + theEntityA.position().add(mAB); + theEntityB.position().sub(mAB); + } + } else { + if (RESOLVE_SAME_PLACE != null) { + final Vector3f myOffset = new Vector3f(RESOLVE_SAME_PLACE); + myOffset.scale(theEntityB.radius() + theEntityA.radius()); + myOffset.scale(0.5f); + theEntityA.position().add(myOffset); + theEntityB.position().sub(myOffset); + } + } + } + + public static void resolveOverlap(E theEntity, + E[] theEntities) { + if (theEntities == null || theEntities.length < 1) { + return; + } + + for (int i = 0; i < theEntities.length; i++) { + resolveOverlap(theEntities[i], theEntity); + } + } + + public static void resolveOverlap(E theEntity, + List theEntities) { + if (theEntities == null || theEntities.size() < 1) { + return; + } + + for (int i = 0; i < theEntities.size(); i++) { + resolveOverlap(theEntities.get(i), theEntity); + } + } + + public static void resolveOverlap(List theEntities) { + if (theEntities == null || theEntities.isEmpty()) { + return; + } + + /** + * @todo room for improvement. there is some redundant testing going on + * here. + */ + for (int i = 0; i < theEntities.size(); i++) { + for (int j = 0; j < theEntities.size(); j++) { + if (i == j) { + continue; + } +// final SpatialEntity myOtherEntity = theEntities.get(j); + resolveOverlap(theEntities.get(i), theEntities.get(j)); + } + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/Packing.java b/day3/libs/teilchen/src/teilchen/util/Packing.java new file mode 100755 index 0000000..37e3701 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/Packing.java @@ -0,0 +1,73 @@ +package teilchen.util; + + +import mathematik.Vector3f; + +import java.util.List; +import java.util.Vector; + + +public class Packing { + + public static void pack(Vector mShapes, Vector3f pCenter, float pDamping) { + resolveOverlap(mShapes); + contract(mShapes, pCenter, pDamping); + } + + public static void resolveOverlap(List mEntities) { + /* @TODO this is somewhat redundant to 'AntiOverlap' */ + for (int i = 0; i < mEntities.size(); i++) { + final SpatialEntity mA = mEntities.get(i); + for (int j = i + 1; j < mEntities.size(); j++) { + if (i != j) { + final SpatialEntity mB = mEntities.get(j); + final float mIdealDistance = mA.radius() + mB.radius(); + final Vector3f mAB = mathematik.Util.sub(mB.position(), mA.position()); + final float mDistance = mAB.length(); + if (mDistance > 0.0f) { + if (mDistance < mIdealDistance) { + mAB.normalize(); + mAB.scale((mIdealDistance - mDistance) * 0.5f); + mB.position().add(mAB); + mA.position().sub(mAB); + } + } + } + } + } + } + + public static void contract(Vector mEntities, Vector3f pCenter, float pDamping) { + for (int i = 0; i < mEntities.size(); i++) { + final SpatialEntity mEntity = mEntities.get(i); + final Vector3f v = mathematik.Util.sub(mEntity.position(), pCenter); + v.scale(pDamping); + mEntity.position().sub(v); + } + } + + public static class PackingEntity + implements SpatialEntity { + + private Vector3f mPosition; + + private float mRadius; + + public PackingEntity() { + mPosition = new Vector3f(); + mRadius = 1; + } + + public float radius() { + return mRadius; + } + + public Vector3f position() { + return mPosition; + } + + public void radius(float pRadius) { + mRadius = pRadius; + } + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/ParticleTrail.java b/day3/libs/teilchen/src/teilchen/util/ParticleTrail.java new file mode 100755 index 0000000..fb3dae7 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/ParticleTrail.java @@ -0,0 +1,141 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.util; + + +import java.util.Vector; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.ShortLivedParticle; + + +public class ParticleTrail { + + private Physics _myTrailParticleSystem; + + private final Particle _myParticle; + + private final float _myInterval; + + private final Vector _myFragments; + + private final float _myFragmentLifetime; + + private float _myCurrentTime; + + private boolean _myFixState; + + private Class _myParticleClass = ShortLivedParticle.class; + + private float mTrailParticleMass = 1.0f; + + public ParticleTrail(final Physics theTrailParticleSystem, + final Particle theParticle, + float theInterval, + float theFragmentLifetime) { + _myTrailParticleSystem = theTrailParticleSystem; + _myParticle = theParticle; + _myInterval = theInterval; + _myFragmentLifetime = theFragmentLifetime; + _myFragments = new Vector(); + _myFixState = false; + } + + public void mass(float pMass) { + mTrailParticleMass = pMass; + } + + public float mass() { + return mTrailParticleMass; + } + + public void fix(boolean theFixState) { + _myFixState = theFixState; + } + + public Particle particle() { + return _myParticle; + } + + public void clear() { + _myFragments.clear(); + } + + public Vector fragments() { + return _myFragments; + } + + public void set() { + /* this would be more precise but has other issues -- _myCurrentTime -= _myInterval; */ + _myCurrentTime = 0; + final Particle myParticle = makeParticle(); + _myFragments.add(myParticle); + } + + public void loop(float theDeltaTime) { + _myCurrentTime += theDeltaTime; + + if (_myCurrentTime > _myInterval) { + set(); + } + + for (int i = 0; i < _myFragments.size(); i++) { + Particle myTrailFragment = _myFragments.get(i); + if (myTrailFragment.dead()) { + _myFragments.remove(myTrailFragment); + } + } + } + + public void setParticleClass(Class theClass) { + _myParticleClass = theClass; + } + + private static T createParticle(Class theParticleClass) { + T myParticle; + try { + myParticle = theParticleClass.newInstance(); + } catch (Exception ex) { + System.err.println(ex); + myParticle = null; + } + return myParticle; + } + + protected Particle makeParticle() { + final Particle myTrailFragment = createParticle(_myParticleClass); + myTrailFragment.mass(mTrailParticleMass); + + if (_myTrailParticleSystem != null) { + _myTrailParticleSystem.add(myTrailFragment); + } + + if (myTrailFragment instanceof ShortLivedParticle) { + ((ShortLivedParticle) myTrailFragment).setMaxAge(_myFragmentLifetime); + } + + myTrailFragment.position().set(_myParticle.position()); + myTrailFragment.fixed(_myFixState); + return myTrailFragment; + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/SpatialEntity.java b/day3/libs/teilchen/src/teilchen/util/SpatialEntity.java new file mode 100755 index 0000000..73a2918 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/SpatialEntity.java @@ -0,0 +1,33 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.util; + + +import mathematik.Vector3f; + + +public interface SpatialEntity { + + float radius(); + + Vector3f position(); +} diff --git a/day3/libs/teilchen/src/teilchen/util/StableSpringQuad.java b/day3/libs/teilchen/src/teilchen/util/StableSpringQuad.java new file mode 100755 index 0000000..d40d42b --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/StableSpringQuad.java @@ -0,0 +1,117 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.util; + + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.Spring; + + +public class StableSpringQuad { + + public Particle a; + + public Particle b; + + public Particle c; + + public Particle d; + + public Spring ab; + + public Spring bc; + + public Spring cd; + + public Spring da; + + public Spring ac; + + public Spring bd; + + /** + * this utility method creates a 'stable' shape from 4 positions. in this + * case a stable shape is created by connecting the four positions' edge + * plus two diagonals to create a stable quad.
+ * the positions should be in counter clockwise order.
+ * the positions are stored as reference which means that if you change + * either of the vectors afterwards it will also change the position of the + * connected particles. + * + * @param theParticleSystem ParticleSystem + * @param a Vector3f + * @param b Vector3f + * @param c Vector3f + * @param d Vector3f + */ + public StableSpringQuad(final Physics theParticleSystem, + final Vector3f theA, + final Vector3f theB, + final Vector3f theC, + final Vector3f theD) { + a = theParticleSystem.makeParticle(); + b = theParticleSystem.makeParticle(); + c = theParticleSystem.makeParticle(); + d = theParticleSystem.makeParticle(); + + a.setPositionRef(theA); + b.setPositionRef(theB); + c.setPositionRef(theC); + d.setPositionRef(theD); + + /* edges */ + final float mySpringConstant = 100; + final float mySpringDamping = 5; + ab = theParticleSystem.makeSpring(a, b, mySpringConstant, mySpringDamping); + bc = theParticleSystem.makeSpring(b, c, mySpringConstant, mySpringDamping); + cd = theParticleSystem.makeSpring(c, d, mySpringConstant, mySpringDamping); + da = theParticleSystem.makeSpring(d, a, mySpringConstant, mySpringDamping); + /* diagonals */ + ac = theParticleSystem.makeSpring(a, c, mySpringConstant, mySpringDamping); + bd = theParticleSystem.makeSpring(b, d, mySpringConstant, mySpringDamping); + } + + public StableSpringQuad(final Physics theParticleSystem, + final Particle pA, + final Particle pB, + final Particle pC, + final Particle pD) { + a = pA; + b = pB; + c = pC; + d = pD; + + /* edges */ + final float mySpringConstant = 500; + final float mySpringDamping = 5; + ab = theParticleSystem.makeSpring(a, b, mySpringConstant, mySpringDamping); + bc = theParticleSystem.makeSpring(b, c, mySpringConstant, mySpringDamping); + cd = theParticleSystem.makeSpring(c, d, mySpringConstant, mySpringDamping); + da = theParticleSystem.makeSpring(d, a, mySpringConstant, mySpringDamping); + /* diagonals */ + ac = theParticleSystem.makeSpring(a, c, mySpringConstant, mySpringDamping); + bd = theParticleSystem.makeSpring(b, d, mySpringConstant, mySpringDamping); + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/StableStickQuad.java b/day3/libs/teilchen/src/teilchen/util/StableStickQuad.java new file mode 100755 index 0000000..fe31a8d --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/StableStickQuad.java @@ -0,0 +1,85 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.util; + + +import mathematik.Vector3f; + +import teilchen.Particle; +import teilchen.Physics; +import teilchen.constraint.Stick; + + +public class StableStickQuad { + + public Particle a; + + public Particle b; + + public Particle c; + + public Particle d; + + public Stick ab; + + public Stick bc; + + public Stick cd; + + public Stick da; + + public Stick ac; + + public Stick bd; + + public StableStickQuad(final Physics theParticleSystem, + final Vector3f theA, + final Vector3f theB, + final Vector3f theC, + final Vector3f theD) { + a = theParticleSystem.makeParticle(); + b = theParticleSystem.makeParticle(); + c = theParticleSystem.makeParticle(); + d = theParticleSystem.makeParticle(); + + a.setPositionRef(theA); + b.setPositionRef(theB); + c.setPositionRef(theC); + d.setPositionRef(theD); + + /* edges */ + ab = new Stick(a, b); + bc = new Stick(b, c); + cd = new Stick(c, d); + da = new Stick(d, a); + theParticleSystem.add(ab); + theParticleSystem.add(bc); + theParticleSystem.add(cd); + theParticleSystem.add(da); + + /* diagonals */ + ac = new Stick(a, c); + bd = new Stick(b, d); + theParticleSystem.add(ac); + theParticleSystem.add(bd); + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/StickMan.java b/day3/libs/teilchen/src/teilchen/util/StickMan.java new file mode 100755 index 0000000..575b0e1 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/StickMan.java @@ -0,0 +1,122 @@ +package teilchen.util; + + +import mathematik.Vector3f; + +import teilchen.BasicParticle; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.MuscleSpring; +import processing.core.PApplet; +import processing.core.PGraphics; + + +public class StickMan { + + private StableSpringQuad _myQuad; + + private float _myScale; + + private BasicParticle myLeftFoot; + + private BasicParticle myRightFoot; + + private BasicParticle myLeftHand; + + private BasicParticle myRightHand; + + public StickMan(Physics theParticleSystem, float theOffset, float theScale) { + + _myScale = theScale; + + /* body */ + _myQuad = new StableSpringQuad(theParticleSystem, + new Vector3f(10 * theScale + theOffset, 50 * theScale), + new Vector3f(40 * theScale + theOffset, 50 * theScale), + new Vector3f(50 * theScale + theOffset, 0), + new Vector3f(0 + theOffset, 0)); + /* legs */ + myLeftFoot = theParticleSystem.makeParticle(new Vector3f(10 * theScale + theOffset, 100 * theScale), 0.5f); + theParticleSystem.makeSpring(_myQuad.a, myLeftFoot, 100, 0.1f); + theParticleSystem.makeSpring(_myQuad.b, myLeftFoot, 100, 0.1f); + theParticleSystem.makeSpring(_myQuad.d, myLeftFoot, 2, 1f); + + myRightFoot = theParticleSystem.makeParticle(new Vector3f(40 * theScale + theOffset, 100 * theScale), 0.5f); + theParticleSystem.makeSpring(_myQuad.a, myRightFoot, 100, 0.1f); + theParticleSystem.makeSpring(_myQuad.b, myRightFoot, 100, 0.1f); + theParticleSystem.makeSpring(_myQuad.c, myRightFoot, 2, 1f); + + /* arms */ + myRightHand = theParticleSystem.makeParticle(new Vector3f(70 * theScale + theOffset, 0), 0.1f); + theParticleSystem.makeSpring(_myQuad.c, myRightHand, 100, 0.1f); + theParticleSystem.makeSpring(_myQuad.b, myRightHand, 10, 0.1f); + + myLeftHand = theParticleSystem.makeParticle(new Vector3f(-20 * theScale + theOffset, 0), 0.1f); + theParticleSystem.makeSpring(_myQuad.d, myLeftHand, 100, 0.1f); + theParticleSystem.makeSpring(_myQuad.a, myLeftHand, 10, 0.1f); + + theParticleSystem.makeSpring(myLeftHand, myRightHand, 10, 0.1f); + + myLeftFoot.radius(7 * theScale); + myRightFoot.radius(7 * theScale); + myLeftHand.radius(20 * theScale); + myRightHand.radius(20 * theScale); + _myQuad.a.radius(7 * theScale); + _myQuad.a.radius(7 * theScale); + _myQuad.a.radius(7 * theScale); + _myQuad.a.radius(7 * theScale); + + final float myMass = 2f; + myLeftFoot.mass(myMass * theScale); + myRightFoot.mass(myMass * theScale); + myLeftHand.mass(myMass * theScale); + myRightHand.mass(myMass * theScale); + _myQuad.a.mass(myMass * theScale); + _myQuad.b.mass(myMass * theScale); + _myQuad.c.mass(myMass * theScale); + _myQuad.d.mass(myMass * theScale); + + /* make legs move */ + MuscleSpring myMuscleSpring = new MuscleSpring(myLeftFoot, myRightFoot); + myMuscleSpring.amplitude(20 * theScale); + myMuscleSpring.strength(100); + myMuscleSpring.offset((float) Math.random() * 2 * PApplet.PI); + theParticleSystem.add(myMuscleSpring); + } + + public void draw(PGraphics g) { + + g.stroke(255, 0, 0, 127); + + /* draw arms */ + g.line(myRightHand.position().x, myRightHand.position().y, + _myQuad.c.position().x, _myQuad.c.position().y); + g.line(myLeftHand.position().x, myLeftHand.position().y, + _myQuad.d.position().x, _myQuad.d.position().y); + + /* draw legs */ + g.line(myRightFoot.position().x, myRightFoot.position().y, + _myQuad.b.position().x, _myQuad.b.position().y); + g.line(myLeftFoot.position().x, myLeftFoot.position().y, + _myQuad.a.position().x, _myQuad.a.position().y); + + /* draw body */ + g.line(_myQuad.a.position().x, _myQuad.a.position().y, + _myQuad.b.position().x, _myQuad.b.position().y); + g.line(_myQuad.b.position().x, _myQuad.b.position().y, + _myQuad.c.position().x, _myQuad.c.position().y); + g.line(_myQuad.c.position().x, _myQuad.c.position().y, + _myQuad.d.position().x, _myQuad.d.position().y); + g.line(_myQuad.d.position().x, _myQuad.d.position().y, + _myQuad.a.position().x, _myQuad.a.position().y); + + /* draw head */ + g.ellipse((_myQuad.c.position().x + _myQuad.d.position().x) * 0.5f, + (_myQuad.c.position().y + _myQuad.d.position().y) * 0.5f, + 40 * _myScale, 40 * _myScale); + } + + public Particle anchor() { + return _myQuad.a; + } +} diff --git a/day3/libs/teilchen/src/teilchen/util/Util.java b/day3/libs/teilchen/src/teilchen/util/Util.java new file mode 100755 index 0000000..8dcc472 --- /dev/null +++ b/day3/libs/teilchen/src/teilchen/util/Util.java @@ -0,0 +1,198 @@ +/* + * Teilchen + * + * Copyright (C) 2013 + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + * {@link http://www.gnu.org/licenses/lgpl.html} + * + */ +package teilchen.util; + + +import mathematik.Vector3f; + +import processing.core.PMatrix3D; +import teilchen.Particle; +import teilchen.Physics; +import teilchen.force.IForce; +import teilchen.force.TriangleDeflector; +import teilchen.force.TriangleDeflectorIndexed; + +import java.util.Vector; +import teilchen.constraint.IConstraint; + + +public class Util { + + public final static void satisfyNeighborConstraints(final Vector theParticles, final float theRelaxedness) { + for (int i = 0; i < theParticles.size(); i++) { + final Particle p1 = theParticles.get(i); + for (int j = i + 1; j < theParticles.size(); j++) { + final Particle p2 = theParticles.get(j); + /* satisfy overlap */ + if (p1.position().almost(p2.position())) { + p1.position().x += 0.01f; + p2.position().x -= 0.01f; + continue; + } + /* recover bad positions */ + if (p1.position().isNaN()) { + p1.position().set(p1.old_position()); + } + if (p2.position().isNaN()) { + p2.position().set(p2.old_position()); + } + final float myDistance = p1.position().distance(p2.position()); + /* skip bad values */ + if (myDistance == 0.0f || Float.isNaN(myDistance)) { + continue; + } + final float myDesiredDistance = p1.radius() + p2.radius(); + if (myDistance < myDesiredDistance) { + final Vector3f myDiff = mathematik.Util.sub(p1.position(), p2.position()); + myDiff.scale(1.0f / myDistance); + myDiff.scale(myDesiredDistance - myDistance); + myDiff.scale(0.5f); + myDiff.scale(theRelaxedness); + p1.position().add(myDiff); + p2.position().sub(myDiff); + } + } + } + } + private static final Vector3f TMP_NORMAL = new Vector3f(); + + private static final Vector3f TMP_TANGENT = new Vector3f(); + + public final static void reflectVelocity(final Particle theParticle, + final Vector3f theNormal, + float theCoefficientOfRestitution) { + final Vector3f myVelocity = theParticle.velocity(); + /* normal */ + TMP_NORMAL.set(theNormal); + TMP_NORMAL.scale(theNormal.dot(myVelocity)); + /* tangent */ + TMP_TANGENT.sub(myVelocity, TMP_NORMAL); + /* negate normal */ + TMP_NORMAL.scale(-theCoefficientOfRestitution); + /* set reflection vector */ + myVelocity.add(TMP_TANGENT, TMP_NORMAL); + + /* also set old position */ + if (Physics.HINT_UPDATE_OLD_POSITION) { + theParticle.old_position().set(theParticle.position()); + } + } + + public final static void reflect(final Vector3f theVector, final Vector3f theNormal, final float theCoefficientOfRestitution) { + final Vector3f myNormalComponent = new Vector3f(); + final Vector3f myTangentComponent = new Vector3f(); + + /* normal */ + myNormalComponent.set(theNormal); + myNormalComponent.scale(theNormal.dot(theVector)); + /* tangent */ + myTangentComponent.sub(theVector, myNormalComponent); + /* negate normal */ + myNormalComponent.scale(-theCoefficientOfRestitution); + /* set reflection vector */ + theVector.add(myTangentComponent, myNormalComponent); + } + + public final static void reflect(final Vector3f theVector, final Vector3f theNormal) { + /* normal */ + TMP_NORMAL.set(theNormal); + TMP_NORMAL.scale(theNormal.dot(theVector)); + /* tangent */ + TMP_TANGENT.sub(theVector, TMP_NORMAL); + /* negate normal */ + TMP_NORMAL.scale(-1.0f); + /* set reflection vector */ + theVector.add(TMP_TANGENT, TMP_NORMAL); + } + + public static final Vector createTriangleDeflectors(final float[] theVertices, + final float theCoefficientOfRestitution) { + final Vector myDeflectors = new Vector(); + for (int i = 0; i < theVertices.length / 9; i++) { + final TriangleDeflector myTriangleDeflector = new TriangleDeflector(); + myTriangleDeflector.a().set(theVertices[i * 9 + 0], + theVertices[i * 9 + 1], + theVertices[i * 9 + 2]); + myTriangleDeflector.b().set(theVertices[i * 9 + 3], + theVertices[i * 9 + 4], + theVertices[i * 9 + 5]); + myTriangleDeflector.c().set(theVertices[i * 9 + 6], + theVertices[i * 9 + 7], + theVertices[i * 9 + 8]); + myTriangleDeflector.coefficientofrestitution(theCoefficientOfRestitution); + myTriangleDeflector.updateProperties(); + myDeflectors.add(myTriangleDeflector); + } + return myDeflectors; + } + + public static final Vector createTriangleDeflectorsIndexed(final float[] theVertices, + final float theCoefficientOfRestitution) { + final Vector myDeflectors = new Vector(); + for (int i = 0; i < theVertices.length / 9; i++) { + final TriangleDeflectorIndexed myTriangleDeflector = new TriangleDeflectorIndexed( + theVertices, + i * 9 + 0, + i * 9 + 3, + i * 9 + 6); + myTriangleDeflector.coefficientofrestitution(theCoefficientOfRestitution); + myTriangleDeflector.updateProperties(); + myDeflectors.add(myTriangleDeflector); + } + return myDeflectors; + } + + public static void pointAt(final PMatrix3D pResult, + final Vector3f pPosition, + final Vector3f pUpVector, /* should be normalized */ + final Vector3f pPointAtPosition) { + + /* forward */ + final Vector3f mForwardVector = mathematik.Util.sub(pPosition, pPointAtPosition); + mForwardVector.normalize(); + + /* side */ + final Vector3f mSideVector = mathematik.Util.cross(pUpVector, mForwardVector); + mSideVector.normalize(); + + /* up */ + final Vector3f mUpVector = mathematik.Util.cross(mForwardVector, mSideVector); + mUpVector.normalize(); + + if (!mSideVector.isNaN() + && !mUpVector.isNaN() + && !mForwardVector.isNaN()) { + /* x */ + pResult.m00 = mSideVector.x; + pResult.m10 = mSideVector.y; + pResult.m20 = mSideVector.z; + /* y */ + pResult.m01 = mUpVector.x; + pResult.m11 = mUpVector.y; + pResult.m21 = mUpVector.z; + /* z */ + pResult.m02 = mForwardVector.x; + pResult.m12 = mForwardVector.y; + pResult.m22 = mForwardVector.z; + } + } +}