Hi I'm creating a water scene and have a class called drawWater. The class takes in a equation to alter it's appearance. When I try to create
drawater water = new drawWater();
drawater water2 = new drawWater();
They both seem to be created with the correct values but when I draw them onto the screen only one is shown. Both the values are different.
I don't know where I'm going wrong. It doesn't seem to be a JOGL problem but the way I'm setting up the class?
Can anyone see where I went wrong?
This is the main class:
package waterAttempt41;
import Common.GLDisplay;
public class Lesson27 {
public static void main(String[] args) {
GLDisplay neheGLDisplay = GLDisplay.createGLDisplay("Current water attempt");
Renderer renderer = new Renderer();
//InputHandler inputHandler = new InputHandler(renderer, neheGLDisplay);
neheGLDisplay.addGLEventListener(renderer);
//neheGLDisplay.addKeyListener(inputHandler);
neheGLDisplay.start();
}
}
This is the renderer class:
package waterAttempt41;
import Common.TextureReader;
import java.io.IOException;
import java.util.logging.Logger;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.glu.GLU;
class Renderer implements GLEventListener {
private static final Logger logger = Logger.getLogger(Renderer.class.getName());
drawWater water;
drawWater water2;
private int[] textures = new int[3]; // Storage For 3 Textures
private boolean aDown = false;
private boolean up = false;
private GLU glu = new GLU();
public void init(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
try {
loadGLTextures(drawable);
} catch (IOException e) {
logger.info("Exception loading textures or Objects");
System.out.println("Couldn't load model/Texture");
throw new RuntimeException(e);
}
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glShadeModel(GL.GL_SMOOTH);
gl.glLightModeli(GL.GL_LIGHT_MODEL_TWO_SIDE, GL.GL_TRUE);
gl.glCullFace(GL.GL_BACK); // Set Culling Face To Back Face
gl.glEnable(GL.GL_CULL_FACE); // Enable Culling
gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f); // Set Clear Color (Greenish Color)
float spot_ambient[] = {0.2f, 0.2f, 0.2f, 1.0f};
float spot_diffuse[] = {10.2f, 10.2f, 10.2f, 10.0f};
float spot_specular[] = {10.2f, 10.2f, 10.2f, 10.0f};
gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, spot_ambient, 1);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, spot_diffuse, 1);
gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, spot_specular, 1);
gl.glEnable(GL.GL_LIGHTING);
gl.glEnable(GL.GL_LIGHT0);
water = new drawWater();
water.setup(gl, "a*sin( y *(x-b) )");
water.setFuncVar('a', 1.103);
water.setFuncVar('b', 1.103);
water.setMax(5);
water2 = new drawWater();
water2.setup(gl, "a*sin( y *(x-b) )");
water2.setFuncVar('a', 0.05);
water2.setFuncVar('b', 10.0);
water2.setMax(25);
}
public void display(GLAutoDrawable drawable) {
GL gl = drawable.getGL();
// Clear Color Buffer, Depth Buffer, Stencil Buffer
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT | GL.GL_STENCIL_BUFFER_BIT);
logger.info("\nWater: a = " + water.getFuncVar('a') + " b =" + water.getFuncVar('b') + "\n"
+ "Water2: a = " + water2.getFuncVar('a') + " b =" + water2.getFuncVar('b')
+ "\nWater: = " + water.getEqu() + " \nWater2 =" + water2.getEqu()
+ "\nWater: max = " + water.getMax() + " Water2: max = " + water2.getMax());
gl.glPushMatrix();
gl.glTranslatef(0.0f, -20.50f, 0.0f);
gl.glTranslatef(0.0f, 0.0f, -31.0f);
gl.glRotatef(90, 0.0f, 0.0f, 1.0f); // Rotate By -yrot On Y Axis
gl.glRotatef(90, 0.0f, 1.0f, 0.0f);
water.draw(gl);
gl.glTranslatef(0.0f, -20.0f, 0.0f);
water2.draw(gl);
gl.glPopMatrix();
gl.glPushMatrix();
gl.glTranslatef(0.0f, 0.0f, -20.0f); // Zoom Into The Screen 20 Units
gl.glEnable(GL.GL_TEXTURE_2D); // Enable Texture Mapping ( NEW )
drawRoom(gl); // Draw The Room
gl.glPopMatrix();
gl.glFlush(); // Flush The OpenGL Pipeline
}
private void drawRoom(GL gl) { // Draw The Room (Box)
gl.glBegin(GL.GL_QUADS); // Begin Drawing Quads
/*
// Floor
gl.glNormal3f(0.0f, 1.0f, 0.0f); // Normal Pointing Up
gl.glVertex3f(-20.0f, -20.0f, -40.0f); // Back Left
gl.glVertex3f(-20.0f, -20.0f, 40.0f); // Front Left
gl.glVertex3f(20.0f, -20.0f, 40.0f); // Front Right
gl.glVertex3f(20.0f, -20.0f, -40.0f); // Back Right
// Ceiling
gl.glNormal3f(0.0f, -1.0f, 0.0f); // Normal Point Down
gl.glVertex3f(-10.0f, 10.0f, 20.0f); // Front Left
gl.glVertex3f(-10.0f, 10.0f, -20.0f); // Back Left
gl.glVertex3f(10.0f, 10.0f, -20.0f); // Back Right
gl.glVertex3f(10.0f, 10.0f, 20.0f); // Front Right
// Back Wall
gl.glNormal3f(0.0f, 0.0f, -1.0f); // Normal Pointing Towards Viewer
gl.glVertex3f(20.0f, 20.0f, 30.0f); // Top Right
gl.glVertex3f(20.0f, -20.0f, 30.0f); // Bottom Right
gl.glVertex3f(-20.0f, -20.0f, 30.0f); // Bottom Left
gl.glVertex3f(-20.0f, 20.0f, 30.0f); // Top Left
// Left Wall
gl.glNormal3f(1.0f, 0.0f, 0.0f); // Normal Pointing Right
gl.glVertex3f(-20.0f, 20.0f, 30.0f); // Top Front
gl.glVertex3f(-20.0f, -20.0f, 30.0f); // Bottom Front
gl.glVertex3f(-20.0f, -20.0f, -30.0f); // Bottom Back
gl.glVertex3f(-20.0f, 20.0f, -30.0f); // Top Back
// Right Wall
gl.glNormal3f(-1.0f, 0.0f, 0.0f); // Normal Pointing Left
gl.glVertex3f(20.0f, 20.0f, -30.0f); // Top Back
gl.glVertex3f(20.0f, -20.0f, -30.0f); // Bottom Back
gl.glVertex3f(20.0f, -20.0f, 30.0f); // Bottom Front
gl.glVertex3f(20.0f, 20.0f, 30.0f); // Top Front
*/
// Front Wall
gl.glNormal3f(0.0f, 0.0f, 1.0f); // Normal Pointing Away From Viewer
gl.glTexCoord2f(1, 1);
gl.glVertex3f(-20.0f, 20.0f, -30.0f); // Top Left
gl.glTexCoord2f(1, 0);
gl.glVertex3f(-20.0f, -20.0f, -30.0f); // Bottom Left
gl.glTexCoord2f(0, 0);
gl.glVertex3f(20.0f, -20.0f, -30.0f); // Bottom Right
gl.glTexCoord2f(0, 1);
gl.glVertex3f(20.0f, 20.0f, -30.0f); // Top Right
gl.glPopMatrix();
gl.glEnd(); // Done Drawing Quads
}
public void reshape(GLAutoDrawable drawable, int xstart, int ystart, int width, int height) {
GL gl = drawable.getGL();
height = (height == 0) ? 1 : height;
gl.glViewport(0, 0, width, height);
gl.glMatrixMode(GL.GL_PROJECTION);
gl.glLoadIdentity();
gl.glRotatef(90, 0.0f, 0.0f, 1.0f);
glu.gluPerspective(60, (float) width / height, 1, 1000);
glu.gluLookAt(1.0f, 0.0f, 25.0f,
0.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f);
gl.glMatrixMode(GL.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void displayChanged(GLAutoDrawable drawable, boolean modeChanged, boolean deviceChanged) {
}
private void loadGLTextures(GLAutoDrawable gldrawable) throws IOException {
TextureReader.Texture texture = null;
texture = TextureReader.readTexture("data/images/042.bmp");
GL gl = gldrawable.getGL();
//Create Nearest Filtered Texture
gl.glGenTextures(1, textures, 0);
gl.glBindTexture(GL.GL_TEXTURE_2D, textures[0]);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
gl.glTexParameteri(GL.GL_TEXTURE_2D, GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
gl.glTexImage2D(GL.GL_TEXTURE_2D,
0,
3,
texture.getWidth(),
texture.getHeight(),
0,
GL.GL_RGB,
GL.GL_UNSIGNED_BYTE,
texture.getPixels());
}
}
The drawWater Class:
import com.sun.opengl.util.BufferUtil;
import javax.media.opengl.GL;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
/**
*
* #author Shane
*/
public class drawWater {
private Expr2 func; // The function that is being drawn.
private String functionInput;
private boolean version_1_5; // Check is OpenGL 1.5 is available; set in init().
private boolean dataIsValid; // Set to true whenever data needs to be recomputed.
// This is checked in the display() method before drawing.
private int max;
/* Buffers to hold the points and normals for the surface. */
private FloatBuffer vBuf = BufferUtil.newFloatBuffer(201 * 201 * 3);
private FloatBuffer nBuf = BufferUtil.newFloatBuffer(201 * 201 * 3);
/* Buffers to hold the indices for drawing the surface and lines with glDrawElements*/
private IntBuffer surfaceIndexBuffer = BufferUtil.newIntBuffer(200 * 201 * 2);
private IntBuffer xLineIndexBuffer = BufferUtil.newIntBuffer(21 * 201);
private IntBuffer yLineIndexBuffer = BufferUtil.newIntBuffer(21 * 201);
/* VBO ID numbers for holding the data when OpenGL version is 1.5 or higher */
private int vertexVBO, normalVBO; // VBO IDs for surface data.
private int xLineVBO, yLineVBO, surfaceVBO; // VBO IDs for index data.
public drawWater() {
}
public void setup(GL gl, String equ) {
version_1_5 = gl.isExtensionAvailable("GL_VERSION_1_5");
if (gl.isExtensionAvailable("GL_VERSION_1_3")) {
gl.glEnable(GL.GL_MULTISAMPLE);
}
this.makeElementBuffers(); // Generate lists of indices for glDrawElements. This data never changes.
if (version_1_5) {
// Generate VBOs for the data, and fill the ones that are for index data with
// data from Java nio buffers. The VBOs for index data won't change again and
// so use GL.GL_STATIC_DRAW.
int[] ids = new int[5];
gl.glGenBuffers(5, ids, 0);
this.vertexVBO = ids[0];
this.normalVBO = ids[1];
this.xLineVBO = ids[2];
this.yLineVBO = ids[3];
this.surfaceVBO = ids[4];
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO);
gl.glVertexPointer(3, GL.GL_FLOAT, 0, 0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normalVBO);
gl.glNormalPointer(GL.GL_FLOAT, 0, 0);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, surfaceVBO);
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 2 * 200 * 201, surfaceIndexBuffer, GL.GL_STATIC_DRAW);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, xLineVBO);
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 21 * 201, xLineIndexBuffer, GL.GL_STATIC_DRAW);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, yLineVBO);
gl.glBufferData(GL.GL_ELEMENT_ARRAY_BUFFER, 4 * 21 * 201, yLineIndexBuffer, GL.GL_STATIC_DRAW);
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
} else {
gl.glVertexPointer(3, GL.GL_FLOAT, 0, vBuf);
gl.glNormalPointer(GL.GL_FLOAT, 0, nBuf);
}
this.functionInput = equ;
this.func = new Expr2(equ);
this.dataIsValid = false; // Force recomputation of data with new graph definition.
}
public void draw(GL gl) {
if (func != null) {
gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT_AND_DIFFUSE, new float[]{0.7f, 10.7f, 1}, 0);
gl.glMaterialfv(GL.GL_BACK, GL.GL_AMBIENT_AND_DIFFUSE, new float[]{10.8f, 0.8f, 0.5f}, 0);
if (!dataIsValid) {
this.computeSurfaceData();
if (version_1_5) {
// Set up VBOs for surface points and normals. Since these change
// pretty regularly, use GL.GL_DYNAMIC_DRAW.
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, vertexVBO);
gl.glBufferData(GL.GL_ARRAY_BUFFER, 4 * 3 * 201 * 201, vBuf, GL.GL_DYNAMIC_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, normalVBO);
gl.glBufferData(GL.GL_ARRAY_BUFFER, 4 * 3 * 201 * 201, nBuf, GL.GL_DYNAMIC_DRAW);
gl.glBindBuffer(GL.GL_ARRAY_BUFFER, 0);
}
}
gl.glEnableClientState(GL.GL_VERTEX_ARRAY);
gl.glEnableClientState(GL.GL_NORMAL_ARRAY);
this.drawSurface(gl); // Just draw the surface.
gl.glPolygonOffset(1, 1);
gl.glEnable(GL.GL_POLYGON_OFFSET_FILL);
this.drawSurface(gl);
gl.glDisable(GL.GL_POLYGON_OFFSET_FILL);
gl.glDisable(GL.GL_LIGHTING);
gl.glColor3f(0, 0, 0);
gl.glDisableClientState(GL.GL_NORMAL_ARRAY);
gl.glEnable(GL.GL_LIGHTING);
}
gl.glDisableClientState(GL.GL_VERTEX_ARRAY);
gl.glDisableClientState(GL.GL_NORMAL_ARRAY);
}
public void setIsVaild(boolean bool) {
this.dataIsValid = bool;
}
public void setMax(int max) {
this.max = max;
}
public int getMax() {
return this.max;
}
public double getFuncVar(char var) {
return this.func.getVariable(var);
}
public void setFuncVar(char var, double value) {
this.func.setVariable(var, value);
}
public void setFunc(String func) {
this.func.parse(func);
}
public String getEqu() {
return this.functionInput;
}
private void makeElementBuffers() {
for (int i = 0; i < 201; i += 10) { // indices for drawing lines in x-direction
for (int j = 0; j < 201; j++) {
this.xLineIndexBuffer.put(201 * i + j);
}
}
for (int i = 0; i < 201; i += 10) { // indices for drawing lines in y-direction
for (int j = 0; j < 201; j++) {
this.yLineIndexBuffer.put(201 * j + i);
}
}
for (int i = 0; i < 200; i++) { // indices for drawing surface with GL_TRIANGLE_STRIPs
for (int j = 0; j < 201; j++) {
this.surfaceIndexBuffer.put(201 * (i + 1) + j);
this.surfaceIndexBuffer.put(201 * i + j);
}
}
this.xLineIndexBuffer.rewind();
this.yLineIndexBuffer.rewind();
this.surfaceIndexBuffer.rewind();
}
private void computeSurfaceData() {
double xmin = -5;
double xmax = 5;
double ymin = -5;
double ymax = 5;
double xRes = 200;
double yRes = 200;
float[] surfaceData = new float[301 * 3];
float[] normalData = new float[301 * 3];
double dx = (xmax - xmin) / xRes;
double dy = (ymax - ymin) / yRes;
for (int i = 0; i <= xRes; i++) {
int v = 0;
int n = 0;
double y1 = ymin + dy * i;
for (int j = 0; j <= yRes; j++) {
double x = xmin + dx * j;
this.func.setVariable('x', x);
this.func.setVariable('y', y1);
double z1 = this.func.value();
float[] normal1 = computeUnitNormal(x, y1);
surfaceData[v++] = (float) x;
surfaceData[v++] = (float) y1;
surfaceData[v++] = (float) z1;
normalData[n++] = normal1[0];
normalData[n++] = normal1[1];
normalData[n++] = normal1[2];
}
this.vBuf.put(surfaceData, 0, 201 * 3);
this.nBuf.put(normalData, 0, 201 * 3);
}
this.vBuf.rewind();
this.nBuf.rewind();
this.dataIsValid = true;
}
/**
* Draw the surface as a series of triangle strips.
*/
private void drawSurface(GL gl) {
if (version_1_5) {
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, surfaceVBO);
for (int i = 0; i < 200; i++) {
gl.glDrawElements(GL.GL_TRIANGLE_STRIP, 402, GL.GL_UNSIGNED_INT, 402 * i * 4);
}
gl.glBindBuffer(GL.GL_ELEMENT_ARRAY_BUFFER, 0);
} else {
for (int i = 0; i < 200; i++) {
this.surfaceIndexBuffer.position(402 * i);
gl.glDrawElements(GL.GL_TRIANGLE_STRIP, 402, GL.GL_UNSIGNED_INT, surfaceIndexBuffer);
}
}
}
/**
* Compute a unit normal to the graph of z = func(x,y).
* This is only an approximation, using nearby points instead
* of exact derivatives.
*/
private float[] computeUnitNormal(double x, double y) {
double epsilon = 0.00001;
this.func.setVariable('x', x);
this.func.setVariable('y', y);
double z = this.func.value();
this.func.setVariable('x', x + epsilon);
double z1 = func.value();
this.func.setVariable('x', x);
this.func.setVariable('y', y + epsilon);
double z2 = this.func.value();
// normal is (epsilon,0,z1-z) X (0,epsilon,z2-z)
double a = -epsilon * (z1 - z);
double b = -epsilon * (z2 - z);
double c = epsilon * epsilon;
double length = Math.sqrt(a * a + b * b + c * c);
if (Double.isNaN(length) || Double.isInfinite(length)) {
return new float[]{0, 0, 1};
} else {
return new float[]{(float) (a / length), (float) (b / length), (float) (c / length)};
}
}
}
Any help would be a appreciated. This is part of my final year project in college. So any help would be great.
The calls to glVertexPointer/glNormalPointer are not done per draw, but per setup.
So, when you create the 2 drawWater objects, the last one leaves its vertex and normal data bound to the GL, which all the calls to glDrawElements will use.
You need to modify the code so that glVertexPointer/glNormalPointer (along with the glBindBuffer calls that accompany them) are done per draw.
Related
I'm learning to use LibGDX and my goal is to create a cube, with which you can control the resolution (number of vertices along each face). I already did that, and managed to use MeshBuilder to make it out of 6 different meshes and then render the resulting Mesh successfully using basic shaders :
Cube Mesh
//creates a square face with a normal vector and resolution number of vertices along any edge of the face
public Mesh createFace(Vector3 normal, int resolution) {
//creates 2 vectors perpendicular to each other and to the vector normal
Vector3 axisA = new Vector3(normal.y,normal.z,normal.x);
Vector3 axis = u.crs(normal, axisA);
Vector3 axisB = new Vector3(u.sqrt(axis.x),u.sqrt(axis.y),u.sqrt(axis.z));
//creates the arrays to hold the vertices and triangles
Vector3[] vertices = new Vector3[resolution * resolution];
//code for triangles
short[] triangles = new short[(resolution - 1) * (resolution - 1) * 6];
int triIndex = 0;
//looping over each vertex in the face
for (int y = 0; y < resolution; y++) {
for (int x = 0; x < resolution; x++) {
int vertexIndex = x + y * resolution;
//vector representing how close to the end of the x or y axis the loop is
Vector2 t = new Vector2(x / (resolution - 1f),y / (resolution - 1f));
//calculates the position of the vertex to place on the face
Vector3 mulA = u.mul(axisA, (2*t.x - 1));
Vector3 mulB = u.mul(axisB, (2*t.y-1));
Vector3 point = u.add3(normal, mulA, mulB);
//point = u.normalize(point);
vertices[vertexIndex] = point;
//puts the vertices into triangles
if (x != resolution - 1 && y != resolution - 1) {
triangles[triIndex + 0] = (short) vertexIndex;
triangles[triIndex + 1] = (short) (vertexIndex + resolution + 1);
triangles[triIndex + 2] = (short) (vertexIndex + resolution);
triangles[triIndex + 3] = (short) vertexIndex;
triangles[triIndex + 4] = (short) (vertexIndex + 1);
triangles[triIndex + 5] = (short) (vertexIndex + resolution + 1);
triIndex += 6;
}
}
}
float[] verticeList = u.vectorToList(vertices);
Mesh m = new Mesh(true, resolution * resolution, triangles.length, new VertexAttribute(Usage.Position,3,"a_Position"));
m.setIndices(triangles);
m.setVertices(verticeList);
return m;
}
//generates a cube Mesh with resolution vertices along each face
public Mesh generateFaces(int resolution, float scale) {
MeshBuilder meshBuilder = new MeshBuilder();
meshBuilder.begin(new VertexAttributes(new VertexAttribute (Usage.Position, 3 ,"a_Position")));
Vector3[] faceNormals = {
new Vector3(0,1*scale,0), //up
new Vector3(0,-1*scale,0), //down
new Vector3(-1*scale,0,0), //left
new Vector3(1*scale,0,0), //right
new Vector3(0,0,1*scale), //forward
new Vector3(0,0,-1*scale) //back
};
for (int i = 0; i < faceNormals.length; i++) {
meshBuilder.part("part"+ Integer.toString(i), GL20.GL_TRIANGLES);
meshBuilder.addMesh(createFace(faceNormals[i], resolution));
}
Mesh mesh = meshBuilder.end();
return mesh;
}
u is just a utilities class i created to store some math functions.
I then render it like so:
#Override
public void render () {
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
shader.bind();
shader.setUniformMatrix("matViewProj", cam.combined);
//rendering mesh
mesh1.render(shader, GL20.GL_LINE_STRIP);
[...]
}
I now want to make a model out of that mesh where each of the 6 faces will have a different color.
I thus tried to do it using a ModelBuilder following the LibGDX wiki, like so:
public Model generateModel(int resolution, float scale, Color[] colors) {
Vector3[] faceNormals = {
new Vector3(0,1*scale,0), //up
new Vector3(0,-1*scale,0), //down
new Vector3(-1*scale,0,0), //left
new Vector3(1*scale,0,0), //right
new Vector3(0,0,1*scale), //forward
new Vector3(0,0,-1*scale) //back
};
ModelBuilder modelBuilder = new ModelBuilder();
modelBuilder.begin();
for (int i = 0; i < faceNormals.length; i++) {
Mesh mesh = createFace(faceNormals[i], resolution);
MeshPart part = new MeshPart("part"+Integer.toString(i),mesh, 0, mesh.getNumVertices() ,GL20.GL_TRIANGLES);
modelBuilder.node().parts.add(new NodePart(part, new Material(ColorAttribute.createDiffuse(colors[i]))));
}
Model m = modelBuilder.end();
return m;
}
And then i rendered it using a ModelBatch and ModelInstance :
#Override
public void create () {
//creates an environment to handle lighting and such
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight,0.4f,0.4f,0.4f,1f));
environment.add(new DirectionalLight().set(0.8f,0.8f,0.8f,-1f,-0.8f,-0.2f));
modelBatch = new ModelBatch();
//handling the inputProcessors of the camera and stage(UI)
multiplexer = new InputMultiplexer();
stage = new Stage();
multiplexer.addProcessor(stage);
scroll = new ScrolledInputProcessor();
multiplexer.addProcessor(scroll);
//camera (3D inputProcessor)
cam = new PerspectiveCamera(67,Gdx.graphics.getWidth(),Gdx.graphics.getHeight());
cam.position.set(10f,10f,10f);
cam.lookAt(0,0,0);
cam.near = 1f;
cam.far = 300f;
cam.update();
camController = new CameraInputController(cam);
multiplexer.addProcessor(camController);
//shaders for every vertex and every pixel(fragment)
shader = new ShaderProgram(Gdx.files.internal("shader/vertexshader.glsl").readString() ,Gdx.files.internal("shader/fragmentshader.glsl").readString());
shader2 = new ShaderProgram(Gdx.files.internal("shader/vertexshader.glsl").readString() ,Gdx.files.internal("shader/fragmentshader2.glsl").readString());
//The 2D box encompassing the screen (UI)
table = new Table();
table.setFillParent(true);
stage.addActor(table);
//skins for UI
skin = new Skin(Gdx.files.internal("uiskin.json"));
//making a slider and dressing it in the skin
Drawable knobDown = skin.newDrawable("default-slider-knob", Color.GRAY);
SliderStyle sliderStyle = skin.get("default-horizontal", SliderStyle.class);
sliderStyle.knobDown = knobDown;
slider = new Slider(3.0f, 70.0f, 1.0f, false, sliderStyle);
table.right().top();
table.add(slider).row();
//creates the unit cube and unit sphere
model = generateModel(res, 1, colors);
instance = new ModelInstance(model);
font = new BitmapFont(Gdx.files.internal("uiskin.fnt"));
batch = new SpriteBatch();
Gdx.input.setInputProcessor(multiplexer);
}
#Override
public void render () {
camController.update();
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(0.5f, 0.5f, 0.5f, 0.5f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
shader.bind();
shader.setUniformMatrix("matViewProj", cam.combined);
modelBatch.begin(cam);
modelBatch.render(instance, environment);
modelBatch.end();
batch.begin();
font.draw(batch, "Zoom Level : " + zoomLevel, 1000f, 100f);
batch.end();
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
However, when i run the program, nothing is rendered, just the gray void.
Gray void of nothingness
My question is: How do I get my model to render?
I've been working on this a while and feel so close! Should be easy, but I'm still new to this.
The skeleton hand data is being passed in as joints[KinectPV2.JointType_HandLeft] and can be accessed through joint.getX() and joint.getY(). I want to pass this data into the update function to replace mouseX and mouseY. I'm guessing I have to create global variables to access it within the update function or maybe I have to pass the skeleton data as parameters into the update function? How can I replace the mouse position data with the hand position?
import KinectPV2.*;
KinectPV2 kinect;
private class MyFluidData implements DwFluid2D.FluidData{
// update() is called during the fluid-simulation update step.
#Override
public void update(DwFluid2D fluid) {
float px, py, vx, vy, radius, vscale, temperature;
radius = 15;
vscale = 10;
px = width/2;
py = 50;
vx = 1 * +vscale;
vy = 1 * vscale;
radius = 40;
temperature = 1f;
fluid.addDensity(px, py, radius, 0.2f, 0.3f, 0.5f, 1.0f);
fluid.addTemperature(px, py, radius, temperature);
particles.spawn(fluid, px, py, radius, 100);
boolean mouse_input = mousePressed;
// add impulse: density + velocity, particles
if(mouse_input && mouseButton == LEFT){
radius = 15;
vscale = 15;
px = mouseX;
py = height-mouseY;
vx = (mouseX - pmouseX) * +vscale;
vy = (mouseY - pmouseY) * -vscale;
fluid.addDensity (px, py, radius, 0.25f, 0.0f, 0.1f, 1.0f);
fluid.addVelocity(px, py, radius, vx, vy);
particles.spawn(fluid, px, py, radius*2, 300);
}
// add impulse: density + temperature, particles
if(mouse_input && mouseButton == CENTER){
radius = 15;
vscale = 15;
px = mouseX;
py = height-mouseY;
temperature = 2f;
fluid.addDensity(px, py, radius, 0.25f, 0.0f, 0.1f, 1.0f);
fluid.addTemperature(px, py, radius, temperature);
particles.spawn(fluid, px, py, radius, 100);
}
// particles
if(mouse_input && mouseButton == RIGHT){
px = mouseX;
py = height - 1 - mouseY; // invert
radius = 50;
particles.spawn(fluid, px, py, radius, 300);
}
}
}
int viewport_w = 1280;
int viewport_h = 720;
int viewport_x = 230;
int viewport_y = 0;
int gui_w = 200;
int gui_x = 20;
int gui_y = 20;
int fluidgrid_scale = 3;
DwFluid2D fluid;
// render targets
PGraphics2D pg_fluid;
//texture-buffer, for adding obstacles
PGraphics2D pg_obstacles;
// custom particle system
MyParticleSystem particles;
// some state variables for the GUI/display
int BACKGROUND_COLOR = 0;
boolean UPDATE_FLUID = true;
boolean DISPLAY_FLUID_TEXTURES = false;
boolean DISPLAY_FLUID_VECTORS = false;
int DISPLAY_fluid_texture_mode = 0;
boolean DISPLAY_PARTICLES = true;
public void settings() {
size(viewport_w, viewport_h, P2D);
smooth(4);
}
public void setup() {
surface.setLocation(viewport_x, viewport_y);
// main library context
DwPixelFlow context = new DwPixelFlow(this);
context.print();
context.printGL();
// fluid simulation
fluid = new DwFluid2D(context, viewport_w, viewport_h, fluidgrid_scale);
// set some simulation parameters
fluid.param.dissipation_density = 0.999f;
fluid.param.dissipation_velocity = 0.99f;
fluid.param.dissipation_temperature = 0.80f;
fluid.param.vorticity = 0.10f;
fluid.param.timestep = 0.25f;
fluid.param.gridscale = 8f;
// interface for adding data to the fluid simulation
MyFluidData cb_fluid_data = new MyFluidData();
fluid.addCallback_FluiData(cb_fluid_data);
// pgraphics for fluid
pg_fluid = (PGraphics2D) createGraphics(viewport_w, viewport_h, P2D);
pg_fluid.smooth(4);
pg_fluid.beginDraw();
pg_fluid.background(BACKGROUND_COLOR);
pg_fluid.endDraw();
// pgraphics for obstacles
pg_obstacles = (PGraphics2D) createGraphics(viewport_w, viewport_h, P2D);
pg_obstacles.smooth(4);
pg_obstacles.beginDraw();
pg_obstacles.clear();
float radius;
radius = 200;
pg_obstacles.stroke(64);
pg_obstacles.strokeWeight(1);
pg_obstacles.fill(0);
pg_obstacles.rect(1*width/2f, 1*height/4f, radius, radius/2, 10);
pg_obstacles.stroke(64);
pg_obstacles.strokeWeight(1);
pg_obstacles.fill(0);
pg_obstacles.rect(1*width/3.5f, 1*height/2.5f, radius, radius/2, 10);
//// border-obstacle
//pg_obstacles.strokeWeight(20);
//pg_obstacles.stroke(64);
//pg_obstacles.noFill();
//pg_obstacles.rect(0, 0, pg_obstacles.width, pg_obstacles.height);
pg_obstacles.endDraw();
fluid.addObstacles(pg_obstacles);
// custom particle object
particles = new MyParticleSystem(context, 1024 * 1024);
kinect = new KinectPV2(this);
//Enables depth and Body tracking (mask image)
kinect.enableDepthMaskImg(true);
kinect.enableSkeletonDepthMap(true);
kinect.init();
background(0);
frameRate(60);
}
public void draw() {
PImage imgC = kinect.getDepthMaskImage();
image(imgC, 0, 0, 320, 240);
//get the skeletons as an Arraylist of KSkeletons
ArrayList<KSkeleton> skeletonArray = kinect.getSkeletonDepthMap();
//individual joints
for (int i = 0; i < skeletonArray.size(); i++) {
KSkeleton skeleton = (KSkeleton) skeletonArray.get(i);
//if the skeleton is being tracked compute the skleton joints
if (skeleton.isTracked()) {
KJoint[] joints = skeleton.getJoints();
color col = skeleton.getIndexColor();
fill(col);
stroke(col);
drawHandState(joints[KinectPV2.JointType_HandRight]);
drawHandState(joints[KinectPV2.JointType_HandLeft]);
}
}
// update simulation
if(UPDATE_FLUID){
fluid.addObstacles(pg_obstacles);
fluid.update();
particles.update(fluid);
}
// clear render target
pg_fluid.beginDraw();
pg_fluid.background(BACKGROUND_COLOR);
pg_fluid.endDraw();
// render fluid stuff
if(DISPLAY_FLUID_TEXTURES){
// render: density (0), temperature (1), pressure (2), velocity (3)
fluid.renderFluidTextures(pg_fluid, DISPLAY_fluid_texture_mode);
}
if(DISPLAY_FLUID_VECTORS){
// render: velocity vector field
fluid.renderFluidVectors(pg_fluid, 10);
}
if( DISPLAY_PARTICLES){
// render: particles; 0 ... points, 1 ...sprite texture, 2 ... dynamic points
particles.render(pg_fluid, BACKGROUND_COLOR);
}
// display
image(pg_fluid , 320, 0);
image(pg_obstacles, 320, 0);
// display number of particles as text
//String txt_num_particles = String.format("Particles %,d", particles.ALIVE_PARTICLES);
//fill(0, 0, 0, 220);
//noStroke();
//rect(10, height-10, 160, -30);
//fill(255,128,0);
//text(txt_num_particles, 20, height-20);
// info
//String txt_fps = String.format(getClass().getName()+ " [size %d/%d] [frame %d] [fps %6.2f]", fluid.fluid_w, fluid.fluid_h, fluid.simulation_step, frameRate);
//surface.setTitle(txt_fps);
}
//draw a ellipse depending on the hand state
void drawHandState(KJoint joint) {
noStroke();
handState(joint.getState());
//println(joint.getState());
pushMatrix();
translate(joint.getX(), joint.getY(), joint.getZ());
//println(joint.getX(), joint.getY(), joint.getZ());
ellipse(joint.getX(), joint.getY(), 70, 70);
popMatrix();
}
/*
Different hand state
KinectPV2.HandState_Open
KinectPV2.HandState_Closed
KinectPV2.HandState_Lasso
KinectPV2.HandState_NotTracked
*/
//Depending on the hand state change the color
void handState(int handState) {
switch(handState) {
case KinectPV2.HandState_Open:
fill(0, 255, 0);
break;
case KinectPV2.HandState_Closed:
fill(255, 0, 0);
break;
case KinectPV2.HandState_Lasso:
fill(0, 0, 255);
break;
case KinectPV2.HandState_NotTracked:
fill(100, 100, 100);
break;
}
}
I'm guessing I have to create global variables to access it within the update function or maybe I have to pass the skeleton data as parameters into the update function?
What happened when you tried those approaches?
Either approach sounds fine. You could store the variables in a sketch-level variable, set those variables from the kinect code, then use those variables in your drawing code. Or you could pass the variables as a parameter to the drawing code. Either should work fine. I'd probably go for the first approach because it sounds easier to me, but that's just my personal preference.
I suggest working in smaller chunks. Create a separate program that ignores the kinect for now. Create a hard-coded sketch-level variable that holds the same type of information you'd get from the kinect. Then write drawing code that uses that hard-coded variable to draw the frame. Get that working perfectly before you try adding the kinect code back in.
Then if you get stuck on a specific step, you can post a MCVE and we can go from there. Good luck.
So far, i have the code to get the mouse's position in the world, however i need to get it on a given plane (z=0), how can i go about doing this? Here is my picking code :
static public Vector3f getMousePositionIn3dCoords(int mouseX, int mouseY) {
viewport.clear();
modelview.clear();
projection.clear();
winZ.clear();;
position.clear();
float winX, winY;
GL11.glGetFloat( GL11.GL_MODELVIEW_MATRIX, modelview );
GL11.glGetFloat( GL11.GL_PROJECTION_MATRIX, projection );
GL11.glGetInteger( GL11.GL_VIEWPORT, viewport );
winX = (float)mouseX;
winY = (float)mouseY;
GL11.glReadPixels(mouseX, mouseY, 1, 1, GL11.GL_DEPTH_COMPONENT, GL11.GL_FLOAT, winZ);
float zz = winZ.get();
GLU.gluUnProject(winX, winY, zz, modelview, projection, viewport, position);
Vector3f v = new Vector3f(position.get(0),position.get(1),position.get(2));
return v ;
}
I've solved it, for anyone interested, here is my modified code for getting the x and y in the world when z=0 :
static public Vector3f getMouseOnPlaneZ(int mouseX, int mouseY)
{
viewport.clear();
modelview.clear();
projection.clear();
winZ.clear();;
position.clear();
float winX, winY;
GL11.glGetFloat( GL11.GL_MODELVIEW_MATRIX, modelview );
GL11.glGetFloat( GL11.GL_PROJECTION_MATRIX, projection );
GL11.glGetInteger( GL11.GL_VIEWPORT, viewport );
winX = (float)mouseX;
winY = (float)mouseY;
GLU.gluUnProject(winX, winY, 0.0f, modelview, projection, viewport, position);
GLU.gluUnProject(winX, winY, 1.0f, modelview, projection, viewport, position1);
float zeropoint, zeroperc;
double posXt, posYt, posZt;
posXt = position.get(0) - position1.get(0);
posYt = position.get(1) - position1.get(1);
posZt = position.get(2) - position1.get(2);
if ((position.get(2) < 0.0 && position1.get(2) < 0.0) || (position.get(2) > 0.0 && position1.get(2) > 0.0))
return null;
zeropoint = 0.0f - (float)position.get(2);
//Find the percentage that this point is between them
zeroperc = (zeropoint / (float)posZt);
Vector3f v = new Vector3f((float)position.get(0) + (float)(posXt * zeroperc),(float)position.get(1) + (float)(posYt * zeroperc),(float)position.get(2) + (float)(posZt * zeroperc));
return v ;
}
I am trying to make a game/demo with Java/LWJGL and having troubles with the first person camera:
I use the WASD to move the eye vector around, however strange things are happening:
When I move the eye away or to me, the right resp. left parts of the view get blocked for my view.
When I move the eye to the right or left of me, then the top resp. bottom parts of the view get blocked for my view.
I have implemented mouse movement (to look around) with success, the relevant pieces of code now:
(Note: The Matrix4f class works in column-major order)
Matrix4f viewMatrix = new Matrix4f();
private void checkKeys() {
if (isKeyCurrentlyDown(Keyboard.KEY_W)) {
eye.updateTranslate(1.0f, 0.0f, 0.0f);
updateView();
}
else if (isKeyCurrentlyDown(Keyboard.KEY_S)) {
eye.updateTranslate(-1.0f, 0.0f, 0.0f);
updateView();
}
else if (isKeyCurrentlyDown(Keyboard.KEY_A)) {
eye.updateTranslate(0.0f, -1.0f, 0.0f);
updateView();
}
else if (isKeyCurrentlyDown(Keyboard.KEY_D)) {
eye.updateTranslate(0.0f, 1.0f, 0.0f);
updateView();
}
}
private void updateView() {
System.out.println("eye = " + eye);
viewMatrix.identity().viewFPS(eye, roll, yaw, pitch);
System.out.println("viewMatrix = " + viewMatrix);
Uniforms.setUniformMatrix4(UNIFORM_VIEW_MATRIX, false, viewMatrix);
}
#Override
protected void render(final double msDelta) {
super.render(msDelta);
glClearColor(0.0f, 0.25f, 0.0f, 1.0f);
glClearDepthf(1f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
program.use();
for (int i = 0; i < 24; i++) {
float fVar = i + currentTime / 1000f * 0.3f;
modelviewMatrix.identity()
.translate(0.0f, 0.0f, -8.0f)
.rotate(currentTime / 1000f * 45.0f, 0.0f, 1.0f, 0.0f)
.rotate(currentTime / 1000f * 21.0f, 1.0f, 0.0f, 0.0f)
.translate(
(float)Math.sin(2.1f * fVar) * 2.0f,
(float)Math.cos(1.7f * fVar) * 2.0f,
(float)Math.sin(1.3f * fVar) * (float)Math.cos(1.5f * fVar) * 2.0f
);
Uniforms.setUniformMatrix4(UNIFORM_MODEL_MATRIX, false, modelviewMatrix.writeToFloatBuffer(modelViewMatrixBuffer));
program.drawElements(GL_TRIANGLES, 36, GL_UNSIGNED_INT, 0);
}
}
#version 440 core
layout(location = 0) in vec4 position;
out VS_OUT {
vec4 color;
} vs_out;
layout(location = 0) uniform mat4 model_matrix;
layout(location = 1) uniform mat4 view_matrix;
layout(location = 2) uniform mat4 proj_matrix;
void main() {
gl_Position = proj_matrix * view_matrix * model_matrix * position;
vs_out.color = position * 2.0 + vec4(0.5, 0.5, 0.5, 0.0);
}
public enum UniformLocation {
UNIFORM_MODEL_MATRIX(0),
UNIFORM_VIEW_MATRIX(1),
UNIFORM_PROJECTION_MATRIX(2)
;
private final int location;
private UniformLocation(final int location) {
this.location = location;
}
public int getLocation() {
return this.location;
}
}
//Column-major order
public Matrix4f viewFPS(final Vector3f eye, final float rollAngle, final float yawAngle, final float pitchAngle) {
//roll = rolling your head, Q&E
//yaw = looking left/right, mouseY
//pitch = looking up/down, mouseX
float sinRoll = (float)Math.sin(Math.toRadians(rollAngle));
float cosRoll = (float)Math.cos(Math.toRadians(rollAngle));
float sinYaw = (float)Math.sin(Math.toRadians(yawAngle));
float cosYaw = (float)Math.cos(Math.toRadians(yawAngle));
float sinPitch = (float)Math.sin(Math.toRadians(pitchAngle));
float cosPitch = (float)Math.cos(Math.toRadians(pitchAngle));
Vector3f xAxis = new Vector3f(
cosYaw * cosPitch,
sinYaw * cosPitch,
-sinPitch
);
Vector3f yAxis = new Vector3f(
cosYaw * sinPitch * sinRoll - sinYaw * cosRoll,
sinYaw * sinPitch * sinRoll + cosYaw * cosRoll,
cosPitch * sinRoll
);
Vector3f zAxis = new Vector3f(
cosYaw * sinPitch * cosRoll + sinYaw * sinRoll,
sinYaw * sinPitch * cosRoll - cosYaw * sinRoll,
cosPitch * cosRoll
);
return multiply(
xAxis.getX(), xAxis.getY(), xAxis.getZ(), -xAxis.dot(eye), //X column
yAxis.getX(), yAxis.getY(), yAxis.getZ(), -yAxis.dot(eye), //Y column
zAxis.getX(), zAxis.getY(), zAxis.getZ(), -zAxis.dot(eye), //Z column
0.0f, 0.0f, 0.0f, 1.0f //W column
);
}
I really have no clue why the camera is behaving so weirdly, and what it even means?
How can parts of the picture suddenly become not visible anymore?
Update: It might have to do with the viewFPS() method, as the translations look slightly odd there, could someone confirm?
Noticed that in viewFPS you combine rotation and translation in one matrix multiplication.
I am not familiar with the way you build the matrix, but I can tell you what works for me.
Create 3 matrices, one for X rotation, Y rotation and Z rotation values.
Multiply those matrices in the order you want. (I use Z, Y then X)
Multiply the result with your translation matrix. (i.e Position of your eye)
The resulting matrix is your view matrix.
This might be less efficient than the method you are using, but it's great to get it working then optimize from there? Splitting up the rotation axies also gives the benefit of being able to debug 1 axis at a time.
Rotation matrices I use:
Where , (phi), and (psi) are the rotations around the X, Y and Z axes.(http://www.fastgraph.com/makegames/3drotation/)
Help me find my mistake. I make an example from book but may be author (or i)make some trouble and i cant find solve.
First class is geometry of my object
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import javax.microedition.khronos.opengles.GL10;
public class Planet {
FloatBuffer m_VertexData;
FloatBuffer m_NormalData;
FloatBuffer m_ColorData;
float m_Scale;
float m_Squash;
float m_Radius;
int m_Stacks, m_Slices;
public final static int SS_SUNLIGHT = GL10.GL_LIGHT0;
public Planet(int stacks, int slices, float radius, float squash) {
this.m_Stacks = stacks; //1
this.m_Slices = slices;
this.m_Radius = radius;
this.m_Squash=squash;
init(m_Stacks,m_Slices,radius,squash,"dummy");
}
private void init(int stacks,int slices, float radius, float squash, String textureFile) {
float[] vertexData;
float[] colorData; //2
float[] normalData;
float colorIncrement=0f;
float blue=0f;
float red=1.0f;
int numVertices=0;
int vIndex=0;
int cIndex=0;
int nIndex =0;
m_Scale=radius;
m_Squash=squash;
colorIncrement=1.0f/(float)stacks;//3
m_Stacks = stacks;
m_Slices = slices;
//vertices
vertexData = new float[ 3*((m_Slices*2+2) * m_Stacks)]; //4
//color data
colorData = new float[ (4*(m_Slices*2+2) * m_Stacks)]; //5
// Normalize data
normalData = new float [ (3*(m_Slices*2+2)* m_Stacks)]; //1
int phiIdx, thetaIdx;
//latitude
for(phiIdx=0; phiIdx < m_Stacks; phiIdx++) //6
{
//starts at -90 degrees (-1.57 radians) goes up to +90 degrees (or +1.57 radians)
//the first circle
float phi0 = (float)Math.PI * ((float)(phiIdx+0) * (1.0f/(float)(m_Stacks)) - 0.5f); //7
//the next, or second one.
float phi1 = (float)Math.PI * ((float)(phiIdx+1) * (1.0f/(float)(m_Stacks)) - 0.5f); //8
float cosPhi0 = (float)Math.cos(phi0); //9
float sinPhi0 = (float)Math.sin(phi0);
float cosPhi1 = (float)Math.cos(phi1);
float sinPhi1 = (float)Math.sin(phi1);
float cosTheta, sinTheta;
//longitude
for(thetaIdx=0;thetaIdx < m_Slices; thetaIdx++)
{
//increment along the longitude circle each "slice"
float theta= (float) (-2.0f*(float)Math.PI * ((float)thetaIdx) *(1.0/(float)(m_Slices-1)));
cosTheta = (float)Math.cos(theta);
sinTheta = (float)Math.sin(theta);
//we're generating a vertical pair of points, such
//as the first point of stack 0 and the first point of stack 1
//above it. This is how TRIANGLE_STRIPS work,
//taking a set of 4 vertices and essentially drawing two triangles
//at a time. The first is v0-v1-v2 and the next is v2-v1-v3. Etc.
//get x-y-z for the first vertex of stack
vertexData[vIndex+0] = m_Scale*cosPhi0*cosTheta; //11
vertexData[vIndex+1] = m_Scale*(sinPhi0*m_Squash);
vertexData[vIndex+2] = m_Scale*(cosPhi0*sinTheta);
vertexData[vIndex+3] = m_Scale*cosPhi1*cosTheta;
vertexData[vIndex+4] = m_Scale*(sinPhi1*m_Squash);
vertexData[vIndex+5] = m_Scale*(cosPhi1*sinTheta);
colorData[cIndex+0] = (float)red; //12
colorData[cIndex+1] = (float)0f;
colorData[cIndex+2] = (float)blue;
colorData[cIndex+4] = (float)red;
colorData[cIndex+5] = (float)0f;
colorData[cIndex+6] = (float)blue;
colorData[cIndex+3] = (float)1.0;
colorData[cIndex+7] = (float)1.0;
// Normalize data pointers for lighting.
normalData[nIndex + 0] = cosPhi0*cosTheta;
normalData[nIndex + 1] = sinPhi0;
normalData[nIndex + 2] = cosPhi0*sinTheta;
normalData[nIndex + 3] = cosPhi1*cosTheta;
normalData[nIndex + 4] = sinPhi1;
normalData[nIndex + 5] = cosPhi1*sinTheta;
cIndex+=2*4; //13
vIndex+=2*3; //14
nIndex+=2*3;
}
// blue+=colorIncrement; //15
red-=colorIncrement;
// create a degenerate triangle to connect stacks and maintain winding order //16
vertexData[vIndex+0] = vertexData[vIndex+3] = vertexData[vIndex-3];
vertexData[vIndex+1] = vertexData[vIndex+4] = vertexData[vIndex-2];
vertexData[vIndex+2] = vertexData[vIndex+5] = vertexData[vIndex-1];
}
m_VertexData = makeFloatBuffer(vertexData); //17
m_ColorData = makeFloatBuffer(colorData);
m_NormalData = makeFloatBuffer(normalData);
}
protected static FloatBuffer makeFloatBuffer(float[] arr)
{
ByteBuffer bb = ByteBuffer.allocateDirect(arr.length*4);
bb.order(ByteOrder.nativeOrder());
FloatBuffer fb = bb.asFloatBuffer(); fb.put(arr);
fb.position(0);
return fb;
}
public void draw(GL10 gl) {
gl.glFrontFace(GL10.GL_CW); //1
gl.glVertexPointer(3, GL10.GL_FLOAT, 0, m_VertexData); //2
gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
gl.glColorPointer(4, GL10.GL_FLOAT, 0, m_ColorData); gl.glEnableClientState(GL10.GL_COLOR_ARRAY);
//3
gl.glDrawArrays(GL10.GL_TRIANGLE_FAN, 0, (m_Slices+1)*2*(m_Stacks-1)+2);
}
private void initLighting(GL10 gl) {
float[] diffuse = {0.0f, 1.0f, 0.0f, 1.0f}; //1
float[] pos = {0.0f, 10.0f, -3.0f, 1.0f}; //2
gl.glLightfv(SS_SUNLIGHT, GL10.GL_POSITION, makeFloatBuffer(pos)); //3
gl.glLightfv(SS_SUNLIGHT, GL10.GL_DIFFUSE, makeFloatBuffer(diffuse)); //4
gl.glShadeModel(GL10.GL_FLAT); //5
gl.glEnable(GL10.GL_LIGHTING); //6
gl.glEnable(SS_SUNLIGHT); //7
}
}
And second is a render:
package com.example.solarsystem;
import javax.microedition.khronos.egl.EGLConfig;
import javax.microedition.khronos.opengles.GL10;
import android.opengl.GLSurfaceView;
public class SolarSystemRenderer implements GLSurfaceView.Renderer{
private Planet mPlanet;
public SolarSystemRenderer(boolean b) {
mPlanet=new Planet(30,30,1.0f, 1.0f);
}
private float mTransY;
private float mAngle;
public void onDrawFrame(GL10 gl) {
gl.glClear(GL10.GL_COLOR_BUFFER_BIT | GL10.GL_DEPTH_BUFFER_BIT);
gl.glClearColor(0.0f,0.0f,0.0f,1.0f);
gl.glMatrixMode(GL10.GL_MODELVIEW);
gl.glLoadIdentity();
gl.glTranslatef(0.0f,(float)Math.sin(mTransY), -10.0f);
gl.glRotatef(mAngle, 1, 0, 0);
gl.glRotatef(mAngle, 0, 1, 0);
mPlanet.draw(gl);
mTransY+=.0f;
mAngle+=.4;
}
public void onSurfaceChanged(GL10 gl, int width, int height) //11
{
gl.glViewport(0, 0, width, height); //12
float aspectRatio;
float zNear =3.2f;
float zFar =1000;
float fieldOfView = 30.0f/57.3f; //1
float size;
gl.glEnable(GL10.GL_NORMALIZE);
aspectRatio=(float)width/(float)height; //2
gl.glMatrixMode(GL10.GL_PROJECTION); //3
size = zNear * (float)(Math.tan((double)(fieldOfView/2.0f))); //4
gl.glFrustumf(-size, size, -size /aspectRatio, //5
size /aspectRatio, zNear, zFar);
}
public void onSurfaceCreated(GL10 gl, EGLConfig config) //15
{
gl.glDisable(GL10.GL_DITHER); //16
gl.glHint(GL10.GL_PERSPECTIVE_CORRECTION_HINT, GL10.GL_FASTEST); //17
gl.glEnable(GL10.GL_CULL_FACE);
gl.glCullFace(GL10.GL_BACK);
gl.glShadeModel(GL10.GL_SMOOTH);
gl.glEnable(GL10.GL_DEPTH_TEST);
gl.glDepthMask(false);
initGeometry(gl);
initLighting(gl);
}
}
So in surfaceCreated method i have mistake in initialization initGeometry(gl);
initLighting(gl);
Also if i cut my initLighting method from first class to render class i get mistake on initialization makeFloatBuffer.
I also had problems with this part of the book.
Try commenting out a couple of lines in the onSurfaceCreated method in the renderer:
initGeometry(gl); - because there is no method defined for this in the code.
gl.glEnable(GL10.GL_DEPTH_TEST); - Not sure what the problem with this line, but commenting this one out made the whole thing work as described in the book.