Make photo more suitable for launching from OR UI

This commit is contained in:
bkuker 2013-12-04 16:19:46 -05:00
parent e9a75b1111
commit 830fe96115
2 changed files with 244 additions and 235 deletions

View File

@ -2,6 +2,7 @@ package net.sf.openrocket.gui.figure3d.photo;
import java.awt.Dimension; import java.awt.Dimension;
import java.awt.Toolkit; import java.awt.Toolkit;
import java.awt.Window;
import java.awt.event.ActionEvent; import java.awt.event.ActionEvent;
import java.awt.event.ActionListener; import java.awt.event.ActionListener;
import java.awt.event.KeyEvent; import java.awt.event.KeyEvent;
@ -41,31 +42,31 @@ import com.google.inject.Injector;
import com.google.inject.Module; import com.google.inject.Module;
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class PhotoApp extends JFrame { public class PhotoFrame extends JFrame {
private static final Logger log = LoggerFactory.getLogger(PhotoApp.class); private static final Logger log = LoggerFactory.getLogger(PhotoFrame.class);
private final int SHORTCUT_KEY = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask(); private final int SHORTCUT_KEY = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
private final Translator trans = Application.getTranslator(); private final Translator trans = Application.getTranslator();
private PhotoPanel photoPanel; private final PhotoPanel photoPanel;
private JDialog settings; private final JDialog settings;
public PhotoApp() { public PhotoFrame(OpenRocketDocument document, Window parent) {
this(false);
setTitle("Photo - " + document.getRocket().getName());
photoPanel.setDoc(document);
}
public PhotoFrame(boolean app) {
setSize(1024, 768); setSize(1024, 768);
this.setMinimumSize(new Dimension(160, 150)); this.setMinimumSize(new Dimension(160, 150));
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
photoPanel = new PhotoPanel(); photoPanel = new PhotoPanel();
setJMenuBar(getMenu()); setJMenuBar(getMenu(app));
setContentPane(photoPanel); setContentPane(photoPanel);
GUIUtil.rememberWindowSize(this); GUIUtil.rememberWindowSize(this);
this.setLocationByPlatform(true); this.setLocationByPlatform(true);
GUIUtil.setWindowIcons(this); GUIUtil.setWindowIcons(this);
setTitle("OpenRocket - Photo Studio Alpha");
setVisible(true);
settings = new JDialog(this, "Settings") { settings = new JDialog(this, "Settings") {
{ {
setContentPane(new PhotoSettingsConfig(photoPanel.getSettings())); setContentPane(new PhotoSettingsConfig(photoPanel.getSettings()));
@ -75,63 +76,64 @@ public class PhotoApp extends JFrame {
} }
}; };
} }
JMenuBar getMenu() { private JMenuBar getMenu(final boolean showFileMenu) {
JMenuBar menubar = new JMenuBar(); JMenuBar menubar = new JMenuBar();
JMenu menu; JMenu menu;
JMenuItem item; JMenuItem item;
//// File // // File
menu = new JMenu(trans.get("main.menu.file")); if (showFileMenu) {
menu.setMnemonic(KeyEvent.VK_F); menu = new JMenu(trans.get("main.menu.file"));
//// File-handling related tasks menu.setMnemonic(KeyEvent.VK_F);
menu.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.desc")); // // File-handling related tasks
menubar.add(menu); menu.getAccessibleContext().setAccessibleDescription(trans.get("main.menu.file.desc"));
menubar.add(menu);
item = new JMenuItem(trans.get("main.menu.file.open"), KeyEvent.VK_O);
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY)); item = new JMenuItem(trans.get("main.menu.file.open"), KeyEvent.VK_O);
//// Open a rocket design item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_O, SHORTCUT_KEY));
item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.Openrocketdesign")); // // Open a rocket design
item.setIcon(Icons.FILE_OPEN); item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.Openrocketdesign"));
item.addActionListener(new ActionListener() { item.setIcon(Icons.FILE_OPEN);
@Override item.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) { @Override
log.info(Markers.USER_MARKER, "Open... selected"); public void actionPerformed(ActionEvent e) {
log.info(Markers.USER_MARKER, "Open... selected");
JFileChooser chooser = new JFileChooser();
JFileChooser chooser = new JFileChooser();
chooser.addChoosableFileFilter(FileHelper.ALL_DESIGNS_FILTER);
chooser.addChoosableFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER); chooser.addChoosableFileFilter(FileHelper.ALL_DESIGNS_FILTER);
chooser.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER); chooser.addChoosableFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
chooser.setFileFilter(FileHelper.ALL_DESIGNS_FILTER); chooser.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
chooser.setFileFilter(FileHelper.ALL_DESIGNS_FILTER);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
int option = chooser.showOpenDialog(PhotoApp.this); chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
if (option == JFileChooser.APPROVE_OPTION) { int option = chooser.showOpenDialog(PhotoFrame.this);
File file = chooser.getSelectedFile(); if (option == JFileChooser.APPROVE_OPTION) {
log.debug("Opening File " + file.getAbsolutePath()); File file = chooser.getSelectedFile();
GeneralRocketLoader grl = new GeneralRocketLoader(file); log.debug("Opening File " + file.getAbsolutePath());
try { GeneralRocketLoader grl = new GeneralRocketLoader(file);
OpenRocketDocument doc = grl.load(); try {
photoPanel.setDoc(doc); OpenRocketDocument doc = grl.load();
} catch (RocketLoadException e1) { photoPanel.setDoc(doc);
e1.printStackTrace(); } catch (RocketLoadException e1) {
e1.printStackTrace();
}
} }
} }
} });
}); menu.add(item);
menu.add(item); }
//// Edit // // Edit
menu = new JMenu(trans.get("main.menu.edit")); menu = new JMenu(trans.get("main.menu.edit"));
menu.setMnemonic(KeyEvent.VK_E); menu.setMnemonic(KeyEvent.VK_E);
//// Rocket editing // // Rocket editing
menu.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.menu.Rocketedt")); menu.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.menu.Rocketedt"));
menubar.add(menu); menubar.add(menu);
Action action = new AbstractAction("Copy") { Action action = new AbstractAction("Copy") {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
@ -143,101 +145,90 @@ public class PhotoApp extends JFrame {
item.setMnemonic(KeyEvent.VK_C); item.setMnemonic(KeyEvent.VK_C);
item.getAccessibleContext().setAccessibleDescription("Copy image to clipboard"); item.getAccessibleContext().setAccessibleDescription("Copy image to clipboard");
menu.add(item); menu.add(item);
menu.add(new JMenuItem(new AbstractAction("Photo Settings") { menu.add(new JMenuItem(new AbstractAction("Photo Settings") {
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
settings.setVisible(true); settings.setVisible(true);
} }
})); }));
//Window // Window
menu = new JMenu("Window"); menu = new JMenu("Window");
menubar.add(menu); menubar.add(menu);
JMenu sizeMenu = new JMenu("Size"); JMenu sizeMenu = new JMenu("Size");
menu.add(sizeMenu); menu.add(sizeMenu);
sizeMenu.add(new JMenuItem(new SizeAction(320, 240, "QVGA"))); sizeMenu.add(new JMenuItem(new SizeAction(320, 240, "QVGA")));
sizeMenu.add(new JMenuItem(new SizeAction(640, 480, "VGA"))); sizeMenu.add(new JMenuItem(new SizeAction(640, 480, "VGA")));
sizeMenu.add(new JMenuItem(new SizeAction(1024, 768, "XGA"))); sizeMenu.add(new JMenuItem(new SizeAction(1024, 768, "XGA")));
sizeMenu.addSeparator(); sizeMenu.addSeparator();
sizeMenu.add(new JMenuItem(new SizeAction(240, 320, "QVGA Portrait"))); sizeMenu.add(new JMenuItem(new SizeAction(240, 320, "QVGA Portrait")));
sizeMenu.add(new JMenuItem(new SizeAction(480, 640, "VGA Portrait"))); sizeMenu.add(new JMenuItem(new SizeAction(480, 640, "VGA Portrait")));
sizeMenu.add(new JMenuItem(new SizeAction(768, 1024, "XGA Portrait"))); sizeMenu.add(new JMenuItem(new SizeAction(768, 1024, "XGA Portrait")));
sizeMenu.addSeparator(); sizeMenu.addSeparator();
sizeMenu.add(new JMenuItem(new SizeAction(854, 480, "420p"))); sizeMenu.add(new JMenuItem(new SizeAction(854, 480, "420p")));
sizeMenu.add(new JMenuItem(new SizeAction(1280, 720, "720p"))); sizeMenu.add(new JMenuItem(new SizeAction(1280, 720, "720p")));
sizeMenu.add(new JMenuItem(new SizeAction(1920, 1080, "1080p"))); sizeMenu.add(new JMenuItem(new SizeAction(1920, 1080, "1080p")));
return menubar; return menubar;
} }
private class SizeAction extends AbstractAction { private class SizeAction extends AbstractAction {
private final int w, h; private final int w, h;
SizeAction(final int w, final int h, final String n) { SizeAction(final int w, final int h, final String n) {
super(w + " x " + h + " (" + n + ")"); super(w + " x " + h + " (" + n + ")");
this.w = w; this.w = w;
this.h = h; this.h = h;
} }
@Override @Override
public void actionPerformed(ActionEvent e) { public void actionPerformed(ActionEvent e) {
photoPanel.setPreferredSize(new Dimension(w, h)); photoPanel.setPreferredSize(new Dimension(w, h));
PhotoApp.this.pack(); PhotoFrame.this.pack();
} }
} }
public static void main(String args[]) throws Exception { public static void main(String args[]) throws Exception {
LoggingSystemSetup.setupLoggingAppender(); LoggingSystemSetup.setupLoggingAppender();
LoggingSystemSetup.addConsoleAppender(); LoggingSystemSetup.addConsoleAppender();
// Setup the uncaught exception handler // Setup the uncaught exception handler
log.info("Registering exception handler"); log.info("Registering exception handler");
SwingExceptionHandler exceptionHandler = new SwingExceptionHandler(); SwingExceptionHandler exceptionHandler = new SwingExceptionHandler();
Application.setExceptionHandler(exceptionHandler); Application.setExceptionHandler(exceptionHandler);
exceptionHandler.registerExceptionHandler(); exceptionHandler.registerExceptionHandler();
// Load motors etc. // Load motors etc.
log.info("Loading databases"); log.info("Loading databases");
GuiModule guiModule = new GuiModule(); GuiModule guiModule = new GuiModule();
Module pluginModule = new PluginModule(); Module pluginModule = new PluginModule();
Injector injector = Guice.createInjector(guiModule, pluginModule); Injector injector = Guice.createInjector(guiModule, pluginModule);
Application.setInjector(injector); Application.setInjector(injector);
guiModule.startLoader(); guiModule.startLoader();
// Set the best available look-and-feel // Set the best available look-and-feel
log.info("Setting best LAF"); log.info("Setting best LAF");
GUIUtil.setBestLAF(); GUIUtil.setBestLAF();
// Load defaults // Load defaults
((SwingPreferences) Application.getPreferences()).loadDefaultUnits(); ((SwingPreferences) Application.getPreferences()).loadDefaultUnits();
Databases.fakeMethod(); Databases.fakeMethod();
new PhotoApp(); PhotoFrame pa = new PhotoFrame(true);
pa.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
/* pa.setTitle("OpenRocket - Photo Studio Alpha");
if (true) { pa.setVisible(true);
Thread.sleep(1);
//String f = "C:\\Users\\bkuker\\git\\openrocket\\core\\resources\\datafiles\\examples\\Simulation Listeners.ork";
//String f = "C:\\Users\\bkuker\\git\\openrocket\\core\\resources\\datafiles\\examples\\High Power Airstart.ork";
String f = "C:\\Users\\bkuker\\git\\openrocket\\core\\resources\\datafiles\\examples\\A simple model rocket.ork";
//String f = "C:\\Users\\bkuker\\git\\openrocket\\core\\resources\\datafiles\\examples\\Clustered rocket design.ork";
//String f = "C:\\Users\\bkuker\\git\\openrocket\\core\\resources\\datafiles\\examples\\Boosted Dart.ork";
GeneralRocketLoader grl = new GeneralRocketLoader(new File(f));
OpenRocketDocument doc = grl.load();
pb.setDoc(doc);
}*/
} }
} }

