org.ode4j.drawstuff.internal.LwJGL Maven / Gradle / Ivy
/*************************************************************************
* *
* Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. *
* All rights reserved. Email: [email protected] Web: www.q12.org *
* Open Dynamics Engine 4J, Copyright (C) 2009-2014 Tilmann Zaeschke *
* All rights reserved. Email: [email protected] Web: www.ode4j.org *
* *
* This library is free software; you can redistribute it and/or *
* modify it under the terms of EITHER: *
* (1) The GNU Lesser General Public License as published by the Free *
* Software Foundation; either version 2.1 of the License, or (at *
* your option) any later version. The text of the GNU Lesser *
* General Public License is included with this library in the *
* file LICENSE.TXT. *
* (2) The BSD-style license that is included with this library in *
* the file ODE-LICENSE-BSD.TXT and ODE4J-LICENSE-BSD.TXT. *
* *
* This library is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files *
* LICENSE.TXT, ODE-LICENSE-BSD.TXT and ODE4J-LICENSE-BSD.TXT for more *
* details. *
* *
*************************************************************************/
package org.ode4j.drawstuff.internal;
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.opengl.GL11;
import org.lwjgl.opengl.GLContext;
import org.ode4j.drawstuff.DrawStuff;
import org.ode4j.drawstuff.DrawStuff.dsFunctions;
import org.ode4j.ode.OdeHelper;
import org.ode4j.ode.internal.Common;
import static org.ode4j.ode.internal.cpp4j.Cstdio.*;
/**
* Main window and event handling for LWJGL.
* Ported from x11.cpp.
*/
abstract class LwJGL extends Internal implements DrawStuffApi {
//Ensure that Display.destroy() is called (TZ)
//Not sure this works, but it's an attempt at least.
//-> This should avoid the Problem that a process keeps running with 99%CPU,
// even if the window is closed (clicking on the 'x'). The supposed
// problem is that when clicking 'x', Display.destroy() never gets called
// by dsPlatformSimLoop().
static {
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
// Display.destroy();
}
});
}
//***************************************************************************
// error handling for unix
//static void printMessage (const char *msg1, const char *msg2, va_list ap)
private static void printMessage (String msg1, String fmt, Object ... ap)
{
fflush (stderr);
fflush (stdout);
fprintf (stderr,"\n%s: ",msg1);
vfprintf (stderr,fmt,ap);
fprintf (stderr,"\n");
fflush (stderr);
}
//extern "C" void dsError (const char *msg, ...)
static void dsError (String msg, Object ... ap)
{
// va_list ap;
// va_start (ap,msg);
printMessage ("Error",msg,ap);
//TZ exit (1);
throw new RuntimeException();
}
//extern "C" void dsDebug (const char *msg, ...)
static void dsDebug (String msg, Object ... ap)
{
// va_list ap;
// va_start (ap,msg);
printMessage ("INTERNAL ERROR",msg,ap);
// *((char *)0) = 0; ... commit SEGVicide ?
//TZ abort();
throw new RuntimeException();
}
//extern "C" void dsPrint (const char *msg, ...)
static void dsPrint (String msg, Object ... ap)
{
// va_list ap;
// va_start (ap,msg);
vprintf (msg,ap);
}
//***************************************************************************
// openGL window
// X11 display info
//static Display display;//*display=0;
//private static int screen=0;
//static XVisualInfo visual;//*visual=0; // best visual for openGL
//static Colormap colormap=null; // window's colormap
//static Atom wm_protocols_atom = null;
//static Atom wm_delete_window_atom = null;
// window and openGL
//static Window win=null; // X11 window, 0 if not initialized
private static int width=0,height=0; // window size
//static GLXContext glx_context=null; // openGL rendering context
private static int last_key_pressed=0; // last key pressed in the window
private static boolean run=true; // 1 if simulation running
private static boolean pause=false; // 1 if in `pause' mode
private static boolean singlestep=false; // 1 if single step key pressed
private static boolean writeframes=false; // 1 if frame files to be written
private static void createMainWindow (int _width, int _height)
{
// create Window of size 300x300
try {
Display.setLocation((Display.getDisplayMode().getWidth() - _width) / 2,
(Display.getDisplayMode().getHeight() - _height) / 2);
} catch (UnsatisfiedLinkError e) {
System.err.println("Missing lwjgl native libraries.");
System.err.println("If you are using maven, make sure to use "
+ "'-Djava.library.path=target/natives' as VM argument of your application.");
System.err.println("For plain Eclipse, add the native library path to the included "
+ "lwjgl.jar in the definition of the Referenced Libraries.");
throw e;
}
try {
Display.setDisplayMode(new DisplayMode(_width, _height));
Display.setTitle("Simulation");
Display.setVSyncEnabled(true); //for VSync (TZ)
Display.create();
} catch (LWJGLException e) {
throw new RuntimeException(e);
}
try {
Keyboard.create();
Mouse.create();
} catch (LWJGLException e) {
throw new RuntimeException(e);
}
if (firsttime) {
System.err.println("GL_VENDOR: " + GL11.glGetString(GL11.GL_VENDOR));
System.err.println("GL_RENDERER: " + GL11.glGetString(GL11.GL_RENDERER));
System.err.println("GL_VERSION: " + GL11.glGetString(GL11.GL_VERSION));
System.err.println("LWJGL_VERSION: " + Sys.getVersion());
System.err.println();
System.err.println("glLoadTransposeMatrixfARB() supported: " +
GLContext.getCapabilities().GL_ARB_transpose_matrix);
}
// // create X11 display connection
// display = XOpenDisplay (null);
// if (!display) dsError ("can not open X11 display");
// screen = DefaultScreen(display);
//
// // get GL visual
// static int attribList[] = {GLX_RGBA, GLX_DOUBLEBUFFER, GLX_DEPTH_SIZE,16,
// GLX_RED_SIZE,4, GLX_GREEN_SIZE,4,
// GLX_BLUE_SIZE,4, None};
// visual = glXChooseVisual (display,screen,attribList);
// if (!visual) dsError ("no good X11 visual found for OpenGL");
// create colormap
// colormap = XCreateColormap (display,RootWindow(display,screen),
// visual.visual,AllocNone);
// initialize variables
// win = 0;
width = _width;
height = _height;
// glx_context = 0;
last_key_pressed = 0;
if (width < 1 || height < 1) dsDebug ("","bad window width or height");
// create the window
// XSetWindowAttributes attributes;
// attributes.background_pixel = BlackPixel(display,screen);
// attributes.colormap = colormap;
// attributes.event_mask = ButtonPressMask | ButtonReleaseMask |
// KeyPressMask | KeyReleaseMask | ButtonMotionMask | PointerMotionHintMask |
// StructureNotifyMask;
// win = XCreateWindow (display,RootWindow(display,screen),50,50,width,height,
// 0,visual.depth, InputOutput,visual.visual,
// CWBackPixel | CWColormap | CWEventMask, attributes);
// associate a GLX context with the window
// glx_context = glXCreateContext (display,visual,0,GL_TRUE);
// if (!glx_context) dsError ("can't make an OpenGL context");
// set the window title
// XTextProperty window_name;
// window_name.value = "Simulation";//(unsigned char *) "Simulation";
// window_name.encoding = XA_STRING;
// window_name.format = 8;
// window_name.nitems = window_name.value.length;//strlen((char *) window_name.value);
// XSetWMName (display,win,window_name);
// participate in the window manager 'delete yourself' protocol
// wm_protocols_atom = XInternAtom (display,"WM_PROTOCOLS",False);
// wm_delete_window_atom = XInternAtom (display,"WM_DELETE_WINDOW",False);
// if (XSetWMProtocols (display,win,wm_delete_window_atom,1)==0)
// dsError ("XSetWMProtocols() call failed");
// pop up the window
// XMapWindow (display,win);
// XSync (display,win);
}
private static void destroyMainWindow()
{
// glXDestroyContext (display,glx_context);
// XDestroyWindow (display,win);
// XSync (display,0);
// XCloseDisplay(display);
// display = 0;
// win = 0;
// glx_context = 0;
Keyboard.destroy();
Mouse.destroy();
Display.destroy();
}
// private static int mx=0,my=0; // mouse position
// private static int mode = 0; // mouse button bits
//static void handleEvent (XEvent &event, dsFunctions *fn)
// static void handleEvent (XEvent event, dsFunctions fn)
// {
// //TZ static int mx=0,my=0; // mouse position
// //TZ static int mode = 0; // mouse button bits
// switch (event.type) {
//
// case ButtonPress: {
// if (event.xbutton.button == Button1) mode |= 1;
// if (event.xbutton.button == Button2) mode |= 2;
// if (event.xbutton.button == Button3) mode |= 4;
// mx = event.xbutton.x;
// my = event.xbutton.y;
// }
// return;
//
// case ButtonRelease: {
// if (event.xbutton.button == Button1) mode &= (~1);
// if (event.xbutton.button == Button2) mode &= (~2);
// if (event.xbutton.button == Button3) mode &= (~4);
// mx = event.xbutton.x;
// my = event.xbutton.x;
// }
// return;
//
// case MotionNotify: {
// if (event.xmotion.is_hint) {
// Window root,child;
// //unsigned
// int mask;
// XQueryPointer (display,win,root,child,event.xbutton.x_root,
// event.xbutton.y_root,event.xbutton.x,event.xbutton.y,
// mask);
// }
// dsMotion (mode, event.xmotion.x - mx, event.xmotion.y - my);
// mx = event.xmotion.x;
// my = event.xmotion.y;
// }
// return;
//Moved to handleKeyboard() TZ
// case KeyPress: {
// KeySym key;
// XLookupString (event.xkey,NULL,0,key,0);
// if ((event.xkey.state & ControlMask) == 0) {
// if (key >= ' ' && key <= 126 && fn.command) fn.command (key);
// }
// else if (event.xkey.state & ControlMask) {
// switch (key) {
// case 't': case 'T':
// dsSetTextures (dsGetTextures() ^ 1);
// break;
// case 's': case 'S':
// dsSetShadows (dsGetShadows() ^ 1);
// break;
// case 'x': case 'X':
// run = 0;
// break;
// case 'p': case 'P':
// pause ^= 1;
// singlestep = 0;
// break;
// case 'o': case 'O':
// if (pause) singlestep = 1;
// break;
// case 'v': case 'V': {
// float[] xyz=new float [3], hpr = new float [3];
// dsGetViewpoint (xyz,hpr);
// printf ("Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n",
// xyz[0],xyz[1],xyz[2],hpr[0],hpr[1],hpr[2]);
// break;
// }
// case 'w': case 'W':
// writeframes ^= 1;
// if (writeframes) printf ("Now writing frames to PPM files\n");
// break;
// }
// }
// last_key_pressed = key; // a kludgy place to put this...
// }
// return;
//
// case KeyRelease: {
// // hmmmm...
// }
// return;
// case ClientMessage:
// if (event.xclient.message_type == wm_protocols_atom &&
// event.xclient.format == 32 &&
// Atom(event.xclient.data.l[0]) == wm_delete_window_atom) {
// run = 0;
// return;
// }
// return;
//
// case ConfigureNotify:
// width = event.xconfigure.width;
// height = event.xconfigure.height;
// return;
// }
// }
// // return the index of the highest bit
// //static int getHighBitIndex (unsigned int x)
// private static int getHighBitIndex (int x)
// {
// int i = 0;
// while (x!=0) {
// i++;
// x >>= 1;
// }
// return i-1;
// }
//
//
// // shift x left by i, where i can be positive or negative
// //#define SHIFTL(x,i) (((i) >= 0) ? ((x) << (i)) : ((x) >> (-i)))
// //int? double?
// private final int SHIFTL(long x, int i) {
// return (int) ((i >= 0) ? (x << (i)) : ((x) >> (-i)));
// }
private static void captureFrame (int num)
{
throw new UnsupportedOperationException();
// fprintf (stderr,"capturing frame %04d\n",num);
//
// char s[100];
// sprintf (s,"frame/frame%04d.ppm",num);
// FILE *f = fopen (s,"wb");
// if (!f) dsError ("can't open \"%s\" for writing",s);
// fprintf (f,"P6\n%d %d\n255\n",width,height);
// XImage *image = XGetImage (display,win,0,0,width,height,~0,ZPixmap);
//
// int rshift = 7 - getHighBitIndex (image.red_mask);
// int gshift = 7 - getHighBitIndex (image.green_mask);
// int bshift = 7 - getHighBitIndex (image.blue_mask);
//
// for (int y=0; y= ' ' && key <= 126 && fn.command) fn.command (key);
char keyChar = Keyboard.getEventCharacter();
if (keyChar >= ' ' && keyChar <= 126) fn.command (keyChar);
// System.out.println("cmd-c " +Keyboard.getEventCharacter());
// System.out.println("cmd- " + (char)(key+65));
} else { //if (event.xkey.state & ControlMask) {
if (key == last_key_pressed) {
continue;
}
switch (key) {
case Keyboard.KEY_T:
dsSetTextures (!dsGetTextures());
break;
case Keyboard.KEY_S:
dsSetShadows (!dsGetShadows());
break;
case Keyboard.KEY_X:
run = false;
break;
case Keyboard.KEY_P:
pause = !pause;
singlestep = false;
break;
case Keyboard.KEY_O:
if (pause) singlestep = true;
break;
case Keyboard.KEY_V: {
float[] xyz=new float [3], hpr = new float [3];
dsGetViewpoint (xyz,hpr);
printf ("Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n",
xyz[0],xyz[1],xyz[2],hpr[0],hpr[1],hpr[2]);
break;
}
case Keyboard.KEY_W:
writeframes = !writeframes;
if (writeframes) printf ("Now writing frames to PPM files\n");
break;
}
}
last_key_pressed = key; // a kludgy place to put this...
}
}
/**
* handles the mouse
*/
private void handleMouse() {
readBufferedMouse();
}
/**
* reads a mouse in buffered mode
*/
private void readBufferedMouse() {
// iterate all events, use the last button down
while(Mouse.next()) {
if (Mouse.getEventButton() != -1) {
if (Mouse.getEventButtonState()) {
}
//lastButton = Mouse.getEventButton();
}
}
updateState();
}
/**
* Updates our "model"
*
*/
private void updateState() {
int dx = Mouse.getDX();
int dy = Mouse.getDY();
int dw = Mouse.getDWheel();
// get out if no movement
if (dx == dy && dx == 0 && dw == 0) {
return;
}
//LWJGL: 0=left 1=right 2=middle
//GL: 0=left 1=middle 2=right
int mode = 0;
if (Mouse.isButtonDown(0)) mode |= 1;
if (Mouse.isButtonDown(2)) mode |= 2;
if (Mouse.isButtonDown(1)) mode |= 4;
if (mode != 0) {
//LWJGL has inverted dy wrt C++/GL
dsMotion (mode, dx, -dy);
}
}
//void dsPlatformSimLoop (int window_width, int window_height, dsFunctions *fn,
// int initial_pause)
private static boolean firsttime=true;
@Override
void dsPlatformSimLoop (int window_width, int window_height, dsFunctions fn,
boolean initial_pause)
{
pause = initial_pause;
createMainWindow (window_width, window_height);
//glXMakeCurrent (display,win,glx_context);
//TODO ?
//GLContext.useContext(context);
try {
//Sets the context / by TZ
Display.makeCurrent();
} catch (LWJGLException e) {
throw new RuntimeException(e);
}
dsStartGraphics (window_width,window_height,fn);
//TZ static bool firsttime=true;
if (firsttime)
{
System.err.println();
System.err.print("Using ode4j version: " + OdeHelper.getVersion());
System.err.println(" [" + OdeHelper.getConfiguration() + "]");
System.err.println();
fprintf
(
stderr,
"\n" +
"Simulation test environment v%d.%02d\n" +
" Ctrl-P : pause / unpause (or say `-pause' on command line).\n" +
" Ctrl-O : single step when paused.\n" +
" Ctrl-T : toggle textures (or say `-notex' on command line).\n" +
" Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n" +
" Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n" +
" Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n" +
" Ctrl-X : exit.\n" +
"\n" +
"Change the camera position by clicking + dragging in the window.\n" +
" Left button - pan and tilt.\n" +
" Right button - forward and sideways.\n" +
" Left + Right button (or middle button) - sideways and up.\n" +
"\n",DrawStuff.DS_VERSION >> 8,DrawStuff.DS_VERSION & 0xff
);
firsttime = false;
}
//if (fn.start)
fn.start();
int frame = 1;
run = true;
long startTime = System.currentTimeMillis() + 5000;
long fps = 0;
while (run && !Display.isCloseRequested()) {
// while (run) {
// read in and process all pending events for the main window
// XEvent event;
// while (run && XPending (display)) {
// XNextEvent (display,event);
// handleEvent (event,fn);
// }
handleKeyboard(fn);
handleMouse();
//processDrawFrame: This was not move into separate method for convenience
GL11.glClear(GL11.GL_COLOR_BUFFER_BIT | GL11.GL_DEPTH_BUFFER_BIT);
dsDrawFrame (width,height,fn,pause && !singlestep);
singlestep = false;
Display.update();
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;
}
// glFlush();
// glXSwapBuffers (display,win);
// XSync (display,0);
// capture frames if necessary
if (pause==false && writeframes) {
captureFrame (frame);
frame++;
}
}
//if (fn.stop)
fn.stop();
dsStopGraphics();
destroyMainWindow();
}
//extern "C" void dsStop()
@Override
public void dsStop()
{
run = false;
}
private static double prev=System.nanoTime()/1000000000.0;
//extern "C" double dsElapsedTime()
@Override
public double dsElapsedTime()
{
// if (true) {//(HAVE_GETTIMEOFDAY) { //#if HAVE_GETTIMEOFDAY
//TZ static double prev=0.0;
// timeval tv ;
//
// gettimeofday(tv, 0);
// double curr = tv.tv_sec + (double) tv.tv_usec / 1000000.0 ;
double curr = System.nanoTime()/1000000000.0;
// if (prev==-1)
// prev=curr;
double retval = curr-prev;
prev=curr;
if (retval>1.0) retval=1.0;
if (retval © 2015 - 2025 Weber Informatics LLC | Privacy Policy