LWJGL Camera rotating around point? - java

*THIS HAS BEEN SOLVED
Well, the problem is that in LWJGL I made a basic FPS camera using glTranslatef and glRotatef. It acts like it should at first, but when I move the camera it starts rotating around a pivot from where the camera originally was! Here's my code (Without the imports and such) :
public class Main {
public static float camera_x,camera_y,camera_z,camera_rot;
public static ArrayList<Block>blocks = new ArrayList<Block>();
public Main(){
try{
Display.setDisplayMode(new DisplayMode(800,600));
Display.setTitle("Voxel");
Display.create();
}catch(LWJGLException e){
e.printStackTrace();
}
//Init
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective((float)45,800f/600f,0.1f,1000.0f);
glMatrixMode(GL_MODELVIEW);
glLoadIdentity();
glShadeModel(GL_SMOOTH);
glEnable(GL_DEPTH_TEST);
glEnable(GL_TEXTURE_2D);
glDepthFunc(GL_LEQUAL);
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
generateWorld();
glTranslatef(0,15,0);
float dt,time,lastTime = 0;
Mouse.setGrabbed(true);
while(!Display.isCloseRequested() && !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)){
time = Sys.getTime();
dt = (time - lastTime)/1000.0f;
lastTime = time;
render();
tick();
Display.update();
Display.sync(60);
}
Display.destroy();
System.exit(0);
}
public void tick(){
camera_x = 0;
camera_y = 0;
camera_z = 0;
camera_rot = 0;
if(Keyboard.isKeyDown(Keyboard.KEY_W)){
camera_z = +1;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_S)){
camera_z = -1;
}
if(Keyboard.isKeyDown(Keyboard.KEY_A)){
camera_x = +1;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_D)){
camera_x = -1;
}
if(Keyboard.isKeyDown(Keyboard.KEY_SPACE)){
camera_y = -1;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_LSHIFT)){
camera_y = +1;
}
while(Keyboard.next()){
if(Keyboard.isKeyDown(Keyboard.KEY_R)){
generateWorld();
}
}
//Updating all of the blocks
for(int i=0; i < blocks.size(); i++){
blocks.get(i).tick();
}
camera_rot += Mouse.getDX();
}
public void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(camera_rot, 0f, 1f, 0f);
glTranslatef(camera_x, camera_y, camera_z);
for(int i=0; i < blocks.size(); i++){
blocks.get(i).render();
}
}
public static void main(String[] arguments){
new Main();
}
public void generateWorld(){
blocks.clear();
int heightlevel = 0;
Random r = new Random();
for(int i=0; i < 50; i++){
for(int j=0; j < 50; j++){
if(r.nextBoolean() == false){
heightlevel -= 4;
}
else{
heightlevel += 4;
}
blocks.add(new Block((i*4)-64,-8+ heightlevel,(j*4)-64,4,4,4));
float y = -8+heightlevel;
for(int k = 0; k < 10; k++){
blocks.add(new Block((i*4)-64,y - (k*4),(j*4)-64,4,4,4));
}
}
}
}
}
There's a Block class as well:
public class Block {
public float x,y,z,width,height,depth,shade;
public Random rand;
public Block(float xx,float yy,float zz,float ww,float hh,float dd){
x = xx;
y = yy;
z = zz;
width = ww;
height = hh;
depth = dd;
rand = new Random();
shade = (rand.nextFloat()+0.2f);
}
public void tick(){
}
public void render(){
glBegin(GL_QUADS);
glColor3f(0,shade,0);
//Front
glTexCoord2f(0,0);
glVertex3f(x,y,z);
glTexCoord2f(1,0);
glVertex3f(x+width,y,z);
glTexCoord2f(1,1);
glVertex3f(x+width,y+height,z);
glTexCoord2f(0,1);
glVertex3f(x,y+height,z);
//Back
glVertex3f(x,y,z+depth);
glVertex3f(x+width,y,z+depth);
glVertex3f(x+width,y+height,z+depth);
glVertex3f(x,y+height,z+depth);
//Left
glVertex3f(x,y,z);
glVertex3f(x,y,z+depth);
glVertex3f(x,y+height,z+depth);
glVertex3f(x,y+height,z);
//Right
glVertex3f(x+width,y,z);
glVertex3f(x+width,y,z+depth);
glVertex3f(x+width,y+height,z+depth);
glVertex3f(x+width,y+height,z);
//Top
glVertex3f(x,y,z);
glVertex3f(x+width,y,z);
glVertex3f(x+width,y,z+depth);
glVertex3f(x,y,z+depth);
//Bottom
glVertex3f(x,y+height,z);
glVertex3f(x+width,y+height,z);
glVertex3f(x+width,y+height,z+depth);
glVertex3f(x,y+height,z+depth);
glEnd();
}
}

