Java LWJGL OPENGL trying to render .obj file with no success - java

I'm trying to render a 3D model of a bunny.
I tried to render the .obj file but nothing shows up on my screen, here's the code :
MainDisplay class :
Code:
package com.dryadengine.gui;
import com.dryadengine.core.Model;
import com.dryadengine.framework.OBJLoader;
import com.dryadengine.framework.ShaderFactory;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.BufferUtils;
import org.lwjgl.opengl.Display;
import org.lwjgl.opengl.DisplayMode;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL15.*;
import static org.lwjgl.opengl.GL20.*;
import org.lwjgl.util.vector.Matrix4f;
/**
*
* #author Roy
*/
public class MainDisplay {
private Model bunny;
private Matrix4f mProjection;
private Matrix4f mView;
private Matrix4f mModel;
private int shaderProgramID;
private int vboID;
private int vPositionID;
private int mProjectionID;
private int mViewID;
private int mModelID;
/**
* #param args the command line arguments
*/
public static void main(String[] args) {
MainDisplay md = new MainDisplay();
md.create();
md.init();
md.run();
}
public MainDisplay() {
}
public void create() {
try {
Display.setDisplayMode(new DisplayMode(800, 600));
Display.setTitle("Dryad Engine 1.0.0");
Display.setFullscreen(false);
Display.setResizable(true);
Display.create();
} catch (LWJGLException ex) {
Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
System.exit(-1);
}
}
public void init() {
glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
try {
shaderProgramID = ShaderFactory.createShaderProgram("vertexShader", "fragmentShader");
glUseProgram(shaderProgramID);
bunny = OBJLoader.parseOBJ(new File("src/com/dryadengine/assets/bunny.obj"));
FloatBuffer vbo = BufferUtils.createFloatBuffer(bunny.getVertices().length);
vbo.put(bunny.getVertices());
vbo.flip();
vboID = glGenBuffers();
glBindBuffer(GL_ARRAY_BUFFER, vboID);
glBufferData(GL_ARRAY_BUFFER, vbo, GL_STATIC_DRAW);
vPositionID = glGetAttribLocation(shaderProgramID, "vPosition");
glEnableVertexAttribArray(vPositionID);
mProjection = new Matrix4f();
float fieldOfView = 60f;
float aspectRatio = (float)Display.getWidth() / (float)Display.getHeight();
float nearPlane = 0.1f;
float farPlane = 100f;
float yScale = (float)(1.0f / Math.tan((fieldOfView / 2.0f) * Math.PI / 180));//this.coTangent(this.degreesToRadians(fieldOfView / 2f));
float xScale = yScale / aspectRatio;
float frustum_length = farPlane - nearPlane;
mProjection.m00 = xScale;
mProjection.m11 = yScale;
mProjection.m22 = -((farPlane + nearPlane) / frustum_length);
mProjection.m23 = -1;
mProjection.m32 = -((2 * nearPlane * farPlane) / frustum_length);
mProjection.m33 = 0;
mView = new Matrix4f();
mView.m23 = -5;
mModel = new Matrix4f();
mProjectionID = glGetUniformLocation(shaderProgramID, "mProjection");
mViewID = glGetUniformLocation(shaderProgramID, "mView");
mModelID = glGetUniformLocation(shaderProgramID, "mModel");
glEnable(GL_CULL_FACE);
glCullFace(GL_BACK);
glEnable(GL_DEPTH_TEST);
} catch (FileNotFoundException ex) {
Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
} catch (IOException ex) {
Logger.getLogger(MainDisplay.class.getName()).log(Level.SEVERE, null, ex);
}
}
public void run() {
while (!Display.isCloseRequested()) {
if (Display.isVisible()) {
render();
}
if (Display.wasResized()) {
reshape();
}
Display.update();
Display.sync(60);
}
destroy();
}
public void render() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
FloatBuffer fb1 = BufferUtils.createFloatBuffer(16);
FloatBuffer fb2 = BufferUtils.createFloatBuffer(16);;
FloatBuffer fb3 = BufferUtils.createFloatBuffer(16);;
mProjection.store(fb1);
mView.store(fb2);
mModel.store(fb3);
glUniformMatrix4(mProjectionID, true, fb1);
glUniformMatrix4(mViewID, true, fb2);
glUniformMatrix4(mModelID, true, fb3);
for (int i = 0; i < bunny.getVertices().length / 3; i += 3) {
glVertexAttribPointer(vPositionID, 3, GL_FLOAT, false, 0, i);
glDrawArrays(GL_TRIANGLES, 0, 3);
}
}
public void reshape() {
glViewport(0, 0, Display.getWidth(), Display.getHeight());
}
public void dispose() {
glDeleteProgram(shaderProgramID);
glUseProgram(0);
glDeleteBuffers(vboID);
glBindBuffer(GL_ARRAY_BUFFER, 0);
}
public void destroy() {
Display.destroy();
}
}
ShaderFactory class :
package com.dryadengine.framework;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import org.lwjgl.LWJGLException;
import org.lwjgl.opengl.Display;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
/**
*
* #author Roy
*/
public class ShaderFactory {
private static final String COMMON_SHADERS_PATH = "/com/dryadengine/shaders/";
private static final String SHADER_EXTENSION = ".dsf";
/**
*
* #param vertexShaderName
* #param fragmentShaderName
* #return a shader program
* #throws FileNotFoundException
* #throws IOException
*/
public static int createShaderProgram(String vertexShaderName, String fragmentShaderName) throws FileNotFoundException, IOException {
ArrayList<Integer> shaders = new ArrayList();
shaders.add(ShaderFactory.compileShader(GL_VERTEX_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + vertexShaderName + SHADER_EXTENSION)));
shaders.add(ShaderFactory.compileShader(GL_FRAGMENT_SHADER, getShaderFileCode(COMMON_SHADERS_PATH + fragmentShaderName + SHADER_EXTENSION)));
return ShaderFactory.linkProgram(shaders);
}
/**
*
* #param shaderFilePath
* #return a shader file code
* #throws FileNotFoundException
* #throws IOException
*/
private static String getShaderFileCode(String shaderFilePath) throws FileNotFoundException, IOException {
StringBuilder shaderCode = new StringBuilder();
String line;
try {
try (BufferedReader br = new BufferedReader(new InputStreamReader(ShaderFactory.class.getResourceAsStream(shaderFilePath)))) {
while ((line = br.readLine()) != null) {
shaderCode.append(line).append("\n");
}
}
} catch (FileNotFoundException e) {
throw new FileNotFoundException(e.getMessage());
}
return shaderCode.toString();
}
/**
*
* #param shaderType
* #param shaderCode
* #return a compiled shader file id
*/
public static int compileShader(int shaderType, String shaderCode) {
int shaderID = glCreateShader(shaderType);
glShaderSource(shaderID, shaderCode);
glCompileShader(shaderID);
int status = glGetShaderi(shaderID, GL_COMPILE_STATUS);
if (status == GL_FALSE) {
glDeleteShader(shaderID);
throw new RuntimeException(glGetShaderInfoLog(shaderID, glGetShaderi(shaderID, GL_INFO_LOG_LENGTH)));
}
return shaderID;
}
/**
* Link the vertex shader and the fragment shader to the shader program
* #param shaders
* #return a shader program
*/
public static int linkProgram(ArrayList <Integer> shaders) {
int shaderProgramID = glCreateProgram();
for (Integer shader : shaders) {
glAttachShader(shaderProgramID, shader);
}
glLinkProgram(shaderProgramID);
int status = glGetProgrami(shaderProgramID, GL_LINK_STATUS);
if (status == GL_FALSE) {
glDeleteProgram(shaderProgramID);
throw new RuntimeException(glGetShaderInfoLog(shaderProgramID, glGetProgrami(shaderProgramID, GL_INFO_LOG_LENGTH)));
}
for (int shader : shaders) {
glDeleteShader(shader);
}
return shaderProgramID;
}
}
OBJLoader class :
package com.dryadengine.framework;
import com.dryadengine.core.Model;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
*
* #author Roy
*/
public class OBJLoader {
/**
* Parse .obj file and make a model from it.
* #param f
* #return a model object
* #throws FileNotFoundException
* #throws IOException
*/
public static Model parseOBJ(File f) throws FileNotFoundException, IOException {
BufferedReader br = new BufferedReader(new FileReader(f));
String line;
Model m;
List<Float> vertices = new ArrayList<>();
List<Float> normals = new ArrayList<>();
while ((line = br.readLine()) != null) {
if (line.startsWith("v")) {
float x = Float.valueOf(line.split(" ")[1]);
float y = Float.valueOf(line.split(" ")[2]);
float z = Float.valueOf(line.split(" ")[3]);
vertices.add(x);
vertices.add(y);
vertices.add(z);
} else if (line.startsWith("vn")) {
float x = Float.valueOf(line.split(" ")[1]);
float y = Float.valueOf(line.split(" ")[2]);
float z = Float.valueOf(line.split(" ")[3]);
normals.add(x);
normals.add(y);
normals.add(z);
}
}
br.close();
float[] a = new float[vertices.size()];
float[] b = new float[normals.size()];
for (int i = 0; i < vertices.size(); i++) {
a[i] = vertices.get(i);
}
for (int i = 0; i < normals.size(); i++) {
b[i] = normals.get(i);
}
m = new Model(a, b);
return m;
}
}
Model class :
package com.dryadengine.core;
/**
*
* #author Roy
*/
public class Model {
private float[] vertices;
private float[] normals;
/**
* Construct a new model object.
* #param vertices
* #param normals
*/
public Model(float[] vertices, float[] normals) {
this.vertices = vertices;
this.normals = normals;
}
/**
*
* #return the model vertices array
*/
public float[] getVertices() {
return vertices;
}
/**
*
* #return the model normals array
*/
public float[] getNormals() {
return normals;
}
}
vertex shader code :
#version 330
uniform mat4 mProjection;
uniform mat4 mView;
uniform mat4 mModel;
in vec4 vPosition;
void main()
{
gl_Position = mProjection * mView * mModel * vPosition;
}
fragment shader code :
#version 330
out vec4 color;
void main()
{
color = vec4(1.0, 0.0, 0.0, 1.0);
}
Result is just black screen

