@Override public void draw(final Renderer r) { initialize(r); updateTranslations(); final double camWaterDist = waterPlane.pseudoDistance(cam.getLocation()); aboveWater = camWaterDist >= 0; if (isSupported()) { waterShader.setUniform("tangent", tangent); waterShader.setUniform("binormal", binormal); waterShader.setUniform("useFadeToFogColor", useFadeToFogColor); waterShader.setUniform("waterColor", waterColorStart); waterShader.setUniform("waterColorEnd", waterColorEnd); waterShader.setUniform("normalTranslation", (float) normalTranslation); waterShader.setUniform("refractionTranslation", (float) refractionTranslation); waterShader.setUniform("abovewater", aboveWater); if (useProjectedShader) { waterShader.setUniform("cameraPos", cam.getLocation()); waterShader.setUniform("waterHeight", (float) waterPlane.getConstant()); waterShader.setUniform("amplitude", (float) waterMaxAmplitude); waterShader.setUniform("heightFalloffStart", (float) heightFalloffStart); waterShader.setUniform("heightFalloffSpeed", (float) heightFalloffSpeed); } final double heightTotal = clipBias + waterMaxAmplitude - waterPlane.getConstant(); final Vector4 clipPlane = Vector4.fetchTempInstance(); if (useReflection) { clipPlane.set( waterPlane.getNormal().getX(), waterPlane.getNormal().getY(), waterPlane.getNormal().getZ(), heightTotal); renderReflection(clipPlane); } if (useRefraction && aboveWater) { clipPlane.set( -waterPlane.getNormal().getX(), -waterPlane.getNormal().getY(), -waterPlane.getNormal().getZ(), -waterPlane.getConstant()); renderRefraction(clipPlane); } } if (fallbackTextureState != null) { fallbackTextureStateMatrix.setM31(normalTranslation); fallbackTexture.setTextureMatrix(fallbackTextureStateMatrix); } super.draw(r); }
private void modifyProjectionMatrix(final Vector4 clipPlane) { // Get the current projection matrix projectionMatrix = cam.getProjectionMatrix().toArray(projectionMatrix); // Get the inverse transpose of the current modelview matrix final ReadOnlyMatrix4 modelViewMatrixInvTrans = tRenderer.getCamera().getModelViewMatrix().invert(tmpMatrix).transposeLocal(); modelViewMatrixInvTrans.applyPre(clipPlane, clipPlane); // Calculate the clip-space corner point opposite the clipping plane // as (sgn(clipPlane.x), sgn(clipPlane.y), 1, 1) and // transform it into camera space by multiplying it // by the inverse of the projection matrix cornerPoint.setX((sign(clipPlane.getX()) + projectionMatrix[8]) / projectionMatrix[0]); cornerPoint.setY((sign(clipPlane.getY()) + projectionMatrix[9]) / projectionMatrix[5]); cornerPoint.setZ(-1.0); cornerPoint.setW((1.0 + projectionMatrix[10]) / projectionMatrix[14]); // Calculate the scaled plane vector final Vector4 scaledPlaneVector = clipPlane.multiply((2.0 / clipPlane.dot(cornerPoint)), cornerPoint); // Replace the third row of the projection matrix projectionMatrix[2] = scaledPlaneVector.getX(); projectionMatrix[6] = scaledPlaneVector.getY(); projectionMatrix[10] = scaledPlaneVector.getZ() + 1.0; projectionMatrix[14] = scaledPlaneVector.getW(); // Load it back into OpenGL final Matrix4 newProjectionMatrix = tmpMatrix.fromArray(projectionMatrix); tRenderer.getCamera().setProjectionMatrix(newProjectionMatrix); }
@Override protected void initExample() { _canvas.setTitle("Interact Example"); final Camera camera = _canvas.getCanvasRenderer().getCamera(); camera.setLocation(-20, 70, 180); camera.lookAt(0, 0, 0, Vector3.UNIT_Y); // setup our interact controls addControls(); // create a floor to act as a reference. addFloor(); // create an object or two to manipulate addObjects(); }
/** * Calculates the distance from a spatial to the camera. Distance is a squared distance. * * @param spat Spatial to check distance. * @return Distance from Spatial to current context's camera. */ protected double distanceToCam(final Spatial spat) { if (spat._queueDistance != Double.NEGATIVE_INFINITY) { return spat._queueDistance; } final Camera cam = Camera.getCurrentCamera(); if (spat.getWorldBound() != null && Vector3.isValid(spat.getWorldBound().getCenter())) { spat._queueDistance = spat.getWorldBound().distanceToEdge(cam.getLocation()); } else { final ReadOnlyVector3 spatPosition = spat.getWorldTranslation(); if (!Vector3.isValid(spatPosition)) { spat._queueDistance = Double.POSITIVE_INFINITY; } else { spat._queueDistance = cam.getLocation().distance(spatPosition); } } return spat._queueDistance; }
/** Render water refraction RTT */ private void renderRefraction(final Vector4 clipPlane) { if (renderList.isEmpty()) { return; } refractionTime += tpf; if (refractionTime < refractionThrottle) { return; } refractionTime = 0; // tRenderer.getCamera().set(cam); tRenderer.getCamera().setLocation(cam.getLocation()); tRenderer.getCamera().setDirection(cam.getDirection()); tRenderer.getCamera().setUp(cam.getUp()); tRenderer.getCamera().setLeft(cam.getLeft()); CullHint cullMode = CullHint.Dynamic; if (skyBox != null) { cullMode = skyBox.getSceneHints().getCullHint(); skyBox.getSceneHints().setCullHint(CullHint.Always); } tRenderer.getCamera().setProjectionMatrix(cam.getProjectionMatrix()); texArray.clear(); texArray.add(textureRefract); texArray.add(textureDepth); tRenderer.getCamera().update(); tRenderer.getCamera().getModelViewMatrix(); tRenderer.getCamera().getProjectionMatrix(); tRenderer.render(renderList, texArray, Renderer.BUFFER_COLOR_AND_DEPTH); if (skyBox != null) { skyBox.getSceneHints().setCullHint(cullMode); } }
public void updateCamera() { if (isSupported()) { tRenderer .getCamera() .setFrustum( cam.getFrustumNear(), cam.getFrustumFar(), cam.getFrustumLeft(), cam.getFrustumRight(), cam.getFrustumTop(), cam.getFrustumBottom()); } }
/** * Update the vertices for this particle, taking size, spin and viewer into consideration. In the * case of particle type ParticleType.GeomMesh, the original triangle normal is maintained rather * than rotating it to face the camera or parent vectors. * * @param cam Camera to use in determining viewer aspect. If null, or if parent is not set to * camera facing, parent's left and up vectors are used. */ public void updateVerts(final Camera cam) { final double orient = parent.getParticleOrientation() + values[VAL_CURRENT_SPIN]; final double currSize = values[VAL_CURRENT_SIZE]; if (type == ParticleSystem.ParticleType.GeomMesh || type == ParticleSystem.ParticleType.Point) {; // nothing to do } else if (cam != null && parent.isCameraFacing()) { final ReadOnlyVector3 camUp = cam.getUp(); final ReadOnlyVector3 camLeft = cam.getLeft(); final ReadOnlyVector3 camDir = cam.getDirection(); if (parent.isVelocityAligned()) { bbX.set(_velocity).normalizeLocal().multiplyLocal(currSize); camDir.cross(bbX, bbY).normalizeLocal().multiplyLocal(currSize); } else if (orient == 0) { bbX.set(camLeft).multiplyLocal(currSize); bbY.set(camUp).multiplyLocal(currSize); } else { final double cA = MathUtils.cos(orient) * currSize; final double sA = MathUtils.sin(orient) * currSize; bbX.set(camLeft) .multiplyLocal(cA) .addLocal(camUp.getX() * sA, camUp.getY() * sA, camUp.getZ() * sA); bbY.set(camLeft) .multiplyLocal(-sA) .addLocal(camUp.getX() * cA, camUp.getY() * cA, camUp.getZ() * cA); } } else { bbX.set(parent.getLeftVector()).multiplyLocal(0); bbY.set(parent.getUpVector()).multiplyLocal(0); } final Vector3 tempVec3 = Vector3.fetchTempInstance(); final FloatBuffer vertexBuffer = parent.getParticleGeometry().getMeshData().getVertexBuffer(); switch (type) { case Quad: { _position.subtract(bbX, tempVec3).subtractLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 0); _position.subtract(bbX, tempVec3).addLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 1); _position.add(bbX, tempVec3).addLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 2); _position.add(bbX, tempVec3).subtractLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 3); break; } case GeomMesh: { final Quaternion tempQuat = Quaternion.fetchTempInstance(); final ReadOnlyVector3 norm = triModel.getNormal(); if (orient != 0) { tempQuat.fromAngleNormalAxis(orient, norm); } for (int x = 0; x < 3; x++) { if (orient != 0) { tempQuat.apply(triModel.get(x), tempVec3); } else { tempVec3.set(triModel.get(x)); } tempVec3.multiplyLocal(currSize).addLocal(_position); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + x); } Quaternion.releaseTempInstance(tempQuat); break; } case Triangle: { _position .subtract(3 * bbX.getX(), 3 * bbX.getY(), 3 * bbX.getZ(), tempVec3) .subtractLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 0); _position.add(bbX, tempVec3).addLocal(3 * bbY.getX(), 3 * bbY.getY(), 3 * bbY.getZ()); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 1); _position.add(bbX, tempVec3).subtractLocal(bbY); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 2); break; } case Line: { _position.subtract(bbX, tempVec3); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex); _position.add(bbX, tempVec3); BufferUtils.setInBuffer(tempVec3, vertexBuffer, startIndex + 1); break; } case Point: { BufferUtils.setInBuffer(_position, vertexBuffer, startIndex); break; } } Vector3.releaseTempInstance(tempVec3); }
/** Render water reflection RTT */ private void renderReflection(final Vector4 clipPlane) { if (renderList.isEmpty()) { return; } reflectionTime += tpf; if (reflectionTime < reflectionThrottle) { return; } reflectionTime = 0; if (aboveWater) { camLocation.set(cam.getLocation()); double planeDistance = waterPlane.pseudoDistance(camLocation); calcVect.set(waterPlane.getNormal()).multiplyLocal(planeDistance * 2.0f); camReflectPos.set(camLocation.subtractLocal(calcVect)); camLocation.set(cam.getLocation()).addLocal(cam.getDirection()); planeDistance = waterPlane.pseudoDistance(camLocation); calcVect.set(waterPlane.getNormal()).multiplyLocal(planeDistance * 2.0f); camReflectDir .set(camLocation.subtractLocal(calcVect)) .subtractLocal(camReflectPos) .normalizeLocal(); camLocation.set(cam.getLocation()).addLocal(cam.getUp()); planeDistance = waterPlane.pseudoDistance(camLocation); calcVect.set(waterPlane.getNormal()).multiplyLocal(planeDistance * 2.0f); camReflectUp .set(camLocation.subtractLocal(calcVect)) .subtractLocal(camReflectPos) .normalizeLocal(); camReflectLeft.set(camReflectUp).crossLocal(camReflectDir).normalizeLocal(); tRenderer.getCamera().setLocation(camReflectPos); tRenderer.getCamera().setDirection(camReflectDir); tRenderer.getCamera().setUp(camReflectUp); tRenderer.getCamera().setLeft(camReflectLeft); } else { tRenderer.getCamera().setLocation(cam.getLocation()); tRenderer.getCamera().setDirection(cam.getDirection()); tRenderer.getCamera().setUp(cam.getUp()); tRenderer.getCamera().setLeft(cam.getLeft()); } if (skyBox != null) { tmpLocation.set(skyBox.getTranslation()); skyBox.setTranslation(tRenderer.getCamera().getLocation()); skyBox.updateGeometricState(0.0f); skyBox.getSceneHints().setCullHint(CullHint.Never); } texArray.clear(); if (doBlurReflection) { texArray.add(textureReflect); } else { texArray.add(textureReflectBlur); } tRenderer.getCamera().setProjectionMode(ProjectionMode.Custom); tRenderer.getCamera().setProjectionMatrix(cam.getProjectionMatrix()); tRenderer.render(skyBox, texArray, Renderer.BUFFER_COLOR_AND_DEPTH); if (skyBox != null) { skyBox.getSceneHints().setCullHint(CullHint.Always); } modifyProjectionMatrix(clipPlane); tRenderer.render(renderList, texArray, Renderer.BUFFER_NONE); if (doBlurReflection) { blurReflectionTexture(); } if (skyBox != null) { skyBox.setTranslation(tmpLocation); skyBox.updateGeometricState(0.0f); skyBox.getSceneHints().setCullHint(CullHint.Never); } }
/** * Initialize texture renderers. Load water textures. Create shaders. * * @param r */ private void initialize(final Renderer r) { if (cam == null || initialized) { return; } initialized = true; final ContextCapabilities caps = ContextManager.getCurrentContext().getCapabilities(); if (useRefraction && useProjectedShader && caps.getNumberOfFragmentTextureUnits() < 6 || useRefraction && caps.getNumberOfFragmentTextureUnits() < 5) { useRefraction = false; logger.info("Not enough textureunits, falling back to non refraction water"); } if (!caps.isGLSLSupported()) { supported = false; } if (!(caps.isPbufferSupported() || caps.isFBOSupported())) { supported = false; } if (isSupported()) { tRenderer = TextureRendererFactory.INSTANCE.createTextureRenderer( // cam.getWidth() / renderScale, // width cam.getHeight() / renderScale, // height 8, // Depth bits... TODO: Make configurable? 0, // Samples... TODO: Make configurable? r, caps); // blurSampleDistance = 1f / ((float) cam.getHeight() / renderScale); tRenderer.setMultipleTargets(true); tRenderer.setBackgroundColor(new ColorRGBA(0.0f, 0.0f, 0.0f, 1.0f)); tRenderer .getCamera() .setFrustum( cam.getFrustumNear(), cam.getFrustumFar(), cam.getFrustumLeft(), cam.getFrustumRight(), cam.getFrustumTop(), cam.getFrustumBottom()); textureState = new TextureState(); textureState.setEnabled(true); setupTextures(); fullScreenQuad = new Quad("FullScreenQuad", cam.getWidth() / 4, cam.getHeight() / 4); fullScreenQuad.setTranslation(cam.getWidth() / 2, cam.getHeight() / 2, 0); fullScreenQuad.getSceneHints().setRenderBucketType(RenderBucketType.Ortho); fullScreenQuad.getSceneHints().setCullHint(CullHint.Never); fullScreenQuad.getSceneHints().setTextureCombineMode(TextureCombineMode.Replace); fullScreenQuad.getSceneHints().setLightCombineMode(LightCombineMode.Off); final TextureState ts = new TextureState(); ts.setTexture(textureReflect); fullScreenQuad.setRenderState(ts); fullScreenQuad.setRenderState(blurShaderVertical); fullScreenQuad.updateWorldRenderStates(false); } if (!isSupported()) { createFallbackData(); } else { noFog = new FogState(); noFog.setEnabled(false); } getSceneHints().setCullHint(CullHint.Never); setWaterEffectOnSpatial(this); }
@Override protected void initExample() { _canvas.setTitle("Generating textures... please wait"); final Camera cam = _canvas.getCanvasRenderer().getCamera(); wside = cam.getWidth() / SPAN; hside = wside; padding = wside / 10; // Set up hud hud = new UIHud(); hud.setupInput(_canvas, _physicalLayer, _logicalLayer); // Set up the frames for (int i = 0; i < views.length; i++) { views[i] = new UIPanel(); views[i].setLocalComponentSize(wside, hside); views[i].layout(); hud.add(views[i]); } // Set up the panels for (int i = 0; i < COUNT; i++) { srcs[i] = new UIPanel(null) { @Override public boolean mousePressed( final com.ardor3d.input.MouseButton button, final com.ardor3d.input.InputState state) { if (zoom || this == zoomed) { toggleZoom(this); } return true; }; }; srcs[i].setTooltipPopTime(25); } // set up our different textures... int index = 0; // check setCheck(srcs[index++]); // mandelbrot setMandelbrot(srcs[index++]); // voronoi setVoronoi(srcs[index++]); // *** 'Planet' example: final Function3D terrain = Functions.scaleInput(Functions.simplexNoise(), 2, 2, 1); terrainColors = new ReadOnlyColorRGBA[256]; terrainColors[0] = new ColorRGBA(0, 0, .5f, 1); terrainColors[95] = new ColorRGBA(0, 0, 1, 1); terrainColors[127] = new ColorRGBA(0, .5f, 1, 1); terrainColors[137] = new ColorRGBA(240 / 255f, 240 / 255f, 64 / 255f, 1); terrainColors[143] = new ColorRGBA(32 / 255f, 160 / 255f, 0, 1); terrainColors[175] = new ColorRGBA(224 / 255f, 224 / 255f, 0, 1); terrainColors[223] = new ColorRGBA(128 / 255f, 128 / 255f, 128 / 255f, 1); terrainColors[255] = ColorRGBA.WHITE; GeneratedImageFactory.fillInColorTable(terrainColors); // simplex - luminance setTerrain(srcs[index], terrain, false, false); srcs[index++].setTooltipText("Simplex noise."); // simplex + FBM - luminance setTerrain(srcs[index], terrain, true, false); srcs[index++].setTooltipText("Simplex noise + Fractional Brownian Motion (fBm)."); // color ramp setColors(srcs[index++]); // simplex + FBM - color setTerrain(srcs[index], terrain, true, true); srcs[index++].setTooltipText("Noise + Colormap == Something that looks like a map. :)"); // *** A few textures derived from samples in the libnoise project. // *** Perhaps we can get an some better ones from the community :) // A simple wood grain setWoodGrain(srcs[index++]); // Jade setJade(srcs[index++]); // Slime setSlime(srcs[index++]); _canvas.setTitle("Generated Textures Example - Ardor3D"); }
/**