+++ /dev/null
-/*
- * Sixth 3D engine. Copyright ©2012-2018, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 3 of the GNU Lesser General Public License
- * or later as published by the Free Software Foundation.
- *
- */
-
-package eu.svjatoslav.sixth.e3d.gui;
-
-import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseInteractionController;
-
-import javax.swing.*;
-import java.awt.*;
-import java.awt.event.ComponentEvent;
-import java.awt.event.ComponentListener;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Timer;
-
-public class View extends JPanel implements ComponentListener {
-
- private static final long serialVersionUID = 1683277888885045387L;
- private final List<ViewListener> viewListeners = new ArrayList<>();
- private final List<ViewRenderListener> viewRenderListeners = new ArrayList<>();
- private final ViewContext context = new ViewContext(this);
- /**
- * Last time this view was updated
- */
- long lastUpdateMillis = 0;
- private Timer canvasUpdateTimer;
- private ViewUpdateTimerTask canvasUpdateTimerTask;
- private RenderingContext renderingContext = null;
- private MouseInteractionController currentMouseOverComponent;
- /**
- * Currently target FPS for this view. It might change at runtime.
- */
- private int targetFramerate = 30;
- private boolean repaintDuringNextViewUpdate = true;
-
- public View() {
- viewRenderListeners.add(context.getAvatar());
-
- // initialize input tracker
- context.getUserInputTracker().bind(this);
- viewRenderListeners.add(context.getUserInputTracker());
-
- initializePanelLayout();
-
- setFrameRate(targetFramerate);
-
- addComponentListener(this);
- }
-
- public void addViewListener(final ViewListener listener) {
- getViewListeners().add(listener);
- }
-
- public void addViewUpdateListener(final ViewRenderListener listener) {
- viewRenderListeners.add(listener);
- }
-
- @Override
- public void componentHidden(final ComponentEvent e) {
-
- }
-
- @Override
- public void componentMoved(final ComponentEvent e) {
-
- }
-
- @Override
- public void componentResized(final ComponentEvent e) {
- repaintDuringNextViewUpdate = true;
- }
-
- @Override
- public void componentShown(final ComponentEvent e) {
- repaintDuringNextViewUpdate = true;
- }
-
- public ViewContext getContext() {
- return context;
- }
-
- @Override
- public Dimension getMaximumSize() {
- return getPreferredSize();
- }
-
- @Override
- public Dimension getMinimumSize() {
- return getPreferredSize();
- }
-
- @Override
- public java.awt.Dimension getPreferredSize() {
- return new java.awt.Dimension(640, 480);
- }
-
- public RenderingContext getRenderBuffer() {
- return renderingContext;
- }
-
- public RenderingContext getRenderingContext() {
- return renderingContext;
- }
-
- public List<ViewListener> getViewListeners() {
- return viewListeners;
- }
-
- private void handleDetectedComponentMouseEvents() {
- if (renderingContext.clickedItem != null) {
- if (renderingContext.mouseClick.button == 0) {
- // mouse over
- if (currentMouseOverComponent == null) {
- currentMouseOverComponent = renderingContext.clickedItem;
- currentMouseOverComponent.mouseEntered();
- repaintDuringNextViewUpdate = true;
- } else if (currentMouseOverComponent != renderingContext.clickedItem) {
- currentMouseOverComponent.mouseExited();
- currentMouseOverComponent = renderingContext.clickedItem;
- currentMouseOverComponent.mouseEntered();
- repaintDuringNextViewUpdate = true;
- }
- } else {
- // mouse click
- renderingContext.clickedItem.mouseClicked();
- repaintDuringNextViewUpdate = true;
- }
- } else if (currentMouseOverComponent != null) {
- currentMouseOverComponent.mouseExited();
- repaintDuringNextViewUpdate = true;
- currentMouseOverComponent = null;
- }
- }
-
- private void initializePanelLayout() {
- setFocusCycleRoot(true);
- setOpaque(true);
- setFocusable(true);
- setDoubleBuffered(false);
- setVisible(true);
- requestFocusInWindow();
- }
-
- public void renderFrame() {
- // build new render buffer if needed, this happens when window was just
- // created or resized
- if ((renderingContext == null)
- || (renderingContext.width != getWidth())
- || (renderingContext.height != getHeight()))
- renderingContext = new RenderingContext(getWidth(), getHeight());
-
- // clear drawing area
- {
- renderingContext.graphics.setColor(Color.BLACK);
- renderingContext.graphics.fillRect(0, 0, getWidth(), getHeight());
- }
-
- // paint root geometry collection to the offscreen render buffer
- context.getRootShapeCollection().paint(context, renderingContext);
-
- // draw rendered offscreen image to visible screen
- final Graphics graphics = getGraphics();
- if (graphics != null)
- graphics.drawImage(renderingContext.bufferedImage, 0, 0, null);
- }
-
- /**
- * Calling this methods tells 3D engine that current 3D view needs to be
- * repainted on first opportunity.
- */
- public void repaintDuringNextViewUpdate() {
- repaintDuringNextViewUpdate = true;
- }
-
- public void setFrameRate(final int frameRate) {
- if (canvasUpdateTimerTask != null) {
- canvasUpdateTimerTask.cancel();
- canvasUpdateTimerTask = null;
-
- canvasUpdateTimer.cancel();
- canvasUpdateTimer = null;
- }
-
- targetFramerate = frameRate;
-
- if (frameRate > 0) {
- canvasUpdateTimer = new Timer();
- canvasUpdateTimerTask = new ViewUpdateTimerTask(this);
-
- canvasUpdateTimer.schedule(canvasUpdateTimerTask, 0,
- 1000 / frameRate);
- }
- }
-
- public void stop() {
- if (canvasUpdateTimerTask != null) {
- canvasUpdateTimerTask.cancel();
- canvasUpdateTimerTask = null;
- }
-
- if (canvasUpdateTimer != null) {
- canvasUpdateTimer.cancel();
- canvasUpdateTimer = null;
- }
- }
-
- /**
- * This method is executed by periodic timer task, in frequency according to
- * defined frame rate.
- * <p>
- * It tells view to update itself. View can decide if actual re-rendering of
- * graphics is needed.
- */
- public void updateView() {
- if (renderingContext != null){
- renderingContext.mouseClick = null;
- renderingContext.clickedItem = null;
- }
-
- // compute time passed since last view update
- final long currentTime = System.currentTimeMillis();
-
- if (lastUpdateMillis == 0) {
- lastUpdateMillis = currentTime;
- return;
- }
-
- final int millisecondsPassedSinceLastUpdate = (int) (currentTime - lastUpdateMillis);
- lastUpdateMillis = currentTime;
-
- // notify update listeners
- boolean reRenderFrame = false;
-
- for (final ViewRenderListener listener : viewRenderListeners)
- if (listener.beforeRender(context,
- millisecondsPassedSinceLastUpdate))
- reRenderFrame = true;
-
- // abort rendering if window size is invalid
- if ((getWidth() <= 0) || (getHeight() <= 0))
- return;
-
- if (repaintDuringNextViewUpdate) {
- repaintDuringNextViewUpdate = false;
- reRenderFrame = true;
- }
-
- if (reRenderFrame) {
- renderFrame();
- handleDetectedComponentMouseEvents();
- }
- }
-}
private final Avatar avatar = new Avatar();
- private final View view;
+ private final ViewPanel viewPanel;
private final ShapeCollection rootShapeCollection = new ShapeCollection();
- public ViewContext(final View view) {
- this.view = view;
+ public ViewContext(final ViewPanel viewPanel) {
+ this.viewPanel = viewPanel;
}
public Avatar getAvatar() {
return userInputTracker;
}
- public View getView() {
- return view;
+ public ViewPanel getViewPanel() {
+ return viewPanel;
}
}
import java.awt.event.WindowEvent;
import java.awt.event.WindowListener;
-public class ViewFrame extends JFrame implements ViewListener, WindowListener {
+public class ViewFrame extends JFrame implements WindowListener {
private static final long serialVersionUID = -7037635097739548470L;
- private final View view;
+ private final ViewPanel viewPanel;
public ViewFrame() {
setTitle("3D engine");
}
});
- view = new View();
+ viewPanel = new ViewPanel();
- add(getView());
-
- getView().addViewListener(this);
+ add(getViewPanel());
setSize(800, 600);
@Override
public void componentShown(final ComponentEvent e) {
- view.repaintDuringNextViewUpdate();
+ viewPanel.repaintDuringNextViewUpdate();
}
});
}
- @Override
public void exit() {
- if (getView() != null) {
- getView().stop();
- getView().setEnabled(false);
- getView().setVisible(false);
+ if (getViewPanel() != null) {
+ getViewPanel().stop();
+ getViewPanel().setEnabled(false);
+ getViewPanel().setVisible(false);
}
dispose();
}
/**
* @return the view
*/
- public View getView() {
- return view;
+ public ViewPanel getViewPanel() {
+ return viewPanel;
}
@Override
public void windowActivated(final WindowEvent e) {
- view.repaintDuringNextViewUpdate();
+ viewPanel.repaintDuringNextViewUpdate();
}
@Override
@Override
public void windowDeiconified(final WindowEvent e) {
- view.repaintDuringNextViewUpdate();
+ viewPanel.repaintDuringNextViewUpdate();
}
@Override
@Override
public void windowOpened(final WindowEvent e) {
- view.repaintDuringNextViewUpdate();
+ viewPanel.repaintDuringNextViewUpdate();
}
}
+++ /dev/null
-/*
- * Sixth 3D engine. Copyright ©2012-2018, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of version 3 of the GNU Lesser General Public License
- * or later as published by the Free Software Foundation.
- *
- */
-
-package eu.svjatoslav.sixth.e3d.gui;
-
-public interface ViewListener {
-
- void exit();
-
-}
--- /dev/null
+/*
+ * Sixth 3D engine. Copyright ©2012-2018, Svjatoslav Agejenko, svjatoslav@svjatoslav.eu
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of version 3 of the GNU Lesser General Public License
+ * or later as published by the Free Software Foundation.
+ *
+ */
+
+package eu.svjatoslav.sixth.e3d.gui;
+
+import eu.svjatoslav.sixth.e3d.gui.humaninput.MouseInteractionController;
+
+import javax.swing.*;
+import java.awt.*;
+import java.awt.event.ComponentEvent;
+import java.awt.event.ComponentListener;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Timer;
+
+public class ViewPanel extends JPanel implements ComponentListener {
+
+ private static final long serialVersionUID = 1683277888885045387L;
+ private final List<ViewRenderListener> viewRenderListeners = new ArrayList<>();
+ private final ViewContext context = new ViewContext(this);
+ /**
+ * Last time this view was updated.
+ */
+ private long lastUpdateMillis = 0;
+ private Timer canvasUpdateTimer;
+ private ViewUpdateTimerTask canvasUpdateTimerTask;
+ private RenderingContext renderingContext = null;
+ private MouseInteractionController currentMouseOverComponent;
+ /**
+ * Currently target FPS for this view. It might change at runtime.
+ */
+ private int targetFramerate = 30;
+ private boolean repaintDuringNextViewUpdate = true;
+
+ public ViewPanel() {
+ viewRenderListeners.add(context.getAvatar());
+
+ // initialize input tracker
+ context.getUserInputTracker().bind(this);
+ viewRenderListeners.add(context.getUserInputTracker());
+
+ initializePanelLayout();
+
+ setFrameRate(targetFramerate);
+
+ addComponentListener(this);
+ }
+
+ public void addViewUpdateListener(final ViewRenderListener listener) {
+ viewRenderListeners.add(listener);
+ }
+
+ @Override
+ public void componentHidden(final ComponentEvent e) {
+
+ }
+
+ @Override
+ public void componentMoved(final ComponentEvent e) {
+
+ }
+
+ @Override
+ public void componentResized(final ComponentEvent e) {
+ repaintDuringNextViewUpdate = true;
+ }
+
+ @Override
+ public void componentShown(final ComponentEvent e) {
+ repaintDuringNextViewUpdate = true;
+ }
+
+ public ViewContext getContext() {
+ return context;
+ }
+
+ @Override
+ public Dimension getMaximumSize() {
+ return getPreferredSize();
+ }
+
+ @Override
+ public Dimension getMinimumSize() {
+ return getPreferredSize();
+ }
+
+ @Override
+ public java.awt.Dimension getPreferredSize() {
+ return new java.awt.Dimension(640, 480);
+ }
+
+ public RenderingContext getRenderBuffer() {
+ return renderingContext;
+ }
+
+ public RenderingContext getRenderingContext() {
+ return renderingContext;
+ }
+
+ private void handleDetectedComponentMouseEvents() {
+ if (renderingContext.clickedItem != null) {
+ if (renderingContext.mouseClick.button == 0) {
+ // mouse over
+ if (currentMouseOverComponent == null) {
+ currentMouseOverComponent = renderingContext.clickedItem;
+ currentMouseOverComponent.mouseEntered();
+ repaintDuringNextViewUpdate = true;
+ } else if (currentMouseOverComponent != renderingContext.clickedItem) {
+ currentMouseOverComponent.mouseExited();
+ currentMouseOverComponent = renderingContext.clickedItem;
+ currentMouseOverComponent.mouseEntered();
+ repaintDuringNextViewUpdate = true;
+ }
+ } else {
+ // mouse click
+ renderingContext.clickedItem.mouseClicked();
+ repaintDuringNextViewUpdate = true;
+ }
+ } else if (currentMouseOverComponent != null) {
+ currentMouseOverComponent.mouseExited();
+ repaintDuringNextViewUpdate = true;
+ currentMouseOverComponent = null;
+ }
+ }
+
+ private void initializePanelLayout() {
+ setFocusCycleRoot(true);
+ setOpaque(true);
+ setFocusable(true);
+ setDoubleBuffered(false);
+ setVisible(true);
+ requestFocusInWindow();
+ }
+
+ public void renderFrame() {
+ // build new render buffer if needed, this happens when window was just
+ // created or resized
+ if ((renderingContext == null)
+ || (renderingContext.width != getWidth())
+ || (renderingContext.height != getHeight()))
+ renderingContext = new RenderingContext(getWidth(), getHeight());
+
+ // clear drawing area
+ {
+ renderingContext.graphics.setColor(Color.BLACK);
+ renderingContext.graphics.fillRect(0, 0, getWidth(), getHeight());
+ }
+
+ // paint root geometry collection to the offscreen render buffer
+ context.getRootShapeCollection().paint(context, renderingContext);
+
+ // draw rendered offscreen image to visible screen
+ final Graphics graphics = getGraphics();
+ if (graphics != null)
+ graphics.drawImage(renderingContext.bufferedImage, 0, 0, null);
+ }
+
+ /**
+ * Calling this methods tells 3D engine that current 3D view needs to be
+ * repainted on first opportunity.
+ */
+ public void repaintDuringNextViewUpdate() {
+ repaintDuringNextViewUpdate = true;
+ }
+
+ public void setFrameRate(final int frameRate) {
+ if (canvasUpdateTimerTask != null) {
+ canvasUpdateTimerTask.cancel();
+ canvasUpdateTimerTask = null;
+
+ canvasUpdateTimer.cancel();
+ canvasUpdateTimer = null;
+ }
+
+ targetFramerate = frameRate;
+
+ if (frameRate > 0) {
+ canvasUpdateTimer = new Timer();
+ canvasUpdateTimerTask = new ViewUpdateTimerTask(this);
+
+ canvasUpdateTimer.schedule(canvasUpdateTimerTask, 0,
+ 1000 / frameRate);
+ }
+ }
+
+ public void stop() {
+ if (canvasUpdateTimerTask != null) {
+ canvasUpdateTimerTask.cancel();
+ canvasUpdateTimerTask = null;
+ }
+
+ if (canvasUpdateTimer != null) {
+ canvasUpdateTimer.cancel();
+ canvasUpdateTimer = null;
+ }
+ }
+
+ /**
+ * This method is executed by periodic timer task, in frequency according to
+ * defined frame rate.
+ * <p>
+ * It tells view to update itself. View can decide if actual re-rendering of
+ * graphics is needed.
+ */
+ public void updateView() {
+ if (renderingContext != null){
+ renderingContext.mouseClick = null;
+ renderingContext.clickedItem = null;
+ }
+
+ // compute time passed since last view update
+ final long currentTime = System.currentTimeMillis();
+
+ if (lastUpdateMillis == 0) {
+ lastUpdateMillis = currentTime;
+ return;
+ }
+
+ final int millisecondsPassedSinceLastUpdate = (int) (currentTime - lastUpdateMillis);
+ lastUpdateMillis = currentTime;
+
+ // notify update listeners
+ boolean reRenderFrame = false;
+
+ for (final ViewRenderListener listener : viewRenderListeners)
+ if (listener.beforeRender(context,
+ millisecondsPassedSinceLastUpdate))
+ reRenderFrame = true;
+
+ // abort rendering if window size is invalid
+ if ((getWidth() <= 0) || (getHeight() <= 0))
+ return;
+
+ if (repaintDuringNextViewUpdate) {
+ repaintDuringNextViewUpdate = false;
+ reRenderFrame = true;
+ }
+
+ if (reRenderFrame) {
+ renderFrame();
+ handleDetectedComponentMouseEvents();
+ }
+ }
+}
public class ViewUpdateTimerTask extends java.util.TimerTask {
- public View view;
+ public ViewPanel viewPanel;
- public ViewUpdateTimerTask(final View view) {
- this.view = view;
+ public ViewUpdateTimerTask(final ViewPanel viewPanel) {
+ this.viewPanel = viewPanel;
}
@Override
public void run() {
// update and possibly render view
- view.updateView();
+ viewPanel.updateView();
}
}
import eu.svjatoslav.sixth.e3d.geometry.Point2D;
import eu.svjatoslav.sixth.e3d.gui.Avatar;
-import eu.svjatoslav.sixth.e3d.gui.View;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
import eu.svjatoslav.sixth.e3d.gui.ViewContext;
import eu.svjatoslav.sixth.e3d.gui.ViewRenderListener;
@Override
public boolean beforeRender(final ViewContext viewContext, final int millisecondsSinceLastFrame) {
- boolean viewUpdateNeeded = handleDetectedMouseClicks(viewContext.getView());
+ boolean viewUpdateNeeded = handleDetectedMouseClicks(viewContext.getViewPanel());
viewUpdateNeeded |= handleDetectedKeyEvents();
/**
* @return <code>true</code> if view needs to be repainted.
*/
- private synchronized boolean handleDetectedMouseClicks(final View view) {
+ private synchronized boolean handleDetectedMouseClicks(final ViewPanel viewPanel) {
if (detectedMouseClicks.isEmpty()) {
if (currentMouseLocation != null)
- view.getRenderingContext().mouseClick = new MouseClick(currentMouseLocation, 0);
+ viewPanel.getRenderingContext().mouseClick = new MouseClick(currentMouseLocation, 0);
if (mouseMoved) {
mouseMoved = false;
return false;
}
- view.getRenderingContext().mouseClick = detectedMouseClicks.remove(0);
+ viewPanel.getRenderingContext().mouseClick = detectedMouseClicks.remove(0);
return true;
}
synchronized (detectedKeyEvents) {
pressedKeysToPressedTimeMap.put(evt.getKeyCode(), System.currentTimeMillis());
detectedKeyEvents.add(evt);
- viewContext.getView().repaintDuringNextViewUpdate();
+ viewContext.getViewPanel().repaintDuringNextViewUpdate();
}
}
synchronized (detectedKeyEvents) {
pressedKeysToPressedTimeMap.remove(evt.getKeyCode());
detectedKeyEvents.add(evt);
- viewContext.getView().repaintDuringNextViewUpdate();
+ viewContext.getViewPanel().repaintDuringNextViewUpdate();
}
}
package eu.svjatoslav.sixth.e3d.renderer.octree.raytracer;
-import eu.svjatoslav.sixth.e3d.gui.View;
+import eu.svjatoslav.sixth.e3d.gui.ViewPanel;
import eu.svjatoslav.sixth.e3d.renderer.octree.OctreeVolume;
import eu.svjatoslav.sixth.e3d.renderer.raster.Color;
import eu.svjatoslav.sixth.e3d.renderer.raster.texture.Texture;
private static final int PROGRESS_UPDATE_FREQUENCY_MILLIS = 1000;
private final Camera camera;
private final Texture texture;
- private final View view;
+ private final ViewPanel viewPanel;
private OctreeVolume octreeVolume;
private Vector<LightSource> lights;
private int computedLights;
public RayTracer(final Texture texture, final OctreeVolume octreeVolume,
final Vector<LightSource> lights, final Camera camera,
- final View view) {
+ final ViewPanel viewPanel) {
this.texture = texture;
this.octreeVolume = octreeVolume;
this.lights = lights;
this.camera = camera;
- this.view = view;
+ this.viewPanel = viewPanel;
}
@Override
nextBitmapUpdate = System.currentTimeMillis()
+ PROGRESS_UPDATE_FREQUENCY_MILLIS;
texture.resetResampledBitmapCache();
- view.repaintDuringNextViewUpdate();
+ viewPanel.repaintDuringNextViewUpdate();
}
}
texture.resetResampledBitmapCache();
- view.repaintDuringNextViewUpdate();
+ viewPanel.repaintDuringNextViewUpdate();
// System.out.println("Raytracing done.");
// System.out.println("New lights computed:" + computedLights);
}