That is because you need to flip the calls. So it is like:
glRotatef(camera_rot, 0f, 1f, 0f);
glTranslatef(camera_x, camera_y, camera_z);
and not like this:
glTranslatef(camera_x, camera_y, camera_z);
glRotatef(camera_rot, 0f, 1f, 0f);
The reason is that you rotate the camera, and then you translate the camera. This gives the effect you are seeing, since it rotates using camera_rot, and then it translates according to camera_x, camera_y, camera_z.
Edit
You need to change this:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glRotatef(camera_rot, 0f, 1f, 0f);
glTranslatef(camera_x, camera_y, camera_z);
Into this:
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glRotatef(camera_rot, 0f, 1f, 0f);
glTranslatef(camera_x, camera_y, camera_z);
So when you've done that you will realize that your cameras position and rotation will be stuck. That is because each time you call tick()
You call:
camera_x = 0;
camera_y = 0;
camera_z = 0;
camera_rot = 0;
What that does is resetting the position and rotation, and that is why the camera "gets stuck".
So you need to change that so the values increment or decrement and not just stay at -1, 0 and 1.

There may be some mess with coordinates since they are also rotated. You can try rotating your (camera_x, camera_y, camera_z) vector, but I'd recommend you to use GLU.gluLookAt().
It does all the work for you, you just have to do some simple vector math to evaluate eye point, reference point and up vector from your camera_x, camera_y, camera_z and camera_rot values.
You can read gluLookAt specification and learn about Up vector.
UPD: Also I tried to mess with glTranslate* and glRotate* a bit, here is what I got:
while (!Display.isCloseRequested()) {
//clear:
GL11.glLoadIdentity();
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
GL11.glRotatef(90.0f, -1.0f, 0.0f, 0.0f); //with z axis looking up we get Oxy plane being wrong oriented, it is a little odd for me and I prefer to set z axis vertical ))
//rotate and translate:
GL11.glRotatef(camera_rot, 0.0f, 0.0f, 1.0f); //rotate
GL11.glTranslatef(camera_x, camera_y, camera_z); //translate
/* draw here */
//process input:
float move = 0.0f;
float strife = 0.0f;
if (Keyboard.isKeyDown(Keyboard.KEY_A)) {
strife -= 0.1f;
}
if (Keyboard.isKeyDown(Keyboard.KEY_D)) {
strife += 0.1f;
}
if (Keyboard.isKeyDown(Keyboard.KEY_W)) {
move += 0.1f;
}
if (Keyboard.isKeyDown(Keyboard.KEY_S)) {
move -= 0.1f;
}
//we move relatively to the direction we are looking
camera_x -= strife * Math.cos(Math.toRadians(rotp)) + move * Math.sin(Math.toRadians(rotp));
camera_y -= - strife * Math.sin(Math.toRadians(rotp)) + move * Math.cos(Math.toRadians(rotp));
camera_rot += Mouse.getDX();
//Display stuff
Display.update();
Display.sync(60);
}
This code works well for me.

Related

OpenGL doesn't draw with my own matrix

I am trying to make a 2D game with opengl.I made the the class which draw meshes.And i made my own Matrix4f class.I have experience with 3D opengl.
When i pass my matrix4f to the shader it doesn't draw.But when i remove it from multiplying with the position the triangle appears on the screen.I tried my Matrix4f from my 3D Game Engine but it doesn't work as well.
Matrix4f class
package com.game.main.maths;
import java.nio.FloatBuffer;
import com.game.main.util.Util;
public class Matrix4f {
private float[][] m;
public Matrix4f() {
m = new float[4][4];
initIdentity();
}
public Matrix4f initIdentity() {
for (int x = 0; x < 4; x++)
for (int y = 0; y < 4; y++) {
if (x == y)
m[x][y] = 1.0f;
else
m[x][y] = 0;
}
return this;
}
public Matrix4f translate(float x, float y, float z) {
initIdentity();
m[0][3] = x;
m[1][3] = y;
m[2][3] = z;
return this;
}
public Matrix4f translate(Vector3f pos) {
initIdentity();
m[0][3] = pos.getX();
m[1][3] = pos.getY();
m[2][3] = pos.getZ();
return this;
}
public Matrix4f rotate(float angle) {
initIdentity();
float rad = (float) Math.toRadians(angle);
float cos = (float) Math.cos(rad);
float sin = (float) Math.sin(rad);
m[0][0] = cos;
m[1][0] = sin;
m[0][1] = -sin;
m[1][1] = cos;
return this;
}
public Matrix4f initOrthographic(float left, float right, float bottom,
float top, float near, float far) {
initIdentity();
m[0][0] = 2.0f / (right - left);
m[1][1] = 2.0f / (top - bottom);
m[2][2] = 2.0f / (near - far);
m[0][3] = (left + right) / (left - right);
m[1][3] = (bottom + top) / (bottom - top);
m[2][3] = (near + far) / (far - near);
return this;
}
public Matrix4f mul(Matrix4f matrix) {
Matrix4f result = new Matrix4f();
for (int y = 0; y < 4; y++) {
for (int x = 0; x < 4; x++) {
float sum = 0.0f;
for (int index = 0; index < 4; index++)
sum += m[index][y] * matrix.get(x, index);
result.set(x, y, sum);
}
}
return result;
}
public float[][] getM() {
return m;
}
public float get(int x, int y) {
return m[x][y];
}
public void setM(float[][] m) {
this.m = m;
}
public void set(int x, int y, float value) {
m[x][y] = value;
}
public FloatBuffer toFloatBuffer() {
return Util.createFlippedBufferBuffer(this);
}
}
Shader class function
public void setUniform(String uniformName, Matrix4f matrix){
int uniformLocation = getUniformLocation(uniformName);
glUniformMatrix4(uniformLocation, false, matrix.toFloatBuffer());
}
Util class
package com.game.main.util;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import com.game.main.graphics.Vertex;
import com.game.main.maths.Matrix4f;
public class Util {
public static FloatBuffer createFlippedBuffer(float[] data){
FloatBuffer buffer = ByteBuffer.allocateDirect(data.length * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
buffer.put(data).flip();
return buffer;
}
public static IntBuffer createFlippedBuffer(int[] data){
IntBuffer buffer = ByteBuffer.allocateDirect(data.length * 4).order(ByteOrder.nativeOrder()).asIntBuffer();
buffer.put(data).flip();
return buffer;
}
public static IntBuffer createIntBuffer(int size){
IntBuffer buffer = ByteBuffer.allocateDirect(size * 4).order(ByteOrder.nativeOrder()).asIntBuffer();
return buffer;
}
public static FloatBuffer createFloatBuffer(int size){
FloatBuffer buffer = ByteBuffer.allocateDirect(size * 4).order(ByteOrder.nativeOrder()).asFloatBuffer();
return buffer;
}
public static FloatBuffer createFlippedBufferBuffer(Matrix4f matrix){
FloatBuffer buffer = createFloatBuffer(4 * 4);
for(int x = 0; x < 4; x++)
for(int y = 0; y < 4; y++)
buffer.put(matrix.get(x, y));
buffer.flip();
return buffer;
}
public static FloatBuffer createFlippedBuffer(Vertex[] vertecies){
FloatBuffer buffer = createFloatBuffer(vertecies.length * Vertex.SIZE);
for(int i = 0; i < vertecies.length; i++){
buffer.put(vertecies[i].getPos().getX());
buffer.put(vertecies[i].getPos().getY());
buffer.put(vertecies[i].getPos().getZ());
buffer.put(vertecies[i].getTexCoord().getX());
buffer.put(vertecies[i].getTexCoord().getY());
}
buffer.flip();
return buffer;
}
}
Initializing the matrix uniform
Matrix4f matrix = new Matrix4f().initOrthographic(0, 800, 0, 600, -1.0f, 1.0f);
Shader.Object.setUniform("mat", matrix);
Vertex Shader
#version 330
layout(location = 0) in vec3 pos;
uniform mat4 mat;
void main(){
gl_Position = mat * vec4(pos, 1.0f);
}
Mesh class
package com.game.main.graphics;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import com.game.main.util.Util;
public class Mesh {
private int vbo, ibo, size;
public Mesh(Vertex[] vertecies, int[] indices){
vbo = glGenBuffers();
ibo = glGenBuffers();
size = indices.length;
createMesh(vertecies, indices);
}
private void createMesh(Vertex[] vertecies, int[] indices){
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, Util.createFlippedBuffer(vertecies), GL_STATIC_DRAW);
glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glVertexAttribPointer(0, 3, GL_FLOAT, false, 5 * 4, 0);
glVertexAttribPointer(1, 2, GL_FLOAT, false, 5 * 4, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, Util.createFlippedBuffer(indices), GL_STATIC_DRAW);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
public void bind(){
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ibo);
}
public void unbind(){
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
public void drawWithBinding()
{
bind();
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
unbind();
}
public void draw(){
glDrawElements(GL_TRIANGLES, size, GL_UNSIGNED_INT, 0);
}
public void destroy(){
glDeleteBuffers(ibo);
glDeleteBuffers(vbo);
}
}
Vertex class
package com.game.main.graphics;
import com.game.main.maths.Vector2f;
import com.game.main.maths.Vector3f;
public class Vertex {
private Vector3f pos = new Vector3f();
private Vector2f texCoord = new Vector2f();
public static final int SIZE = 5;
public Vertex(Vector3f pos){
this(pos, new Vector2f());
}
public Vertex(Vector3f pos, Vector2f texCoord){
this.pos = pos;
this.texCoord = texCoord;
}
public Vector3f getPos() {
return pos;
}
public void setPos(Vector3f pos) {
this.pos = pos;
}
public Vector2f getTexCoord() {
return texCoord;
}
public void setTexCoord(Vector2f texCoord) {
this.texCoord = texCoord;
}
}
transpose code
public Matrix4f transpose() {
float m00 = get(0, 0);
float m01 = get(1, 0);
float m02 = get(2, 0);
float m03 = get(3, 0);
float m10 = get(0, 1);
float m11 = get(1, 1);
float m12 = get(2, 1);
float m13 = get(3, 1);
float m20 = get(0, 2);
float m21 = get(1, 2);
float m22 = get(2, 2);
float m23 = get(3, 2);
float m30 = get(0, 3);
float m31 = get(1, 3);
float m32 = get(2, 3);
float m33 = get(3, 3);
set(0, 0, m00);
set(0, 1, m01);
set(0, 2, m02);
set(0, 3, m03);
set(1, 0, m10);
set(1, 1, m11);
set(1, 2, m12);
set(1, 3, m13);
set(2, 0, m20);
set(2, 1, m21);
set(2, 2, m22);
set(2, 3, m23);
set(3, 0, m30);
set(3, 1, m31);
set(3, 2, m32);
set(3, 3, m33);
return this;
}
Game class
package com.game.main;
import static org.lwjgl.opengl.GL11.*;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import com.game.main.graphics.Mesh;
import com.game.main.graphics.Shader;
import com.game.main.graphics.Vertex;
import com.game.main.maths.Matrix4f;
import com.game.main.maths.Vector3f;
public class Game{
private boolean running = false;
private Mesh mesh;
public Game(int width, int height){
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle("2D Game");
Display.create();
} catch (LWJGLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
Matrix4f matrix = new Matrix4f().initOrthographic(-1, 1, -1, 1, -1.0f, 1.0f);
Shader.Object.setUniform("mat", matrix);
Vertex[] vertecies = new Vertex[]{
new Vertex(new Vector3f(0.5f, 0.5f, 0)),
new Vertex(new Vector3f(0.5f, 0,0)),
new Vertex(new Vector3f(0, 0.5f,0)),
new Vertex(new Vector3f(0.5f, 0,0))
};
/*float[] vertecies = new float[]{
-10f, -10f * 9.0f / 16.0f, 1,
-10f, 10f * 9.0f / 16.0f,1,
0, 10f * 9.0f / 1.0f,1,
0, -10f * 9.0f / 6.0f,1
};*/
int[] ind = new int[]{
0, 1, 2,
2, 3, 0
};
mesh = new Mesh(vertecies, ind);
}
private void init(){
glEnable(GL_DEPTH_TEST);
}
public void start(){
if(running)
return;
running = true;
gameLoop();
}
public void stop(){
if(!running)
return;
running = false;
}
private void gameLoop(){
init();
long timer = System.currentTimeMillis();
long lastTime = System.nanoTime();
double delta = 0;
int frames = 0, updates = 0;
while(running){
long now = System.nanoTime();
delta += (now - lastTime) / (1000000000.0 / 60.0);
lastTime = now;
while(delta >= 1){
if(Display.isCloseRequested())
stop();
update();
updates++;
delta--;
}
render();
frames++;
if(System.currentTimeMillis() - timer >= 1000){
timer += 1000;
Display.setTitle("Frames: "+frames+" Updates: "+updates);
frames = updates = 0;
}
}
destroy();
}
private void update(){
}
private void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
Shader.Object.bind();
mesh.drawWithBinding();
Shader.Object.unbind();
Display.update();
}
private void destroy(){
mesh.destroy();
Display.destroy();
}
}
It seems the problem is in setting the matrix uniform. OpenGL is a state machine and doesn't remember uniform values. More importantly, glUniformMatrix4 must be called while the shader is in use.
Currently, the matrix is set only at initialization (in the Game constructor), when it needs to be in render().
Shader.Object.bind(); //glUseProgram(programHandle)
Shader.Object.setUniform(...) //glUniformMatrix4
mesh.drawWithBinding(); //glDrawElements
Shader.Object.unbind(); //glUseProgram(0), but not necessary unless you want fixed function rendering
With mat not being set it'd probably be a zero matrix that was stopping things from drawing.
In addition to the above, there are two other potential issues:
Take a look in the bottom left of your screen and see if that pixel is on. I suspect everything's working, just really small. If the following works:
gl_Position = vec4(pos, 1.0f);
which is essentially a multiply by the identity matrix and nearly ortho(-1,1,-1,1,-1,1) (except the ortho call gives mat[2][2]=-1), then I'm guessing your mesh is around the size of a unit cube.
Introducing mat = initOrthographic(0, 800, 0, 600, -1.0f, 1.0f) looks like it's set up for a scene where vertices are given in pixels. The origin will be bottom left and if the mesh fits in a unit cube will draw to at most one pixel.
See #Jerem's answer about row/column major matrices.
It looks like your matrix is row major. You need to transpose it before sending it to the shader.
Note that there is a boolean parameter called transpose in glUniformMatrix4f but you can't use it in opengl es - the doc says it has to be false - you have to transpose it yourself.

