📄 jcanvas3d.java
字号:
} /** * Creates an offscreen buffer to be attached to the heavyweight * buffer. Buffer is created 'byreference' * * @param width the width of the buffer. * @param height the height of the buffer. */ private void createOffScreenBuffer(int width, int height) { computePhysicalDimensions(); // this.canvas.setDoubleBufferEnable( false ); java.awt.image.BufferedImage bImage = new java.awt.image.BufferedImage(width, height, java.awt.image.BufferedImage.TYPE_INT_ARGB); javax.media.j3d.ImageComponent2D image = new javax.media.j3d.ImageComponent2D(javax.media.j3d.ImageComponent2D.FORMAT_RGBA8, bImage, true, false ); image.setCapability(image.ALLOW_IMAGE_READ); image.setCapability(image.ALLOW_IMAGE_WRITE); this.canvas.stopRenderer(); // offscreenrendering might occur even if the renderer is stopped. For that reason, i'm waiting for an hypothetical offscreen render to finish before setting offscreen rendering. // Otherwise, rendering will stop with an exception. this.canvas.waitForOffScreenRendering(); this.canvas.setOffScreenBuffer(image); this.canvas.startRenderer(); } /** * Returns the offscreen heavyweight canvas of that lightweight * component. * * @return the heavyweight canvas that lies in the deepness of this * Component. */ public Canvas3D getOffscreenCanvas3D() { if (null == this.canvas) { createCanvas(getWidth(), getHeight()); } return this.canvas; } /** * Retrieves the resize mode for that component. * * @return the resize mode, which can be one of RESIZE_IMMEDIATELY or * RESIZE_DELAYED */ public int getResizeMode() { return resizeMode; } /** * Retrieves the validation delay for that canvas, whatever the * resize mode is set to. * * @return the validation delay. */ public int getResizeValidationDelay() { return resizeValidationDelay; } /** * Paints the result of the rendering. If the rendered buffer is * not useable (render thread being between [code]postRender()[/code] and * [code]postSwap()[/code]), it will wait for it to be ready. Otherwise it * will directly paint the previous buffer. * * @param g {@inheritDoc} */ public void paintComponent(java.awt.Graphics g) { super.paintComponent(g); //paint background // Wait for and display image if JCanvas3D was added to an ancestor if (hasBeenAdded) { if ((false == canvas.canvasCrashed) && (true == canvas.isRendererRunning())) { // System.err.println("paintComponentWaitforSwap"); canvas.waitForSwap(); // System.err.println("wait is over"); } if (null != canvas.bi) { // can eventually be null if the canvas did not send the result in the desired timeframe // for first render. In that case, we don't paint and keep the background as-is. g.drawImage(canvas.bi, 0, 0, getWidth(), getHeight(), null); } } } /** * Redirects event to canvas and to superclass. * * @param e {@inheritDoc} */ protected void processComponentKeyEvent(java.awt.event.KeyEvent e) { super.processComponentKeyEvent(e); Object src = e.getSource(); e.setSource(canvas); canvas.processComponentEvent(e); e.setSource(src); } /** * Redirects event to canvas and to superclass. * * @param e {@inheritDoc} */ protected void processFocusEvent(java.awt.event.FocusEvent e) { super.processFocusEvent(e); Object src = e.getSource(); e.setSource(canvas); canvas.processFocusEvent(e); e.setSource(src); } /** * Redirects event to canvas and to superclass. * * @param e {@inheritDoc} */ protected void processInputMethodEvent(java.awt.event.InputMethodEvent e) { super.processInputMethodEvent(e); Object src = e.getSource(); e.setSource(canvas); canvas.processInputMethodEvent(e); e.setSource(src); } /** * Redirects event to canvas and to superclass. * * @param e {@inheritDoc} */ protected void processKeyEvent(java.awt.event.KeyEvent e) { super.processKeyEvent(e); Object src = e.getSource(); e.setSource(canvas); canvas.processKeyEvent(e); e.setSource(src); } /** * Redirects event to canvas and to superclass. * * @param e {@inheritDoc} */ protected void processMouseEvent(java.awt.event.MouseEvent e) { super.processMouseEvent(e); Object src = e.getSource(); e.setSource(canvas); canvas.processMouseEvent(e); e.setSource(src); } /** * Redirects event to canvas and to superclass. * * @param e {@inheritDoc} */ protected void processMouseMotionEvent(java.awt.event.MouseEvent e) { super.processMouseMotionEvent(e); Object src = e.getSource(); e.setSource(canvas); canvas.processMouseMotionEvent(e); e.setSource(src); } /** * Redirects event to canvas and to superclass. * * @param e {@inheritDoc} */ protected void processMouseWheelEvent(java.awt.event.MouseWheelEvent e) { super.processMouseWheelEvent(e); Object src = e.getSource(); e.setSource(canvas); canvas.processMouseWheelEvent(e); e.setSource(src); } /** * {@inheritDoc} * * @param x {@inheritDoc} * @param y {@inheritDoc} * @param width {@inheritDoc} * @param height {@inheritDoc} */ public void setBounds(int x, int y, int width, int height) { super.setBounds(x, y, width, height); if ((null == canvas) || (null == canvas.getOffScreenBuffer()) || (JCanvas3D.RESIZE_IMMEDIATELY == getResizeMode())) //whatever the resize mode, i create on first setbounds(). (not doing so would create a deadlock in DELAYED mode when trying to do the first paint { createCanvas(width, height); } else if ((JCanvas3D.RESIZE_DELAYED == getResizeMode()) && ((null != canvas.getParent()) && (true == canvas.getParent().isVisible()))) { if ((null == canvas.resizeThread) || (false == canvas.resizeThread.isAlive())) { canvas.resizeThread = new ResizeThread(width, height, getResizeValidationDelay(), this); canvas.resizeThread.start(); } else { canvas.resizeThread.setWidth(width); canvas.resizeThread.setHeight(height); } } } /** * Sets resize mode to be used on this component. Resize mode * permits to have smoother canvas resizes. The time taken by a canvas to * be resized can be pretty long: renderer has to stop, current render has * to end, everything has to be initialized again, and after all that has * been done, renderer is started again, then the image is displayed once * rendered. Resize mode uses a timer to make those steps only after the * last refresh request occured. 'Latest refresh' is determined by the * amount of time between now and the last time you asked for a size * change. If that time expires, a real resize is done. In between, the * same size is rendered, but the drawn image is scaled down/up. This has * some drawbacks, as the image can appear blocked, imprecise, distorted, * incomplete for that while, but most of the time only some of the * drawbacks will be users will see nothing. Default delay is set to * 100ms, which is low enough for common human not to be able to really * see that the rendered image is scaled. * * @param resizeMode can be one of RESIZE_IMMEDIATELY or RESIZE_DELAYED * @see #RESIZE_IMMEDIATELY * @see #RESIZE_DELAYED */ public void setResizeMode(int resizeMode) { this.resizeMode = resizeMode; } /** * Sets the validation delay for the component. The validation * delay is the maximum time allowed for the canvas resizing to occur * using rendered buffer scaling. Once that delay expired, the canvas is * resized at the lowest level possible, thus in the rendering pipeline. * Note: Changing this field is only useful if resize mode is set to * RESIZE_IMMEDIATELY or RESIZE_DELAYED * * @param resizeValidationDelay the delay before a real resize would occur. * @see #RESIZE_IMMEDIATELY * @see #RESIZE_DELAYED */ public void setResizeValidationDelay(int resizeValidationDelay) { this.resizeValidationDelay = resizeValidationDelay; } /** * This class is the internal Canvas3D that is used and sent to * Java 3D. It is remote controlled through JCanvas3D and is modified to be * able to tell the lightweight component when refreshes are needed. */ static class InternalCanvas3D extends Canvas3D implements AutoOffScreenCanvas3D { // These two constants define the maximum amount of time // to wait for the readback of the off-screen buffer to complete. // The total time is MAX_WAIT_LOOPS * MAX_WAIT_TIME msec. private static final int MAX_WAIT_LOOPS = 5; private static final long MAX_WAIT_TIME = 100; /** * the bufferedImage that will be displayed as the result * of the computations. */ BufferedImage bi = null; /** * This is the lightweight canvas that is linked to that * offscreen canvas. */ JCanvas3D lwCanvas; /** * If delayed resizing is selected, a thread handling * resising will be started. */ ResizeThread resizeThread; /** * flag used to sort a call to addnotify() from user and * from the lightweight component. Lightweight component calls * addNotify() so that the rendering begins and uses normal routines, * but this is a method that user must not call. */ boolean addNotifyFlag; /** * flag indicating that the canvas crashed in a way or an * other, making swing to wait for the swap for much too long. */ protected boolean canvasCrashed; /** * flag used to know when image can be painted or not. This * is to avoid component potentially displaying a buffer with an * unfinished blit. There is already a flag (imageReady) in Canvas3D * that does this but it can't be used because of restrictions. This * flag is not really fine grained, being set from end of postRender() * to end of postSwap() */ boolean imageReadyBis; /** * Flag to indicate that the component is waiting for the * canvas to acomplish its swap, and that the component has to be * notified when done. */ boolean waitingForSwap; /**
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -