L'animazione 3D della fissione è stato realizzato con Eclipse e con le libreie JOGL.
Main.java
import java.awt.BorderLayout;
import java.awt.EventQueue;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SpringLayout;
import javax.swing.border.EmptyBorder;
import com.jogamp.newt.event.KeyEvent;
import com.jogamp.newt.event.KeyListener;
import com.jogamp.newt.event.MouseEvent;
import com.jogamp.newt.event.MouseListener;
import com.jogamp.newt.event.WindowEvent;
import com.jogamp.newt.event.WindowListener;
import com.jogamp.newt.event.WindowUpdateEvent;
import com.jogamp.newt.opengl.GLWindow;
import com.jogamp.opengl.GLCapabilities;
import com.jogamp.opengl.GLProfile;
import com.jogamp.opengl.util.FPSAnimator;
import javax.swing.JCheckBox;
public class Main extends JFrame {
private JPanel contentPane;
private GLRenderer renderer;
private GLWindow window;
private FPSAnimator animator;
/**
* Launch the application.
*/
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
Main frame = new Main();
frame.setVisible(true);
} catch (Exception e) {
e.printStackTrace();
}
}
});
}
/**
* Create the frame.
*/
public Main() {
addWindowListener(new WindowAdapter() {
@Override
public void windowClosing(java.awt.event.WindowEvent e) {
window.destroy();
}
});
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(0, 150, 337, 188);
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);
JButton btnStart = new JButton("Start");
btnStart.setFocusPainted(false);
btnStart.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
animator.start();
}
});
contentPane.add(btnStart, BorderLayout.WEST);
JButton btnStop = new JButton("Stop");
btnStop.setFocusPainted(false);
btnStop.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
animator.stop();
}
});
contentPane.add(btnStop, BorderLayout.EAST);
JPanel panel = new JPanel();
contentPane.add(panel, BorderLayout.CENTER);
SpringLayout sl_panel = new SpringLayout();
panel.setLayout(sl_panel);
JButton btnReset = new JButton("Reset");
btnReset.setFocusPainted(false);
btnReset.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
renderer.reset();
window.display();
}
});
sl_panel.putConstraint(SpringLayout.NORTH, btnReset, 10, SpringLayout.NORTH, panel);
sl_panel.putConstraint(SpringLayout.WEST, btnReset, 10, SpringLayout.WEST, panel);
panel.add(btnReset);
window = GLWindow.create(new GLCapabilities(GLProfile.getDefault()));
window.setSize(500, 500);
renderer = new GLRenderer();
window.addGLEventListener(renderer);
window.setPosition(600, 100);
window.setVisible(true);
animator = new FPSAnimator(window, 60, true);
window.addWindowListener(new WindowListener(){
@Override
public void windowResized(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowMoved(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDestroyNotify(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowDestroyed(WindowEvent e) {
System.exit(0);
}
@Override
public void windowGainedFocus(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowLostFocus(WindowEvent e) {
// TODO Auto-generated method stub
}
@Override
public void windowRepaint(WindowUpdateEvent e) {
// TODO Auto-generated method stub
}
});
}
}
GLRenderer.java
import java.util.ArrayList;
import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL2;
import com.jogamp.opengl.GLAutoDrawable;
import com.jogamp.opengl.GLEventListener;
import com.jogamp.opengl.glu.GLU;
import com.jogamp.opengl.util.gl2.GLUT;
public class GLRenderer implements GLEventListener {
//telecamera
private int dist = 50, w = 0, h = 0;
private double rX = 240, rY = 25, rXInc = 0, rYInc = 0;
private double scale = 1;
private double zCam = 0, xCam = 0;
//elementi
private double r = 0.5;
private double R = 5 * r;
private double xEl1 = 0, xEl2 = 0, zEl1 = 0, zEl2 = 0;
private double REl1 = R, REl2 = R;
//animazioni
private int frame = 0;
private double tAnimazione1 = 1, tAnimazione2 = 1, tAnimazione3 = 3;
//animazione 1
private double zN = -20;
private double dzN = (zEl1 - R - zN) / (tAnimazione1 * 60);
//animazione 2
private double dREl1 = r / (tAnimazione2 * 60.0), dREl2 = 0.5 * r / (tAnimazione2 * 60);
private double gradient = 1;
//animazione 3
private double zN1 = 0;
private double dzN1 = 30 * Math.cos(-10.0 / 180 * Math.PI) / (tAnimazione3 * 60);
private double xN1 = 0;
private double dxN1 = 30 * Math.sin(-10.0 / 180 * Math.PI) / (tAnimazione3 * 60);
private double yN1 = 0;
private double dyN1 = 30 * Math.sin(-20.0 / 180 * Math.PI) / (tAnimazione3 * 60);
private double zN2 = 0;
private double dzN2 = 30 * Math.cos(-45.0 / 180 * Math.PI) / (tAnimazione3 * 60);
private double xN2 = 0;
private double dxN2 = 30 * Math.sin(-45.0 / 180 * Math.PI) / (tAnimazione3 * 60);
private double yN2 = 0;
private double dyN2 = 30 * Math.sin(5.0 / 180 * Math.PI) / (tAnimazione3 * 60);
private double zN3 = 0;
private double dzN3 = 30 * Math.cos(25.0 / 180 * Math.PI) / (tAnimazione3 * 60);
private double xN3 = 0;
private double dxN3 = 30 * Math.sin(25.0 / 180 * Math.PI) / (tAnimazione3 * 60);
private double yN3 = 0;
private double dyN3 = 30 * Math.sin(10.0 / 180 * Math.PI) / (tAnimazione3 * 60);
//tracce
private ArrayList tracciaN = new ArrayList();
private ArrayList tracciaN1 = new ArrayList();
private ArrayList tracciaN2 = new ArrayList();
private ArrayList tracciaN3 = new ArrayList();
@Override
public void init(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
gl.glEnable(GL.GL_DEPTH_TEST);
gl.glDepthFunc(GL2.GL_LEQUAL);
gl.glShadeModel(GL2.GL_SMOOTH);
gl.glHint(GL2.GL_PERSPECTIVE_CORRECTION_HINT, GL2.GL_NICEST);
//luce
float[] lDiffusa = new float[]{1, 1, 1, 0};
float[] lPosizione = new float[]{0, 20, 0, 1};
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_DIFFUSE, lDiffusa, 0);
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_POSITION, lPosizione, 0);
//materiale
float[] mAmbiente = new float[]{0, 0, 0, 1};
float[] mDiffusa = new float[]{1, 1, 1, 1};
float[] mSpeculare = new float[]{1, 1, 1, 1};
float[] mEmissione = new float[]{0, 0, 0, 1};
float[] mLucentezza = new float[]{30};
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_AMBIENT, mAmbiente, 0);
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_DIFFUSE, mDiffusa, 0);
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SPECULAR, mSpeculare, 0);
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_EMISSION, mEmissione, 0);
gl.glMaterialfv(GL2.GL_FRONT, GL2.GL_SHININESS, mLucentezza, 0);
gl.glEnable(GL2.GL_LIGHT0);
gl.glEnable(GL2.GL_LIGHTING);
gl.glEnable(GL2.GL_COLOR_MATERIAL);
}
@Override
public void dispose(GLAutoDrawable drawable) {
}
@Override
public void display(GLAutoDrawable drawable) {
GL2 gl = drawable.getGL().getGL2();
GLUT glut = new GLUT();
GLU glu = new GLU();
gl.glClear(GL2.GL_COLOR_BUFFER_BIT | GL2.GL_DEPTH_BUFFER_BIT);
gl.glLoadIdentity();
gl.glMatrixMode(GL2.GL_PROJECTION);
gl.glLoadIdentity();
glu.gluPerspective(45, (float) w / h, 5, 100);
//imposta la telecamera (punto di vista)
if(frame < tAnimazione1 * 60)
{
xCam = 0;
zCam = zN;
}
else
{
xCam = xN2 / 3;
zCam = zN1 / 2;
}
glu.gluLookAt((dist * Math.cos((rY + rYInc) * Math.PI / 180.0) * Math.sin((rX + rXInc) * Math.PI / 180.0)),
(dist * Math.sin((rY + rYInc) * Math.PI / 180.0)), (dist * Math.cos((rY + rYInc) * Math.PI / 180.0) * Math.cos((rX + rXInc) * Math.PI / 180.0)), xCam, 0, zCam, 0, 1, 0);
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
//elemento 1
if((frame >= tAnimazione1 * 60) && (frame <= (tAnimazione1 * 60) + 6))
gl.glColor3d(0.8, 0.8, 0.8);
else
gl.glColor3d(gradient, 1, 0);
for(double x = -REl1 + r; x <= REl1 - r; x += r)
for(double y = -REl1 + r; y <= REl1 - r; y += r)
for(double z = -REl1 + r; z <= REl1 - r; z += r)
{
if(x+ xEl1 >= 0){
if(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2) < Math.pow(REl1 - r, 2))
{
gl.glLoadIdentity();
gl.glScaled(scale, scale, scale);
gl.glTranslated(xEl1, 0, zEl1);
gl.glTranslated(x, y, z);
glut.glutSolidSphere(r, 16, 16);
}
}
}
//elemento 2
if((frame >= tAnimazione1 * 60) && (frame <= (tAnimazione1 * 60) + 6))
gl.glColor3d(0.8, 0.8, 0.8);
else
gl.glColor3d(1, gradient, 0);
for(double x = -REl2 + r; x <= REl2 - r; x += r)
for(double y = -REl2 + r; y <= REl2 - r; y += r)
for(double z = -REl2 + r; z <= REl2 - r; z += r)
{
if(x+ xEl2 <= 0){
if(Math.pow(x, 2) + Math.pow(y, 2) + Math.pow(z, 2) < Math.pow(REl2 - r, 2))
{
gl.glLoadIdentity();
gl.glScaled(scale, scale, scale);
gl.glTranslated(xEl2, 0, zEl2);
gl.glTranslated(x, y, z);
glut.glutSolidSphere(r, 16, 16);
}
}
}
//animazioni
if(frame < tAnimazione1 * 60)
{
//traccia neutrone iniziale
tracciaN.add(new Point(0,0,zN));
if(tracciaN.size() >= 20)
tracciaN.remove(0);
gl.glLoadIdentity();
gl.glScaled(scale, scale, scale);
gl.glBegin(GL2.GL_LINES);
Point p1, p2;
for(int i = tracciaN.size() - 1; i > 0; i--)
{
p1 = tracciaN.get(i);
p2 = tracciaN.get(i - 1);
gl.glColor3d(1 - 0.02 * (tracciaN.size() - 1 - i), 1 - 0.02 * (tracciaN.size() - 1 - i),1 - 0.02 * (tracciaN.size() - 1 - i));
gl.glVertex3d(p1.getX(), p1.getY(), p1.getZ());
gl.glVertex3d(p2.getX(), p2.getY(), p2.getZ());
}
gl.glEnd();
//neutrone iniziale
gl.glLoadIdentity();
gl.glScaled(scale, scale, scale);
gl.glTranslated(0, 0, zN);
gl.glColor3d(0.8, 0.8, 0.8);
glut.glutSolidSphere(r, 16, 16);
zN += dzN;
}
else
{
//flash
if(frame == tAnimazione1 * 60){
float[] lAmbiente = new float[]{1, 1, 1, 0};
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, lAmbiente, 0);
}
if(frame == (tAnimazione1 * 60) + 6){
float[] lAmbiente = new float[]{0, 0, 0, 0};
gl.glLightfv(GL2.GL_LIGHT0, GL2.GL_AMBIENT, lAmbiente, 0);
}
//raggio elementi
if(frame < (tAnimazione1 + tAnimazione2) * 60)
{
REl1 -= dREl1;
REl2 -= dREl2;
}
if(frame == (tAnimazione1 + tAnimazione2) * 60)
{
REl1 = 2.0;
REl2 = 2.25;
}
//colore elementi
if(xEl2 + REl2 < 0) {
gradient -= 0.01;
}
//movimento elementi
if(xEl1 < 4 * REl1)
{
xEl1 += 0.025 / ( 0.5 + (frame - (tAnimazione1 * 60.0)) / 120.0);
xEl2 -= 0.025 / ( 0.5 + (frame - (tAnimazione1 * 60.0)) / 120.0);
zEl1 += 0.025 / ( 0.5 + (frame - (tAnimazione1 * 60.0)) / 120.0);
zEl2 += 0.025 / ( 0.5 + (frame - (tAnimazione1 * 60.0)) / 120.0);
}
//neutroni prodotti
gl.glLoadIdentity();
gl.glScaled(scale, scale, scale);
gl.glTranslated(xN1, yN1, zN1);
gl.glColor3d(0.8, 0.8, 0.8);
glut.glutSolidSphere(r, 16, 16);
gl.glLoadIdentity();
gl.glScaled(scale, scale, scale);
gl.glTranslated(xN2, yN2, zN2);
gl.glColor3d(0.8, 0.8, 0.8);
glut.glutSolidSphere(r, 16, 16);
gl.glLoadIdentity();
gl.glScaled(scale, scale, scale);
gl.glTranslated(xN3, yN3, zN3);
gl.glColor3d(0.8, 0.8, 0.8);
glut.glutSolidSphere(r, 16, 16);
zN1 += dzN1;
zN2 += dzN2;
zN3 += dzN3;
xN1 += dxN1;
xN2 += dxN2;
xN3 += dxN3;
yN1 += dyN1;
yN2 += dyN2;
yN3 += dyN3;
//tracce neutroni prodotti
tracciaN1.add(new Point(xN1,yN1,zN1));
if(tracciaN1.size() >= 40)
tracciaN1.remove(0);
tracciaN2.add(new Point(xN2,yN2,zN2));
if(tracciaN2.size() >= 40)
tracciaN2.remove(0);
tracciaN3.add(new Point(xN3,yN3,zN3));
if(tracciaN3.size() >= 40)
tracciaN3.remove(0);
gl.glLoadIdentity();
gl.glScaled(scale, scale, scale);
gl.glBegin(GL2.GL_LINES);
Point p1, p2;
for(int i = tracciaN1.size() - 1; i > 0; i--)
{
p1 = tracciaN1.get(i);
p2 = tracciaN1.get(i - 1);
gl.glColor3d(1 - 0.02 * (tracciaN1.size() - 1 - i), 1 - 0.02 * (tracciaN1.size() - 1 - i),1 - 0.02 * (tracciaN1.size() - 1 - i));
gl.glVertex3d(p1.getX(), p1.getY(), p1.getZ());
gl.glVertex3d(p2.getX(), p2.getY(), p2.getZ());
}
for(int i = tracciaN2.size() - 1; i > 0; i--)
{
p1 = tracciaN2.get(i);
p2 = tracciaN2.get(i - 1);
gl.glColor3d(1 - 0.02 * (tracciaN2.size() - 1 - i), 1 - 0.02 * (tracciaN2.size() - 1 - i),1 - 0.02 * (tracciaN2.size() - 1 - i));
gl.glVertex3d(p1.getX(), p1.getY(), p1.getZ());
gl.glVertex3d(p2.getX(), p2.getY(), p2.getZ());
}
for(int i = tracciaN3.size() - 1; i > 0; i--)
{
p1 = tracciaN3.get(i);
p2 = tracciaN3.get(i - 1);
gl.glColor3d(1 - 0.02 * (tracciaN3.size() - 1 - i), 1 - 0.02 * (tracciaN3.size() - 1 - i),1 - 0.02 * (tracciaN3.size() - 1 - i));
gl.glVertex3d(p1.getX(), p1.getY(), p1.getZ());
gl.glVertex3d(p2.getX(), p2.getY(), p2.getZ());
}
gl.glEnd();
if(frame > (tAnimazione1 + tAnimazione3) * 60)
{
reset();
}
}
//telecamera
if(frame < tAnimazione1 * 60)
{
rX += (180 - 240) / (tAnimazione1 * 60);
rY += (0 - 25) / (tAnimazione1 * 60);
scale += (2.2 - 1) / (tAnimazione1 * 60);
}
else
{
if(frame == tAnimazione1 * 60){
rX = 55;
rY = 10;
scale = 1;
}
if(frame < (tAnimazione1 + tAnimazione2) * 60){
rX += (-10 - 55) / ((tAnimazione2) * 60);
rY += (25 - 10) / ((tAnimazione2) * 60);
scale += (1 - 1) / ((tAnimazione2) * 60);
}
else
{
rX += (-140 + 10) / ((tAnimazione3 - tAnimazione2) * 60);
rY += (15 - 25) / ((tAnimazione3 - tAnimazione2) * 60);
scale += (0.9 - 1) / ((tAnimazione3 - tAnimazione2) * 60);
}
}
frame++;
}
@Override
public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h) {
GL2 gl = drawable.getGL().getGL2();
GLU glu = new GLU();
this.w = w;
this.h = h;
gl.glMatrixMode(GL2.GL_MODELVIEW);
gl.glLoadIdentity();
}
public void reset(){
frame = 0;
REl1 = R;
REl2 = R;
xEl1 = 0;
xEl2 = 0;
zEl1 = 0;
zEl2 = 0;
gradient = 1;
zN = -20;
xN1 = 0;
xN2 = 0;
xN3 = 0;
zN1 = 0;
zN2 = 0;
zN3 = 0;
yN1 = 0;
yN2 = 0;
yN3 = 0;
rX = 240;
rY = 25;
scale = 1;
tracciaN.clear();
tracciaN1.clear();
tracciaN2.clear();
tracciaN3.clear();
}
}
Point.java
public class Point {
double x, y, z;
public Point(double x, double y, double z) {
this.x = x;
this.y = y;
this.z = z;
}
public double getX() {
return x;
}
public void setX(double x) {
this.x = x;
}
public double getY() {
return y;
}
public void setY(double y) {
this.y = y;
}
public double getZ() {
return z;
}
public void setZ(double z) {
this.z = z;
}
}