Healthy way of drawing grid lines in LibGdx

So, I wanted to draw a grid in my game and as I was writing it out, it seemed incredibly unusual (at least to me) in terms of efficiency. I've got two for loops inside a render method which is used to render the game, so it is called very often and fast.
Is this ShapeRenderer portion a red flag?
public void render(float deltaTime) {
Gdx.gl.glClearColor(Color.GRAY.r, Color.GRAY.g, Color.GRAY.b, 1);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
batch.begin();
this.world.getPlayer().render(deltaTime, batch);
batch.end();
// Gridlines
shape.begin(ShapeType.Line);
shape.setColor(Color.BLACK);
for (int i = 0; i < Gdx.graphics.getHeight() / 32; i++) {
shape.line(0, i * 32, Gdx.graphics.getWidth(), i * 32);
}
for (int i = 0; i < Gdx.graphics.getWidth() / 32; i++) {
shape.line(i * 32, 0, i * 32, Gdx.graphics.getHeight());
}
shape.end();
}
You could use fast, simple and powerful ImmediateModeRenderer20.
Please have a look on the following code with PerspectiveCamera:
// init primitive renderer
ImmediateModeRenderer20 lineRenderer = new ImmediateModeRenderer20(false, true, 0);
// create atomic method for line
public static void line(float x1, float y1, float z1,
float x2, float y2, float z2,
float r, float g, float b, float a) {
lineRenderer.color(r, g, b, a);
lineRenderer.vertex(x1, y1, z1);
lineRenderer.color(r, g, b, a);
lineRenderer.vertex(x2, y2, z2);
}
// method for whole grid
public static void grid(int width, int height) {
for (int x = 0; x <= width; x++) {
// draw vertical
line(x, 0, 0,
x, 0, -height,
0, 1, 0, 0);
}
for (int y = 0; y <= height; y++) {
// draw horizontal
line(0, 0, -y,
width, 0, -y,
0, 1, 0, 0);
}
}
// init 3d camera
PerspectiveCamera perspectiveCamera = new PerspectiveCamera(55, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
// your render loop {
perspectiveCamera.update();
lineRenderer.begin(perspectiveCamera.combined, GL30.GL_LINES);
//... lineRenderer works a lot
grid(10, 10);
//... lineRenderer works a lot
lineRenderer.end();
//}
Hope it helps!

Java - Use the vertex buffer object (vbo) LWJGL

OK, I have the following code, i am trying to convert this code into the vertex buffer object render way. but it doesn't seem to work..
So here is the code:
package com.game.base;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.util.glu.GLU.gluPerspective;
import java.nio.FloatBuffer;
import java.util.Random;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Keyboard;
import com.game.display.graphics.Entity;
public class Game {
float speed = 0.0f;
float speedChange = 0.000001f;
int stars = 20000;
int starsDistance = 4000;
float starSize = 2.0f;
int vertices = 3;
int vertex_size = 3; // X, Y, Z,
int color_size = 3; // R, G, B,
Entity[] points;
Random random = new Random();
public Game() {
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
gluPerspective((float) 60, (float) (MainClass.WIDTH / MainClass.HEIGHT), 0.001f, 100);
glMatrixMode(GL_MODELVIEW);
glEnable(GL_DEPTH_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
points = new Entity[stars];
for (int i = 0; i < points.length; i++) {
points[i] = new Entity((random.nextFloat() - 0.5f) * 100f, (random.nextFloat() - 0.5f) * 100f, random.nextInt(starsDistance) - starsDistance);
}
}
public void render() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glTranslatef(0, 0, speed);
glPointSize(2.0f);
glBegin(GL_POINTS);
for (Entity p : points) {
glVertex3f(p.x, p.y, p.z);
}
glEnd();
}
public void update() {
}
public void dispose() {
}
public void input() {
if (Keyboard.isKeyDown(Keyboard.KEY_UP)) {
speed += speed < 0 ? speedChange * 5 : speedChange;
}
if (Keyboard.isKeyDown(Keyboard.KEY_DOWN)) {
speed -= speed > 0 ? speedChange * 5 : speedChange;
}
if (Keyboard.isKeyDown(Keyboard.KEY_SPACE)) {
speed = 0f;
}
if (Keyboard.isKeyDown(Keyboard.KEY_C)) {
speed = 0;
glLoadIdentity();
}
if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
MainClass.stop();
}
}
}
Any ideas how to convert this into VBO (Vertex Buffer Object) ?
Can someone convert this into VBO and show me how?
Thanks in Advance,
And I accept fast :)

