package com.akjava.gwt.threejsexamples.client.examples.shaders;
import com.akjava.gwt.html5.client.file.File;
import com.akjava.gwt.html5.client.file.FileUploadForm;
import com.akjava.gwt.html5.client.file.FileUtils;
import com.akjava.gwt.html5.client.file.FileUtils.DataURLListener;
import com.akjava.gwt.lib.client.CanvasUtils;
import com.akjava.gwt.lib.client.ImageElementUtils;
import com.akjava.gwt.lib.client.LogUtils;
import com.akjava.gwt.stats.client.Stats;
import com.akjava.gwt.three.client.examples.js.GWTExampleParamUtils;
import com.akjava.gwt.three.client.examples.js.THREEExp;
import com.akjava.gwt.three.client.examples.js.Water;
import com.akjava.gwt.three.client.examples.js.controls.OrbitControls;
import com.akjava.gwt.three.client.gwt.GWTParamUtils;
import com.akjava.gwt.three.client.gwt.extras.Shader;
import com.akjava.gwt.three.client.java.Skybox;
import com.akjava.gwt.three.client.java.ui.example.AbstractExample;
import com.akjava.gwt.three.client.java.utils.GWTThreeUtils;
import com.akjava.gwt.three.client.js.THREE;
import com.akjava.gwt.three.client.js.cameras.PerspectiveCamera;
import com.akjava.gwt.three.client.js.extras.ImageUtils;
import com.akjava.gwt.three.client.js.extras.geometries.IcosahedronGeometry;
import com.akjava.gwt.three.client.js.lights.HemisphereLight;
import com.akjava.gwt.three.client.js.loaders.ImageLoader;
import com.akjava.gwt.three.client.js.loaders.ImageLoader.ImageLoadHandler;
import com.akjava.gwt.three.client.js.materials.MeshPhongMaterial;
import com.akjava.gwt.three.client.js.materials.ShaderMaterial;
import com.akjava.gwt.three.client.js.objects.Mesh;
import com.akjava.gwt.three.client.js.renderers.WebGLRenderer;
import com.akjava.gwt.three.client.js.renderers.shaders.WebGLShaders.ShaderChunk.ShaderLib;
import com.akjava.gwt.three.client.js.scenes.Scene;
import com.akjava.gwt.three.client.js.textures.CubeTexture;
import com.akjava.gwt.three.client.js.textures.Texture;
import com.akjava.gwt.threejsexamples.client.LabeledInputColorBoxWidget;
import com.akjava.gwt.threejsexamples.client.LabeledInputRangeWidget;
import com.akjava.lib.common.utils.ColorUtils;
import com.google.gwt.canvas.client.Canvas;
import com.google.gwt.dom.client.ImageElement;
import com.google.gwt.dom.client.NativeEvent;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.logical.shared.ValueChangeEvent;
import com.google.gwt.event.logical.shared.ValueChangeHandler;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.CheckBox;
import com.google.gwt.user.client.ui.FocusPanel;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.VerticalPanel;
public class OceanExample extends AbstractExample{
@Override
public String getName() {
return "ocean";
}
@Override
public void animate(double timestamp) {
render(timestamp);
stats.update();//really deprecate?many still use this
}
private WebGLRenderer renderer;
private Scene scene;
private PerspectiveCamera camera;
private Stats stats;
int WIDTH;
int HEIGHT;
int parametersWidth=2000;
int parametersHeight=2000;
private OrbitControls controls;
private Texture waterNormals;
private Water water;
private Mesh mirrorMesh;
private Mesh sphere;
@Override
public void init() {
WIDTH = (int)getWindowInnerWidth();//var WIDTH = window.innerWidth;
HEIGHT = (int)getWindowInnerHeight();//var HEIGHT = window.innerHeight;
// camera
int VIEW_ANGLE = 55;//var VIEW_ANGLE = 45;
double ASPECT = getWindowInnerWidth() / getWindowInnerHeight();
double NEAR = 0.5;//var NEAR = 1;
double FAR = 3000000;
FocusPanel container = createContainerPanel();
// renderer
renderer = THREE.WebGLRenderer();//renderer = new THREE.WebGLRenderer();
renderer.setPixelRatio( GWTThreeUtils.getWindowDevicePixelRatio() );//renderer.setPixelRatio( window.devicePixelRatio );
renderer.setSize( WIDTH, HEIGHT );
// scene
scene = THREE.Scene();//scene = new THREE.Scene();
// camera
camera = THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);//camera = new THREE.PerspectiveCamera(VIEW_ANGLE, ASPECT, NEAR, FAR);
camera.getPosition().set( 2000, 750, 2000 );
controls = THREEExp.OrbitControls( camera, renderer.getDomElement());//controls = new THREE.OrbitControls( camera, renderer.domElement );
//controls.setUserPan(false);//controls.userPan = false;
//controls.setUserPanSpeed(0.0);//controls.userPanSpeed = 0.0;
controls.setMaxDistance(5000.0);//controls.maxDistance = 5000.0;
controls.setMaxPolarAngle(Math.PI * 0.495);//controls.maxPolarAngle = Math.PI * 0.495;
controls.getCenter().set( 0, 500, 0 );//controls.center.set( 0, 500, 0 );
container.getElement().appendChild( renderer.getDomElement() );
//stats
stats = Stats.create();
stats.setPosition(0, 0);
container.getElement().appendChild(stats.domElement());
//add html info
container.add(createAbsoluteHTML("<div style='text:white'><a href='http://threejs.org' target='_blank'>three.js</a> - ocean</a>"
,100,10));
fillScene();
//handle resize & gui
initResizeHandlerAndGUI();
//setDebugAnimateOneTimeOnly(true);
}
public void fillScene(){
HemisphereLight light = THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );//var light = new THREE.HemisphereLight( 0xffffbb, 0x080820, 1 );
light.getPosition().set( - 1, 1, - 1 );//light.position.set( - 1, 1, - 1 );
scene.add( light );
//waternormals
waterNormals = ImageUtils.loadTexture( "textures/waternormals.jpg" );//waterNormals = new THREE.ImageUtils.loadTexture( 'textures/waternormals.jpg' );
waterNormals.setWrapS(THREE.RepeatWrapping);//waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
waterNormals.setWrapT(THREE.RepeatWrapping);
water = THREEExp.Water( renderer, camera, scene, GWTExampleParamUtils.Water().
textureWidth(512).
textureHeight(512).
waterNormals(waterNormals).
alpha(1.0).
sunDirection(light.getPosition().clone().normalize()).
sunColor(0xffffff).
waterColor(0x001e0f).
distortionScale(50.0)
);
mirrorMesh = THREE.Mesh(//mirrorMesh = new THREE.Mesh(
THREE.PlaneBufferGeometry( parametersWidth * 500, parametersHeight * 500 ),//new THREE.PlaneBufferGeometry( parameters.width * 500, parameters.height * 500 ),
water.getMaterial()
);
mirrorMesh.add( water );
mirrorMesh.getRotation().setX(- Math.PI * 0.5);//mirrorMesh.rotation.x = - Math.PI * 0.5;
scene.add( mirrorMesh );
cubeMap = THREE.CubeTexture();
cubeMap.setFormat(THREE.RGBFormat);//cubeMap.format = THREE.RGBFormat;
cubeMap.setFlipY(false);//cubeMap.flipY = false;
ImageLoader loader = THREE.ImageLoader();//var loader = new THREE.ImageLoader();
loader.load( "textures/skyboxsun25degtest.png", new ImageLoadHandler() {
@Override
public void onProgress(NativeEvent progress) {
// TODO Auto-generated method stub
}
@Override
public void onLoad(ImageElement imageElement) {
Skybox skybox=new Skybox(imageElement);
skybox.setToCubeTexture(cubeMap);
LogUtils.log(cubeMap);
/*
cubeMap.getImages().set(0, getSide(imageElement,2,1));
cubeMap.getImages().set(1, getSide(imageElement,0,1));
cubeMap.getImages().set(2, getSide(imageElement,1,0));
cubeMap.getImages().set(3, getSide(imageElement,1,2));
cubeMap.getImages().set(4, getSide(imageElement,1,1));
cubeMap.getImages().set(5, getSide(imageElement,3,1));
cubeMap.setNeedsUpdate(true);//cubeMap.needsUpdate = true;
*/
}
@Override
public void onError(NativeEvent error) {
// TODO Auto-generated method stub
}
});
Shader cubeShader = ShaderLib.cube();
cubeShader.uniforms().set("tCube",cubeMap);//cubeShader.uniforms['tCube'].value = cubeMap;
ShaderMaterial skyBoxMaterial = THREE.ShaderMaterial( GWTParamUtils.ShaderMaterial().fragmentShader(cubeShader.fragmentShader()).vertexShader(cubeShader.vertexShader()).uniforms(cubeShader.uniforms()).depthWrite(false).side(THREE.BackSide));//var skyBoxMaterial = new THREE.ShaderMaterial( {fragmentShader: cubeShader.fragmentShader,vertexShader: cubeShader.vertexShader,uniforms: cubeShader.uniforms,depthWrite: false,side: THREE.BackSide});
Mesh skyBox = THREE.Mesh(//var skyBox = new THREE.Mesh(
THREE.BoxGeometry( 1000000, 1000000, 1000000 ),//new THREE.BoxGeometry( 1000000, 1000000, 1000000 ),
skyBoxMaterial
);
scene.add( skyBox );
IcosahedronGeometry geometry = THREE.IcosahedronGeometry( 400, 4 );//var geometry = new THREE.IcosahedronGeometry( 400, 4 );
for ( int i = 0, j = geometry.getFaces().length(); i < j; i ++ ) {//for ( var i = 0, j = geometry.faces.length; i < j; i ++ ) {
geometry.getFaces().get( i ).getColor().setHex( (int) (Math.random() * 0xffffff) );//geometry.faces[ i ].color.setHex( Math.random() * 0xffffff );
}
MeshPhongMaterial material = THREE.MeshPhongMaterial( GWTParamUtils.MeshPhongMaterial().vertexColors(THREE.FaceColors).shininess(100).envMap(cubeMap) );//var material = new THREE.MeshPhongMaterial( {vertexColors: THREE.FaceColors,shininess: 100,envMap: cubeMap} );
sphere = THREE.Mesh( geometry, material );//sphere = new THREE.Mesh( geometry, material );
scene.add( sphere );
}
//forced convert canvas as imageelement
public native final ImageElement getSide(ImageElement image,int x,int y)/*-{
var size = 1024;
var canvas = document.createElement( 'canvas' );
canvas.width = size;
canvas.height = size;
var context = canvas.getContext( '2d' );
context.drawImage( image, - x * size, - y * size );
return canvas;
}-*/;
private void initResizeHandlerAndGUI() {
VerticalPanel gui=addResizeHandlerAndCreateGUIPanel();
gui.setWidth("200px");//some widget broke,like checkbox without parent size
gui.setSpacing(2);
CheckBox showSphere=new CheckBox("show sphere");
showSphere.setValue(true);
gui.add(showSphere);
showSphere.addValueChangeHandler(new ValueChangeHandler<Boolean>() {
@Override
public void onValueChange(ValueChangeEvent<Boolean> event) {
sphere.setVisible(event.getValue());
}
});
LabeledInputRangeWidget distortionScale=new LabeledInputRangeWidget("distortionScale", 10, 400, 10);
gui.add(distortionScale);
distortionScale.setValue(50);
distortionScale.addtRangeListener(new ValueChangeHandler<Number>() {
@Override
public void onValueChange(ValueChangeEvent<Number> event) {
water.getMaterial().getUniforms().set("distortionScale", event.getValue().doubleValue());
}
});
LabeledInputRangeWidget alpha=new LabeledInputRangeWidget("alpha", 0.05, 1, 0.05);
gui.add(alpha);
alpha.setValue(1);
alpha.addtRangeListener(new ValueChangeHandler<Number>() {
@Override
public void onValueChange(ValueChangeEvent<Number> event) {
water.getMaterial().getUniforms().set("alpha", event.getValue().doubleValue());
}
});
LabeledInputRangeWidget speed=new LabeledInputRangeWidget("speed", 1, 200,1);
gui.add(speed);
speed.setValue(60);
speed.addtRangeListener(new ValueChangeHandler<Number>() {
@Override
public void onValueChange(ValueChangeEvent<Number> event) {
//water.getMaterial().getUniforms().set("alpha", event.getValue().doubleValue());
timeSplit=event.getValue().doubleValue();
}
});
LabeledInputColorBoxWidget waterColor=new LabeledInputColorBoxWidget("waterColor");
waterColor.setValue("#001E0F");
waterColor.addListener(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
int value=ColorUtils.toColor(ColorUtils.toRGB(event.getValue()));
water.getMaterial().getUniforms().set("waterColor", THREE.Color(value));
}
});
gui.add(waterColor);
LabeledInputColorBoxWidget sunColor=new LabeledInputColorBoxWidget("sunColor");
sunColor.setValue("#ffffff");
sunColor.addListener(new ValueChangeHandler<String>() {
@Override
public void onValueChange(ValueChangeEvent<String> event) {
int value=ColorUtils.toColor(ColorUtils.toRGB(event.getValue()));
water.getMaterial().getUniforms().set("sunColor", THREE.Color(value));
}
});
gui.add(sunColor);
gui.add(new Label("WaterNormals"));
final FileUploadForm fileUpload=FileUtils.createSingleFileUploadForm(new DataURLListener() {
@Override
public void uploaded(File file, String text) {
ImageElement image=ImageElementUtils.create(text);
int w=image.getWidth();
int h=image.getHeight();
//LogUtils.log(w+"x"+h);
Texture texture;
if(w!=1024 || h!=1024){
Canvas canvas=CanvasUtils.createCanvas(1024, 1024);
CanvasUtils.drawFitCenter(canvas, image);
texture=ImageUtils.loadTexture(canvas.toDataUrl());
}else{
texture=ImageUtils.loadTexture(text);
}
texture.setWrapS(THREE.RepeatWrapping);//waterNormals.wrapS = waterNormals.wrapT = THREE.RepeatWrapping;
texture.setWrapT(THREE.RepeatWrapping);
water.getMaterial().getUniforms().set("normalSampler", texture);//somehow normalSampler
//water.updateTextureMatrix();
}
},false);
fileUpload.setAccept(FileUploadForm.ACCEPT_IMAGE);
gui.add(fileUpload);
Button resetTexture=new Button("resetTexture",new ClickHandler() {
@Override
public void onClick(ClickEvent event) {
fileUpload.reset();
water.getMaterial().getUniforms().set("normalSampler", waterNormals);
}
});
gui.add(resetTexture);
gui.add(new Label("Skybox"));
final FileUploadForm fileUpload2=FileUtils.createSingleFileUploadForm(new DataURLListener() {
@Override
public void uploaded(File file, String text) {
ImageElement image=ImageElementUtils.create(text);
if(!Skybox.isValidImage(image)){
Window.alert("invalid skybox image-size");
return;
}
Skybox skybox=new Skybox(image);
skybox.setToCubeTexture(cubeMap);
//water.updateTextureMatrix();
}
},false);
fileUpload2.setAccept(FileUploadForm.ACCEPT_IMAGE);
gui.add(fileUpload2);
}
public void onWindowResize() {
camera.setAspect(getWindowInnerWidth() / getWindowInnerHeight());
camera.updateProjectionMatrix();
renderer.setSize( (int)getWindowInnerWidth() , (int)getWindowInnerHeight() );
}
private double timeSplit=60;
private CubeTexture cubeMap;
public void render(double now) {//GWT animateFrame has time
double time = now * 0.001;
sphere.getPosition().setY(Math.sin( time ) * 500 + 250);//sphere.position.y = Math.sin( time ) * 500 + 250;
sphere.getRotation().setX(time * 0.5);//sphere.rotation.x = time * 0.5;
sphere.getRotation().setZ(time * 0.51);//sphere.rotation.z = time * 0.51;
((ShaderMaterial)water.getMaterial().cast()).getUniforms().gwtIncrementValue("time", 1.0 / timeSplit);//water.material.uniforms.time.value += 1.0 / 60.0;
controls.update();
water.render();
renderer.render(scene, camera);
}
@Override
public String getTokenKey() {
return "ocean";
}
}