I'm not sure if anything else is wrong since I'm not too experienced with GL, but I noticed that in your OBJLoader class, you're checking if a line starts with 'v' first.
if (line.startsWith("v")) {
} else if (line.startsWith("vn")) {
}
This means that if it detects a 'vn', then it will be handled by the first part of the statement since 'vn' starts with 'v'. The second part of the statement never gets executed. You could either check for 'vn' first, or add a space after 'v', checking for 'v '.

You are doing something very strange in your render (...) method; issuing 1 draw call per-triangle.
With the way your data is laid out, you should be able to draw all of your triangles in a single call if you pass the number of vertices in the array instead of setting up a different vertex pointer and passing the value 3 for each triangle.
glVertexAttribPointer (vPositionID, 3, GL_FLOAT, false, 0, 0);
glDrawArrays (GL_TRIANGLES, 0, bunny.getVertices ().length / 3);
You are also telling GL to transpose your matrices by passing true to glUniformMatrix4. If you transpose your matrices, then you need to reverse the order of your matrix multiplication in the vertex shader for proper transformation.
void main()
{
gl_Position = vPosition * mModel * mView * mProjection;
}
This runs counter to everything you should be learning in OpenGL (column-major matrices), so rather than modifying your vertex shader that way you should really just stop passing true.

Related

rendering 3d lwjgl flat terrain doesn't work