View File

@ -34,6 +34,8 @@ import javax.swing.JPopupMenu;
import javax.swing.event.MouseInputAdapter; import javax.swing.event.MouseInputAdapter;
import net.sf.openrocket.document.OpenRocketDocument; import net.sf.openrocket.document.OpenRocketDocument;
import net.sf.openrocket.document.events.DocumentChangeEvent;
import net.sf.openrocket.document.events.DocumentChangeListener;
import net.sf.openrocket.gui.figure3d.RealisticRenderer; import net.sf.openrocket.gui.figure3d.RealisticRenderer;
import net.sf.openrocket.gui.figure3d.RocketRenderer; import net.sf.openrocket.gui.figure3d.RocketRenderer;
import net.sf.openrocket.gui.figure3d.TextureCache; import net.sf.openrocket.gui.figure3d.TextureCache;
@ -58,58 +60,78 @@ import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
public class PhotoPanel extends JPanel implements GLEventListener { public class PhotoPanel extends JPanel implements GLEventListener {
private static final long serialVersionUID = 1L; private static final long serialVersionUID = 1L;
private static final Logger log = LoggerFactory.getLogger(PhotoPanel.class); private static final Logger log = LoggerFactory.getLogger(PhotoPanel.class);
static { static {
//this allows the GL canvas and things like the motor selection // this allows the GL canvas and things like the motor selection
//drop down to z-order themselves. // drop down to z-order themselves.
JPopupMenu.setDefaultLightWeightPopupEnabled(false); JPopupMenu.setDefaultLightWeightPopupEnabled(false);
} }
private Configuration configuration; private Configuration configuration;
private Component canvas; private Component canvas;
private TextureCache textureCache = new TextureCache(); private TextureCache textureCache = new TextureCache();
private double ratio; private double ratio;
private boolean doCopy = false; private boolean doCopy = false;
private boolean needUpdate = false;
private RocketRenderer rr; private RocketRenderer rr;
private PhotoSettings p; private PhotoSettings p;
private Trackball trackball = new Trackball(); private Trackball trackball = new Trackball();
public void setDoc(final OpenRocketDocument doc) { void setDoc(final OpenRocketDocument doc) {
((GLAutoDrawable) canvas).invoke(true, new GLRunnable() { ((GLAutoDrawable) canvas).invoke(false, new GLRunnable() {
@Override @Override
public boolean run(GLAutoDrawable drawable) { public boolean run(final GLAutoDrawable drawable) {
PhotoPanel.this.configuration = doc.getDefaultConfiguration(); PhotoPanel.this.configuration = doc.getDefaultConfiguration();
cachedBounds = null; cachedBounds = null;
rr = new RealisticRenderer(doc); rr = new RealisticRenderer(doc);
rr.init(drawable); rr.init(drawable);
doc.getDefaultConfiguration().addChangeListener(new StateChangeListener() {
@Override
public void stateChanged(EventObject e) {
log.debug("Repainting on config state change");
needUpdate = true;
PhotoPanel.this.repaint();
}
});
doc.addDocumentChangeListener(new DocumentChangeListener() {
@Override
public void documentChanged(DocumentChangeEvent event) {
log.debug("Repainting on document change");
needUpdate = true;
PhotoPanel.this.repaint();
}
});
return false; return false;
} }
}); });
} }
public void doCopy() { void doCopy() {
doCopy = true; doCopy = true;
repaint(); repaint();
} }
public PhotoSettings getSettings() { PhotoSettings getSettings() {
return p; return p;
} }
public PhotoPanel() { PhotoPanel() {
this.setLayout(new BorderLayout()); this.setLayout(new BorderLayout());
p = new PhotoSettings(); p = new PhotoSettings();
//Fixes a linux / X bug: Splash must be closed before GL Init // Fixes a linux / X bug: Splash must be closed before GL Init
SplashScreen splash = Splash.getSplashScreen(); SplashScreen splash = Splash.getSplashScreen();
if (splash != null && splash.isVisible()) if (splash != null && splash.isVisible())
splash.close(); splash.close();
initGLCanvas(); initGLCanvas();
setupMouseListeners(); setupMouseListeners();
p.addChangeListener(new StateChangeListener() { p.addChangeListener(new StateChangeListener() {
@Override @Override
public void stateChanged(EventObject e) { public void stateChanged(EventObject e) {
@ -117,24 +139,23 @@ public class PhotoPanel extends JPanel implements GLEventListener {
PhotoPanel.this.repaint(); PhotoPanel.this.repaint();
} }
}); });
} }
private void initGLCanvas() { private void initGLCanvas() {
try { try {
log.debug("Setting up GL capabilities..."); log.debug("Setting up GL capabilities...");
final GLProfile glp = GLProfile.get(GLProfile.GL2); final GLProfile glp = GLProfile.get(GLProfile.GL2);
final GLCapabilities caps = new GLCapabilities(glp); final GLCapabilities caps = new GLCapabilities(glp);
if (Application.getPreferences().getBoolean(Preferences.OPENGL_ENABLE_AA, true)) { if (Application.getPreferences().getBoolean(Preferences.OPENGL_ENABLE_AA, true)) {
caps.setSampleBuffers(true); caps.setSampleBuffers(true);
caps.setNumSamples(6); caps.setNumSamples(6);
} else { } else {
log.trace("GL - Not enabling AA by user pref"); log.trace("GL - Not enabling AA by user pref");
} }
if (Application.getPreferences().getBoolean(Preferences.OPENGL_USE_FBO, false)) { if (Application.getPreferences().getBoolean(Preferences.OPENGL_USE_FBO, false)) {
log.trace("GL - Creating GLJPanel"); log.trace("GL - Creating GLJPanel");
canvas = new GLJPanel(caps); canvas = new GLJPanel(caps);
@ -142,41 +163,41 @@ public class PhotoPanel extends JPanel implements GLEventListener {
log.trace("GL - Creating GLCanvas"); log.trace("GL - Creating GLCanvas");
canvas = new GLCanvas(caps); canvas = new GLCanvas(caps);
} }
((GLAutoDrawable) canvas).addGLEventListener(this); ((GLAutoDrawable) canvas).addGLEventListener(this);
this.add(canvas, BorderLayout.CENTER); this.add(canvas, BorderLayout.CENTER);
} catch (Throwable t) { } catch (Throwable t) {
log.error("An error occurred creating 3d View", t); log.error("An error occurred creating 3d View", t);
canvas = null; canvas = null;
this.add(new JLabel("Unable to load 3d Libraries: " this.add(new JLabel("Unable to load 3d Libraries: " + t.getMessage()));
+ t.getMessage()));
} }
} }
private void setupMouseListeners() { private void setupMouseListeners() {
MouseInputAdapter a = new MouseInputAdapter() { MouseInputAdapter a = new MouseInputAdapter() {
int lastX; int lastX;
int lastY; int lastY;
MouseEvent pressEvent; MouseEvent pressEvent;
@Override @Override
public void mousePressed(final MouseEvent e) { public void mousePressed(final MouseEvent e) {
lastX = e.getX(); lastX = e.getX();
lastY = e.getY(); lastY = e.getY();
pressEvent = e; pressEvent = e;
} }
@Override @Override
public void mouseClicked(final MouseEvent e) { public void mouseClicked(final MouseEvent e) {
} }
@Override @Override
public void mouseDragged(final MouseEvent e) { public void mouseDragged(final MouseEvent e) {
//You can get a drag without a press while a modal dialog is shown // You can get a drag without a press while a modal dialog is
// shown
if (pressEvent == null) if (pressEvent == null)
return; return;
final double height = canvas.getHeight(); final double height = canvas.getHeight();
final double width = canvas.getWidth(); final double width = canvas.getWidth();
final double x1 = (width - 2 * lastX) / width; final double x1 = (width - 2 * lastX) / width;
@ -184,14 +205,14 @@ public class PhotoPanel extends JPanel implements GLEventListener {
final double x2 = (width - 2 * e.getX()) / width; final double x2 = (width - 2 * e.getX()) / width;
final double y2 = (2 * e.getY() - height) / height; final double y2 = (2 * e.getY() - height) / height;
trackball.swipe(x1, y1, x2, y2, p.getViewAz(), p.getViewAlt()); trackball.swipe(x1, y1, x2, y2, p.getViewAz(), p.getViewAlt());
p.setPitchYawRoll(trackball.getPitch(), trackball.getYaw(), trackball.getRoll()); p.setPitchYawRoll(trackball.getPitch(), trackball.getYaw(), trackball.getRoll());
lastX = e.getX(); lastX = e.getX();
lastY = e.getY(); lastY = e.getY();
} }
}; };
p.addChangeListener(new StateChangeListener() { p.addChangeListener(new StateChangeListener() {
@Override @Override
public void stateChanged(EventObject e) { public void stateChanged(EventObject e) {
@ -201,47 +222,49 @@ public class PhotoPanel extends JPanel implements GLEventListener {
canvas.addMouseMotionListener(a); canvas.addMouseMotionListener(a);
canvas.addMouseListener(a); canvas.addMouseListener(a);
} }
@Override @Override
public void repaint() { public void repaint() {
if (canvas != null) if (canvas != null)
((GLAutoDrawable) canvas).display(); ((GLAutoDrawable) canvas).display();
super.repaint(); super.repaint();
} }
@Override @Override
public void display(final GLAutoDrawable drawable) { public void display(final GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2(); GL2 gl = drawable.getGL().getGL2();
d(drawable, 0); if (needUpdate)
rr.updateFigure(drawable);
needUpdate = false;
draw(drawable, 0);
if (p.isMotionBlurred()) { if (p.isMotionBlurred()) {
Bounds b = calculateBounds(); Bounds b = calculateBounds();
float m = .6f; float m = .6f;
int c = 10; int c = 10;
float d = (float) b.xSize / 25.0f; float d = (float) b.xSize / 25.0f;
gl.glAccum(GL2.GL_LOAD, m); gl.glAccum(GL2.GL_LOAD, m);
for (int i = 1; i <= c; i++) { for (int i = 1; i <= c; i++) {
d(drawable, d / c * i); draw(drawable, d / c * i);
gl.glAccum(GL2.GL_ACCUM, (1.0f - m) / c); gl.glAccum(GL2.GL_ACCUM, (1.0f - m) / c);
} }
gl.glAccum(GL2.GL_RETURN, 1.0f); gl.glAccum(GL2.GL_RETURN, 1.0f);
} }
if (doCopy) { if (doCopy) {
copy(drawable); copy(drawable);
doCopy = false; doCopy = false;
} }
} }
protected static void convertColor(Color color, float[] out) { private static void convertColor(Color color, float[] out) {
if (color == null) { if (color == null) {
out[0] = 1; out[0] = 1;
out[1] = 1; out[1] = 1;
@ -252,47 +275,49 @@ public class PhotoPanel extends JPanel implements GLEventListener {
out[2] = (float) color.getBlue() / 255f; out[2] = (float) color.getBlue() / 255f;
} }
} }
public void d(final GLAutoDrawable drawable, float dx) { private void draw(final GLAutoDrawable drawable, float dx) {
GL2 gl = drawable.getGL().getGL2(); GL2 gl = drawable.getGL().getGL2();
GLU glu = new GLU(); GLU glu = new GLU();
float[] color = new float[3]; float[] color = new float[3];
gl.glEnable(GL.GL_MULTISAMPLE); gl.glEnable(GL.GL_MULTISAMPLE);
convertColor(p.getSunlight(), color); convertColor(p.getSunlight(), color);
float amb = (float) p.getAmbiance(); float amb = (float) p.getAmbiance();
float dif = 1.0f - amb; float dif = 1.0f - amb;
float spc = 1.0f; float spc = 1.0f;
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_AMBIENT, new float[] { amb * color[0], amb * color[1], amb * color[2], 1 }, 0); gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_AMBIENT, new float[] { amb * color[0], amb * color[1],
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_DIFFUSE, new float[] { dif * color[0], dif * color[1], dif * color[2], 1 }, 0); amb * color[2], 1 }, 0);
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_SPECULAR, new float[] { spc * color[0], spc * color[1], spc * color[2], 1 }, 0); gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_DIFFUSE, new float[] { dif * color[0], dif * color[1],
dif * color[2], 1 }, 0);
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_SPECULAR, new float[] { spc * color[0],
spc * color[1], spc * color[2], 1 }, 0);
convertColor(p.getSkyColor(), color); convertColor(p.getSkyColor(), color);
gl.glClearColor(color[0], color[1], color[2], 1); gl.glClearColor(color[0], color[1], color[2], 1);
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT); gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION); gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
gl.glLoadIdentity(); gl.glLoadIdentity();
glu.gluPerspective(p.getFov() * (180.0 / Math.PI), ratio, 0.1f, 50f); glu.gluPerspective(p.getFov() * (180.0 / Math.PI), ratio, 0.1f, 50f);
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
//Flip textures for LEFT handed coords // Flip textures for LEFT handed coords
gl.glMatrixMode(GL.GL_TEXTURE); gl.glMatrixMode(GL.GL_TEXTURE);
gl.glLoadIdentity(); gl.glLoadIdentity();
gl.glScaled(-1, 1, 1); gl.glScaled(-1, 1, 1);
gl.glTranslated(-1, 0, 0); gl.glTranslated(-1, 0, 0);
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW); gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
gl.glLoadIdentity(); gl.glLoadIdentity();
gl.glEnable(GL.GL_CULL_FACE); gl.glEnable(GL.GL_CULL_FACE);
gl.glCullFace(GL.GL_BACK); gl.glCullFace(GL.GL_BACK);
gl.glFrontFace(GL.GL_CCW); gl.glFrontFace(GL.GL_CCW);
//Draw the sky // Draw the sky
gl.glPushMatrix(); gl.glPushMatrix();
gl.glDisable(GLLightingFunc.GL_LIGHTING); gl.glDisable(GLLightingFunc.GL_LIGHTING);
gl.glDepthMask(false); gl.glDepthMask(false);
@ -305,63 +330,60 @@ public class PhotoPanel extends JPanel implements GLEventListener {
gl.glDepthMask(true); gl.glDepthMask(true);
gl.glEnable(GLLightingFunc.GL_LIGHTING); gl.glEnable(GLLightingFunc.GL_LIGHTING);
gl.glPopMatrix(); gl.glPopMatrix();
if (rr == null) if (rr == null)
return; return;
glu.gluLookAt(0, 0, p.getViewDistance(), 0, 0, 0, 0, 1, 0); glu.gluLookAt(0, 0, p.getViewDistance(), 0, 0, 0, 0, 1, 0);
gl.glRotated(p.getViewAlt() * (180.0 / Math.PI), 1, 0, 0); gl.glRotated(p.getViewAlt() * (180.0 / Math.PI), 1, 0, 0);
gl.glRotated(p.getViewAz() * (180.0 / Math.PI), 0, 1, 0); gl.glRotated(p.getViewAz() * (180.0 / Math.PI), 0, 1, 0);
float[] lightPosition = new float[] { float[] lightPosition = new float[] { (float) Math.cos(p.getLightAlt()) * (float) Math.sin(p.getLightAz()),//
(float) Math.cos(p.getLightAlt()) * (float) Math.sin(p.getLightAz()),//
(float) Math.sin(p.getLightAlt()),// (float) Math.sin(p.getLightAlt()),//
(float) Math.cos(p.getLightAlt()) * (float) Math.cos(p.getLightAz()), // (float) Math.cos(p.getLightAlt()) * (float) Math.cos(p.getLightAz()), //
0 0 };
};
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_POSITION, lightPosition, 0);
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_POSITION,
lightPosition, 0); // Change to LEFT Handed coordinates
//Change to LEFT Handed coordinates
gl.glScaled(1, 1, -1); gl.glScaled(1, 1, -1);
gl.glFrontFace(GL.GL_CW); gl.glFrontFace(GL.GL_CW);
setupModel(gl); setupModel(gl);
gl.glTranslated(dx - p.getAdvance(), 0, 0); gl.glTranslated(dx - p.getAdvance(), 0, 0);
if (p.isFlame()) { if (p.isFlame()) {
convertColor(p.getFlameColor(), color); convertColor(p.getFlameColor(), color);
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_AMBIENT, new float[] { 0, 0, 0, 1 }, 0); gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_AMBIENT, new float[] { 0, 0, 0, 1 }, 0);
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_DIFFUSE, new float[] { color[0], color[1], color[2], 1 }, 0); gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_DIFFUSE, new float[] { color[0], color[1],
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_SPECULAR, new float[] { color[0], color[1], color[2], 1 }, 0); color[2], 1 }, 0);
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_SPECULAR, new float[] { color[0], color[1],
color[2], 1 }, 0);
Bounds b = calculateBounds(); Bounds b = calculateBounds();
gl.glLightf(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_QUADRATIC_ATTENUATION, 20f); gl.glLightf(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_QUADRATIC_ATTENUATION, 20f);
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_POSITION, new float[] { (float) (b.xMax + .1f), 0, 0, 1 }, 0); gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_POSITION, new float[] { (float) (b.xMax + .1f), 0,
0, 1 }, 0);
gl.glEnable(GLLightingFunc.GL_LIGHT2); gl.glEnable(GLLightingFunc.GL_LIGHT2);
} else { } else {
gl.glDisable(GLLightingFunc.GL_LIGHT2); gl.glDisable(GLLightingFunc.GL_LIGHT2);
gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_DIFFUSE, new float[] { 0,0,0,1 }, 0); gl.glLightfv(GLLightingFunc.GL_LIGHT2, GLLightingFunc.GL_DIFFUSE, new float[] { 0, 0, 0, 1 }, 0);
} }
rr.render(drawable, configuration, new HashSet<RocketComponent>()); rr.render(drawable, configuration, new HashSet<RocketComponent>());
//glu.gluSphere(new GLUquadricImpl(gl, false), .2, 10, 10); // glu.gluSphere(new GLUquadricImpl(gl, false), .2, 10, 10);
String motorID = configuration.getFlightConfigurationID(); String motorID = configuration.getFlightConfigurationID();
Iterator<MotorMount> iterator = configuration.motorIterator(); Iterator<MotorMount> iterator = configuration.motorIterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
MotorMount mount = iterator.next(); MotorMount mount = iterator.next();
Motor motor = mount.getMotorConfiguration().get(motorID).getMotor(); Motor motor = mount.getMotorConfiguration().get(motorID).getMotor();
double length = motor.getLength(); double length = motor.getLength();
Coordinate[] position = ((RocketComponent) mount).toAbsolute(new Coordinate(((RocketComponent) mount) Coordinate[] position = ((RocketComponent) mount).toAbsolute(new Coordinate(((RocketComponent) mount)
.getLength() + mount.getMotorOverhang() - length)); .getLength() + mount.getMotorOverhang() - length));
for (int i = 0; i < position.length; i++) { for (int i = 0; i < position.length; i++) {
gl.glPushMatrix(); gl.glPushMatrix();
gl.glTranslated(position[i].x + motor.getLength(), position[i].y, position[i].z); gl.glTranslated(position[i].x + motor.getLength(), position[i].y, position[i].z);
@ -369,11 +391,11 @@ public class PhotoPanel extends JPanel implements GLEventListener {
gl.glPopMatrix(); gl.glPopMatrix();
} }
} }
gl.glDisable(GL.GL_BLEND); gl.glDisable(GL.GL_BLEND);
gl.glFrontFace(GL.GL_CCW); gl.glFrontFace(GL.GL_CCW);
} }
@Override @Override
public void dispose(final GLAutoDrawable drawable) { public void dispose(final GLAutoDrawable drawable) {
log.trace("GL - dispose() called"); log.trace("GL - dispose() called");
@ -381,32 +403,31 @@ public class PhotoPanel extends JPanel implements GLEventListener {
rr.dispose(drawable); rr.dispose(drawable);
textureCache.dispose(drawable); textureCache.dispose(drawable);
} }
@Override @Override
public void init(final GLAutoDrawable drawable) { public void init(final GLAutoDrawable drawable) {
log.trace("GL - init()"); log.trace("GL - init()");
drawable.setGL(new DebugGL2(drawable.getGL().getGL2())); drawable.setGL(new DebugGL2(drawable.getGL().getGL2()));
final GL2 gl = drawable.getGL().getGL2(); final GL2 gl = drawable.getGL().getGL2();
gl.glClearDepth(1.0f); // clear z-buffer to the farthest gl.glClearDepth(1.0f); // clear z-buffer to the farthest
gl.glDepthFunc(GL.GL_LESS); // the type of depth test to do gl.glDepthFunc(GL.GL_LESS); // the type of depth test to do
textureCache.init(drawable); textureCache.init(drawable);
//gl.glDisable(GLLightingFunc.GL_LIGHT1); // gl.glDisable(GLLightingFunc.GL_LIGHT1);
FlameRenderer.init(gl); FlameRenderer.init(gl);
} }
@Override @Override
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int w, final int h) { public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int w, final int h) {
log.trace("GL - reshape()"); log.trace("GL - reshape()");
ratio = (double) w / (double) h; ratio = (double) w / (double) h;
} }
@SuppressWarnings("unused") @SuppressWarnings("unused")
private static class Bounds { private static class Bounds {
double xMin, xMax, xSize; double xMin, xMax, xSize;
@ -414,9 +435,9 @@ public class PhotoPanel extends JPanel implements GLEventListener {
double zMin, zMax, zSize; double zMin, zMax, zSize;
double rMax; double rMax;
} }
private Bounds cachedBounds = null; private Bounds cachedBounds = null;
/** /**
* Calculates the bounds for the current configuration * Calculates the bounds for the current configuration
* *
@ -431,13 +452,13 @@ public class PhotoPanel extends JPanel implements GLEventListener {
for (Coordinate c : bounds) { for (Coordinate c : bounds) {
b.xMax = Math.max(b.xMax, c.x); b.xMax = Math.max(b.xMax, c.x);
b.xMin = Math.min(b.xMin, c.x); b.xMin = Math.min(b.xMin, c.x);
b.yMax = Math.max(b.yMax, c.y); b.yMax = Math.max(b.yMax, c.y);
b.yMin = Math.min(b.yMin, c.y); b.yMin = Math.min(b.yMin, c.y);
b.zMax = Math.max(b.zMax, c.z); b.zMax = Math.max(b.zMax, c.z);
b.zMin = Math.min(b.zMin, c.z); b.zMin = Math.min(b.zMin, c.z);
double r = MathUtil.hypot(c.y, c.z); double r = MathUtil.hypot(c.y, c.z);
b.rMax = Math.max(b.rMax, r); b.rMax = Math.max(b.rMax, r);
} }
@ -448,7 +469,7 @@ public class PhotoPanel extends JPanel implements GLEventListener {
return b; return b;
} }
} }
private void setupModel(final GL2 gl) { private void setupModel(final GL2 gl) {
// Get the bounds // Get the bounds
final Bounds b = calculateBounds(); final Bounds b = calculateBounds();
@ -458,32 +479,29 @@ public class PhotoPanel extends JPanel implements GLEventListener {
// Center the rocket in the view. // Center the rocket in the view.
gl.glTranslated(-b.xMin - b.xSize / 2.0, 0, 0); gl.glTranslated(-b.xMin - b.xSize / 2.0, 0, 0);
} }
private void copy(final GLAutoDrawable drawable) { private void copy(final GLAutoDrawable drawable) {
final BufferedImage image = (new AWTGLReadBufferUtil(GLProfile.get(GLProfile.GL2), false)) final BufferedImage image = (new AWTGLReadBufferUtil(GLProfile.get(GLProfile.GL2), false))
.readPixelsToBufferedImage(drawable.getGL(), 0, 0, drawable.getWidth(), drawable.getHeight(), true); .readPixelsToBufferedImage(drawable.getGL(), 0, 0, drawable.getWidth(), drawable.getHeight(), true);
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new Transferable() { Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new Transferable() {
@Override @Override
public Object getTransferData(DataFlavor flavor) public Object getTransferData(DataFlavor flavor) throws UnsupportedFlavorException, IOException {
throws UnsupportedFlavorException, IOException {
if (flavor.equals(DataFlavor.imageFlavor) && image != null) { if (flavor.equals(DataFlavor.imageFlavor) && image != null) {
return image; return image;
} } else {
else {
throw new UnsupportedFlavorException(flavor); throw new UnsupportedFlavorException(flavor);
} }
} }
@Override @Override
public DataFlavor[] getTransferDataFlavors() { public DataFlavor[] getTransferDataFlavors() {
DataFlavor[] flavors = new DataFlavor[1]; DataFlavor[] flavors = new DataFlavor[1];
flavors[0] = DataFlavor.imageFlavor; flavors[0] = DataFlavor.imageFlavor;
return flavors; return flavors;
} }
@Override @Override
public boolean isDataFlavorSupported(DataFlavor flavor) { public boolean isDataFlavorSupported(DataFlavor flavor) {
DataFlavor[] flavors = getTransferDataFlavors(); DataFlavor[] flavors = getTransferDataFlavors();
@ -492,10 +510,10 @@ public class PhotoPanel extends JPanel implements GLEventListener {
return true; return true;
} }
} }
return false; return false;
} }
}, null); }, null);
} }
} }