SWT Transparent Button/Label

I have researched this for days. It appears that most folks want to place buttons on a transparent canvas or shell. I need to place transparent clickable objects over a canvas/component. In my testing I find that if I don't attempt to put the object on the canvas it simply never displays.
In the final project the application will be showing animated objects with a number of controls that I plan to use images for.
In the example I am trying to work out I have taken Snipped195 which displays a turning torus. I am attempting to place an image label over the torus such that as the torus turns it will show through the area of the label that is transparent. I have set up a gif file that is a red plus sign and has a transparent background. I also picked up some code (can't remember where it came from now) that is part of the paintControl method that looks for transparent pixels and builds a Region object. The region object obviously is doing what it needs to do to define where the image goes. Do I need to apply the region somehow to the image instead of the canvas?
At first when I tried to do this I did get the image displayed. However where the transparent areas where it displayed white. After implementing the paintControl code it at least handled the transparent area properly. Now I need to get the actual image content to display.
I built an object to take care of the image label. I called it TransparentImageLabel. It looks like:
public class TransparentImageLabel extends Canvas {
private Image labelImage;
public TransparentImageLabel(Composite parent, Image image, int style) {
super(parent, style);
this.labelImage = image;
addDisposeListener(new DisposeListener() {
public void widgetDisposed(DisposeEvent e) {
TransparentImageLabel.this.widgetDisposed(e);
}
});
addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
TransparentImageLabel.this.paintControl(e);
}
});
}
private void widgetDisposed(DisposeEvent e) {
}
private void paintControl(PaintEvent event) {
System.out.println("at paint control");
ImageData imgData = this.labelImage.getImageData();
Region region = new Region();
if (imgData.alphaData != null) {
Rectangle pixel = new Rectangle(0, 0, 1, 1);
for (int y = 0; y < imgData.height; y++) {
for (int x = 0; x < imgData.width; x++) {
if (imgData.getAlpha(x, y) == 255) {
pixel.x = imgData.x + x;
pixel.y = imgData.y + y;
region.add(pixel);
}
}
}
} else {
ImageData mask = imgData.getTransparencyMask();
Rectangle pixel = new Rectangle(0, 0, 1, 1);
for (int y = 0; y < mask.height; y++) {
for (int x = 0; x < mask.width; x++) {
if (mask.getPixel(x, y) != 0) {
pixel.x = imgData.x + x;
pixel.y = imgData.y + y;
region.add(pixel);
}
}
}
}
this.setRegion(region);
event.gc.drawImage(labelImage, this.getBounds().x, this.getBounds().y);
region.dispose();
}
}
After adding this to Snipped195 the code looks like:
public class Snippet195 {
private Image redPlus;
static void drawTorus(float r, float R, int nsides, int rings) {
float ringDelta = 2.0f * (float) Math.PI / rings;
float sideDelta = 2.0f * (float) Math.PI / nsides;
float theta = 0.0f, cosTheta = 1.0f, sinTheta = 0.0f;
for (int i = rings - 1; i >= 0; i--) {
float theta1 = theta + ringDelta;
float cosTheta1 = (float) Math.cos(theta1);
float sinTheta1 = (float) Math.sin(theta1);
GL11.glBegin(GL11.GL_QUAD_STRIP);
float phi = 0.0f;
for (int j = nsides; j >= 0; j--) {
phi += sideDelta;
float cosPhi = (float) Math.cos(phi);
float sinPhi = (float) Math.sin(phi);
float dist = R + r * cosPhi;
GL11.glNormal3f(cosTheta1 * cosPhi, -sinTheta1 * cosPhi, sinPhi);
GL11.glVertex3f(cosTheta1 * dist, -sinTheta1 * dist, r * sinPhi);
GL11.glNormal3f(cosTheta * cosPhi, -sinTheta * cosPhi, sinPhi);
GL11.glVertex3f(cosTheta * dist, -sinTheta * dist, r * sinPhi);
}
GL11.glEnd();
theta = theta1;
cosTheta = cosTheta1;
sinTheta = sinTheta1;
}
}
private Snippet195() {
final Display display = new Display();
Shell shell = new Shell(display, SWT.NO_REDRAW_RESIZE);
shell.setLayout(new FillLayout());
Composite comp = new Composite(shell, SWT.NONE);
comp.setLayout(new FillLayout());
GLData data = new GLData();
data.doubleBuffer = true;
redPlus = new Image(shell.getDisplay(), new ImageData(
Snippet237.class.getResourceAsStream("/red-plus.png")));
final GLCanvas canvas = new GLCanvas(comp, SWT.NONE, data);
canvas.addPaintListener(new PaintListener() {
public void paintControl(PaintEvent e) {
e.gc.setAlpha(15);
e.gc.drawImage(Snippet195.this.redPlus, 0, 0);
}
});
canvas.setCurrent();
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
canvas.addListener(SWT.Resize, new Listener() {
public void handleEvent(Event event) {
Rectangle bounds = canvas.getBounds();
float fAspect = (float) bounds.width / (float) bounds.height;
canvas.setCurrent();
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glViewport(0, 0, bounds.width, bounds.height);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GLU.gluPerspective(45.0f, fAspect, 0.5f, 400.0f);
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
}
});
GL11.glClearColor(1.0f, 1.0f, 1.0f, 1.0f);
GL11.glColor3f(1.0f, 0.0f, 0.0f);
GL11.glHint(GL11.GL_PERSPECTIVE_CORRECTION_HINT, GL11.GL_NICEST);
GL11.glClearDepth(1.0);
GL11.glLineWidth(2);
GL11.glEnable(GL11.GL_DEPTH_TEST);
TransparentImageLabel redPlusLabel = new TransparentImageLabel(canvas,
redPlus, SWT.NONE);
redPlusLabel.setSize(48, 48);
redPlusLabel.setLocation(500, 200);
shell.setText("SWT/LWJGL Example");
shell.setSize(880, 720);
shell.open();
final Runnable run = new Runnable() {
int rot = 0;
public void run() {
if (!canvas.isDisposed()) {
canvas.setCurrent();
try {
GLContext.useContext(canvas);
} catch (LWJGLException e) {
e.printStackTrace();
}
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT
| GL11.GL_DEPTH_BUFFER_BIT);
GL11.glClearColor(.3f, .5f, .8f, 1.0f);
GL11.glLoadIdentity();
GL11.glTranslatef(0.0f, 0.0f, -10.0f);
float frot = rot;
GL11.glRotatef(0.15f * rot, 2.0f * frot, 10.0f * frot, 1.0f);
GL11.glRotatef(0.3f * rot, 3.0f * frot, 1.0f * frot, 1.0f);
rot++;
GL11.glPolygonMode(GL11.GL_FRONT_AND_BACK, GL11.GL_LINE);
GL11.glColor3f(0.9f, 0.9f, 0.9f);
drawTorus(1, 1.9f + ((float) Math.sin((0.004f * frot))), 25, 75);
canvas.swapBuffers();
display.asyncExec(this);
}
}
};
canvas.addListener(SWT.Paint, new Listener() {
public void handleEvent(Event event) {
run.run();
}
});
display.asyncExec(run);
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
public static void main(String[] args) {
new Snippet195();
}
}
I have to be close. The areas of the image that are defined as transparent are being drawn as transparent. But I'm not getting anything but a white plus instead of the red that is in the image.
The problem is in your TransparentImageLabel#paintControl(..) method. Correct the second last line to the following:
event.gc.drawImage(labelImage, 0, 0);
Since you are drawing within the context of the canvas so the coordinates you specify for location should be relative to that Canvas. You are currently using the location of canvas which is returned relative to it's parent.