import static org.lwjgl.glfw.GLFW.*;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL20.*;
import java.io.BufferedReader;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.nio.DoubleBuffer;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import static org.lwjgl.opengl.GL15.*;
import org.lwjgl.BufferUtils;
import org.lwjgl.glfw.GLFWCursorPosCallback;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL15;
import org.lwjgl.opengl.GL20;
import org.lwjgl.system.MemoryUtil;
import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;
import org.omg.Messaging.SYNC_WITH_TRANSPORT;
public class man {
private static final int VERTEX_COUNT = 128;
private static final float SIZE = 1;
public static int count;
public static int vid;
public static int iid;
public static int program;
public static float fov = 70f;
public static float near = 0.1f;
public static float far = 1000f;
public static Matrix4f modelMatrix = new Matrix4f() ;
public static Matrix4f view = new Matrix4f();
public static Matrix4f projectionmatrix = new Matrix4f();
public static GLFWCursorPosCallback mouseCallback;
public static boolean t = true;
public static void main(String[] argv) throws IOException {
glfwInit();
int prog = 0 , id=0;
long window = glfwCreateWindow(1920,
1080, "HI", 0 , 0);
glfwShowWindow(window);
glfwMakeContextCurrent(window);
GL.createCapabilities();
// glfwSetCursorPosCallback(window, mouseCallback = new mouse());
while (!glfwWindowShouldClose(window))
{
glfwSwapBuffers(window);
glfwPollEvents();
new man().createShader();
new man().bind();
GL11.glClear(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_COLOR_BUFFER_BIT);
GL11.glEnable(GL11.GL_DEPTH_TEST);
GL11.glLoadIdentity();
glEnable(GL_PROJECTION_MATRIX);
glEnable(GL_PROJECTION);
new man().createprojection();
new man().createview();
glUseProgram(program);
new man().loadtoshader();
glEnableClientState(GL_VERTEX_ARRAY);
glBindBuffer(GL_ARRAY_BUFFER, vid);
glVertexPointer(3, GL_FLOAT , 0, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, iid);
glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, 0);
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
glDisable(GL_VERTEX_ARRAY);
}
}
public void createShader() throws IOException
{
StringBuilder vertex = new StringBuilder();
StringBuilder frag = new StringBuilder();
BufferedReader vert ,fragment;
vert = new BufferedReader(new FileReader("D:/work/opengl2/src/opengl2/vertexShader.txt"));
fragment = new BufferedReader(new FileReader("D:/work/opengl2/src/opengl2/frageShader.txt"));
//vertex Shader
String line, line2;
while ( (line = vert.readLine()) != null)
{
vertex.append(line).append('\n');
}
while ( (line2 = fragment.readLine()) != null)
{
frag.append(line2).append('\n');
}
//create and comile shaders
int vertexShader = GL20.glCreateShader(GL20.GL_VERTEX_SHADER);
GL20.glShaderSource(vertexShader, vertex);
GL20.glCompileShader(vertexShader);
int fragmentShader = GL20.glCreateShader(GL20.GL_FRAGMENT_SHADER);
GL20.glShaderSource(fragmentShader, frag);
GL20.glCompileShader(fragmentShader);
program = GL20.glCreateProgram();
GL20.glAttachShader(program, vertexShader);
GL20.glAttachShader(program, fragmentShader);
GL20.glBindAttribLocation(program, 0 , "postion");
GL20.glLinkProgram(program);
if (GL20.glGetProgrami(program, GL20.GL_LINK_STATUS) != 1)
{
System.err.println(GL20.glGetProgramInfoLog(program));
System.exit(1);
}
GL20.glValidateProgram(program);
}
public void bind()
{
float[] vertices = new float[128 * 128 * 3];
int[] indices = new int[6*(VERTEX_COUNT-1)*(VERTEX_COUNT-1)];
//generaete terrain
int vertexPointer = 0;
for(int i=0;i<VERTEX_COUNT;i++){
for(int j=0;j<VERTEX_COUNT;j++){
vertices[vertexPointer*3] = (float)j/((float)VERTEX_COUNT - 1) * SIZE;
vertices[vertexPointer*3+1] = 0;
vertices[vertexPointer*3+2] = (float)i/((float)VERTEX_COUNT - 1) * SIZE;
vertexPointer++;
}
}
int pointer = 0;
for(int gz=0;gz<VERTEX_COUNT-1;gz++){
for(int gx=0;gx<VERTEX_COUNT-1;gx++){
int topLeft = (gz*VERTEX_COUNT)+gx;
int topRight = topLeft + 1;
int bottomLeft = ((gz+1)*VERTEX_COUNT)+gx;
int bottomRight = bottomLeft + 1;
indices[pointer++] = topLeft;
indices[pointer++] = bottomLeft;
indices[pointer++] = topRight;
indices[pointer++] = topRight;
indices[pointer++] = bottomLeft;
indices[pointer++] = bottomRight;
}
}
//end generate terrain
FloatBuffer buffer = BufferUtils.createFloatBuffer(vertices.length);
buffer.put(vertices);
buffer.flip();
count = indices.length ;
vid = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, vid);
GL15.glBufferData(GL15.GL_ARRAY_BUFFER, buffer, GL15.GL_STATIC_DRAW);
iid = GL15.glGenBuffers();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, iid);
IntBuffer indbuf = BufferUtils.createIntBuffer(indices.length);
indbuf.put(indices);
indbuf.flip();
GL15.glBufferData(GL15.GL_ELEMENT_ARRAY_BUFFER, indbuf, GL15.GL_STATIC_DRAW);
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL15.glBindBuffer(GL15.GL_ARRAY_BUFFER, 0);
}
public void createprojection()
{
float aspect = (float) 1920/1080;
float y_scale = (float) (1/Math.tan(Math.toRadians(fov/2f)));
float x_scale = y_scale / aspect;
float frustum_length = far - near;
projectionmatrix.m00 = x_scale;
projectionmatrix.m11 = y_scale;
projectionmatrix.m22 = -((far + near) / frustum_length);
projectionmatrix.m23 = -1;
projectionmatrix.m32 = -((2 * near * far) / frustum_length);
projectionmatrix.m33 = 0;
}
public void createview()
{
Vector3f modelPos = null;
Vector3f modelAngle = null;
Vector3f modelScale = null;
Vector3f camera = new Vector3f(0,1f,-2f);
modelPos = new Vector3f(0,0,0);
modelAngle = new Vector3f(0,0,0);
modelScale = new Vector3f(1, 1, 1);
modelMatrix.setIdentity();
Matrix4f.scale(modelScale, modelMatrix, modelMatrix);
Matrix4f.translate(modelPos, modelMatrix, modelMatrix);
Matrix4f.rotate((float) Math.toRadians(modelAngle.z), new Vector3f(0, 0, 1),
modelMatrix, modelMatrix);
Matrix4f.rotate((float) Math.toRadians(modelAngle.y), new Vector3f(0, 1, 0),
modelMatrix, modelMatrix);
Matrix4f.rotate((float) Math.toRadians(modelAngle.x), new Vector3f(1, 0, 0),
modelMatrix, modelMatrix);
Matrix4f.translate(camera, view, view);
}
public void loadtoshader()
{
int loc1 = glGetUniformLocation(program, "projection");
FloatBuffer matrixx = BufferUtils.createFloatBuffer(16);
projectionmatrix.store(matrixx);
matrixx.flip();
glUniformMatrix4fv(loc1, false,matrixx);
int loc2 = glGetUniformLocation(program, "view");
FloatBuffer matrixx2 = BufferUtils.createFloatBuffer(16);
view.store(matrixx2);
matrixx2.flip();
glUniformMatrix4fv(loc2, false,matrixx2);
int loc3 = glGetUniformLocation(program, "model");
FloatBuffer matrixx3 = BufferUtils.createFloatBuffer(16);
modelMatrix.store(matrixx3);
matrixx3.flip();
glUniformMatrix4fv(loc3, false,matrixx3);
}
}
class mouse extends GLFWCursorPosCallback
{
#Override
public void invoke(long arg0, double x, double y) {
// TODO Auto-generated method stub
System.out.println(x+ " "+ y );
}
}
Hi guys !
I want to generate a simple flat terrain in lwjgl but this code doesn't produce me anything. I am very new in this chapter so if you can explain why this code does nothing please do it! I am generating the terrain with the code shared by ThinMatrix , then i upload the vertices to the buffers and then render them in the main game loop . When i compile it , it shows me a black screen. I have searched for a lot of tutorials but I didn't find anything that can help me .
I see several issues with your code:
Issue Number 1: You are generating a new instance of the man class on every iteration of the loop. Create a single instance of the object outside of the loop and use it in the loop.
Issue Number 2: You are using the old, static pipeline OpenGL. Following ThinMatrix's tutorials, you should be using OpenGL 3 or newer. Everything should be going through shaders, rather than using the GL_PROJECTION_MATRIX and the likes of that.
Your program should look something like the following:
man instance = new man()
while (!glfwWindowShouldClose(window))
{
RENDER THE TERRAIN HERE
glfwPoll
glfwSwapBuffers
glClear
}
If you want some example code, I have a repository here that should help, as I used to watch ThinMatrix tutorials.
EDIT: SOLUTION
The vertex shader code should read:
gl_Position = projection * view * model * position;
My shaders: fragment
#version 330
in vec4 pos;
void main()
{
gl_FragColor = vec4 (pos);
}
vertex:
#version 330
attribute vec3 postion;
uniform mat4 projection;
uniform mat4 view;
uniform mat4 model;
out vec4 pos;
void main()
{
gl_Position = vec4(postion, 1.0) * projection * view * model;
pos = vec4(postion, 1.0) ;
}
I have updated my java code so it renders different colors base on the vertex position.

OpenGL ES 1.0 strange texture behavior

