]> gerrit.simantics Code Review - simantics/3d.git/blobdiff - dev/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/JmeSinglePassRenderingComponent.java
latest release (0.41)
[simantics/3d.git] / dev / org.simantics.proconf.g3d / src / org / simantics / proconf / g3d / common / JmeSinglePassRenderingComponent.java
diff --git a/dev/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/JmeSinglePassRenderingComponent.java b/dev/org.simantics.proconf.g3d/src/org/simantics/proconf/g3d/common/JmeSinglePassRenderingComponent.java
new file mode 100644 (file)
index 0000000..fb9aff6
--- /dev/null
@@ -0,0 +1,411 @@
+/*******************************************************************************\r
+ * Copyright (c) 2007 VTT Technical Research Centre of Finland and others.\r
+ * All rights reserved. This program and the accompanying materials\r
+ * are made available under the terms of the Eclipse Public License v1.0\r
+ * which accompanies this distribution, and is available at\r
+ * http://www.eclipse.org/legal/epl-v10.html\r
+ *\r
+ * Contributors:\r
+ *     VTT Technical Research Centre of Finland - initial API and implementation\r
+ *******************************************************************************/\r
+package org.simantics.proconf.g3d.common;\r
+\r
+import java.net.URL;\r
+\r
+import org.eclipse.core.runtime.FileLocator;\r
+import org.eclipse.core.runtime.Path;\r
+import org.simantics.proconf.g3d.Activator;\r
+import org.simantics.proconf.g3d.base.JmeRenderingComponent;\r
+import org.simantics.proconf.g3d.preferences.PreferenceConstants;\r
+\r
+import com.jme.image.Texture;\r
+import com.jme.light.DirectionalLight;\r
+import com.jme.math.Vector3f;\r
+import com.jme.renderer.Camera;\r
+import com.jme.renderer.ColorRGBA;\r
+import com.jme.renderer.pass.BasicPassManager;\r
+import com.jme.renderer.pass.RenderPass;\r
+import com.jme.renderer.pass.ShadowedRenderPass;\r
+import com.jme.renderer.swt.SWTRenderer;\r
+import com.jme.scene.Node;\r
+import com.jme.scene.Spatial;\r
+import com.jme.scene.Text;\r
+import com.jme.scene.state.AlphaState;\r
+import com.jme.scene.state.LightState;\r
+import com.jme.scene.state.TextureState;\r
+import com.jme.scene.state.WireframeState;\r
+import com.jme.scene.state.ZBufferState;\r
+import com.jme.system.DisplaySystem;\r
+import com.jme.util.TextureManager;\r
+import com.jme.util.Timer;\r
+import com.jme.util.geom.Debugger;\r
+import com.jmex.effects.glsl.BloomRenderPass;\r
+import com.jmex.effects.glsl.SketchRenderPass;\r
+\r
+\r
+public class JmeSinglePassRenderingComponent extends JmeRenderingComponent {\r
+       protected DisplaySystem displaySystem;\r
+       protected Timer timer;\r
+       protected Node rootNode = new Node("Root");\r
+       protected Node shadowRootNode = new Node("Shadow");\r
+       protected Node noCastShadowRootNode = new Node("No Cast Shadow");\r
+       protected Node noShadowRootNode = new Node("No Shadow");\r
+       protected Camera cam;\r
+       protected float near = .1f;\r
+       protected float far = 3000f;\r
+       protected float fov = 55f;\r
+    \r
+       protected int projectionPolicy;\r
+    \r
+    /** The root node of our text. */\r
+       protected Node orthoNode = new Node("ortho");\r
+\r
+    /** Displays all the lovely information at the bottom. */\r
+    protected Text fps;\r
+    protected Text debug;\r
+    protected String debugText  = "";\r
+    public static String fontLocation = "data/defaultfont.tga";//AppProperties.PATH_DEFAULT_FONT;\r
+    \r
+    \r
+    protected BasicPassManager pManager = new BasicPassManager();\r
+    \r
+    private boolean showBounds = false;\r
+    private boolean showNormals = false;\r
+    private WireframeState ws = null;\r
+    \r
+    private boolean projectionUpdated = false;\r
+    \r
+       public JmeSinglePassRenderingComponent() {\r
+               \r
+       }\r
+       \r
+       public void init(DisplaySystem displaySystem) {\r
+               this.displaySystem = displaySystem;\r
+               cam = displaySystem.getRenderer().createCamera(\r
+                displaySystem.getRenderer().getWidth(), displaySystem.getRenderer().getHeight());\r
+               displaySystem.getRenderer().setBackgroundColor(new ColorRGBA(0.2f,0.2f,0.2f,0.f));//(0.357F, 0.647F, 0.890F, 1.0F));\r
+        displaySystem.getRenderer().getQueue().setTwoPassTransparency(true);\r
+               cam.setFrustumPerspective(fov,\r
+                (float) displaySystem.getRenderer().getWidth()/\r
+                (float) displaySystem.getRenderer().getHeight(),near, far);\r
+        projectionPolicy = PERSPECTIVE_PROJECTION;\r
+        Vector3f loc = new Vector3f(0.0f, 0.0f, 10.0f);\r
+        Vector3f left = new Vector3f(-1.0f, 0.0f, 0.0f);\r
+        Vector3f up = new Vector3f(0.0f, 1.0f, 0.0f);\r
+        Vector3f dir = new Vector3f(0.0f, 0f, -1.0f);\r
+        /** Move our camera to a correct place and orientation. */\r
+        cam.setFrame(loc, left, up, dir);\r
+        /** Signal that we've changed our camera's location/frustum. */\r
+        cam.update();\r
+        displaySystem.getRenderer().setCamera(cam);\r
+        timer = Timer.getTimer();\r
+        displaySystem.setTitle("ShapeEditor");\r
+        displaySystem.getRenderer().enableStatistics(true);\r
+        \r
+        initRoot();\r
+       }\r
+       \r
+       protected Texture loadFontTexture() {\r
+               URL url = FileLocator.find(org.simantics.proconf.g3d.Activator.getDefault().getBundle(),new Path(fontLocation),null);\r
+        return TextureManager.loadTexture(url, Texture.MM_LINEAR,\r
+                Texture.FM_LINEAR);\r
+       }\r
+       \r
+       protected void initRoot() {\r
+               ZBufferState buf = displaySystem.getRenderer().createZBufferState();\r
+        buf.setEnabled(true);\r
+        buf.setFunction(ZBufferState.CF_LEQUAL);\r
+        //buf.setWritable(false);\r
+        rootNode.setRenderState(buf);   \r
+        rootNode.attachChild(noShadowRootNode);\r
+        rootNode.attachChild(noCastShadowRootNode);\r
+        rootNode.attachChild(shadowRootNode);\r
+        noShadowRootNode.setCullMode(Spatial.CULL_NEVER);\r
+        \r
+        //PointLight light = new PointLight();\r
+        DirectionalLight light = new DirectionalLight();\r
+        light.setDiffuse( new ColorRGBA( 0.75f, 0.75f, 0.75f, 0.75f ) );\r
+        light.setAmbient( new ColorRGBA( 0.5f, 0.5f, 0.5f, 0.5f ) );\r
+        //light.setLocation( new Vector3f( 100, 100, 100 ) );\r
+        light.setDirection(new Vector3f( -100, -150, -100 ));\r
+        light.setEnabled( true );\r
+        light.setShadowCaster(true);\r
+        \r
+        LightState lightState = displaySystem.getRenderer().createLightState();\r
+        lightState.setEnabled( true );\r
+        lightState.attach( light );\r
+        lightState.setSeparateSpecular(true);\r
+        lightState.setTwoSidedLighting(false);\r
+        rootNode.setRenderState( lightState );\r
+        \r
+        ws = displaySystem.getRenderer().createWireframeState();\r
+        ws.setEnabled(false);\r
+        rootNode.setRenderState(ws);\r
+        \r
+        AlphaState as1 = displaySystem.getRenderer().createAlphaState();\r
+        as1.setBlendEnabled(true);\r
+        as1.setSrcFunction(AlphaState.SB_SRC_ALPHA);\r
+        as1.setDstFunction(AlphaState.DB_ONE);\r
+        as1.setTestEnabled(true);\r
+        as1.setTestFunction(AlphaState.TF_GREATER);\r
+        as1.setEnabled(true);\r
+        \r
+        TextureState font = displaySystem.getRenderer().createTextureState();\r
+        /** The texture is loaded from fontLocation */\r
+        font.setTexture(loadFontTexture());\r
+\r
+        font.setEnabled(true);\r
+\r
+        // Then our font Text object.\r
+        /** This is what will actually have the text at the bottom. */\r
+        fps = new Text("FPS label", "");\r
+        fps.setCullMode(Spatial.CULL_NEVER);\r
+        fps.setTextureCombineMode(TextureState.REPLACE);\r
+        \r
+        debug = new Text("Debug", "Debug");\r
+        debug.setCullMode(Spatial.CULL_NEVER);\r
+        debug.setTextureCombineMode(TextureState.REPLACE);\r
+        debug.setLocalTranslation(new Vector3f(1.f,10.f,0.f));\r
+\r
+        // Finally, a stand alone node (not attached to root on purpose)\r
+        Node fpsNode = new Node("FPS node");\r
+        fpsNode.attachChild(fps);\r
+        fpsNode.attachChild(debug);\r
+        fpsNode.setRenderState(font);\r
+        fpsNode.setRenderState(as1);\r
+        fpsNode.setCullMode(Spatial.CULL_NEVER);\r
+        orthoNode.attachChild(fpsNode);\r
+        \r
+        rootNode.updateGeometricState(0.0f, true);\r
+        rootNode.updateRenderState();\r
+        \r
+        orthoNode.updateGeometricState(0.0f, true);\r
+        orthoNode.updateRenderState();\r
+        if (Activator.getDefault().getPreferenceStore().getBoolean(PreferenceConstants.SHADOWS)) {\r
+               ShadowedRenderPass shadowRootPass = new ShadowedRenderPass();\r
+               shadowRootPass.add(shadowRootNode);\r
+               shadowRootPass.add(noCastShadowRootNode);\r
+               shadowRootPass.addOccluder(shadowRootNode);\r
+               pManager.add(shadowRootPass);\r
+               //rootPass.setRenderShadows(false);\r
+               shadowRootPass.setShadowColor(new ColorRGBA(0.1f,0.1f,0.1f,0.9f));\r
+               shadowRootPass.setLightingMethod(ShadowedRenderPass.MODULATIVE);\r
+               RenderPass rootPass = new RenderPass();\r
+               rootPass.add(noShadowRootNode);\r
+               pManager.add(rootPass);\r
+        } else {\r
+               RenderPass rootPass = new RenderPass();\r
+               rootPass.add(rootNode);\r
+               pManager.add(rootPass);\r
+        }\r
+               \r
+               String postProcess = Activator.getDefault().getPreferenceStore().getString(PreferenceConstants.POST_PROCESS);\r
+               if (postProcess.startsWith("bloom")) {\r
+                       BloomRenderPass bloomRenderPass = new BloomRenderPass(cam, 4);\r
+                       if (bloomRenderPass.isSupported()) {\r
+                               bloomRenderPass.add(rootNode);\r
+                               bloomRenderPass.setUseCurrentScene(false);\r
+                               pManager.add(bloomRenderPass);\r
+                       }\r
+               } else if (postProcess.startsWith("sketch")) {\r
+                       SketchRenderPass sketchRenderPass = new SketchRenderPass(cam, 4);\r
+                       if (sketchRenderPass.isSupported()) {\r
+                               sketchRenderPass.add(rootNode);\r
+                               pManager.add(sketchRenderPass);\r
+                       }\r
+               }\r
+\r
+               \r
+               RenderPass fpsPass = new RenderPass();\r
+               fpsPass.add(orthoNode);\r
+               pManager.add(fpsPass);\r
+       }\r
+       \r
+       public void render() {\r
+               displaySystem.setCurrent();\r
+                /** Recalculate the framerate. */\r
+        timer.update();\r
+        \r
+          /** Update tpf to time per frame according to the Timer. */\r
+        float tpf = timer.getTimePerFrame();\r
+        /** Send the fps to our fps bar at the bottom. */\r
+        fps.print("FPS: " + (int) timer.getFrameRate() + " - "\r
+                + displaySystem.getRenderer().getStatistics());\r
+        /**\r
+         * Update the physics for this world.\r
+         */\r
+        debug.print(debugText);\r
+\r
+        /** Update controllers/render states/transforms/bounds for rootNode. */\r
+        rootNode.updateGeometricState(tpf, true);\r
+        rootNode.updateRenderState();\r
+       \r
+        orthoNode.updateGeometricState(tpf, true);\r
+        orthoNode.updateRenderState();\r
+        \r
+        displaySystem.getRenderer().clearStatistics();\r
+        /** Clears the previously rendered information. */\r
+        displaySystem.getRenderer().clearBuffers();\r
+\r
+        pManager.updatePasses(tpf);\r
+        \r
+        pManager.renderPasses(displaySystem.getRenderer());\r
+        if ( showBounds ) {\r
+            Debugger.drawBounds( shadowRootNode, displaySystem.getRenderer(), true );\r
+        }\r
+\r
+        if ( showNormals ) {\r
+            Debugger.drawNormals( shadowRootNode, displaySystem.getRenderer());\r
+        }\r
+        displaySystem.getRenderer().displayBackBuffer();\r
+        \r
+        \r
+        \r
+        //swap buffers\r
+        ((SWTRenderer)displaySystem.getRenderer()).swap();\r
+       }\r
+       \r
+       @Override\r
+       public void resize(int width, int height) {\r
+               updateProjection();\r
+       }\r
+       \r
+       @Override\r
+       public Node getShadowRoot() {\r
+               return shadowRootNode;\r
+       }\r
+       \r
+       @Override\r
+       public Node getNoCastRoot() {\r
+               return noCastShadowRootNode;\r
+       }\r
+       \r
+       @Override\r
+       public Node getRoot() {\r
+               return rootNode;\r
+       }\r
+       \r
+       @Override\r
+       public Node getOrthoNode() {\r
+               return orthoNode;\r
+       }\r
+       \r
+       @Override\r
+       public Node getNoShadowRoot() {\r
+               return noShadowRootNode;\r
+       }\r
+       \r
+//     public void setRootNode(Node node) {\r
+//             rootNode = node;\r
+//             initRoot();\r
+//     }\r
+       \r
+       @Override\r
+       public int getProjectionPolicy() {\r
+               return projectionPolicy;\r
+       }\r
+       \r
+       @Override\r
+       public void setProjectionPolicy(int policy) {\r
+               if (policy != projectionPolicy) {\r
+                       projectionPolicy = policy;\r
+                       updateProjection();\r
+               }\r
+       }\r
+       \r
+       private void updateProjection() {\r
+               switch (projectionPolicy) {\r
+               case PERSPECTIVE_PROJECTION:\r
+                       cam.setParallelProjection(false);\r
+                       cam.setFrustumPerspective(fov,\r
+                       (float) displaySystem.getRenderer().getWidth() /\r
+                       (float) displaySystem.getRenderer().getHeight(),near, far);\r
+                       break;\r
+                       \r
+               case PARALLEL_PROJECTION:\r
+                       cam.setParallelProjection(true);\r
+                       break;\r
+               }\r
+               cam.update();\r
+               projectionUpdated = true;\r
+       }\r
+       \r
+       @Override\r
+       public float getScreenScale() {\r
+               //System.out.println(cam.getFrustumLeft() + " " + cam.getFrustumRight() + " " + cam.getFrustumBottom() + " " + cam.getFrustumTop()+ " " + cam.getFrustumNear() + " " + cam.getFrustumFar());\r
+               return Math.abs(cam.getFrustumTop());\r
+       }\r
+       \r
+       @Override\r
+       public void setScreenScale(float screenScale) {\r
+               float aspect = (float) displaySystem.getRenderer().getWidth() /\r
+        (float) displaySystem.getRenderer().getHeight();\r
+               cam.setFrustum(-screenScale*8.f, cam.getFrustumFar(), -screenScale*aspect, screenScale*aspect, -screenScale, screenScale);\r
+       }\r
+       \r
+       @Override\r
+       public float getFieldOfView() {\r
+               return fov;\r
+       }\r
+       \r
+       @Override\r
+       public void dispose() {\r
+               pManager.cleanUp();\r
+               rootNode.dispose();\r
+               rootNode = null;\r
+               noShadowRootNode = null;\r
+               noCastShadowRootNode = null;\r
+               orthoNode = null;\r
+               shadowRootNode = null;\r
+       }\r
+       \r
+       @Override\r
+       public boolean update() {\r
+               if (!projectionUpdated) {\r
+                       return false;\r
+               }\r
+               projectionUpdated = false;\r
+               return true;\r
+       }\r
+       \r
+       @Override\r
+       public Camera getCamera() {\r
+               return cam;\r
+       }\r
+       \r
+       @Override\r
+       public DisplaySystem getDisplaySystem() {\r
+               return displaySystem;\r
+       }\r
+       \r
+       public void setDebugText(String text) {\r
+               this.debugText = text;\r
+               //System.out.println("JmeSinglePass.setDebugText() " + text);\r
+       }\r
+       \r
+       public void setShowNormals(boolean b) {\r
+               showNormals = b;\r
+       }\r
+       \r
+       public void setShowBounds(boolean b) {\r
+               showBounds = b;\r
+       }\r
+       \r
+       public void setShowWireframe(boolean b) {\r
+               ws.setEnabled(b);\r
+       }\r
+       \r
+       public boolean isShowNormals() {\r
+               return showNormals;\r
+       }\r
+       \r
+       public boolean isShowBounds() {\r
+               return showBounds;\r
+       }\r
+       \r
+       public boolean isShowWireframe() {\r
+               return ws.isEnabled();\r
+       }\r
+       \r
+       \r
+}\r