The problem is that when rotating my 3D cube on more than one axes, it distorts weirdly roughly halfway through. I am using the JOML math library for matrices.
// This is the model matrix for the rotation of a textured cube
Matrix4f model = new Matrix4f();
model.identity();
model.rotate((float)(glfwGetTime() * Math.toRadians(50.0f)), new Vector3f(0.5f, 1.0f, 0.0f), model);
// Other matrices for coordinate system
Matrix4f view = new Matrix4f();
view.identity();
view.translate(new Vector3f(0.0f, 0.0f, -3.0f), view);
Matrix4f projection = new Matrix4f();
projection.identity();
projection.perspective((float)Math.toRadians(45.0f), 800.0f / 600.0f, 0.1f, 100.0f); // FOV is 45
This is a gif of the distortion:
The main problem is that your rotation axis (0.5f, 1.0f, 0.0f) is not unit/normalized, (as is also required by its JavaDoc)
Parameters:
axis - the rotation axis (needs to be normalized)
To solve the problem and still use a matrix, you simply need to normalize the rotation axis.
Also (but this is irrelevant to the error):
JOML matrices are identity by default after instantiation - you do not need to call identity() on them)
you can omit supplying model as the argument to the dest parameter of rotate()
So:
// This is the model matrix for the rotation of a textured cube
Matrix4f model = new Matrix4f();
model.rotate((float)(glfwGetTime() * Math.toRadians(50.0f)),
new Vector3f(0.5f, 1.0f, 0.0f).normalize());
There are 2 mistakes in your code:
First: you try to update 2 axis at once.
Doing this will cause the model to scale as it rotates.
Second: you don't use 1.0f when defining what axis you want to rotate. This aswell causes the model to scale.
The way Matrix4f.rotate(float angleInRadiants, Vector3f(x, y, z)) works is it will rotate the axis specified in the the vector by the specified angleInRadians.
This is the correct way to rotate both axis:
model
.rotate((float)(glfwGetTime() * Math.toRadians(50.0f)), new Vector3f(0.0f, 1.0f, 0.0f), model)
.rotate(((float)(glfwGetTime() * Math.toRadians(50.0f)) / 2), new Vector3f(0.1f, 0.0f, 0.0f), model);
A better way to do rotation is quaternions.
You can create a new Quaternionf object, set it's angles and rotate the model matrix using it.
float someAngleInRads = (float) Math.toRadians(20f * glfwGetTime());
Quaternionf quaternionf = new Quaternionf()
.rotateAxis(someAngleInRads, new Vector3f(0, 1, 0))
.rotateAxis(someAngleInRads / 2, new Vector3f(1, 0, 0));
model.rotate(quaternionf);
You could also set the angles for the quaternion this way:
Quaternionf quaternionf = new Quaternionf().rotateXYZ(Math.toRadians(someAngleInRads / 2), Math.toRadians(someAngleInRads), Math.toRadians(0f));
Related
I created a simple dynamic body from a PolygonShape and rendering it as a PolygonSprite rendered by a PolygonSpriteBatch. The rendering works fine, but the physics is not. The translation due to velocity works well, but when I set angular velocity or apply torque the body "orbits" around a point while rotating on its origin too. The problem isn't the origin, as while debugging I noticed that the body's position is also changing. The only rotation shouldn't make the body translate, right?
Here's how it rotates. I've only set angular velocity.
The linear velocity is always equal to 0 as I checked during debugging, but the position changes (which doesn't make any sense), so it should not be a rendering problem caused by a wrong rotation origin.
Here's where I create the body with the polygon.
public DrawableBody createFullBody(float[] vertices, Body body, Texture tex, Vector2 coord){
//in our example: vertices = new float[]{0.0f, 0.0f, 0.0f, 1f, 1f, 1f, 1f, 0.0f};
DrawableBody out = new DrawableBody(); //a class that contains Body and PolygonSprite
ShortArray indices = triangulate(vertices); //uses EarClippingTriangulator
PolygonShape shape = new PolygonShape();
shape.set(vertices);
FixtureDef fixtureDef = new FixtureDef();
fixtureDef.shape = shape;
fixtureDef.density = 1f;
fixtureDef.restitution = 0.9f;
Fixture fixture = body.createFixture(fixtureDef);
shape.dispose(); //this is useless now, so we can dispose it.
PolygonRegion region = new PolygonRegion(new TextureRegion(tex), vertices, indices.toArray());
PolygonSprite sprite = new PolygonSprite(region);
body.setTransform(coord, 0);
sprite.setPosition(coord.x, coord.y);
out.body = body;
out.poly = sprite;
return out;
}
And that's how I render the square:
public void render(PolygonSpriteBatch batch, float delta){
Vector2 pos = body.getPosition(); //this changes even if velocity is zero?!?
Vector2 size = model.robotSize; //this is Vector2(0.1f, 0.1f)
float angle = body.getAngle();
d_body.poly.setPosition(pos.x - size.x / 2.0f, pos.y - size.y / 2.0f);
d_body.poly.setSize(size.x, size.y);
d_body.poly.setOrigin(size.x / 2.0f, size.y / 2.0f);
d_body.poly.setRotation(angle);
batch.draw(d_body.poly.getRegion(),
d_body.poly.getX(), d_body.poly.getY(),
d_body.poly.getOriginX(), d_body.poly.getOriginY(),
d_body.poly.getWidth(), d_body.poly.getHeight(),
1.0f, 1.0f,
d_body.poly.getRotation());
}
I'm struggling with this issue for two days now, so any help would really be appreciated.
How i make camera in my lwjgl 3D java application?
I try use glRotate and glTranslatef, but this move only objects, and i need move scene.
Same i try use
glLoadMatrixf(new float[]{
50, 50, 50, 50,
50, 50, 50, 50,
-75, 50, 50, 50,
100, 100, 100, 100
});
But I don’t quite understand how it works, and i see white screen
What solotion i can use for my task?
In OpenGL there is no camera. To "move the camera", you have to move the objects in the opposite direction instead. For example, instead of moving the camera forward, you would move the objects backward.
If you want to make your first view matrix, then start with gluLookAt.
With this handy Legacy OpenGL utility function, you can define a view matrix by a position (eye), a target point (target) and an up vector (up):
(See also Java Code Examples for org.lwjgl.util.glu.GLU.gluLookAt())
GLU.gluLookAt(eye.x, eye.y, eye.z, target.x, target.y, target.z, up.x, up.y, up.z);
The view space is the local system which is defined by the point of view onto the scene.
The position of the view, the line of sight and the upwards direction of the view, define a coordinate system relative to the world coordinate system. The objects of a scene have to be drawn in relation to the view coordinate system, to be "seen" from the viewing position. The inverse matrix of the view coordinate system is named the view matrix. This matrix transforms from world coordinates to view coordinates.
Additionally you well need either an Orthographic or Perspective projection matrix.
The former matrix can be defined by glOrtho
(See also Java Code Examples for org.lwjgl.opengl.GL11.glOrtho())
GL11.glOrtho(0, width, height, 0, 1, -1);
and the later by gluPerspective
(See also Java Code Examples for org.lwjgl.util.glu.GLU.gluPerspective())
GLU.gluPerspective(45.0f, wRatio, (float) near, (float) far);
The projection matrix describes the mapping from 3D points of a scene, to 2D points of the viewport. The projection matrix transforms from view space to the clip space. The coordinates in the clip space are transformed to the normalized device coordinates (NDC) in the range (-1, -1, -1) to (1, 1, 1) by dividing with the w component of the clip coordinates.
In legacy OpenGL there exist different current matrices. The projection matrix should be set to the current GL_PROJECTION matrix and the view matrix to the current GL_MODELVIEW matrix. See glMatrixMode.
e.g.:
float width = ...; // width of the window
float height = ...; // height of the window
Vector3f eye = ...; // camera position
Vector3f target = ...; // camera target
Vector3f up = ...; // camera up vector
float ratio = 1.0f * width / height;
GL11.glViewport(0, 0, (int) w, (int) h);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(45.0f, ratio , 0.1f, 100.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GLU.gluLookAt(eye.x, eye.y, eye.z, target.x, target.y, target.z, up.x, up.y, up.z);
Instead of GLU.gluPerspective, a perspective projection matrix can be set as follows:
float width = ...; // width of the window
float height = ...; // height of the window
float fov_y = 45.0f; // filed of view in degrees (y axis)
float n = 0.1f; // near plane
float f = 100.0f; // far plane
float a = width / height;
float ta = Math.tan(Math.radians(fov_y) / 2.0f);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
glLoadMatrixf(new float[]{
1.0f/(ta*a), 0.0f, 0.0f, 0.0f,
0.0f, 1.0f/ta, 0.0f, 0.0f,
0.0f, 0.0f, -(f+n)/(f-n), -1.0f,
0.0f, 0.0f, -2.0f*f*n/(f-n), 0.0f
});
Instead of using a GLU.gluLookAt a view matrix can be set by glTranslate and glRoatate:
float distance = 10.0f; // distance to object
float pitch = 0.0f; // pitch in degrees
float yaw = 0.0f; // yaw in degrees
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glRotatef(yaw, 0.0f, 1.0f, 0.0f);
GL11.glRotatef(pitch, 1.0f, 0.0f, 0.0f);
GL11.glTranslatef(0.0f, 0.0f, -distance);
The question change a bit, I figured out how to rotate around a single axis
I want to rotate a box around the Y axis using an angle.
The box has a size, and a Vector3f to signal the rotation.
To rotate the box correctly what I do is rotate the origin position then rotate the origin position plus the size, and use those two references to render the box.
However this rotation does not work correctly and causes rendering artifacts.
This is my code to rotate the positions:
Matrix4f matrix = new Matrix4f();
// Rotate the origin position
Vector3f pos = new Vector3f(new Vector3f(blockX, blockY, blockZ));
matrix.m03 = pos.x;
matrix.m13 = pos.y;
matrix.m23 = pos.z;
Vector3f rot = new Vector3f(new Vector3f(0, 1f, 0f));
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
Vector3f locationMin = new Vector3f(matrix.m03, matrix.m13, matrix.m23);
// Rotate the position with the size
// Top left back is the position of the block
Vector3f sizeRot = new Vector3f(new Vector3f(blockX + size, blockY + size, blockZ + size));
matrix = new Matrix4f();
matrix.m03 = sizeRot.x;
matrix.m13 = sizeRot.y;
matrix.m23 = sizeRot.z;
rot = new Vector3f(new Vector3f(0, 1f, 0f));
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
Vector3f locationMax = new Vector3f(matrix.m03, matrix.m13, matrix.m23);
// Then here I use the locationMax and the locationMin to render the cube
What could be wrong with this code? Is the logic I am using to rotate the box correct? as in rotate the origin position then rotate the origin position plus the size..
EDIT: I released that rotating after translating is stupid so instead I just rotated the locationMax which is not translated (it is only the size) then I translated and I still get the same result (Graphical Artifacts).
New Code:
float rx = blockX, ry = blockY, rz = blockZ;
Matrix4f matrix = new Matrix4f();
Vector3f rot = new Vector3f(0, 1f, 0f);
matrix = new Matrix4f();
matrix.m03 = size;
matrix.m13 = size;
matrix.m23 = size;
Matrix4f.rotate((float) Math.toRadians(45f), rot, matrix, matrix);
matrix.translate(new Vector3f(rx, ry, rz), matrix);
float mx = matrix.m03;
float my = matrix.m13;
float mz = matrix.m23;
// Here is use rx, ry, rz and mx, my, mz to render the box
============ * I figured it out (See below)* =============
EDIT:
This is what I ended up doing:
// Origin point
Vector4f a = new Vector4f(blockX, blockY, blockZ, 1);
// Rotate a matrix 45 degrees
Matrix4f mat = new Matrix4f();
mat.rotate((float) Math.toRandians(45f), new Vector3f(
0, 1f, 0), mat);
/* Transform the matrix to each point */
Vector4f c = new Vector4f(size.x, 0, size.z, 1);
Matrix4f.transform(mat, c, c);
Vector4f.add(c, a, c);
Vector4f b = new Vector4f(size.x, 0, 0, 1);
Matrix4f.transform(mat, b, b);
Vector4f.add(b, a, b);
Vector4f d = new Vector4f(0, 0, size.z, 1);
Matrix4f.transform(mat, d, d);
Vector4f.add(d, a, d);
// Here is use a, b, c, and d to render the box.
The problem with this is that I want to rotate around all axises and not only around the Y axis. This makes the code very long and unreadable and There are a lot of bugs when I try to rotate around all axises.
Update Question:
How do I take the above code and make it so I can rotate around all 3 axises. I want to do this so I can have a billboard that will always face the camera.
This is how I calculate the angle between the camera and the object:
Vector3f angle = new Vector3f();
// Calculate the distance between camera and object
Vector3f.sub(game.getCamera().getLocation(),
new Vector3f(blockX, blockY, blockZ), angle);
// Calculate the angle around the Y axis.
float vectorAngle = (float) ((float) Math.atan2(angle.z, angle.x) * -1 + (Math.PI / 2.0f));
Billboards are a very common application of computer graphics (as I'm sure you've noticed, since you're asking the question!)
Ultimately I think you are over complicating the problem, based on:
as in rotate the origin position then rotate the origin position plus the size..
For computer graphics, the most common transformations are Scaling, Translating, and Rotating, and you do these in an order to achieve a desired effect (traditionally you scale, then rotate about the origin, then translate the vertex's position).
Additionally, you will have three main matrices to render a model in 3d: World Matrix, View Matrix, and Projection Matrix. I believe you are having misunderstandings of transforming from Model Space to World Space.
Graphics TRS and Matrix info. If you are having conceptual problems, or this answer is insufficient, I highly recommend looking at this link. I have yet to find a better resource explaining the fundamentals of computer graphics.
So right at the moment, you have your three angles (in degrees, in a Vector3) corresponding to the angle difference in the X,Y, and Z coordinate spaces from your billboard and your camera. With this information, we generate the View matrix by first gathering all of our matrix transformations in one place.
I'm going to assume that you already have your Translation and Scaling matrices, and that they both work. This means that we only need to generate our Rotation matrix, and then transform that matrix with the scaling matrix, and then transforming that matrix by our translation matrix.
X Rotation Matrix
Y Rotation Matrix
Z Rotation Matrix
(Images taken from CodingLabs link above)
So you will generate these three matrices, using the X,Y, and Z angles you calculated earlier, and then transform them to consolidate them into a single matrix, transform that matrix by the scaling matrix, and then transform that matrix by the translation matrix. Now you have your awesome matrix that, when you multiply a a vertex by it, will transform that vertex into the desired size, rotation, and position.
So you transform every single vertex point by this generated matrix.
And then after that, you should be done! Using these techniques will hopefully simplify your code greatly, and set you on the right path :)
So now how about some code?
//I do not guarantee that this code compiles! I did not write it in an IDE nor did I compile it
float angleToRotX = 180f;
float angleToRotY = 90f;
float angleToRotZ = 0f;
// example vertex
Vector4f vertex = new Vector4f(0, 1, 0, 1);
// Rotate vertex's X coordinates by the desired degrees
Matrix4f rotationXMatrix = new Matrix4f();
rotationXMatrix.rotX(angleToRotX);
Matrix4f rotationYMatrix = new Matrix4f();
rotationYMatrix.rotY(angleToRotY);
Matrix4f rotationZMatrix = new Matrix4f();
rotationZMatrix.rotZ(angleToRotZ);
//now let's translate it by 1.5, 1, 1.5 in the X,Y,Z directions
Matrix4f translationMatrix = new Matrix4f();
translationMatrix.setTranslate(new Vector3f(1.5, 1, 1.5));
/*
Now we have our three rotational matrices. So we multiply them (transform them) to get a single matrix to transform all of the points in this model to the desired world coordinates
*/
Matrix4f rotationMatrix = new Matrix4f();
rotationMatrix.mul(rotationXMatrix);
rotationMatrix.mul(rotationYMatrix);
rotationMatrix.mul(rotationZMatrix);
Matrix4f worldMatrix = translationMatrix;
worldMatrix.mul(rotationMatrix);
//now worldMatrix, when applied to a vertex, will rotate it by X,Y,Z degrees about the origin of it's model space, and then translate it by the amount given in translationMatrix
worldMatrix.transform(vertex);
//now vertex should be (1.5, 0, 1.5, 1) with (x,y,z,1)
Now this code could really be simplified, and it is excessively verbose. Try it out! I don't have java downloaded on my machine, but I grabbed the methods from the java documentation Here
Here is an image of what is happening (again, taking from coding labs):
(Advanced Info: Quaternions. These are really cool way of orienting a model in 3d space, however I don't quite understand them to the degree I need to in order to explain it to someone else, and I also believe that your problem is more fundamental)
You could generate the matrix without much hassle. The OpenGL matrix looks like the following:
|lx,ux,vx,px| - lx,ly,lz = the left vector
|ly,uy,vy,py| - ux,uy,uz = the up vector
|lz,uz,vz,pz| - vx,vy,vz = the view vector
|0 ,0 ,0 ,1 | - px,py,pz = the translation
All you need to do, is set px,py,pz to the position of your box in the world,
your view vector to the normalized(camera position - box position), your up comes straight from your camera, and the left is calculated via normalized cross product. It's also good practice to reconstruct the up vector, after left one is derived (by another cross product). That's all there's to it.
My solution aims to save you some time coding, rather than explain everything in detail. Hope that is useful to someone.
I am attempting to have a 2D HUD which has icons that track the location on the screen of 3D objects behind the HUD in a 3D environment.
Reasoning: Sometimes you cannot see a 3D object (too far away or off screen) but you still want to know where it is.
Issue: 3D scene is using a perspective matrix to transform it, giving it depth (z-axis), the HUD is strictly 2D (xy-plane). Because of the depth, the 2D HUD cannot properly track objects when they are farther/closer away.
What I want: A way to get a 2D Vector [(x,y) pos] of where to put an icon so that it is centered where the 3D object in the background would be.
Example of all objects in an xy-plane (z=0):
You can see that as the objects get farther away from the center, the Icon (circle thing in white) is more off center.
Example of objects with increasing depths (farther from center == deeper):
You can see that the HUD thinks 3D objects are in the same plane still.
Pseudo-Code:
.getPos() gets the Vector (x,y,z)
lookAtObj = Object.getPos() - camera.getPos() // lookAt vector from camera to the object
icon.pos = Orthogonal Component of lookAtObj on camera.get_lookAt()
My Perspective Matrix:
// Function call in the OpenGL draw() method
FloatMatrix proj = FloatMatrix.getPerspectiveMatrix( this.fov, this.width, this.height, 0.1f, 200.0f );
// Function
public static FloatMatrix getPerspectiveMatrix( Double fov, float w, float h, float near, float far ){
float asp = w/h;
float fov_cos = (float) Math.cos( fov / 2.0d );
float fov_sin = (float) Math.sin( fov / 2.0d );
float fov_cot = fov_cos/fov_sin;
float a_0 = fov_cot/asp;
float a_3 = (far + near)/(near-far);
float a_43 = (2.0f * far * near)/(near-far);
float[] an = {
a_0, 0.0f, 0.0f, 0.0f,
0.0f, fov_cot, 0.0f, 0.0f,
0.0f, 0.0f, a_3, -1.0f,
0.0f, 0.0f, a_43, 0.0f,
};
return new FloatMatrix( an, 4, 4 );
}
This is pretty straightforward. You can use gluProject. It will take a given modelview, projection, and viewport transform, and a 3D point, and apply the inverse and spit out a 2D point in window coordinates for you (apologies for minor typos, just typing this here):
double myX = ..., myY = ..., myZ = ...; // your object's 3d coordinates
double[] my2DPoint = new double[2]; // will contain 2d window coords when done
double[] modelview = new double[16];
double[] projection = new double[16];
int[] viewport = new int[4];
gl.glGetDoublev(GL2.GL_MODELVIEW_MATRIX, modelview, 0);
gl.glGetDoublev(GL2.GL_PROJECTION_MATRIX, projection, 0);
gl.glGetIntegerv(GL2.GL_VIEWPORT, viewport, 0);
glu.gluProject(myX, myY, myZ, modelview, 0, projection, 0,
viewport, 0, my2DPoint, 0);
// now my2DPoint[0] is window x, and my2DPoint[1] is window y
After you do this, you'll have your 3D point in 2D window coordinates. Then simply switch your projection over to a 2D orthogonal projection, in window pixels, and draw your HUD in 2D space.
For performance, if you have multiple HUD items to draw per frame; just get the modelview/projection/viewport once per frame (or, even better, invalidate your cached ones if you change them and re-query only as needed) and reuse them in subsequent calls to gluProject.
The following code puts a cube at (0, 0, 0) and another at (0, .5, .5) and each cube is (.5, .5, .5) in dimension. I'm trying to rotate the view that the screen gets to one like this but instead I get this view . Also, I realize I got the colors backwards.
Anyway, this is my code so far:
import com.sun.j3d.utils.geometry.*;
import com.sun.j3d.utils.universe.*;
import javax.media.j3d.*;
import javax.vecmath.*;
public class Positioning {
private Color3f lightBlue;
private Color3f aquaGreen;
private Color3f white;
private Color3f teal;
private BranchGroup group;
private SimpleUniverse universe;
public Positioning() {
lightBlue = new Color3f(0.0f, 0.749019608f, 1.0f);
aquaGreen = new Color3f(0.439215686f, 0.858823529f, 0.576470588f);
white = new Color3f(1.0f, 1.0f, 1.0f);
teal = new Color3f(0.196078431f, 0.6f, 0.8f);
universe = new SimpleUniverse();
group = new BranchGroup();
addCube(0.5f, 0.5f, 0.5f, new Vector3f(0.0f, 0.0f, 0.0f), lightBlue);
addCube(0.5f, 0.5f, 0.5f, new Vector3f(0.5f, 0.0f, 0.5f), aquaGreen);
//add light
DirectionalLight light1 = new DirectionalLight(white, new Vector3f(0.0f, 7.0f, -12.0f));
light1.setInfluencingBounds(new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0));
group.addChild(light1);
//look at the right spot
Transform3D lookAt = new Transform3D();
lookAt.lookAt(new Point3d(0.0, 0.0, 3.0), new Point3d(0.0, 0.0, 0.0), new Vector3d(1.0, 1.0, 0.0));
lookAt.invert();
universe.getViewingPlatform().getViewPlatformTransform().setTransform(lookAt);
universe.addBranchGraph(group);
}
public void addCube(float x, float y, float z, Vector3f position, Color3f color) {
TransformGroup tg = new TransformGroup();
Transform3D trans = new Transform3D();
Appearance app = new Appearance();
Material mat = new Material();
mat.setDiffuseColor(color);
mat.setSpecularColor(color);
app.setMaterial(mat);
Box b = new Box(x, y, z, app);
//move into position and add to the branch group
trans.setTranslation(position);
tg.setTransform(trans);
tg.addChild(b);
group.addChild(tg);
}
public static void main(String[] args) {
new Positioning();
}
}
So right now the canvas is black and I think it might be my positioning on the lookAt function. I'm also not exactly for sure what the up vector is for. Any ideas on how to fix this?
I'm not familiar with Java but usually you can set up a view matrix using some sort of "lookAt" function. A quick look at the docs came up with this.
BTW, setNominalViewingTransform only translates along the z-axis so the screenshot you showed is what I would expect to see. You are correct to try to set the view transform yourself.
Edit
As far as the up direction for the lookAt function is concerned this is just a way of controlling the roll of the camera. In other words by specifying the eye point and the centre point (the point the camera is looking at) you have only defined a direction. The camera could still rotate 360 degrees on that axis. If you want to look at things the right way up then just specify a vector in the direction of "up" in your system - if that is y then it would be (0,1,0). If you wanted to look at things upside down then it would be (0,-1,0).
Note that you don't have to make sure that the "up" vector is perpendicular to the direction defined by eye and centre. As long as it's not parallel to that direction then the method should automatically just use the component of your supplied "up" vector that is perpendicular to the direction.
Edit2:
Based on your edits it looks as if you have put in a position for the "up" vector rather than a direction. It should just be the vector (0,1,0). Having said that it still won't fix your problem as an incorrect "up" vector just means that the camera might end up rolled around on its own axis so that it's upside-down, on its side, etc., but it won't affect the direction.
Therefore there must be something wrong with the eye and centre positions or the matrix is still not inverted. Your edit for the invert() looks wrong as you haven't called it on your lookAt Transform3D but I assume that's just a typo. when you updated the question?
I would try a simpler viewing angle to start with. Just try to look along the z-axis with something like
Transform3D lookAt = new Transform3D();
lookAt.lookAt( new Point3d( 0.0, 0.0, 1.0 )
, new Point3d( 0.0, 0.0, 0.0 )
, new Vector3d( 0.0, 1.0, 0.0) );
lookAt.invert();
What happens with that?
If you still get black then try changing the eye point's position along the z-axis, perhaps try 2.0, 3.0 and then a few negative values too.
The other possibility is that your camera is looking in the right direction but the objects are being culled due to frustum clipping. You might want to check the documentation to see what the default clip planes are set to. This might show up in the example above when you change the eye position along the z-axis. If you can see your objects for some values of z but not others then it's probably a clipping problem.
Let me know how you get on.