I am learning how to work with OpenGL ES 1.0 (I was told that it is better to start with "1.0"/"1.1").
I am trying to create transperent 3D globe on android device using transparent texture and vertex indexing but having problem which I don't understand and can't find any solution on internet.
The problem is that depending on angle of camera rotation my globe stops rendering "back side" of sphere or sphere back sides texture. On image below you can see what happens if I rotate camera in same direction.
Link to image: CLICK HERE (I have no reputation to add image directly, sorry)
So can you help me? What is my mistake, why "back" is disappearing?
"Sphere" class:
package com.example.OpenGL_Testing.openGl.geometry;
import com.example.OpenGL_Testing.openGl.Texture;
import javax.microedition.khronos.opengles.GL10;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.ShortBuffer;
public class Sphere {
float step = 5f; // density of sphere; step in degrees
float[] verArray;
float[] texIndex;
short[] verIndex;
private FloatBuffer vBuff;
private FloatBuffer tBuff;
private ShortBuffer iBuff;
public final float mCenterX, mCenterY, mCenterZ;
public final float mRadius;
private final GL10 mGL;
private int stepsPai, stepsTheta;
private Texture texture;
public Sphere(float mRadius, float mCenterX, float mCenterY, float mCenterZ, GL10 mGL) {
this.mGL = mGL;
// sphere parameters
this.mRadius = mRadius;
this.mCenterX = mCenterX;
this.mCenterY = mCenterY;
this.mCenterZ = mCenterZ;
stepsPai = (int) (180f / step) ; //sphere vertical 'lines'
stepsTheta = (int) (360f / step) + 1; //sphere horizontal 'lines'
// create sphere 'dots'
createVerticesBuff();
createIndexingBuffer();
}
private float[] createVerticesArray() {
float[] vertices = new float[stepsPai * stepsTheta * 3];
int n = 0;
float cRadius, cHeight, co, si;
for (float pai = 180f - step; pai > 0f; pai -= step) {
cRadius = (float) Math.sin((pai + step) * Math.PI / 180f);
cHeight = (float) Math.cos((pai + step) * Math.PI / 180f);
for (float theta = 0.0f; theta <= 360f; theta += step) {
co = (float) Math.cos(theta * Math.PI / 180f);
si = -(float) Math.sin(theta * Math.PI / 180f);
vertices[n * 3] = mRadius * (cRadius * co) + mCenterX;
vertices[n * 3 + 1] = mRadius * (cHeight) + mCenterY;
vertices[n * 3 + 2] = mRadius * (cRadius * si) + mCenterZ;
n ++;
}
}
return vertices;
}
public FloatBuffer createVerticesBuff() {
// create array
verArray = createVerticesArray();
// create buffer
if (vBuff == null) {
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(verArray.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
vBuff = byteBuffer.asFloatBuffer();
vBuff.put(verArray);
vBuff.flip();
}
return vBuff;
}
public short[] createIndexingArray() {
short[] indexies = new short[verArray.length*2];
int n=0;
for (int i = 0; i < stepsPai-1; i++) {
for (int j = 0; j < stepsTheta; j++) {
indexies[n] = (short) (i*stepsTheta+j);
indexies[n+1] = (short) ((i+1)*stepsTheta+j);
indexies[n+2] = (short) ((i+1)*stepsTheta+j+1);
indexies[n+3] = indexies[n+2];
indexies[n+4] = (short) (i*stepsTheta+j+1);
indexies[n+5] = indexies[n];
n+=6;
}
}
return indexies;
}
public void createIndexingBuffer(){
// create array
verIndex = createIndexingArray();
//create buffer
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(verIndex.length * 2);
byteBuffer.order(ByteOrder.nativeOrder());
iBuff = byteBuffer.asShortBuffer();
iBuff.put(verIndex);
iBuff.flip();
}
public void draw() {
// setup vertices buffer
mGL.glEnableClientState(GL10.GL_VERTEX_ARRAY);
vBuff.position(0);
mGL.glVertexPointer(3, GL10.GL_FLOAT, 0, vBuff);
// setup texture
if (texture != null) {
mGL.glEnable(GL10.GL_TEXTURE_2D);
mGL.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
tBuff.position(0);
mGL.glTexCoordPointer(2, GL10.GL_FLOAT, 0, tBuff);
}
// display poligons on screen
mGL.glDrawElements(GL10.GL_TRIANGLES, verIndex.length, GL10.GL_UNSIGNED_SHORT, iBuff);
// reset settings
if (texture != null) {
mGL.glDisable(GL10.GL_TEXTURE_2D);
mGL.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
} else {
mGL.glColor4f(1, 1, 1, 1);
}
mGL.glDisableClientState(GL10.GL_VERTEX_ARRAY);
}
public void setTexture(Texture texture) {
if (this.texture != null) {
this.texture.dispose();
}
this.texture = texture;
// create array
texIndex = new float[stepsPai * stepsTheta * 2 * 2];
int n = 0;
for (float pai = 0f; pai < 180f; pai += step) {
for (float theta = 0.0f; theta <= 360f; theta += step) {
texIndex[n] = theta / 360f;
texIndex[n + 1] = pai / 180f;
n += 2;
}
}
// create buffer
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(texIndex.length * 4);
byteBuffer.order(ByteOrder.nativeOrder());
tBuff = byteBuffer.asFloatBuffer();
tBuff.put(texIndex);
tBuff.flip();
// bind texture
texture.bind();
}
}
"World" class
package com.example.OpenGL_Testing.openGl;
import android.opengl.GLSurfaceView;
import android.support.v4.view.GestureDetectorCompat;
import android.view.MotionEvent;
import android.view.View;
import com.example.OpenGL_Testing.MyApp;
import com.example.OpenGL_Testing.MyGestureListener;
import com.example.OpenGL_Testing.Screen;
import com.example.OpenGL_Testing.openGl.geometry.Sphere;
import com.example.OpenGL_Testing.openGl.geometry.Sphere2;
import javax.microedition.khronos.opengles.GL10;
/**
* Created by Aleksandr.Tsatski on 11.11.2014.
*/
public class WorldMap implements Screen {
GLSurfaceView glView;
static final int VERTEX_SIZE = (3) * 4;
Sphere sphere;
GL10 gl;
private GestureDetectorCompat mDetector;
final Object stateChanged = new Object();
public WorldMap(final GLSurfaceView glView, final GL10 gl) {
this.glView = glView;
this.gl = gl;
sphere = new Sphere(400, 0, 0, 0, gl);
}
private void setupGestureListener(final GLSurfaceView glView, final GL10 gl) {
final MyGestureListener listener = new MyGestureListener();
listener.setGestureFeedBackListener(new MyGestureListener.Feedback() {
#Override
public void onFeedback(final int event, final float parameter1, final float parameter2) {
glView.queueEvent(new Runnable() {
#Override
public void run() {
switch (event) {
case MyGestureListener.SCROLL:
gl.glRotatef(parameter1/10, 0f, 1f, 0f);
gl.glRotatef(-parameter2/10, 0f, 0f, 1f);
break;
default:
break;
}
}
});
}
});
glView.post(new Runnable() {
#Override
public void run() {
mDetector = new GestureDetectorCompat(MyApp.getAppContext(), listener);
}
});
glView.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View view, MotionEvent motionEvent) {
return mDetector.onTouchEvent(motionEvent);
}
});
}
#Override
public void present(float deltaTime) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
sphere.draw();
}
#Override
public void resume() {
gl.glClearColor(1, 0, 0, 1);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glEnable(GL10.GL_BLEND);
gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
setupGestureListener(glView, gl);
sphere.setTexture(new Texture(gl, "world_map.png"));
}
#Override
public void pause() {
}
#Override
public void dispose() {
}
}

Drawing curved line arrow on a bar graph using affine transformation

