From 0ccb2e5ef99a6231bb7abe4dd3bb236c6a9f165b Mon Sep 17 00:00:00 2001 From: Diego Marcos Date: Mon, 1 Oct 2018 11:22:40 -0700 Subject: [PATCH] Add saber trail --- src/components/trail.js | 333 ++++++++++++++++++++++++++++++++++++++++ src/index.html | 3 +- 2 files changed, 335 insertions(+), 1 deletion(-) create mode 100644 src/components/trail.js diff --git a/src/components/trail.js b/src/components/trail.js new file mode 100644 index 0000000..0aca8bc --- /dev/null +++ b/src/components/trail.js @@ -0,0 +1,333 @@ +AFRAME.registerComponent('trail', { + schema: { + color: {type: 'color'} + }, + + init: function () { + var geometry = this.geometry = new THREE.BufferGeometry(); + var steps = 10; + var maxPoints = this.maxPoints = 12; + var vertices = this.vertices = new Float32Array(36 * maxPoints); + var colors = this.colors = new Float32Array(48 * maxPoints); + var bladeColor = this.bladeColor = new THREE.Color(this.data.color); + this.bladeColor = { + red: bladeColor.r, + green: bladeColor.g, + blue: bladeColor.b, + alpha: 1.0 + }; + this.saberEl = this.el.querySelector('.blade'); + + this.layers = 0; + this.saberTrajectory = [ + {top: {x:-0.5, y: 0, z: 0}, center: {x: 0, y: 0, z: 0}, bottom: {x: 0.5, y: 0, z: 0}}, + {top: {x:-0.5, y: 0.5, z: 0}, center: {x:0, y: 0.5, z: 0}, bottom: {x: 0.5, y: 0.5, z: 0}}, + {top: {x:-0.5, y: 1.0, z: 0}, center: {x:0, y: 1.0, z: 0}, bottom: {x: 0.5, y: 1.0, z: 0}} + ]; + + //geometry.setDrawRange(0, 0); + geometry.addAttribute('position', new THREE.BufferAttribute(vertices, 3).setDynamic(true)); + geometry.addAttribute('vertexColor', new THREE.BufferAttribute(colors, 4).setDynamic(true)); + + var material = new THREE.ShaderMaterial({ + side: THREE.DoubleSide, + vertexColors: THREE.VertexColors, + transparent: true, + vertexShader: [ + 'varying vec4 vColor;', + 'attribute vec4 vertexColor;', + 'void main() {', + 'vec4 modelViewPosition = modelViewMatrix * vec4(position, 1.0);', + 'vColor = vertexColor;', + 'gl_Position = projectionMatrix * modelViewPosition;', + '}' + ].join(''), + fragmentShader: [ + 'varying vec4 vColor;', + 'void main() {', + 'gl_FragColor = vColor;', + '}' + ].join('') + }); + + //this.initGeometry(); + var mesh = this.mesh = new THREE.Mesh(geometry, material); + // var material = new THREE.MeshBasicMaterial({color: 0xffff00}); + // var wireframe = new THREE.WireframeGeometry(geometry); + // var mesh = new THREE.LineSegments(wireframe, material); + + mesh.frustumCulled = false; + mesh.vertices = vertices; + //mesh.scale.set(0.4, 0.4, 0.4); + //mesh.rotation.set(0, 0, Math.PI / 2.0); + this.el.sceneEl.setObject3D('trail', mesh); + }, + + addLayer: function (length) { + var startX = -1.0; + var segments = this.segments; + var dx = 2 / segments; + var colors = this.colors; + var bottomLayer; + var vertices = this.vertices; + var uvs = this.uvs; + var indexOffset; + var color = this.bladeColor; + + if (this.layers >= this.maxLayers) { this.layers = 0; } + + bottomLayer = this.layers * length; + length = bottomLayer + length; + indexOffset = this.layers * segments * 18; + colorOffset = this.layers * segments * 24; + + for (var i = 0; i < segments; ++i) { + vertices[indexOffset + 18 * i] = startX + i * dx; + vertices[indexOffset + 18 * i + 1] = bottomLayer; + vertices[indexOffset + 18 * i + 2] = 0.0; + + // Color + colors[colorOffset + 24 * i] = color.red; + colors[colorOffset + 24 * i + 1] = color.green; + colors[colorOffset + 24 * i + 2] = color.blue; + colors[colorOffset + 24 * i + 3] = color.alpha; + + vertices[indexOffset + 18 * i + 3] = startX + i * dx; + vertices[indexOffset + 18 * i + 4] = length; + vertices[indexOffset + 18 * i + 5] = 0.0; + + // Color + colors[colorOffset + 24 * i + 4] = color.red; + colors[colorOffset + 24 * i + 5] = color.green; + colors[colorOffset + 24 * i + 6] = color.blue; + colors[colorOffset + 24 * i + 7] = color.alpha; + + vertices[indexOffset + 18 * i + 6] = startX + i * dx + dx; + vertices[indexOffset + 18 * i + 7] = length; + vertices[indexOffset + 18 * i + 8] = 0.0; + + // Color + colors[colorOffset + 24 * i + 8] = color.red; + colors[colorOffset + 24 * i + 9] = color.green; + colors[colorOffset + 24 * i + 10] = color.blue; + colors[colorOffset + 24 * i + 11] = color.alpha; + + vertices[indexOffset + 18 * i + 9] = startX + i * dx + dx; + vertices[indexOffset + 18 * i + 10] = bottomLayer; + vertices[indexOffset + 18 * i + 11] = 0.0; + + // Color + colors[colorOffset + 24 * i + 12] = color.red; + colors[colorOffset + 24 * i + 13] = color.green; + colors[colorOffset + 24 * i + 14] = color.blue; + colors[colorOffset + 24 * i + 15] = color.alpha; + + vertices[indexOffset + 18 * i + 12] = startX + i * dx; + vertices[indexOffset + 18 * i + 13] = bottomLayer; + vertices[indexOffset + 18 * i + 14] = 0.0; + + // Color + colors[colorOffset + 24 * i + 16] = color.red; + colors[colorOffset + 24 * i + 17] = color.green; + colors[colorOffset + 24 * i + 18] = color.blue; + colors[colorOffset + 24 * i + 19] = color.alpha; + + vertices[indexOffset + 18 * i + 15] = startX + i * dx + dx; + vertices[indexOffset + 18 * i + 16] = length; + vertices[indexOffset + 18 * i + 17] = 0.0; + + // Color + colors[colorOffset + 24 * i + 20] = color.red; + colors[colorOffset + 24 * i + 21] = color.green; + colors[colorOffset + 24 * i + 22] = color.blue; + colors[colorOffset + 24 * i + 23] = color.alpha; + } + + this.layers++; + this.geometry.attributes.position.needsUpdate = true; + this.geometry.attributes.vertexColor.needsUpdate = true; + this.geometry.attributes.uv.needsUpdate = true; + }, + + initGeometry: function () { + var i; + var previousPoint; + var currentPoint; + var saberTrajectory = this.saberTrajectory; + var vertices = this.geometry.attributes.position.array; + var colors = this.geometry.attributes.vertexColor.array; + var color = this.bladeColor; + var alpha; + var previousAlpha; + + for (i = 1; i < saberTrajectory.length; i++) { + if (i === 1) { previousAlpha = alpha; } + alpha = 1.0 - ((saberTrajectory.length - i) / saberTrajectory.length); + + currentPoint = saberTrajectory[i]; + previousPoint = saberTrajectory[i-1]; + + vertices[36 * i] = previousPoint.center.x; + vertices[36 * i + 1] = previousPoint.center.y; + vertices[36 * i + 2] = previousPoint.center.z; + + // Color + colors[48 * i] = color.red; + colors[48 * i + 1] = color.green; + colors[48 * i + 2] = color.blue; + colors[48 * i + 3] = previousAlpha * 0.2; + + vertices[36 * i + 3] = currentPoint.top.x; + vertices[36 * i + 4] = currentPoint.top.y; + vertices[36 * i + 5] = currentPoint.top.z; + + // Color + colors[48 * i + 4] = color.red; + colors[48 * i + 5] = color.green; + colors[48 * i + 6] = color.blue; + colors[48 * i + 7] = alpha; + + vertices[36 * i + 6] = previousPoint.top.x; + vertices[36 * i + 7] = previousPoint.top.y; + vertices[36 * i + 8] = previousPoint.top.z; + + // Color + colors[48 * i + 8] = color.red; + colors[48 * i + 9] = color.green; + colors[48 * i + 10] = color.blue; + colors[48 * i + 11] = previousAlpha; + + vertices[36 * i + 9] = previousPoint.center.x; + vertices[36 * i + 10] = previousPoint.center.y; + vertices[36 * i + 11] = previousPoint.center.z; + + // Color + colors[48 * i + 12] = color.red; + colors[48 * i + 13] = color.green; + colors[48 * i + 14] = color.blue; + colors[48 * i + 15] = previousAlpha * 0.2; + + vertices[36 * i + 12] = currentPoint.center.x; + vertices[36 * i + 13] = currentPoint.center.y; + vertices[36 * i + 14] = currentPoint.center.z; + + // Color + colors[48 * i + 16] = color.red; + colors[48 * i + 17] = color.green; + colors[48 * i + 18] = color.blue; + colors[48 * i + 19] = alpha * 0.2; + + vertices[36 * i + 15] = currentPoint.top.x; + vertices[36 * i + 16] = currentPoint.top.y; + vertices[36 * i + 17] = currentPoint.top.z; + + // Color + colors[48 * i + 20] = color.red; + colors[48 * i + 21] = color.green; + colors[48 * i + 22] = color.blue; + colors[48 * i + 23] = alpha; + + vertices[36 * i + 18] = previousPoint.bottom.x; + vertices[36 * i + 19] = previousPoint.bottom.y; + vertices[36 * i + 20] = previousPoint.bottom.z; + + // Color + colors[48 * i + 24] = color.red; + colors[48 * i + 25] = color.green; + colors[48 * i + 26] = color.blue; + colors[48 * i + 27] = 0.0; + + vertices[36 * i + 21] = currentPoint.center.x; + vertices[36 * i + 22] = currentPoint.center.y; + vertices[36 * i + 23] = currentPoint.center.z; + + // Color + colors[48 * i + 28] = color.red; + colors[48 * i + 29] = color.green; + colors[48 * i + 30] = color.blue; + colors[48 * i + 31] = alpha * 0.2; + + vertices[36 * i + 24] = previousPoint.center.x; + vertices[36 * i + 25] = previousPoint.center.y; + vertices[36 * i + 26] = previousPoint.center.z; + + // Color + colors[48 * i + 32] = color.red; + colors[48 * i + 33] = color.green; + colors[48 * i + 34] = color.blue; + colors[48 * i + 35] = previousAlpha * 0.2; + + vertices[36 * i + 27] = previousPoint.bottom.x; + vertices[36 * i + 28] = previousPoint.bottom.y; + vertices[36 * i + 29] = previousPoint.bottom.z; + + // Color + colors[48 * i + 36] = color.red; + colors[48 * i + 37] = color.green; + colors[48 * i + 38] = color.blue; + colors[48 * i + 39] = 0.0; + + vertices[36 * i + 30] = currentPoint.bottom.x; + vertices[36 * i + 31] = currentPoint.bottom.y; + vertices[36 * i + 32] = currentPoint.bottom.z; + + // Color + colors[48 * i + 40] = color.red; + colors[48 * i + 41] = color.green; + colors[48 * i + 42] = color.blue; + colors[48 * i + 43] = 0.0; + + vertices[36 * i + 33] = currentPoint.center.x; + vertices[36 * i + 34] = currentPoint.center.y; + vertices[36 * i + 35] = currentPoint.center.z; + + // Color + colors[48 * i + 44] = color.red; + colors[48 * i + 45] = color.green; + colors[48 * i + 46] = color.blue; + colors[48 * i + 47] = alpha * 0.2; + + previousAlpha = alpha; + } + + this.geometry.attributes.position.needsUpdate = true; + this.geometry.attributes.vertexColor.needsUpdate = true; + }, + + tock: function (time, delta) { + this.sampleSaberPosition(); + }, + + sampleSaberPosition: function () { + var saberEl = this.el.querySelector('.blade'); + var saberObject; + var sample; + + if (!saberEl) { return; } + + if (this.saberTrajectory.length === this.maxPoints) { + // Dump oldest point + sample = this.saberTrajectory.shift(); + sample.top.set(0, -0.4, 0); + sample.center.set(0, 0, 0); + sample.bottom.set(0, 0.4, 0) + } else { + sample = { + top: new THREE.Vector3(0, -0.4, 0), + center: new THREE.Vector3(0, 0, 0), + bottom: new THREE.Vector3(0, 0.4, 0) + }; + } + + saberObject = saberEl.object3D; + + saberObject.parent.updateMatrixWorld(); + saberObject.localToWorld(sample.top); + saberObject.localToWorld(sample.center); + saberObject.localToWorld(sample.bottom); + + this.saberTrajectory.push(sample); + + this.initGeometry(); + } +}); \ No newline at end of file diff --git a/src/index.html b/src/index.html index 66fa6bb..cdd6278 100644 --- a/src/index.html +++ b/src/index.html @@ -77,7 +77,8 @@ bind__raycaster="enabled: {{ hand }}RaycasterActive" bind__saber-controls="bladeEnabled: !menu.active" haptics="events: mouseenter; dur: 35; force: 0.075" - saber-controls="hand: {{ hand }}"> + saber-controls="hand: {{ hand }}" + trail="color: {{ bladeColor }}">