/* * Copyright (C) 2011 aki@akjava.com * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.akjava.gwt.threetest.client; import java.util.ArrayList; import java.util.List; import com.akjava.gwt.three.client.gwt.materials.ShaderMaterialParameter; import com.akjava.gwt.three.client.java.utils.DShaderUtils; import com.akjava.gwt.three.client.java.utils.DUniformUtils; import com.akjava.gwt.three.client.java.utils.DShaderUtils.DShader; import com.akjava.gwt.three.client.java.utils.DShaderUtils.DUniforms; import com.akjava.gwt.three.client.js.THREE; import com.akjava.gwt.three.client.js.cameras.Camera; import com.akjava.gwt.three.client.js.core.Geometry; import com.akjava.gwt.three.client.js.core.Object3D; import com.akjava.gwt.three.client.js.extras.ImageUtils; import com.akjava.gwt.three.client.js.lights.Light; import com.akjava.gwt.three.client.js.loaders.JSONLoader; import com.akjava.gwt.three.client.js.loaders.JSONLoader.JSONLoadHandler; import com.akjava.gwt.three.client.js.materials.Material; import com.akjava.gwt.three.client.js.math.Vector3; import com.akjava.gwt.three.client.js.math.Vertex; 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.scenes.Scene; import com.akjava.gwt.threetest.client.resources.Bundles; import com.google.gwt.core.client.GWT; import com.google.gwt.core.client.JsArray; import com.google.gwt.user.client.Timer; import com.google.gwt.user.client.ui.FocusPanel; public class NormalmapDemo extends AbstractDemo{ private long last; private AnimationModel model; @Override public void start(final WebGLRenderer renderer,final int width,final int height,FocusPanel panel) { super.start(renderer, width, height, panel); renderer.setClearColor(0x333333, 1); final Scene scene=THREE.Scene(); final Camera camera=THREE.PerspectiveCamera(35,(double)width/height,.1,10000); camera.getPosition().set(0, 300, 0); final Vector3 target=THREE.Vector3(0, 150, 0); scene.add(camera); JSONLoader loader=THREE.JSONLoader(); loader.load("models/animation.js", new JSONLoadHandler() { //loader.load("models/men2b_boned_gun.js", new LoadHandler() { @Override public void loaded(Geometry geometry, JsArray<Material> ms) { log(geometry); DShader shader=DShaderUtils.lib("normal"); DUniforms uniforms=DUniformUtils.clone(shader.uniforms()); uniforms.set("tNormal", ImageUtils.loadTexture("img/normalmap.png")); //uniforms.set("tNormal", ImageUtils.loadTexture("img/men2buv_n.png#10")); uniforms.set("enableDiffuse", true); uniforms.setHex("uDiffuseColor", 0xff0000); //uniforms.set("tDiffuse", ImageUtils.loadTexture("img/men2buv.png#1")); uniforms.set("tDiffuse", ImageUtils.loadTexture("img/uv.png")); uniforms.set("uNormalScale",1,1); /* Material material=ShaderMaterialParameter.create().fragmentShader(shader.fragmentShader()).vertexShader(shader.vertexShader()) //.uniforms(uniforms).lights(true) .morphTargets(false); */ model=new AnimationModel(geometry, null); //TODO fix above if need model.getObject3D().getScale().set( 15, 15, 15); model.getObject3D().getPosition().set(0, -100, 0); scene.add(model.getObject3D()); GWT.log("loaded:"); } }); final Light light=THREE.DirectionalLight(0xeeeeee,2); light.setPosition(1, 1, 1); light.getPosition().normalize(); //scene.add(light); final Light light2=THREE.DirectionalLight(0xeeeeee,2); light2.setPosition(-1, -1, -1); light2.getPosition().normalize(); scene.add(light2); final Light light3=THREE.PointLight(0xffffff); light3.setPosition(0, 0, 600); scene.add(light3); //scene.add(light2); scene.add(THREE.AmbientLight(0xcccccc)); // MainWidget.cameraMove.setZ(-20); MainWidget.cameraMove.setZ(25); // MainWidget.cameraRotation.setX(-90); final int radius = 600; last = System.currentTimeMillis(); Timer timer = new Timer(){ double theta; public void run(){ MainWidget.stats.begin(); try{ theta += 0.2; camera.getPosition().setX(radius * Math.sin( theta * Math.PI / 360 )); camera.getPosition().setZ(radius * Math.cos( theta * Math.PI / 360 )); camera.lookAt( target ); if(model!=null){ //TODO clock long tmp=System.currentTimeMillis(); long delta=tmp-last; //animMesh.updateAnimation(delta); //animMesh.update((int) delta); //tmpwork int index=(int) (tmp/100%model.getFramelength()); model.select(index); last=tmp; } renderer.render(scene, camera); }catch(Exception e){ GWT.log(e.getMessage()); } MainWidget.stats.end(); } }; startTimer(timer); } @Override public String getName() { return "NormalMap Animation"; } public static class AnimationModel{ protected AnimationModel(){ } public int getFramelength(){ return meshs.size(); } List<Mesh> meshs=new ArrayList<Mesh>(); private Mesh current; private Object3D container; Geometry last; private boolean createBetweenFrame=true; public AnimationModel(Geometry geometry,Material material){ container=THREE.Object3D(); int size=getMorphTargetsLength(geometry); for(int i=1;i<size;i++){//0 is reset pose? Geometry geo=makeMorphTargetsGeometry(geometry,i); geo.computeTangents(); if(createBetweenFrame){ //make half if(i!=1){ JsArray<Vector3> pre=last.vertices(); JsArray<Vector3> current=geo.vertices(); JsArray<Vector3> half=halfAndHalf(pre,current,0.5); //Geometry geo2=makeMorphTargetsGeometry(geometry,half); //geo2.computeTangents(); //Mesh mesh=THREE.Mesh(geo2, material); //add(mesh); } } last=geo; Mesh mesh=THREE.Mesh(geo, material); add(mesh); } } public Object3D getObject3D(){ return container; } private final void add(Mesh mesh){ meshs.add(mesh); } public final void select(int index){ if(current!=null){ container.remove(current); } current=meshs.get(index); container.add(current); } public static final native int getMorphTargetsLength(Geometry geometry)/*-{ return geometry.morphTargets.length; }-*/; public static final native Geometry makeMorphTargetsGeometry(Geometry base,int index)/*-{ var geometry=base.clone(); geometry.vertices=base.morphTargets[index].vertices; return geometry; }-*/; public static final native Geometry makeMorphTargetsGeometry(Geometry base,JsArray<Vertex> vertexs)/*-{ var geometry=base.clone(base); geometry.vertices=vertexs; return geometry; }-*/; public static JsArray<Vector3> halfAndHalf(JsArray<Vector3> v1,JsArray<Vector3> v2,double level){ if(v1.length()!=v2.length()){ return null; } double v2level=1-level; JsArray<Vector3> result=(JsArray<Vector3>) JsArray.createArray(); for(int i=0;i<v1.length();i++){ //TODO search better way Vector3 ve1=v1.get(i); Vector3 ve2=v2.get(i); Vector3 newV=THREE.Vector3( ve1.getX()*level+ve2.getX()*v2level, ve1.getY()*level+ve2.getY()*v2level, ve1.getZ()*level+ve2.getZ()*v2level ); result.push(newV); } return result; } } @Override public String getHowToHtml(){ return Bundles.INSTANCE.howto_default().getText(); } }