package demos.nurbs.curveapp; import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayout; import java.awt.Insets; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent; import javax.media.opengl.GLProfile; import javax.media.opengl.GLCanvas; import javax.swing.ButtonGroup; import javax.swing.ImageIcon; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JOptionPane; import javax.swing.JPanel; import javax.swing.JPopupMenu; import javax.swing.JSeparator; import javax.swing.JSpinner; import javax.swing.JToggleButton; import javax.swing.JToolBar; import javax.swing.SpinnerNumberModel; import javax.swing.ToolTipManager; import demos.nurbs.icons.*; import demos.nurbs.knotslidercomponent.JKnotSlider; /** * Main class of application demostrating capabilities of JOGL when working with NURBS curves * Hlavní třída aplikace demonstrující shopnosti knihovny JOGL při práci s NURBS křivkami * @author Tomáš Hráský * */ @SuppressWarnings("serial") public class CurveApp extends JFrame implements ActionListener { /** * Name of X-coord editing component of actually selected control point * Jméno komponenty pro editaci X-ové souřadnice aktuálního bodu */ public static final String X_SPINNER_NAME = "xspinner"; /** * Name of Y-coord editing component of actually selected control point * Jméno komponenty pro editaci Y-ové souřadnice aktuálního bodu */ public static final String Y_SPINNER_NAME = "yspinner"; /** * Name of weight editing component of actually selected control point * Jméno komponenty pro editaci váhy aktuálního bodu */ public static final String W_SPINNER_NAME = "wspinner"; /** * Name of ADD CONTROL POINT event * Jméno události přidání řídícího bodu */ public static final String PRIDAT_AC = "PRIDAT"; /** * Name of SET CURVE DEGREE event * Jméno události zadání stupně křivky */ public static final String STUPEN_AC="STUPEN"; /** * Name of DELETE CONTROL POINT event * Jméno události smazání řídícího bodu */ public static final String SMAZAT_AC = "SMAZAT"; /** * Name of MAKE CLOSED KNOTVECTOR event * Jméno události vytvoření uzavřeného uzlového vektoru */ public static final String UZAVRENY_AC = "UZAVRENY"; /** * Name of MAKE OPEN (UNIFORM) KNOTVECTOR event * Jméno události vytvoření otevřeného (uniformního) uzlového vektoru */ public static final String OTEVRENY_AC = "OTEVRENY"; /** * Name of SAVE CURVE event * Jméno události uložení křivky */ public static final String ULOZIT_AC = "ULOZIT"; /** * Name of LOAD CURVE event * Jméno události načetení uložené definice křivky */ public static final String NACIST_AC = "NACIST"; /** * Name of MOVE CONTROL POINT event * Jméno události pohybu řídícího bodu */ private static final String MOVE_AC = "MOVE"; /** * Name of CREATE NEW CURVE event * Jméno události vytvoření nové křivky */ static final String NOVA_AC = "NEWCURVE"; /** * Name of EXIT APP event * Jméno události ukončení aplikace */ public static final String EXIT_AC = "EXIT"; /** * Name of SHOW ABOUT event * Jméno události zobrazení okna o aplikaci */ public static final String INFO_AC = "INFO"; /** * OpenGL canvas * Plátno pro vykreslování pomocí OpenGL */ private GLCanvas glCanvas; /** * X-coord editing component * Komponenta pro editaci X-ové souřadnice aktuálního bodu */ private JSpinner xSpinner; /** * Y-coord editing component * Komponenta pro editaci Y-ové souřadnice aktuálního bodu */ private JSpinner ySpinner; /** * Weight editing component * Komponenta pro editaci váhy aktuálního bodu */ private JSpinner wSpinner; /** * Mouse events listener * Listener událostí myši */ private CurveMouseListener mouseListener; /** * Knot vector editing component * Komponenta pro editaci uzlového vektoru */ private JKnotSlider knotSlider; /** * Start "move control point" mode * Tlačítko pro zapnutí módu pohybu řídících bodů */ private JToggleButton moveTB; /** * Constructor, initializes GUI * Konstruktor, vytvoří grafické uživatelské rozhraní */ public CurveApp() { super("Tomáš Hráský - example application demonstrating GLU NURBS capabilites - JOGL"); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); initGUI(); } /** * GUI initialization * Inicializace grafického uživatelského rozhraní */ private void initGUI() { JPopupMenu.setDefaultLightWeightPopupEnabled(false); ToolTipManager.sharedInstance().setLightWeightPopupEnabled(false); this.glCanvas = new GLCanvas(); glCanvas.setSize(new Dimension(750, 500)); glCanvas.addGLEventListener(new GLListener()); mouseListener = new CurveMouseListener(this); glCanvas.addMouseListener(mouseListener); glCanvas.addMouseMotionListener(mouseListener); setLayout(new GridBagLayout()); GridBagConstraints c = new GridBagConstraints(); c.fill = GridBagConstraints.BOTH; c.gridy = 0; c.gridwidth = GridBagConstraints.REMAINDER; ActListener listener = new ActListener(this); JMenuBar menuBar = new JMenuBar(); getContentPane().add(menuBar, c); //JMenu aplikaceMenu = new JMenu("Aplikace"); JMenu aplikaceMenu = new JMenu("Application"); menuBar.add(aplikaceMenu); //JMenuItem aboutMI=new JMenuItem("O aplikaci"); JMenuItem aboutMI=new JMenuItem("About"); aboutMI.setActionCommand(INFO_AC); aboutMI.addActionListener(listener); aplikaceMenu.add(aboutMI); aplikaceMenu.add(new JSeparator()); //JMenuItem konecMI=new JMenuItem("Ukončit"); JMenuItem konecMI=new JMenuItem("Exit"); konecMI.addActionListener(listener); konecMI.setActionCommand(EXIT_AC); aplikaceMenu.add(konecMI); //JMenu krivkaMenu = new JMenu("Křivka"); JMenu krivkaMenu = new JMenu("Curve"); menuBar.add(krivkaMenu); //JMenuItem pridatBodyMI = new JMenuItem("Přidat body"); JMenuItem pridatBodyMI = new JMenuItem("Add control points"); krivkaMenu.add(pridatBodyMI); pridatBodyMI.addActionListener(listener); pridatBodyMI.setActionCommand(PRIDAT_AC); JMenuItem smazatBodyMI = new JMenuItem( //"Smazat body"); "Delete points"); krivkaMenu.add(smazatBodyMI); smazatBodyMI.addActionListener(listener); smazatBodyMI.setActionCommand(SMAZAT_AC); //JMenuItem stupenMI=new JMenuItem("Zadat stupeň křivky"); JMenuItem stupenMI=new JMenuItem("Set curve degree"); krivkaMenu.add(stupenMI); stupenMI.addActionListener(listener); stupenMI.setActionCommand(STUPEN_AC); //JMenu knotVecMenu = new JMenu("Vytvořit uzlový vektor"); JMenu knotVecMenu = new JMenu("Create knot vector"); krivkaMenu.add(knotVecMenu); //JMenuItem clampedKVMI = new JMenuItem("Okrajový"); JMenuItem clampedKVMI = new JMenuItem("Clamped"); knotVecMenu.add(clampedKVMI); clampedKVMI.setActionCommand(UZAVRENY_AC); clampedKVMI.addActionListener(listener); //JMenuItem unclampedKVMI = new JMenuItem("Uniformní"); JMenuItem unclampedKVMI = new JMenuItem("Uniform"); knotVecMenu.add(unclampedKVMI); unclampedKVMI.setActionCommand(OTEVRENY_AC); unclampedKVMI.addActionListener(listener); //JMenuItem moveMI=new JMenuItem("Hýbat body"); JMenuItem moveMI=new JMenuItem("Move points"); krivkaMenu.add(moveMI); moveMI.setActionCommand(MOVE_AC); moveMI.addActionListener(listener); krivkaMenu.add(new JSeparator()); krivkaMenu.add(new JSeparator()); //JMenuItem novaMI=new JMenuItem("Nová křivka"); JMenuItem novaMI=new JMenuItem("New curve"); krivkaMenu.add(novaMI); novaMI.setActionCommand(NOVA_AC); novaMI.addActionListener(listener); //JMenuItem ulozitMI = new JMenuItem("Uložit křivku jako..."); JMenuItem ulozitMI = new JMenuItem("Save curve as..."); krivkaMenu.add(ulozitMI); ulozitMI.setActionCommand(ULOZIT_AC); ulozitMI.addActionListener(listener); //JMenuItem nacistMI = new JMenuItem("Načíst křivku"); JMenuItem nacistMI = new JMenuItem("Load curve"); krivkaMenu.add(nacistMI); nacistMI.setActionCommand(NACIST_AC); nacistMI.addActionListener(listener); c.gridy++; JToolBar toolBar = new JToolBar(); getContentPane().add(toolBar, c); ButtonGroup bg = new ButtonGroup(); JButton novaB=new JButton(); // novaB.setText("Nová"); //novaB.setToolTipText("Nová křivka"); novaB.setToolTipText("New curve"); novaB.setIcon(IconFactory.getIcon("demos/nurbs/icons/folder_new.png")); novaB.setActionCommand(NOVA_AC); novaB.addActionListener(listener); toolBar.add(novaB); JButton ulozitB=new JButton(); ulozitB.setIcon(IconFactory.getIcon("demos/nurbs/icons/adept_sourceseditor.png")); // ulozitB.setText("Uložit"); //ulozitB.setToolTipText("Uložit"); ulozitB.setToolTipText("Save"); ulozitB.setActionCommand(ULOZIT_AC); ulozitB.addActionListener(listener); toolBar.add(ulozitB); JButton nahratB=new JButton(); // nahratB.setText("Nahrát"); //nahratB.setToolTipText("Nahrát uloženou křivku"); nahratB.setToolTipText("Load curve"); nahratB.setIcon(IconFactory.getIcon("demos/nurbs/icons/fileimport.png")); nahratB.setActionCommand(NACIST_AC); nahratB.addActionListener(listener); toolBar.add(nahratB); toolBar.add(new JToolBar.Separator()); JToggleButton pridatTB = new JToggleButton(); // pridatTB.setText("Přidat body"); //pridatTB.setToolTipText("Přidat body"); pridatTB.setToolTipText("Add points"); toolBar.add(pridatTB); pridatTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/add.png")); pridatTB.setActionCommand(PRIDAT_AC); pridatTB.addActionListener(listener); bg.add(pridatTB); JToggleButton smazatTB = new JToggleButton(); // smazatTB.setText("Smazat body"); //smazatTB.setToolTipText("Smazat body"); smazatTB.setToolTipText("Delete points"); toolBar.add(smazatTB); smazatTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/fileclose.png")); smazatTB.setActionCommand(SMAZAT_AC); smazatTB.addActionListener(listener); bg.add(smazatTB); JToggleButton stupenTB = new JToggleButton(); // stupenTB.setText("Smazat body"); //stupenTB.setToolTipText("Zadat stupeň křivky"); stupenTB.setToolTipText("Set curve degree"); toolBar.add(stupenTB); stupenTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/math_rsup.png")); stupenTB.setActionCommand(STUPEN_AC); stupenTB.addActionListener(listener); bg.add(stupenTB); final JPopupMenu popup = new JPopupMenu(); //JMenuItem uzavrenyPopupMI = new JMenuItem("Okrajový"); JMenuItem uzavrenyPopupMI = new JMenuItem("Clamped"); popup.add(uzavrenyPopupMI); uzavrenyPopupMI.setActionCommand(UZAVRENY_AC); uzavrenyPopupMI.addActionListener(listener); //JMenuItem otevrenyPopupMI = new JMenuItem("Uniformní"); JMenuItem otevrenyPopupMI = new JMenuItem("Uniform"); popup.add(otevrenyPopupMI); otevrenyPopupMI.setActionCommand(OTEVRENY_AC); otevrenyPopupMI.addActionListener(listener); JToggleButton vytvoritButton = new JToggleButton(); // vytvoritButton.setText("Vytvořit uzlový vektor"); //vytvoritButton.setToolTipText("Vytvořit uzlový vektor"); vytvoritButton.setToolTipText("Create knot vector"); vytvoritButton.setIcon(IconFactory.getIcon("demos/nurbs/icons/newfunction.png")); bg.add(vytvoritButton); vytvoritButton.addMouseListener(new /** * @author Tomáš Hráský * Class connecting context menu to button on toolbar * Třída pro připojení kontextového menu na tlačítko na liště nástrojů */ MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { super.mouseClicked(e); e.isPopupTrigger(); popup.show(e.getComponent(), e.getX(), e.getY()); } }); popup.setInvoker(vytvoritButton); toolBar.add(vytvoritButton); moveTB=new JToggleButton(); // moveTB.setText("Hýbat body"); //moveTB.setToolTipText("Hýbat body"); moveTB.setToolTipText("Move points"); moveTB.setIcon(IconFactory.getIcon("demos/nurbs/icons/mouse.png")); toolBar.add(moveTB); moveTB.setActionCommand(MOVE_AC); moveTB.addActionListener(listener); bg.add(moveTB); toolBar.add(new JToolBar.Separator()); JButton infoB=new JButton(); // infoB.setText("Ukončit"); //infoB.setToolTipText("O aplikaci"); infoB.setToolTipText("About"); infoB.setIcon(IconFactory.getIcon("demos/nurbs/icons/info.png")); toolBar.add(infoB); infoB.setActionCommand(INFO_AC); infoB.addActionListener(listener); toolBar.add(new JToolBar.Separator()); JButton exitB=new JButton(); // exitB.setText("Ukončit"); //exitB.setToolTipText("Ukončit"); exitB.setToolTipText("Exit"); exitB.setIcon(IconFactory.getIcon("demos/nurbs/icons/exit.png")); toolBar.add(exitB); exitB.setActionCommand(EXIT_AC); exitB.addActionListener(listener); c.gridwidth = 1; c.gridx = 0; c.gridy = 2; c.weightx = 1; c.weighty = 1; getContentPane().add(glCanvas, c); c.gridx = 1; JPanel rightPanel = new JPanel(new GridBagLayout()); GridBagConstraints cc = new GridBagConstraints(); cc.insets = new Insets(5, 5, 5, 5); xSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000.0, 1)); ySpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000.0, 1)); wSpinner = new JSpinner(new SpinnerNumberModel(0, 0, 10000.0, .05)); SpinnerListener spinnerListener = new SpinnerListener(this); xSpinner.addChangeListener(spinnerListener); xSpinner.setName(X_SPINNER_NAME); ySpinner.addChangeListener(spinnerListener); ySpinner.setName(Y_SPINNER_NAME); wSpinner.addChangeListener(spinnerListener); wSpinner.setName(W_SPINNER_NAME); cc.gridx = 0; cc.gridy = 0; cc.gridwidth = 2; cc.weighty = 1; rightPanel.add(new JPanel(), cc); cc.weighty = 0; cc.gridwidth = 1; cc.gridy++; rightPanel.add(new JLabel("X"), cc); cc.gridy++; rightPanel.add(new JLabel("Y"), cc); cc.gridy++; rightPanel.add(new JLabel("W"), cc); cc.gridx = 1; cc.gridy = 1; rightPanel.add(xSpinner, cc); cc.gridy++; rightPanel.add(ySpinner, cc); cc.gridy++; rightPanel.add(wSpinner, cc); xSpinner.setEnabled(false); ySpinner.setEnabled(false); wSpinner.setEnabled(false); c.weightx = 0; c.weighty = 0; getContentPane().add(rightPanel, c); c.gridx = 0; c.gridy++; knotSlider = new JKnotSlider(Curve.getInstance().getKnots()); knotSlider.addActionListener(this); getContentPane().add(knotSlider, c); pack(); invalidate(); setVisible(true); } /** * Main method starting application * Metoda pro spuštění aplikace * @param args no arguments accepted * */ public static void main(String[] args) { // set argument 'NotFirstUIActionOnProcess' in the JNLP's application-desc tag for example // // NotFirstUIActionOnProcess // boolean firstUIActionOnProcess = 0==args.length || !args[0].equals("NotFirstUIActionOnProcess") ; GLProfile.initSingleton(firstUIActionOnProcess); new CurveApp(); } /** * Reaction to request for redrive OpenGL canvas - repaints canvas, sets actually selected control points coords to editing components * Reakce na požadavek překreslení OpenGL plátna, překreslí plátno a nastaví souřadnice aktuálního vybraného bodu do editačních komponent */ public void updateGLCanvas() { glCanvas.repaint(); if (Curve.getInstance().getBodIndex() >= 0) { xSpinner.setEnabled(true); ySpinner.setEnabled(true); wSpinner.setEnabled(true); xSpinner.setValue(Double.valueOf(Math.round(Curve.getInstance() .getActiveX()))); ySpinner.setValue(Double.valueOf(Math.round(Curve.getInstance() .getActiveY()))); wSpinner.setValue(Double.valueOf(Curve.getInstance().getActiveW())); } else { xSpinner.setEnabled(false); ySpinner.setEnabled(false); wSpinner.setEnabled(false); } } /* (non-Javadoc) * @see java.awt.event.ActionListener#actionPerformed(java.awt.event.ActionEvent) */ public void actionPerformed(ActionEvent e) { JKnotSlider src = (JKnotSlider) e.getSource(); if(src.checkKnotMulti(Curve.getInstance().getOrder())){ Curve.getInstance().setKnots(src.getKnotsFloat()); }else{ //JOptionPane.showMessageDialog(this,"Překročení maximální násobnosti uzlu","Chyba",JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(this,"Maximum knot multiplicity exceeded","Error",JOptionPane.ERROR_MESSAGE); src.setKnots(Curve.getInstance().getKnots()); } updateGLCanvas(); } /** * Returns OpenGL canvas * Vrací OpenGL plátno * @return OpenGL canvas */ public GLCanvas getGlCanvas() { return glCanvas; } /** * Returns mouse events listener * Vrací listener událostí myši * @return mouse listener */ public CurveMouseListener getMouseListener() { return mouseListener; } /** * Creates NURBS curve with clamped knot vector * Vytvoří NURBS křivku s okrajovým uzlovým vektorem */ public void uzavernyKV() { int stupen = Curve.getInstance().getOrder(); int pocetBodu = Curve.getInstance().getCtrlPoints().length / 4; if (stupen <= pocetBodu) { int knotCount = stupen + pocetBodu; int middlePartSize = knotCount - 2 * stupen; float[] newKnots = new float[knotCount]; int i; int j = 0; float middleStep = 1f / (middlePartSize + 2); float knot = middleStep; // knot=.5f; for (i = 0; i < stupen; i++) newKnots[j++] = 0; for (i = 0; i < middlePartSize; i++) { newKnots[j++] = knot; knot += middleStep; } for (i = 0; i < stupen; i++) newKnots[j++] = 1; postNewKnot(newKnots); } else //errorMessage("Malý počet řídících bodů vzhledem k zadanému stupni křivky"); errorMessage("Too few control points regarding set curve degree"); } /** * Displays modal window with error report * Zobrazí modální okno s hlášením chyby * @param error error message */ public void errorMessage(String error){ //JOptionPane.showMessageDialog(this,error,"Chyba!",JOptionPane.ERROR_MESSAGE); JOptionPane.showMessageDialog(this,error,"Error!",JOptionPane.ERROR_MESSAGE); } /** * Creates NURBS curves with uniform knot vector * Vytvoří NURBS křivku s uniformním uzlovým vektorem */ public void otevrenyKV() { int stupen = Curve.getInstance().getOrder(); int pocetBodu = Curve.getInstance().getCtrlPoints().length / 4; if (stupen <= pocetBodu) { int knotCount = stupen + pocetBodu; int middlePartSize = knotCount; float[] newKnots = new float[knotCount]; int i; int j = 0; float middleStep = 1f / (middlePartSize - 1); float knot = 0; // knot=.5f; // for(i=0;i