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 ArrayListtracciaN = 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; } }