Photo-booth files copied to the split version of OR.
I HOPE I didn't miss anything!
BIN
swing/resources/datafiles/flame/c-color.png
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
swing/resources/datafiles/flame/c-normal.png
Normal file
After Width: | Height: | Size: 12 KiB |
BIN
swing/resources/datafiles/flame/smoke2.png
Normal file
After Width: | Height: | Size: 6.5 KiB |
25
swing/resources/datafiles/flame/smokeShader.glsl
Normal file
@ -0,0 +1,25 @@
|
||||
uniform sampler2D uNormal;
|
||||
uniform sampler2D uSmoke;
|
||||
|
||||
void main(void)
|
||||
{
|
||||
vec3 normal = 2.0 * texture2D (uNormal, gl_TexCoord[0].st).rgb - 1.0;
|
||||
normal = normalize (normal);
|
||||
|
||||
float lamberFactor = max (dot (gl_LightSource[1].position.xyz, normal), 0.0) ;
|
||||
|
||||
lamberFactor = lamberFactor * .6 + .4;
|
||||
|
||||
vec4 diffuseMaterial = texture2D (uSmoke, gl_TexCoord[0].st);
|
||||
diffuseMaterial.rgb = vec3(1);
|
||||
|
||||
vec4 diffuseLight = gl_LightSource[1].diffuse;
|
||||
vec4 ambientLight = gl_LightSource[1].ambient;
|
||||
|
||||
vec4 bump = vec4(lamberFactor,lamberFactor,lamberFactor,1);
|
||||
|
||||
vec4 light = diffuseLight * bump + ambientLight;
|
||||
|
||||
gl_FragColor = gl_Color * diffuseMaterial * light;
|
||||
|
||||
}
|
BIN
swing/resources/datafiles/sky/Meadow/negx.jpg
Normal file
After Width: | Height: | Size: 615 KiB |
BIN
swing/resources/datafiles/sky/Meadow/negy.jpg
Normal file
After Width: | Height: | Size: 784 KiB |
BIN
swing/resources/datafiles/sky/Meadow/negz.jpg
Normal file
After Width: | Height: | Size: 590 KiB |
BIN
swing/resources/datafiles/sky/Meadow/posx.jpg
Normal file
After Width: | Height: | Size: 531 KiB |
BIN
swing/resources/datafiles/sky/Meadow/posy.jpg
Normal file
After Width: | Height: | Size: 177 KiB |
BIN
swing/resources/datafiles/sky/Meadow/posz.jpg
Normal file
After Width: | Height: | Size: 517 KiB |
13
swing/resources/datafiles/sky/Meadow/readme.txt
Normal file
@ -0,0 +1,13 @@
|
||||
Author
|
||||
======
|
||||
|
||||
This is the work of Emil Persson, aka Humus.
|
||||
http://www.humus.name
|
||||
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
|
||||
This work is licensed under a Creative Commons Attribution 3.0 Unported License.
|
||||
http://creativecommons.org/licenses/by/3.0/
|
BIN
swing/resources/datafiles/sky/box/Down.jpg
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
swing/resources/datafiles/sky/box/East.jpg
Normal file
After Width: | Height: | Size: 46 KiB |
BIN
swing/resources/datafiles/sky/box/North.jpg
Normal file
After Width: | Height: | Size: 67 KiB |
BIN
swing/resources/datafiles/sky/box/South.jpg
Normal file
After Width: | Height: | Size: 39 KiB |
BIN
swing/resources/datafiles/sky/box/Up.jpg
Normal file
After Width: | Height: | Size: 21 KiB |
BIN
swing/resources/datafiles/sky/box/West.jpg
Normal file
After Width: | Height: | Size: 41 KiB |
BIN
swing/resources/datafiles/sky/cross1.jpg
Normal file
After Width: | Height: | Size: 627 KiB |
BIN
swing/resources/datafiles/sky/lake.png
Normal file
After Width: | Height: | Size: 1.5 MiB |
BIN
swing/resources/datafiles/sky/miramar/miramar_bk.jpg
Normal file
After Width: | Height: | Size: 60 KiB |
BIN
swing/resources/datafiles/sky/miramar/miramar_dn.jpg
Normal file
After Width: | Height: | Size: 17 KiB |
BIN
swing/resources/datafiles/sky/miramar/miramar_ft.jpg
Normal file
After Width: | Height: | Size: 56 KiB |
BIN
swing/resources/datafiles/sky/miramar/miramar_lf.jpg
Normal file
After Width: | Height: | Size: 48 KiB |
BIN
swing/resources/datafiles/sky/miramar/miramar_rt.jpg
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
swing/resources/datafiles/sky/miramar/miramar_up.jpg
Normal file
After Width: | Height: | Size: 31 KiB |
BIN
swing/resources/datafiles/sky/space.jpg
Normal file
After Width: | Height: | Size: 184 KiB |
@ -1,14 +1,9 @@
|
||||
package net.sf.openrocket.gui.figure3d;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
import javax.media.opengl.GL2;
|
||||
import javax.media.opengl.GL2ES1;
|
||||
import javax.media.opengl.GLAutoDrawable;
|
||||
import javax.media.opengl.GLProfile;
|
||||
import javax.media.opengl.fixedfunc.GLLightingFunc;
|
||||
import javax.media.opengl.fixedfunc.GLMatrixFunc;
|
||||
|
||||
@ -23,28 +18,24 @@ import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.util.Color;
|
||||
|
||||
import com.jogamp.opengl.util.texture.Texture;
|
||||
import com.jogamp.opengl.util.texture.TextureData;
|
||||
import com.jogamp.opengl.util.texture.TextureIO;
|
||||
|
||||
public class RealisticRenderer extends RocketRenderer {
|
||||
private final float[] colorClear = { 0, 0, 0, 0 };
|
||||
private final float[] colorWhite = { 1, 1, 1, 1 };
|
||||
private final float[] color = new float[4];
|
||||
|
||||
private Map<String, Texture> oldTexCache = new HashMap<String, Texture>();
|
||||
private Map<String, Texture> texCache = new HashMap<String, Texture>();
|
||||
private final TextureCache textures;
|
||||
private float anisotrophy = 0;
|
||||
|
||||
public RealisticRenderer(OpenRocketDocument document) {
|
||||
|
||||
textures = new TextureCache();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(GLAutoDrawable drawable) {
|
||||
super.init(drawable);
|
||||
|
||||
oldTexCache = new HashMap<String, Texture>();
|
||||
texCache = new HashMap<String, Texture>();
|
||||
textures.init(drawable);
|
||||
|
||||
GL2 gl = drawable.getGL().getGL2();
|
||||
|
||||
@ -73,15 +64,14 @@ public class RealisticRenderer extends RocketRenderer {
|
||||
@Override
|
||||
public void updateFigure(GLAutoDrawable drawable) {
|
||||
super.updateFigure(drawable);
|
||||
clearCaches(drawable.getGL().getGL2());
|
||||
textures.advanceCacheGeneration(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose(GLAutoDrawable drawable) {
|
||||
flushTextureCache(drawable);
|
||||
super.dispose(drawable);
|
||||
oldTexCache = null;
|
||||
texCache = null;
|
||||
textures.dispose(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -108,7 +98,7 @@ public class RealisticRenderer extends RocketRenderer {
|
||||
|
||||
private void render(GL2 gl, Geometry g, Appearance a, boolean decals, float alpha) {
|
||||
final Decal t = a.getTexture();
|
||||
final Texture tex = getTexture(t);
|
||||
final Texture tex = textures.getTexture(t);
|
||||
|
||||
gl.glLightModeli(GL2.GL_LIGHT_MODEL_COLOR_CONTROL, GL2.GL_SEPARATE_SPECULAR_COLOR);
|
||||
|
||||
@ -179,54 +169,9 @@ public class RealisticRenderer extends RocketRenderer {
|
||||
|
||||
@Override
|
||||
public void flushTextureCache(GLAutoDrawable drawable) {
|
||||
// Flush the cache twice to get rid of old images.
|
||||
clearCaches(drawable.getGL().getGL2());
|
||||
clearCaches(drawable.getGL().getGL2());
|
||||
textures.flushTextureCache(drawable);
|
||||
}
|
||||
|
||||
private void clearCaches(GL2 gl) {
|
||||
log.debug("ClearCaches");
|
||||
for (Map.Entry<String, Texture> e : oldTexCache.entrySet()) {
|
||||
log.debug("Destroying Texture for " + e.getKey());
|
||||
if (e.getValue() != null)
|
||||
e.getValue().destroy(gl);
|
||||
}
|
||||
oldTexCache = texCache;
|
||||
texCache = new HashMap<String, Texture>();
|
||||
}
|
||||
|
||||
private Texture getTexture(Decal t) {
|
||||
if (t == null)
|
||||
return null;
|
||||
|
||||
String imageName = t.getImage().getName();
|
||||
|
||||
// Return the Cached value if available
|
||||
if (texCache.containsKey(imageName))
|
||||
return texCache.get(imageName);
|
||||
|
||||
// If the texture is in the Old Cache, save it.
|
||||
if (oldTexCache.containsKey(imageName)) {
|
||||
texCache.put(imageName, oldTexCache.get(imageName));
|
||||
oldTexCache.remove(imageName);
|
||||
return texCache.get(imageName);
|
||||
}
|
||||
|
||||
// Otherwise load it.
|
||||
Texture tex = null;
|
||||
try {
|
||||
log.debug("Loading texture " + t);
|
||||
InputStream is = t.getImage().getBytes();
|
||||
TextureData data = TextureIO.newTextureData(GLProfile.getDefault(), is, GL.GL_RGBA, GL.GL_RGBA, true, null);
|
||||
tex = TextureIO.newTexture(data);
|
||||
} catch (Throwable e) {
|
||||
log.error("Error loading Texture", e);
|
||||
}
|
||||
texCache.put(imageName, tex);
|
||||
|
||||
return tex;
|
||||
|
||||
}
|
||||
|
||||
protected Appearance getAppearance(RocketComponent c) {
|
||||
Appearance ret = c.getAppearance();
|
||||
|
131
swing/src/net/sf/openrocket/gui/figure3d/TextureCache.java
Normal file
@ -0,0 +1,131 @@
|
||||
package net.sf.openrocket.gui.figure3d;
|
||||
|
||||
import java.io.InputStream;
|
||||
import java.net.URL;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
import javax.media.opengl.GLAutoDrawable;
|
||||
import javax.media.opengl.GLProfile;
|
||||
|
||||
import net.sf.openrocket.appearance.Decal;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jogamp.opengl.util.texture.Texture;
|
||||
import com.jogamp.opengl.util.texture.TextureData;
|
||||
import com.jogamp.opengl.util.texture.TextureIO;
|
||||
|
||||
public class TextureCache {
|
||||
private static final Logger log = LoggerFactory.getLogger(TextureCache.class);
|
||||
|
||||
private Map<String, Texture> oldTexCache = null;
|
||||
private Map<String, Texture> texCache = null;
|
||||
|
||||
public void init(GLAutoDrawable drawable) {
|
||||
if (texCache != null)
|
||||
throw new IllegalStateException(this + " already initialized.");
|
||||
oldTexCache = new HashMap<String, Texture>();
|
||||
texCache = new HashMap<String, Texture>();
|
||||
}
|
||||
|
||||
public void dispose(GLAutoDrawable drawable) {
|
||||
if (texCache == null)
|
||||
throw new IllegalStateException(this + " not initialized.");
|
||||
flushTextureCache(drawable);
|
||||
oldTexCache = null;
|
||||
texCache = null;
|
||||
}
|
||||
|
||||
public void flushTextureCache(GLAutoDrawable drawable) {
|
||||
advanceCacheGeneration(drawable);
|
||||
advanceCacheGeneration(drawable);
|
||||
}
|
||||
|
||||
public void advanceCacheGeneration(GLAutoDrawable drawable) {
|
||||
if (texCache == null)
|
||||
throw new IllegalStateException(this + " not initialized.");
|
||||
|
||||
log.debug("ClearCaches");
|
||||
for (Map.Entry<String, Texture> e : oldTexCache.entrySet()) {
|
||||
log.debug("Destroying Texture for " + e.getKey());
|
||||
if (e.getValue() != null)
|
||||
e.getValue().destroy(drawable.getGL().getGL2());
|
||||
}
|
||||
oldTexCache = texCache;
|
||||
texCache = new HashMap<String, Texture>();
|
||||
}
|
||||
|
||||
public Texture getTexture(URL uri) {
|
||||
if (texCache == null)
|
||||
throw new IllegalStateException(this + " not initialized.");
|
||||
|
||||
if (uri == null)
|
||||
return null;
|
||||
|
||||
String imageName = uri.toString();
|
||||
|
||||
// Return the Cached value if available
|
||||
if (texCache.containsKey(imageName))
|
||||
return texCache.get(imageName);
|
||||
|
||||
// If the texture is in the Old Cache, save it.
|
||||
if (oldTexCache.containsKey(imageName)) {
|
||||
texCache.put(imageName, oldTexCache.get(imageName));
|
||||
oldTexCache.remove(imageName);
|
||||
return texCache.get(imageName);
|
||||
}
|
||||
|
||||
// Otherwise load it.
|
||||
Texture tex = null;
|
||||
try {
|
||||
log.debug("Loading texture " + uri);
|
||||
InputStream is = uri.openStream();
|
||||
TextureData data = TextureIO.newTextureData(GLProfile.getDefault(), is, GL.GL_RGBA, GL.GL_RGBA, true, null);
|
||||
tex = TextureIO.newTexture(data);
|
||||
} catch (Throwable e) {
|
||||
log.error("Error loading Texture", e);
|
||||
}
|
||||
texCache.put(imageName, tex);
|
||||
|
||||
return tex;
|
||||
}
|
||||
|
||||
public Texture getTexture(Decal decal) {
|
||||
if (texCache == null)
|
||||
throw new IllegalStateException(this + " not initialized.");
|
||||
|
||||
if (decal == null)
|
||||
return null;
|
||||
|
||||
String imageName = decal.getImage().getName();
|
||||
|
||||
// Return the Cached value if available
|
||||
if (texCache.containsKey(imageName))
|
||||
return texCache.get(imageName);
|
||||
|
||||
// If the texture is in the Old Cache, save it.
|
||||
if (oldTexCache.containsKey(imageName)) {
|
||||
texCache.put(imageName, oldTexCache.get(imageName));
|
||||
oldTexCache.remove(imageName);
|
||||
return texCache.get(imageName);
|
||||
}
|
||||
|
||||
// Otherwise load it.
|
||||
Texture tex = null;
|
||||
try {
|
||||
log.debug("Loading texture " + decal);
|
||||
InputStream is = decal.getImage().getBytes();
|
||||
TextureData data = TextureIO.newTextureData(GLProfile.getDefault(), is, GL.GL_RGBA, GL.GL_RGBA, true, null);
|
||||
tex = TextureIO.newTexture(data);
|
||||
} catch (Throwable e) {
|
||||
log.error("Error loading Texture", e);
|
||||
}
|
||||
texCache.put(imageName, tex);
|
||||
|
||||
return tex;
|
||||
|
||||
}
|
||||
}
|
@ -312,7 +312,7 @@ public class ComponentRenderer {
|
||||
final double da = (2.0f * Math.PI) / LOD;
|
||||
final double dt = 1.0 / LOD;
|
||||
gl.glBegin(GL.GL_TRIANGLE_STRIP);
|
||||
gl.glNormal3d(0, 0, 1);
|
||||
gl.glNormal3d(0, 0, -1);
|
||||
for (int i = 0; i < LOD + 1; i++) {
|
||||
gl.glTexCoord2d(i * dt, .875);
|
||||
gl.glVertex3d(r * Math.cos(da * i), r * Math.sin(da * i), 0);
|
||||
@ -323,7 +323,7 @@ public class ComponentRenderer {
|
||||
gl.glBegin(GL.GL_TRIANGLE_STRIP);
|
||||
|
||||
for (int i = 0; i < LOD + 1; i++) {
|
||||
gl.glNormal3d(-Math.cos(da * i), -Math.sin(da * i), 1);
|
||||
gl.glNormal3d(-Math.cos(da * i), -Math.sin(da * i), -1);
|
||||
gl.glTexCoord2d(i * dt, .9);
|
||||
gl.glVertex3d(.8 * r * Math.cos(da * i), .8 * r * Math.sin(da * i), 0);
|
||||
gl.glTexCoord2d(i * dt, 1);
|
||||
|
@ -114,13 +114,11 @@
|
||||
*/
|
||||
package net.sf.openrocket.gui.figure3d.geometry;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
import javax.media.opengl.GL2;
|
||||
|
||||
import net.sf.openrocket.rocketcomponent.Transition;
|
||||
|
||||
final class TransitionRenderer {
|
||||
private static final boolean textureFlag = true;
|
||||
|
||||
private TransitionRenderer() {
|
||||
}
|
||||
@ -132,7 +130,7 @@ final class TransitionRenderer {
|
||||
double x, y, z, nz, lnz = 0;
|
||||
int i;
|
||||
|
||||
da = 2.0f * PI / slices;
|
||||
da = 2.0f * Math.PI / slices;
|
||||
dzBase = (double) tr.getLength() / stacks;
|
||||
|
||||
double ds = 1.0f / slices;
|
||||
@ -148,19 +146,18 @@ final class TransitionRenderer {
|
||||
r = Math.max(0, tr.getRadius(z) + offsetRadius);
|
||||
double rNext = Math.max(0, tr.getRadius(zNext) + offsetRadius);
|
||||
|
||||
|
||||
// Z component of normal vectors
|
||||
nz = (r - rNext) / dz;
|
||||
|
||||
double s = 0.0f;
|
||||
glBegin(gl, GL2.GL_QUAD_STRIP);
|
||||
gl.glBegin(GL2.GL_QUAD_STRIP);
|
||||
for (i = 0; i <= slices; i++) {
|
||||
if (i == slices) {
|
||||
x = sin(0.0f);
|
||||
y = cos(0.0f);
|
||||
x = Math.sin(0.0f);
|
||||
y = Math.cos(0.0f);
|
||||
} else {
|
||||
x = sin((i * da));
|
||||
y = cos((i * da));
|
||||
x = Math.sin((i * da));
|
||||
y = Math.cos((i * da));
|
||||
}
|
||||
|
||||
if (r == 0) {
|
||||
@ -180,77 +177,31 @@ final class TransitionRenderer {
|
||||
} else {
|
||||
normal3d(gl, x, y, lnz);
|
||||
}
|
||||
TXTR_COORD(gl, s, z / tr.getLength());
|
||||
glVertex3d(gl, (x * r), (y * r), z);
|
||||
gl.glTexCoord2d(s, z / tr.getLength());
|
||||
gl.glVertex3d((x * r), (y * r), z);
|
||||
|
||||
normal3d(gl, x, y, nz);
|
||||
TXTR_COORD(gl, s, zNext / tr.getLength());
|
||||
glVertex3d(gl, (x * rNext), (y * rNext), zNext);
|
||||
gl.glTexCoord2d(s, zNext / tr.getLength());
|
||||
gl.glVertex3d((x * rNext), (y * rNext), zNext);
|
||||
|
||||
s += ds;
|
||||
} // for slices
|
||||
glEnd(gl);
|
||||
gl.glEnd();
|
||||
lnz = nz;
|
||||
z = Math.min(z + dz, tr.getLength());
|
||||
} // for stacks
|
||||
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------------
|
||||
// Internals only below this point
|
||||
//
|
||||
|
||||
private static final double PI = (double) Math.PI;
|
||||
|
||||
private static final void glBegin(GL gl, int mode) {
|
||||
gl.getGL2().glBegin(mode);
|
||||
}
|
||||
|
||||
private static final void glEnd(GL gl) {
|
||||
gl.getGL2().glEnd();
|
||||
}
|
||||
|
||||
private static final void glVertex3d(GL gl, double x, double y, double z) {
|
||||
gl.getGL2().glVertex3d(x, y, z);
|
||||
}
|
||||
|
||||
private static final void glNormal3d(GL gl, double x, double y, double z) {
|
||||
gl.getGL2().glNormal3d(x, y, z);
|
||||
}
|
||||
|
||||
private static final void glTexCoord2d(GL gl, double x, double y) {
|
||||
gl.getGL2().glTexCoord2d(x, y);
|
||||
}
|
||||
|
||||
/**
|
||||
* Call glNormal3f after scaling normal to unit length.
|
||||
*
|
||||
* @param x
|
||||
* @param y
|
||||
* @param z
|
||||
*/
|
||||
private static final void normal3d(GL gl, double x, double y, double z) {
|
||||
static final void normal3d(GL2 gl, double x, double y, double z) {
|
||||
double mag;
|
||||
|
||||
mag = (double) Math.sqrt(x * x + y * y + z * z);
|
||||
if (mag > 0.00001F) {
|
||||
x /= mag;
|
||||
y /= mag;
|
||||
z /= mag;
|
||||
}
|
||||
glNormal3d(gl, x, y, z);
|
||||
gl.glNormal3d(x, y, z);
|
||||
}
|
||||
|
||||
private static final void TXTR_COORD(GL gl, double x, double y) {
|
||||
if (textureFlag)
|
||||
glTexCoord2d(gl, x, y);
|
||||
}
|
||||
|
||||
private static final double sin(double r) {
|
||||
return (double) Math.sin(r);
|
||||
}
|
||||
|
||||
private static final double cos(double r) {
|
||||
return (double) Math.cos(r);
|
||||
}
|
||||
}
|
||||
|
242
swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoApp.java
Normal file
@ -0,0 +1,242 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo;
|
||||
|
||||
import java.awt.Dimension;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.awt.event.KeyEvent;
|
||||
import java.io.File;
|
||||
|
||||
import javax.swing.AbstractAction;
|
||||
import javax.swing.Action;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JFileChooser;
|
||||
import javax.swing.JFrame;
|
||||
import javax.swing.JMenu;
|
||||
import javax.swing.JMenuBar;
|
||||
import javax.swing.JMenuItem;
|
||||
import javax.swing.KeyStroke;
|
||||
|
||||
import net.sf.openrocket.database.Databases;
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.file.GeneralRocketLoader;
|
||||
import net.sf.openrocket.file.RocketLoadException;
|
||||
import net.sf.openrocket.gui.main.SwingExceptionHandler;
|
||||
import net.sf.openrocket.gui.util.FileHelper;
|
||||
import net.sf.openrocket.gui.util.GUIUtil;
|
||||
import net.sf.openrocket.gui.util.Icons;
|
||||
import net.sf.openrocket.gui.util.SwingPreferences;
|
||||
import net.sf.openrocket.l10n.Translator;
|
||||
import net.sf.openrocket.logging.LoggingSystemSetup;
|
||||
import net.sf.openrocket.logging.Markers;
|
||||
import net.sf.openrocket.plugin.PluginModule;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.startup.GuiModule;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Module;
|
||||
|
||||
public class PhotoApp extends JFrame {
|
||||
private static final Logger log = LoggerFactory.getLogger(PhotoApp.class);
|
||||
private final int SHORTCUT_KEY = Toolkit.getDefaultToolkit().getMenuShortcutKeyMask();
|
||||
private final Translator trans = Application.getTranslator();
|
||||
|
||||
private PhotoPanel photoPanel;
|
||||
private JDialog settings;
|
||||
|
||||
public PhotoApp() {
|
||||
setSize(1024, 768);
|
||||
this.setMinimumSize(new Dimension(160, 150));
|
||||
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
|
||||
|
||||
photoPanel = new PhotoPanel();
|
||||
setJMenuBar(getMenu());
|
||||
setContentPane(photoPanel);
|
||||
|
||||
GUIUtil.rememberWindowSize(this);
|
||||
this.setLocationByPlatform(true);
|
||||
GUIUtil.setWindowIcons(this);
|
||||
|
||||
setTitle("OpenRocket - Photo Studio Alpha");
|
||||
|
||||
setVisible(true);
|
||||
|
||||
settings = new JDialog(this, "Settings") {
|
||||
{
|
||||
setContentPane(new PhotoSettingsConfig(photoPanel.getSettings()));
|
||||
pack();
|
||||
this.setLocationByPlatform(true);
|
||||
setVisible(true);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
JMenuBar getMenu() {
|
||||
JMenuBar menubar = new JMenuBar();
|
||||
JMenu menu;
|
||||
JMenuItem item;
|
||||
|
||||
//// File
|
||||
menu = new JMenu(trans.get("main.menu.file"));
|
||||
menu.setMnemonic(KeyEvent.VK_F);
|
||||
//// File-handling related tasks
|
||||
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));
|
||||
//// Open a rocket design
|
||||
item.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.item.Openrocketdesign"));
|
||||
item.setIcon(Icons.FILE_OPEN);
|
||||
item.addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
log.info(Markers.USER_MARKER, "Open... selected");
|
||||
|
||||
JFileChooser chooser = new JFileChooser();
|
||||
|
||||
chooser.addChoosableFileFilter(FileHelper.ALL_DESIGNS_FILTER);
|
||||
chooser.addChoosableFileFilter(FileHelper.OPENROCKET_DESIGN_FILTER);
|
||||
chooser.addChoosableFileFilter(FileHelper.ROCKSIM_DESIGN_FILTER);
|
||||
chooser.setFileFilter(FileHelper.ALL_DESIGNS_FILTER);
|
||||
|
||||
chooser.setFileSelectionMode(JFileChooser.FILES_ONLY);
|
||||
|
||||
chooser.setCurrentDirectory(((SwingPreferences) Application.getPreferences()).getDefaultDirectory());
|
||||
int option = chooser.showOpenDialog(PhotoApp.this);
|
||||
if (option == JFileChooser.APPROVE_OPTION) {
|
||||
File file = chooser.getSelectedFile();
|
||||
log.debug("Opening File " + file.getAbsolutePath());
|
||||
GeneralRocketLoader grl = new GeneralRocketLoader(file);
|
||||
try {
|
||||
OpenRocketDocument doc = grl.load();
|
||||
photoPanel.setDoc(doc);
|
||||
} catch (RocketLoadException e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
menu.add(item);
|
||||
|
||||
//// Edit
|
||||
menu = new JMenu(trans.get("main.menu.edit"));
|
||||
menu.setMnemonic(KeyEvent.VK_E);
|
||||
//// Rocket editing
|
||||
menu.getAccessibleContext().setAccessibleDescription(trans.get("BasicFrame.menu.Rocketedt"));
|
||||
menubar.add(menu);
|
||||
|
||||
|
||||
Action action = new AbstractAction("Copy") {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
photoPanel.doCopy();
|
||||
}
|
||||
};
|
||||
item = new JMenuItem(action);
|
||||
item.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_C, SHORTCUT_KEY));
|
||||
item.setMnemonic(KeyEvent.VK_C);
|
||||
item.getAccessibleContext().setAccessibleDescription("Copy image to clipboard");
|
||||
menu.add(item);
|
||||
|
||||
menu.add(new JMenuItem(new AbstractAction("Photo Settings") {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
settings.setVisible(true);
|
||||
}
|
||||
}));
|
||||
|
||||
//Window
|
||||
menu = new JMenu("Window");
|
||||
menubar.add(menu);
|
||||
JMenu sizeMenu = new JMenu("Size");
|
||||
menu.add(sizeMenu);
|
||||
|
||||
sizeMenu.add(new JMenuItem(new SizeAction(320, 240, "QVGA")));
|
||||
sizeMenu.add(new JMenuItem(new SizeAction(640, 480, "VGA")));
|
||||
sizeMenu.add(new JMenuItem(new SizeAction(1024, 768, "XGA")));
|
||||
|
||||
sizeMenu.addSeparator();
|
||||
|
||||
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(768, 1024, "XGA Portrait")));
|
||||
|
||||
sizeMenu.addSeparator();
|
||||
|
||||
sizeMenu.add(new JMenuItem(new SizeAction(854, 480, "420p")));
|
||||
sizeMenu.add(new JMenuItem(new SizeAction(1280, 720, "720p")));
|
||||
sizeMenu.add(new JMenuItem(new SizeAction(1920, 1080, "1080p")));
|
||||
|
||||
return menubar;
|
||||
}
|
||||
|
||||
private class SizeAction extends AbstractAction {
|
||||
private final int w, h;
|
||||
|
||||
SizeAction(final int w, final int h, final String n) {
|
||||
super(w + " x " + h + " (" + n + ")");
|
||||
this.w = w;
|
||||
this.h = h;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
photoPanel.setPreferredSize(new Dimension(w, h));
|
||||
PhotoApp.this.pack();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static void main(String args[]) throws Exception {
|
||||
|
||||
LoggingSystemSetup.setupLoggingAppender();
|
||||
LoggingSystemSetup.addConsoleAppender();
|
||||
|
||||
// Setup the uncaught exception handler
|
||||
log.info("Registering exception handler");
|
||||
SwingExceptionHandler exceptionHandler = new SwingExceptionHandler();
|
||||
Application.setExceptionHandler(exceptionHandler);
|
||||
exceptionHandler.registerExceptionHandler();
|
||||
|
||||
// Load motors etc.
|
||||
log.info("Loading databases");
|
||||
|
||||
GuiModule guiModule = new GuiModule();
|
||||
Module pluginModule = new PluginModule();
|
||||
Injector injector = Guice.createInjector(guiModule, pluginModule);
|
||||
Application.setInjector(injector);
|
||||
|
||||
guiModule.startLoader();
|
||||
|
||||
// Set the best available look-and-feel
|
||||
log.info("Setting best LAF");
|
||||
GUIUtil.setBestLAF();
|
||||
|
||||
// Load defaults
|
||||
((SwingPreferences) Application.getPreferences()).loadDefaultUnits();
|
||||
|
||||
Databases.fakeMethod();
|
||||
|
||||
new PhotoApp();
|
||||
|
||||
/*
|
||||
if (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);
|
||||
}*/
|
||||
}
|
||||
|
||||
}
|
500
swing/src/net/sf/openrocket/gui/figure3d/photo/PhotoPanel.java
Normal file
@ -0,0 +1,500 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo;
|
||||
|
||||
import java.awt.BorderLayout;
|
||||
import java.awt.Component;
|
||||
import java.awt.SplashScreen;
|
||||
import java.awt.Toolkit;
|
||||
import java.awt.datatransfer.DataFlavor;
|
||||
import java.awt.datatransfer.Transferable;
|
||||
import java.awt.datatransfer.UnsupportedFlavorException;
|
||||
import java.awt.event.MouseEvent;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.EventObject;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
|
||||
import javax.media.opengl.DebugGL2;
|
||||
import javax.media.opengl.GL;
|
||||
import javax.media.opengl.GL2;
|
||||
import javax.media.opengl.GLAutoDrawable;
|
||||
import javax.media.opengl.GLCapabilities;
|
||||
import javax.media.opengl.GLEventListener;
|
||||
import javax.media.opengl.GLProfile;
|
||||
import javax.media.opengl.GLRunnable;
|
||||
import javax.media.opengl.awt.GLCanvas;
|
||||
import javax.media.opengl.awt.GLJPanel;
|
||||
import javax.media.opengl.fixedfunc.GLLightingFunc;
|
||||
import javax.media.opengl.fixedfunc.GLMatrixFunc;
|
||||
import javax.media.opengl.glu.GLU;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JPopupMenu;
|
||||
import javax.swing.event.MouseInputAdapter;
|
||||
|
||||
import net.sf.openrocket.document.OpenRocketDocument;
|
||||
import net.sf.openrocket.gui.figure3d.RealisticRenderer;
|
||||
import net.sf.openrocket.gui.figure3d.RocketRenderer;
|
||||
import net.sf.openrocket.gui.figure3d.TextureCache;
|
||||
import net.sf.openrocket.gui.figure3d.photo.exhaust.FlameRenderer;
|
||||
import net.sf.openrocket.gui.main.Splash;
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
import net.sf.openrocket.rocketcomponent.Configuration;
|
||||
import net.sf.openrocket.rocketcomponent.MotorMount;
|
||||
import net.sf.openrocket.rocketcomponent.RocketComponent;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.startup.Preferences;
|
||||
import net.sf.openrocket.util.Color;
|
||||
import net.sf.openrocket.util.Coordinate;
|
||||
import net.sf.openrocket.util.MathUtil;
|
||||
import net.sf.openrocket.util.StateChangeListener;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jogamp.opengl.util.awt.AWTGLReadBufferUtil;
|
||||
|
||||
public class PhotoPanel extends JPanel implements GLEventListener {
|
||||
private static final long serialVersionUID = 1L;
|
||||
private static final Logger log = LoggerFactory.getLogger(PhotoPanel.class);
|
||||
|
||||
static {
|
||||
//this allows the GL canvas and things like the motor selection
|
||||
//drop down to z-order themselves.
|
||||
JPopupMenu.setDefaultLightWeightPopupEnabled(false);
|
||||
}
|
||||
|
||||
private Configuration configuration;
|
||||
private Component canvas;
|
||||
private TextureCache textureCache = new TextureCache();
|
||||
private double ratio;
|
||||
private boolean doCopy = false;
|
||||
|
||||
private RocketRenderer rr;
|
||||
private PhotoSettings p;
|
||||
private Trackball trackball = new Trackball();
|
||||
|
||||
public void setDoc(final OpenRocketDocument doc) {
|
||||
((GLAutoDrawable) canvas).invoke(true, new GLRunnable() {
|
||||
@Override
|
||||
public boolean run(GLAutoDrawable drawable) {
|
||||
PhotoPanel.this.configuration = doc.getDefaultConfiguration();
|
||||
cachedBounds = null;
|
||||
rr = new RealisticRenderer(doc);
|
||||
rr.init(drawable);
|
||||
return false;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void doCopy() {
|
||||
doCopy = true;
|
||||
repaint();
|
||||
}
|
||||
|
||||
public PhotoSettings getSettings() {
|
||||
return p;
|
||||
}
|
||||
|
||||
public PhotoPanel() {
|
||||
this.setLayout(new BorderLayout());
|
||||
|
||||
p = new PhotoSettings();
|
||||
|
||||
//Fixes a linux / X bug: Splash must be closed before GL Init
|
||||
SplashScreen splash = Splash.getSplashScreen();
|
||||
if (splash != null && splash.isVisible())
|
||||
splash.close();
|
||||
|
||||
initGLCanvas();
|
||||
setupMouseListeners();
|
||||
|
||||
p.addChangeListener(new StateChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(EventObject e) {
|
||||
log.debug("Repainting on settings state change");
|
||||
PhotoPanel.this.repaint();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void initGLCanvas() {
|
||||
try {
|
||||
log.debug("Setting up GL capabilities...");
|
||||
final GLProfile glp = GLProfile.get(GLProfile.GL2);
|
||||
|
||||
final GLCapabilities caps = new GLCapabilities(glp);
|
||||
|
||||
|
||||
if (Application.getPreferences().getBoolean(Preferences.OPENGL_ENABLE_AA, true)) {
|
||||
caps.setSampleBuffers(true);
|
||||
caps.setNumSamples(6);
|
||||
} else {
|
||||
log.trace("GL - Not enabling AA by user pref");
|
||||
}
|
||||
|
||||
if (Application.getPreferences().getBoolean(Preferences.OPENGL_USE_FBO, false)) {
|
||||
log.trace("GL - Creating GLJPanel");
|
||||
canvas = new GLJPanel(caps);
|
||||
} else {
|
||||
log.trace("GL - Creating GLCanvas");
|
||||
canvas = new GLCanvas(caps);
|
||||
}
|
||||
|
||||
((GLAutoDrawable) canvas).addGLEventListener(this);
|
||||
this.add(canvas, BorderLayout.CENTER);
|
||||
} catch (Throwable t) {
|
||||
log.error("An error occurred creating 3d View", t);
|
||||
canvas = null;
|
||||
this.add(new JLabel("Unable to load 3d Libraries: "
|
||||
+ t.getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
private void setupMouseListeners() {
|
||||
MouseInputAdapter a = new MouseInputAdapter() {
|
||||
int lastX;
|
||||
int lastY;
|
||||
MouseEvent pressEvent;
|
||||
|
||||
@Override
|
||||
public void mousePressed(final MouseEvent e) {
|
||||
lastX = e.getX();
|
||||
lastY = e.getY();
|
||||
pressEvent = e;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseClicked(final MouseEvent e) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mouseDragged(final MouseEvent e) {
|
||||
//You can get a drag without a press while a modal dialog is shown
|
||||
if (pressEvent == null)
|
||||
return;
|
||||
|
||||
final double height = canvas.getHeight();
|
||||
final double width = canvas.getWidth();
|
||||
final double x1 = (width - 2 * lastX) / width;
|
||||
final double y1 = (2 * lastY - height) / height;
|
||||
final double x2 = (width - 2 * e.getX()) / width;
|
||||
final double y2 = (2 * e.getY() - height) / height;
|
||||
trackball.swipe(x1, y1, x2, y2, p.getViewAz(), p.getViewAlt());
|
||||
|
||||
p.setPitchYawRoll(trackball.getPitch(), trackball.getYaw(), trackball.getRoll());
|
||||
|
||||
lastX = e.getX();
|
||||
lastY = e.getY();
|
||||
}
|
||||
};
|
||||
|
||||
p.addChangeListener(new StateChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(EventObject e) {
|
||||
trackball.setPitchYawRoll(p.getPitch(), p.getYaw(), p.getRoll());
|
||||
}
|
||||
});
|
||||
canvas.addMouseMotionListener(a);
|
||||
canvas.addMouseListener(a);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void repaint() {
|
||||
if (canvas != null)
|
||||
((GLAutoDrawable) canvas).display();
|
||||
super.repaint();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void display(final GLAutoDrawable drawable) {
|
||||
GL2 gl = drawable.getGL().getGL2();
|
||||
|
||||
d(drawable, 0);
|
||||
|
||||
if (p.isMotionBlurred()) {
|
||||
Bounds b = calculateBounds();
|
||||
|
||||
float m = .6f;
|
||||
int c = 10;
|
||||
float d = (float) b.xSize / 25.0f;
|
||||
|
||||
gl.glAccum(GL2.GL_LOAD, m);
|
||||
|
||||
for (int i = 1; i <= c; i++) {
|
||||
d(drawable, d / c * i);
|
||||
gl.glAccum(GL2.GL_ACCUM, (1.0f - m) / c);
|
||||
}
|
||||
|
||||
gl.glAccum(GL2.GL_RETURN, 1.0f);
|
||||
}
|
||||
|
||||
|
||||
if (doCopy) {
|
||||
copy(drawable);
|
||||
doCopy = false;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
protected static void convertColor(Color color, float[] out) {
|
||||
if (color == null) {
|
||||
out[0] = 1;
|
||||
out[1] = 1;
|
||||
out[2] = 0;
|
||||
} else {
|
||||
out[0] = (float) color.getRed() / 255f;
|
||||
out[1] = (float) color.getGreen() / 255f;
|
||||
out[2] = (float) color.getBlue() / 255f;
|
||||
}
|
||||
}
|
||||
|
||||
public void d(final GLAutoDrawable drawable, float dx) {
|
||||
GL2 gl = drawable.getGL().getGL2();
|
||||
GLU glu = new GLU();
|
||||
|
||||
float[] color = new float[3];
|
||||
|
||||
gl.glEnable(GL.GL_MULTISAMPLE);
|
||||
|
||||
convertColor(p.getSunlight(), color);
|
||||
float amb = (float) p.getAmbiance();
|
||||
float dif = 1.0f - amb;
|
||||
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_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);
|
||||
gl.glClearColor(color[0], color[1], color[2], 1);
|
||||
gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
|
||||
gl.glLoadIdentity();
|
||||
glu.gluPerspective(p.getFov() * (180.0 / Math.PI), ratio, 0.1f, 50f);
|
||||
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
|
||||
|
||||
//Flip textures for LEFT handed coords
|
||||
gl.glMatrixMode(GL.GL_TEXTURE);
|
||||
gl.glLoadIdentity();
|
||||
gl.glScaled(-1, 1, 1);
|
||||
gl.glTranslated(-1, 0, 0);
|
||||
|
||||
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
|
||||
gl.glLoadIdentity();
|
||||
|
||||
gl.glEnable(GL.GL_CULL_FACE);
|
||||
gl.glCullFace(GL.GL_BACK);
|
||||
gl.glFrontFace(GL.GL_CCW);
|
||||
|
||||
//Draw the sky
|
||||
gl.glPushMatrix();
|
||||
gl.glDisable(GLLightingFunc.GL_LIGHTING);
|
||||
gl.glDepthMask(false);
|
||||
gl.glRotated(p.getViewAlt() * (180.0 / Math.PI), 1, 0, 0);
|
||||
gl.glRotated(p.getViewAz() * (180.0 / Math.PI), 0, 1, 0);
|
||||
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
|
||||
if (p.getSky() != null) {
|
||||
p.getSky().draw(gl, textureCache);
|
||||
}
|
||||
gl.glDepthMask(true);
|
||||
gl.glEnable(GLLightingFunc.GL_LIGHTING);
|
||||
gl.glPopMatrix();
|
||||
|
||||
if (rr == null)
|
||||
return;
|
||||
|
||||
|
||||
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.getViewAz() * (180.0 / Math.PI), 0, 1, 0);
|
||||
|
||||
float[] lightPosition = new float[] {
|
||||
(float) Math.cos(p.getLightAlt()) * (float) Math.sin(p.getLightAz()),//
|
||||
(float) Math.sin(p.getLightAlt()),//
|
||||
(float) Math.cos(p.getLightAlt()) * (float) Math.cos(p.getLightAz()), //
|
||||
0
|
||||
};
|
||||
|
||||
gl.glLightfv(GLLightingFunc.GL_LIGHT1, GLLightingFunc.GL_POSITION,
|
||||
lightPosition, 0);
|
||||
|
||||
//Change to LEFT Handed coordinates
|
||||
gl.glScaled(1, 1, -1);
|
||||
gl.glFrontFace(GL.GL_CW);
|
||||
setupModel(gl);
|
||||
|
||||
gl.glTranslated(dx - p.getAdvance(), 0, 0);
|
||||
|
||||
|
||||
if (p.isFlame()) {
|
||||
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_DIFFUSE, new float[] { color[0], color[1], 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();
|
||||
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.glEnable(GLLightingFunc.GL_LIGHT2);
|
||||
} else {
|
||||
gl.glDisable(GLLightingFunc.GL_LIGHT2);
|
||||
}
|
||||
|
||||
|
||||
rr.render(drawable, configuration, new HashSet<RocketComponent>());
|
||||
//glu.gluSphere(new GLUquadricImpl(gl, false), .2, 10, 10);
|
||||
|
||||
String motorID = configuration.getFlightConfigurationID();
|
||||
Iterator<MotorMount> iterator = configuration.motorIterator();
|
||||
while (iterator.hasNext()) {
|
||||
MotorMount mount = iterator.next();
|
||||
Motor motor = mount.getMotorConfiguration().get(motorID).getMotor();
|
||||
double length = motor.getLength();
|
||||
|
||||
Coordinate[] position = ((RocketComponent) mount).toAbsolute(new Coordinate(((RocketComponent) mount)
|
||||
.getLength() + mount.getMotorOverhang() - length));
|
||||
|
||||
for (int i = 0; i < position.length; i++) {
|
||||
gl.glPushMatrix();
|
||||
gl.glTranslated(position[i].x + motor.getLength(), position[i].y, position[i].z);
|
||||
FlameRenderer.f(gl, p.isFlame(), p.isSmoke(), p.isSparks(), p.getSmokeColor(), p.getFlameColor(), motor, (float) p.getExhaustScale(), (float) p.getFlameAspectRatio());
|
||||
gl.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
gl.glDisable(GL.GL_BLEND);
|
||||
gl.glFrontFace(GL.GL_CCW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void dispose(final GLAutoDrawable drawable) {
|
||||
log.trace("GL - dispose() called");
|
||||
if (rr != null)
|
||||
rr.dispose(drawable);
|
||||
textureCache.dispose(drawable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init(final GLAutoDrawable drawable) {
|
||||
log.trace("GL - init()");
|
||||
drawable.setGL(new DebugGL2(drawable.getGL().getGL2()));
|
||||
|
||||
final GL2 gl = drawable.getGL().getGL2();
|
||||
|
||||
gl.glClearDepth(1.0f); // clear z-buffer to the farthest
|
||||
gl.glDepthFunc(GL.GL_LESS); // the type of depth test to do
|
||||
|
||||
|
||||
textureCache.init(drawable);
|
||||
|
||||
//gl.glDisable(GLLightingFunc.GL_LIGHT1);
|
||||
|
||||
FlameRenderer.init(gl);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reshape(final GLAutoDrawable drawable, final int x, final int y, final int w, final int h) {
|
||||
log.trace("GL - reshape()");
|
||||
ratio = (double) w / (double) h;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
private static class Bounds {
|
||||
double xMin, xMax, xSize;
|
||||
double yMin, yMax, ySize;
|
||||
double zMin, zMax, zSize;
|
||||
double rMax;
|
||||
}
|
||||
|
||||
private Bounds cachedBounds = null;
|
||||
|
||||
/**
|
||||
* Calculates the bounds for the current configuration
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
private Bounds calculateBounds() {
|
||||
if (cachedBounds != null) {
|
||||
return cachedBounds;
|
||||
} else {
|
||||
final Bounds b = new Bounds();
|
||||
final Collection<Coordinate> bounds = configuration.getBounds();
|
||||
for (Coordinate c : bounds) {
|
||||
b.xMax = Math.max(b.xMax, c.x);
|
||||
b.xMin = Math.min(b.xMin, c.x);
|
||||
|
||||
b.yMax = Math.max(b.yMax, c.y);
|
||||
b.yMin = Math.min(b.yMin, c.y);
|
||||
|
||||
b.zMax = Math.max(b.zMax, c.z);
|
||||
b.zMin = Math.min(b.zMin, c.z);
|
||||
|
||||
double r = MathUtil.hypot(c.y, c.z);
|
||||
b.rMax = Math.max(b.rMax, r);
|
||||
}
|
||||
b.xSize = b.xMax - b.xMin;
|
||||
b.ySize = b.yMax - b.yMin;
|
||||
b.zSize = b.zMax - b.zMin;
|
||||
cachedBounds = b;
|
||||
return b;
|
||||
}
|
||||
}
|
||||
|
||||
private void setupModel(final GL2 gl) {
|
||||
// Get the bounds
|
||||
final Bounds b = calculateBounds();
|
||||
gl.glRotated(-p.getPitch() * (180.0 / Math.PI), 0, 0, 1);
|
||||
gl.glRotated(p.getYaw() * (180.0 / Math.PI), 0, 1, 0);
|
||||
gl.glRotated(p.getRoll() * (180.0 / Math.PI), 1, 0, 0);
|
||||
// Center the rocket in the view.
|
||||
gl.glTranslated(-b.xMin - b.xSize / 2.0, 0, 0);
|
||||
}
|
||||
|
||||
private void copy(final GLAutoDrawable drawable) {
|
||||
|
||||
final BufferedImage image = (new AWTGLReadBufferUtil(GLProfile.get(GLProfile.GL2), false))
|
||||
.readPixelsToBufferedImage(drawable.getGL(), 0, 0, drawable.getWidth(), drawable.getHeight(), true);
|
||||
|
||||
|
||||
Toolkit.getDefaultToolkit().getSystemClipboard().setContents(new Transferable() {
|
||||
@Override
|
||||
public Object getTransferData(DataFlavor flavor)
|
||||
throws UnsupportedFlavorException, IOException {
|
||||
if (flavor.equals(DataFlavor.imageFlavor) && image != null) {
|
||||
return image;
|
||||
}
|
||||
else {
|
||||
throw new UnsupportedFlavorException(flavor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataFlavor[] getTransferDataFlavors() {
|
||||
DataFlavor[] flavors = new DataFlavor[1];
|
||||
flavors[0] = DataFlavor.imageFlavor;
|
||||
return flavors;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDataFlavorSupported(DataFlavor flavor) {
|
||||
DataFlavor[] flavors = getTransferDataFlavors();
|
||||
for (int i = 0; i < flavors.length; i++) {
|
||||
if (flavor.equals(flavors[i])) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}, null);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,252 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.Sky;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.builtin.Mountains;
|
||||
import net.sf.openrocket.util.AbstractChangeSource;
|
||||
import net.sf.openrocket.util.Color;
|
||||
|
||||
public class PhotoSettings extends AbstractChangeSource {
|
||||
private double roll = 3.14;
|
||||
private double yaw = 0;
|
||||
private double pitch = 2.05;
|
||||
private double advance = 0;
|
||||
|
||||
private double viewAlt = -0.23;
|
||||
private double viewAz = 2.08;
|
||||
private double viewDistance = .44;
|
||||
private double fov = 1.4;
|
||||
|
||||
private double lightAlt = .35;
|
||||
private double lightAz = -1;
|
||||
private Color sunlight = new Color(255, 255, 255);
|
||||
private double ambiance = .3f;
|
||||
|
||||
private Color skyColor = new Color(55, 95, 155);
|
||||
|
||||
|
||||
private boolean motionBlurred = false;
|
||||
private boolean flame = false;
|
||||
private Color flameColor = new Color(255, 100, 50);
|
||||
private boolean smoke = true;
|
||||
private Color smokeColor = new Color(230, 230, 230, 204);
|
||||
private boolean sparks = false;
|
||||
private double exhaustScale = 1.0;
|
||||
private double flameAspectRatio = 1.0;
|
||||
|
||||
private Sky sky = Mountains.instance;
|
||||
|
||||
public double getRoll() {
|
||||
return roll;
|
||||
}
|
||||
|
||||
public void setRoll(double roll) {
|
||||
this.roll = roll;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public void setYaw(double yaw) {
|
||||
this.yaw = yaw;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public void setPitch(double pitch) {
|
||||
this.pitch = pitch;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public void setPitchYawRoll(double pitch, double yaw, double roll) {
|
||||
this.roll = roll;
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getAdvance() {
|
||||
return advance;
|
||||
}
|
||||
|
||||
public void setAdvance(double advance) {
|
||||
this.advance = advance;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getViewAlt() {
|
||||
return viewAlt;
|
||||
}
|
||||
|
||||
public void setViewAlt(double viewAlt) {
|
||||
this.viewAlt = viewAlt;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getViewAz() {
|
||||
return viewAz;
|
||||
}
|
||||
|
||||
public void setViewAz(double viewAz) {
|
||||
this.viewAz = viewAz;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getViewDistance() {
|
||||
return viewDistance;
|
||||
}
|
||||
|
||||
public void setViewDistance(double viewDistance) {
|
||||
this.viewDistance = viewDistance;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getFov() {
|
||||
return fov;
|
||||
}
|
||||
|
||||
public void setFov(double fov) {
|
||||
this.fov = fov;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getLightAlt() {
|
||||
return lightAlt;
|
||||
}
|
||||
|
||||
public void setLightAlt(double lightAlt) {
|
||||
this.lightAlt = lightAlt;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getLightAz() {
|
||||
return lightAz;
|
||||
}
|
||||
|
||||
public void setLightAz(double lightAz) {
|
||||
this.lightAz = lightAz;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public boolean isMotionBlurred() {
|
||||
return motionBlurred;
|
||||
}
|
||||
|
||||
public void setMotionBlurred(boolean motionBlurred) {
|
||||
this.motionBlurred = motionBlurred;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public boolean isFlame() {
|
||||
return flame;
|
||||
}
|
||||
|
||||
public void setFlame(boolean flame) {
|
||||
this.flame = flame;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public boolean isSmoke() {
|
||||
return smoke;
|
||||
}
|
||||
|
||||
public void setSmoke(boolean smoke) {
|
||||
this.smoke = smoke;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public Color getSunlight() {
|
||||
return sunlight;
|
||||
}
|
||||
|
||||
public void setSunlight(Color sunlight) {
|
||||
this.sunlight = sunlight;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getAmbiance() {
|
||||
return ambiance;
|
||||
}
|
||||
|
||||
public void setAmbiance(double ambiance) {
|
||||
this.ambiance = ambiance;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public Color getSkyColor() {
|
||||
return skyColor;
|
||||
}
|
||||
|
||||
public void setSkyColor(Color skyColor) {
|
||||
this.skyColor = skyColor;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public Color getFlameColor() {
|
||||
return flameColor;
|
||||
}
|
||||
|
||||
public void setFlameColor(Color flameColor) {
|
||||
this.flameColor = flameColor;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public Color getSmokeColor() {
|
||||
return smokeColor;
|
||||
}
|
||||
|
||||
public void setSmokeColor(Color smokeColor) {
|
||||
smokeColor.setAlpha(this.smokeColor.getAlpha());
|
||||
this.smokeColor = smokeColor;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getSmokeAlpha() {
|
||||
return smokeColor.getAlpha() / 255f;
|
||||
}
|
||||
|
||||
public void setSmokeAlpha(double alpha) {
|
||||
smokeColor.setAlpha((int) (alpha * 255));
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public boolean isSparks() {
|
||||
return sparks;
|
||||
}
|
||||
|
||||
public void setSparks(boolean sparks) {
|
||||
this.sparks = sparks;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getExhaustScale() {
|
||||
return exhaustScale;
|
||||
}
|
||||
|
||||
public void setExhaustScale(double exhaustScale) {
|
||||
this.exhaustScale = exhaustScale;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public double getFlameAspectRatio() {
|
||||
return flameAspectRatio;
|
||||
}
|
||||
|
||||
public void setFlameAspectRatio(double flameAspectRatio) {
|
||||
this.flameAspectRatio = flameAspectRatio;
|
||||
fireChangeEvent();
|
||||
}
|
||||
|
||||
public Sky getSky() {
|
||||
return sky;
|
||||
}
|
||||
|
||||
public void setSky(Sky sky) {
|
||||
this.sky = sky;
|
||||
fireChangeEvent();
|
||||
}
|
||||
}
|
@ -0,0 +1,307 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo;
|
||||
|
||||
import java.awt.Color;
|
||||
import java.awt.Dimension;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.EventObject;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JColorChooser;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JDialog;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JPanel;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSpinner;
|
||||
import javax.swing.JTabbedPane;
|
||||
import javax.swing.JTextArea;
|
||||
import javax.swing.SwingConstants;
|
||||
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import net.sf.openrocket.gui.adaptors.BooleanModel;
|
||||
import net.sf.openrocket.gui.adaptors.DoubleModel;
|
||||
import net.sf.openrocket.gui.components.ColorIcon;
|
||||
import net.sf.openrocket.gui.components.StyledLabel;
|
||||
import net.sf.openrocket.gui.components.StyledLabel.Style;
|
||||
import net.sf.openrocket.gui.components.UnitSelector;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.Sky;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.Sky.Credit;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.builtin.Lake;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.builtin.Meadow;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.builtin.Miramar;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.builtin.Mountains;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.builtin.Orbit;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.builtin.Storm;
|
||||
import net.sf.openrocket.gui.util.ColorConversion;
|
||||
import net.sf.openrocket.startup.Application;
|
||||
import net.sf.openrocket.unit.UnitGroup;
|
||||
import net.sf.openrocket.util.StateChangeListener;
|
||||
|
||||
public class PhotoSettingsConfig extends JTabbedPane {
|
||||
private static final JColorChooser colorChooser = new JColorChooser();
|
||||
|
||||
private class ColorActionListener implements ActionListener {
|
||||
private final String valueName;
|
||||
private final Object o;
|
||||
|
||||
ColorActionListener(final Object o, final String valueName) {
|
||||
this.valueName = valueName;
|
||||
this.o = o;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent colorClickEvent) {
|
||||
try {
|
||||
final Method getMethod = o.getClass().getMethod("get" + valueName);
|
||||
final Method setMethod = o.getClass().getMethod("set" + valueName, net.sf.openrocket.util.Color.class);
|
||||
net.sf.openrocket.util.Color c = (net.sf.openrocket.util.Color) getMethod.invoke(o);
|
||||
Color awtColor = ColorConversion.toAwtColor(c);
|
||||
colorChooser.setColor(awtColor);
|
||||
JDialog d = JColorChooser.createDialog(PhotoSettingsConfig.this,
|
||||
"Color Chooser", true, colorChooser, new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent okEvent) {
|
||||
Color selected = colorChooser.getColor();
|
||||
if (selected == null)
|
||||
return;
|
||||
try {
|
||||
setMethod.invoke(o, ColorConversion.fromAwtColor(selected));
|
||||
} catch (Throwable e1) {
|
||||
Application.getExceptionHandler().handleErrorCondition(e1);
|
||||
}
|
||||
}
|
||||
}, null);
|
||||
d.setVisible(true);
|
||||
} catch (Throwable e1) {
|
||||
Application.getExceptionHandler().handleErrorCondition(e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public PhotoSettingsConfig(final PhotoSettings p) {
|
||||
super();
|
||||
|
||||
setPreferredSize(new Dimension(240, 320));
|
||||
|
||||
final JButton sunLightColorButton = new JButton();
|
||||
sunLightColorButton.setMaximumSize(new Dimension(35, 25));
|
||||
|
||||
final JButton skyColorButton = new JButton();
|
||||
skyColorButton.setMaximumSize(new Dimension(35, 25));
|
||||
|
||||
final JButton smokeColorButton = new JButton();
|
||||
smokeColorButton.setMaximumSize(new Dimension(35, 25));
|
||||
|
||||
final JButton flameColorButton = new JButton();
|
||||
flameColorButton.setMaximumSize(new Dimension(35, 25));
|
||||
|
||||
p.addChangeListener(new StateChangeListener() {
|
||||
{
|
||||
stateChanged(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stateChanged(EventObject e) {
|
||||
sunLightColorButton.setIcon(new ColorIcon(p.getSunlight()));
|
||||
skyColorButton.setIcon(new ColorIcon(p.getSkyColor()));
|
||||
smokeColorButton.setIcon(new ColorIcon(p.getSmokeColor()));
|
||||
flameColorButton.setIcon(new ColorIcon(p.getFlameColor()));
|
||||
}
|
||||
});
|
||||
sunLightColorButton.addActionListener(new ColorActionListener(p, "Sunlight"));
|
||||
skyColorButton.addActionListener(new ColorActionListener(p, "SkyColor"));
|
||||
smokeColorButton.addActionListener(new ColorActionListener(p, "SmokeColor"));
|
||||
flameColorButton.addActionListener(new ColorActionListener(p, "FlameColor"));
|
||||
|
||||
|
||||
|
||||
addTab("Orientation", new JPanel(new MigLayout("fill")) {
|
||||
{
|
||||
add(new StyledLabel("Rocket", Style.BOLD));
|
||||
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
||||
|
||||
add(new JLabel("Pitch"));
|
||||
DoubleModel pitchModel = new DoubleModel(p, "Pitch", UnitGroup.UNITS_ANGLE);
|
||||
add(new JSpinner(pitchModel.getSpinnerModel()), "w 40");
|
||||
add(new UnitSelector(pitchModel), "wrap");
|
||||
|
||||
add(new JLabel("Yaw"));
|
||||
DoubleModel yawModel = new DoubleModel(p, "Yaw", UnitGroup.UNITS_ANGLE);
|
||||
add(new JSpinner(yawModel.getSpinnerModel()), "w 40");
|
||||
add(new UnitSelector(yawModel), "wrap");
|
||||
|
||||
add(new JLabel("Roll"));
|
||||
DoubleModel rollModel = new DoubleModel(p, "Roll", UnitGroup.UNITS_ANGLE);
|
||||
add(new JSpinner(rollModel.getSpinnerModel()), "w 40");
|
||||
add(new UnitSelector(rollModel), "wrap");
|
||||
|
||||
add(new JLabel("Advance"));
|
||||
DoubleModel advanceModel = new DoubleModel(p, "Advance", UnitGroup.UNITS_LENGTH);
|
||||
add(new JSpinner(advanceModel.getSpinnerModel()), "w 40");
|
||||
add(new UnitSelector(advanceModel), "wrap");
|
||||
|
||||
add(new StyledLabel("Camera", Style.BOLD));
|
||||
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
||||
|
||||
add(new JLabel("View Azimuth"));
|
||||
DoubleModel viewAzModel = new DoubleModel(p, "ViewAz", UnitGroup.UNITS_ANGLE);
|
||||
add(new JSpinner(viewAzModel.getSpinnerModel()), "w 40");
|
||||
add(new UnitSelector(viewAzModel), "wrap");
|
||||
|
||||
add(new JLabel("View Altitude"));
|
||||
DoubleModel viewAltModle = new DoubleModel(p, "ViewAlt", UnitGroup.UNITS_ANGLE);
|
||||
add(new JSpinner(viewAltModle.getSpinnerModel()), "w 40");
|
||||
add(new UnitSelector(viewAltModle), "wrap");
|
||||
|
||||
add(new JLabel("View Distance"));
|
||||
DoubleModel viewDistanceModel = new DoubleModel(p, "ViewDistance", UnitGroup.UNITS_LENGTH);
|
||||
add(new JSpinner(viewDistanceModel.getSpinnerModel()), "w 40");
|
||||
add(new UnitSelector(viewDistanceModel), "wrap");
|
||||
|
||||
add(new JLabel("FoV"));
|
||||
DoubleModel fovModel = new DoubleModel(p, "Fov", UnitGroup.UNITS_ANGLE);
|
||||
add(new JSpinner(fovModel.getSpinnerModel()), "w 40");
|
||||
add(new UnitSelector(fovModel), "wrap");
|
||||
}
|
||||
});
|
||||
|
||||
addTab("Environment", new JPanel(new MigLayout("fill")) {
|
||||
{
|
||||
add(new StyledLabel("Light", Style.BOLD));
|
||||
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
||||
|
||||
add(new JLabel("Sun Light"));
|
||||
add(sunLightColorButton, "wrap");
|
||||
|
||||
add(new JLabel("Ambiance"));
|
||||
DoubleModel ambianceModel = new DoubleModel(p, "Ambiance", 100, UnitGroup.UNITS_NONE, 0, 100);
|
||||
add(new JSpinner(ambianceModel.getSpinnerModel()), "wrap");
|
||||
|
||||
add(new JLabel("Light Azimuth"));
|
||||
DoubleModel lightAzModel = new DoubleModel(p, "LightAz", UnitGroup.UNITS_ANGLE);
|
||||
add(new JSpinner(lightAzModel.getSpinnerModel()), "w 40");
|
||||
add(new UnitSelector(lightAzModel), "wrap");
|
||||
|
||||
add(new JLabel("Light Altitude"));
|
||||
DoubleModel lightAltModle = new DoubleModel(p, "LightAlt", UnitGroup.UNITS_ANGLE);
|
||||
add(new JSpinner(lightAltModle.getSpinnerModel()), "wrap");
|
||||
|
||||
add(new StyledLabel("Sky", Style.BOLD));
|
||||
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
||||
|
||||
add(new JLabel("Sky Color"));
|
||||
add(skyColorButton, "wrap");
|
||||
|
||||
add(new JLabel("Sky Image"));
|
||||
|
||||
add(new JComboBox(new DefaultComboBoxModel(new Object[] {
|
||||
null,
|
||||
Mountains.instance,
|
||||
Meadow.instance,
|
||||
Storm.instance,
|
||||
Lake.instance,
|
||||
Orbit.instance,
|
||||
Miramar.instance
|
||||
}) {
|
||||
}) {
|
||||
{
|
||||
addActionListener(new ActionListener() {
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e) {
|
||||
Object s = ((JComboBox) e.getSource()).getSelectedItem();
|
||||
if (s instanceof Sky) {
|
||||
p.setSky((Sky) s);
|
||||
skyColorButton.setEnabled(false);
|
||||
} else if (s == null) {
|
||||
p.setSky(null);
|
||||
skyColorButton.setEnabled(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
setSelectedItem(p.getSky());
|
||||
}
|
||||
}, "wrap");
|
||||
|
||||
final JLabel creditLabel = new JLabel("Image Credit:");
|
||||
add(creditLabel, "wrap");
|
||||
|
||||
final JTextArea credit = new JTextArea();
|
||||
credit.setEditable(false);
|
||||
credit.setCursor(null);
|
||||
credit.setOpaque(false);
|
||||
credit.setFocusable(false);
|
||||
credit.setFont(creditLabel.getFont());
|
||||
add(credit, "span, gap left 10px");
|
||||
|
||||
final StateChangeListener skyChange = new StateChangeListener() {
|
||||
@Override
|
||||
public void stateChanged(EventObject e) {
|
||||
if (p.getSky() instanceof Sky.Credit) {
|
||||
credit.setText(((Credit) p.getSky()).getCredit());
|
||||
} else {
|
||||
credit.setText("");
|
||||
}
|
||||
}
|
||||
};
|
||||
p.addChangeListener(skyChange);
|
||||
|
||||
skyChange.stateChanged(null);
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
addTab("Effects", new JPanel(new MigLayout("fill")) {
|
||||
{
|
||||
add(new StyledLabel("Smoke & Flame", Style.BOLD));
|
||||
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
||||
|
||||
add(new JLabel("Smoke"));
|
||||
BooleanModel smokeModel = new BooleanModel(p, "Smoke");
|
||||
add(new JCheckBox(smokeModel), "split 2, w 15");
|
||||
|
||||
add(smokeColorButton, "wrap");
|
||||
smokeModel.addEnableComponent(smokeColorButton);
|
||||
|
||||
add(new JLabel("Smoke Opacity"));
|
||||
DoubleModel smokeAlphaModel = new DoubleModel(p, "SmokeAlpha", 100, UnitGroup.UNITS_NONE, 0, 100);
|
||||
JSpinner opacitySpinner = new JSpinner(smokeAlphaModel.getSpinnerModel());
|
||||
add(opacitySpinner, "wrap");
|
||||
smokeModel.addEnableComponent(opacitySpinner);
|
||||
|
||||
add(new JLabel("Flame"));
|
||||
BooleanModel fireModel = new BooleanModel(p, "Flame");
|
||||
add(new JCheckBox(fireModel), "split 2, w 15");
|
||||
|
||||
add(flameColorButton, "wrap");
|
||||
fireModel.addEnableComponent(flameColorButton);
|
||||
|
||||
add(new JLabel("Flame Aspect Ratio"));
|
||||
DoubleModel flameAspectModel = new DoubleModel(p, "FlameAspectRatio", 100, UnitGroup.UNITS_NONE, 25, 250);
|
||||
JSpinner flameAspectSpinner = new JSpinner(flameAspectModel.getSpinnerModel());
|
||||
add(flameAspectSpinner, "wrap");
|
||||
fireModel.addEnableComponent(flameAspectSpinner);
|
||||
|
||||
add(new JLabel("Sparks"));
|
||||
JCheckBox sparksCheck = new JCheckBox(new BooleanModel(p, "Sparks"));
|
||||
add(sparksCheck, "wrap");
|
||||
fireModel.addEnableComponent(sparksCheck);
|
||||
|
||||
add(new JLabel("Exhaust Scale"));
|
||||
DoubleModel exhaustScaleModel = new DoubleModel(p, "ExhaustScale", 100, UnitGroup.UNITS_NONE, 0, 1000);
|
||||
add(new JSpinner(exhaustScaleModel.getSpinnerModel()), "wrap");
|
||||
|
||||
add(new StyledLabel("Effects", Style.BOLD));
|
||||
add(new JSeparator(SwingConstants.HORIZONTAL), "span, wrap, growx");
|
||||
|
||||
add(new JLabel("Speed"));
|
||||
add(new JCheckBox(new BooleanModel(p, "MotionBlurred")), "wrap");
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
|
||||
public class Trackball {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(Trackball.class);
|
||||
|
||||
private double pitch, yaw, roll;
|
||||
|
||||
public Trackball() {
|
||||
|
||||
}
|
||||
|
||||
public void setPitchYawRoll(final double pitch, final double yaw, final double roll) {
|
||||
this.pitch = pitch;
|
||||
this.yaw = yaw;
|
||||
this.roll = roll;
|
||||
}
|
||||
|
||||
public double getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
public double getYaw() {
|
||||
return yaw;
|
||||
}
|
||||
|
||||
public double getRoll() {
|
||||
return roll;
|
||||
}
|
||||
|
||||
public void swipe
|
||||
(final double p1x, final double p1y, final double p2x, final double p2y, final double vAz, final double vAlt) {
|
||||
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,466 @@
|
||||
/*
|
||||
** License Applicability. Except to the extent portions of this file are
|
||||
** made subject to an alternative license as permitted in the SGI Free
|
||||
** Software License B, Version 2.0 (the "License"), the contents of this
|
||||
** file are subject only to the provisions of the License. You may not use
|
||||
** this file except in compliance with the License. You may obtain a copy
|
||||
** of the License at Silicon Graphics, Inc., attn: Legal Services, 1600
|
||||
** Amphitheatre Parkway, Mountain View, CA 94043-1351, or at:
|
||||
**
|
||||
** http://oss.sgi.com/projects/FreeB
|
||||
**
|
||||
** Note that, as provided in the License, the Software is distributed on an
|
||||
** "AS IS" basis, with ALL EXPRESS AND IMPLIED WARRANTIES AND CONDITIONS
|
||||
** DISCLAIMED, INCLUDING, WITHOUT LIMITATION, ANY IMPLIED WARRANTIES AND
|
||||
** CONDITIONS OF MERCHANTABILITY, SATISFACTORY QUALITY, FITNESS FOR A
|
||||
** PARTICULAR PURPOSE, AND NON-INFRINGEMENT.
|
||||
**
|
||||
** NOTE: The Original Code (as defined below) has been licensed to Sun
|
||||
** Microsystems, Inc. ("Sun") under the SGI Free Software License B
|
||||
** (Version 1.1), shown above ("SGI License"). Pursuant to Section
|
||||
** 3.2(3) of the SGI License, Sun is distributing the Covered Code to
|
||||
** you under an alternative license ("Alternative License"). This
|
||||
** Alternative License includes all of the provisions of the SGI License
|
||||
** except that Section 2.2 and 11 are omitted. Any differences between
|
||||
** the Alternative License and the SGI License are offered solely by Sun
|
||||
** and not by SGI.
|
||||
**
|
||||
** Original Code. The Original Code is: OpenGL Sample Implementation,
|
||||
** Version 1.2.1, released January 26, 2000, developed by Silicon Graphics,
|
||||
** Inc. The Original Code is Copyright (c) 1991-2000 Silicon Graphics, Inc.
|
||||
** Copyright in any portions created by third parties is as indicated
|
||||
** elsewhere herein. All Rights Reserved.
|
||||
**
|
||||
** Additional Notice Provisions: The application programming interfaces
|
||||
** established by SGI in conjunction with the Original Code are The
|
||||
** OpenGL(R) Graphics System: A Specification (Version 1.2.1), released
|
||||
** April 1, 1999; The OpenGL(R) Graphics System Utility Library (Version
|
||||
** 1.3), released November 4, 1998; and OpenGL(R) Graphics with the X
|
||||
** Window System(R) (Version 1.3), released October 19, 1998. This software
|
||||
** was created using the OpenGL(R) version 1.2.1 Sample Implementation
|
||||
** published by SGI, but has not been independently verified as being
|
||||
** compliant with the OpenGL(R) version 1.2.1 Specification.
|
||||
**
|
||||
** $Date: 2009-03-04 17:23:34 -0800 (Wed, 04 Mar 2009) $ $Revision: 1856 $
|
||||
** $Header$
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2002-2004 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (c) 2003 Sun Microsystems, Inc. All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are
|
||||
* met:
|
||||
*
|
||||
* - Redistribution of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistribution 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 Sun Microsystems, Inc. or the names of
|
||||
* contributors may be used to endorse or promote products derived from
|
||||
* this software without specific prior written permission.
|
||||
*
|
||||
* This software is provided "AS IS," without a warranty of any kind. ALL
|
||||
* EXPRESS OR IMPLIED CONDITIONS, REPRESENTATIONS AND WARRANTIES,
|
||||
* INCLUDING ANY IMPLIED WARRANTY OF MERCHANTABILITY, FITNESS FOR A
|
||||
* PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE HEREBY EXCLUDED. SUN
|
||||
* MICROSYSTEMS, INC. ("SUN") AND ITS LICENSORS SHALL NOT BE LIABLE FOR
|
||||
* ANY DAMAGES SUFFERED BY LICENSEE AS A RESULT OF USING, MODIFYING OR
|
||||
* DISTRIBUTING THIS SOFTWARE OR ITS DERIVATIVES. IN NO EVENT WILL SUN OR
|
||||
* ITS LICENSORS BE LIABLE FOR ANY LOST REVENUE, PROFIT OR DATA, OR FOR
|
||||
* DIRECT, INDIRECT, SPECIAL, CONSEQUENTIAL, INCIDENTAL OR PUNITIVE
|
||||
* DAMAGES, HOWEVER CAUSED AND REGARDLESS OF THE THEORY OF LIABILITY,
|
||||
* ARISING OUT OF THE USE OF OR INABILITY TO USE THIS SOFTWARE, EVEN IF
|
||||
* SUN HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
*
|
||||
* You acknowledge that this software is not designed or intended for use
|
||||
* in the design, construction, operation or maintenance of any nuclear
|
||||
* facility.
|
||||
*/
|
||||
package net.sf.openrocket.gui.figure3d.photo.exhaust;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.ByteBuffer;
|
||||
import java.nio.IntBuffer;
|
||||
import java.util.Random;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
import javax.media.opengl.GL2;
|
||||
import javax.media.opengl.GLProfile;
|
||||
import javax.media.opengl.fixedfunc.GLLightingFunc;
|
||||
import javax.media.opengl.fixedfunc.GLMatrixFunc;
|
||||
import javax.media.opengl.glu.GLU;
|
||||
|
||||
import net.sf.openrocket.motor.Motor;
|
||||
import net.sf.openrocket.util.Color;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jogamp.common.nio.Buffers;
|
||||
import com.jogamp.opengl.util.texture.Texture;
|
||||
import com.jogamp.opengl.util.texture.TextureData;
|
||||
import com.jogamp.opengl.util.texture.TextureIO;
|
||||
|
||||
public final class FlameRenderer {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(FlameRenderer.class);
|
||||
|
||||
private FlameRenderer() {
|
||||
}
|
||||
|
||||
static Texture noise;
|
||||
|
||||
protected static void convertColor(Color color, float[] out) {
|
||||
if (color == null) {
|
||||
out[0] = 1;
|
||||
out[1] = 1;
|
||||
out[2] = 0;
|
||||
} else {
|
||||
out[0] = (float) color.getRed() / 255f;
|
||||
out[1] = (float) color.getGreen() / 255f;
|
||||
out[2] = (float) color.getBlue() / 255f;
|
||||
}
|
||||
}
|
||||
|
||||
static Texture flameT;
|
||||
static Texture smokeT;
|
||||
static Texture smokeN;
|
||||
static int shaderprogram;
|
||||
|
||||
private static interface Func {
|
||||
float f(double d);
|
||||
}
|
||||
|
||||
private static final class Const implements Func {
|
||||
final float val;
|
||||
|
||||
public Const(final float val) {
|
||||
this.val = val;
|
||||
}
|
||||
|
||||
@Override
|
||||
public float f(final double d) {
|
||||
return val;
|
||||
}
|
||||
}
|
||||
|
||||
public static void init(GL2 gl) {
|
||||
try {
|
||||
TextureData data = TextureIO.newTextureData(GLProfile.getDefault(), FlameRenderer.class.getResourceAsStream("/datafiles/flame/c-color.png"), GL.GL_RGBA, GL.GL_RGBA, true, null);
|
||||
smokeT = TextureIO.newTexture(data);
|
||||
data = TextureIO.newTextureData(GLProfile.getDefault(), FlameRenderer.class.getResourceAsStream("/datafiles/flame/c-normal.png"), GL.GL_RGBA, GL.GL_RGBA, true, null);
|
||||
smokeN = TextureIO.newTexture(data);
|
||||
data = TextureIO.newTextureData(GLProfile.getDefault(), FlameRenderer.class.getResourceAsStream("/datafiles/flame/smoke2.png"), GL.GL_RGBA, GL.GL_RGBA, true, null);
|
||||
flameT = TextureIO.newTexture(data);
|
||||
|
||||
String line;
|
||||
shaderprogram = gl.glCreateProgram();
|
||||
|
||||
/*int v = gl.glCreateShader(GL2.GL_FRAGMENT_SHADER);
|
||||
BufferedReader brv = new BufferedReader(new InputStreamReader(FlameRenderer.class.getResourceAsStream("smokeVertex.glsl")));
|
||||
String vsrc = "";
|
||||
while ((line = brv.readLine()) != null) {
|
||||
vsrc += line + "\n";
|
||||
}
|
||||
gl.glShaderSource(v, 1, new String[] { vsrc }, (int[]) null, 0);
|
||||
gl.glAttachShader(shaderprogram, v);
|
||||
gl.glCompileShader(v);*/
|
||||
|
||||
int f = gl.glCreateShader(GL2.GL_FRAGMENT_SHADER);
|
||||
BufferedReader brf = new BufferedReader(new InputStreamReader(FlameRenderer.class.getResourceAsStream("/datafiles/flame/smokeShader.glsl")));
|
||||
String fsrc = "";
|
||||
while ((line = brf.readLine()) != null) {
|
||||
fsrc += line + "\n";
|
||||
}
|
||||
gl.glShaderSource(f, 1, new String[] { fsrc }, (int[]) null, 0);
|
||||
gl.glCompileShader(f);
|
||||
|
||||
int statusFragmentShader[] = new int[1];
|
||||
gl.glGetShaderiv(f, GL2.GL_COMPILE_STATUS, IntBuffer.wrap(statusFragmentShader));
|
||||
if (statusFragmentShader[0] == GL2.GL_FALSE)
|
||||
{
|
||||
int infoLogLenght[] = new int[1];
|
||||
gl.glGetShaderiv(f, GL2.GL_INFO_LOG_LENGTH, IntBuffer.wrap(infoLogLenght));
|
||||
ByteBuffer infoLog = Buffers.newDirectByteBuffer(infoLogLenght[0]);
|
||||
gl.glGetShaderInfoLog(f, infoLogLenght[0], null, infoLog);
|
||||
byte[] infoBytes = new byte[infoLogLenght[0]];
|
||||
infoLog.get(infoBytes);
|
||||
String out = new String(infoBytes);
|
||||
System.err.println("Fragment shader error:\n" + out);
|
||||
}
|
||||
|
||||
gl.glAttachShader(shaderprogram, f);
|
||||
|
||||
|
||||
|
||||
|
||||
gl.glLinkProgram(shaderprogram);
|
||||
gl.glValidateProgram(shaderprogram);
|
||||
|
||||
|
||||
} catch (Exception e1) {
|
||||
e1.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static void trail(GL2 gl, Func radius, Func dZ, Func alpha, float LEN, int P, Color color, float scale) {
|
||||
float[] c = new float[4];
|
||||
convertColor(color, c);
|
||||
|
||||
//Figure out if the flame and smoke is point "in" or "out" of the screen
|
||||
//in order to draw the particles in the right Z order
|
||||
final boolean startAtTop;
|
||||
{
|
||||
final double[] mvmatrix = new double[16];
|
||||
final double[] projmatrix = new double[16];
|
||||
final int[] viewport = new int[4];
|
||||
|
||||
gl.glGetIntegerv(GL.GL_VIEWPORT, viewport, 0);
|
||||
gl.glGetDoublev(GLMatrixFunc.GL_MODELVIEW_MATRIX, mvmatrix, 0);
|
||||
gl.glGetDoublev(GLMatrixFunc.GL_PROJECTION_MATRIX, projmatrix, 0);
|
||||
|
||||
final double out[] = new double[4];
|
||||
final double out2[] = new double[4];
|
||||
(new GLU()).gluProject(0, 0, 0, mvmatrix, 0, projmatrix, 0, viewport, 0,
|
||||
out, 0);
|
||||
(new GLU()).gluProject(0, 0, 0.01f, mvmatrix, 0, projmatrix, 0, viewport, 0,
|
||||
out2, 0);
|
||||
|
||||
startAtTop = out2[2] < out[2];
|
||||
}
|
||||
|
||||
final float start;
|
||||
final float len;
|
||||
final float mult;
|
||||
|
||||
if (startAtTop) {
|
||||
start = 0.002f;
|
||||
len = LEN;
|
||||
mult = 1;
|
||||
} else {
|
||||
start = LEN;
|
||||
len = 0.002f;
|
||||
mult = -1;
|
||||
}
|
||||
|
||||
//Use the same seed every time
|
||||
Random r = new Random(0);
|
||||
|
||||
//Loop forwards or backwards. Technically the dZ is applied differently
|
||||
//in either direction, but the difference should be vanishingly small.
|
||||
for (float z = start; mult * z < mult * len; z += mult * dZ.f(z)) {
|
||||
gl.glPushMatrix();
|
||||
gl.glTranslatef(0, 0, z);
|
||||
|
||||
c[3] = alpha.f(z);
|
||||
gl.glColor4fv(c, 0);
|
||||
|
||||
|
||||
for (int i = 0; i < P; i++) {
|
||||
gl.glPushMatrix();
|
||||
float rx = radius.f(z) - ((float) r.nextFloat() * radius.f(z) * 2.0f);
|
||||
float ry = radius.f(z) - ((float) r.nextFloat() * radius.f(z) * 2.0f);
|
||||
float rz = radius.f(z) - ((float) r.nextFloat() * radius.f(z) * 2.0f);
|
||||
gl.glTranslatef(rx, ry, rz);
|
||||
|
||||
final double[] mvmatrix = new double[16];
|
||||
gl.glGetDoublev(GLMatrixFunc.GL_MODELVIEW_MATRIX, mvmatrix, 0);
|
||||
mvmatrix[0] = mvmatrix[5] = mvmatrix[10] = 1;
|
||||
mvmatrix[1] = mvmatrix[2] = mvmatrix[4] = mvmatrix[6] = mvmatrix[8] = mvmatrix[9] = 0;
|
||||
gl.glLoadMatrixd(mvmatrix, 0);
|
||||
|
||||
//TODO Add a random rotation to prevent artifacts from texture.
|
||||
|
||||
gl.glBegin(GL.GL_TRIANGLE_FAN);
|
||||
float d = radius.f(z) * scale * 2;
|
||||
gl.glTexCoord2f(0, 0);
|
||||
gl.glVertex3f(-d, -d, 0);
|
||||
gl.glTexCoord2f(0, 1);
|
||||
gl.glVertex3f(-d, d, 0);
|
||||
gl.glTexCoord2f(1, 1);
|
||||
gl.glVertex3f(d, d, 0);
|
||||
gl.glTexCoord2f(1, 0);
|
||||
gl.glVertex3f(d, -d, 0);
|
||||
gl.glEnd();
|
||||
|
||||
gl.glPopMatrix();
|
||||
}
|
||||
|
||||
gl.glPopMatrix();
|
||||
}
|
||||
}
|
||||
|
||||
public static void setUniform1i(GL2 inGL, int inProgramID, String inName, int inValue) {
|
||||
int tUniformLocation = inGL.glGetUniformLocation(inProgramID, inName);
|
||||
if (tUniformLocation != -1) {
|
||||
inGL.glUniform1i(tUniformLocation, inValue);
|
||||
} else {
|
||||
log.warn("UNIFORM COULD NOT BE FOUND! NAME={}", inName);
|
||||
}
|
||||
}
|
||||
|
||||
public static void sparks(GL2 gl, Color color) {
|
||||
//Use the same seed every time
|
||||
Random r = new Random(0);
|
||||
|
||||
float[] c = new float[4];
|
||||
convertColor(color, c);
|
||||
for (int i = 0; i < 3; i++)
|
||||
c[i] = c[i] * .3f + .7f;
|
||||
gl.glColor4fv(c, 0);
|
||||
|
||||
for (int i = 0; i < 200; i++) {
|
||||
final float z = 2 * (r.nextFloat() * r.nextFloat() * r.nextFloat());
|
||||
final float x = z * (r.nextFloat() - 0.5f);
|
||||
final float y = z * (r.nextFloat() - 0.5f);
|
||||
gl.glBegin(GL.GL_POINTS);
|
||||
gl.glPointSize(1);
|
||||
gl.glVertex3f(x, y, z * 2);
|
||||
gl.glEnd();
|
||||
}
|
||||
}
|
||||
|
||||
public static void f(GL2 gl, boolean flame, boolean smoke, boolean sparks, Color smokeColor, Color flameColor, Motor motor, float scale, float aspect) {
|
||||
|
||||
final float s = (float) Math.max(.5, Math.sqrt(motor.getAverageThrustEstimate()) / 4.0) * scale;
|
||||
gl.glScalef(s, s, s);
|
||||
|
||||
gl.glRotated(90, 0, 1, 0);
|
||||
gl.glTranslated(0, 0, 0);
|
||||
|
||||
gl.glDisable(GLLightingFunc.GL_LIGHTING);
|
||||
|
||||
if (sparks && flame) {
|
||||
sparks(gl, flameColor);
|
||||
}
|
||||
|
||||
gl.glEnable(GL.GL_BLEND);
|
||||
|
||||
gl.glTexEnvi(GL2.GL_TEXTURE_ENV, GL2.GL_TEXTURE_ENV_MODE, GL2.GL_MODULATE);
|
||||
gl.glDepthMask(false);
|
||||
|
||||
|
||||
if (smoke) {
|
||||
final float LEN = 10;
|
||||
final float MAX_R = .15f;
|
||||
final int P = 5;
|
||||
|
||||
final Func radius = new Func() {
|
||||
@Override
|
||||
public float f(double d) {
|
||||
return (float) (Math.atan(d) / (Math.PI / 2.0)) * MAX_R + 0.001f;
|
||||
}
|
||||
};
|
||||
|
||||
final Func dZ = new Func() {
|
||||
@Override
|
||||
public float f(double z) {
|
||||
return radius.f(z);
|
||||
}
|
||||
};
|
||||
|
||||
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE_MINUS_SRC_ALPHA);
|
||||
|
||||
gl.glActiveTexture(GL.GL_TEXTURE0);
|
||||
smokeT.bind(gl);
|
||||
|
||||
gl.glActiveTexture(GL.GL_TEXTURE1);
|
||||
smokeN.bind(gl);
|
||||
|
||||
gl.glUseProgram(shaderprogram);
|
||||
|
||||
setUniform1i(gl, shaderprogram, "uSmoke", 0);
|
||||
setUniform1i(gl, shaderprogram, "uNormal", 1);
|
||||
|
||||
trail(gl, radius, dZ, new Const(0.1f * (smokeColor.getAlpha() / 255f)), LEN, P, smokeColor, s);
|
||||
//trail(gl, radius, dZ, new Const(1), 0.2f, 1, smokeColor);
|
||||
gl.glUseProgram(0);
|
||||
|
||||
smokeN.disable(gl);
|
||||
gl.glActiveTexture(GL.GL_TEXTURE0);
|
||||
}
|
||||
|
||||
|
||||
if (flame) {
|
||||
gl.glScalef(1, 1, aspect);
|
||||
|
||||
gl.glActiveTexture(GL.GL_TEXTURE0);
|
||||
flameT.enable(gl);
|
||||
flameT.bind(gl);
|
||||
|
||||
final float FLEN = 0.3f;
|
||||
final int FP = 6;
|
||||
final Func fr = new Func() {
|
||||
@Override
|
||||
public float f(double z) {
|
||||
z = z / FLEN;
|
||||
z = 1 - z;
|
||||
return (float) (z * z - z * z * z) * .06f;
|
||||
}
|
||||
};
|
||||
|
||||
final Func fdZ = new Func() {
|
||||
@Override
|
||||
public float f(double z) {
|
||||
return 0.002f;
|
||||
}
|
||||
};
|
||||
|
||||
final Func alpha = new Func() {
|
||||
@Override
|
||||
public float f(double z) {
|
||||
return 0.2f * (float) Math.pow((1.0f - (float) z / FLEN), 4);
|
||||
};
|
||||
};
|
||||
|
||||
gl.glBlendFunc(GL.GL_SRC_ALPHA, GL.GL_ONE);
|
||||
trail(gl, fr, fdZ, alpha, FLEN, FP, flameColor, s);
|
||||
|
||||
flameT.disable(gl);
|
||||
}
|
||||
|
||||
gl.glEnable(GLLightingFunc.GL_LIGHTING);
|
||||
gl.glDepthMask(true);
|
||||
|
||||
}
|
||||
|
||||
}
|
13
swing/src/net/sf/openrocket/gui/figure3d/photo/sky/Sky.java
Normal file
@ -0,0 +1,13 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky;
|
||||
|
||||
import javax.media.opengl.GL2;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.TextureCache;
|
||||
|
||||
public abstract class Sky {
|
||||
public abstract void draw(GL2 gl, final TextureCache cache);
|
||||
|
||||
public static interface Credit {
|
||||
public String getCredit();
|
||||
}
|
||||
}
|
115
swing/src/net/sf/openrocket/gui/figure3d/photo/sky/SkyBox.java
Normal file
@ -0,0 +1,115 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
import javax.media.opengl.GL2;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.TextureCache;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.jogamp.opengl.util.texture.Texture;
|
||||
|
||||
public class SkyBox extends Sky {
|
||||
private static final Logger log = LoggerFactory.getLogger(SkyBox.class);
|
||||
|
||||
private static final String NAME[][] = {
|
||||
{ "North", "East", "South", "West", "Up", "Down" },
|
||||
{ "posz", "posx", "negz", "negx", "posy", "negy" },
|
||||
{ "pos_z", "pos_x", "neg_z", "neg_x", "pos_y", "neg_y" },
|
||||
//{ "ft", "rt", "bk", "lf", "up", "dn" }
|
||||
//
|
||||
|
||||
{ "rt", "ft", "lf", "bk", "up", "dn" }
|
||||
};
|
||||
private static final String[] TYPE = { ".jpg", ".jpeg", ".png" };
|
||||
|
||||
private final String prefix;
|
||||
private String suffix;
|
||||
private String[] dir;
|
||||
|
||||
public SkyBox(final String prefix) {
|
||||
this.prefix = prefix;
|
||||
this.suffix = ".jpg";
|
||||
|
||||
found: for (String trySuf : TYPE) {
|
||||
suffix = trySuf;
|
||||
for (String[] tryDir : NAME) {
|
||||
dir = tryDir;
|
||||
try {
|
||||
URL u = url(dir[0]);
|
||||
log.debug("Trying URL {}", u);
|
||||
InputStream is = u.openStream();
|
||||
is.close();
|
||||
break found;
|
||||
} catch (IOException e) {
|
||||
log.debug("Nope, {}", e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private URL url(String s) {
|
||||
try {
|
||||
return new URL(prefix + s + suffix);
|
||||
} catch (MalformedURLException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void draw(GL2 gl, final TextureCache cache) {
|
||||
gl.glPushMatrix();
|
||||
gl.glColor3d(1, 1, 1);
|
||||
|
||||
square(gl, cache.getTexture(url(dir[0])));
|
||||
|
||||
gl.glRotatef(90, 0, 1, 0);
|
||||
square(gl, cache.getTexture(url(dir[1])));
|
||||
|
||||
gl.glRotatef(90, 0, 1, 0);
|
||||
square(gl, cache.getTexture(url(dir[2])));
|
||||
|
||||
gl.glRotatef(90, 0, 1, 0);
|
||||
square(gl, cache.getTexture(url(dir[3])));
|
||||
|
||||
gl.glRotatef(-90, 1, 0, 0);
|
||||
gl.glRotatef(90, 0, 0, 1);
|
||||
square(gl, cache.getTexture(url(dir[4])));
|
||||
|
||||
gl.glRotatef(180, 1, 0, 0);
|
||||
square(gl, cache.getTexture(url(dir[5])));
|
||||
|
||||
gl.glPopMatrix();
|
||||
}
|
||||
|
||||
private static final void square(GL2 gl, Texture t) {
|
||||
t.bind(gl);
|
||||
t.enable(gl);
|
||||
gl.glBegin(GL.GL_TRIANGLE_STRIP);
|
||||
gl.glNormal3f(0, 0, -1);
|
||||
|
||||
gl.glTexCoord2f(1, 1);
|
||||
gl.glVertex3f(-1, -1, 1);
|
||||
|
||||
gl.glTexCoord2f(1, 0);
|
||||
gl.glVertex3f(-1, 1, 1);
|
||||
|
||||
gl.glTexCoord2f(0, 1);
|
||||
gl.glVertex3f(1, -1, 1);
|
||||
|
||||
gl.glTexCoord2f(0, 0);
|
||||
gl.glVertex3f(1, 1, 1);
|
||||
|
||||
gl.glEnd();
|
||||
t.disable(gl);
|
||||
}
|
||||
}
|
@ -0,0 +1,98 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky;
|
||||
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import javax.media.opengl.GL;
|
||||
import javax.media.opengl.GL2;
|
||||
import javax.media.opengl.GLProfile;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.TextureCache;
|
||||
|
||||
import com.jogamp.opengl.util.texture.Texture;
|
||||
import com.jogamp.opengl.util.texture.awt.AWTTextureIO;
|
||||
|
||||
public class SkyBoxCross extends Sky {
|
||||
|
||||
private final URL imageURL;
|
||||
Texture north, east, south, west, up, down;
|
||||
|
||||
public SkyBoxCross(final URL imageURL) {
|
||||
this.imageURL = imageURL;
|
||||
}
|
||||
|
||||
private static BufferedImage fixBug(BufferedImage i) {
|
||||
BufferedImage d2 = new BufferedImage(i.getWidth(), i.getHeight(), i.getType());
|
||||
d2.getGraphics().drawImage(i, 0, 0, null);
|
||||
return d2;
|
||||
}
|
||||
|
||||
private void loadTextures(GL2 gl) {
|
||||
try {
|
||||
BufferedImage i = ImageIO.read(imageURL);
|
||||
int dy = i.getHeight() / 3;
|
||||
int dx = i.getWidth() / 4;
|
||||
west = AWTTextureIO.newTexture(GLProfile.getDefault(), fixBug(i.getSubimage(0, dy, dx, dy)), true);
|
||||
north = AWTTextureIO.newTexture(GLProfile.getDefault(), fixBug(i.getSubimage(dx, dy, dx, dy)), true);
|
||||
east = AWTTextureIO.newTexture(GLProfile.getDefault(), fixBug(i.getSubimage(dx * 2, dy, dx, dy)), true);
|
||||
south = AWTTextureIO.newTexture(GLProfile.getDefault(), fixBug(i.getSubimage(dx * 3, dy, dx, dy)), true);
|
||||
up = AWTTextureIO.newTexture(GLProfile.getDefault(), fixBug(i.getSubimage(dx, 0, dx, dy)), true);
|
||||
down = AWTTextureIO.newTexture(GLProfile.getDefault(), fixBug(i.getSubimage(dx, 2 * dy, dx, dy)), true);
|
||||
} catch (IOException e) {
|
||||
throw new Error(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(GL2 gl, final TextureCache cache) {
|
||||
if (north == null) {
|
||||
loadTextures(gl);
|
||||
}
|
||||
|
||||
gl.glPushMatrix();
|
||||
gl.glColor3d(1, 1, 1);
|
||||
square(gl, north);
|
||||
|
||||
gl.glRotatef(90, 0, 1, 0);
|
||||
square(gl, east);
|
||||
|
||||
gl.glRotatef(90, 0, 1, 0);
|
||||
square(gl, south);
|
||||
|
||||
gl.glRotatef(90, 0, 1, 0);
|
||||
square(gl, west);
|
||||
|
||||
gl.glRotatef(-90, 1, 0, 0);
|
||||
gl.glRotatef(90, 0, 0, 1);
|
||||
square(gl, up);
|
||||
|
||||
gl.glRotatef(180, 1, 0, 0);
|
||||
square(gl, down);
|
||||
|
||||
|
||||
gl.glPopMatrix();
|
||||
}
|
||||
|
||||
private static final void square(GL2 gl, Texture t) {
|
||||
t.bind(gl);
|
||||
t.enable(gl);
|
||||
gl.glBegin(GL.GL_TRIANGLE_STRIP);
|
||||
gl.glNormal3f(0, 0, -1);
|
||||
|
||||
gl.glTexCoord2f(1, 1);
|
||||
gl.glVertex3f(-1, -1, 1);
|
||||
|
||||
gl.glTexCoord2f(1, 0);
|
||||
gl.glVertex3f(-1, 1, 1);
|
||||
|
||||
gl.glTexCoord2f(0, 1);
|
||||
gl.glVertex3f(1, -1, 1);
|
||||
|
||||
gl.glTexCoord2f(0, 0);
|
||||
gl.glVertex3f(1, 1, 1);
|
||||
gl.glEnd();
|
||||
t.disable(gl);
|
||||
}
|
||||
}
|
@ -0,0 +1,59 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
import javax.media.opengl.GL2;
|
||||
import javax.media.opengl.fixedfunc.GLMatrixFunc;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.TextureCache;
|
||||
|
||||
import com.jogamp.opengl.util.texture.Texture;
|
||||
|
||||
public class SkyPhoto extends Sky {
|
||||
private final URL imageURL;
|
||||
|
||||
public SkyPhoto(final URL imageURL) {
|
||||
this.imageURL = imageURL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(GL2 gl, final TextureCache cache) {
|
||||
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
|
||||
gl.glPushMatrix();
|
||||
gl.glLoadIdentity();
|
||||
|
||||
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
|
||||
gl.glPushMatrix();
|
||||
gl.glLoadIdentity();
|
||||
gl.glScaled(1, 1, -1);
|
||||
|
||||
Texture sky = cache.getTexture(imageURL);
|
||||
|
||||
gl.glColor3d(1, 1, 1);
|
||||
sky.bind(gl);
|
||||
sky.enable(gl);
|
||||
gl.glBegin(GL.GL_TRIANGLE_STRIP);
|
||||
gl.glNormal3f(0, 0, -1);
|
||||
|
||||
gl.glTexCoord2f(1, 1);
|
||||
gl.glVertex3f(-1, -1, 1);
|
||||
|
||||
gl.glTexCoord2f(0, 1);
|
||||
gl.glVertex3f(1, -1, 1);
|
||||
|
||||
gl.glTexCoord2f(1, 0);
|
||||
gl.glVertex3f(-1, 1, 1);
|
||||
|
||||
gl.glTexCoord2f(0, 0);
|
||||
gl.glVertex3f(1, 1, 1);
|
||||
gl.glEnd();
|
||||
sky.disable(gl);
|
||||
|
||||
gl.glMatrixMode(GLMatrixFunc.GL_PROJECTION);
|
||||
gl.glPopMatrix();
|
||||
|
||||
gl.glMatrixMode(GLMatrixFunc.GL_MODELVIEW);
|
||||
gl.glPopMatrix();
|
||||
}
|
||||
}
|
@ -0,0 +1,40 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
import javax.media.opengl.GL;
|
||||
import javax.media.opengl.GL2;
|
||||
import javax.media.opengl.glu.GLU;
|
||||
import javax.media.opengl.glu.GLUquadric;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.TextureCache;
|
||||
|
||||
import com.jogamp.opengl.util.texture.Texture;
|
||||
|
||||
public class SkySphere extends Sky {
|
||||
|
||||
private final URL imageURL;
|
||||
|
||||
public SkySphere(final URL imageURL) {
|
||||
this.imageURL = imageURL;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(GL2 gl, final TextureCache cache) {
|
||||
gl.glCullFace(GL.GL_FRONT);
|
||||
gl.glPushMatrix();
|
||||
GLU glu = new GLU();
|
||||
gl.glRotatef(90, 1, 0, 0);
|
||||
Texture sky = cache.getTexture(imageURL);
|
||||
sky.enable(gl);
|
||||
sky.bind(gl);
|
||||
gl.glColor3d(1, 1, 1);
|
||||
GLUquadric q = glu.gluNewQuadric();
|
||||
glu.gluQuadricTexture(q, true);
|
||||
glu.gluQuadricOrientation(q, GLU.GLU_OUTSIDE);
|
||||
glu.gluSphere(q, 1f, 20, 20);
|
||||
sky.disable(gl);
|
||||
gl.glPopMatrix();
|
||||
gl.glCullFace(GL.GL_BACK);
|
||||
}
|
||||
}
|
@ -0,0 +1,36 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky.builtin;
|
||||
|
||||
import javax.media.opengl.GL2;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.TextureCache;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.Sky.Credit;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.SkySphere;
|
||||
|
||||
public class Lake extends SkySphere implements Credit {
|
||||
|
||||
public static final Lake instance = new Lake();
|
||||
|
||||
private Lake() {
|
||||
super(Lake.class.getResource("/datafiles/sky/lake.png"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void draw(GL2 gl, final TextureCache cache) {
|
||||
//I have not been able to understand the projection in this
|
||||
//image but this scale seems to fix it.
|
||||
gl.glPushMatrix();
|
||||
gl.glScalef(1, 3, 1);
|
||||
super.draw(gl, cache);
|
||||
gl.glPopMatrix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCredit() {
|
||||
return "Sampo Niskanen.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Frozen Lake";
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky.builtin;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.Sky.Credit;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.SkyBox;
|
||||
|
||||
public class Meadow extends SkyBox implements Credit {
|
||||
public static final Meadow instance = new Meadow();
|
||||
|
||||
private Meadow() {
|
||||
super(Meadow.class.getResource("/datafiles/sky/Meadow/").toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCredit() {
|
||||
return "© Emil Persson, aka Humus.\nCC-BY 3.0 Attribution License.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Meadow";
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky.builtin;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.Sky.Credit;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.SkyBox;
|
||||
|
||||
public class Miramar extends SkyBox implements Credit {
|
||||
public static final Miramar instance = new Miramar();
|
||||
|
||||
private Miramar() {
|
||||
super(Miramar.class.getResource("/datafiles/sky/miramar/").toString() + "miramar_");
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCredit() {
|
||||
return "© Jockum Skoglund aka hipshot.\nCC-BY 3.0 Attribution License.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Miramar";
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky.builtin;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.Sky.Credit;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.SkyBox;
|
||||
|
||||
public class Mountains extends SkyBox implements Credit {
|
||||
public static final Mountains instance = new Mountains();
|
||||
|
||||
private Mountains() {
|
||||
super(Mountains.class.getResource("/datafiles/sky/box/").toString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCredit() {
|
||||
return "Rendering by Bill Kuker.\nCC0 Public Domain.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Mountains";
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky.builtin;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.Sky.Credit;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.SkyPhoto;
|
||||
|
||||
public class Orbit extends SkyPhoto implements Credit {
|
||||
public static final Orbit instance = new Orbit();
|
||||
|
||||
private Orbit() {
|
||||
super(Orbit.class.getResource("/datafiles/sky/space.jpg"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCredit() {
|
||||
return "NASA";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Orbit";
|
||||
}
|
||||
}
|
@ -0,0 +1,22 @@
|
||||
package net.sf.openrocket.gui.figure3d.photo.sky.builtin;
|
||||
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.Sky.Credit;
|
||||
import net.sf.openrocket.gui.figure3d.photo.sky.SkyBoxCross;
|
||||
|
||||
public class Storm extends SkyBoxCross implements Credit {
|
||||
public static final Storm instance = new Storm();
|
||||
|
||||
private Storm() {
|
||||
super(Storm.class.getResource("/datafiles/sky/cross1.jpg"));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getCredit() {
|
||||
return "© Jockum Skoglund aka hipshot.\nCC-BY 3.0 Attribution License.";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Stormy Days";
|
||||
}
|
||||
}
|