I am trying to draw a curved Line arrow on a stacked bar graph.I have been able to draw the curved line and arrow.But i am not able to connect the arrow to the end of the curved line.I am using affine transformation to draw the curved line.The below link describes the curved line and arrow that i have been able to draw http://i58.tinypic.com/2m422hy.png.Can anyone guide me as to how to connect the arrow to the end of the curved line.
Here is the code
package Stack;
/*
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
/**
*
* #author OSPL-B4
/
/
* To change this template, choose Tools | Templates
* and open the template in the editor.
*/
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Paint;
import java.awt.Polygon;
import java.awt.Shape;
import java.awt.Stroke;
import java.awt.font.TextLayout;
import java.awt.geom.AffineTransform;
import java.awt.geom.Ellipse2D;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import java.awt.geom.QuadCurve2D;
import java.awt.geom.Rectangle2D;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.Serializable;
import org.jfree.chart.annotations.CategoryAnnotation;
import org.jfree.chart.axis.CategoryAnchor;
import org.jfree.chart.axis.CategoryAxis;
import org.jfree.chart.axis.ValueAxis;
import org.jfree.chart.event.AnnotationChangeListener;
import org.jfree.chart.plot.CategoryPlot;
import org.jfree.chart.plot.Plot;
import org.jfree.chart.plot.PlotOrientation;
import org.jfree.data.category.CategoryDataset;
import org.jfree.io.SerialUtilities;
import org.jfree.ui.RectangleEdge;
import org.jfree.util.ObjectUtilities;
import org.jfree.util.PaintUtilities;
//import java.awt.Font;
/**
* A line annotation that can be placed on a
* {#link org.jfree.chart.plot.CategoryPlot}.
*/
public class CategoryLineAnnotation_demo1 implements CategoryAnnotation,
Cloneable, Serializable {
/** The category for the start of the line. */
private Comparable category1;
/** The value for the start of the line. */
private double value1;
/** The category for the end of the line. */
private Comparable category2;
/** The value for the end of the line. */
private double value2;
private final int ARR_SIZE = 4;
/** The line color. */
private transient Paint paint = Color.black;
/** The line stroke. */
private transient Stroke stroke = new BasicStroke(1.0f);
/**
* Creates a new annotation that draws a line between (category1, value1)
* and (category2, value2).
*
* #param category1 the category (<code>null</code> not permitted).
* #param value1 the value.
* #param category2 the category (<code>null</code> not permitted).
* #param value2 the value.
*/
public CategoryLineAnnotation_demo1(Comparable category1, double value1,
Comparable category2, double value2,
Paint paint, Stroke stroke) {
if (category1 == null) {
throw new IllegalArgumentException("Null 'category1' argument.");
}
if (category2 == null) {
throw new IllegalArgumentException("Null 'category2' argument.");
}
if (paint == null) {
throw new IllegalArgumentException("Null 'paint' argument.");
}
if (stroke == null) {
throw new IllegalArgumentException("Null 'stroke' argument.");
}
this.category1 = category1;
System.out.println("First Category value is "+category1);
this.value1 = value1;
this.category2 = category2;
System.out.println("Second Category value is "+category2);
this.value2 = value2;
this.paint = paint;
this.stroke = stroke;
}
/**
* Returns the category for the start of the line.
*
* #return The category for the start of the line (never <code>null</code>).
*/
public Comparable getCategory1() {
return this.category1;
}
/**
* Sets the category for the start of the line.
*
* #param category the category (<code>null</code> not permitted).
*/
public void setCategory1(Comparable category) {
if (category == null) {
throw new IllegalArgumentException("Null 'category' argument.");
}
this.category1 = category;
}
/**
* Returns the y-value for the start of the line.
*
* #return The y-value for the start of the line.
*/
public double getValue1() {
return this.value1;
}
/**
* Sets the y-value for the start of the line.
*
* #param value the value.
*/
public void setValue1(double value) {
this.value1 = value;
}
/**
* Returns the category for the end of the line.
*
* #return The category for the end of the line (never <code>null</code>).
*/
public Comparable getCategory2() {
return this.category2;
}
/**
* Sets the category for the end of the line.
*
* #param category the category (<code>null</code> not permitted).
*/
public void setCategory2(Comparable category) {
if (category == null) {
throw new IllegalArgumentException("Null 'category' argument.");
}
this.category2 = category;
}
/**
* Returns the y-value for the end of the line.
*
* #return The y-value for the end of the line.
*/
public double getValue2() {
return this.value2;
}
/**
* Sets the y-value for the end of the line.
*
* #param value the value.
*/
public void setValue2(double value) {
this.value2 = value;
}
/**
* Returns the paint used to draw the connecting line.
*
* #return The paint (never <code>null</code>).
*/
public Paint getPaint() {
return this.paint;
}
/**
* Sets the paint used to draw the connecting line.
*
* #param paint the paint (<code>null</code> not permitted).
*/
public void setPaint(Paint paint) {
if (paint == null) {
throw new IllegalArgumentException("Null 'paint' argument.");
}
this.paint = paint;
}
/**
* Returns the stroke used to draw the connecting line.
*
* #return The stroke (never <code>null</code>).
*/
public Stroke getStroke() {
// System.out.println("In Stacked bar Stroke is "+getStroke());
return this.stroke;
}
/**
* Sets the stroke used to draw the connecting line.
*
* #param stroke the stroke (<code>null</code> not permitted).
*/
public void setStroke(Stroke stroke) {
if (stroke == null) {
throw new IllegalArgumentException("Null 'stroke' argument.");
}
this.stroke = stroke;
}
/**
* Draws the annotation.
*
* #param g2 the graphics device.
* #param plot the plot.
* #param dataArea the data area.
* #param domainAxis the domain axis.
* #param rangeAxis the range axis.
*/
public void draw(Graphics2D g2, CategoryPlot plot, Rectangle2D dataArea,
CategoryAxis domainAxis, ValueAxis rangeAxis) {
CategoryDataset dataset = plot.getDataset();
int catIndex1 = dataset.getColumnIndex(this.category1);
int catIndex2 = dataset.getColumnIndex(this.category2);
int catCount = dataset.getColumnCount();
double lineX1 = 0.0f;
double lineY1 = 0.0f;
double lineX2 = 0.0f;
double lineY2 = 0.0f;
PlotOrientation orientation = plot.getOrientation();
RectangleEdge domainEdge = Plot.resolveDomainAxisLocation(
plot.getDomainAxisLocation(), orientation);
RectangleEdge rangeEdge = Plot.resolveRangeAxisLocation(
plot.getRangeAxisLocation(), orientation);
if (orientation == PlotOrientation.HORIZONTAL) {
lineY1 = domainAxis.getCategoryJava2DCoordinate(
CategoryAnchor.MIDDLE, catIndex1, catCount, dataArea,
domainEdge);
lineX1 = rangeAxis.valueToJava2D(this.value1, dataArea, rangeEdge);
lineY2 = domainAxis.getCategoryJava2DCoordinate(
CategoryAnchor.MIDDLE, catIndex2, catCount, dataArea,
domainEdge);
lineX2 = rangeAxis.valueToJava2D(this.value2, dataArea, rangeEdge);
}
else if (orientation == PlotOrientation.VERTICAL) {
lineX1 = domainAxis.getCategoryJava2DCoordinate(
CategoryAnchor.MIDDLE, catIndex1, catCount, dataArea,
domainEdge);
lineY1 = rangeAxis.valueToJava2D(this.value1, dataArea, rangeEdge);
lineX2 = domainAxis.getCategoryJava2DCoordinate(
CategoryAnchor.MIDDLE, catIndex2, catCount, dataArea,
domainEdge);
lineY2 = rangeAxis.valueToJava2D(this.value2, dataArea, rangeEdge);
}
g2.setPaint(this.paint);
g2.setStroke(this.stroke);
drawArrow(g2,(int) lineX1, (int) lineY1, (int) lineX2, (int) lineY2);
}
void drawArrow(Graphics g1, int x1, int y1, int x2, int y2) {
Graphics2D g = (Graphics2D) g1.create();
double dx = x2 - x1, dy = y2 - y1;
System.out.println("Value of DX "+dx);
System.out.println("Value of DY "+dy);
double angle = Math.atan2(dy, dx);
System.out.println("Getting angle "+angle);
int len = (int) Math.sqrt(dx*dx + dy*dy);
AffineTransform at = AffineTransform.getTranslateInstance(x1, y1);
at.concatenate(AffineTransform.getRotateInstance(angle));
g.transform(at);
System.out.println("Affine transform X co-ordinate value is "+at.getScaleX());
System.out.println("Affine transform Y co-ordinate value is "+at.getScaleY());
float center1=(x1+x2)/2-40;
float center2= (y1+y2)/2-40;
QuadCurve2D q=new QuadCurve2D.Float(0,0,center1,center2,x2,y2);
g.draw(q);
g.setColor(Color.RED);
System.out.println("Length of arrow is "+len);
System.out.println("Get Start point 2D "+q.getP1());
System.out.println("Get End point 2D "+q.getP2());
g.fillPolygon(new int[] {len, len-ARR_SIZE, len-ARR_SIZE-10, len-60},
new int[] {0, -ARR_SIZE, ARR_SIZE-20, 5}, 4);
}
public void paintComponent(Graphics g) {
for (int x = 15; x < 200; x += 16)
drawArrow(g, x, x, x, 150);
drawArrow(g, 30, 300, 300, 190);
}
/**
* Tests this object for equality with another.
*
* #param obj the object (<code>null</code> permitted).
*
* #return <code>true</code> or <code>false</code>.
*/
public boolean equals(Object obj) {
if (obj == this) {
return true;
}
if (!(obj instanceof CategoryLineAnnotation_demo1)) {
return false;
}
CategoryLineAnnotation_demo1 that = (CategoryLineAnnotation_demo1) obj;
if (!this.category1.equals(that.getCategory1())) {
return false;
}
if (this.value1 != that.getValue1()) {
return false;
}
if (!this.category2.equals(that.getCategory2())) {
return false;
}
if (this.value2 != that.getValue2()) {
return false;
}
if (!PaintUtilities.equal(this.paint, that.paint)) {
return false;
}
if (!ObjectUtilities.equal(this.stroke, that.stroke)) {
return false;
}
return true;
}
/**
* Returns a hash code for this instance.
*
* #return A hash code.
*/
public int hashCode() {
// TODO: this needs work
return this.category1.hashCode() + this.category2.hashCode();
}
/**
* Returns a clone of the annotation.
*
* #return A clone.
*
* #throws CloneNotSupportedException this class will not throw this
* exception, but subclasses (if any) might.
*/
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
/**
* Provides serialization support.
*
* #param stream the output stream.
*
* #throws IOException if there is an I/O error.
*/
private void writeObject(ObjectOutputStream stream) throws IOException {
stream.defaultWriteObject();
SerialUtilities.writePaint(this.paint, stream);
SerialUtilities.writeStroke(this.stroke, stream);
}
/**
* Provides serialization support.
*
* #param stream the input stream.
*
* #throws IOException if there is an I/O error.
* #throws ClassNotFoundException if there is a classpath problem.
*/
private void readObject(ObjectInputStream stream)
throws IOException, ClassNotFoundException {
stream.defaultReadObject();
this.paint = SerialUtilities.readPaint(stream);
this.stroke = SerialUtilities.readStroke(stream);
}
#Override
public void addChangeListener(AnnotationChangeListener al) {
}
#Override
public void removeChangeListener(AnnotationChangeListener al) {
}
}
You can create the arrow head based on the last line segment (which might already be transformed using an AffineTransform)
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Point;
import java.awt.Shape;
import java.awt.event.MouseEvent;
import java.awt.event.MouseMotionListener;
import java.awt.geom.Line2D;
import java.awt.geom.Path2D;
import java.awt.geom.Point2D;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
public class ArrowPainter
{
public static void main(String[] args)
{
SwingUtilities.invokeLater(new Runnable()
{
#Override
public void run()
{
createAndShowGUI();
}
});
}
private static void createAndShowGUI()
{
JFrame f = new JFrame();
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JPanel panel = new ArrowPaintPanel();
f.getContentPane().add(panel);
f.setSize(500,500);
f.setLocationRelativeTo(null);
f.setVisible(true);
}
}
class ArrowPaintPanel extends JPanel implements MouseMotionListener
{
private Point2D startPoint = null;
private Point2D endPoint = null;
ArrowPaintPanel()
{
addMouseMotionListener(this);
}
#Override
protected void paintComponent(Graphics gr)
{
super.paintComponent(gr);
Graphics2D g = (Graphics2D)gr;
if (startPoint == null)
{
startPoint = new Point(getWidth()/2, getHeight()/2);
}
if (endPoint == null)
{
return;
}
Line2D line = new Line2D.Double(startPoint, endPoint);
Shape arrowHead = createArrowHead(line, 30, 20);
g.draw(line);
g.fill(arrowHead);
}
#Override
public void mouseDragged(MouseEvent e)
{
endPoint = e.getPoint();
repaint();
}
#Override
public void mouseMoved(MouseEvent e)
{
endPoint = e.getPoint();
repaint();
}
private static Shape createArrowHead(Line2D line, double length, double width)
{
Point2D p0 = line.getP1();
Point2D p1 = line.getP2();
double x0 = p0.getX();
double y0 = p0.getY();
double x1 = p1.getX();
double y1 = p1.getY();
double dx = x1 - x0;
double dy = y1 - y0;
double invLength = 1.0 / Math.sqrt(dx*dx+dy*dy);
double dirX = dx * invLength;
double dirY = dy * invLength;
double ax = x1 - length * dirX;
double ay = y1 - length * dirY;
double offsetX = width * -dirY * 0.5;
double offsetY = width * dirX * 0.5;
double c0x = ax + offsetX;
double c0y = ay + offsetY;
double c1x = ax - offsetX;
double c1y = ay - offsetY;
Path2D arrowHead = new Path2D.Double();
arrowHead.moveTo(x1, y1);
arrowHead.lineTo(c0x, c0y);
arrowHead.lineTo(c1x, c1y);
arrowHead.closePath();
return arrowHead;
}
}
EDIT: Update for the above EDIT and the comments: That's a lot of code, but still nothing that can be tested easily. What happens when you replace your line
drawArrow(g2,(int) lineX1, (int) lineY1, (int) lineX2, (int) lineY2);
with
g.fill(createArrowHead(new Line2D.Double(lineX1, lineY1, lineX2, lineY2), 30, 20));
?

