嗨,我正在创建一个水景,并有一个名为drawWater的课程。该类采用等式来改变它的外观。当我尝试创建
时drawater water = new drawWater();
drawater water2 = new drawWater();
它们似乎都是使用正确的值创建的,但是当我将它们绘制到屏幕上时,只会显示一个值。两个值都不同。
我不知道我哪里出错了。它似乎不是JOGL问题,而是我设置课程的方式?
谁能看到我哪里出错?
这是主要课程:
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();
}
}
这是渲染器类:
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());
}
}
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)};
}
}
}
任何帮助都会受到赞赏。这是我大学最后一年项目的一部分。所以任何帮助都会很棒。
答案 0 :(得分:0)
glVertexPointer/glNormalPointer
的调用不是每次绘制,而是按照设置完成。
因此,当你创建2个drawWater对象时,最后一个将其顶点和普通数据绑定到GL,所有对glDrawElements的调用都将使用。
你需要修改代码,以便每次绘制glVertexPointer / glNormalPointer(以及伴随它们的glBindBuffer调用)。