|
@@ -0,0 +1,585 @@
|
|
|
+<!DOCTYPE HTML>
|
|
|
+<html lang="en">
|
|
|
+ <head>
|
|
|
+ <title>three.js canvas/webgl - geometry - text</title>
|
|
|
+ <meta charset="utf-8">
|
|
|
+ <meta name="viewport" content="width=device-width; initial-scale=1.0; maximum-scale=1.0; user-scalable=0;"/>
|
|
|
+ <style type="text/css">
|
|
|
+ body {
|
|
|
+ font-family: Monospace;
|
|
|
+ background-color: #f0f0f0;
|
|
|
+ margin: 0px;
|
|
|
+ overflow: hidden;
|
|
|
+ }
|
|
|
+ </style>
|
|
|
+ </head>
|
|
|
+ <body>
|
|
|
+
|
|
|
+
|
|
|
+ <script type="text/javascript" src="../build/Three.js"></script>
|
|
|
+
|
|
|
+ <script type="text/javascript" src="js/RequestAnimationFrame.js"></script>
|
|
|
+ <script type="text/javascript" src="js/Stats.js"></script>
|
|
|
+ <script type="text/javascript" src="js/Tween.js"></script>
|
|
|
+ <script type="text/javascript" src="js/Sparks.js"></script>
|
|
|
+
|
|
|
+ <script type="text/javascript" src="js/ShaderExtras.js"></script>
|
|
|
+ <script type="text/javascript" src="js/postprocessing/EffectComposer.js"></script>
|
|
|
+ <script type="text/javascript" src="js/postprocessing/RenderPass.js"></script>
|
|
|
+ <script type="text/javascript" src="js/postprocessing/ShaderPass.js"></script>
|
|
|
+ <script type="text/javascript" src="js/postprocessing/MaskPass.js"></script>
|
|
|
+ <script type="text/javascript" src="js/postprocessing/BloomPass.js"></script>
|
|
|
+
|
|
|
+ <!-- load the font file from canvas-text -->
|
|
|
+
|
|
|
+
|
|
|
+ <script type="text/javascript" src="fonts/helvetiker_regular.typeface.js"></script>
|
|
|
+
|
|
|
+ <script type="x-shader/x-vertex" id="vertexshader">
|
|
|
+
|
|
|
+ attribute float size;
|
|
|
+ attribute vec4 ca;
|
|
|
+
|
|
|
+ varying vec4 vColor;
|
|
|
+
|
|
|
+ void main() {
|
|
|
+
|
|
|
+ vColor = ca;
|
|
|
+
|
|
|
+ vec4 mvPosition = modelViewMatrix * vec4( position, 1.0 );
|
|
|
+
|
|
|
+ gl_PointSize = size * ( 150.0 / length( mvPosition.xyz ) );
|
|
|
+
|
|
|
+ gl_Position = projectionMatrix * mvPosition;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ </script>
|
|
|
+
|
|
|
+ <script type="x-shader/x-fragment" id="fragmentshader">
|
|
|
+
|
|
|
+ uniform vec3 color;
|
|
|
+ uniform sampler2D texture;
|
|
|
+
|
|
|
+ varying vec4 vColor;
|
|
|
+
|
|
|
+
|
|
|
+ uniform float radius;
|
|
|
+
|
|
|
+ uniform vec2 delta;
|
|
|
+
|
|
|
+ varying vec2 texCoord;
|
|
|
+
|
|
|
+
|
|
|
+ void main() {
|
|
|
+
|
|
|
+ vec4 outColor = texture2D( texture, gl_PointCoord );
|
|
|
+
|
|
|
+ if ( outColor.a < 0.5 ) discard;
|
|
|
+
|
|
|
+ gl_FragColor = outColor * vec4( color * vColor.xyz, 1.0 );
|
|
|
+
|
|
|
+ //float depth = gl_FragCoord.z / gl_FragCoord.w;
|
|
|
+ ///const vec3 fogColor = vec3( 0.0 );
|
|
|
+
|
|
|
+ //float fogFactor = smoothstep( 200.0, 600.0, depth );
|
|
|
+ //gl_FragColor = mix( gl_FragColor, vec4( fogColor, gl_FragColor.w ), fogFactor );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ </script>
|
|
|
+
|
|
|
+ <script type="text/javascript">
|
|
|
+
|
|
|
+ var container, stats;
|
|
|
+
|
|
|
+ var camera, scene, renderer;
|
|
|
+
|
|
|
+ var text, plane;
|
|
|
+
|
|
|
+ var targetRotation = 0;
|
|
|
+ var targetRotationOnMouseDown = 0;
|
|
|
+
|
|
|
+ var mouseX = 0;
|
|
|
+ var mouseXOnMouseDown = 0;
|
|
|
+
|
|
|
+ var windowHalfX = window.innerWidth / 2;
|
|
|
+ var windowHalfY = window.innerHeight / 2;
|
|
|
+
|
|
|
+
|
|
|
+ var heartShape, particleCloud, sparksEmitter, emitterPos;
|
|
|
+ var _rotation = 0;
|
|
|
+ var timeOnShapePath = 0;
|
|
|
+
|
|
|
+ init();
|
|
|
+ animate();
|
|
|
+
|
|
|
+ function init() {
|
|
|
+
|
|
|
+ container = document.createElement( 'div' );
|
|
|
+ document.body.appendChild( container );
|
|
|
+
|
|
|
+ var info = document.createElement( 'div' );
|
|
|
+ info.style.position = 'absolute';
|
|
|
+ info.style.top = '10px';
|
|
|
+ info.style.width = '100%';
|
|
|
+ info.style.textAlign = 'center';
|
|
|
+ info.innerHTML = 'Three.js with WebGL Love. Simple Particle Systems with Shapes by <a href="http://www.lab4games.net/zz85/blog">zz85</a><br/>Move your mouse. Click to pause/resume.';
|
|
|
+ container.appendChild( info );
|
|
|
+
|
|
|
+ camera = new THREE.Camera( 50, window.innerWidth / window.innerHeight, 1, 1000 );
|
|
|
+ camera.position.y = 150;
|
|
|
+ camera.position.z = 700;
|
|
|
+ camera.target.position.y = 150;
|
|
|
+
|
|
|
+ scene = new THREE.Scene();
|
|
|
+
|
|
|
+ // Get text from hash
|
|
|
+
|
|
|
+ var theText = "THREE.JS";
|
|
|
+
|
|
|
+ var hash = document.location.hash.substr( 1 );
|
|
|
+
|
|
|
+ if ( hash.length !== 0 ) {
|
|
|
+
|
|
|
+ theText = hash;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ var text3d = new THREE.TextGeometry( theText, {
|
|
|
+
|
|
|
+ size: 80,
|
|
|
+ height: 20,
|
|
|
+ curveSegments: 2,
|
|
|
+ font: "helvetiker"
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ text3d.computeBoundingBox();
|
|
|
+ var centerOffset = -0.5 * ( text3d.boundingBox.x[ 1 ] - text3d.boundingBox.x[ 0 ] );
|
|
|
+
|
|
|
+ var textMaterial = new THREE.MeshBasicMaterial( { color: Math.random() * 0xffffff, wireframe: false } );
|
|
|
+
|
|
|
+ text = new THREE.Mesh( text3d, textMaterial );
|
|
|
+ // Potentially, we can extract the vertices or faces of the text to generate particles too.
|
|
|
+ // Geo > Vertices > Position
|
|
|
+
|
|
|
+ text.doubleSided = false;
|
|
|
+
|
|
|
+ text.position.x = centerOffset;
|
|
|
+ text.position.y = 100;
|
|
|
+ text.position.z = 0;
|
|
|
+
|
|
|
+ text.rotation.x = 0;
|
|
|
+ text.rotation.y = Math.PI * 2;
|
|
|
+ text.overdraw = true;
|
|
|
+
|
|
|
+ parent = new THREE.Object3D();
|
|
|
+ parent.addChild( text );
|
|
|
+ scene.addObject( parent );
|
|
|
+
|
|
|
+ ///// Create particle objects for Three.js
|
|
|
+
|
|
|
+
|
|
|
+ var particleslength = 50000;
|
|
|
+
|
|
|
+ var particles = new THREE.Geometry();
|
|
|
+
|
|
|
+ function newpos(x, y, z) {
|
|
|
+ return new THREE.Vertex(
|
|
|
+ new THREE.Vector3(x, y, z)
|
|
|
+ );
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ var Pool = {
|
|
|
+ __pools: [],
|
|
|
+
|
|
|
+ // Get a new Vector
|
|
|
+ get: function() {
|
|
|
+ if (this.__pools.length>0) {
|
|
|
+ return this.__pools.pop();
|
|
|
+ }
|
|
|
+
|
|
|
+ console.log("pool ran out!")
|
|
|
+ return null;
|
|
|
+
|
|
|
+ },
|
|
|
+
|
|
|
+ // Release a vector back into the pool
|
|
|
+ add: function(v) {
|
|
|
+ this.__pools.push(v);
|
|
|
+ },
|
|
|
+
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ for ( i = 0; i < particleslength; i++ ) {
|
|
|
+ particles.vertices.push(newpos(Math.random() *200 - 100, Math.random() *100+150, Math.random() *50));
|
|
|
+ Pool.add(i);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // Create pools of vectors
|
|
|
+
|
|
|
+ attributes = {
|
|
|
+
|
|
|
+ size: { type: 'f', value: [] },
|
|
|
+ ca: { type: 'c', value: [] } //ca //customColor
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ var sprite = generateSprite() ;
|
|
|
+ textu = new THREE.Texture ( sprite );
|
|
|
+ textu.needsUpdate = true;
|
|
|
+
|
|
|
+ uniforms = {
|
|
|
+
|
|
|
+ amplitude: { type: "f", value: 1.0 },
|
|
|
+ color: { type: "c", value: new THREE.Color( 0xffffff ) },
|
|
|
+ texture: { type: "t", value: 0, texture:textu} //
|
|
|
+ //
|
|
|
+
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ // PARAMS.
|
|
|
+ // Steadycounter
|
|
|
+ // Life
|
|
|
+ // Opacity
|
|
|
+ // Hue Speed
|
|
|
+ // Movement Speed
|
|
|
+
|
|
|
+ function generateSprite() {
|
|
|
+
|
|
|
+ var canvas = document.createElement( 'canvas' );
|
|
|
+ canvas.width = 128;
|
|
|
+ canvas.height = 128;
|
|
|
+
|
|
|
+ var context = canvas.getContext( '2d' );
|
|
|
+
|
|
|
+
|
|
|
+ // Just a square, doesnt work too bad with blur pp.
|
|
|
+ // context.fillStyle = "white";
|
|
|
+ // context.strokeStyle = "white";
|
|
|
+ // context.fillRect(0, 0, 63, 63) ;
|
|
|
+
|
|
|
+ // Heart Shapes are not too pretty here
|
|
|
+ // var x = 4, y = 0;
|
|
|
+ // context.save();
|
|
|
+ // context.scale(8, 8); // Scale so canvas render can redraw within bounds
|
|
|
+ // context.beginPath();
|
|
|
+ // context.bezierCurveTo( x + 2.5, y + 2.5, x + 2.0, y, x, y );
|
|
|
+ // context.bezierCurveTo( x - 3.0, y, x - 3.0, y + 3.5,x - 3.0,y + 3.5 );
|
|
|
+ // context.bezierCurveTo( x - 3.0, y + 5.5, x - 1.0, y + 7.7, x + 2.5, y + 9.5 );
|
|
|
+ // context.bezierCurveTo( x + 6.0, y + 7.7, x + 8.0, y + 5.5, x + 8.0, y + 3.5 );
|
|
|
+ // context.bezierCurveTo( x + 8.0, y + 3.5, x + 8.0, y, x + 5.0, y );
|
|
|
+ // context.bezierCurveTo( x + 3.5, y, x + 2.5, y + 2.5, x + 2.5, y + 2.5 );
|
|
|
+ // context.closePath();
|
|
|
+
|
|
|
+ context.beginPath();
|
|
|
+ context.arc(64, 64, 60, 0, Math.PI*2, false);
|
|
|
+ context.closePath();
|
|
|
+
|
|
|
+ context.lineWidth = 0.5; //0.05
|
|
|
+ context.stroke();
|
|
|
+ context.restore();
|
|
|
+ var gradient = context.createRadialGradient( canvas.width /2, canvas.height /2, 0, canvas.width /2, canvas.height /2, canvas.width /2 );
|
|
|
+
|
|
|
+ gradient.addColorStop( 0, 'rgba(255,255,255,1)' );
|
|
|
+ gradient.addColorStop( 0.2, 'rgba(255,255,255,1)' );
|
|
|
+ //gradient.addColorStop( 0.6, 'rgba(200,200,200,1)' );
|
|
|
+ gradient.addColorStop( 0.4, 'rgba(128,128,128,1)' );
|
|
|
+ gradient.addColorStop( 1, 'rgba(0,0,0,1)' );
|
|
|
+
|
|
|
+
|
|
|
+ context.fillStyle = gradient;
|
|
|
+
|
|
|
+ context.fill();
|
|
|
+
|
|
|
+
|
|
|
+ //var idata =context.getImageData(0, 0, canvas.width, canvas.height);
|
|
|
+ //document.body.appendChild(canvas);
|
|
|
+ return canvas;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ var shaderMaterial = new THREE.MeshShaderMaterial( {
|
|
|
+
|
|
|
+ uniforms: uniforms,
|
|
|
+ attributes: attributes,
|
|
|
+
|
|
|
+ vertexShader: document.getElementById( 'vertexshader' ).textContent,
|
|
|
+ fragmentShader: document.getElementById( 'fragmentshader' ).textContent
|
|
|
+ ,
|
|
|
+ blending: THREE.AdditiveBlending,
|
|
|
+ depthTest: false,
|
|
|
+ transparent: true
|
|
|
+
|
|
|
+ });
|
|
|
+
|
|
|
+ particleCloud = new THREE.ParticleSystem( particles, shaderMaterial );
|
|
|
+
|
|
|
+ particleCloud.dynamic = true;
|
|
|
+ //particleCloud.sortParticles = true;
|
|
|
+
|
|
|
+ var vertices = particleCloud.geometry.vertices;
|
|
|
+ var values_size = attributes.size.value;
|
|
|
+ var values_color = attributes.ca.value;
|
|
|
+
|
|
|
+ for( var v = 0; v < vertices.length; v++ ) {
|
|
|
+
|
|
|
+ values_size[ v ] = 50;
|
|
|
+ values_color[ v ] = new THREE.Color( 0xaaff00 );
|
|
|
+ values_color[ v ].setHSV( 0, 0, 0 );
|
|
|
+ particles.vertices[v].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ parent.addChild( particleCloud );
|
|
|
+ //scene.addObject( particleCloud );
|
|
|
+ particleCloud.y = 800;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // Create Particle Systems
|
|
|
+ // EMITTER STUFF
|
|
|
+
|
|
|
+ // Heart
|
|
|
+
|
|
|
+ var x = 0, y = 0;
|
|
|
+
|
|
|
+ heartShape = new THREE.Shape();
|
|
|
+
|
|
|
+ heartShape.moveTo( x + 25, y + 25 );
|
|
|
+ heartShape.bezierCurveTo( x + 25, y + 25, x + 20, y, x, y );
|
|
|
+ heartShape.bezierCurveTo( x - 30, y, x - 30, y + 35,x - 30,y + 35 );
|
|
|
+ heartShape.bezierCurveTo( x - 30, y + 55, x - 10, y + 77, x + 25, y + 95 );
|
|
|
+ heartShape.bezierCurveTo( x + 60, y + 77, x + 80, y + 55, x + 80, y + 35 );
|
|
|
+ heartShape.bezierCurveTo( x + 80, y + 35, x + 80, y, x + 50, y );
|
|
|
+ heartShape.bezierCurveTo( x + 35, y, x + 25, y + 25, x + 25, y + 25 );
|
|
|
+
|
|
|
+
|
|
|
+ var hue = 0;
|
|
|
+
|
|
|
+ var setTargetParticle = function() {
|
|
|
+
|
|
|
+ var target = Pool.get();
|
|
|
+ values_size[target] = Math.random() * 200 + 100;
|
|
|
+
|
|
|
+ return target;
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ var onParticleCreated = function(p) {
|
|
|
+ var position = p.position;
|
|
|
+ p.target.position = position;
|
|
|
+
|
|
|
+ var target = p.target;
|
|
|
+ if (target) {
|
|
|
+ //console.log(target,particles.vertices[target]);
|
|
|
+ //values_size[target]
|
|
|
+ //values_color[target]
|
|
|
+
|
|
|
+ hue += 0.0006;
|
|
|
+ if (hue>1) hue-=1;
|
|
|
+
|
|
|
+ // TODO Create a PointOnShape Action/Zone in the particle engine
|
|
|
+ timeOnShapePath += 0.002;
|
|
|
+ if (timeOnShapePath > 1) timeOnShapePath -= 1;
|
|
|
+ var pointOnShape = heartShape.getPointAt(timeOnShapePath);
|
|
|
+
|
|
|
+ emitterpos.x = pointOnShape.x * 5 - 100;
|
|
|
+ emitterpos.y = -pointOnShape.y * 5 + 400;
|
|
|
+
|
|
|
+ particles.vertices[target].position = p.position;
|
|
|
+
|
|
|
+ values_color[target].setHSV(hue, 0.8, 0.15);
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ var onParticleDead = function(particle) {
|
|
|
+ var target = particle.target;
|
|
|
+ if (target) {
|
|
|
+ // Hide the particle
|
|
|
+ values_color[target].setHSV(0, 0, 0);
|
|
|
+ particles.vertices[target].position.set(Number.POSITIVE_INFINITY,Number.POSITIVE_INFINITY, Number.POSITIVE_INFINITY);
|
|
|
+
|
|
|
+ // Mark particle system as available by returning to pool
|
|
|
+ Pool.add(particle.target);
|
|
|
+ }
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+ var engineLoopUpdate = function() {
|
|
|
+
|
|
|
+ };
|
|
|
+
|
|
|
+
|
|
|
+ sparksEmitter = new SPARKS.Emitter(new SPARKS.SteadyCounter(600));
|
|
|
+
|
|
|
+ emitterpos = new THREE.Vector3(0,0,0);
|
|
|
+
|
|
|
+ sparksEmitter.addInitializer(new SPARKS.Position( new SPARKS.PointZone( emitterpos ) ) );
|
|
|
+ sparksEmitter.addInitializer(new SPARKS.Lifetime(1,4));
|
|
|
+ sparksEmitter.addInitializer(new SPARKS.Target(null, setTargetParticle));
|
|
|
+
|
|
|
+
|
|
|
+ sparksEmitter.addInitializer(new SPARKS.Velocity(new SPARKS.PointZone(new THREE.Vector3(0,-50,10))));
|
|
|
+ // TOTRY Set velocity to move away from centroid
|
|
|
+
|
|
|
+ sparksEmitter.addAction(new SPARKS.Age());
|
|
|
+ sparksEmitter.addAction(new SPARKS.Accelerate(0,0,50));
|
|
|
+ sparksEmitter.addAction(new SPARKS.Move());
|
|
|
+ sparksEmitter.addAction(new SPARKS.RandomDrift(50,50,2000));
|
|
|
+
|
|
|
+
|
|
|
+ sparksEmitter.addCallback("created", onParticleCreated);
|
|
|
+ sparksEmitter.addCallback("dead", onParticleDead);
|
|
|
+ sparksEmitter.start();
|
|
|
+
|
|
|
+ //sparksEmitter.addCallback("loopUpdated", engineLoopUpdate);
|
|
|
+
|
|
|
+ //sparksEmitter.addCallback("updated", function(p) {
|
|
|
+ // var target = particle.target;
|
|
|
+ // if (target) {
|
|
|
+ // // update energy properties
|
|
|
+ // //values_size[target] = Math.random()*100;
|
|
|
+ // }
|
|
|
+ //});
|
|
|
+ //
|
|
|
+ // End Particles
|
|
|
+
|
|
|
+
|
|
|
+ renderer = new THREE.WebGLRenderer();
|
|
|
+ renderer.setSize( window.innerWidth, window.innerHeight );
|
|
|
+
|
|
|
+ container.appendChild( renderer.domElement );
|
|
|
+
|
|
|
+ stats = new Stats();
|
|
|
+ stats.domElement.style.position = 'absolute';
|
|
|
+ stats.domElement.style.top = '0px';
|
|
|
+ container.appendChild( stats.domElement );
|
|
|
+
|
|
|
+ // POST PROCESSING
|
|
|
+ var shaderFocus = THREE.ShaderExtras[ "focus" ];
|
|
|
+ var effectFocus = new THREE.ShaderPass( shaderFocus );
|
|
|
+
|
|
|
+ var shaderBlur = THREE.ShaderExtras[ "triangleBlur" ];
|
|
|
+ var effectBlur = new THREE.ShaderPass( shaderBlur, 'texture' );; //
|
|
|
+ var blurAmount = 0.0020;
|
|
|
+ effectBlur.uniforms['delta'].value = new THREE.Vector2(blurAmount,blurAmount);
|
|
|
+ effectFocus.uniforms['sampleDistance'].value = 0.99; //0.94
|
|
|
+ effectFocus.uniforms['waveFactor'].value = 0.002; //0.00125
|
|
|
+
|
|
|
+ var renderScene = new THREE.RenderPass( scene, camera );
|
|
|
+
|
|
|
+ composer = new THREE.EffectComposer( renderer );
|
|
|
+ composer.addPass( renderScene );
|
|
|
+ composer.addPass( effectBlur ); // effectBlur effectFocus
|
|
|
+
|
|
|
+ effectBlur.renderToScreen = true;
|
|
|
+ effectFocus.renderToScreen = true;
|
|
|
+
|
|
|
+ document.addEventListener( 'mousedown', onDocumentMouseDown, false );
|
|
|
+ document.addEventListener( 'touchstart', onDocumentTouchStart, false );
|
|
|
+ document.addEventListener( 'touchmove', onDocumentTouchMove, false );
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+
|
|
|
+ document.addEventListener( 'mousemove', onDocumentMouseMove, false );
|
|
|
+
|
|
|
+
|
|
|
+ function onDocumentMouseDown( event ) {
|
|
|
+
|
|
|
+ event.preventDefault();
|
|
|
+
|
|
|
+ mouseXOnMouseDown = event.clientX - windowHalfX;
|
|
|
+ targetRotationOnMouseDown = targetRotation;
|
|
|
+
|
|
|
+ if (sparksEmitter.isRunning()) {
|
|
|
+ sparksEmitter.stop();
|
|
|
+ } else {
|
|
|
+ sparksEmitter.start();
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function onDocumentMouseMove( event ) {
|
|
|
+
|
|
|
+ mouseX = event.clientX - windowHalfX;
|
|
|
+
|
|
|
+ targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.02;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function onDocumentTouchStart( event ) {
|
|
|
+
|
|
|
+ if ( event.touches.length == 1 ) {
|
|
|
+
|
|
|
+ event.preventDefault();
|
|
|
+
|
|
|
+ mouseXOnMouseDown = event.touches[ 0 ].pageX - windowHalfX;
|
|
|
+ targetRotationOnMouseDown = targetRotation;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ function onDocumentTouchMove( event ) {
|
|
|
+
|
|
|
+ if ( event.touches.length == 1 ) {
|
|
|
+
|
|
|
+ event.preventDefault();
|
|
|
+
|
|
|
+ mouseX = event.touches[ 0 ].pageX - windowHalfX;
|
|
|
+ targetRotation = targetRotationOnMouseDown + ( mouseX - mouseXOnMouseDown ) * 0.05;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ //
|
|
|
+
|
|
|
+ function animate() {
|
|
|
+
|
|
|
+ requestAnimationFrame( animate );
|
|
|
+
|
|
|
+ render();
|
|
|
+ stats.update();
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ function render() {
|
|
|
+
|
|
|
+ particleCloud.geometry.__dirtyVertices = true;
|
|
|
+ particleCloud.geometry.__dirtyColors = true;
|
|
|
+ attributes.size.needsUpdate = true;
|
|
|
+ attributes.ca.needsUpdate = true;
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+ // Pretty cool effect if you enable this
|
|
|
+ //particleCloud.rotation.y += 0.05;
|
|
|
+
|
|
|
+ parent.rotation.y += ( targetRotation - parent.rotation.y ) * 0.05;
|
|
|
+ //renderer.render( scene, camera );
|
|
|
+ composer.render( );
|
|
|
+
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ </script>
|
|
|
+
|
|
|
+ </body>
|
|
|
+</html>
|