OpenGL ES 2.0: Vertex Shader compile status result is 0 with no Shader Log Info

Current situation doesn't allow me to use a computer. And it will be like this for a while. I use Android IDE (AIDE) to program on my phone.
In my code, I used glGetShaderiv() to get the compile status, and noticed the status value is 0. However, there is no indication to suggest the vertex shader code contains an error or something is wrong with loading the GLSL code from a text file.
Below are the codes. Note that I jumbled all the codes together so that the execution of the code is as iterative as possible. Meaning the code doesn't jump around a lot using function calls, for easier debugging.
RenderView class:
package p.e;
import android.opengl.GLSurfaceView;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.content.Context;
import static android.opengl.GLES20.*;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.opengl.GLES20;
import android.opengl.GLUtils;
import android.opengl.Matrix;
public class RenderView extends GLSurfaceView implements GLSurfaceView.Renderer{
private Context context;
private Table table;
private int texture;
private final float[] projectionMatrix=new float[16];
private final float[] modelMatrix=new float[16];
private Shader shader;
public RenderView(Context context){
super(context);
this.context=context;
}
#Override
public void onSurfaceCreated(GL10 p1, EGLConfig p2)
{
// TODO: Implement this method
glClearColor(1f,0f,1f,1f);
this.shader=new Shader(context);
this.table=new Table();
final int[] textureID=new int[1];
glGenTextures(1,textureID,0);
texture=textureID[0];
BitmapFactory.Options options=new BitmapFactory.Options();
options.inScaled=false;
Bitmap bitmap=BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_launcher, options);
glBindTexture(GL_TEXTURE_2D, texture);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER,GL_LINEAR);
GLUtils.texImage2D(GL_TEXTURE_2D,0,bitmap,0);
glGenerateMipmap(GL_TEXTURE_2D);
bitmap.recycle();
glBindTexture(GL_TEXTURE_2D,0);
}
#Override
public void onSurfaceChanged(GL10 p1, int width, int height)
{
// TODO: Implement this method
glViewport(0,0,width,height);
perspectiveM(projectionMatrix,45f, (float)width/(float)height,1f,10f);
Matrix.setIdentityM(modelMatrix, 0);
Matrix.translateM(modelMatrix,0,0f,0f,-2.5f);
Matrix.rotateM(modelMatrix,0,-60f,1f,0f,0f);
final float[] temp=new float[16];
Matrix.multiplyMM(temp,0,projectionMatrix,0,modelMatrix,0);
System.arraycopy(temp,0,projectionMatrix,0,temp.length);
}
#Override
public void onDrawFrame(GL10 p1)
{
// TODO: Implement this method
glClear(GL_COLOR_BUFFER_BIT);
glUseProgram(shader.getProgram());
glUniformMatrix4fv(shader.uMatrixLocation, 1, false, projectionMatrix,0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texture);
glUniform1i(shader.uTextureUnitLocation,0);
table.getVertexBuffer().position(0);
glVertexAttribPointer(shader.aPositionLocation, 2, GL_FLOAT,false,2*4,table.getVertexBuffer());
//glBindBuffer(GL_ARRAY_BUFFER, table.vertexBufferPointer);
//table.getVertexBuffer().position(0);
glEnableVertexAttribArray(shader.aPositionLocation);
//table.getVertexBuffer().rewind();
table.getVertexBuffer().position(0);
//table.getTexBuffer().position(0);
//glBindBuffer(GL_ARRAY_BUFFER, table.texBufferPointer);
table.getTexBuffer().position(0);
glVertexAttribPointer(shader.aTexPositionLocaton,2,GL_FLOAT,false,2*4,table.getTexBuffer());
glEnableVertexAttribArray(shader.aTexPositionLocaton);
//table.getTexBuffer().rewind();
table.getTexBuffer().position(0);
glDrawArrays(GL_TRIANGLE_FAN,0,4);
//glDisableVertexAttribArray(shader.aPositionLocation);
//glDisableVertexAttribArray(shader.aTexPositionLocaton);
}
public static void perspectiveM(float[] m, float yFovInDegrees, float aspect, float n, float f) {
final float angleInRadians = (float) (yFovInDegrees * Math.PI / 180.0);
final float a = (float) (1.0 / Math.tan(angleInRadians / 2.0));
m[0] = a / aspect;
m[1] = 0f;
m[2] = 0f;
m[3] = 0f;
m[4] = 0f;
m[5] = a;
m[6] = 0f;
m[7] = 0f;
m[8] = 0f;
m[9] = 0f;
m[10] = -((f + n) / (f - n));
m[11] = -1f;
m[12] = 0f;
m[13] = 0f;
m[14] = -((2f * f * n) / (f - n));
m[15] = 0f;
}
}
`
Table class:
package p.e;
import java.nio.*;
import static android.opengl.GLES20.*;
public class Table
{
private FloatBuffer vertexBuffer;
private FloatBuffer texBuffer;
public int vertexBufferPointer;
public int texBufferPointer;
private final float[] vertexData={
-0.5f,-0.5f,
0.5f,-0.5f,
0.5f,0.5f,
-0.5f,0.5f
};
private final float[] texData={
0f,1f,
1f,1f,
1f,0f,
0f,0f
};
public Table(){
int[] bufferPointer=new int[1];
glGenBuffers(1,bufferPointer,0);
vertexBuffer=ByteBuffer.allocateDirect(vertexData.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer();
vertexBuffer.put(vertexData);
vertexBuffer.flip();
glBindBuffer(GL_ARRAY_BUFFER, bufferPointer[0]);
glBufferData(GL_ARRAY_BUFFER, vertexData.length*4, vertexBuffer, GL_STATIC_DRAW);
vertexBufferPointer=bufferPointer[0];
texBuffer=ByteBuffer.allocateDirect(texData.length*4).order(ByteOrder.nativeOrder()).asFloatBuffer();
texBuffer.put(texData);
texBuffer.flip();
glGenBuffers(1, bufferPointer,0);
glBindBuffer(GL_ARRAY_BUFFER,bufferPointer[0]);
glBufferData(GL_ARRAY_BUFFER,texData.length*4, texBuffer, GL_STATIC_DRAW);
}
public FloatBuffer getVertexBuffer(){
return vertexBuffer;
}
public FloatBuffer getTexBuffer(){
return texBuffer;
}
}
Shader class:
package p.e;
import java.io.*;
import android.content.Context;
import static android.opengl.GLES20.*;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.ByteBuffer;
import android.util.Log;
import java.nio.ByteOrder;
public class Shader
{
private int program;
private final String U_MATRIX="u_matrix";
private final String U_TEXTUREUNIT="u_texUnit";
private final String A_POSITION="a_position";
private final String A_TEXCOORDS="a_texPos";
public int uMatrixLocation;
public int uTextureUnitLocation;
public int aPositionLocation;
public int aTexPositionLocaton;
public Shader(Context context){
int vertex=glCreateShader(GL_VERTEX_SHADER);
IntBuffer intBuf=ByteBuffer.allocateDirect(4).order(ByteOrder.nativeOrder()).asIntBuffer();
Log.wtf("Code",Shader.loadString(context,R.raw.tex_vert));
glShaderSource(vertex,Shader.loadString(context,R.raw.tex_vert));
glCompileShader(vertex);
//check
int status;
glGetShaderiv(vertex, GL_COMPILE_STATUS, intBuf);
status=intBuf.get(0);
if(status==0){
glGetShaderiv(vertex,GL_INFO_LOG_LENGTH,intBuf);
status=intBuf.get(0);
if (status>1){
Log.i("Shader","Vertex Shader: "+glGetShaderInfoLog(vertex));
}
glDeleteShader(vertex);
Log.w("Shader","Vertex Shader error.");
return;
}
//check end
int fragment=glCreateShader(GL_FRAGMENT_SHADER);
Log.wtf("Code",Shader.loadString(context,R.raw.tex_frag));
glShaderSource(fragment, Shader.loadString(context,R.raw.tex_frag));
glCompileShader(fragment);
//check
glGetShaderiv(fragment, GL_COMPILE_STATUS, intBuf);
status=intBuf.get(0);
Log.i("Shader","Fragment Shader: "+glGetShaderInfoLog(fragment));
if(status==0){
glDeleteShader(fragment);
Log.w("Shader","Fragment Shader error.");
return;
}
//check end
program=glCreateProgram();
//check
Log.i("Shader","Program: "+glGetProgramInfoLog(program));
if(program==0){
Log.w("Shader","Program not created.");
return;
}
//check end
glAttachShader(program,vertex);
glAttachShader(program,fragment);
glLinkProgram(program);
//check
glValidateProgram(program);
glGetProgramiv(program, GL_LINK_STATUS, intBuf);
status=intBuf.get(0);
if(status==0){
glDeleteProgram(program);
Log.w("Shader","Program unable to link.");
return;
}
//check end
//check
glGetProgramiv(program, GL_VALIDATE_STATUS, intBuf);
status=intBuf.get(0);
Log.i("Shader","Program validation: "+glGetProgramInfoLog(program));
if(status==0){
glDeleteProgram(program);
Log.w("Shader","Program validation failed.");
return;
}
//check end
uMatrixLocation=glGetUniformLocation(program,U_MATRIX);
uTextureUnitLocation=glGetUniformLocation(program,U_TEXTUREUNIT);
aPositionLocation=glGetAttribLocation(program,A_POSITION);
aTexPositionLocaton=glGetAttribLocation(program,A_TEXCOORDS);
}
public void setVertexAttributePointer(int location, int offset, int componentCount, int type, boolean isTranspose, int stride, FloatBuffer buffer){
buffer.position(offset);
glVertexAttribPointer(location, componentCount,type,isTranspose,stride,buffer);
glEnableVertexAttribArray(location);
buffer.rewind();
}
public void setup(FloatBuffer vertexBuffer, FloatBuffer texBuffer){
vertexBuffer.position(0);
glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT,false,0,vertexBuffer);
glEnableVertexAttribArray(aPositionLocation);
vertexBuffer.rewind();
texBuffer.position(0);
glVertexAttribPointer(aTexPositionLocaton,2,GL_FLOAT,false,0,texBuffer);
glEnableVertexAttribArray(aTexPositionLocaton);
texBuffer.rewind();
}
public int getProgram(){
return program;
}
public void bind(int texture, float[] matrix){
glUniformMatrix4fv(uMatrixLocation, 1, false, matrix,0);
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D,texture);
glUniform1i(uTextureUnitLocation,0);
}
private static String loadString(Context context, int resourceID){
StringBuilder builder=new StringBuilder();
try{
BufferedReader reader=new BufferedReader(new InputStreamReader(context.getResources().openRawResource(resourceID)));
String line;
while((line=reader.readLine())!=null){
builder.append(line);
builder.append('\n');
}
}
catch(Exception e){
}
return builder.toString();
}
}
Below are the shader source codes.
Vertex Shader:
uniform mat4 u_matrix;
attribute vec4 a_position;
attribute vec2 a_texPos;
varying vec2 v_texPos;
void main{
v_texPos=a_texPos;
gl_Position=u_matrix*a_position;
}
Fragment Shader:
precision mediump float;
uniform sampler2D u_texUnit;
varying vec2 v_texPos;
void main(){
gl_FragColor=texture2D(u_texUnit,v_texPos);
}
I will post a screenshot of Logcat displaying nothing but the phrase "Vertex shader error" debug message. The GL_INVALID_OPERATION is caused by the vertex shader status being 0, was deleted and returned back to the onSurfaceCreated(), and not being able to point to the matrix location, as the vertex shader is nonexistent at that point in time.
I think it's just a simple typo. The vertex shader is missing () after main:
void main{
needs to be:
void main(){

My Rotation's are not working

I a working on my 'game engine,' and after completing the player class, I realized that the camera movement was not working... I did a bunch of try/catch if/else statements and I narrowed it down to either being a problem with Mouse.getDX not functioning properly, or the glRotate is not working properly...
Here is my game class:
package com.matisse.engine;
import static org.lwjgl.opengl.GL11.GL_POINTS;
import static org.lwjgl.opengl.GL11.glBegin;
import static org.lwjgl.opengl.GL11.glCallList;
import static org.lwjgl.opengl.GL11.glColor3f;
import static org.lwjgl.opengl.GL11.glEnd;
import static org.lwjgl.opengl.GL11.glVertex3f;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import org.lwjgl.LWJGLException;
import org.lwjgl.input.Keyboard;
import assets.TestBlock;
import com.matisse.world.Chunk;
import com.matisse.world.Level;
import com.thoughtworks.xstream.XStream;
import com.thoughtworks.xstream.io.xml.DomDriver;
public class Game {
public boolean[] keys;
public XStream xstream;
public Level world;
public File file;
public Camera camera;
public Game() throws LWJGLException {
run();
}
public void run() {
try {
Keyboard.create();
keys = new boolean[256];
xstream = new XStream(new DomDriver());
Level first_world = new Level(0, 0);
Chunk first_chunk = new Chunk();
TestBlock floor = new TestBlock(-10, -2, -10, 10, -1, 10);
first_chunk.voxels.add(floor);
first_world.chunks.add(first_chunk);
first_world.genLists();
String xml = xstream.toXML(first_world);
saveFile("world", xml);
world = (Level) xstream.fromXML(readFile("res/maps/world.xml"));
camera = new Camera(this, world.startx, world.startz);
} catch (LWJGLException e) {
e.printStackTrace();
}
}
public void update() {
if (Keyboard.isKeyDown(Keyboard.KEY_ESCAPE)) {
Engine.state = State.MENU;
}
mapKeys();
camera.update();
camera.translateCamera();
}
public void draw3D() {
for (Chunk i : world.chunks) {
i.render();
glCallList(i.displayListHandle);
}
}
public void draw2D() {
glBegin(GL_POINTS);
glColor3f(1, 0, 0);
glVertex3f(0, 0, 10);
glEnd();
}
public void mapKeys() {
for (int i = 0; i < keys.length; i++) {
keys[i] = Keyboard.isKeyDown(i);
}
}
public void saveFile(String mapname, String xml) {
FileOutputStream fop = null;
String content = xml;
try {
file = new File("res/maps/" + mapname + ".xml");
fop = new FileOutputStream(file);
// if file doesnt exists, then create it
if (!file.exists()) {
file.createNewFile();
}
// get the content in bytes
byte[] contentInBytes = content.getBytes();
fop.write(contentInBytes);
fop.flush();
fop.close();
System.out.println("Done");
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (fop != null) {
fop.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public String readFile(String filename) {
StringBuffer result = new StringBuffer();
// The name of the file to open
// This will reference one line at a time
String line = null;
try {
// FileReader reads text files in the default encoding.
FileReader fileReader = new FileReader(filename);
// Always wrap FileReader in BufferedReader.
BufferedReader bufferedReader = new BufferedReader(fileReader);
while ((line = bufferedReader.readLine()) != null) {
result.append(line);
}
// Always close files.
bufferedReader.close();
} catch (FileNotFoundException ex) {
System.out.println("Unable to open file '" + filename + "'");
} catch (IOException ex) {
System.out.println("Error reading file '" + filename + "'");
// Or we could just do this:
// ex.printStackTrace();
}
String product = result.toString();
return product;
}
}
And here is my Camera class: (Note: this is one of the first 'engines' I am trying to do with almost little to no outside reference, so the rest of the code is a bit rustic)
package com.matisse.engine;
import static org.lwjgl.opengl.GL11.glRotatef;
import static org.lwjgl.opengl.GL11.glTranslatef;
import org.lwjgl.input.Keyboard;
import org.lwjgl.input.Mouse;
import org.lwjgl.util.vector.Vector3f;
public class Camera {
static float speed = 0.35f;
Vector3f vector = new Vector3f(7, 1, 7);
Vector3f rotation = new Vector3f(0, 1, 0);
Vector3f previous = new Vector3f();
boolean moveForward = false, moveBackward = false, strafeLeft = false,
strafeRight = false;
Game world;
public Camera(Game app, float startx, float starty) {
world = app;
vector.x = startx;
vector.y = starty;
}
public void translateCamera() {
glRotatef(rotation.x, 1, 0, 0);
glRotatef(rotation.y, 0, 1, 0);
glRotatef(rotation.z, 0, 0, 1);
glTranslatef(-vector.x, -vector.y - 1.4f, -vector.z);
}
public void update() {
if (Engine.state == State.GAME) {
Mouse.setGrabbed(true);
} else {
Mouse.setGrabbed(false);
}
updatePreviousVector();
updateMotion();
input();
}
public void input() {
if (world.keys[Keyboard.KEY_W]) {
moveForward = true;
} else {
moveForward = false;
}
if (world.keys[Keyboard.KEY_S]) {
moveBackward = true;
} else {
moveBackward = false;
}
if (world.keys[Keyboard.KEY_A]) {
strafeLeft = true;
} else {
strafeLeft = false;
}
if (world.keys[Keyboard.KEY_D]) {
strafeRight = true;
} else {
strafeRight = false;
}
try {
float mouseDX = Mouse.getDX() * 0.8f * 0.16f;
float mouseDY = Mouse.getDY() * 0.8f * 0.16f;
System.out.println(Mouse.getDX());
if (rotation.y + mouseDX >= 360) {
rotation.y = rotation.y + mouseDX - 360;
} else if (rotation.y + mouseDX < 0) {
rotation.y = 360 - rotation.y + mouseDX;
} else {
rotation.y += mouseDX;
System.out.println(mouseDX);
}
if (rotation.x - mouseDY >= -89 && rotation.x - mouseDY <= 89) {
rotation.x += -mouseDY;
} else if (rotation.x - mouseDY < -89) {
rotation.x = -89;
} else if (rotation.x - mouseDY > 89) {
rotation.x = 89;
}
} catch (Exception e) {
e.printStackTrace();
}
}
public void updatePreviousVector() {
previous.x = vector.x;
previous.y = vector.y;
previous.z = vector.z;
}
public void updateMotion() {
if (moveForward) {
vector.x += Math.sin(rotation.y * Math.PI / 180) * speed;
vector.z += -Math.cos(rotation.y * Math.PI / 180) * speed;
}
if (moveBackward) {
vector.x -= Math.sin(rotation.y * Math.PI / 180) * speed;
vector.z -= -Math.cos(rotation.y * Math.PI / 180) * speed;
}
if (strafeLeft) {
vector.x += Math.sin((rotation.y - 90) * Math.PI / 180) * speed;
vector.z += -Math.cos((rotation.y - 90) * Math.PI / 180) * speed;
}
if (strafeRight) {
vector.x += Math.sin((rotation.y + 90) * Math.PI / 180) * speed;
vector.z += -Math.cos((rotation.y + 90) * Math.PI / 180) * speed;
}
}
}
Please, it may end up being a Wolfenstien clone, but I would like to try to implement mouse usage.
Since I see no location in your code where you load an identity matrix, I can only assume that your camera's transformations are accumulating every time you call translateCamera (...) and that this is the source of your problem.
You have to realize that OpenGL boils down to a very unsophisticated state machine. Without using GLSL and arbitrary per-program matrix uniforms, you have to rely on the matrix stack to manipulate your transformations. Every time you do glRotatef (...) or glTranslatef (...) it multiplies the "current" matrix by a rotation or translation matrix. The current matrix is defined using the Matrix Mode and the top of the matrix stack for that mode.
Unless you load a new matrix into your current matrix, or alter the top of the matrix stack, then every time you call rotate, translate, scale, etc. functions you are actually rotating, translating and scaling relative to the prior state of the matrix.
I have looked at your camera's code and I do not think this is the behavior you want. It looks like you want absolute rotation and translation, and not relative. A call to glLoadIdentity (...) will correct this.

Categories

Resources