/** 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); } }
/** * 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); } }