Computing Mouse Position to 3d Space - OpenGL - java

I'm trying to create a ray to that translates my mouse coordinates to 3d world coordinates.
Cx = Mx / screenWidth * 2 - 1
Cy = -( My / screenHeight * 2 - 1 )
vNear = InverseViewProjectionMatrix * ( Cx, Cy, -1, 1 )
VFar = InverseViewProjectionMatrix * ( Cx, Cy, 1, 1 )
vNear /= vNear.w
vFar /= vFar.w
After testing the ray's vFar always appears to come from the same general direction
It seems like I need to add the camera perspective as I would expect vFar to always be behind my camera.
I'm not entirely sure how that should be added in. Here's my test code.
public void mouseToWorldCordinates(Window window,Camera camera, Vector2d mousePosition){
float normalised_x = (float)((mousePosition.x / (window.getWidth()*2)) -1);
float normalised_y = -(float)((mousePosition.y / (window.getHeight()*2)) -1);
Vector4f mouse = new Vector4f(normalised_x,normalised_y,-1,1);
Matrix4f projectionMatrix = new Matrix4f(transformation.getProjectionMatrix()).invert();
Matrix4f mouse4f = new Matrix4f(mouse,new Vector4f(),new Vector4f(),new Vector4f());
Matrix4f vNear4f = projectionMatrix.mul(mouse4f);
Vector4f vNear = new Vector4f();
vNear4f.getColumn(0,vNear);
mouse.z = 1f;
projectionMatrix = new Matrix4f(transformation.getProjectionMatrix()).invert();
mouse4f = new Matrix4f(mouse,new Vector4f(),new Vector4f(),new Vector4f());
Matrix4f vFar4f = projectionMatrix.mul(mouse4f);
Vector4f vFar = new Vector4f();
vFar4f.getColumn(0,vFar);
vNear.div(vNear.w);
vFar.div(vFar.w);
lines[0] = vNear.x;
lines[1] = vNear.y;
lines[2] = vNear.z;
lines[3] = vFar.x;
lines[4] = vFar.y;
lines[5] = vFar.z;
}

The computation of normalised_x and normalised_y is wrong. Normalized device coordinates are in range [-1.0, 1.0]:
float normalised_x = 2.0f * (float)mousePosition.x / (float)window.getWidth() - 1.0f;
float normalised_y = 1.0f - 2.0f * (float)mousePosition.y / (float)window.getHeight();

Related

Scaling of a quad is incorrect after resizing the window. How to fix?

