mirror of
https://github.com/shadowfacts/lwjgl2-arm64.git
synced 2026-04-11 01:14:00 +00:00
Added support for OpenGL ES.
This commit is contained in:
parent
8f6dcd3a6d
commit
40cbf3e45f
213 changed files with 19618 additions and 194 deletions
327
src/java/org/lwjgl/test/opengles/FullScreenWindowedTest.java
Normal file
327
src/java/org/lwjgl/test/opengles/FullScreenWindowedTest.java
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2008 LWJGL Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'LWJGL' nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
package org.lwjgl.test.opengles;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.DisplayMode;
|
||||
import org.lwjgl.opengles.PixelFormat;
|
||||
import org.lwjgl.opengles.PowerManagementEventException;
|
||||
import org.lwjgl.util.vector.Vector2f;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
import static org.lwjgl.test.opengles.util.GLMatrix.*;
|
||||
|
||||
/**
|
||||
* Tests switching between windowed and fullscreen
|
||||
*
|
||||
* @author Brian Matzon <brian@matzon.dk>
|
||||
* @version $Revision: 3172 $
|
||||
* $Id: FullScreenWindowedTest.java 3172 2008-12-28 19:30:43Z elias_naur $
|
||||
*/
|
||||
public class FullScreenWindowedTest {
|
||||
|
||||
/** Intended deiplay mode */
|
||||
private DisplayMode mode;
|
||||
/** our quad moving around */
|
||||
private Vector2f quadPosition;
|
||||
/** our quadVelocity */
|
||||
private Vector2f quadVelocity;
|
||||
/** angle of quad */
|
||||
private float angle;
|
||||
/** degrees to rotate per frame */
|
||||
private float angleRotation = 1.0f;
|
||||
/** Max speed of all changable attributes */
|
||||
private static final float MAX_SPEED = 20.0f;
|
||||
|
||||
private static int buffer_id;
|
||||
private static int indices_buffer_id;
|
||||
|
||||
private QuadRenderer renderer;
|
||||
|
||||
/** Creates a FullScreenWindowedTest */
|
||||
public FullScreenWindowedTest() {
|
||||
}
|
||||
|
||||
/** Executes the test */
|
||||
public void execute() {
|
||||
initialize();
|
||||
mainLoop();
|
||||
cleanup();
|
||||
Display.destroy();
|
||||
}
|
||||
|
||||
private void switchMode() throws LWJGLException {
|
||||
mode = findDisplayMode(1024, 600, Display.getDisplayMode().getBitsPerPixel());
|
||||
try {
|
||||
Display.setDisplayModeAndFullscreen(mode);
|
||||
} catch (PowerManagementEventException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/** Initializes the test */
|
||||
private void initialize() {
|
||||
try {
|
||||
//find displaymode
|
||||
switchMode();
|
||||
// start of in windowed mode
|
||||
Display.create(new PixelFormat());
|
||||
glInit();
|
||||
quadPosition = new Vector2f(100f, 100f);
|
||||
quadVelocity = new Vector2f(1.0f, 1.0f);
|
||||
|
||||
renderer = new QuadRenderer();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/** Runs the main loop of the "test" */
|
||||
private void mainLoop() {
|
||||
while ( !Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) && !Display.isCloseRequested() ) {
|
||||
if ( Display.isVisible() ) {
|
||||
// check keyboard input
|
||||
processKeyboard();
|
||||
// do "game" logic, and render it
|
||||
logic();
|
||||
render();
|
||||
} else {
|
||||
// no need to render/paint if nothing has changed (ie. window
|
||||
// dragged over)
|
||||
if ( Display.isDirty() ) {
|
||||
render();
|
||||
}
|
||||
// don't waste cpu time, sleep more
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
} catch (InterruptedException inte) {
|
||||
}
|
||||
}
|
||||
// Update window
|
||||
try {
|
||||
Display.update();
|
||||
Display.sync(60);
|
||||
} catch (PowerManagementEventException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Performs the logic */
|
||||
private void logic() {
|
||||
angle += angleRotation;
|
||||
if ( angle > 90.0f ) {
|
||||
angle = 0.0f;
|
||||
}
|
||||
quadPosition.x += quadVelocity.x;
|
||||
quadPosition.y += quadVelocity.y;
|
||||
//check colision with vertical border border
|
||||
if ( quadPosition.x + 50 >= mode.getWidth() || quadPosition.x - 50 <= 0 ) {
|
||||
quadVelocity.x *= -1;
|
||||
}
|
||||
//check collision with horizontal border
|
||||
if ( quadPosition.y + 50 >= mode.getHeight() || quadPosition.y - 50 <= 0 ) {
|
||||
quadVelocity.y *= -1;
|
||||
}
|
||||
}
|
||||
|
||||
private void render() {
|
||||
//clear background
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
// draw white quad
|
||||
glPushMatrix();
|
||||
{
|
||||
glTranslatef(quadPosition.x, quadPosition.y, 0);
|
||||
glRotatef(angle, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
renderer.setMVPUniform();
|
||||
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
/** Processes keyboard input */
|
||||
private void processKeyboard() {
|
||||
//check for fullscreen key
|
||||
if ( Keyboard.isKeyDown(Keyboard.KEY_F) ) {
|
||||
try {
|
||||
cleanup();
|
||||
|
||||
switchMode();
|
||||
|
||||
glInit();
|
||||
renderer = new QuadRenderer();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
//check for window key
|
||||
if ( Keyboard.isKeyDown(Keyboard.KEY_W) ) {
|
||||
try {
|
||||
cleanup();
|
||||
|
||||
mode = new DisplayMode(800, 480);
|
||||
Display.setDisplayModeAndFullscreen(mode);
|
||||
|
||||
glInit();
|
||||
renderer = new QuadRenderer();
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
//check for speed changes
|
||||
if ( Keyboard.isKeyDown(Keyboard.KEY_UP) ) {
|
||||
quadVelocity.y += 0.1f;
|
||||
}
|
||||
if ( Keyboard.isKeyDown(Keyboard.KEY_DOWN) ) {
|
||||
quadVelocity.y -= 0.1f;
|
||||
}
|
||||
if ( Keyboard.isKeyDown(Keyboard.KEY_RIGHT) ) {
|
||||
quadVelocity.x += 0.1f;
|
||||
}
|
||||
if ( Keyboard.isKeyDown(Keyboard.KEY_LEFT) ) {
|
||||
quadVelocity.x -= 0.1f;
|
||||
}
|
||||
if ( Keyboard.isKeyDown(Keyboard.KEY_ADD) ) {
|
||||
angleRotation += 0.1f;
|
||||
}
|
||||
if ( Keyboard.isKeyDown(Keyboard.KEY_SUBTRACT) ) {
|
||||
angleRotation -= 0.1f;
|
||||
}
|
||||
//throttle
|
||||
if ( quadVelocity.x < -MAX_SPEED ) {
|
||||
quadVelocity.x = -MAX_SPEED;
|
||||
}
|
||||
if ( quadVelocity.x > MAX_SPEED ) {
|
||||
quadVelocity.x = MAX_SPEED;
|
||||
}
|
||||
if ( quadVelocity.y < -MAX_SPEED ) {
|
||||
quadVelocity.y = -MAX_SPEED;
|
||||
}
|
||||
if ( quadVelocity.y > MAX_SPEED ) {
|
||||
quadVelocity.y = MAX_SPEED;
|
||||
}
|
||||
if ( angleRotation < 0.0f ) {
|
||||
angleRotation = 0.0f;
|
||||
}
|
||||
if ( angleRotation > MAX_SPEED ) {
|
||||
angleRotation = MAX_SPEED;
|
||||
}
|
||||
}
|
||||
|
||||
/** Cleans up the test */
|
||||
private void cleanup() {
|
||||
renderer.cleanup();
|
||||
|
||||
IntBuffer int_buffer = BufferUtils.createIntBuffer(2);
|
||||
int_buffer.put(0, buffer_id);
|
||||
int_buffer.put(1, indices_buffer_id);
|
||||
|
||||
glDeleteBuffers(int_buffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves a displaymode, if one such is available
|
||||
*
|
||||
* @param width Required width
|
||||
* @param height Required height
|
||||
* @param bpp Minimum required bits per pixel
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private static DisplayMode findDisplayMode(int width, int height, int bpp) throws LWJGLException {
|
||||
DisplayMode[] modes = Display.getAvailableDisplayModes();
|
||||
for ( int i = 0; i < modes.length; i++ ) {
|
||||
if ( modes[i].getWidth() == width && modes[i].getHeight() == height && modes[i].getBitsPerPixel() >= bpp && modes[i].getFrequency() <= 60 ) {
|
||||
return modes[i];
|
||||
}
|
||||
}
|
||||
return Display.getDesktopDisplayMode();
|
||||
}
|
||||
|
||||
/** Initializes OGL */
|
||||
private void glInit() {
|
||||
// Go into orthographic projection mode.
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, mode.getWidth(), 0, mode.getHeight(), -1.0f, 1.0f);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
|
||||
glViewport(0, 0, mode.getWidth(), mode.getHeight());
|
||||
//set clear color to black
|
||||
glClearColor(0.0f, 0.0f, 0.0f, 0.0f);
|
||||
|
||||
//sync frame (only works on windows)
|
||||
Display.setVSyncEnabled(true);
|
||||
|
||||
final IntBuffer int_buffer = BufferUtils.createIntBuffer(2);
|
||||
glGenBuffers(int_buffer);
|
||||
buffer_id = int_buffer.get(0);
|
||||
indices_buffer_id = int_buffer.get(1);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer_id);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer_id);
|
||||
|
||||
final FloatBuffer vertices = BufferUtils.createFloatBuffer(2 * 4);
|
||||
vertices
|
||||
.put(-50).put(-50)
|
||||
.put(50).put(-50)
|
||||
.put(-50).put(50)
|
||||
.put(50).put(50);
|
||||
vertices.rewind();
|
||||
|
||||
final IntBuffer indices = BufferUtils.createIntBuffer(4);
|
||||
indices.put(0).put(1).put(2).put(3);
|
||||
indices.rewind();
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, vertices, GL_STATIC_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices, GL_STATIC_DRAW);
|
||||
}
|
||||
|
||||
/** Test entry point */
|
||||
public static void main(String[] args) {
|
||||
System.out.println("Change between fullscreen and windowed mode, by pressing F and W respectively");
|
||||
System.out.println("Move quad using arrowkeys, and change rotation using +/-");
|
||||
FullScreenWindowedTest fswTest = new FullScreenWindowedTest();
|
||||
fswTest.execute();
|
||||
System.exit(0);
|
||||
}
|
||||
}
|
||||
580
src/java/org/lwjgl/test/opengles/Gears.java
Normal file
580
src/java/org/lwjgl/test/opengles/Gears.java
Normal file
|
|
@ -0,0 +1,580 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2008 LWJGL Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'LWJGL' nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* 3-D gear wheels. Originally by Brian Paul
|
||||
*/
|
||||
package org.lwjgl.test.opengles;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.LWJGLException;
|
||||
import org.lwjgl.Sys;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.DisplayMode;
|
||||
import org.lwjgl.opengles.*;
|
||||
import org.lwjgl.test.opengles.util.Geometry;
|
||||
import org.lwjgl.test.opengles.util.ImmediateModeBuffer;
|
||||
import org.lwjgl.test.opengles.util.Shader;
|
||||
import org.lwjgl.test.opengles.util.ShaderProgram;
|
||||
import org.lwjgl.util.vector.Matrix4f;
|
||||
import org.lwjgl.util.vector.Vector3f;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
import static org.lwjgl.test.opengles.util.GLLight.*;
|
||||
import static org.lwjgl.test.opengles.util.GLMatrix.*;
|
||||
import static org.lwjgl.test.opengles.util.Geometry.*;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is the OpenGL "standard" Gears demo, originally by Brian Paul
|
||||
* </p>
|
||||
*
|
||||
* @author Brian Matzon <brian@matzon.dk>
|
||||
* @version $Revision: 3276 $
|
||||
* $Id: Gears.java 3276 2010-02-21 21:18:17Z matzon $
|
||||
*/
|
||||
public class Gears {
|
||||
|
||||
private boolean run = true;
|
||||
|
||||
private float view_rotx = 20.0f;
|
||||
|
||||
private float view_roty = 30.0f;
|
||||
|
||||
private float view_rotz = 0.0f;
|
||||
|
||||
private Gear gear1;
|
||||
|
||||
private Gear gear2;
|
||||
|
||||
private Gear gear3;
|
||||
|
||||
private float angle = 0.0f;
|
||||
|
||||
private Shader vsh;
|
||||
private Shader fsh;
|
||||
|
||||
private ShaderProgram program;
|
||||
|
||||
private int LIGHT_POS;
|
||||
|
||||
private int MVP;
|
||||
private int NM;
|
||||
|
||||
private int GEAR_COLOR;
|
||||
|
||||
private int vPosition;
|
||||
private int vNormal;
|
||||
|
||||
private final Matrix4f p = new Matrix4f();
|
||||
private final Matrix4f mv = new Matrix4f();
|
||||
private final Matrix4f mvp = new Matrix4f();
|
||||
|
||||
private final FloatBuffer m4fBuffer = BufferUtils.createFloatBuffer(4 * 4);
|
||||
private final FloatBuffer m3fBuffer = BufferUtils.createFloatBuffer(3 * 3);
|
||||
|
||||
public static void main(String[] args) {
|
||||
new Gears().execute();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void execute() {
|
||||
try {
|
||||
init();
|
||||
} catch (LWJGLException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("Failed to initialize Gears.");
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("\nGL RENDERER: " + glGetString(GL_RENDERER));
|
||||
System.out.println("GL VENDOR: " + glGetString(GL_VENDOR));
|
||||
System.out.println("GL VERSION: " + glGetString(GL_VERSION));
|
||||
System.out.println("GL_SHADING_LANGUAGE_VERSION: " + glGetString(GL_SHADING_LANGUAGE_VERSION));
|
||||
System.out.println("GL_EXTENSIONS = " + glGetString(GL_EXTENSIONS));
|
||||
|
||||
ContextCapabilities caps = GLContext.getCapabilities();
|
||||
|
||||
System.out.println();
|
||||
|
||||
// Check extension support
|
||||
Field[] field = ContextCapabilities.class.getFields();
|
||||
for ( Field f : field ) {
|
||||
if ( f.getName().startsWith("GL_") ) {
|
||||
try {
|
||||
System.out.println(f.getName() + " - " + f.getBoolean(caps));
|
||||
} catch (IllegalAccessException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
System.out.println();
|
||||
|
||||
// Check for extensions that LWJGL does not support
|
||||
final String extensions = glGetString(GL_EXTENSIONS);
|
||||
|
||||
final StringTokenizer tokenizer = new StringTokenizer(extensions);
|
||||
while ( tokenizer.hasMoreTokens() ) {
|
||||
final String ext = tokenizer.nextToken();
|
||||
try {
|
||||
if ( !caps.getClass().getField(ext).getBoolean(caps) )
|
||||
System.out.println("-- Extension exposed but functions are missing: " + ext);
|
||||
} catch (NoSuchFieldException e) {
|
||||
System.out.println("-- No LWJGL support for extension: " + ext);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
loop();
|
||||
|
||||
destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void destroy() {
|
||||
program.destroy();
|
||||
|
||||
fsh.destroy();
|
||||
vsh.destroy();
|
||||
|
||||
gear3.destroy();
|
||||
gear2.destroy();
|
||||
gear1.destroy();
|
||||
|
||||
Display.destroy();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void loop() {
|
||||
long lastFrameTime = Sys.getTime();
|
||||
long startTime = System.currentTimeMillis() + 5000;
|
||||
long fps = 0;
|
||||
|
||||
while ( run ) {
|
||||
if ( !Display.isVisible() )
|
||||
Thread.yield();
|
||||
else {
|
||||
// This is the current frame time.
|
||||
long frameStart = Sys.getTime();
|
||||
|
||||
// How many seconds passed since last frame.
|
||||
final float frameTime = (float)((frameStart - lastFrameTime) / (double)Sys.getTimerResolution());
|
||||
lastFrameTime = frameStart;
|
||||
|
||||
angle += frameTime * 120.0f;
|
||||
|
||||
handleInput();
|
||||
|
||||
//glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_COVERAGE_BUFFER_BIT_NV);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glRotatef(view_rotx, 1.0f, 0.0f, 0.0f);
|
||||
glRotatef(view_roty, 0.0f, 1.0f, 0.0f);
|
||||
glRotatef(view_rotz, 0.0f, 0.0f, 1.0f);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.0f, -2.0f, 0.0f);
|
||||
glRotatef(angle, 0.0f, 0.0f, 1.0f);
|
||||
gear1.render();
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(3.1f, -2.0f, 0.0f);
|
||||
glRotatef(-2.0f * angle - 9.0f, 0.0f, 0.0f, 1.0f);
|
||||
gear2.render();
|
||||
glPopMatrix();
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(-3.1f, 4.2f, 0.0f);
|
||||
glRotatef(-2.0f * angle - 25.0f, 0.0f, 0.0f, 1.0f);
|
||||
gear3.render();
|
||||
glPopMatrix();
|
||||
|
||||
glPopMatrix();
|
||||
|
||||
try {
|
||||
Display.update();
|
||||
//Display.sync(60);
|
||||
} catch (PowerManagementEventException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
if ( startTime > System.currentTimeMillis() ) {
|
||||
fps++;
|
||||
} else {
|
||||
long timeUsed = 5000 + (startTime - System.currentTimeMillis());
|
||||
startTime = System.currentTimeMillis() + 5000;
|
||||
System.out.println(fps + " frames in " + (timeUsed / 1000f) + " seconds = " + (fps / (timeUsed / 1000f)));
|
||||
fps = 0;
|
||||
}
|
||||
|
||||
if ( Display.isCloseRequested() )
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void handleInput() {
|
||||
if ( Keyboard.getNumKeyboardEvents() != 0 ) {
|
||||
while ( Keyboard.next() ) {
|
||||
if ( Keyboard.getEventKeyState() )
|
||||
continue;
|
||||
|
||||
final int key = Keyboard.getEventKey();
|
||||
switch ( key ) {
|
||||
case Keyboard.KEY_ESCAPE:
|
||||
run = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
while ( Mouse.next() ) ;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
*/
|
||||
private void init() throws LWJGLException {
|
||||
final int WIDTH = 640;
|
||||
final int HEIGHT = 480;
|
||||
|
||||
Display.setLocation((Display.getDisplayMode().getWidth() - WIDTH) / 2,
|
||||
(Display.getDisplayMode().getHeight() - HEIGHT) / 2);
|
||||
try {
|
||||
Display.setDisplayMode(new DisplayMode(WIDTH, HEIGHT));
|
||||
} catch (PowerManagementEventException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
Display.setTitle("Gears");
|
||||
Display.create(new PixelFormat());
|
||||
|
||||
//glCoverageMaskNV(true);
|
||||
|
||||
// setup ogl
|
||||
glViewport(0, 0, WIDTH, HEIGHT);
|
||||
glFrontFace(GL_CCW);
|
||||
glCullFace(GL_BACK);
|
||||
glEnable(GL_CULL_FACE);
|
||||
glEnable(GL_DEPTH_TEST);
|
||||
|
||||
final Vector3f lp = new Vector3f(5.0f, 5.0f, 10.0f);
|
||||
lp.normalise();
|
||||
glLight(GL_LIGHT0, GL_POSITION, lp.getX(), lp.getY(), lp.getZ(), 0.0f);
|
||||
|
||||
/* make the gears */
|
||||
gear1 = new Gear(gear(1.0f, 4.0f, 1.0f, 20, 0.7f), new float[] { 0.8f, 0.1f, 0.0f, 1.0f });
|
||||
gear2 = new Gear(gear(0.5f, 2.0f, 2.0f, 10, 0.7f), new float[] { 0.0f, 0.8f, 0.2f, 1.0f });
|
||||
gear3 = new Gear(gear(1.3f, 2.0f, 0.5f, 10, 0.7f), new float[] { 0.2f, 0.2f, 1.0f, 1.0f });
|
||||
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
|
||||
final float h = (float)300 / (float)300;
|
||||
glFrustum(-1.0f, 1.0f, -h, h, 5.0f, 60.0f);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glTranslatef(0.0f, 0.0f, -40.0f);
|
||||
|
||||
vsh = new Shader(GL_VERTEX_SHADER, "uniform highp vec4 LIGHT_POS;\n" +
|
||||
"uniform highp mat4 MODEL_VIEW_PROJECTION_MATRIX;\n" +
|
||||
"uniform mediump mat3 NORMAL_MATRIX;\n" +
|
||||
"uniform lowp vec3 GEAR_COLOR;\n" +
|
||||
"attribute highp vec3 vPosition;\n" +
|
||||
"attribute mediump vec3 vNormal;\n" +
|
||||
"varying lowp vec3 color;\n" +
|
||||
"void main(void) {\n" +
|
||||
"\tgl_Position = MODEL_VIEW_PROJECTION_MATRIX * vec4(vPosition, 1.0);\n" +
|
||||
"\tvec3 normal = NORMAL_MATRIX * vNormal;\n" +
|
||||
"\tcolor = max(dot(normal, vec3(LIGHT_POS)), 0.0) * GEAR_COLOR + vec3(0.05);\n" +
|
||||
"}");
|
||||
|
||||
fsh = new Shader(GL_FRAGMENT_SHADER, "varying lowp vec3 color;\n" +
|
||||
"void main(void) {\n" +
|
||||
"\tgl_FragColor = vec4(color, 1.0);\n" +
|
||||
"}");
|
||||
|
||||
program = new ShaderProgram(vsh, fsh);
|
||||
program.enable();
|
||||
|
||||
LIGHT_POS = program.getUniformLocation("LIGHT_POS");
|
||||
|
||||
MVP = program.getUniformLocation("MODEL_VIEW_PROJECTION_MATRIX");
|
||||
NM = program.getUniformLocation("NORMAL_MATRIX");
|
||||
|
||||
GEAR_COLOR = program.getUniformLocation("GEAR_COLOR");
|
||||
|
||||
vPosition = program.getAttributeLocation("vPosition");
|
||||
vNormal = program.getAttributeLocation("vNormal");
|
||||
|
||||
glEnableVertexAttribArray(vNormal);
|
||||
glEnableVertexAttribArray(vPosition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Draw a gear wheel. You'll probably want to call this function when
|
||||
* building a display list since we do a lot of trig here.
|
||||
*
|
||||
* @param inner_radius radius of hole at center
|
||||
* @param outer_radius radius at center of teeth
|
||||
* @param width width of gear
|
||||
* @param teeth number of teeth
|
||||
* @param tooth_depth depth of tooth
|
||||
*/
|
||||
private static Geometry gear(float inner_radius, float outer_radius, float width, int teeth, float tooth_depth) {
|
||||
int i;
|
||||
float r0, r1, r2;
|
||||
float angle, da;
|
||||
float u, v, len;
|
||||
|
||||
r0 = inner_radius;
|
||||
r1 = outer_radius - tooth_depth / 2.0f;
|
||||
r2 = outer_radius + tooth_depth / 2.0f;
|
||||
|
||||
da = 2.0f * (float)Math.PI / teeth / 4.0f;
|
||||
|
||||
final Geometry gear = new Geometry();
|
||||
final ImmediateModeBuffer imb = new ImmediateModeBuffer(1024);
|
||||
int lastDrawIndex = 0;
|
||||
|
||||
//glShadeModel(GL_FLAT);
|
||||
|
||||
// draw front face
|
||||
lastDrawIndex += gear.addDrawCommand(GL_TRIANGLE_STRIP, lastDrawIndex, teeth * 4 + 2);
|
||||
for ( i = 0; i <= teeth; i++ ) {
|
||||
angle = i * 2.0f * (float)Math.PI / teeth;
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5f);
|
||||
|
||||
if ( i < teeth ) {
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r1 * cos(angle + 3.0f * da), r1 * sin(angle + 3.0f * da), width * 0.5f);
|
||||
}
|
||||
}
|
||||
|
||||
// draw front sides of teeth
|
||||
for ( i = 0; i < teeth; i++ ) {
|
||||
lastDrawIndex += gear.addDrawCommand(GL_TRIANGLE_STRIP, lastDrawIndex, 4);
|
||||
|
||||
angle = i * 2.0f * (float)Math.PI / teeth;
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r1 * cos(angle + 3.0f * da), r1 * sin(angle + 3.0f * da), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r2 * cos(angle + 2.0f * da), r2 * sin(angle + 2.0f * da), width * 0.5f);
|
||||
}
|
||||
|
||||
// draw back face
|
||||
lastDrawIndex += gear.addDrawCommand(GL_TRIANGLE_STRIP, lastDrawIndex, (teeth + 1) * 4);
|
||||
for ( i = 0; i <= teeth; i++ ) {
|
||||
angle = i * 2.0f * (float)Math.PI / teeth;
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5f);
|
||||
}
|
||||
|
||||
// draw back sides of teeth
|
||||
for ( i = 0; i < teeth; i++ ) {
|
||||
lastDrawIndex += gear.addDrawCommand(GL_TRIANGLE_STRIP, lastDrawIndex, 4);
|
||||
|
||||
angle = i * 2.0f * (float)Math.PI / teeth;
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5f);
|
||||
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5f);
|
||||
}
|
||||
|
||||
// draw outward faces of teeth
|
||||
// OpenGL ES 2.0 note: This needs to be converted to a triangle
|
||||
// list with face normals to get the flat look of the original.
|
||||
lastDrawIndex += gear.addDrawCommand(GL_TRIANGLE_STRIP, lastDrawIndex, teeth * 8 + 2);
|
||||
for ( i = 0; i < teeth; i++ ) {
|
||||
angle = i * 2.0f * (float)Math.PI / teeth;
|
||||
|
||||
imb.glNormal3f(cos(angle), sin(angle), 0.0f);
|
||||
imb.glVertex3f(r1 * cos(angle), r1 * sin(angle), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(cos(angle), sin(angle), 0.0f);
|
||||
imb.glVertex3f(r1 * cos(angle), r1 * sin(angle), -width * 0.5f);
|
||||
|
||||
u = r2 * cos(angle + da) - r1 * cos(angle);
|
||||
v = r2 * sin(angle + da) - r1 * sin(angle);
|
||||
len = (float)Math.sqrt(u * u + v * v);
|
||||
u /= len;
|
||||
v /= len;
|
||||
|
||||
imb.glNormal3f(v, -u, 0.0f);
|
||||
imb.glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(v, -u, 0.0f);
|
||||
imb.glVertex3f(r2 * cos(angle + da), r2 * sin(angle + da), -width * 0.5f);
|
||||
|
||||
imb.glNormal3f(cos(angle), sin(angle), 0.0f);
|
||||
imb.glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(cos(angle), sin(angle), 0.0f);
|
||||
imb.glVertex3f(r2 * cos(angle + 2 * da), r2 * sin(angle + 2 * da), -width * 0.5f);
|
||||
|
||||
u = r1 * cos(angle + 3 * da) - r2 * cos(angle + 2 * da);
|
||||
v = r1 * sin(angle + 3 * da) - r2 * sin(angle + 2 * da);
|
||||
|
||||
imb.glNormal3f(v, -u, 0.0f);
|
||||
imb.glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(v, -u, 0.0f);
|
||||
imb.glVertex3f(r1 * cos(angle + 3 * da), r1 * sin(angle + 3 * da), -width * 0.5f);
|
||||
}
|
||||
imb.glNormal3f(cos(0), sin(0), 0.0f);
|
||||
imb.glVertex3f(r1 * cos(0), r1 * sin(0), width * 0.5f);
|
||||
|
||||
imb.glNormal3f(cos(0), sin(0), 0.0f);
|
||||
imb.glVertex3f(r1 * cos(0), r1 * sin(0), -width * 0.5f);
|
||||
|
||||
//glShadeModel(GL_SMOOTH);
|
||||
|
||||
// draw inside radius cylinder
|
||||
lastDrawIndex += gear.addDrawCommand(GL_TRIANGLE_STRIP, lastDrawIndex, (teeth + 1) * 2);
|
||||
for ( i = 0; i <= teeth; i++ ) {
|
||||
angle = i * 2.0f * (float)Math.PI / teeth;
|
||||
|
||||
imb.glNormal3f(-cos(angle), -sin(angle), 0.0f);
|
||||
imb.glVertex3f(r0 * cos(angle), r0 * sin(angle), -width * 0.5f);
|
||||
|
||||
imb.glNormal3f(-cos(angle), -sin(angle), 0.0f);
|
||||
imb.glVertex3f(r0 * cos(angle), r0 * sin(angle), width * 0.5f);
|
||||
}
|
||||
|
||||
gear.update(imb.getBuffer());
|
||||
return gear;
|
||||
}
|
||||
|
||||
private class Gear {
|
||||
|
||||
private final Geometry geom;
|
||||
|
||||
private final float[] color;
|
||||
|
||||
Gear(final Geometry geom, final float[] color) {
|
||||
this.geom = geom;
|
||||
this.color = color;
|
||||
}
|
||||
|
||||
void render() {
|
||||
// Set gear color
|
||||
glUniform3f(GEAR_COLOR, color[0], color[1], color[2]);
|
||||
|
||||
// Set Light position
|
||||
setUniform4f(LIGHT_POS, GL_LIGHT0, GL_POSITION);
|
||||
|
||||
// Get Projection and Modelview matrices
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glGetMatrix(p);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glGetMatrix(mv);
|
||||
|
||||
// Set MVP uniform
|
||||
Matrix4f.mul(p, mv, mvp);
|
||||
mvp.store(m4fBuffer);
|
||||
m4fBuffer.flip();
|
||||
glUniformMatrix4(MVP, false, m4fBuffer);
|
||||
|
||||
// Set normal matrix (upper-left 3x3 of the inverse transpose MV matrix)
|
||||
mv.invert();
|
||||
mv.transpose();
|
||||
mv.store3f(m3fBuffer);
|
||||
m3fBuffer.flip();
|
||||
glUniformMatrix3(NM, false, m3fBuffer);
|
||||
|
||||
geom.bind();
|
||||
|
||||
final int stride = (3 + 3) * 4;
|
||||
glVertexAttribPointer(vNormal, 3, GL_FLOAT, false, stride, 0);
|
||||
glVertexAttribPointer(vPosition, 3, GL_FLOAT, false, stride, 3 * 4);
|
||||
|
||||
geom.draw();
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
geom.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
251
src/java/org/lwjgl/test/opengles/MappedIndexedVBOTest.java
Normal file
251
src/java/org/lwjgl/test/opengles/MappedIndexedVBOTest.java
Normal file
|
|
@ -0,0 +1,251 @@
|
|||
/*
|
||||
* Copyright (c) 2002-2008 LWJGL Project
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of 'LWJGL' nor the names of
|
||||
* its contributors may be used to endorse or promote products derived
|
||||
* from this software without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
|
||||
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
|
||||
* CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* $Id: VBOIndexTest.java 2983 2008-04-07 18:36:09Z matzon $
|
||||
*
|
||||
* Simple java test program.
|
||||
*
|
||||
* @author elias_naur <elias_naur@users.sourceforge.net>
|
||||
* @version $Revision: 2983 $
|
||||
*/
|
||||
|
||||
package org.lwjgl.test.opengles;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.Sys;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
import org.lwjgl.input.Mouse;
|
||||
import org.lwjgl.opengl.Display;
|
||||
import org.lwjgl.opengl.DisplayMode;
|
||||
import org.lwjgl.opengles.GLContext;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.FloatBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
import static org.lwjgl.opengles.OESMapbuffer.*;
|
||||
import static org.lwjgl.test.opengles.util.GLMatrix.*;
|
||||
|
||||
public final class MappedIndexedVBOTest {
|
||||
|
||||
static {
|
||||
try {
|
||||
//find first display mode that allows us 640*480*16
|
||||
int mode = -1;
|
||||
DisplayMode[] modes = Display.getAvailableDisplayModes();
|
||||
for ( int i = 0; i < modes.length; i++ ) {
|
||||
if ( modes[i].getWidth() == 640
|
||||
&& modes[i].getHeight() == 480
|
||||
&& modes[i].getBitsPerPixel() >= 16 ) {
|
||||
mode = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if ( mode != -1 ) {
|
||||
//select above found displaymode
|
||||
System.out.println("Setting display mode to " + modes[mode]);
|
||||
Display.setDisplayMode(modes[mode]);
|
||||
System.out.println("Created display.");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failed to create display due to " + e);
|
||||
}
|
||||
}
|
||||
|
||||
static {
|
||||
try {
|
||||
Display.createES();
|
||||
System.out.println("Created OpenGL.");
|
||||
|
||||
if ( !GLContext.getCapabilities().GL_OES_mapbuffer ) {
|
||||
System.out.println("GL_OES_mapbuffer is not supported, quitting!");
|
||||
System.exit(0);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failed to create OpenGL due to " + e);
|
||||
System.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
/** Is the game finished? */
|
||||
private static boolean finished;
|
||||
|
||||
/** A rotating square! */
|
||||
private static float angle;
|
||||
private static int buffer_id;
|
||||
private static int indices_buffer_id;
|
||||
private static FloatBuffer vertices;
|
||||
private static ByteBuffer mapped_buffer;
|
||||
private static FloatBuffer mapped_float_buffer;
|
||||
private static IntBuffer indices;
|
||||
private static ByteBuffer mapped_indices_buffer;
|
||||
private static IntBuffer mapped_indices_int_buffer;
|
||||
|
||||
private static QuadRenderer renderer;
|
||||
|
||||
public static void main(String[] arguments) {
|
||||
try {
|
||||
init();
|
||||
while ( !finished ) {
|
||||
Display.update();
|
||||
Display.sync(30);
|
||||
|
||||
if ( !Display.isVisible() )
|
||||
Thread.sleep(200);
|
||||
else if ( Display.isCloseRequested() )
|
||||
System.exit(0);
|
||||
|
||||
mainLoop();
|
||||
render();
|
||||
}
|
||||
} catch (Throwable t) {
|
||||
t.printStackTrace();
|
||||
} finally {
|
||||
cleanup();
|
||||
}
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
/** All calculations are done in here */
|
||||
private static void mainLoop() {
|
||||
angle += 1f;
|
||||
if ( angle > 360.0f )
|
||||
angle = 0.0f;
|
||||
|
||||
if ( Mouse.getDX() != 0 || Mouse.getDY() != 0 || Mouse.getDWheel() != 0 )
|
||||
System.out.println("Mouse moved " + Mouse.getDX() + " " + Mouse.getDY() + " " + Mouse.getDWheel());
|
||||
for ( int i = 0; i < Mouse.getButtonCount(); i++ )
|
||||
if ( Mouse.isButtonDown(i) )
|
||||
System.out.println("Button " + i + " down");
|
||||
if ( Keyboard.isKeyDown(Keyboard.KEY_ESCAPE) )
|
||||
finished = true;
|
||||
for ( int i = 0; i < Keyboard.getNumKeyboardEvents(); i++ ) {
|
||||
Keyboard.next();
|
||||
if ( Keyboard.getEventKey() == Keyboard.KEY_ESCAPE && Keyboard.getEventKeyState() )
|
||||
finished = true;
|
||||
if ( Keyboard.getEventKey() == Keyboard.KEY_T && Keyboard.getEventKeyState() )
|
||||
System.out.println("Current time: " + Sys.getTime());
|
||||
}
|
||||
}
|
||||
|
||||
/** All rendering is done in here */
|
||||
private static void render() {
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
glPushMatrix();
|
||||
glTranslatef(Display.getDisplayMode().getWidth() / 2, Display.getDisplayMode().getHeight() / 2, 0.0f);
|
||||
glRotatef(angle, 0, 0, 1.0f);
|
||||
|
||||
renderer.setMVPUniform();
|
||||
|
||||
ByteBuffer new_mapped_buffer = glMapBufferOES(GL_ARRAY_BUFFER, GL_WRITE_ONLY_OES, mapped_buffer);
|
||||
if ( new_mapped_buffer != mapped_buffer ) {
|
||||
mapped_buffer = new_mapped_buffer;
|
||||
mapped_float_buffer = new_mapped_buffer.asFloatBuffer();
|
||||
}
|
||||
|
||||
new_mapped_buffer = glMapBufferOES(GL_ELEMENT_ARRAY_BUFFER, GL_WRITE_ONLY_OES, mapped_indices_buffer);
|
||||
if ( new_mapped_buffer != mapped_indices_buffer ) {
|
||||
mapped_indices_buffer = new_mapped_buffer;
|
||||
mapped_indices_int_buffer = new_mapped_buffer.asIntBuffer();
|
||||
}
|
||||
|
||||
mapped_float_buffer.rewind();
|
||||
vertices.rewind();
|
||||
mapped_float_buffer.put(vertices);
|
||||
|
||||
mapped_indices_int_buffer.rewind();
|
||||
indices.rewind();
|
||||
mapped_indices_int_buffer.put(indices);
|
||||
if ( glUnmapBufferOES(GL_ARRAY_BUFFER) &&
|
||||
glUnmapBufferOES(GL_ELEMENT_ARRAY_BUFFER) ) {
|
||||
glDrawElements(GL_TRIANGLE_STRIP, 4, GL_UNSIGNED_INT, 0);
|
||||
}
|
||||
|
||||
glPopMatrix();
|
||||
}
|
||||
|
||||
/** Initialize */
|
||||
private static void init() throws Exception {
|
||||
System.out.println("Timer resolution: " + Sys.getTimerResolution());
|
||||
|
||||
// Go into orthographic projection mode.
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glLoadIdentity();
|
||||
glOrtho(0, Display.getDisplayMode().getWidth(), 0, Display.getDisplayMode().getHeight(), -1.0f, 1.0f);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glLoadIdentity();
|
||||
glViewport(0, 0, Display.getDisplayMode().getWidth(), Display.getDisplayMode().getHeight());
|
||||
|
||||
final IntBuffer int_buffer = BufferUtils.createIntBuffer(2);
|
||||
glGenBuffers(int_buffer);
|
||||
buffer_id = int_buffer.get(0);
|
||||
indices_buffer_id = int_buffer.get(1);
|
||||
|
||||
glBindBuffer(GL_ARRAY_BUFFER, buffer_id);
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indices_buffer_id);
|
||||
|
||||
vertices = BufferUtils.createFloatBuffer(2 * 4);
|
||||
vertices
|
||||
.put(-50).put(-50)
|
||||
.put(50).put(-50)
|
||||
.put(-50).put(50)
|
||||
.put(50).put(50);
|
||||
vertices.rewind();
|
||||
|
||||
indices = BufferUtils.createIntBuffer(4);
|
||||
indices.put(0).put(1).put(2).put(3);
|
||||
indices.rewind();
|
||||
|
||||
glBufferData(GL_ARRAY_BUFFER, 2 * 4 * 4, GL_STREAM_DRAW);
|
||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, 4 * 4, GL_STREAM_DRAW);
|
||||
|
||||
renderer = new QuadRenderer();
|
||||
}
|
||||
|
||||
/** Cleanup */
|
||||
private static void cleanup() {
|
||||
renderer.cleanup();
|
||||
|
||||
IntBuffer int_buffer = BufferUtils.createIntBuffer(2);
|
||||
int_buffer.put(0, buffer_id);
|
||||
int_buffer.put(1, indices_buffer_id);
|
||||
|
||||
glDeleteBuffers(int_buffer);
|
||||
|
||||
Display.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
70
src/java/org/lwjgl/test/opengles/QuadRenderer.java
Normal file
70
src/java/org/lwjgl/test/opengles/QuadRenderer.java
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
package org.lwjgl.test.opengles;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
import org.lwjgl.test.opengles.util.Shader;
|
||||
import org.lwjgl.test.opengles.util.ShaderProgram;
|
||||
import org.lwjgl.util.vector.Matrix4f;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
import static org.lwjgl.test.opengles.util.GLMatrix.*;
|
||||
|
||||
final class QuadRenderer {
|
||||
|
||||
private final Shader vsh;
|
||||
private final Shader fsh;
|
||||
private final ShaderProgram program;
|
||||
|
||||
private final int uniMVP;
|
||||
|
||||
private final Matrix4f p = new Matrix4f();
|
||||
private final Matrix4f mv = new Matrix4f();
|
||||
private final Matrix4f mvp = new Matrix4f();
|
||||
|
||||
private final FloatBuffer m4fBuffer = BufferUtils.createFloatBuffer(4 * 4);
|
||||
|
||||
QuadRenderer() {
|
||||
vsh = new Shader(GL_VERTEX_SHADER, "uniform highp mat4 MODEL_VIEW_PROJECTION_MATRIX;\n" +
|
||||
"attribute highp vec2 vPosition;\n" +
|
||||
"void main(void) {\n" +
|
||||
"\tgl_Position = MODEL_VIEW_PROJECTION_MATRIX * vec4(vPosition, 0.0, 1.0);\n" +
|
||||
"}");
|
||||
|
||||
fsh = new Shader(GL_FRAGMENT_SHADER, "void main(void) {\n" +
|
||||
"\tgl_FragColor = vec4(1.0);\n" +
|
||||
"}");
|
||||
|
||||
program = new ShaderProgram(vsh, fsh);
|
||||
program.enable();
|
||||
|
||||
uniMVP = program.getUniformLocation("MODEL_VIEW_PROJECTION_MATRIX");
|
||||
|
||||
final int vPosition = program.getAttributeLocation("vPosition");
|
||||
glVertexAttribPointer(vPosition, 2, GL_FLOAT, false, 0, 0);
|
||||
glEnableVertexAttribArray(vPosition);
|
||||
}
|
||||
|
||||
void setMVPUniform() {
|
||||
// Get Projection and Modelview matrices
|
||||
glMatrixMode(GL_PROJECTION);
|
||||
glGetMatrix(p);
|
||||
|
||||
glMatrixMode(GL_MODELVIEW);
|
||||
glGetMatrix(mv);
|
||||
|
||||
// Set MVP uniform
|
||||
Matrix4f.mul(p, mv, mvp);
|
||||
mvp.store(m4fBuffer);
|
||||
m4fBuffer.flip();
|
||||
glUniformMatrix4(uniMVP, false, m4fBuffer);
|
||||
}
|
||||
|
||||
void cleanup() {
|
||||
program.destroy();
|
||||
|
||||
fsh.destroy();
|
||||
vsh.destroy();
|
||||
}
|
||||
|
||||
}
|
||||
99
src/java/org/lwjgl/test/opengles/util/BufferObject.java
Normal file
99
src/java/org/lwjgl/test/opengles/util/BufferObject.java
Normal file
|
|
@ -0,0 +1,99 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import java.nio.*;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
import static org.lwjgl.opengles.OESMapbuffer.*;
|
||||
|
||||
abstract class BufferObject implements GLObject {
|
||||
|
||||
protected final int ID;
|
||||
|
||||
protected int target;
|
||||
protected int usage;
|
||||
|
||||
/** The BufferObject data size in bytes. */
|
||||
private int size;
|
||||
|
||||
protected BufferObject(final int type, final int usage) {
|
||||
this.ID = glGenBuffers();
|
||||
this.target = type;
|
||||
this.usage = usage;
|
||||
}
|
||||
|
||||
protected BufferObject(final int type, final int usage, final Buffer buffer) {
|
||||
this(type, usage);
|
||||
setData(buffer);
|
||||
}
|
||||
|
||||
protected BufferObject(final int type, final int usage, final int dataSize) {
|
||||
this(type, usage);
|
||||
setData(dataSize);
|
||||
}
|
||||
|
||||
public final int getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
glDeleteBuffers(ID);
|
||||
}
|
||||
|
||||
public final int getTarget() {
|
||||
return target;
|
||||
}
|
||||
|
||||
public final int getUsage() {
|
||||
return usage;
|
||||
}
|
||||
|
||||
public final int getSize() {
|
||||
return size;
|
||||
}
|
||||
|
||||
public abstract void enable();
|
||||
|
||||
public abstract void disable();
|
||||
|
||||
public final void setData(final Buffer buffer) {
|
||||
enable();
|
||||
|
||||
if ( buffer instanceof ByteBuffer ) {
|
||||
glBufferData(target, (ByteBuffer)buffer, usage);
|
||||
size = buffer.remaining();
|
||||
} else if ( buffer instanceof ShortBuffer ) {
|
||||
glBufferData(target, (ShortBuffer)buffer, usage);
|
||||
size = buffer.remaining() << 1;
|
||||
} else if ( buffer instanceof IntBuffer ) {
|
||||
glBufferData(target, (IntBuffer)buffer, usage);
|
||||
size = buffer.remaining() << 2;
|
||||
} else if ( buffer instanceof FloatBuffer ) {
|
||||
glBufferData(target, (FloatBuffer)buffer, usage);
|
||||
size = buffer.remaining() << 2;
|
||||
}
|
||||
|
||||
disable();
|
||||
}
|
||||
|
||||
public final void setData(final int dataSize) {
|
||||
enable();
|
||||
|
||||
glBufferData(target, dataSize, usage);
|
||||
size = dataSize;
|
||||
|
||||
disable();
|
||||
}
|
||||
|
||||
public final ByteBuffer map(final int access, final ByteBuffer oldBuffer) {
|
||||
return glMapBufferOES(target, access, oldBuffer);
|
||||
}
|
||||
|
||||
public final ByteBuffer map(final int access, final int length, final ByteBuffer oldBuffer) {
|
||||
return glMapBufferOES(target, access, length, oldBuffer);
|
||||
}
|
||||
|
||||
public final boolean unmap() {
|
||||
return glUnmapBufferOES(target);
|
||||
}
|
||||
|
||||
}
|
||||
41
src/java/org/lwjgl/test/opengles/util/BufferObjectArray.java
Normal file
41
src/java/org/lwjgl/test/opengles/util/BufferObjectArray.java
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import java.nio.Buffer;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
|
||||
public final class BufferObjectArray extends BufferObject {
|
||||
|
||||
private static int boundBOArray;
|
||||
|
||||
public BufferObjectArray(final int usage) {
|
||||
super(GL_ARRAY_BUFFER, usage);
|
||||
}
|
||||
|
||||
public BufferObjectArray(final int usage, final Buffer buffer) {
|
||||
super(GL_ARRAY_BUFFER, usage, buffer);
|
||||
}
|
||||
|
||||
public BufferObjectArray(final int usage, final int dataSize) {
|
||||
super(GL_ARRAY_BUFFER, usage, dataSize);
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
if ( boundBOArray != ID ) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, ID);
|
||||
boundBOArray = ID;
|
||||
}
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
boArrayDisable();
|
||||
}
|
||||
|
||||
public static void boArrayDisable() {
|
||||
if ( boundBOArray != 0 ) {
|
||||
glBindBuffer(GL_ARRAY_BUFFER, 0);
|
||||
boundBOArray = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import java.nio.Buffer;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
|
||||
public final class BufferObjectElement extends BufferObject {
|
||||
|
||||
private static int boundBOElementArray;
|
||||
|
||||
public BufferObjectElement(final int usage) {
|
||||
super(GL_ELEMENT_ARRAY_BUFFER, usage);
|
||||
}
|
||||
|
||||
public BufferObjectElement(final int usage, final Buffer buffer) {
|
||||
super(GL_ELEMENT_ARRAY_BUFFER, usage, buffer);
|
||||
}
|
||||
|
||||
public BufferObjectElement(final int usage, final int dataSize) {
|
||||
super(GL_ELEMENT_ARRAY_BUFFER, usage, dataSize);
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
if ( boundBOElementArray != ID ) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, ID);
|
||||
boundBOElementArray = ID;
|
||||
}
|
||||
}
|
||||
|
||||
public void disable() {
|
||||
boElementArrayDisable();
|
||||
}
|
||||
|
||||
public static void boElementArrayDisable() {
|
||||
if ( boundBOElementArray != 0 ) {
|
||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
|
||||
boundBOElementArray = 0;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
165
src/java/org/lwjgl/test/opengles/util/GLLight.java
Normal file
165
src/java/org/lwjgl/test/opengles/util/GLLight.java
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
|
||||
/** Emulates the light state in fixed-function OpenGL. */
|
||||
public class GLLight {
|
||||
|
||||
public static final int GL_LIGHT0 = 0x4000;
|
||||
public static final int GL_LIGHT1 = 0x4001;
|
||||
public static final int GL_LIGHT2 = 0x4002;
|
||||
public static final int GL_LIGHT3 = 0x4003;
|
||||
public static final int GL_LIGHT4 = 0x4004;
|
||||
public static final int GL_LIGHT5 = 0x4005;
|
||||
public static final int GL_LIGHT6 = 0x4006;
|
||||
public static final int GL_LIGHT7 = 0x4007;
|
||||
|
||||
public static final int GL_AMBIENT = 0x1200;
|
||||
public static final int GL_DIFFUSE = 0x1201;
|
||||
public static final int GL_SPECULAR = 0x1202;
|
||||
public static final int GL_POSITION = 0x1203;
|
||||
public static final int GL_SPOT_DIRECTION = 0x1204;
|
||||
public static final int GL_SPOT_EXPONENT = 0x1205;
|
||||
public static final int GL_SPOT_CUTOFF = 0x1206;
|
||||
public static final int GL_CONSTANT_ATTENUATION = 0x1207;
|
||||
public static final int GL_LINEAR_ATTENUATION = 0x1208;
|
||||
public static final int GL_QUADRATIC_ATTENUATION = 0x1209;
|
||||
|
||||
private static final Light[] lights = new Light[8];
|
||||
|
||||
static {
|
||||
for ( int i = 0; i < lights.length; i++ )
|
||||
lights[i] = new Light();
|
||||
|
||||
System.arraycopy(new float[] { 1.0f, 1.0f, 1.0f, 1.0f }, 0, lights[0].diffuse, 0, 4);
|
||||
System.arraycopy(new float[] { 1.0f, 1.0f, 1.0f, 1.0f }, 0, lights[0].specular, 0, 4);
|
||||
}
|
||||
|
||||
private GLLight() {
|
||||
}
|
||||
|
||||
public static void glLight(final int light, final int pname, final float v) {
|
||||
if ( light < GL_LIGHT0 || GL_LIGHT7 < light )
|
||||
throw new IllegalArgumentException("Invalid light specified: " + light);
|
||||
|
||||
final Light l = lights[light - GL_LIGHT0];
|
||||
|
||||
switch ( pname ) {
|
||||
case GL_SPOT_EXPONENT:
|
||||
l.s = v;
|
||||
break;
|
||||
case GL_SPOT_CUTOFF:
|
||||
l.c = v;
|
||||
break;
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
l.k0 = v;
|
||||
break;
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
l.k1 = v;
|
||||
break;
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
l.k2 = v;
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid light parameter specified: " + pname);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glLight(final int light, final int pname,
|
||||
final float x, final float y, final float z) {
|
||||
if ( light < GL_LIGHT0 || GL_LIGHT7 < light )
|
||||
throw new IllegalArgumentException("Invalid light specified: " + light);
|
||||
|
||||
if ( pname != GL_SPOT_DIRECTION )
|
||||
throw new IllegalArgumentException("Invalid light parameter specified: " + pname);
|
||||
|
||||
final float[] param = lights[light - GL_LIGHT0].direction;
|
||||
|
||||
param[0] = x;
|
||||
param[1] = y;
|
||||
param[2] = z;
|
||||
}
|
||||
|
||||
private static float[] getParam4f(final int light, final int pname) {
|
||||
if ( light < GL_LIGHT0 || GL_LIGHT7 < light )
|
||||
throw new IllegalArgumentException("Invalid light specified: " + light);
|
||||
|
||||
final Light l = lights[light - GL_LIGHT0];
|
||||
switch ( pname ) {
|
||||
case GL_AMBIENT:
|
||||
return l.ambient;
|
||||
case GL_DIFFUSE:
|
||||
return l.diffuse;
|
||||
case GL_SPECULAR:
|
||||
return l.specular;
|
||||
case GL_POSITION:
|
||||
return l.position;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid light parameter specified: " + pname);
|
||||
}
|
||||
}
|
||||
|
||||
public static void glLight(final int light, final int pname,
|
||||
final float x, final float y, final float z, final float w) {
|
||||
final float[] param = getParam4f(light, pname);
|
||||
param[0] = x;
|
||||
param[1] = y;
|
||||
param[2] = z;
|
||||
param[3] = w;
|
||||
}
|
||||
|
||||
public static void setUniform1f(final int location, final int light, final int pname) {
|
||||
if ( light < GL_LIGHT0 || GL_LIGHT7 < light )
|
||||
throw new IllegalArgumentException("Invalid light specified: " + light);
|
||||
|
||||
final Light l = lights[light - GL_LIGHT0];
|
||||
|
||||
switch ( pname ) {
|
||||
case GL_SPOT_EXPONENT:
|
||||
glUniform1f(location, l.s);
|
||||
break;
|
||||
case GL_SPOT_CUTOFF:
|
||||
glUniform1f(location, l.c);
|
||||
break;
|
||||
case GL_CONSTANT_ATTENUATION:
|
||||
glUniform1f(location, l.k0);
|
||||
break;
|
||||
case GL_LINEAR_ATTENUATION:
|
||||
glUniform1f(location, l.k1);
|
||||
break;
|
||||
case GL_QUADRATIC_ATTENUATION:
|
||||
glUniform1f(location, l.k2);
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid light parameter specified: " + pname);
|
||||
}
|
||||
}
|
||||
|
||||
public static void setUniform3f(final int location, final int light, final int pname) {
|
||||
if ( pname != GL_SPOT_DIRECTION )
|
||||
throw new IllegalArgumentException("Invalid light parameter specified: " + pname);
|
||||
|
||||
final float[] param = lights[light - GL_LIGHT0].direction;
|
||||
glUniform3f(location, param[0], param[1], param[2]);
|
||||
}
|
||||
|
||||
public static void setUniform4f(final int location, final int light, final int pname) {
|
||||
final float[] param = getParam4f(light, pname);
|
||||
glUniform4f(location, param[0], param[1], param[2], param[3]);
|
||||
}
|
||||
|
||||
private static class Light {
|
||||
|
||||
float[] ambient = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
float[] diffuse = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
float[] specular = { 0.0f, 0.0f, 0.0f, 1.0f };
|
||||
|
||||
float[] position = { 0.0f, 0.0f, 1.0f, 0.0f };
|
||||
float[] direction = { 0.0f, 0.0f, -1.0f };
|
||||
|
||||
float s, c = 180.0f;
|
||||
float k0 = 1.0f, k1, k2;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
163
src/java/org/lwjgl/test/opengles/util/GLMatrix.java
Normal file
163
src/java/org/lwjgl/test/opengles/util/GLMatrix.java
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import org.lwjgl.util.vector.Matrix4f;
|
||||
import org.lwjgl.util.vector.Vector3f;
|
||||
|
||||
import java.util.Stack;
|
||||
|
||||
import static java.lang.Math.*;
|
||||
|
||||
/** Emulates the matrix stack in fixed-function OpenGL. */
|
||||
public final class GLMatrix {
|
||||
|
||||
public static final int GL_MODELVIEW = 0x1700;
|
||||
public static final int GL_PROJECTION = 0x1701;
|
||||
|
||||
private static final float PI = (float)Math.PI;
|
||||
|
||||
/** The model/view matrix stack. */
|
||||
private static final Stack<Matrix4f> mvMatrixStack = new Stack<Matrix4f>();
|
||||
|
||||
/** The projection matrix stack. */
|
||||
private static final Stack<Matrix4f> pMatrixStack = new Stack<Matrix4f>();
|
||||
|
||||
private static final Matrix4f m4f = new Matrix4f();
|
||||
private static final Vector3f v3f = new Vector3f();
|
||||
|
||||
private static int mode = GL_MODELVIEW;
|
||||
|
||||
static {
|
||||
mvMatrixStack.push(new Matrix4f());
|
||||
pMatrixStack.push(new Matrix4f());
|
||||
}
|
||||
|
||||
private GLMatrix() {
|
||||
}
|
||||
|
||||
private static Stack<Matrix4f> getCurrentStack() {
|
||||
switch ( mode ) {
|
||||
case GL_MODELVIEW:
|
||||
return mvMatrixStack;
|
||||
case GL_PROJECTION:
|
||||
return pMatrixStack;
|
||||
default:
|
||||
return null; // Cannot happen
|
||||
}
|
||||
}
|
||||
|
||||
private static Matrix4f getCurrentMatrix() {
|
||||
return getCurrentStack().peek();
|
||||
}
|
||||
|
||||
public static void glMatrixMode(final int mode) {
|
||||
if ( mode != GL_MODELVIEW && mode != GL_PROJECTION )
|
||||
throw new IllegalArgumentException("Invalid matrix mode specified: " + mode);
|
||||
|
||||
GLMatrix.mode = mode;
|
||||
}
|
||||
|
||||
public static void glPushMatrix() {
|
||||
final Stack<Matrix4f> stack = getCurrentStack();
|
||||
stack.push(new Matrix4f(stack.peek()));
|
||||
}
|
||||
|
||||
public static void glPopMatrix() {
|
||||
final Stack<Matrix4f> stack = getCurrentStack();
|
||||
|
||||
if ( stack.size() == 1 )
|
||||
throw new IllegalStateException("The last matrix in the stack cannot be popped.");
|
||||
|
||||
getCurrentStack().pop();
|
||||
}
|
||||
|
||||
public static void glLoadIdentity() {
|
||||
final Matrix4f m = getCurrentMatrix();
|
||||
m.setIdentity();
|
||||
}
|
||||
|
||||
public static void glLoadMatrix(final Matrix4f s) {
|
||||
getCurrentMatrix().load(s);
|
||||
}
|
||||
|
||||
public static void glMultMatrix(final Matrix4f m) {
|
||||
final Matrix4f c = getCurrentMatrix();
|
||||
Matrix4f.mul(c, m, c);
|
||||
}
|
||||
|
||||
public static void glTranslatef(final float x, final float y, final float z) {
|
||||
final Matrix4f m = getCurrentMatrix();
|
||||
v3f.set(x, y, z);
|
||||
m.translate(v3f);
|
||||
}
|
||||
|
||||
public static void glRotatef(final float angle, final float x, final float y, final float z) {
|
||||
final Matrix4f m = getCurrentMatrix();
|
||||
v3f.set(x, y, z);
|
||||
m.rotate((float)toRadians(angle), v3f);
|
||||
}
|
||||
|
||||
public static void glOrtho(final float l, final float r, final float b, final float t, final float n, final float f) {
|
||||
final Matrix4f m = m4f;
|
||||
m.setIdentity();
|
||||
|
||||
m.m00 = 2.0f / (r - l);
|
||||
m.m30 = -(r + l) / (r - l);
|
||||
|
||||
m.m11 = 2.0f / (t - b);
|
||||
m.m31 = -(t + b) / (t - b);
|
||||
|
||||
m.m22 = -2.0f / (f - n);
|
||||
m.m32 = -(f + n) / (f - n);
|
||||
|
||||
glMultMatrix(m);
|
||||
}
|
||||
|
||||
public static void glFrustum(final float l, final float r, final float b, final float t, final float n, final float f) {
|
||||
final Matrix4f m = m4f;
|
||||
m.setIdentity();
|
||||
|
||||
m.m00 = 2.0f * n / (r - l);
|
||||
m.m20 = (r + l) / (r - l);
|
||||
|
||||
m.m11 = 2.0f * n / (t - b);
|
||||
m.m21 = (t + b) / (t - b);
|
||||
|
||||
m.m22 = -(f + n) / (f - n);
|
||||
m.m32 = -(2.0f * f * n) / (f - n);
|
||||
|
||||
m.m23 = -1.0f;
|
||||
m.m33 = 0.0f;
|
||||
|
||||
glMultMatrix(m);
|
||||
}
|
||||
|
||||
public static void gluPerspective(final float fovy, final float aspect, final float zNear, final float zFar) {
|
||||
final float radians = fovy / 2.0f * PI / 180.0f;
|
||||
|
||||
final float deltaZ = zFar - zNear;
|
||||
final float sine = (float)sin(radians);
|
||||
|
||||
if ( (deltaZ == 0) || (sine == 0) || (aspect == 0) ) {
|
||||
return;
|
||||
}
|
||||
|
||||
final float cotangent = (float)cos(radians) / sine;
|
||||
|
||||
final Matrix4f m = m4f;
|
||||
m.setIdentity();
|
||||
|
||||
m.m00 = cotangent / aspect;
|
||||
m.m11 = cotangent;
|
||||
m.m22 = -(zFar + zNear) / deltaZ;
|
||||
m.m23 = -1.0f;
|
||||
m.m32 = -2 * zNear * zFar / deltaZ;
|
||||
m.m33 = 0.0f;
|
||||
|
||||
glMultMatrix(m);
|
||||
}
|
||||
|
||||
public static void glGetMatrix(final Matrix4f d) {
|
||||
d.load(getCurrentMatrix());
|
||||
}
|
||||
|
||||
}
|
||||
9
src/java/org/lwjgl/test/opengles/util/GLObject.java
Normal file
9
src/java/org/lwjgl/test/opengles/util/GLObject.java
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
public interface GLObject {
|
||||
|
||||
int getID();
|
||||
|
||||
void destroy();
|
||||
|
||||
}
|
||||
78
src/java/org/lwjgl/test/opengles/util/Geometry.java
Normal file
78
src/java/org/lwjgl/test/opengles/util/Geometry.java
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import org.lwjgl.test.opengles.util.BufferObjectArray;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
|
||||
public class Geometry {
|
||||
|
||||
protected BufferObjectArray bo;
|
||||
|
||||
protected final List<DrawCommand> drawCommands = new ArrayList<DrawCommand>(4);
|
||||
|
||||
public Geometry() {
|
||||
}
|
||||
|
||||
public Geometry(final FloatBuffer buffer) {
|
||||
update(buffer);
|
||||
}
|
||||
|
||||
public void update(final FloatBuffer buffer) {
|
||||
if ( bo != null )
|
||||
destroy();
|
||||
|
||||
bo = new BufferObjectArray(GL_STATIC_DRAW, buffer);
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
bo.enable();
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
for ( DrawCommand command : drawCommands )
|
||||
command.draw();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
bo.destroy();
|
||||
bo = null;
|
||||
|
||||
drawCommands.clear();
|
||||
}
|
||||
|
||||
public int addDrawCommand(final int mode, final int first, final int count) {
|
||||
drawCommands.add(new DrawCommand(mode, first, count));
|
||||
return count;
|
||||
}
|
||||
|
||||
public static float sin(final float r) {
|
||||
return (float)Math.sin(r);
|
||||
}
|
||||
|
||||
public static float cos(final float r) {
|
||||
return (float)Math.cos(r);
|
||||
}
|
||||
|
||||
protected static class DrawCommand {
|
||||
|
||||
private int mode;
|
||||
private int first;
|
||||
private int count;
|
||||
|
||||
private DrawCommand(final int mode, final int first, final int count) {
|
||||
this.mode = mode;
|
||||
this.first = first;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
void draw() {
|
||||
glDrawArrays(mode, first, count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,58 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
|
||||
/**
|
||||
* Utility class that emulates immediate mode vertex data submission.
|
||||
* Can be used to create VBO data.
|
||||
*/
|
||||
public final class ImmediateModeBuffer {
|
||||
|
||||
private FloatBuffer buffer;
|
||||
|
||||
public ImmediateModeBuffer(final int startSize) {
|
||||
this.buffer = BufferUtils.createFloatBuffer(startSize);
|
||||
}
|
||||
|
||||
private void checkSize(final int count) {
|
||||
while ( buffer.remaining() < count ) {
|
||||
final FloatBuffer newBuffer = BufferUtils.createFloatBuffer(buffer.capacity() << 1);
|
||||
buffer.flip();
|
||||
newBuffer.put(buffer);
|
||||
buffer = newBuffer;
|
||||
}
|
||||
}
|
||||
|
||||
public FloatBuffer getBuffer() {
|
||||
buffer.flip();
|
||||
return buffer;
|
||||
}
|
||||
|
||||
public void glVertex2f(final float x, final float y) {
|
||||
checkSize(2);
|
||||
buffer.put(x).put(y);
|
||||
}
|
||||
|
||||
public void glVertex3f(final float x, final float y, final float z) {
|
||||
checkSize(3);
|
||||
buffer.put(x).put(y).put(z);
|
||||
}
|
||||
|
||||
public void glVertex4f(final float x, final float y, final float z, final float w) {
|
||||
checkSize(4);
|
||||
buffer.put(x).put(y).put(z).put(w);
|
||||
}
|
||||
|
||||
public void glNormal3f(final float x, final float y, final float z) {
|
||||
checkSize(3);
|
||||
buffer.put(x).put(y).put(z);
|
||||
}
|
||||
|
||||
public void glTexCoord2f(final float s, final float t) {
|
||||
checkSize(2);
|
||||
buffer.put(s).put(t);
|
||||
}
|
||||
|
||||
}
|
||||
98
src/java/org/lwjgl/test/opengles/util/Shader.java
Normal file
98
src/java/org/lwjgl/test/opengles/util/Shader.java
Normal file
|
|
@ -0,0 +1,98 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import org.lwjgl.BufferUtils;
|
||||
|
||||
import java.io.BufferedInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
|
||||
public class Shader implements GLObject {
|
||||
|
||||
protected static ByteBuffer fileBuffer = BufferUtils.createByteBuffer(1024 * 10);
|
||||
|
||||
private int type;
|
||||
private int ID;
|
||||
|
||||
public Shader() {
|
||||
}
|
||||
|
||||
public Shader(final int type, final CharSequence source) {
|
||||
createFromSource(type, source);
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
if ( ID == 0 )
|
||||
throw new IllegalStateException("The shader has not been created");
|
||||
|
||||
glDeleteShader(ID);
|
||||
ID = 0;
|
||||
}
|
||||
|
||||
public void createFromFile(final int type, final ClassLoader loader, final String file) throws IOException {
|
||||
final InputStream inputStream = loader.getResourceAsStream(file);
|
||||
|
||||
if ( inputStream == null )
|
||||
throw new IllegalArgumentException("A shader source file could not be found: " + file);
|
||||
|
||||
final BufferedInputStream stream = new BufferedInputStream(inputStream);
|
||||
|
||||
byte character;
|
||||
while ( (character = (byte)stream.read()) != -1 )
|
||||
fileBuffer.put(character);
|
||||
fileBuffer.flip();
|
||||
|
||||
stream.close();
|
||||
|
||||
final byte[] array = new byte[fileBuffer.remaining()];
|
||||
fileBuffer.get(array);
|
||||
|
||||
final String source = new String(array);
|
||||
|
||||
fileBuffer.clear();
|
||||
|
||||
createFromSource(type, source);
|
||||
}
|
||||
|
||||
public void createFromSource(final int type, final CharSequence source) {
|
||||
if ( ID != 0 )
|
||||
throw new IllegalStateException("The shader has already been created");
|
||||
|
||||
this.type = type;
|
||||
this.ID = glCreateShader(type);
|
||||
|
||||
glShaderSource(ID, source);
|
||||
|
||||
glCompileShader(ID);
|
||||
|
||||
if ( glGetShader(ID, GL_COMPILE_STATUS) == GL_FALSE ) {
|
||||
printInfoLog();
|
||||
destroy();
|
||||
throw new RuntimeException("A compilation error occured in a shader.");
|
||||
}
|
||||
}
|
||||
|
||||
public void printInfoLog() {
|
||||
if ( ID == 0 )
|
||||
throw new IllegalStateException("The shader has not been created");
|
||||
|
||||
final int logLength = glGetShader(ID, GL_INFO_LOG_LENGTH);
|
||||
if ( logLength <= 1 )
|
||||
return;
|
||||
|
||||
System.out.println("\nInfo Log of Shader Object: " + ID);
|
||||
System.out.println("--------------------------");
|
||||
System.out.println(glGetShaderInfoLog(ID, logLength));
|
||||
}
|
||||
|
||||
}
|
||||
82
src/java/org/lwjgl/test/opengles/util/ShaderProgram.java
Normal file
82
src/java/org/lwjgl/test/opengles/util/ShaderProgram.java
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
|
||||
public class ShaderProgram implements GLObject {
|
||||
|
||||
private final int ID;
|
||||
|
||||
public ShaderProgram(final Shader... shaders) {
|
||||
this.ID = glCreateProgram();
|
||||
|
||||
for ( Shader shader : shaders )
|
||||
glAttachShader(ID, shader.getID());
|
||||
|
||||
glLinkProgram(ID);
|
||||
|
||||
if ( glGetProgram(ID, GL_LINK_STATUS) == GL_FALSE ) {
|
||||
printInfoLog();
|
||||
destroy();
|
||||
throw new RuntimeException("Failed to link a Shader Program: " + ID);
|
||||
}
|
||||
}
|
||||
|
||||
public void validate() {
|
||||
glValidateProgram(ID);
|
||||
|
||||
final boolean error = glGetProgram(ID, GL_VALIDATE_STATUS) == GL_FALSE;
|
||||
|
||||
if ( error ) {
|
||||
printInfoLog();
|
||||
throw new RuntimeException("Failed to validate a Shader Program.");
|
||||
}
|
||||
}
|
||||
|
||||
public int getID() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
glDeleteProgram(ID);
|
||||
}
|
||||
|
||||
public void enable() {
|
||||
glUseProgram(ID);
|
||||
}
|
||||
|
||||
public static void disable() {
|
||||
glUseProgram(0);
|
||||
}
|
||||
|
||||
public int getUniformLocation(final String uniform) {
|
||||
final int location = glGetUniformLocation(ID, uniform);
|
||||
|
||||
if ( location == -1 )
|
||||
throw new IllegalArgumentException("Invalid uniform name specified: " + uniform);
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
public int getAttributeLocation(final String attrib) {
|
||||
final int location = glGetAttribLocation(ID, attrib);
|
||||
|
||||
if ( location == -1 )
|
||||
throw new IllegalArgumentException("Invalid attribute name specified: " + attrib);
|
||||
|
||||
return location;
|
||||
}
|
||||
|
||||
private void printInfoLog() {
|
||||
final int logLength = glGetProgram(ID, GL_INFO_LOG_LENGTH);
|
||||
|
||||
System.out.println(logLength);
|
||||
if ( logLength <= 1 )
|
||||
return;
|
||||
|
||||
System.out.println("\nInfo Log of Shader Program: " + ID);
|
||||
System.out.println("-------------------");
|
||||
System.out.println(glGetProgramInfoLog(ID, logLength));
|
||||
System.out.println("-------------------");
|
||||
}
|
||||
|
||||
}
|
||||
414
src/java/org/lwjgl/test/opengles/util/Sphere.java
Normal file
414
src/java/org/lwjgl/test/opengles/util/Sphere.java
Normal file
|
|
@ -0,0 +1,414 @@
|
|||
package org.lwjgl.test.opengles.util;
|
||||
|
||||
import java.nio.FloatBuffer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.lwjgl.opengles.GLES20.*;
|
||||
|
||||
/** VBO implementation of GLU Sphere. */
|
||||
public final class Sphere {
|
||||
|
||||
/* QuadricNormal */
|
||||
public static final int GLU_SMOOTH = 100000;
|
||||
public static final int GLU_FLAT = 100001;
|
||||
public static final int GLU_NONE = 100002;
|
||||
|
||||
/* QuadricDrawStyle */
|
||||
public static final int GLU_POINT = 100010;
|
||||
public static final int GLU_LINE = 100011;
|
||||
public static final int GLU_FILL = 100012;
|
||||
public static final int GLU_SILHOUETTE = 100013;
|
||||
|
||||
/* QuadricOrientation */
|
||||
public static final int GLU_OUTSIDE = 100020;
|
||||
public static final int GLU_INSIDE = 100021;
|
||||
|
||||
static final float PI = (float)Math.PI;
|
||||
|
||||
private int drawStyle;
|
||||
private int orientation;
|
||||
private boolean textureFlag;
|
||||
private int normals;
|
||||
|
||||
private BufferObjectArray bo;
|
||||
|
||||
private final List<DrawCommand> drawCommands = new ArrayList<DrawCommand>(4);
|
||||
|
||||
public Sphere() {
|
||||
this(GLU_FILL, GLU_OUTSIDE, false, GLU_SMOOTH);
|
||||
}
|
||||
|
||||
public Sphere(final int drawStyle, final int orientation, final boolean textureFlag, final int normals) {
|
||||
setDrawStyle(drawStyle);
|
||||
setOrientation(orientation);
|
||||
setTextureFlag(textureFlag);
|
||||
setNormals(normals);
|
||||
}
|
||||
|
||||
public Sphere(final float radius, final int slices, final int stacks) {
|
||||
this();
|
||||
updateGeometry(radius, slices, stacks);
|
||||
}
|
||||
|
||||
public Sphere(final float radius, final int slices, final int stacks,
|
||||
final int drawStyle, final int orientation, final boolean textureFlag, final int normals) {
|
||||
this(drawStyle, orientation, textureFlag, normals);
|
||||
updateGeometry(radius, slices, stacks);
|
||||
}
|
||||
|
||||
public void updateGeometry(final float radius, final int slices, final int stacks) {
|
||||
if ( bo != null )
|
||||
destroy();
|
||||
|
||||
bo = new BufferObjectArray(GL_STATIC_DRAW, createBuffer(radius, slices, stacks));
|
||||
}
|
||||
|
||||
public void bind() {
|
||||
bo.enable();
|
||||
}
|
||||
|
||||
public void draw() {
|
||||
for ( DrawCommand command : drawCommands )
|
||||
command.draw();
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
bo.destroy();
|
||||
bo = null;
|
||||
|
||||
drawCommands.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies the draw style for quadrics.
|
||||
* <p/>
|
||||
* The legal values are as follows:
|
||||
* <p/>
|
||||
* GLU.FILL: Quadrics are rendered with polygon primitives. The polygons
|
||||
* are drawn in a counterclockwise fashion with respect to
|
||||
* their normals (as defined with glu.quadricOrientation).
|
||||
* <p/>
|
||||
* GLU.LINE: Quadrics are rendered as a set of lines.
|
||||
* <p/>
|
||||
* GLU.SILHOUETTE: Quadrics are rendered as a set of lines, except that edges
|
||||
* separating coplanar faces will not be drawn.
|
||||
* <p/>
|
||||
* GLU.POINT: Quadrics are rendered as a set of points.
|
||||
*
|
||||
* @param drawStyle The drawStyle to set
|
||||
*/
|
||||
public void setDrawStyle(int drawStyle) {
|
||||
switch ( drawStyle ) {
|
||||
case GLU_FILL:
|
||||
case GLU_LINE:
|
||||
case GLU_SILHOUETTE:
|
||||
case GLU_POINT:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid draw style specified: " + drawStyle);
|
||||
}
|
||||
|
||||
this.drawStyle = drawStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies what kind of normals are desired for quadrics.
|
||||
* The legal values are as follows:
|
||||
* <p/>
|
||||
* GLU.NONE: No normals are generated.
|
||||
* <p/>
|
||||
* GLU.FLAT: One normal is generated for every facet of a quadric.
|
||||
* <p/>
|
||||
* GLU.SMOOTH: One normal is generated for every vertex of a quadric. This
|
||||
* is the default.
|
||||
*
|
||||
* @param normals The normals to set
|
||||
*/
|
||||
public void setNormals(int normals) {
|
||||
switch ( normals ) {
|
||||
case GLU_NONE:
|
||||
case GLU_FLAT:
|
||||
case GLU_SMOOTH:
|
||||
break;
|
||||
default:
|
||||
throw new IllegalArgumentException("Invalid normal kind specified: " + normals);
|
||||
}
|
||||
|
||||
this.normals = normals;
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies what kind of orientation is desired for.
|
||||
* The orientation values are as follows:
|
||||
* <p/>
|
||||
* GLU.OUTSIDE: Quadrics are drawn with normals pointing outward.
|
||||
* <p/>
|
||||
* GLU.INSIDE: Normals point inward. The default is GLU.OUTSIDE.
|
||||
* <p/>
|
||||
* Note that the interpretation of outward and inward depends on the quadric
|
||||
* being drawn.
|
||||
*
|
||||
* @param orientation The orientation to set
|
||||
*/
|
||||
public void setOrientation(int orientation) {
|
||||
if ( orientation != GLU_OUTSIDE && orientation != GLU_INSIDE )
|
||||
throw new IllegalArgumentException("Invalid orientation specified: " + orientation);
|
||||
|
||||
this.orientation = orientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* specifies if texture coordinates should be generated for
|
||||
* quadrics rendered with qobj. If the value of textureCoords is true,
|
||||
* then texture coordinates are generated, and if textureCoords is false,
|
||||
* they are not.. The default is false.
|
||||
* <p/>
|
||||
* The manner in which texture coordinates are generated depends upon the
|
||||
* specific quadric rendered.
|
||||
*
|
||||
* @param textureFlag The textureFlag to set
|
||||
*/
|
||||
public void setTextureFlag(boolean textureFlag) {
|
||||
this.textureFlag = textureFlag;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the drawStyle.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getDrawStyle() {
|
||||
return drawStyle;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the normals.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getNormals() {
|
||||
return normals;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the orientation.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public int getOrientation() {
|
||||
return orientation;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the textureFlag.
|
||||
*
|
||||
* @return boolean
|
||||
*/
|
||||
public boolean getTextureFlag() {
|
||||
return textureFlag;
|
||||
}
|
||||
|
||||
private static float sin(final float r) {
|
||||
return (float)Math.sin(r);
|
||||
}
|
||||
|
||||
private static float cos(final float r) {
|
||||
return (float)Math.cos(r);
|
||||
}
|
||||
|
||||
private int addDrawCommand(final int mode, final int first, final int count) {
|
||||
drawCommands.add(new DrawCommand(mode, first, count));
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* draws a sphere of the given radius centered around the origin.
|
||||
* The sphere is subdivided around the z axis into slices and along the z axis
|
||||
* into stacks (similar to lines of longitude and latitude).
|
||||
* <p/>
|
||||
* If the orientation is set to GLU.OUTSIDE (with glu.quadricOrientation), then
|
||||
* any normals generated point away from the center of the sphere. Otherwise,
|
||||
* they point toward the center of the sphere.
|
||||
* <p/>
|
||||
* If texturing is turned on (with glu.quadricTexture), then texture
|
||||
* coordinates are generated so that t ranges from 0.0 at z=-radius to 1.0 at
|
||||
* z=radius (t increases linearly along longitudinal lines), and s ranges from
|
||||
* 0.0 at the +y axis, to 0.25 at the +x axis, to 0.5 at the -y axis, to 0.75
|
||||
* at the -x axis, and back to 1.0 at the +y axis.
|
||||
*/
|
||||
public FloatBuffer createBuffer(float radius, int slices, int stacks) {
|
||||
float rho, theta;
|
||||
float x, y, z;
|
||||
float s, t, ds, dt;
|
||||
int i, j;
|
||||
|
||||
final boolean normals = this.normals != GLU_NONE;
|
||||
final float nsign = this.orientation == GLU_INSIDE ? -1.0f : 1.0f;
|
||||
|
||||
final float drho = PI / stacks;
|
||||
final float dtheta = 2.0f * PI / slices;
|
||||
|
||||
final ImmediateModeBuffer imb = new ImmediateModeBuffer(16 * 1024); // TODO: We can calculate this to avoid re-allocs
|
||||
int lastDrawIndex = 0;
|
||||
|
||||
if ( this.drawStyle == GLU_FILL ) {
|
||||
if ( !this.textureFlag ) {
|
||||
lastDrawIndex += addDrawCommand(GL_TRIANGLE_FAN, lastDrawIndex, slices + 2);
|
||||
|
||||
// draw +Z end as a triangle fan
|
||||
imb.glNormal3f(0.0f, 0.0f, 1.0f);
|
||||
imb.glVertex3f(0.0f, 0.0f, nsign * radius);
|
||||
for ( j = 0; j <= slices; j++ ) {
|
||||
theta = (j == slices) ? 0.0f : j * dtheta;
|
||||
x = -sin(theta) * sin(drho);
|
||||
y = cos(theta) * sin(drho);
|
||||
z = nsign * cos(drho);
|
||||
if ( normals )
|
||||
imb.glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
imb.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
}
|
||||
|
||||
ds = 1.0f / slices;
|
||||
dt = 1.0f / stacks;
|
||||
t = 1.0f; // because loop now runs from 0
|
||||
|
||||
final int imin, imax;
|
||||
if ( this.textureFlag ) {
|
||||
imin = 0;
|
||||
imax = stacks;
|
||||
} else {
|
||||
imin = 1;
|
||||
imax = stacks - 1;
|
||||
}
|
||||
|
||||
// draw intermediate stacks as quad strips
|
||||
for ( i = imin; i < imax; i++ ) {
|
||||
lastDrawIndex += addDrawCommand(GL_TRIANGLE_STRIP, lastDrawIndex, (slices + 1) * 2);
|
||||
|
||||
rho = i * drho;
|
||||
s = 0.0f;
|
||||
for ( j = 0; j <= slices; j++ ) {
|
||||
theta = (j == slices) ? 0.0f : j * dtheta;
|
||||
|
||||
x = -sin(theta) * sin(rho);
|
||||
y = cos(theta) * sin(rho);
|
||||
z = nsign * cos(rho);
|
||||
if ( normals )
|
||||
imb.glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
if ( textureFlag )
|
||||
imb.glTexCoord2f(s, t);
|
||||
imb.glVertex3f(x * radius, y * radius, z * radius);
|
||||
|
||||
x = -sin(theta) * sin(rho + drho);
|
||||
y = cos(theta) * sin(rho + drho);
|
||||
z = nsign * cos(rho + drho);
|
||||
if ( normals )
|
||||
imb.glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
if ( textureFlag )
|
||||
imb.glTexCoord2f(s, t - dt);
|
||||
s += ds;
|
||||
imb.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
t -= dt;
|
||||
}
|
||||
|
||||
if ( !this.textureFlag ) {
|
||||
lastDrawIndex += addDrawCommand(GL_TRIANGLE_FAN, lastDrawIndex, slices + 2);
|
||||
|
||||
// draw -Z end as a triangle fan
|
||||
imb.glNormal3f(0.0f, 0.0f, -1.0f);
|
||||
imb.glVertex3f(0.0f, 0.0f, -radius * nsign);
|
||||
rho = PI - drho;
|
||||
s = 1.0f;
|
||||
for ( j = slices; j >= 0; j-- ) {
|
||||
theta = (j == slices) ? 0.0f : j * dtheta;
|
||||
x = -sin(theta) * sin(rho);
|
||||
y = cos(theta) * sin(rho);
|
||||
z = nsign * cos(rho);
|
||||
if ( normals )
|
||||
imb.glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
s -= ds;
|
||||
imb.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
}
|
||||
} else if ( this.drawStyle == GLU_LINE || this.drawStyle == GLU_SILHOUETTE ) {
|
||||
// draw stack lines
|
||||
for ( i = 1; i < stacks; i++ ) { // stack line at i==stacks-1 was missing here
|
||||
lastDrawIndex += addDrawCommand(GL_LINE_LOOP, lastDrawIndex, slices);
|
||||
|
||||
rho = i * drho;
|
||||
for ( j = 0; j < slices; j++ ) {
|
||||
theta = j * dtheta;
|
||||
x = cos(theta) * sin(rho);
|
||||
y = sin(theta) * sin(rho);
|
||||
z = cos(rho);
|
||||
if ( normals )
|
||||
imb.glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
imb.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
}
|
||||
// draw slice lines
|
||||
for ( j = 0; j < slices; j++ ) {
|
||||
lastDrawIndex += addDrawCommand(GL_LINE_STRIP, lastDrawIndex, stacks + 1);
|
||||
|
||||
theta = j * dtheta;
|
||||
for ( i = 0; i <= stacks; i++ ) {
|
||||
rho = i * drho;
|
||||
x = cos(theta) * sin(rho);
|
||||
y = sin(theta) * sin(rho);
|
||||
z = cos(rho);
|
||||
if ( normals )
|
||||
imb.glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
imb.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
}
|
||||
} else if ( this.drawStyle == GLU_POINT ) {
|
||||
lastDrawIndex += addDrawCommand(GL_POINTS, lastDrawIndex, 2 + (stacks - 2) * slices);
|
||||
|
||||
// top and bottom-most points
|
||||
if ( normals )
|
||||
imb.glNormal3f(0.0f, 0.0f, nsign);
|
||||
imb.glVertex3f(0.0f, 0.0f, radius);
|
||||
if ( normals )
|
||||
imb.glNormal3f(0.0f, 0.0f, -nsign);
|
||||
imb.glVertex3f(0.0f, 0.0f, -radius);
|
||||
|
||||
// loop over stacks
|
||||
for ( i = 1; i < stacks - 1; i++ ) {
|
||||
rho = i * drho;
|
||||
for ( j = 0; j < slices; j++ ) {
|
||||
theta = j * dtheta;
|
||||
x = cos(theta) * sin(rho);
|
||||
y = sin(theta) * sin(rho);
|
||||
z = cos(rho);
|
||||
if ( normals )
|
||||
imb.glNormal3f(x * nsign, y * nsign, z * nsign);
|
||||
imb.glVertex3f(x * radius, y * radius, z * radius);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return imb.getBuffer();
|
||||
}
|
||||
|
||||
private static class DrawCommand {
|
||||
|
||||
private int mode;
|
||||
private int first;
|
||||
private int count;
|
||||
|
||||
private DrawCommand(final int mode, final int first, final int count) {
|
||||
this.mode = mode;
|
||||
this.first = first;
|
||||
this.count = count;
|
||||
}
|
||||
|
||||
void draw() {
|
||||
glDrawArrays(mode, first, count);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue