added particles on beat slicing (fixes #54)

This commit is contained in:
Diego F. Goberna
2018-10-06 01:36:04 +02:00
parent 4b3f257b71
commit 9892f993e6
9 changed files with 637 additions and 36 deletions

BIN
assets/img/spark.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

File diff suppressed because one or more lines are too long

25
package-lock.json generated
View File

@@ -99,21 +99,11 @@
"animejs": "2.2.0"
}
},
"aframe-animation-timeline-component": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/aframe-animation-timeline-component/-/aframe-animation-timeline-component-1.5.0.tgz",
"integrity": "sha512-mVxIH5qjik3qnbmeuXnYWFyKkcdLdZEQIFIFky1Z3QY8gZFsbCgocImwAx9UV9DTsIywa/lt3nXyNrpgOQgNCg=="
},
"aframe-audioanalyser-component": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/aframe-audioanalyser-component/-/aframe-audioanalyser-component-4.0.1.tgz",
"integrity": "sha512-jTkt9umD4SoRmW6vlJfm2zG9fV8pzecNzTdJYn12w8hpZ0lp3BtFSKqTDy0RE3dqAsDJo9AU72niZAu8w3NeeA=="
},
"aframe-cubemap-component": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/aframe-cubemap-component/-/aframe-cubemap-component-0.1.4.tgz",
"integrity": "sha512-9k5CVFltFACmoQxmS9Jf3XpjqpES9iNSRnCxamxSDCpNyXn7myHii7bjnfIuzs6zwSeJU8Gbb72zzRyQ6Csp9g=="
},
"aframe-event-decorators": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/aframe-event-decorators/-/aframe-event-decorators-1.0.2.tgz",
@@ -129,11 +119,6 @@
"resolved": "https://registry.npmjs.org/aframe-geometry-merger-component/-/aframe-geometry-merger-component-2.0.0-beta1.tgz",
"integrity": "sha512-0anZA8K7X5lybhbQEGdI8uH0tMZx1b90EA69MOkWfaYPKLWEK9neOWoF+qxOQql5Zz04zVl+BJ9q0fESuUnS9Q=="
},
"aframe-gltf-part-component": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/aframe-gltf-part-component/-/aframe-gltf-part-component-1.1.0.tgz",
"integrity": "sha1-jX/8ViYbozraC6izQf3eif8rhlQ="
},
"aframe-haptics-component": {
"version": "1.4.2",
"resolved": "https://registry.npmjs.org/aframe-haptics-component/-/aframe-haptics-component-1.4.2.tgz",
@@ -153,16 +138,6 @@
"resolved": "https://registry.npmjs.org/aframe-orbit-controls/-/aframe-orbit-controls-1.2.0.tgz",
"integrity": "sha512-g3j3Z3Lpf+LxIuNUwteVcB+eJ5jXwYEEzHbbRhdCJ754a9yqlvjt4tjvBq56F5ilpsg/bNUi8cjza8FFvJfd5g=="
},
"aframe-particle-system-component": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/aframe-particle-system-component/-/aframe-particle-system-component-1.0.11.tgz",
"integrity": "sha1-rB86vvIweyON9YyTWJgsmH+xABY="
},
"aframe-particleplayer-component": {
"version": "2.0.0-beta2",
"resolved": "https://registry.npmjs.org/aframe-particleplayer-component/-/aframe-particleplayer-component-2.0.0-beta2.tgz",
"integrity": "sha512-5g2G5a9rvEma6ybgcCZJhJF53PKB5H5rIXjxozh7tE1ZbSDJv5EhCYLlwAJpmxUHbd59DJJQQGTbGdh33py2Iw=="
},
"aframe-proxy-event-component": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/aframe-proxy-event-component/-/aframe-proxy-event-component-2.1.0.tgz",

View File

@@ -7,18 +7,13 @@
},
"dependencies": {
"aframe-animation-component": "^5.1.2",
"aframe-animation-timeline-component": "^1.3.1",
"aframe-audioanalyser-component": "^4.0.1",
"aframe-cubemap-component": "^0.1.2",
"aframe-event-decorators": "^1.0.2",
"aframe-event-set-component": "^4.0.1",
"aframe-geometry-merger-component": "^2.0.0-beta1",
"aframe-gltf-part-component": "1.1.0",
"aframe-haptics-component": "^1.4.2",
"aframe-layout-component": "^5.2.0",
"aframe-orbit-controls": "^1.2.0",
"aframe-particle-system-component": "^1.0.11",
"aframe-particleplayer-component": "^2.0.0-beta2",
"aframe-proxy-event-component": "^2.1.0",
"aframe-slice9-component": "^1.0.0",
"aframe-state-component": "^5.0.0-beta6",

View File

@@ -1,5 +1,7 @@
var SIGN_MATERIAL = {shader: 'flat', color: '#88f'};
var auxObj3D = new THREE.Object3D();
/**
* Create beat from pool, collision detection, clipping planes.
*/
@@ -52,6 +54,7 @@ AFRAME.registerComponent('beat', {
this.missElRight = document.getElementById('missRight');
this.beams = document.getElementById('beams').components['beams'];
this.particles = document.getElementById('saberParticles');
this.initBlock();
this.initColliders();
@@ -308,7 +311,12 @@ AFRAME.registerComponent('beat', {
this.returnToPoolTimer = 800;
// this.el.sceneEl.components['json-particles__hit'].explode(this.el.object3D.position, rightCutPlane.normal, direction, this.data.color);
auxObj3D.up.copy(rightCutPlane.normal);
auxObj3D.lookAt(direction);
this.particles.emit('explode', {
position: this.el.object3D.position,
rotation: auxObj3D.rotation
});
}
})(),

View File

@@ -0,0 +1,621 @@
const NUM_PLANE_POSITIONS = 12;
const BLENDINGS = {
normal: THREE.NormalBlending,
additive: THREE.AdditiveBlending,
substractive: THREE.SubstractiveBlending,
multiply: THREE.MultiplyBlending
};
const SHADERS = {
flat: THREE.MeshBasicMaterial,
lambert: THREE.MeshLambertMaterial,
phong: THREE.MeshPhongMaterial,
standard: THREE.MeshStandardMaterial
};
const OFFSCREEN_VEC3 = new THREE.Vector3(-99999, -99999, -99999);
/**
* Particle Player component for A-Frame.
*/
AFRAME.registerComponent('particleplayer', {
schema: {
blending: {
default: 'additive',
oneOf: ['normal', 'additive', 'multiply', 'substractive']
},
color: {default: '#fff', type: 'color'},
count: {default: '100%'},
delay: {default: 0, type: 'int'},
dur: {default: 1000, type: 'int'},
img: {type: 'selector'},
interpolate: {default: false},
loop: {default: 'false'},
on: {default: 'init'},
poolSize: {default: 5, type: 'int'}, // number of simultaneous particle systems
protation: {type: 'vec3'},
pscale: {default: 1.0, type: 'float'},
scale: {default: 1.0, type: 'float'},
initialScale: {type: 'vec3'},
finalScale: {type: 'vec3'},
animateScale: {default: false},
shader: {
default: 'flat',
oneOf: ['flat', 'lambert', 'phong', 'standard']
},
src: {type: 'selector'}
},
multiple: true,
init: function() {
this.frame = 0;
this.framedata = null;
this.indexPool = null;
this.lastFrame = 0;
this.material = null;
this.msPerFrame = 0;
this.numFrames = 0;
this.numParticles = 0; // total number of particles per system
this.originalVertexPositions = [];
this.particleCount = 0; // actual number of particles to spawn per event (data.count)
this.particleSystems = [];
this.protation = false;
this.restPositions = []; // position at first frame each particle is alive
this.restRotations = [];
this.sprite_rotation = false;
this.systems = null;
this.useRotation = false;
this.scaleAnim = new THREE.Vector3();
},
update: function(oldData) {
const data = this.data;
if (!data.src) {
return;
}
if (oldData.on !== data.on) {
if (oldData.on) {
this.el.removeEventListener(oldData.on, this.start);
}
if (data.on !== 'play') {
this.el.addEventListener(data.on, this.start.bind(this));
}
}
this.loadParticlesJSON(data.src, data.scale);
this.numFrames = this.framedata.length;
this.numParticles = this.numFrames > 0 ? this.framedata[0].length : 0;
if (data.count[data.count.length - 1] === '%') {
this.particleCount = Math.floor(
(parseInt(data.count) * this.numParticles) / 100.0
);
} else {
this.particleCount = parseInt(data.count);
}
this.particleCount = Math.min(
this.numParticles,
Math.max(0, this.particleCount)
);
this.msPerFrame = data.dur / this.numFrames;
this.indexPool = new Array(this.numParticles);
const materialParams = {
color: new THREE.Color(data.color),
side: THREE.DoubleSide,
blending: BLENDINGS[data.blending],
map: data.img ? new THREE.TextureLoader().load(data.img.src) : null,
depthWrite: false,
opacity: data.opacity,
transparent: !!data.img || data.blending !== 'normal' || data.opacity < 1
};
if (SHADERS[data.shader] !== undefined) {
this.material = new SHADERS[data.shader](materialParams);
} else {
this.material = new SHADERS['flat'](materialParams);
}
this.createParticles(data.poolSize);
if (data.on === 'init') {
this.start();
}
},
loadParticlesJSON: function(json, scale) {
var alive;
this.restPositions.length = 0;
this.restRotations.length = 0;
const jsonData = JSON.parse(json.data);
const frames = jsonData.frames;
const precision = jsonData.precision;
this.useRotation = jsonData.rotation;
if (jsonData.sprite_rotation !== false) {
this.sprite_rotation = {
x: jsonData.sprite_rotation[0] / precision,
y: jsonData.sprite_rotation[1] / precision,
z: jsonData.sprite_rotation[2] / precision
};
} else {
this.sprite_rotation = false;
}
this.framedata = new Array(frames.length);
for (let frameIndex = 0; frameIndex < frames.length; frameIndex++) {
this.framedata[frameIndex] = new Array(frames[frameIndex].length);
for (
let particleIndex = 0;
particleIndex < frames[frameIndex].length;
particleIndex++
) {
let rawP = frames[frameIndex][particleIndex]; // data of particle i in frame f
alive = rawP !== 0; // 0 means not alive yet this frame.
let p = (this.framedata[frameIndex][particleIndex] = {
position: alive
? {
x: (rawP[0] / precision) * scale,
y: (rawP[1] / precision) * scale,
z: (rawP[2] / precision) * scale
}
: null,
alive: alive
});
if (jsonData.rotation) {
p.rotation = alive
? {
x: rawP[3] / precision,
y: rawP[4] / precision,
z: rawP[5] / precision
}
: null;
}
if (alive && frameIndex === 0) {
this.restPositions[particleIndex] = p.position
? {x: p.position.y, y: p.position.y, z: p.position.z}
: null;
this.restRotations[particleIndex] = p.rotation
? {x: p.rotation.y, y: p.rotation.y, z: p.rotation.z}
: null;
}
}
}
},
createParticles: (function() {
const tempGeometries = [];
return function(numParticleSystems) {
const data = this.data;
var loop = parseInt(this.data.loop);
this.particleSystems.length = 0;
if (isNaN(loop)) {
loop = this.data.loop === 'true' ? Number.MAX_VALUE : 0;
}
for (let i = 0; i < numParticleSystems; i++) {
let particleSystem = {
active: false,
activeParticleIndices: new Array(this.particleCount),
loopCount: 0,
loopTotal: loop,
mesh: null,
time: 0,
pscale: data.animateScale ? new THREE.Vector3() : null
};
// Fill array of geometries to merge.
const ratio = data.img ? data.img.width / data.img.height : 1;
tempGeometries.length = 0;
for (let p = 0; p < this.numParticles; p++) {
let geometry = new THREE.PlaneBufferGeometry(
0.1 * ratio * data.pscale,
0.1 * data.pscale
);
if (this.sprite_rotation !== false) {
geometry.rotateX(this.sprite_rotation.x);
geometry.rotateY(this.sprite_rotation.y);
geometry.rotateZ(this.sprite_rotation.z);
} else {
geometry.rotateX((this.data.protation.x * Math.PI) / 180);
geometry.rotateY((this.data.protation.y * Math.PI) / 180);
geometry.rotateZ((this.data.protation.z * Math.PI) / 180);
}
tempGeometries.push(geometry);
}
// Create merged geometry for whole particle system.
let mergedBufferGeometry = THREE.BufferGeometryUtils.mergeBufferGeometries(
tempGeometries
);
particleSystem.mesh = new THREE.Mesh(
mergedBufferGeometry,
this.material
);
particleSystem.mesh.visible = false;
this.el.setObject3D(`particleplayer${i}`, particleSystem.mesh);
copyArray(
this.originalVertexPositions,
mergedBufferGeometry.attributes.position.array
);
// Hide all particles by default.
for (
let i = 0;
i < mergedBufferGeometry.attributes.position.array.length;
i++
) {
mergedBufferGeometry.attributes.position.array[i] = -99999;
}
for (let i = 0; i < particleSystem.activeParticleIndices.length; i++) {
particleSystem.activeParticleIndices[i] = i;
};
this.particleSystems.push(particleSystem);
}
};
})(),
start: function(evt) {
if (this.data.delay > 0) {
setTimeout(() => this.startAfterDelay(evt), this.data.delay);
} else {
this.startAfterDelay(evt);
}
},
startAfterDelay: function(evt) {
// position, rotation
var found = -1;
var particleSystem;
var oldestTime = 0;
var position = evt ? evt.detail.position : null;
var rotation = evt ? evt.detail.rotation : null;
if (!(position instanceof THREE.Vector3)) {
position = new THREE.Vector3();
}
if (!(rotation instanceof THREE.Euler)) {
rotation = new THREE.Euler();
}
// find available (or oldest) particle system
for (var i = 0; i < this.particleSystems.length; i++) {
if (this.particleSystems[i].active === false) {
found = i;
break;
}
if (this.particleSystems[i].time > oldestTime) {
found = i;
oldestTime = this.particleSystems[i].time;
}
}
particleSystem = this.particleSystems[found];
particleSystem.active = true;
particleSystem.loopCount = 1;
particleSystem.mesh.visible = true;
particleSystem.mesh.position.copy(position);
particleSystem.mesh.rotation.copy(rotation);
particleSystem.time = 0;
if (this.data.animateScale) {
particleSystem.pscale.copy(this.data.initialScale);
}
this.resetParticles(particleSystem);
},
doLoop: function(particleSystem) {
particleSystem.loopCount++;
particleSystem.frame = -1;
particleSystem.time = 0;
if (this.data.animateScale) {
particleSystem.pscale.copy(data.initialScale);
}
this.resetParticles(particleSystem);
},
resetParticle: function(particleSystem, particleIndex) {
const geometry = particleSystem.mesh.geometry;
if (this.restPositions[particleIndex]) {
transformPlane(
particleIndex,
geometry,
this.originalVertexPositions,
this.restPositions[particleIndex],
this.useRotation && this.restRotations[particleIndex],
particleSystem.pscale
);
} else {
// Hide.
transformPlane(
particleIndex,
geometry,
this.originalVertexPositions,
OFFSCREEN_VEC3,
undefined,
null
);
}
// TODO: Can update transformPlane for lookAt.
// lookAt does not support rotated or translated parents! :_(
// part.lookAt(this.camera.position);
},
/**
* When starting or finishing (looping) animation, this resets particles
* to their initial position and, if user asked for replaying less than 100%
* of particles, randomly choose them.
*/
resetParticles: function(particleSystem) {
var i;
var rand;
// no picking, just hide and reset
if (this.particleCount === this.numParticles) {
for (i = 0; i < this.numParticles; i++) {
this.resetParticle(particleSystem, i);
}
return;
}
// hide particles from last animation and initialize indexPool
const geometry = particleSystem.mesh.geometry;
for (i = 0; i < this.numParticles; i++) {
if (i < this.particleCount) {
transformPlane(
particleSystem.activeParticleIndices[i],
geometry,
this.originalVertexPositions,
OFFSCREEN_VEC3,
undefined,
null
);
}
this.indexPool[i] = i;
}
// scramble indexPool
for (i = 0; i < this.particleCount; i++) {
rand = i + Math.floor(Math.random() * (this.numParticles - i));
particleSystem.activeParticleIndices[i] = this.indexPool[rand];
this.indexPool[rand] = this.indexPool[i];
this.resetParticle(
particleSystem,
particleSystem.activeParticleIndices[i]
);
}
},
tick: (function() {
const helperPositionVec3 = new THREE.Vector3();
return function(time, delta) {
var frame; // current particle system frame
var fdata; // all particles data in current frame
var fdataNext; // next frame (for interpolation)
var useRotation = this.useRotation;
var frameTime; // time in current frame (for interpolation)
var relTime; // current particle system relative time (0-1)
var interpolate; // whether interpolate between frames or not
for (
let particleSystemIndex = 0;
particleSystemIndex < this.particleSystems.length;
particleSystemIndex++
) {
let particleSystem = this.particleSystems[particleSystemIndex];
if (!particleSystem.active) {
continue;
}
// if the duration is so short that there's no need to interpolate, don't do it
// even if user asked for it.
interpolate =
this.data.interpolate && this.data.dur / this.numFrames > delta;
relTime = particleSystem.time / this.data.dur;
frame = relTime * this.numFrames;
fdata = this.framedata[Math.floor(frame)];
if (interpolate) {
frameTime = frame - Math.floor(frame);
fdataNext =
frame < this.numFrames - 1
? this.framedata[Math.floor(frame) + 1]
: null;
}
if (this.data.animateScale){
particleSystem.pscale.lerp(this.data.finalScale, relTime);
}
for (
let activeParticleIndex = 0;
activeParticleIndex < particleSystem.activeParticleIndices.length;
activeParticleIndex++
) {
let particleIndex =
particleSystem.activeParticleIndices[activeParticleIndex];
let rotation = useRotation && fdata[particleIndex].rotation;
// TODO: Add vertex position to original position to all vertices of plane...
if (!fdata[particleIndex].alive) {
// Hide plane off-screen when not alive.
transformPlane(
particleIndex,
particleSystem.mesh.geometry,
this.originalVertexPositions,
OFFSCREEN_VEC3,
undefined,
null
);
continue;
}
if (interpolate && fdataNext && fdataNext[particleIndex].alive) {
helperPositionVec3.lerpVectors(
fdata[particleIndex].position,
fdataNext[particleIndex].position,
frameTime
);
transformPlane(
particleIndex,
particleSystem.mesh.geometry,
this.originalVertexPositions,
helperPositionVec3,
rotation,
particleSystem.pscale
);
} else {
transformPlane(
particleIndex,
particleSystem.mesh.geometry,
this.originalVertexPositions,
fdata[particleIndex].position,
rotation,
particleSystem.pscale
);
}
}
particleSystem.time += delta;
if (particleSystem.time >= this.data.dur) {
if (particleSystem.loopCount < particleSystem.loopTotal) {
this.el.emit('particleplayerloop', null, false);
this.doLoop(particleSystem);
} else {
this.el.emit('particleplayerfinished', null, false);
particleSystem.active = false;
particleSystem.mesh.visible = false;
}
continue;
}
}
};
})(),
_transformPlane: transformPlane
});
// Use triangle geometry as a helper for rotating.
const tri = (function() {
const tri = new THREE.Geometry();
tri.vertices.push(new THREE.Vector3());
tri.vertices.push(new THREE.Vector3());
tri.vertices.push(new THREE.Vector3());
tri.faces.push(new THREE.Face3(0, 1, 2));
return tri;
})();
/**
* Faces of a plane are v0, v2, v1 and v2, v3, v1.
* Positions are 12 numbers: [v0, v1, v2, v3].
*/
function transformPlane(
particleIndex,
geometry,
originalArray,
position,
rotation,
scale
) {
const array = geometry.attributes.position.array;
const index = particleIndex * NUM_PLANE_POSITIONS;
// Calculate first face (0, 2, 1).
tri.vertices[0].set(
originalArray[index + 0],
originalArray[index + 1],
originalArray[index + 2]
);
tri.vertices[1].set(
originalArray[index + 3],
originalArray[index + 4],
originalArray[index + 5]
);
tri.vertices[2].set(
originalArray[index + 6],
originalArray[index + 7],
originalArray[index + 8]
);
if (scale !== null) {
tri.scale(scale.x, scale.y, scale.z);
}
if (rotation) {
tri.rotateX(rotation.x);
tri.rotateY(rotation.y);
tri.rotateZ(rotation.z);
}
tri.vertices[0].add(position);
tri.vertices[1].add(position);
tri.vertices[2].add(position);
array[index + 0] = tri.vertices[0].x;
array[index + 1] = tri.vertices[0].y;
array[index + 2] = tri.vertices[0].z;
array[index + 3] = tri.vertices[1].x;
array[index + 4] = tri.vertices[1].y;
array[index + 5] = tri.vertices[1].z;
array[index + 6] = tri.vertices[2].x;
array[index + 7] = tri.vertices[2].y;
array[index + 8] = tri.vertices[2].z;
// Calculate second face (2, 3, 1) just for the last vertex.
tri.vertices[0].set(
originalArray[index + 3],
originalArray[index + 4],
originalArray[index + 5]
);
tri.vertices[1].set(
originalArray[index + 6],
originalArray[index + 7],
originalArray[index + 8]
);
tri.vertices[2].set(
originalArray[index + 9],
originalArray[index + 10],
originalArray[index + 11]
);
if (scale !== null) {
tri.scale(scale.x, scale.y, scale.z);
}
if (rotation) {
tri.rotateX(rotation.x);
tri.rotateY(rotation.y);
tri.rotateZ(rotation.z);
}
tri.vertices[0].add(position);
tri.vertices[1].add(position);
tri.vertices[2].add(position);
array[index + 9] = tri.vertices[2].x;
array[index + 10] = tri.vertices[2].y;
array[index + 11] = tri.vertices[2].z;
geometry.attributes.position.needsUpdate = true;
}
module.exports.transformPlane = transformPlane;
function copyArray(dest, src) {
dest.length = 0;
for (let i = 0; i < src.length; i++) {
dest[i] = src[i];
}
}

View File

@@ -35,8 +35,9 @@
<a-asset-item id="logofrontObj" src="assets/models/logofront.obj"></a-asset-item>
<a-asset-item id="logobackObj" src="assets/models/logoback.obj"></a-asset-item>
<a-asset-item id="logofrontUObj" src="assets/models/logofront-u.obj"></a-asset-item>
<a-asset-item id="logoSparks" src="assets/models/logosparks.json"></a-asset-item>
<a-asset-item id="laserObj" src="assets/models/laser/laser.obj"></a-asset-item>
<a-asset-item id="logoSparks" src="assets/models/logosparks.json"></a-asset-item>
<a-asset-item id="sabercutParticles" src="assets/models/sabercut.json"></a-asset-item>
<audio id="hoverSound" src="assets/sounds/hover.ogg"></audio>
<audio id="saberDraw" src="assets/sounds/saberDraw.wav"></audio>
@@ -57,6 +58,7 @@
<img id="wrongRedImg" src="assets/img/wrongred.png">
<img id="missBlueImg" src="assets/img/missblue.png">
<img id="missRedImg" src="assets/img/missred.png">
<img id="sparkImg" src="assets/img/spark.png">
<a-mixin id="slice" slice9="color: #050505; transparent: true; opacity: 0.7; src: #sliceImg; left: 50; right: 52; top: 50; bottom: 52; padding: 0.18"></a-mixin>
<a-mixin id="font" text="font: assets/fonts/Teko-Bold.json; shader: msdf; letterSpacing: 1"></a-mixin>
@@ -96,6 +98,8 @@
<a-entity id="missLeft" mixin='badBeat' geometry="height: 0.25; width: 0.5" material="src: #missRedImg"></a-entity>
<a-entity id="missRight" mixin='badBeat' geometry="height: 0.25; width: 0.5" material="src: #missBlueImg"></a-entity>
<a-entity id="saberParticles" particleplayer="src: #sabercutParticles; pscale: 0.5; loop: false; on: explode; img: #sparkImg; count: 20%; animateScale: true; initialScale: 4 1 1; finalScale: 0.2 0.2 1"> </a-entity>
<!-- Player. -->
<a-mixin
id="raycaster"

View File

@@ -4,19 +4,16 @@ require('../vendor/BufferGeometryUtils');
require('aframe-animation-component');
require('aframe-audioanalyser-component');
require('aframe-cubemap-component');
require('aframe-event-set-component');
require('aframe-geometry-merger-component');
require('aframe-haptics-component');
require('aframe-layout-component');
require('aframe-orbit-controls');
require('aframe-particle-system-component');
require('aframe-proxy-event-component');
require('aframe-state-component');
require('aframe-slice9-component');
require('aframe-super-keyboard');
require('aframe-thumb-controls-component');
require('aframe-particleplayer-component');
requireAll(require.context('./components/', true, /\.js$/));
requireAll(require.context('./state/', true, /\.js$/));

View File

@@ -64,7 +64,7 @@
light="type: spot; penumbra: 1; intensity: 5; angle: 20"
animation="property: object3D.rotation.y; from: 0.87; to: -0.87; dur:300; easing: linear; startEvents: audioanalyser-beat"></a-entity>
<a-entity id="logosparks" bind__visible="menu.active" particleplayer="src: #logoSparks; scale: 1.4; pscale: 0.35; count: 10; dur: 600; on: logoflicker" position="-2.8 5.5 -7.2"></a-entity>
<a-entity id="logosparks" bind__visible="menu.active" particleplayer="src: #logoSparks; scale: 1.4; pscale: 0.35; count: 10; dur: 1000; on: logoflicker; animateScale: true; initialScale: 1.5 1.5 1.5; finalScale: 0.3 0.3 0.3" position="-2.8 5.5 -7.2"></a-entity>
<a-entity id="logo" bind__visible="menu.active" position="0 6 -7.5" rotation="90 0 0">
<a-entity obj-model="obj: #logobackObj" material="color: #001b29"></a-entity>
<a-entity obj-model="obj: #logofrontObj" material="color: #e81e23"></a-entity>