If I try to render a square with the same scaling for x and y without resizing the window everything is fine. But after resizing the window there is no longer a square rendered. Instead, you can see a rectangle, even though I am recalculating the projection matrix and passing the matrix to the shader every time the window's width or height changes.
With a different width and height, the scaling of a square is incorrect. Changing the size of the window in my code without resizing the window does not change the scaling.
I have no idea where the error is. Maybe I missed something.
Coordinates:
float[] positions = new float[] {0, 1, 0, 0, 1, 1, 1, 0};
Calculating the projection matrix:
public static void createProjectionMatrix() {
Vector2f windowSize = DisplayManager.getWindowSize();
float aspectRatio = windowSize.x / windowSize.y;
float halfWidth = 1.0f;
float halfHeight = halfWidth / aspectRatio;
float left = -halfWidth;
float right = halfWidth;
float bottom = -halfHeight;
float top = halfHeight;
float far = -1f;
float near = 1f;
Matrix4f matrix = new Matrix4f();
matrix.setIdentity();
matrix.m00 = 2f / (right - left);
matrix.m11 = 2f / (top - bottom);
matrix.m22 = -2f / (far - near);
matrix.m32 = (far + near) / (far - near);
matrix.m30 = (right + left) / (right - left);
matrix.m31 = (top + bottom) / (top - bottom);
projectionMatrix = matrix;
}
Calculation the transformation (Vector2f worldScale is not used):
private Vector2f getDisplayCoords(Vector2f percentage) {
Vector2f v = DisplayManager.getWindowSize();
return new Vector2f(v.x * percentage.x, v.y * percentage.y);
}
public void loadTransformationMatricies() {
Vector2f displaySize = getDisplayCoords(size);
Vector2f displayPos = getDisplayCoords(position);
Vector2f display = DisplayManager.getWindowSize();
Vector2f worldPos = Mouse.getWorldPos(displayPos);
Vector2f worldScale = new Vector2f(displaySize.x / (display.x / 2.0f), displaySize.y / (display.y / 2));
float x, y;
x = worldPos.x;
y = worldPos.y - CORNER_SCALE;
//y is calculated correct. Moving the mouse to the same y value as calculated shows that everything is correctly calculated
System.out.println(y + " | " + Mouse.getWorldPos().y);
transforms[0] = Maths.getTransformationMatrix(new Vector2f(x, y), new Vector2f(CORNER_SCALE, CORNER_SCALE));
}
Check size:
GLFW.glfwSetWindowSizeCallback(WINDOW, new GLFWWindowSizeCallback() {
#Override
public void invoke(long arg0, int arg1, int arg2) {
resized = true;
}
});
Rendering (would normally render more objects):
#Override
protected void render() {
shader.start();
if(DisplayManager.isResized()) {
shader.loadProjectionMatrix(MasterRenderer.getProjectionMatrix());
}
bindModel(Loader.getQuad(), new int[] {0});
for(GUI gui : guis) {
if(DisplayManager.isResized()) {
gui.loadTransformationMatricies();
}
bindTexture(gui.getTexture().getTopLeftCorner(), GL13.GL_TEXTURE0);
Matrix4f[] transforms = gui.getTransformations();
for(int i = 0; i < 1; i++) {
shader.loadTransformationMatrix(transforms[i]);
drawSTRIP(Loader.getQuad());
}
}
unbind(new int[] {0});
shader.stop();
}
Vertexshader:
#version 400 core
in vec2 position;
uniform mat4 transformationMatrix;
uniform mat4 projectionMatrix;
out vec2 textureCoords;
void main (void){
gl_Position = projectionMatrix * transformationMatrix * vec4(position, 0, 1.0);
textureCoords = vec2((position.x+1.0)/2.0, 1 - (position.y+1.0)/2.0);
}
You can find the whole code on Github if you need more information but I only want to know how to fix this specific problem.
https://github.com/StackOverflowEx/GameEngine2D
After the size of the window has changed, the viewport rectangle has to be adjusted to the new size:
Use glViewport to set the viewport rectangle.
Add a method updateViewPort to the class DisplayManager
public static void updateViewPort() {
IntBuffer pWidth = stack.mallocInt(1);
IntBuffer pHeight = stack.mallocInt(1);
GLFW.glfwGetFramebufferSize(WINDOW, pWidth, pHeight);
GL11.glViewport(0, 0, pWidth.get(0), pHeight.get(0));
}
Call the DisplayManager.updateViewPort in the methodprepare in the class MasterRenderer:
private void prepare() {
if(DisplayManager.isResized()) {
DisplayManager.updateViewPort();
createProjectionMatrix();
}
Camera.calcViewMatrix();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glClearColor(1, 0, 0, 1);
}
See also Java Code Examples for org.lwjgl.glfw.GLFW.glfwGetFramebufferSize().

Binding Video Texture on OpenGL Sphere on Android