java.io.IOException Difficulty when adding "player" texture into screen

I get this strange error from loading "Player.png" file from the Player Class.
I understand that my organization of the code is very sloppy and the methods I use are terrible. half of the code is borrowed from tutorials.
What 2 classes are supposed to do is create a screen with green colored tiles filling up the screen with a "player" sprite that can move right, left, up, and down with the W,A,S,D keys.
error:
java.io.IOException: Attempt to allocate a texture to big for the current hardware
at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:293)
at org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:231)
at
org.newdawn.slick.opengl.InternalTextureLoader.getTexture(InternalTextureLoader.java:184)
at org.newdawn.slick.opengl.TextureLoader.getTexture(TextureLoader.java:64)
at org.newdawn.slick.opengl.TextureLoader.getTexture(TextureLoader.java:24)
at test.PlayerClass.render(PlayerClass.java:69)
at test.Main.render(Main.java:110)
at test.Main.run(Main.java:82)
at test.Main.main(Main.java:27)
Main Class
public class Main{
private static boolean running = true;
public static final int WIDTH = 1024;
public static final int HEIGHT = 768;
private static Texture tile;
static PlayerClass playerClass = new PlayerClass(100, 100, 32, 32);
public static void main(String[] args){
Main main = new Main();
main.run();
}
//Initialize Method
public static void init(int width, int height ) throws LWJGLException
{
DisplayMode[] m = Display.getAvailableDisplayModes();
for(DisplayMode mode : m)
{
if(mode.getWidth() == 1024 && mode.getHeight() == 768 && mode.getBitsPerPixel() == 32)
{
Display.setDisplayMode(mode);
}
}
Display.setTitle("Game");
Display.setVSyncEnabled(true);
Display.sync(100);
Display.create();
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
GL11.glOrtho(0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight(), 0, -1, 1 );
GL11.glMatrixMode(GL11.GL_MODELVIEW);
GL11.glLoadIdentity();
GL11.glEnable(GL11.GL_ALPHA_TEST);
GL11.glAlphaFunc(GL11.GL_GREATER, 0.2f);
GL11.glEnable(GL11.GL_TEXTURE_2D);
try {
tile = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("RPG/tile.png"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
public void run()
{
try {
init(1024, 768);
} catch (LWJGLException e) {
e.printStackTrace();
}
while(running)
{
Display.update();
drawTiled(WIDTH, HEIGHT);
input();
update();
render();
}
cleanup();
}
public static void input()
{
if(Keyboard.isKeyDown(Keyboard.KEY_ESCAPE))
{
running = false;
}
playerClass.input();
}
public static void update()
{
}
public static void render()
{
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT);
GL11.glLoadIdentity();
try {
playerClass.render();
} catch (IOException e) {
e.printStackTrace();
}
Display.update();
}
public static void cleanup()
{
Display.destroy();
}
public void drawTiled(int screenWidth, int screenHeight) {
Color.white.bind();
tile.bind();
int numberPerRow = screenWidth / tile.getTextureWidth();
int numberOfRows = screenHeight / tile.getTextureHeight();
GL11.glBegin(GL11.GL_QUADS);
for (int j = 0; j < numberOfRows; j++) {
//System.out.print("{");
for (int i = 0; i < numberPerRow; i++)
{
//top left
GL11.glTexCoord2f(0, 0);
GL11.glVertex2f(tile.getTextureWidth() * i, tile.getTextureHeight() * j);
//top right
GL11.glTexCoord2f(1, 0);
GL11.glVertex2f(tile.getTextureWidth() * (i + 1), tile.getTextureHeight() * j);
//bottom right
GL11.glTexCoord2f(1, 1);
GL11.glVertex2f(tile.getTextureWidth() * (i + 1), tile.getTextureHeight() * (j + 1));
//bottom left
GL11.glTexCoord2f(0, 1);
GL11.glVertex2f(tile.getTextureWidth() * i, tile.getTextureHeight() * (j + 1));
}
}
}
}
Player Class
public class PlayerClass {
private float x, y;
private int w, h;
private Texture player;
private FloatBuffer verts = BufferUtils.createFloatBuffer(2 * 4);
private FloatBuffer tex = BufferUtils.createFloatBuffer(2 * 4);
public PlayerClass(float X, float Y, int W, int H)
{
x = X;
y = Y;
w = W;
h = H;
verts.put(new float[]{
0.0f, 0.0f,
32.0f, 0.0f,
32.0f, 32.0f,
0.0f, 32.0f
});
tex.put(new float[]{
0.0f, 0.0f,
1.0f, 0.0f,
1.0f, 1.0f,
0.0f, 1.0f
});
}
public void input()
{
if(Keyboard.isKeyDown(Keyboard.KEY_W))
{
y -= 10;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_S))
{
y += 10;
}
if(Keyboard.isKeyDown(Keyboard.KEY_A))
{
x -= 10;
}
else if(Keyboard.isKeyDown(Keyboard.KEY_D))
{
x += 10;
}
}
public void render() throws IOException
{
player = TextureLoader.getTexture("PNG", ResourceLoader.getResourceAsStream("RPG/player.png"));
player.bind();
verts.rewind();
tex.rewind();
GL11.glEnableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glEnableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
GL11.glTranslatef(x, y, 0.0f);
GL11.glVertexPointer(2, 0, verts);
GL11.glTexCoordPointer(2, 0, tex);
GL11.glDrawArrays(GL11.GL_QUADS, 0, 4);
GL11.glTranslatef(-x, -y, 0.0f);
GL11.glDisableClientState(GL11.GL_VERTEX_ARRAY);
GL11.glDisableClientState(GL11.GL_TEXTURE_COORD_ARRAY);
}
}
Run this:
System.out.println(GL11.glGetInteger(GL11.GL_MAX_TEXTURE_SIZE));
It'll tell you the max texture size allowed by your Graphics card. Make sure that your graphics card can handle a texture of the size that you are trying to use. According to the error, it can't.
How large is tile.png - the maximum texture size can vary depending your card, and I think, some other factors. Your file is probably outside this dimension.
Cody's answer gives you the way to get the max texture size for your card. If you're writing a game for use by many other people, you'll probably want to integrate that code into your game code in such a way that it loads different resolution textures based on the capabilities of the card it's running on, or simply find a default that works on any card that you want to support, and use that for all installations.
Here's some additional reading that will explain more about this issue, some history about it, and more technical info that you might find useful:
Official OpenGL wiki on 'Texture'
List of maximum texture size by video card (from 2006, but you'll get the idea)
An FAQ of texture mapping

Categories