use of spacegraph.space2d.phys.common.Vec2 in project narchy by automenta.
the class PolygonShape method set.
/**
* Create a convex hull from the given array of points. The count must be in the range [3,
* Settings.maxPolygonVertices]. This method takes an arraypool for pooling.
*
* @param verts
* @param num
* @warning the points may be re-ordered, even if they form a convex polygon.
* @warning collinear points are removed.
*/
public final PolygonShape set(final Tuple2f[] verts, final int num) {
assert (3 <= num && num <= Settings.maxPolygonVertices);
// Create the convex hull using the Gift wrapping algorithm
// http://en.wikipedia.org/wiki/Gift_wrapping_algorithm
// Find the right most point on the hull
int i0 = 0;
float x0 = verts[0].x;
for (int i = 1; i < num; ++i) {
float x = verts[i].x;
if (x > x0 || (x == x0 && verts[i].y < verts[i0].y)) {
i0 = i;
x0 = x;
}
}
int[] hull = new int[Settings.maxPolygonVertices];
int m = 0;
int ih = i0;
while (true) {
hull[m] = ih;
int ie = 0;
for (int j = 1; j < num; ++j) {
if (ie == ih) {
ie = j;
continue;
}
Tuple2f r = pool1.set(verts[ie]).subbed(verts[hull[m]]);
Tuple2f v = pool2.set(verts[j]).subbed(verts[hull[m]]);
float c = Tuple2f.cross(r, v);
if (c < 0.0f) {
ie = j;
}
// Collinearity check
if (c == 0.0f && v.lengthSquared() > r.lengthSquared()) {
ie = j;
}
}
++m;
ih = ie;
if (ie == i0) {
break;
}
}
this.vertices = m;
// Copy vertices.
for (int i = 0; i < vertices; ++i) {
if (vertex[i] == null) {
vertex[i] = new Vec2();
}
vertex[i].set(verts[hull[i]]);
}
Tuple2f edge = pool1;
for (int i = 0; i < vertices; ++i) {
final int i1 = i;
final int i2 = i + 1 < vertices ? i + 1 : 0;
edge.set(vertex[i2]).subbed(vertex[i1]);
assert (edge.lengthSquared() > Settings.EPSILON * Settings.EPSILON);
Tuple2f.crossToOutUnsafe(edge, 1f, normals[i]);
normals[i].normalize();
}
// Compute the polygon centroid.
computeCentroidToOut(vertex, vertices, centroid);
return this;
}
use of spacegraph.space2d.phys.common.Vec2 in project narchy by automenta.
the class PolygonShape method computeMass.
public void computeMass(final MassData massData, float density) {
assert (vertices >= 3);
final Tuple2f center = pool1;
center.setZero();
float area = 0.0f;
float I = 0.0f;
// pRef is the reference point for forming triangles.
// It's location doesn't change the result (except for rounding error).
final Vec2 s = pool2;
s.setZero();
// This code would put the reference point inside the polygon.
for (int i = 0; i < vertices; ++i) {
s.addLocal(vertex[i]);
}
s.scaled(1.0f / vertices);
final float k_inv3 = 1.0f / 3.0f;
final Tuple2f e1 = pool3;
final Tuple2f e2 = pool4;
for (int i = 0; i < vertices; ++i) {
// Triangle vertices.
e1.set(vertex[i]).subbed(s);
e2.set(s).negated().added(i + 1 < vertices ? vertex[i + 1] : vertex[0]);
final float D = Tuple2f.cross(e1, e2);
final float triangleArea = 0.5f * D;
area += triangleArea;
// Area weighted centroid
center.x += triangleArea * k_inv3 * (e1.x + e2.x);
center.y += triangleArea * k_inv3 * (e1.y + e2.y);
final float ex1 = e1.x, ey1 = e1.y;
final float ex2 = e2.x, ey2 = e2.y;
float intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2;
float inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2;
I += (0.25f * k_inv3 * D) * (intx2 + inty2);
}
// Total mass
massData.mass = density * area;
// Center of mass
assert (area > Settings.EPSILON);
center.scaled(1.0f / area);
massData.center.set(center).added(s);
// Inertia tensor relative to the local origin (point s)
massData.I = I * density;
// Shift to center of mass then to original body origin.
massData.I += massData.mass * (Tuple2f.dot(massData.center, massData.center));
}
use of spacegraph.space2d.phys.common.Vec2 in project narchy by automenta.
the class CarefulRover method newTorso.
@Override
protected Body newTorso() {
PolygonShape shape = new PolygonShape();
Vec2[] vertices = { new Vec2(3.0f, 0.0f), new Vec2(-1.0f, +2.0f), new Vec2(-1.5f, 0), new Vec2(-1.0f, -2.0f) };
shape.set(vertices, vertices.length);
// shape.m_centroid.set(bodyDef.position);
BodyDef bd = new BodyDef();
bd.linearDamping = (linearDamping);
bd.angularDamping = (angularDamping);
bd.type = BodyType.DYNAMIC;
bd.position.set(0, 0);
Body torso = getWorld().createBody(bd);
Fixture f = torso.createFixture(shape, mass);
f.setRestitution(restitution);
f.setFriction(friction);
initSensors(torso);
initMotors(torso);
return torso;
}
use of spacegraph.space2d.phys.common.Vec2 in project narchy by automenta.
the class Rover method feelMotion.
@Override
protected void feelMotion() {
// radians per frame to angVelocity discretized value
float xa = torso.getAngularVelocity();
float angleScale = 1.50f;
float angVelocity = (float) (Math.log(Math.abs(xa * angleScale) + 1f)) / 2f;
float maxAngleVelocityFelt = 0.8f;
if (angVelocity > maxAngleVelocityFelt) {
angVelocity = maxAngleVelocityFelt;
}
// if (angVelocity < 0.1) {
// feltAngularVelocity.set("rotated(" + RoverEngine.f(0) + "). :|: %0.95;0.90%");
// //feltAngularVelocity.set("feltAngularMotion. :|: %0.00;0.90%");
// } else {
// String direction;
// if (xa < 0) {
// direction = sim.angleTerm(-MathUtils.PI);
// } else /*if (xa > 0)*/ {
// direction = sim.angleTerm(+MathUtils.PI);
// }
// feltAngularVelocity.set("rotated(" + RoverEngine.f(angVelocity) + "," + direction + "). :|:");
// // //feltAngularVelocity.set("<" + direction + " --> feltAngularMotion>. :|: %" + da + ";0.90%");
// }
float linVelocity = torso.getLinearVelocity().length();
linearVelocity.observe(linVelocity);
Vec2 currentPosition = torso.getWorldCenter();
if (!positions.isEmpty()) {
Vec2 movement = currentPosition.sub(positions.poll());
double theta = Math.atan2(movement.y, movement.x);
motionAngle.observe((float) theta);
}
positions.addLast(currentPosition.clone());
// feltOrientation.set("oriented(" + sim.angleTerm(torso.getAngle()) + "). :|:");
//
// if (linVelocity == 0)
// feltSpeed.set("moved(0). :|:");
// else
// feltSpeed.set("moved(" + (lvel < 0 ? "n" : "p") + "," + RoverEngine.f(linVelocity) + "). :|:");
// String motion = "<(" + RoverEngine.f(linVelocity) + ',' + sim.angleTerm(torso.getAngle()) + ',' + RoverEngine.f(angVelocity) + ") --> motion>. :|:";
// );
facingAngle.observe(angVelocity);
// nar.inputDirect(nar.task("<facing-->[" + + "]>. :|:"));
nar.input(nar.task("<A-->[w" + Sim.angleTerm(torso.getAngle()) + "]>. :|:"));
// System.out.println(" " + motion);
// feltSpeed.set(motion);
// feltSpeed.set("feltSpeed. :|: %" + sp + ";0.90%");
// int positionWindow1 = 16;
/*if (positions.size() >= positionWindow1) {
Vec2 prevPosition = positions.removeFirst();
float dist = prevPosition.sub(currentPosition).length();
float scale = 1.5f;
dist /= positionWindow1;
dist *= scale;
if (dist > 1.0f) {
dist = 1.0f;
}
feltSpeedAvg.set("<(*,linVelocity," + Rover2.f(dist) + ") --> feel" + positionWindow1 + ">. :\\:");
}*/
}
use of spacegraph.space2d.phys.common.Vec2 in project narchy by automenta.
the class Spider method init.
@Override
public void init(Sim p) {
this.sim = p;
// ix, iy, 1.0f, m);
Body base = sim.create(new Vec2(ix, iy), sim.circle(torsoRadius), BodyType.DYNAMIC);
float da = (float) ((Math.PI * 2.0) / arms);
float a = 0;
for (int i = 0; i < arms; i++) {
float ax = (float) (ix + (Math.cos(a) * torsoRadius));
float ay = (float) (iy + (Math.sin(a) * torsoRadius));
addArm(base, ax, ay, a, armSegments, armLength, armWidth);
a += da;
}
// //base's eyes
// int n = numRetinasPerSegment;
// for (float z = 0; z < n; z++) {
//
// float ba = z * (float) (Math.PI * 2.0 / ((float) n));
// retinas.add(new Retina(brain, base, new Vector2(0, 0), ba, (float) initialVisionDistance, retinaLevels));
//
// brain.addOutput(new Thruster(base, ba));
// }
//
//
// brainWiring.wireBrain(brain);
//
// new BrainReport(brain);
}
Aggregations