I'm trying to create a 360 video sphere (like the ones for cardboard) on Android. I have done this with a photo by rendering a sphere in OpenGL ES1.0 and than attaching a texture to it. Afterwards I can use the sensor values to rotate the sphere.
However, I can't figure out how to change the picture to a video. I've tried frame by frame rendering using texSubImage2D() but it's SUPER SLOW. My video is probably going to be about 4k density as I need a good quality even when only small portion of it is shown.
I've read some theoretical stuff about how this should be done (i.e. Frame Buffers, External Texture, Synchronization, etc.) but I couldn't find any example for these things, so some code would be EXTREMELY appreciated...
Here is how I render the Sphere, draw it and attach a texture to it (i.e. my Sphere class)...
import rapid.decoder.BitmapDecoder;
public class Sphere {
/** Buffer holding the vertices. */
private final List<FloatBuffer> mVertexBuffer = new ArrayList<FloatBuffer>();
/** The vertices for the sphere. */
private final List<float[]> mVertices = new ArrayList<float[]>();
/** Buffer holding the texture coordinates. */
private final List<FloatBuffer> mTextureBuffer = new ArrayList<FloatBuffer>();
/** Mapping texture coordinates for the vertices. */
private final List<float[]> mTexture = new ArrayList<float[]>();
/** The texture pointer. */
private final int[] mTextures = new int[1];
/** Total number of strips for the given depth. */
private final int mTotalNumStrips;
public Sphere(final int depth, final float radius) {
// Calculate basic values for the sphere.
this.mTotalNumStrips = Maths.power(2, depth - 1) * 5; //last 5 is related to properties of a icosahedron
final int numVerticesPerStrip = Maths.power(2, depth) * 3;
final double altitudeStepAngle = Maths.rad120 / Maths.power(2, depth);
final double azimuthStepAngle = Maths.rad360 / this.mTotalNumStrips;
double x, y, z, h, altitude, azimuth;
Log.e("mTotalNumStrips", ""+mTotalNumStrips);
Log.e("numVerticesPerStrip", ""+numVerticesPerStrip);
for (int stripNum = 0; stripNum < this.mTotalNumStrips; stripNum++) {
// Setup arrays to hold the points for this strip.
final float[] vertices = new float[numVerticesPerStrip * 3]; // x,y,z
final float[] texturePoints = new float[numVerticesPerStrip * 2]; // 2d texture
int vertexPos = 0;
int texturePos = 0;
// Calculate position of the first vertex in this strip.
altitude = Maths.rad90;
azimuth = stripNum * azimuthStepAngle;
// Draw the rest of this strip.
for (int vertexNum = 0; vertexNum < numVerticesPerStrip; vertexNum += 2) {
// First point - Vertex.
y = radius * Math.sin(altitude);
h = radius * Math.cos(altitude);
z = h * Math.sin(azimuth);
x = h * Math.cos(azimuth);
vertices[vertexPos++] = (float) x;
vertices[vertexPos++] = (float) y;
vertices[vertexPos++] = (float) z;
// First point - Texture.
texturePoints[texturePos++] = (float) (1 + azimuth / Maths.rad360);
texturePoints[texturePos++] = (float) (1 - (altitude + Maths.rad90) / Maths.rad180);
// Second point - Vertex.
altitude -= altitudeStepAngle;
azimuth -= azimuthStepAngle / 2.0;
y = radius * Math.sin(altitude);
h = radius * Math.cos(altitude);
z = h * Math.sin(azimuth);
x = h * Math.cos(azimuth);
vertices[vertexPos++] = (float) x;
vertices[vertexPos++] = (float) y;
vertices[vertexPos++] = (float) z;
// Second point - Texture.
texturePoints[texturePos++] = (float) (1 + azimuth / Maths.rad360);
texturePoints[texturePos++] = (float) (1 - (altitude + Maths.rad90) / Maths.rad180);
azimuth += azimuthStepAngle;
}
this.mVertices.add(vertices);
this.mTexture.add(texturePoints);
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(numVerticesPerStrip * 3 * Float.SIZE);
byteBuffer.order(ByteOrder.nativeOrder());
FloatBuffer fb = byteBuffer.asFloatBuffer();
fb.put(this.mVertices.get(stripNum));
fb.position(0);
this.mVertexBuffer.add(fb);
// Setup texture.
byteBuffer = ByteBuffer.allocateDirect(numVerticesPerStrip * 2 * Float.SIZE);
byteBuffer.order(ByteOrder.nativeOrder());
fb = byteBuffer.asFloatBuffer();
fb.put(this.mTexture.get(stripNum));
fb.position(0);
this.mTextureBuffer.add(fb);
}
}
public void loadGLTexture(final GL10 gl, final Context context, final int texture) {
Bitmap bitmap = BitmapDecoder.from(context.getResources(), texture)
.scale(4048, 2024)
.decode();
// Generate one texture pointer, and bind it to the texture array.
gl.glGenTextures(1, this.mTextures, 0);
gl.glBindTexture(GL10.GL_TEXTURE_2D, this.mTextures[0]);
// Create nearest filtered texture.
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
// Use Android GLUtils to specify a two-dimensional texture image from our bitmap.
GLUtils.texImage2D(GL10.GL_TEXTURE_2D, 0, bitmap, 0);
// Tide up.
bitmap.recycle();
}
/**
* The draw method for the square with the GL context.
*
* #param gl Graphics handle.
*/
public void draw(final GL10 gl) {
// bind the previously generated texture.
gl.glBindTexture(GL10.GL_TEXTURE_2D, this.mTextures[0]);
// Point to our buffers.
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
// Set the face rotation, clockwise in this case.
gl.glFrontFace(GL10.GL_CW);
// Point to our vertex buffer.
for (int i = 0; i < this.mTotalNumStrips; i++) {
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, this.mVertexBuffer.get(i));
gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, this.mTextureBuffer.get(i));
// Draw the vertices as triangle strip.
gl.glDrawArrays(GL10.GL_TRIANGLE_STRIP, 0, this.mVertices.get(i).length / 3);
}
// Disable the client state before leaving.
gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
}
}
And this is my renderer...
#Override
public void onDrawFrame(final GL10 gl) {
zvector = new float[] {0,0,1,0};
resultvector = new float[] {0,0,1,0};
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
float radiansX = (float) Math.toRadians(gyro_angle[1]);
float radiansY = (float) Math.toRadians(-gyro_angle[0]);
float radiansZ = (float) Math.toRadians(-gyro_angle[2]);
// Finds the Sin and Cosin for the half angle.
float sinX =(float) Math.sin(radiansX * 0.5);
float cosX =(float) Math.cos(radiansX * 0.5);
float sinY =(float) Math.sin(radiansY * 0.5);
float cosY =(float) Math.cos(radiansY * 0.5);
float sinZ =(float) Math.sin(radiansZ * 0.5);
float cosZ =(float) Math.cos(radiansZ * 0.5);
// Formula to construct a new Quaternion based on direction and angle.
quatX[0] = cosX;
quatX[1] = 1 * sinX;
quatX[2] = 0 * sinX;
quatX[3] = 0 * sinX;
quatY[0] = cosY;
quatY[1] = 0 * sinY;
quatY[2] = 1 * sinY;
quatY[3] = 0 * sinY;
quatZ[0] = cosZ;
quatZ[1] = 0 * sinZ;
quatZ[2] = 0 * sinZ;
quatZ[3] = 1 * sinZ;
quat1 = multiplyQuat(quatX, quatY);
quat2 = multiplyQuat(quat1, quatZ);
mMatrix = getMatrixfromQuat(quat1);
gl.glLoadMatrixf(mMatrix, 0);
this.mSphere.draw(gl);
}
#Override
public void onSurfaceChanged(final GL10 gl, final int width, final int height) {
final float aspectRatio = (float) width / (float) (height == 0 ? 1 : height);
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL10.GL_PROJECTION);
gl.glLoadIdentity();
GLU.gluPerspective(gl, 45.0f, aspectRatio, 0.1f, 100.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
}
#Override
public void onSurfaceCreated(final GL10 gl, final EGLConfig config) {
this.mSphere.loadGLTexture(gl, this.mContext, R.drawable.pic360);
gl.glEnable(GL10.GL_TEXTURE_2D);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glClearColor(0.0f, 0.0f, 0.0f, 0.5f);
gl.glClearDepthf(1.0f);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthFunc(GL10.GL_LEQUAL);
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_NICEST);
}
//CONSTRUCTER
public GlRenderer(final Context context) {
this.mContext = context;
this.mSphere = new Sphere(5, 2);
sensorManager = (SensorManager) this.mContext.getSystemService(this.mContext.SENSOR_SERVICE);
sensorGyroscope = sensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
sensorAccelerometer = sensorManager.getDefaultSensor(Sensor.TYPE_ACCELEROMETER);
sensorMagneticField = sensorManager.getDefaultSensor(Sensor.TYPE_MAGNETIC_FIELD);
valuesAccelerometer = new float[3];
valuesMagneticField = new float[3];
matrixR = new float[9];
matrixI = new float[9];
matrixValues = new float[3];
sensorManager.registerListener(this, sensorGyroscope, SensorManager.SENSOR_DELAY_FASTEST);
sensorManager.registerListener(this, sensorAccelerometer, SensorManager.SENSOR_DELAY_FASTEST);
sensorManager.registerListener(this, sensorMagneticField, SensorManager.SENSOR_DELAY_FASTEST);
}
//HERE GOES SOME CURRENTLY IRRELEVANT STUFF ABOUT THE SENSORS AND QUATERNIONS
I had some this type of video texturing problem. First time I used ffmpeg for video decoding but the performance was so poor (just like you- Extracting frame by frame). For improving performance I used android default mediaplayer. You can use surface texture to create an opengl surface (sphere, cylinder, cube etc...) and then set the surface in the media player
Surface surface = new Surface(mSurface);//mSurface is your surface texture
mMediaPlayer.setSurface(surface);
mMediaPlayer.setScreenOnWhilePlaying(true);
This is just a technique. I did this for some commercial enclosed project, so I cant share the code. I hope I'll published a free code in github soon.

