I have a basic OpenGL program written in LWJGL for java. I'm just starting to look into rotation matrices after reading up on why it's a bad idea to use pitch, yaw and roll variables. However, as matrices are more difficult to work with, I am writing a function that takes yaw, pitch and roll and converts them into a rotation matrix, which is then multiplied with the Modelview matrix. My code is as follows:
public static void loadRotationalMatrix(double pitch, double yaw, double roll)
{
FloatBuffer Ry = ByteBuffer.allocateDirect(16 * Double.SIZE).asFloatBuffer();
FloatBuffer Rx = ByteBuffer.allocateDirect(16 * Double.SIZE).asFloatBuffer();
FloatBuffer Rz = ByteBuffer.allocateDirect(16 * Double.SIZE).asFloatBuffer();
Rx.put(new float[]
{
1, 0, 0, 0,
0, (float) cos(pitch), (float) sin(pitch), 0,
0, (float) -sin(pitch), (float) cos(pitch), 0,
0, 0, 0, 1
});
Ry.put(new float[]
{
(float) cos(yaw), 0, (float) -sin(yaw), 0,
0, 1, 0, 0,
(float) sin(yaw), 0, (float) cos(yaw), 0,
0, 0, 0, 1
});
Rz.put(new float[]
{
(float) cos(roll), (float) sin(roll), 0, 0,
(float) -sin(roll), (float) cos(roll), 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
});
GL11.glMultMatrix(Rx);
GL11.glMultMatrix(Ry);
GL11.glMultMatrix(Rz);
}
To begin, I passed 0, 0, 0 to this function, which I expected to have no effect on the rendered scene. However, the simple square I was drawing disappeared after the function call. To debug, I used glGetFloat to access the modelview matrix and see what happened.
This is where things get strange (for me at least): before I call my function, the retrieved FloatBuffer storing the modelview matrix is
4.6006E-41, 0.0, 0.0, 0.0, 0.0, 4.6006E-41, 0.0, 0.0, 0.0, 0.0, 4.6006E-41, 0.0, 0.0, 0.0, 0.0, 4.6006E-41,
or, more readable,
4.6006E-41, 0.0, 0.0, 0.0,
0.0, 4.6006E-41, 0.0, 0.0,
0.0, 0.0, 4.6006E-41, 0.0,
0.0, 0.0, 0.0, 4.6006E-41,
and everything renders normally.
After my call, the matrix becomes
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
0.0, 0.0, 0.0, 0.0,
and my test square disappears.
What is happening? Are my matrices created incorrectly? Is there something I do not understand about glMultMatrix? Is there something I need to enable or disable? Why does the normal matrix have those weird floats in it? Isn't it supposed to be the identity matrix (with 1's)?
EDIT:
If BufferUtils.createFloatBuffer(16 * Float.SIZE); is used instead of ByteBuffer.allocateDirect(16 * Float.SIZE).asFloatBuffer();, the the byte-ordering problems mentioned go away and the 4.6006E-41's becomes 1.0 as expected. However, the matrix still transforms from the identity to pure zeroes.
(This is really an extended comment, with code)
There is definitely a byte order problem here. I ran the following:
public class Test {
public static void main(String[] args) {
float f = (float)4.6006E-41;
System.out.println(Integer.toHexString(Float.floatToIntBits(f)));
}
}
and got output 803f
Float 1.0 is big-endian 0x3f800000.
Related
Via this code:
import java.util.Arrays;
public class RREFS {
public static void main(String[] args){
double[][] rref;
double[][] matrix;
matrix=new double[][]{
new double[]{ 8.385956100787163E-8, 0.9103664774626016, 0.41380294430118253, 0.0, 0.0, 0.0 },
new double[]{ 2.0779736498353668E-8, 0.22558161873553792, -0.4962795612181877, 0.8383433249008051, 0.0, 0.0 },
new double[]{ 1.0081125874457642E-7, -0.34690893617920376, 0.7631996595942279, 0.5451426139958772, 0.0, 0.0 },
new double[]{ 0.0, 0.0, 0.0, 0.0, 1.0, 0.0 },
new double[]{ 0.0, 0.0, 0.0, 0.0, 0.0, 1.0 }
};
rref=RREFS.rref(matrix);
print(rref);
// this
// [ 8.385956100787163E-8, 0.9103664774626016, 0.41380294430118253, 0.0, 0.0, 0.0]
// [2.0779736498353668E-8, 0.22558161873553792, -0.4962795612181877, 0.8383433249008051, 0.0, 0.0]
// [1.0081125874457642E-7, -0.34690893617920376, 0.7631996595942279, 0.5451426139958772, 0.0, 0.0]
// [ 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
// [ 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
// produces
// [1.0, 0.0, 0.0, 0.0, 0.0, 0.0]
// [0.0, 1.0, 0.0, 0.0, 0.0, 0.0]
// [0.0, 0.0, 1.0, -1.3999999999999997, 0.0, 0.0]
// [0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
// [0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
// insteada
// [1.0, 0.0, 0.0, 1.38165312352941182995E7, 0.0, 0.0]
// [0.0, 1.0, 0.0, -0.636363636363636, 0.0, 0.0]
// [0.0, 0.0, 1.0, -1.4, 0.0, 0.0]
// [0.0, 0.0, 0.0, 0, 1.0, 0.0]
// [0.0, 0.0, 0.0, 0, 0.0, 1.0]
}
/**
* Puts a matrix into reduced row echelon form
*
* #param matrix input matrix
*
* #return 2D result matrix
*/
public static double[][] rref(double[][] matrix){
int columnIndex = 0;
int cursor;
// number of rows and columns in matrix
int getRowSize = matrix.length;
int getColumnSize = matrix[0].length;
loop:
for(int rowIndex = 0; rowIndex < getRowSize; rowIndex++){
if(getColumnSize <= columnIndex){
break loop;
}
cursor = rowIndex;
while(matrix[cursor][columnIndex] == 0){
cursor++;
if(getRowSize == cursor){
cursor = rowIndex;
columnIndex++;
if(getColumnSize == columnIndex){
break loop;
}
}
}
matrix = rowSwap(matrix, cursor, rowIndex);
if(matrix[rowIndex][columnIndex] != 0){
matrix = rowScale(matrix, rowIndex, (1/matrix[rowIndex][columnIndex]));
}
for(cursor = 0; cursor < getRowSize; cursor++){
if(cursor != rowIndex){
matrix = rowAddScale(matrix, rowIndex, cursor,((-1) * matrix[cursor][columnIndex]));
}
}columnIndex++;
}return matrix;
}
/**
* Swap positions of 2 rows
*
* #param matrix matrix before row additon
* #param rowIndex1 int index of row to swap
* #param rowIndex2 int index of row to swap
*
* #return matrix after row swap
*/
private static double[][] rowSwap(double[][] matrix, int rowIndex1,
int rowIndex2){
// number of columns in matrix
int numColumns = matrix[0].length;
// holds number to be swapped
double hold;
for(int k = 0; k < numColumns; k++){
hold = matrix[rowIndex2][k];
matrix[rowIndex2][k] = matrix[rowIndex1][k];
matrix[rowIndex1][k] = hold;
}
return matrix;
}
/**
* Adds 2 rows together row2 = row2 + row1
*
* #param matrix matrix before row additon
* #param rowIndex1 int index of row to be added
* #param rowIndex2 int index or row that row1 is added to
*
* #return matrix after row addition
*/
private static double[][] rowAdd(double[][] matrix, int rowIndex1,
int rowIndex2){
// number of columns in matrix
int numColumns = matrix[0].length;
for(int k = 0; k < numColumns; k++){
matrix[rowIndex2][k] += matrix[rowIndex1][k];
}
return matrix;
}
/**
* Multiplies a row by a scalar
*
* #param matrix matrix before row additon
* #param rowIndex int index of row to be scaled
* #param scalar double to scale row by
*
* #return matrix after row scaling
*/
private static double[][] rowScale(double[][] matrix, int rowIndex,
double scalar){
// number of columns in matrix
int numColumns = matrix[0].length;
for(int k = 0; k < numColumns; k++){
matrix[rowIndex][k] *= scalar;
}
return matrix;
}
/**
* Adds a row by the scalar of another row
* row2 = row2 + (row1 * scalar)
* #param matrix matrix before row additon
* #param rowIndex1 int index of row to be added
* #param rowIndex2 int index or row that row1 is added to
* #param scalar double to scale row by
*
* #return matrix after row addition
*/
private static double[][] rowAddScale(double[][] matrix, int rowIndex1,
int rowIndex2, double scalar){
// number of columns in matrix
int numColumns = matrix[0].length;
for(int k = 0; k < numColumns; k++){
matrix[rowIndex2][k] += (matrix[rowIndex1][k] * scalar);
}
return matrix;
}
public static void print(double[][] matrix) {
print("",matrix);
}
public static void print(String message, double[][] matrix) {
System.out.println(message);
for (int i = 0; i < matrix.length; i++) {
System.out.println(Arrays.toString(matrix[i]));
}System.out.println();
}
}
I am trying to build a custom rref calculator thus I have
edie-zhou's implementation asper.
It works with every simple matrix I have tested so far, However the result of
[ 8.385956100787163E-8, 0.9103664774626016, 0.41380294430118253, 0.0, 0.0, 0.0]
[2.0779736498353668E-8, 0.22558161873553792, -0.4962795612181877, 0.8383433249008051, 0.0, 0.0]
[1.0081125874457642E-7, -0.34690893617920376, 0.7631996595942279, 0.5451426139958772, 0.0, 0.0]
[ 0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
[ 0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
is this
[1.0, 0.0, 0.0, 0.0, 0.0, 0.0]
[0.0, 1.0, 0.0, 0.0, 0.0, 0.0]
[0.0, 0.0, 1.0, -1.3999999999999997, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
instead of
[1.0, 0.0, 0.0, 1.38165312352941182995E7, 0.0, 0.0]
[0.0, 1.0, 0.0, -0.636363636363636, 0.0, 0.0]
[0.0, 0.0, 1.0, -1.4, 0.0, 0.0]
[0.0, 0.0, 0.0, 0, 1.0, 0.0]
[0.0, 0.0, 0.0, 0, 0.0, 1.0]
according to this online calculator and some others I tested, please what seems to be the problem with the code.
You may actually have a "do not compare floats for equality" problem in there.
If I do:
public static boolean isZero(double foo) {
// demonstration only, replace with less silly implementation
return Math.abs(foo)<0.0000001;
}
...
while(isZero(matrix[cursor][columnIndex])){
//instead of
while(matrix[cursor][columnIndex] == 0){
I get
[1.0, 0.0, 0.0, 1.3816531235294117E7, 0.0, 0.0]
[0.0, 1.0, 0.0, -0.6363636363636362, 0.0, 0.0]
[0.0, 0.0, 1.0, -1.3999999999999997, 0.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 1.0, 0.0]
[0.0, 0.0, 0.0, 0.0, 0.0, 1.0]
which is the result you wanted I believe.
More discussion e.g. in How should I do floating point comparison?
Problem: Write a program that reads a list of real numbers. After the program ends it should print out only the unique numbers. That is, only numbers that appear once in the list. If there are more than 50 unique numbers on the list, then you should only print the first 50.
import java.util.*;
import java.io.*;
import java.util.Arrays;
public class Hmwk {
public static void main(String[] args) throws FileNotFoundException {
Scanner input=new Scanner (new File ("input.txt"));
int n = 0;
final int MAX_SIZE = 50;
double[] numbersArray = new double[MAX_SIZE];
while (input.hasNextDouble() && n<MAX_SIZE){
double in = input.nextDouble();
if (inList(in,numbersArray))
numbersArray[n]=in;
n++;
}
printReport(numbersArray);
}
public static boolean inList(double number, double[] list){
for (double i : list)
{
if (i == number){
return false;
}
}
return true;
}
public static void printReport(double[] list)
{
System.out.println("The unique numbers were");
System.out.println(Arrays.toString(list));
}
}
input.txt file=
5.0 6.0 7.0 8.9 3.0 2.0 8.9 8.9 9.0 7.0 6.0 5.0 4.0 3.0 2.0 1.0
results-
The unique numbers were
[5.0, 6.0, 7.0, 8.9, 3.0, 2.0, 0.0, 0.0, 9.0, 0.0, 0.0, 0.0, 4.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
No idea where I'm going wrong here, I think its my inlist method? Any and all help is much appreciated. Thanks!
Add bracket for IF condition
if (inList(in,numbersArray))
{
numbersArray[n]=in;
n++;
}
Your if needs braces
if (inList(in,numbersArray)){
numbersArray[n]=in;
n++;
}
or do this
if (inList(in,numbersArray))
numbersArray[n++]=in;
You are incrementing n whether the number is already in the list or not. What you've written is (re-indented for clarity):
if (inList(in,numbersArray))
numbersArray[n]=in;
n++;
But it should be:
if (inList(in,numbersArray)) {
numbersArray[n]=in;
n++;
}
Then when you're done, truncate the list to be n elements long.
I'm facing a problem i worked around some time ago (Incorrect VBO for mesh: some triangles are connected and shouldn't [2D]), and since my shader have become more complex and different problems connected to this arose, i need to solve it at its foundations!
This is the VBO content:
[0.0, 0.0,
0.0, 240.0,
10.0, 0.0,
10.0, 240.0,
20.0, 0.0,
20.0, 240.0,
30.0, 0.0,
30.0, 240.0
and so on up to
1190.0, 0.0,
1190.0, 240.0,
1200.0, 0.0,
1200.0, 240.0,
1210.0, 0.0,
1210.0, 240.0]
So the array length is 244 point * 2 coordinate = 488 elements.
This is the opengl trace of a frame
glClearColor(red = 0,100000, green = 0,100000, blue = 0,100000, alpha = 1,000000)
glClear(mask = 16384)
glEnable(cap = GL_BLEND)
glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 2)
glDisableVertexAttribArray(index = 1)
glVertexAttribPointer(indx = 0, size = 2, type = GL_FLOAT, normalized = false, stride = 8, ptr = 0x0)
glUniformMatrix4fv(location = 1, count = 1, transpose = false, value = [0.0025, 0.0, 0.0, 0.0, 0.0, 0.004166667, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -1.0, -1.0, 0.0, 1.0])
glUniform1i(location = 5, x = 0)
glUniform4f(location = 3, x = 0,000000, y = 0,000000, z = 1,000000, w = 0,500000)
glUniform1f(location = 4, x = 2,491089)
glUniform1f(location = 0, x = 1780,000000)
glUniformMatrix4fv(location = 2, count = 1, transpose = false, value = [-100.0, 40.0, 260.0, 430.0, 165.6131, 122.20027, 247.55757, 189.05222, 680.0, 880.0, -268.66666, -268.66666, 126.442535, 1.7712338, 160.0, 160.0])
glDrawArrays(mode = GL_TRIANGLE_STRIP, first = 0, count = 486)
glEnableVertexAttribArray(index = 1)
glDisable(cap = GL_BLEND)
glEnable(cap = GL_BLEND)
glBindBuffer(target = GL_ARRAY_BUFFER, buffer = 3)
glDisableVertexAttribArray(index = 1)
glVertexAttribPointer(indx = 0, size = 2, type = GL_FLOAT, normalized = false, stride = 8, ptr = 0x0)
glUniformMatrix4fv(location = 1, count = 1, transpose = false, value = [0.0025, 0.0, 0.0, 0.0, 0.0, 0.004166667, 0.0, 0.0, 0.0, 0.0, -1.0, 0.0, -1.0, 1.0, 0.0, 1.0])
glUniform1i(location = 5, x = 0)
glUniform4f(location = 3, x = 0,000000, y = 0,500000, z = 1,000000, w = 0,500000)
glUniform1f(location = 4, x = 2,491089)
glUniform1f(location = 0, x = 1780,000000)
glUniformMatrix4fv(location = 2, count = 1, transpose = false, value = [-60.0, 150.0, 330.0, 550.0, -71.13025, -193.20978, -11.679321, -223.35025, 740.0, 990.0, -268.66666, -268.66666, -394.54395, -270.3169, -160.0, -160.0])
glDrawArrays(mode = GL_TRIANGLE_STRIP, first = 0, count = 486)
glEnableVertexAttribArray(index = 1)
glDisable(cap = GL_BLEND)
eglSwapBuffers
My shader is a bit long and complex, but it does nothing but move along the Y axis the vertices that have the Y component different from 0. The uniform values are correct, and the shader works correctly.
When i render with TRIANGLE_STRIP the screen shows lines that connect the first vertex (0,0) with the last one (1210, ???) (??? because my shader moves it, and it is not at 240. I know where it is, and it is where it should be, but it constantly varies.)
Rendering with LINE_STRIP just confirms the problem.
So, is this the expected behaviour of TRIANGLE_STRIP? Or is something wrong? Reading the opengl specification it seams that it shouldn't wrap, but it does (in different devices, so it's not a specific driver issue)
Totally found the solution.
I was passing the length of my array minus 2 as the count of vertex to draw. The error was that my vertex array holds both X and Y coordinates, so it was actually long twice the number of primitive to draw.
I now use array.length / 2, and all works correctly.
Btw, when I found it out, I thought performances would increase. Instead it didn't happen.
I'm trying to create some sort of basic lighting system. I have this struct set up:
struct Light
{
vec3 position;
vec4 diffuse;
vec4 ambient;
bool enabled;
};
And then i define 4 disabled lights:
uniform Light light0 = Light(vec3(0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), false);
uniform Light light1 = Light(vec3(0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), false);
uniform Light light2 = Light(vec3(0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), false);
uniform Light light3 = Light(vec3(0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), vec4(0.0, 0.0, 0.0, 0.0), false);
In my program I'm trying to get the uniform locations so I can change the lights, so I use this code.
int[][] lightLocs = new int[MAX_LIGHTS][4]; //Position, Diffuse, Ambient, Enabled
for(int i = 0; i < MAX_LIGHTS; i++) { //MAX_LIGHTS is set to 4
lightLocs[i][0] = GL20.glGetUniformLocation(shaderProgram, "light"+i+".position");
lightLocs[i][1] = GL20.glGetUniformLocation(shaderProgram, "light"+i+".diffuse");
lightLocs[i][2] = GL20.glGetUniformLocation(shaderProgram, "light"+i+".ambient");
lightLocs[i][3] = GL20.glGetUniformLocation(shaderProgram, "light"+i+".enabled");
//Print locations just for bug testing
for(int j = 0; j < 4; j++) {
System.out.print(lightLocs[i][j] + ", ");
}
System.out.println();
}
But I'm getting some strange results. All 4 locations for the first 3 lights (0-2) return -1. the position location on light3 also returns -1, but the last 3 values return 4, 5, and 6. The 4, 5, and 6 make sense because I have 4 uniforms defined before the lights in the vertex shader, but why am I getting -1 for the other locations? I have also tried this:
uniform Light light0;
uniform Light light1;
uniform Light light2;
uniform Light light3;
to see if it would work, but then the rest of the uniform locations for the lights return as -1.
Uniforms that are not used in your shader code will often be optimized out. These uniforms are not considered "active" and therefore have a location of -1.
I am studying java and I am having trouble using put to add data into a Java hashtable.
I have this code
double finalIDF = 0.0;
double finalIDF = 0.0;
double finalBM = 0.0;
ArrayList<Double> finalTMlist = new ArrayList<Double>();
Hashtable<String, ArrayList<Double>> BM25TFIDF = new Hashtable<String, ArrayList<Double>>();
String[] bm25QueryList // this is the array to store strings like {hey , good , by}
for(int finalindex = 0; finalindex < bm25QueryList.length ; finalindex++)
{
actualTFvalueforEachDoc.clear();
finalTMlist.clear();
finalIDF = 0.0;
finalIDF = htBM25IDF.get(bm25QueryList[finalindex]);
finalTMlist = tfForAlldoc.get(bm25QueryList[finalindex]);
for(int innerfinal = 0 ; innerfinal < finalTMlist.size() ; innerfinal++ ){
finalTM =finalTMlist.get(innerfinal);
finalBM = finalIDF * finalTM;
actualTFvalueforEachDoc.add(finalBM);
finalTM = 0.0;
finalBM = 0.0; }
BM25TFIDF.put(bm25QueryList[finalindex], actualTFvalueforEachDoc);
System.out.println("Right before final step after BM25TFIDF " + BM25TFIDF); }
I would like to put the ArrayList<Double> into the hashtable using a String key.
The first time through the loop I got the key "orange"
Right before final step after BM25TFIDF {orange=[1.1698113207547172, 1.0508474576271187, 0.8682367918523235, 1.6330439988027539, 0.8938401048492793, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 1.0133729569093612, 0.0]}
which is fine
However, when I insert the second arraylist with second string key "bye" I get
Right before final step after BM25TFIDF {orange=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.238037326690413, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0], bye=[0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 4.238037326690413, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]}
It is overwriting the first arraylist. I used string array to change the key every time, so it shouldn't be happen.
I am not really sure the reason that it keeps over writing.
does anyone know the reason ?
Don't do finalTmList.clear() in your for loop. That will clear the list pointed to by the finalTmList, and subsequently for all the reference pointing to that list.
Since, when you add a list to the Map, you are not adding a copy of your List, rather a copy of your List Reference, that points to the same List. So, any change you make to that list with that reference, or any reference pointing to the list, will be reflected in all the reference.
You should rather create a new list in your for loop, for each entry of your Map: -
finalTMlist = new ArrayList<Double>();
Move the above statement inside your first for loop.
for(int finalindex = 0; finalindex < bm25QueryList.length ; finalindex++) {
finalTMlist = new ArrayList<Double>();
// Your rest code.
And follow the same thing for actualTFvalueforEachDoc.clear() also, whatever it is, as I can't see the declaration in the code.
You should make a new ArrayList for each entry in the map.
You have to create a new array list before start a new iteration
actualTFvalueforEachDoc = new ArraList<Double>();