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