WorldWind Sphere Line Intersection Bug? - java

I'm seeing what appears to be contradictory behavior out of WorldWind's Sphere-Line intersection logic. I create a Sphere and Line and they intersect but then the intersection returns null (scan code for comment: // *** This is where it gets whacky).
Here is what's going on visually (the line is gray it's there but hard to see):
public class WWTest extends ApplicationTemplate {
public static class VisualizationFrame extends ApplicationTemplate.AppFrame {
public VisualizationFrame() {
super(new Dimension(1200, 1024));
final Globe globe = getWwd().getModel().getGlobe();
//Create a sphere at 0,0 on the surface of the Earth wtih a 60 NMi radius
final Vec4 sphereCenter = globe.computePointFromLocation(LatLon.ZERO);
final Sphere sphere = new Sphere(sphereCenter, 111120);
// Draw the sphere
final RenderableLayer sphereLayer = new RenderableLayer();
sphereLayer.addRenderable(sphere);
final RenderableLayer pathLayer = new RenderableLayer();
// Create a line at 10k feet (3048 meters) that starts outside the sphere at (2,-2) and proceeds into the sphere at (0.5, 0.5)
final Position lineStart = Position.fromDegrees(2, -2, 3048);
final Position lineEnds = Position.fromDegrees(0.5, 0.5, 3048);
final Path asPath = new Path(lineStart, lineEnds);
pathLayer.addRenderable(asPath);
// Now that we've visualized the line, let's do some intersection math
final Vec4 lineStartsAsVec = globe.computePointFromPosition(lineStart);
final Vec4 lineEndsAsVec = globe.computePointFromPosition(lineEnds);
final Line asLine = Line.fromSegment(lineStartsAsVec, lineEndsAsVec);
// *** This is where it gets whacky - true, but no intersection?
final boolean doesIntersect = sphere.intersects(asLine);
final Intersection[] intersection = sphere.intersect(asLine);
//outputs: Intersection found: null
System.out.println(doesIntersect ? "Intersection found: " + Arrays.toString(intersection) : "No intersection, Why Not!?!?");
insertBeforeCompass(getWwd(), sphereLayer);
insertBeforeCompass(getWwd(), pathLayer);
getWwd().getView().setEyePosition(Position.fromDegrees(0, 0, 500_000));
getLayerPanel().update(getWwd());
}
}
public static void main(String[] args) {
ApplicationTemplate.start("World Wind Sphere-Line Intersection", VisualizationFrame.class);
}
}
And here are the dependencies I declared to get WorldWind into my maven project (I also did try version '2.0.0-986', but that didn't seem to help):
<dependency>
<groupId>gov.nasa</groupId>
<artifactId>worldwind</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>gov.nasa</groupId>
<artifactId>worldwindx</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.jogamp.gluegen</groupId>
<artifactId>gluegen-rt-main</artifactId>
<version>2.2.4</version>
</dependency>
<dependency>
<groupId>org.jogamp.jogl</groupId>
<artifactId>jogl-all-main</artifactId>
<version>2.2.4</version>
</dependency>
To be completely thorough, here are the code imports:
import gov.nasa.worldwind.geom.Intersection;
import gov.nasa.worldwind.geom.LatLon;
import gov.nasa.worldwind.geom.Line;
import gov.nasa.worldwind.geom.Position;
import gov.nasa.worldwind.geom.Sphere;
import gov.nasa.worldwind.geom.Vec4;
import gov.nasa.worldwind.globes.Globe;
import gov.nasa.worldwind.layers.RenderableLayer;
import gov.nasa.worldwind.render.Path;
import gov.nasa.worldwindx.examples.ApplicationTemplate;
import static gov.nasa.worldwindx.examples.ApplicationTemplate.insertBeforeCompass;
import java.awt.Dimension;
import java.util.Arrays;

If you look at the implementation of Sphere#intersect() it is expecting the line in coordinates centered at the sphere's origin (not the Earth's) which is almost certainly a bug. You should be able to do:
final Vec4 pa = lineStartsAsVec.subtract3(sphereCenter);
final Vec4 pb = lineEndsAsVec.subtract3(sphereCenter);
final Line asLine2 = Line.fromSegment(pa, pb);
final Intersection[] intersection = sphere.intersect(asLine2);
Keep in mind that the intersections returned are still in Cartesian coordinates centered at the sphere's origin, so to transform them back to World Wind Cartesian you need to do:
final Vec4 intersectionPos = intersection[0].getIntersectionPoint().add3(sphereCenter);
The implementation also considers the line to be infinitely long so it will return two points, not one.
It would be pretty straight forward to implement your own version of intersect() that works in normal coordinates and takes into account the length of the line, see here.

If you look at the Worldwind source code, specifically the intersects() and intersect() methods of the Sphere class and step through them with your code as input, you see the following:
The method:
public boolean intersects(Line line)
returns true because the distance from the sphere centre to the line is less than the radius of the sphere, as expected.
For the method:
public final Intersection[] intersect(Line line)
it turns out that the discriminant of the quadratic is less than zero (i.e. there are no real roots to the quadratic equation - two distinct complex roots).
The WorldWind API reference is here.
The specific methods involved are:
/**
* Tests for intersection with a <code>Line</code>.
*
* #param line the <code>Line</code> with which to test for intersection
*
* #return true if <code>line</code> intersects or makes a tangent with the surface of this <code>Sphere</code>
*
* #throws IllegalArgumentException if <code>line</code> is null
*/
public boolean intersects(Line line)
{
if (line == null)
{
String msg = Logging.getMessage("nullValue.LineIsNull");
Logging.logger().severe(msg);
throw new IllegalArgumentException(msg);
}
return line.distanceTo(this.center) <= this.radius;
}
and:
/**
* Obtains the intersections of this sphere with a line. The returned array may be either null or of zero length if
* no intersections are discovered. It does not contain null elements and will have a size of 2 at most. Tangential
* intersections are marked as such. <code>line</code> is considered to have infinite length in both directions.
*
* #param line the <code>Line</code> with which to intersect this <code>Sphere</code>
*
* #return an array containing all the intersections of this <code>Sphere</code> and <code>line</code>
*
* #throws IllegalArgumentException if <code>line</code> is null
*/
public final Intersection[] intersect(Line line)
{
if (line == null)
{
String message = Logging.getMessage("nullValue.LineIsNull");
Logging.logger().severe(message);
throw new IllegalArgumentException(message);
}
double a = line.getDirection().getLengthSquared3();
double b = 2 * line.selfDot();
double c = line.getOrigin().getLengthSquared3() - this.radius * this.radius;
double discriminant = Sphere.discriminant(a, b, c);
if (discriminant < 0)
return null;
double discriminantRoot = Math.sqrt(discriminant);
if (discriminant == 0)
{
Vec4 p = line.getPointAt((-b - discriminantRoot) / (2 * a));
return new Intersection[] {new Intersection(p, true)};
}
else // (discriminant > 0)
{
Vec4 near = line.getPointAt((-b - discriminantRoot) / (2 * a));
Vec4 far = line.getPointAt((-b + discriminantRoot) / (2 * a));
return new Intersection[] {new Intersection(near, false), new Intersection(far, false)};
}
}
which uses:
/**
* Calculates a discriminant. A discriminant is useful to determine the number of roots to a quadratic equation. If
* the discriminant is less than zero, there are no roots. If it equals zero, there is one root. If it is greater
* than zero, there are two roots.
*
* #param a the coefficient of the second order pronumeral
* #param b the coefficient of the first order pronumeral
* #param c the constant parameter in the quadratic equation
*
* #return the discriminant "b squared minus 4ac"
*/
private static double discriminant(double a, double b, double c)
{
return b * b - 4 * a * c;
}
in this case your code fails the:
if (discriminant < 0)
test.
It looks like I've been a bit slow in answering this question, and in the meantime it has been pointed out by Chris K that this is due to the intersect() method expecting the line coordinates to be centered at the origin of the sphere and not of Earth.
As Chris K said, this seems to be a bug and should probably be logged with the maintainers of this source code.

Related

Orbit Simulator in Java returning odd values for velocity etc. despite correct math

I am using LibGDX to make an orbit simulator (elliptical as planets possess their own initial velocity) and I have the physics mapped out like so:
public void move(float deltaTime, Planet planet) {
float deltaX = planet.getPos().x - this.pos.x;
float deltaY = planet.getPos().y - this.pos.y;
float alpha = (float) Math.toDegrees(Math.atan2(deltaY, deltaX));
float distance = (float) Math.sqrt(Math.pow(deltaX, 2) + Math.pow(deltaY, 2));
float F = G * this.m * planet.getM() / distance*distance;
this.force.x = F * MathUtils.cos(alpha);
this.force.y = F * MathUtils.sin(alpha);
this.vel.x += (this.force.x / this.m) * deltaTime;
this.vel.y += (this.force.y / this.m) * deltaTime;
this.pos.x += this.vel.x * deltaTime;
this.pos.y += this.vel.y * deltaTime;
}
The problem is that my planet wobbles around and doesn't orbit at all. I fear my calculations in the code might be wrong as the physics are definitely double-checked and correct.
Each celestial object is a planet and I have no 'Sun' classes of any type so far. Only one Planet class, which only has Getter and Setter methods, a render() method (which seems irrelevant) and the presented move() method.
I find nothing necessitates the following however I will add the parameters' values I chose for the both planets:
planet1 = new Planet(30, 1, new Vector2(300, 300));
planet2 = new Planet(70, 332000, new Vector2(400, 400));
I am also aware LibGDX won't have the x, y coordinates of my circle in the middle but rather the bottom left. Therefore I have modified that in the constructor:
this.pos = pos;
this.pos.x -= r;
this.pos.y -= r;
I have been messing around and debugging the code and realised it was a very minor mistake, a classic mistake to assume that the math library's cos() and sin() functions use degrees. They don't. They use radians and that was the whole problem all along.
Instead of:
this.force.x = F * MathUtils.cos(alpha);
this.force.y = F * MathUtils.sin(alpha);
One must do:
this.force.x = F * MathUtils.cosDeg(alpha);
this.force.y = F * MathUtils.sinDeg(alpha);
I will make sure to edit the question to emphasize this problem and solution for future viewers of it.

Ray-tracing triangles

I am writing a raytracer in java, and I was able to get tracing of spheres working, but I believe I have something wrong with how I am tracing triangles.
Here is the basic algorithm, as I understand it:
First determine if the ray even intersects the plane that the triangle is on.
Clip all points so they are on the same plane as the triangle (so to the xy plane, as an example).
Determine if the potential intersection point falls inside or out of the triangle, based on the number of polygon edges you cross when sending out a ray in an arbitrary direction along the new plane.
Now, here is my implementation of that (specifically the first point):
public Vector getIntersectionVector(Ray ray)
{
Vector planeIntersectionVector = getPlaneIntersectionVector(ray, getPlaneNormal());
if (planeIntersectionVector != null)
{
if (isIntersectionVectorInsideTriangle(planeIntersectionVector))
{
return planeIntersectionVector;
}
else
{
return null;
}
}
else
{
return null;
}
}
Where getPlaceIntersectionVector() is:
private Vector getPlaneIntersectionVector(Ray ray, Vector planeNormal)
{
double vd = planeNormal.dotProduct(ray.getDirection());
//(p_n \dot r_d) == 0, parallel. (p_n \dot r_d) > 0 Plane normal pointing away from ray.
if (vd >= 0)
{
return null;
}
double distance = planeNormal.distance(0d, 0d, 0d);
double vo = -(planeNormal.dotProduct(ray.getOrigin()) + distance);
double intersectionDistance = vo / vd;
//intersectionDistance <= 0 means the "intersection" is behind the ray, so not a real intersection
return (intersectionDistance <= 0) ? null : ray.getLocation(intersectionDistance);
}
Which basically tries to mimic this:
And this:
Where t is the distance along the ray that the point hits, ro is the origin of the ray, rd is the direction of the ray, pn refers to the plane normal of the triangle/plane, and d is the distance from the plane that the triangle is on to the origin (0,0,0)
Am I doing that wrong? When I send out the ray from the first pixel in the image (0,0), I am seeing that the intersectionDistance (or t) is almost 1100, which intuitively seems wrong to me. I would think that the intersection point would be much closer.
Here is the relevant data:
Ray origin (0,0,1), Ray Direction is roughly (0.000917, -0.4689, -0.8833).
Triangle has vertices as (-0.2, 0.1, 0.1), (-0.2, -0.5, 0.2), (-0.2, 0.1, -0.3), which makes the plane normal (-1, 0, 0).
According to my code, the Ray intersects the plane 1090 distance away, which as I mentioned before, seems wrong to me. The scene is only -1.0 to 1.0 in every direction, which means the intersection is very very far in the distance.
Am I doing the plane intersection wrong?
Please let me know where to clarify points, and if you need any more information.
The problem is this line:
double distance = planeNormal.distance(0d, 0d, 0d);
A plane is defined by a normal and a distance from the plane to the origin. The distance of a vector from the origin is the length of a vector, so what you are calculating there is just the length of the plane normal (which will always be 1.0 if it has been normalized).
The distance of the plane from the origin is an extra piece of information that needs to be passed into your function, you can't just calculate it from the normal because it's independent of it (you can can have lots of planes with normals pointing in the same direction at different distances from the origin).
So define your function something like this:
private Vector getPlaneIntersectionVector(Ray ray, Vector planeNormal, double planeDistance)
and call it something like this:
Vector planeIntersectionVector = getPlaneIntersectionVector(ray, getPlaneNormal(), getPlaneDistance());
Then you can calculate vo like this:
double vo = -(planeNormal.dotProduct(ray.getOrigin()) + planeDistance);
Slightly different approach:
Let's triangle vertices are V0, V1, V2
Edge vectors are
A = V1-V0
B = V2 - V0
Ray has parametric equation (as you wrote)
P = R0 + t * Rd
From the other side, intersection point has parametric coordinates u, v in the triangle plane
P = V0 + u * A + v * B
So you can write system of three linear equation for x, y, z coordinates and solve it for t, u, v. If determinant ius non-zero (ray is not parallel to the plane), and t >=0, and u, v, u+v lie in range 0..1, then P is inside triangle.
R0.X + t * Rd.X = V0.X + u * A.X + v * B.X
R0.Y + t * Rd.Y = V0.Y + u * A.Y + v * B.Y
R0.Z + t * Rd.Z = V0.Z + u * A.Z + v * B.Z

SurfacePlotMesh (FXyz) constructor arguments

I would like to know if I am correct with understanding the constructor argument as a Function<Point2D, Number> function.
My function which I have used for 1D charts based on the applying the variables after every step on the x axis, but there is as a parametr Point2D which contain 2 variables : x and y, if i am correct the x varriable is step which increase "0.5" for every calculations after apply the function of y.
Then what is the second parametr of generic type, the Number ?
How could I implement other functions, using the SurfacePlotMesh class. Could someone explain me a little bit how it works ? Or link the documenations ( If it exist ) ?
If you have a look at the code for SurfacePlotMesh in the FXyz library, you'll find createPlotMesh(), a method that creates the mesh for the surface, based on two coordinates on a plane grid (x, y), taken from the Point2D coordinates, and a function value (z), given by the function applied on that point.
If you have a look at the default parameters:
private static final Function<Point2D, Number> DEFAULT_FUNCTION =
p -> Math.sin(p.magnitude()) / p.magnitude();
private static final double DEFAULT_X_RANGE = 10; // -5 +5
private static final double DEFAULT_Y_RANGE = 10; // -5 +5
private static final int DEFAULT_X_DIVISIONS = 64;
private static final int DEFAULT_Y_DIVISIONS = 64;
private static final double DEFAULT_FUNCTION_SCALE = 1.0D;
what it means it that there will be a grid of 10x10 units, with 64x64 divisions. In each and every vertex (x,y) of the total 65x65 vertices, we will evaluate the function to get the value z = f(x, y), with a default scale of 1.
I.e., for the top left 2D point at (-5, -5) -> f(-5, -5) = 1.0025, so the 3D point for the mesh will be (-5, -5, 1.0025), and so on.
This picture shows a grid of 10x10 range with 20x20 divisions, and the mesh with a scale of 4 for that function.
You can change the function at any time, like:
p -> p.getX()
p -> p.getX() * p.getY()
p -> Math.cos(p.getX()) * Math.sin(p.getY())
...
as well as the other parameters (range, divisions, scale).
For the moment there is no documentation, but the code is fully available.
Also there is a sampler to run most of the samples and modify the parameters to easily check the result without recompiling all over again here.
EDIT
Based on the OP comment, for a function where there is no y dependency, a ribbon type of surface can be created by setting a very low value on y:
private void createSurface(double time) {
surface = new SurfacePlotMesh(
p-> Math.sqrt(Math.pow(Math.exp(-(Math.pow((p.getX() - time), 2))) *
(Math.cos((2 * Math.PI * (p.getX() - time)))), 2) +
Math.pow(Math.exp(-(Math.pow((p.getX() - time), 2))) *
(Math.sin((2 * Math.PI * (p.getX() - time)))), 2)),
10, 0.1, 64, 2, 2);
}
where the time parameter will be set to a fixed value or in an animation.

Gradient Descent Linear Regression in Java

This a bit of a long shot, but I wonder if someone could look at this. Am I doing Batch Gradient descent for linear regression correctly here?
It gives the expected answers for a single independent and intercept, but not for multiple independent variables.
/**
* (using Colt Matrix library)
* #param alpha Learning Rate
* #param thetas Current Thetas
* #param independent
* #param dependent
* #return new Thetas
*/
public DoubleMatrix1D descent(double alpha,
DoubleMatrix1D thetas,
DoubleMatrix2D independent,
DoubleMatrix1D dependent ) {
Algebra algebra = new Algebra();
// ALPHA*(1/M) in one.
double modifier = alpha / (double)independent.rows();
//I think this can just skip the transpose of theta.
//This is the result of every Xi run through the theta (hypothesis fn)
//So each Xj feature is multiplied by its Theata, to get the results of the hypothesis
DoubleMatrix1D hypothesies = algebra.mult( independent, thetas );
//hypothesis - Y
//Now we have for each Xi, the difference between predictect by the hypothesis and the actual Yi
hypothesies.assign(dependent, Functions.minus);
//Transpose Examples(MxN) to NxM so we can matrix multiply by hypothesis Nx1
DoubleMatrix2D transposed = algebra.transpose(independent);
DoubleMatrix1D deltas = algebra.mult(transposed, hypothesies );
// Scale the deltas by 1/m and learning rate alhpa. (alpha/m)
deltas.assign(Functions.mult(modifier));
//Theta = Theta - Deltas
thetas.assign( deltas, Functions.minus );
return( thetas );
}
There is nothing wrong in your implementation and based on your comment the problem in collinearity which you induce when generating x2. This is problematic in regression estimation.
To test your algorithm, you can generate two independent columns of random numbers. Pick a value of w0, w1 and w2 i.e. coefficients for intercept, x1 and x2 respectively. Calculate the dependent value y.
Then see if your stochastic/batch gradient decent algorithm can recover w0, w1 and w2 values
I think adding
// ALPHA*(1/M) in one.
double modifier = alpha / (double)independent.rows();
Is a bad Idea, since you're mixing gradient function with the gradient descent algorithm, it's much better to have a gradientDescent algorithm inside a public method like following in Java:
import org.la4j.Matrix;
import org.la4j.Vector;
public Vector gradientDescent(Matrix x, Matrix y, int kmax, double alpha)
{
int k=1;
Vector thetas = Vector.fromArray(new double[] { 0.0, 0.0});
while (k<kmax)
{
thetas = thetas.subtract(gradient(x, y, thetas).multiply(alpha));
k++;
}
return thetas;
}

Find delta angle to use for rotation given entity with position, initial rotation and target point to 'face toward'

I'm coding a flocking algorithm in Java but I'm stuck at a certain point (using the Ardor3D libraries, in a 2D plane).
Basically, I need to find the angle difference to add to the current rotation. If you can only get the way it should be pointing with polar coordinates with 0 degs at north and not the difference, not to worry -- I have a method which returns the angle difference taking into account the wraparound on the angle and negative angles.
At the moment, I have the following code, which clearly wouldn't work since the algorithm has no reference to the initial rotation:
long tpf = currUpdateTimeMS - lastUpdateTimeMS;
Vector2 pos = new Vector2();
rt.getPosition(pos);
double rot = pos.angleBetween(app.getAvgBoidPos(new Vector2()).normalizeLocal());
rt.setRotation(rot);
pos.addLocal(
Math.cos((rot - MathUtils.HALF_PI)) * (tpf / 10f),
Math.sin((rot - MathUtils.HALF_PI)) * (tpf / 10f)
);
rt.setPosition(pos);
super.updateLogic();
Updated code (not working, from first answer):
long tpf = currUpdateTimeMS - lastUpdateTimeMS;
//rt.setRotation(rt.getRotation() + ((tpf / (ROT_SPEED / 2f)) % 360));
Vector2 avgpos = app.getAvgBoidPos(new Vector2());
Vector2 pos = rt.getPosition(new Vector2());
avgpos.subtractLocal(pos);
double angleRads = rt.getRotation() * FastMath.DEG_TO_RAD;
double rot = MathUtils.acos((
(avgpos.getX() * MathUtils.sin(angleRads)
) +
(avgpos.getY() * MathUtils.cos(angleRads)
)) / ((Math.pow(avgpos.getX(), 2) + Math.pow(avgpos.getY(), 2)) * 0.5));
double adegdiff = rot * FastMath.RAD_TO_DEG;
rt.setRotation(rt.getRotation() - adegdiff);
double newrot = rt.getRotation();
pos.addLocal(
Math.cos((newrot - MathUtils.HALF_PI)) * (tpf / 10f),
Math.sin((newrot - MathUtils.HALF_PI)) * (tpf / 10f)
);
rt.setPosition(pos);
super.updateLogic();
Another modification based on the other answer:
long tpf = currUpdateTimeMS - lastUpdateTimeMS;
//rt.setRotation(rt.getRotation() + ((tpf / (ROT_SPEED / 2f)) % 360));
Vector2 avgpos = app.getAvgBoidPos(new Vector2());
Vector2 pos = rt.getPosition(new Vector2());
avgpos.subtractLocal(pos);
double rot = pos.angleBetween(
app.getAvgBoidPos(new Vector2()).normalizeLocal()
) - (rt.getRotation() * MathUtils.DEG_TO_RAD);
rt.setRotation(rt.getRotation() - (rot * MathUtils.RAD_TO_DEG));
double newrot = rt.getRotation();
pos.addLocal(
Math.cos((newrot - MathUtils.HALF_PI)) * (tpf / 10f),
Math.sin((newrot - MathUtils.HALF_PI)) * (tpf / 10f)
);
rt.setPosition(pos);
super.updateLogic();
I'm not really too good at Maths problems, so code would be helpful rather than formulas :)
Inputs
Current position of entity
Current rotation of entity (polar-oriented) in degrees
Output
Degrees or radians to add or subtract to current rotation
... or degrees or radians expressed as polar-oriented angle
Thanks in advance if you can help :)
Chris
You can use the dot product to determine the cosine of the angle (in radians) between the current orientation and the point you want to face. Assume the agent doing the viewing is locate at the origin and oriented to face some direction given by the angle θ relative to the Y-Axis (i.e. 0 degrees is "up" or "north"). You want to find the angular difference θ' between that direction and facing a point (x, y). That is given by:
θ' = cos-1[(x*sin(θ) + y*cos(θ)) / sqrt(x2 + y2)]
Subtracting θ' from θ will orient the agent towards the target.
If the agent is not at the origin, simply subtract the position of the agent from the object to view to bring it into the form above.
Slightly off topic, but you might find the particle swarm and wander code in our effects package (ardor3d-effects) interesting as well.
They can be found in the ardor svn, or here:
http://ardorlabs.trac.cvsdude.com/Ardor3Dv1/browser/trunk/ardor3d-effects/src/main/java/com/ardor3d/extension/effect/particle/
heres an implementation on how to find the angle beetween two vectors with a common origin. this has been hacked together based on the algorithm described there:
http://www.wikihow.com/Find-the-Angle-Between-Two-Vectors
public class DeltaDoodle {
private double delta(ColumnVector v1,ColumnVector v2) throws Exception{
double sp=scalarProduct(v1,v2);
double magV1=magnitude(v1);
double magV2=magnitude(v2);
return Math.acos(sp/(magV1*magV2)) * (180/Math.PI);
}
private double scalarProduct(ColumnVector a, ColumnVector b) {
return (a.x*b.x) + (a.y*b.y);
}
private double magnitude(ColumnVector a){
return Math.sqrt((a.x*a.x) + (a.y*a.y));
}
public static void main(String[] args) {
DeltaDoodle v=new DeltaDoodle();
try {
System.out.println("angle: " + v.delta(new ColumnVector(5, 5), new ColumnVector(1,1)));
} catch (Exception e) {
e.printStackTrace();
}
}
}
public class ColumnVector {
public final double x, y;
public ColumnVector(double x1, double x2) {
this.x = x1;
this.y = x2;
}
}
hope that helps...
If I understand these functions correctly, this might just work:
Vector2 pos = new Vector2();
rt.getPosition(pos);
double rot = pos.angleBetween(app.getAvgBoidPos(new Vector2()).normalizeLocal()) - rt.getRotation();
P.S. Forgot to mention: this rot is intended to be the angle difference. Rotate the entity by this much and it should be pointing toward the target.
EDIT:
Thanks, the code does help (I had misconstrued angleBetween). Let me try again:
Here is the vector from the entity to the point (pardon me if I get the syntax wrong, I don't know java):
Vector2 pos = new Vector2();
rt.getPosition(pos);
Vector2 direction = app.getAvgBoidPos(new Vector2());
direction.subtractLocal(pos);
Now we normalize it to get a unit vector pointing toward the point, and take the angle difference:
double rot = rt.getRotation().angleBetween(direction.normalizeLocal())

Categories

Resources