I've been looking into getting an object on a two dimensional plane to follow a smooth curve defined by several control points.From what I've found, I'm looking for a Catmull-Rom-Spline.
I've been using LibGDX for my project, and it has its own Catmull-Rom-Spline implementation but I'm having trouble wrapping my head around how it works, as I've had trouble finding documentation or other source code implementing Catmull-Rom-Splines using LibGDX.
I'm looking for either an explanation of the LibGDX Catmull-Rom-Spline implementation or another way to implement a smooth path that implements control points using Catmull-Rom-Splines or another method. All I'm looking for is the ability to generate a path and pass back the x and y coordinates of a point on that path. If anyone has any suggestions or pointers, it would be appreciated. Thanks.
The libgdx Path classes (including CatmullRomSpline) are suitable for both 2D and 3D. So when creating a CatmullRomSpline, you must specify which Vector (Vector2 or Vector3) to use:
CatmullRomSpline<Vector2> path = new CatmulRomSpline<Vector2> ( controlpoints, continuous );
For example:
float w = Gdx.graphics.getWidth();
float h = Gdx.graphics.getHeight();
Vector2 cp[] = new Vector2[]{
new Vector2(0, 0), new Vector2(w * 0.25f, h * 0.5f), new Vector2(0, h), new Vector2(w*0.5f, h*0.75f),
new Vector2(w, h), new Vector2(w * 0.75f, h * 0.5f), new Vector2(w, 0), new Vector2(w*0.5f, h*0.25f)
};
CatmullRomSpline<Vector2> path = new CatmullRomSpline<Vector2>(cp, true);
Now you can get the location on the path (ranging from 0 to 1) using the valueAt method:
Vector2 position = new Vector2();
float t = a_vulue_between_0_and_1;
path.valueAt(position, t);
For example:
Vector2 position = new Vector2();
float t = 0;
public void render() {
t = (t + Gdx.graphics.getDeltaTime()) % 1f;
path.valueAt(position, t);
// Now you can use the position vector
}
Here's an example: https://github.com/libgdx/libgdx/blob/master/tests/gdx-tests/src/com/badlogic/gdx/tests/PathTest.java
Related
Hi I am attempting to build OBB's into my 3d java game using lwjgl. Currently I am just attempting to rotate the OBB around using matrix4f's and testing it by rendering the points. So, when I render it, with its xyx=0,0,0 and its angle on the x axis =1 it will rotate fine. But when i move the y axis up say y=5 the rotation will no longer go around the center.
I tried fixing this with translation but It doesnt work. Im also wondering if there is a way to access opengl's push/pop and rotate methods to get those variables for my points because opengl rotate does it perfectly.
This is my OBB class:
public OBB(float x, float y, float z, float angleX, float angleY, float angleZ, float sizeX, float sizeY, float sizeZ){
this.x=x;
this.y=y;
this.z=z;
this.angleX=angleX;
this.angleY=angleY;
this.angleZ=angleZ;
this.sizeX=sizeX;
this.sizeY=sizeY;
this.sizeZ=sizeZ;
posUBR = new Vector3f(x-sizeX,y+sizeY,z+sizeZ);//UpperBackRight
posUBL = new Vector3f(x-sizeX,y+sizeY,z-sizeZ);//UpperBackLeft
posUFL = new Vector3f(x+sizeX,y+sizeY,z-sizeZ);//UpperForLeft
posUFR = new Vector3f(x+sizeX,y+sizeY,z+sizeZ);//UpperForRight
posLBR = new Vector3f(x-sizeX,y-sizeY,z+sizeZ);//LowerBackRight
posLBL = new Vector3f(x-sizeX,y-sizeY,z-sizeZ);//LowerBackLeft
posLFL = new Vector3f(x+sizeX,y-sizeY,z-sizeZ);//LowerForLeft
posLFR = new Vector3f(x+sizeX,y-sizeY,z+sizeZ);//LowerForRight
posUBR=rotMat(posUBR);
posUBL=rotMat(posUBL);
posUFL=rotMat(posUFL);
posUFR=rotMat(posUFR);
posLBR=rotMat(posLBR);
posLBL=rotMat(posLBL);
posLFL=rotMat(posLFL);
posLFR=rotMat(posLFR);
}
This is my rotation method:
public Vector3f rotMatrix(Vector3f point) {
Matrix4f rotationMatrix = new Matrix4f();
rotationMatrix.m00 = point.x;
rotationMatrix.m10 = point.y;
rotationMatrix.m20 = point.z;
rotationMatrix.translate(new Vector3f(-x,-y,-z));
rotationMatrix.rotate(angleX,new Vector3f(1,0,0));
rotationMatrix.rotate(angleY,new Vector3f(0,1,0));
rotationMatrix.rotate(angleZ,new Vector3f(0,0,1));
rotationMatrix.translate(new Vector3f(x,y,-z));
return new Vector3f(rotationMatrix.m00, rotationMatrix.m10, rotationMatrix.m20);
}
public void rotate(){
posUBR=rotMatrix(posUBR);
posUBL=rotMatrix(posUBL);
posUFL=rotMatrix(posUFL);
posUFR=rotMatrix(posUFR);
posLBR=rotMatrix(posLBR);
posLBL=rotMatrix(posLBL);
posLFL=rotMatrix(posLFL);
posLFR=rotMatrix(posLFR);
}
My render function is a bit long to put in here but it basically renders a cube.
Sorry all I needed to do was this set to origin function:
public void setToOrigin(){
posUBR = new Vector3f(0-sizeX,0+sizeY,0+sizeZ);
posUBL = new Vector3f(0-sizeX,0+sizeY,0-sizeZ);
posUFL = new Vector3f(0+sizeX,0+sizeY,0-sizeZ);
posUFR = new Vector3f(0+sizeX,0+sizeY,0+sizeZ);
posLBR = new Vector3f(0-sizeX,0-sizeY,0+sizeZ);
posLBL = new Vector3f(0-sizeX,0-sizeY,0-sizeZ);
posLFL = new Vector3f(0+sizeX,0-sizeY,0-sizeZ);
posLFR = new Vector3f(0+sizeX,0-sizeY,0+sizeZ);
}
I would like to rotate an object to face a point which I'm have a bit of of trouble with.
So I'm starting with an object that has a base at zero and is aligned on the y axis.
I would like to rotate it so that the top of the object is facing the destination
My process so far is to:
Given axis A
find the distance between my position and my look position: D
create a direction vector: V = D.normalize()
find the right vector: R = A cross D
find the up vector: U = D cross R
find the angle between up and direction: ANGLE = acos((U dot D) / (U.length * D.length))
rotate by angle scaled by direction on each axis
here is the code representation of that. I'm not sure what exactly is wrong with this I've worked it out on paper and to my knowledge this approach should work but the results are completely incorrect when drawn. If anyone sees any flaws and could point me in the right direction it would be great.
Vector3 distance = new Vector3(from.x, from.y, from.z).sub(to.x, to.y, to.z);
final Vector3 axis = new Vector3(0, 1, 0);
final Vector3 direction = distance.clone().normalize();
final Vector3 right = (axis.clone().cross(direction));
final Vector3 up = (distance.clone().cross(right));
float angle = (float) Math.acos((up.dot(direction)/ (up.length() * direction.length())));
bondObject.rotateLocal(angle, direction.x , direction.y, direction.z);
The basic idea here is as follows.
Determine which way the object is facing: directionA
Determine which way the object should be facing: directionB
Determine the angle between those directions: rotationAngle
Determine the rotation axis: rotationAxis
Here's the modified code.
Vector3 distance = new Vector3(from.x, from.y, from.z).sub(to.x, to.y, to.z);
if (distance.length() < DISTANCE_EPSILON)
{
//exit - don't do any rotation
//distance is too small for rotation to be numerically stable
}
//Don't actually need to call normalize for directionA - just doing it to indicate
//that this vector must be normalized.
final Vector3 directionA = new Vector3(0, 1, 0).normalize();
final Vector3 directionB = distance.clone().normalize();
float rotationAngle = (float)Math.acos(directionA.dot(directionB));
if (Math.abs(rotationAngle) < ANGLE_EPSILON)
{
//exit - don't do any rotation
//angle is too small for rotation to be numerically stable
}
final Vector3 rotationAxis = directionA.clone().cross(directionB).normalize();
//rotate object about rotationAxis by rotationAngle
im trying to build a 3D Model, by building dynamically 3D models and translate them to where i need them.
Im starting with a basic model, trying to to achieve what is on the picture bellow. I want to dynamically build two cylinders, and the X,Y,Z of the TOP of my cylinder will be the same X,Y,Z of the BOTTOM of the second Cylinder, like the picture bellow:
For now i have this code:
public static void main(String[] args) throws FileNotFoundException, IOException {
int height = 10;
int radius = 1;
int angle = 0;
BranchGroup objRoot = new BranchGroup();
Cylinder cylinder;
Vector3f last_coordinates = new Vector3f(0f,0f,0f);
TransformGroup transf_group_cylinder = null;
//---- Working ok -----/
//build cylinder
cylinder = new Cylinder(radius, height);
transf_group_cylinder = createTransformGroup_Cylinder(new Vector3f(0f,0f,0f),angle);
transf_group_cylinder.addChild(cylinder);
objRoot.addChild(transf_group_cylinder);
last_coordinates = calculateLastPoint(height/2, angle);
System.out.println(last_coordinates);
//----------------------------//
//build 2nd cylinder
cylinder = new Cylinder(radius, height);
transf_group_cylinder = createTransformGroup_Cylinder(last_coordinates, Math.PI/2);
transf_group_cylinder.addChild(cylinder);
objRoot.addChild(transf_group_cylinder);
OBJWriter objWriter = new OBJWriter("myObj.obj");
objWriter.writeNode(objRoot);
objWriter.close();
}
private static Vector3f calculateLastPoint(int height, int angle) {
float x = (float) (height * Math.sin(angle));
float y = (float) (height * Math.cos(angle));
return new Vector3f(0, x, y);
}
private static TransformGroup createTransformGroup_Cylinder(
Vector3f last_coordinates, double angle) {
TransformGroup transf_group = new TransformGroup();
//position the model
Transform3D transform_origin = new Transform3D();
transform_origin.setTranslation(new Vector3f(0, 0, 0));
// set model in horizontal position
Transform3D transf_horizontal = new Transform3D();
transf_horizontal.rotZ(Math.PI / 2);
transform_origin.mul(transf_horizontal);
// rotate object
Transform3D angleRotation = new Transform3D();
angleRotation.rotX(angle);
transform_origin.mul(angleRotation);
Transform3D transform_xyz = new Transform3D();
transform_xyz.setTranslation(last_coordinates);
transform_origin.mul(transform_xyz); // set Transform for
transf_group.setTransform(transform_origin);
return transf_group;
}
With this code im achieving this:
My first cylinder is ok, but my 2nd cylinder is not placed in a proper place.
I can add any value for the size and angle values, so i need to calculate this two values in a dynamically way.
Can someone help solving this translation problem?
Thank you in advance.
The first step here is to give each cylinder a different color to allow you to see which one is which.
Next: When you create a cylinder, then it's centered at the origin. Since you want to chain them at the end point, you need to move them accordingly: First, you need to move the cylinder (or its transformation matrix) by -half its height to virtually move the "cylinder origin" to it's end.
The next step is that you need to apply the same transformation matrix to the end point (this time plus a full cylinder height), so it lines up with the actual end point.
That said, I would suggest you create a helper function that can create a cylinder between two points. This would allow you to say:
Point endPoint = cylinder(new Point(-1,.5,0), new Point(0,.5,0))
cylinder(endPoint, new Point(0,-.5,0))
...
or even create a helper function which accepts a list of points and creates all the cylinders between them.
I'm trying to write a little game with third-person-camera and I'm just wondering about gluLookAt function. It works with Opengl 1.1, but I'm using 3.2 one so I need something that can return Matrix4f to me, but I didn't find anything on the Internet except some code in C++ and I found it extremely hard to translate it to the LWJGL (their API's are not the same, no sir). For example, I tried to remake this code (This link) :
// ----------------------------------------------------
// View Matrix
//
// note: it assumes the camera is not tilted,
// i.e. a vertical up vector (remmeber gluLookAt?)
//
void setCamera(float posX, float posY, float posZ,
float lookAtX, float lookAtY, float lookAtZ) {
float dir[3], right[3], up[3];
up[0] = 0.0f; up[1] = 1.0f; up[2] = 0.0f;
dir[0] = (lookAtX - posX);
dir[1] = (lookAtY - posY);
dir[2] = (lookAtZ - posZ);
normalize(dir);
crossProduct(dir,up,right);
normalize(right);
crossProduct(right,dir,up);
normalize(up);
float aux[16];
viewMatrix[0] = right[0];
viewMatrix[4] = right[1];
viewMatrix[8] = right[2];
viewMatrix[12] = 0.0f;
viewMatrix[1] = up[0];
viewMatrix[5] = up[1];
viewMatrix[9] = up[2];
viewMatrix[13] = 0.0f;
viewMatrix[2] = -dir[0];
viewMatrix[6] = -dir[1];
viewMatrix[10] = -dir[2];
viewMatrix[14] = 0.0f;
viewMatrix[3] = 0.0f;
viewMatrix[7] = 0.0f;
viewMatrix[11] = 0.0f;
viewMatrix[15] = 1.0f;
setTranslationMatrix(aux, -posX, -posY, -posZ);
multMatrix(viewMatrix, aux);
}
I can understand everything until "float aux[16]", then it just gets messy in my mind, especially in the end.
Can someone make it clear for me? Maybe someone already made "gluLookAt-clone" or something?
EDIT:
Thank you, Brett, now I must understand how to express that in code). You say that "aux" is a matrix, but we give it only 3 floats, so its better be a vector, BUT if it is a vector, so how do I multiply it with 4x4 ViewMatrix? And I cant find a way to just fill Matrix4f with numbers, there is no methods in lib to do that (most likely that because I'm noob and I can't find it, but hey, I really can't)
FINAL EDIT:
Finally I got it to work. I just wasn't understanding full matrix stuff that was required. Here is final working code, if someone interested(I guess not but whatever)). To deal with it, don't forget to setup projection matrix in the begining.
void setCamera(float posX, float posY, float posZ,
float lookAtX, float lookAtY, float lookAtZ) {
Vector3f dir = new Vector3f(lookAtX - posX, lookAtY - posY, lookAtZ - posZ);
Vector3f up = new Vector3f(0, 1f, 0);
Vector3f right = new Vector3f();
dir.normalise();
Vector3f.cross(dir,up,right);
right.normalise();
Vector3f.cross(right,dir,up);
up.normalise();
Matrix4f aux = new Matrix4f();
viewMatrix = new Matrix4f();
viewMatrix.m00 = right.getX();
viewMatrix.m01 = right.getY();
viewMatrix.m02 = right.getZ();
viewMatrix.m03 = 0.0f;
viewMatrix.m10 = up.getX();
viewMatrix.m11 = up.getY();
viewMatrix.m12 = up.getZ();
viewMatrix.m13 = 0.0f;
viewMatrix.m20 = -dir.getX();
viewMatrix.m21 = -dir.getY();
viewMatrix.m22 = -dir.getZ();
viewMatrix.m23 = 0.0f;
viewMatrix.m30 = 0.0f;
viewMatrix.m31 = 0.0f;
viewMatrix.m32 = 0.0f;
viewMatrix.m33 = 1.0f;
//setup aux as a translation matrix by placing positions in the last column
aux.m30 = -posX;
aux.m31 = -posY;
aux.m32 = -posZ;
//multiplication(in fact translation) viewMatrix with aux
Matrix4f.mul(viewMatrix, aux, viewMatrix);
}
I have a first-person camera class that I use (on OpenGL 3.2) which handles movement: x, y and z positions as well as pitch, yaw and roll. The way that I do this is update positions each cycle and a part of rendering I apply these updates from the camera by creating a new view matrix and sending it as a uniform to my vertex shader.
Here is the method that accomplishes this:
#Override
public void applyTranslations(int uniformLocation) {
viewMatrix = new Matrix4f();
Matrix4f.rotate(MatrixUtils.degreesToRadians(pitch), new Vector3f(1, 0, 0), viewMatrix, viewMatrix);
Matrix4f.rotate(MatrixUtils.degreesToRadians(yaw), new Vector3f(0, 1, 0), viewMatrix, viewMatrix);
Matrix4f.rotate(MatrixUtils.degreesToRadians(roll), new Vector3f(0, 0, 1), viewMatrix, viewMatrix);
Matrix4f.translate(new Vector3f(-x, -y, -z), viewMatrix, viewMatrix);
viewMatrix.store(matrix44Buffer); matrix44Buffer.flip();
glUniformMatrix4(uniformLocation, false, matrix44Buffer);
}
Where uniformLocation is the location of my viewMatrix uniform within my shaders.
Steps are to:
Create a new 4x4 matrix
Apply rotations for x, y and z axes
Apply translation for the x, y and z axes
Send matrix to shaders
The code is just populating the matrix as described in the gluLookAt() documentation.
Up until float aux[16], the code is creating an orthonormal basis (3 mutually perpendicular vectors as 'axes'). The properties of orthogonal rotation matrices allow viewMatrix elements to be set directly. aux is then (presumably) populated as a translation matrix, and the transforms are then concatenated with multMatrix.
I've been trying for the past few days to make a working implementation of a virtual trackball for the user interface for a 3D graphing-like program. But I'm having trouble.
Looking at the numbers and many tests the problems seems to be the actual concatenation of my quaternions but I don't know or think so. I've never worked with quaternions or virtual trackballs before, this is all new to me. I'm using the Quaternion class supplied by JOGL. I tried making my own and it worked (or at least as far a I know) but it was a complete mess so I just went with JOGL's.
When I do not concatenate the quaternions the slight rotations I see seem to be what I want, but of course It's hard when it's only moving a little bit in any direction. This code is based off of the Trackball Tutorial on the OpenGL wiki.
When I use the Quaternion class's mult (Quaternion q) method the graph hardly moves (even less than not trying to concatenate the quaternions).
When I tried Quaternionclass'sadd (Quaternion q)` method for the fun of it I get something that at the very least rotates the graph but not in any coherent way. It spazzes out and rotates randomly as I move the mouse. Occasionally I'll get quaternions entirely filled with NaN.
In my code I will not show either of these, I'm lost with what to do with my quaternions. I know I want to multiply them because as far as I'm aware that's how they are concatenated. But like I said I've had no success, I'm assuming the screw up is somewhere else in my code.
Anyway, my setup has a Trackball class with a public Point3f projectMouse (int x, int y) method and a public void rotateFor (Point3f p1, Point3f p2), Where Point3f is a class I made. Another class called Camera has a public void transform (GLAutoDrawable g) method which will call OpenGL methods to rotate based on the trackball's quaternion.
Here's the code:
public Point3f projectMouse (int x, int y)
{
int off = Screen.WIDTH / 2; // Half the width of the GLCanvas
x = x - objx_ - off; // obj being the 2D center of the graph
y = off - objy_ - y;
float t = Util.sq(x) + Util.sq(y); // Util is a class I made with
float rsq = Util.sq(off); // simple some math stuff
// off is also the radius of the sphere
float z;
if (t >= rsq)
z = (rsq / 2.0F) / Util.sqrt(t);
else
z = Util.sqrt(rsq - t);
Point3f result = new Point3f (x, y, z);
return result;
}
Here's the rotation method:
public void rotateFor (Point3f p1, Point3f p2)
{
// Vector3f is a class I made, I already know it works
// all methods in Vector3f modify the object's numbers
// and return the new modify instance of itself
Vector3f v1 = new Vector3f(p1.x, p1.y, p1.z).normalize();
Vector3f v2 = new Vector3f(p2.x, p2.y, p2.z).normalize();
Vector3f n = v1.copy().cross(v2);
float theta = (float) Math.acos(v1.dot(v2));
float real = (float) Math.cos(theta / 2.0F);
n.multiply((float) Math.sin(theta / 2.0F));
Quaternion q = new Quaternion(real, n.x, n.y, n.z);
rotation = q; // A member that can be accessed by a getter
// Do magic on the quaternion
}
EDIT:
I'm getting closer, I found out a few simple mistakes.
1: The JOGL implementation treats W as the real number, not X, I was using X for real
2: I was not starting with the quaternion 1 + 0i + 0j + 0k
3: I was not converting the quaternion into an axis/angle for opengl
4: I was not converting the angle into degrees for opengl
Also as Markus pointed out I was not normalizing the normal, when I did I couldn't see much change, thought it's hard to tell, he's right though.
The problem now is when I do the whole thing the graph shakes with a fierceness like you would never believe. It (kinda) moves in the direction you want it to, but the seizures are too fierce to make anything out of it.
Here's my new code with a few name changes:
public void rotate (Vector3f v1, Vector3f v2)
{
Vector3f v1p = v1.copy().normalize();
Vector3f v2p = v2.copy().normalize();
Vector3f n = v1p.copy().cross(v2p);
if (n.length() == 0) return; // Sometimes v1p equals v2p
float w = (float) Math.acos(v1p.dot(v2p));
n.normalize().multiply((float) Math.sin(w / 2.0F));
w = (float) Math.cos(w / 2.0F);
Quaternion q = new Quaternion(n.x, n.y, n.z, w);
q.mult(rot);
rot_ = q;
}
Here's the OpenGL code:
Vector3f p1 = tb_.project(x1, y1); // projectMouse [changed name]
Vector3f p2 = tb_.project(x2, y2);
tb_.rotate (p1, p2);
float[] q = tb_.getRotation().toAxis(); // Converts to angle/axis
gl.glRotatef((float)Math.toDegrees(q[0]), q[1], q[2], q[3]);
The reason for the name changes is because I deleted everything in the Trackball class and started over. Probably not the greatest idea, but oh well.
EDIT2:
I can say with pretty good certainty that there is nothing wrong with projecting onto the sphere.
I can also say that as far as the whole thing goes it seems to be the VECTOR that is the problem. The angle looks just fine, but the vector seems to jump around.
EDIT3:
The problem is the multiplication of the two quaternions, I can confirm that everything else works as expected. Something goes whacky with the axis during multiplication!
The problem is the multiplication of the two quaternions, I can confirm that everything else works as expected. Something goes whacky with the axis during multiplication!
You are absolutely correct!! I just recently submitted a correct multiplication and Jogamp has accepted my change. They had incorrect multiplication on mult(quaternion).
I am sure if you get the latest jogl release, it'll have the correct mult(Quaternion)
I did it!
Thanks to this C++ implementation I was able to develop a working trackball/arcball interface. My goodness me, I'm still not certain what the problem was, but I rewrote everything and even wrote my own Quaternions class and suddenly the whole thing works. I also made a Vectors class for vectors. I had a Vector3f class before but the Quaternions and Vectors classes are full of static methods and take in arrays. To make it easy to do vector computations on quaternions and vice versa. I will link the code for those two classes below, but only the Trackball class will be show here.
I made those two classes pretty quickly this morning so if there are any mathematical errors, well, uh, oops. I only used what I needed to use and made sure they were correct. These classes are below:
Quaternions: http://pastebin.com/raxS4Ma9
Vectors: http://pastebin.com/fU3PKZB9
Here is my Trackball class:
public class Trackball
{
private static final float RADIUS_ = Screen.DFLT_WIDTH / 2.0F;
private static final int REFRESH_ = 50;
private static final float SQRT2_ = (float) Math.sqrt(2);
private static final float SQRT2_INVERSE_ = 1.0F / SQRT2_;
private int count_;
private int objx_, objy_;
private float[] v1_, v2_;
private float[] rot_;
public Trackball ()
{
v1_ = new float[4];
v2_ = new float[4];
rot_ = new float[] {0, 0, 0, 1};
}
public void click (int x, int y)
{
v1_ = project(x, y);
}
public void drag (int x, int y)
{
v2_ = project(x, y);
if (Arrays.equals(v1_, v2_)) return;
float[] n = Vectors.cross(v2_, v1_, null);
float[] o = Vectors.sub(v1_, v2_, null);
float dt = Vectors.len(o) / (2.0F * RADIUS_);
dt = dt > 1.0F ? 1.0F : dt < -1.0F ? -1.0F : dt;
float a = 2.0F * (float) Math.asin(dt);
Vectors.norm_r(n);
Vectors.mul_r(n, (float) Math.sin(a / 2.0F));
if (count_++ == REFRESH_) { count_ = 0; Quaternions.norm_r(rot_); }
float[] q = Arrays.copyOf(n, 4);
q[3] = (float) Math.cos(a / 2.0F);
rot_ = Quaternions.mul(q, rot_, rot_);
}
public float[] getAxis ()
{
return Quaternions.axis(rot_, null);
}
public float[] project (float x, float y)
{
x = RADIUS_ - objx_ - x;
y = y - objy_ - RADIUS_;
float[] v = new float[] {x, y, 0, 0};
float len = Vectors.len(v);
float tr = RADIUS_ * SQRT2_INVERSE_;
if (len < tr)
v[2] = (float) Math.sqrt(RADIUS_ * RADIUS_ - len * len);
else
v[2] = tr * tr / len;
return v;
}
}
You can see there's a lot of similarities from the C++ example. Also I'd like to note there is no method for setting the objx_ and objy_ values yet. Those are for setting the center of the graph which can be moved around. Just saying, so you don't scratch your head about those fields.
The cross-product of two normalized vectors is not normalized itself. It's length is sin(theta). Try this instead:
n = n.normalize().multiply((float) Math.sin(theta / 2.0F));