Billboard facing the camera has wrong rotation near 180 degrees

I've implemented a particle system. I'm drawing their textures on billboards that should be rotated towards the camera.
This works fine except for the case when the angle between particle->camera and the normal comes near to 180 degrees. Then the particle starts rotating around itself many times.
The angle is calculated using cos(angle) = dot(a, b) / (length(a) * length(b), the length are both 1 cause the Vectors are normalized.
The axis is calculated using the cross product of those two vectors.
glDisable(GL_CULL_FACE);
//calculate rotation
Vector3f normal = new Vector3f(0, 0, 1);
Vector3f dir = Vector3f.sub(new Vector3f(GraphicsData.camera.x, GraphicsData.camera.y, GraphicsData.camera.z), new Vector3f(x, y, z), null);
if(dir.length() == 0)
{
glEnable(GL_CULL_FACE);
return;
}
dir = (Vector3f) dir.normalise();
float angle = (float) Math.toDegrees(Math.acos(Vector3f.dot(normal, dir)));
Vector3f rotationAxis = Vector3f.cross(normal, dir, null);
rotationAxis = (Vector3f) rotationAxis.normalise();
System.out.println("Angle: + " + angle + " Axis: " + rotationAxis);
glBindTexture(GL_TEXTURE_2D, ParticleEngine.particleTextures.get(typeId).texture.getTextureID());
glColor4f(1f,1f,1f, time >= lifeTime - decayTime ? ((float)lifeTime - (float)time) / ((float)lifeTime - (float)decayTime) : 1f);
shaderEngine.createModelMatrix(new Vector3f(x, y, z), new Vector3f(angle * rotationAxis.x, angle * rotationAxis.y, angle * rotationAxis.z), new Vector3f(sx, sy, sz));
shaderEngine.loadModelMatrix(shaderEngine.particle);
glCallList(ParticleEngine.particleTextures.get(typeId).displayListId + textureIndex);
glEnable(GL_CULL_FACE);
What am i doing wrong calculating the rotation?
public static void createModelMatrix(Vector3f pos, Vector3f rot, Vector3f scale)
{
GraphicsData.camera.modelMatrix = new Matrix4f();
GraphicsData.camera.modelMatrix.setIdentity();
GraphicsData.camera.modelMatrix.translate(pos);
GraphicsData.camera.modelMatrix.rotate((float) Math.toRadians(rot.x), new Vector3f(1,0,0));
GraphicsData.camera.modelMatrix.rotate((float) Math.toRadians(rot.y), new Vector3f(0,1,0));
GraphicsData.camera.modelMatrix.rotate((float) Math.toRadians(rot.z), new Vector3f(0,0,1));
GraphicsData.camera.modelMatrix.scale(scale);
}
More a long comment or perhaps a partial answer to the problem:
If you are computing the cross product anyway, then use that
norm( a × b ) = sin(angle) * norm(a)*norm(b)
dot(a,b) = cos(angle) * norm(a)*norm(b)
to determine
angle = atan2( norm(a×b), dot(a,b) )

Drawing normal faces with triangle strips?

I am having to calculate the normals for a triangle strip and am having a issue where every other triangle is dark and not shaded well. I am using the flat shade model. I can't tell if it has to do with the winding direction. When I look under the triangle strip i notice that it is the same thing as the top except the dark areas or switched. I think what the problem may be is that the surface normals I am trying to calculate are using shared vertices. If that is the case would you recommend switching to GL_TRIANGLES? How would you resolve this?
Here is what I have as of now. The triangle class is has the triVerts array in it which have three Vert objects. The Vert objects have variables x, y, and z.
Triangle currentTri = new Triangle();
int triPointIndex = 0;
List<Triangle> triList = new ArrayList<Triangle>()
GL11.glBegin(GL11.GL_TRIANGLE_STRIP);
int counter1 = 0;
float stripZ = 1.0f;
float randY;
for (float x=0.0f; x<20.0f; x+=2.0f) {
if (stripZ == 1.0f) {
stripZ = -1.0f;
} else { stripZ = 1.0f; }
randY = (Float) randYList.get(counter1);
counter1 += 1;
GL11.glVertex3f(x, randY, stripZ);
Vert currentVert = currentTri.triVerts[triPointIndex];
currentVert.x = x;
currentVert.y = randY;
currentVert.z = stripZ;
triPointIndex++;
System.out.println(triList);
Vector3f normal = new Vector3f();
float Ux = currentTri.triVerts[1].x - currentTri.triVerts[0].x;
float Uy = currentTri.triVerts[1].y - currentTri.triVerts[0].y;
float Uz = currentTri.triVerts[1].z - currentTri.triVerts[0].z;
float Vx = currentTri.triVerts[2].x - currentTri.triVerts[0].x;
float Vy = currentTri.triVerts[2].y - currentTri.triVerts[0].y;
float Vz = currentTri.triVerts[2].z - currentTri.triVerts[0].z;
normal.x = (Uy * Vz) - (Uz * Vy);
normal.y = (Uz * Vx) - (Ux * Vz);
normal.z = (Ux * Vy) - (Uy * Vx);
GL11.glNormal3f(normal.x, normal.y, normal.z);
if (triPointIndex == 3) {
triList.add(currentTri);
Triangle nextTri = new Triangle();
nextTri.triVerts[0] = currentTri.triVerts[1];
nextTri.triVerts[1] = currentTri.triVerts[2];
currentTri = nextTri;
triPointIndex = 2;
}
}
GL11.glEnd();
I had to draw a pyramid with about 8-10 faces and some lighting and I used triangles to be properly lighted. For each triangle I had to calculate the normal. This way it worked. Also I think is important to keep the clockwise/counter sense in which you draw the vertices for each triangle. I hope it helps.

Quaternions and drawing with glMultMatrix (OpenGL)

I got a problem again. Since a couple of days I try to write a camera in Java without a gimbal lock. For solving this I try to use Quaternions and glMultMatrix from OpenGL. I also use the library "LWJGL" especially the classes Matrix4f, Vector4f and Quaternions.
Here is the code which calculates the Quaternions:
int DX = Mouse.getDX(); //delta-mouse-movement
int DY = Mouse.getDY();
Vector4f axisY = new Vector4f();
axisY.set(0, 1, 0,DY);
Vector4f axisX = new Vector4f();
axisX.set(1, 0, 0, DX);
Quaternion q1 = new Quaternion();
q1.setFromAxisAngle(axisX);
Quaternion q2 = new Quaternion();
q2.setFromAxisAngle(axisY);
Quaternion.mul(q1, q2, q1);
Quaternion.mul(camera,q1,camera);
And whit this I convert the Quaternion into a matrix:
public Matrix4f quatToMatrix(Quaternion q){
double sqw = q.w*q.w;
double sqx = q.x*q.x;
double sqy = q.y*q.y;
double sqz = q.z*q.z;
Matrix4f m = new Matrix4f();
// invs (inverse square length) is only required if quaternion is not already normalised
double invs = 1 / (sqx + sqy + sqz + sqw);
m.m00 = (float)(( sqx - sqy - sqz + sqw)*invs) ; // since sqw + sqx + sqy + sqz =1/invs*invs
m.m11 = (float)((-sqx + sqy - sqz + sqw)*invs);
m.m22 =(float) ((-sqx - sqy + sqz + sqw)*invs);
double tmp1 = q.x*q.y;
double tmp2 = q.z*q.w;
m.m10 = (float) (2.0 * (tmp1 + tmp2)*invs);
m.m01 = (float) (2.0 * (tmp1 - tmp2)*invs) ;
tmp1 = q.x*q.z;
tmp2 = q.y*q.w;
m.m20 = (float)(2.0 * (tmp1 - tmp2)*invs) ;
m.m02 = (float)(2.0 * (tmp1 + tmp2)*invs) ;
tmp1 = q.y*q.z;
tmp2 = q.x*q.w;
m.m21 = (float)(2.0 * (tmp1 + tmp2)*invs) ;
m.m12 = (float)(2.0 * (tmp1 - tmp2)*invs) ;
return m;
}
A converted Quaternion looks for example like this:
-0.5191307 0.027321965 -0.85425806 0.0
0.048408303 -0.9969446 -0.061303165 0.0
-0.8533229 -0.07317754 0.51622194 0.0
0.0 0.0 0.0 1.0
After this I draw the scene with this code:
java.nio.FloatBuffer fb = BufferUtils.createFloatBuffer(32);
quatToMatrix(camera).store(fb);
GL11.glMultMatrix(fb);
drawPlayer();
My problem now is that the camera maybe doesn't move, or doesn't move enough, because I only see my player model and nothing else (There also is another cube in the scene I draw after the player model).
I don't know what exactly is wrong. Is it the drawing, the rotation, or the converting?
Please help me.
EDIT:
that is my OpenGL initialisation:
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(45.0f, ((float) setting.displayW() / (float) setting.displayH()), 0.1f,10000.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glShadeModel(GL11.GL_SMOOTH);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glDepthFunc(GL11.GL_LEQUAL);
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
Any Idea what is wrong?
you've got some errors in your mouse movement to quaternion function (where do you make a quaternion of the X movement?). Besides that, we'd also need to see the rest of your drawing setup code (projection matrix, modelview initialization).

Categories

Resources