Add song beats. Need pace adjustment

This commit is contained in:
Diego Marcos
2018-10-01 17:37:11 -07:00
parent 865f0cb82f
commit 9855dbca7d
7 changed files with 1223 additions and 5 deletions

BIN
assets/img/envmap.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 87 KiB

15
assets/models/arrow.obj Normal file
View File

@@ -0,0 +1,15 @@
# Blender v2.79 (sub 0) OBJ File: 'cube.blend'
# www.blender.org
o arrow
v 0.102970 0.103067 0.148550
v -0.102970 0.103067 0.148550
v 0.000000 0.039580 0.148550
v 0.102970 0.087624 0.148550
v 0.000000 0.103067 0.148550
v -0.102970 0.087624 0.148550
vn 0.0000 0.0000 1.0000
s off
f 5//1 4//1 1//1
f 5//1 6//1 3//1
f 5//1 3//1 4//1
f 5//1 2//1 6//1

608
assets/models/beat.obj Normal file
View File

@@ -0,0 +1,608 @@
# Blender v2.79 (sub 0) OBJ File: 'cube.blend'
# www.blender.org
o block
v -0.147689 -0.111214 0.111214
v -0.144271 -0.126107 0.110872
v -0.144271 -0.110872 0.126107
v -0.141146 -0.124740 0.124740
v -0.147689 0.111214 0.111214
v -0.144271 0.110872 0.126107
v -0.144271 0.126107 0.110872
v -0.141146 0.124740 0.124740
v -0.147689 0.111214 -0.111214
v -0.144271 0.126107 -0.110872
v -0.144271 0.110872 -0.126107
v -0.141146 0.124740 -0.124740
v -0.147689 -0.111214 -0.111214
v -0.144271 -0.110872 -0.126107
v -0.144271 -0.126107 -0.110872
v -0.141146 -0.124740 -0.124740
v -0.111214 -0.111214 -0.147689
v -0.110872 -0.126107 -0.144271
v -0.126107 -0.110872 -0.144271
v -0.124740 -0.124740 -0.141146
v -0.111214 0.111214 -0.147689
v -0.126107 0.110872 -0.144271
v -0.110872 0.126107 -0.144271
v -0.124740 0.124740 -0.141146
v 0.111214 0.111214 -0.147689
v 0.110872 0.126107 -0.144271
v 0.126107 0.110872 -0.144271
v 0.124740 0.124740 -0.141146
v 0.111214 -0.111214 -0.147689
v 0.126107 -0.110872 -0.144271
v 0.110872 -0.126107 -0.144271
v 0.124740 -0.124740 -0.141146
v 0.147689 -0.111214 -0.111214
v 0.144271 -0.126107 -0.110872
v 0.144271 -0.110872 -0.126107
v 0.141146 -0.124740 -0.124740
v 0.147689 0.111214 -0.111214
v 0.144271 0.110872 -0.126107
v 0.144271 0.126107 -0.110872
v 0.141146 0.124740 -0.124740
v 0.147689 0.111214 0.111214
v 0.144271 0.126107 0.110872
v 0.144271 0.110872 0.126107
v 0.141146 0.124740 0.124740
v 0.147689 -0.111214 0.111214
v 0.144271 -0.110872 0.126107
v 0.144271 -0.126107 0.110872
v 0.141146 -0.124740 0.124740
v 0.111214 -0.111214 0.147689
v 0.110872 -0.126107 0.144271
v 0.126107 -0.110872 0.144271
v 0.124740 -0.124740 0.141146
v 0.111214 0.111214 0.147689
v 0.126107 0.110872 0.144271
v 0.110872 0.126107 0.144271
v 0.124740 0.124740 0.141146
v -0.111214 0.111214 0.147689
v -0.110872 0.126107 0.144271
v -0.126107 0.110872 0.144271
v -0.124740 0.124740 0.141146
v -0.111214 -0.111214 0.147689
v -0.126107 -0.110872 0.144271
v -0.110872 -0.126107 0.144271
v -0.124740 -0.124740 0.141146
v -0.111214 -0.147689 -0.111214
v -0.126107 -0.144271 -0.110872
v -0.110872 -0.144271 -0.126107
v -0.124740 -0.141146 -0.124740
v 0.111214 -0.147689 -0.111214
v 0.110872 -0.144271 -0.126107
v 0.126107 -0.144271 -0.110872
v 0.124740 -0.141146 -0.124740
v 0.111214 -0.147689 0.111214
v 0.126107 -0.144271 0.110872
v 0.110872 -0.144271 0.126107
v 0.124740 -0.141146 0.124740
v -0.111214 -0.147689 0.111214
v -0.110872 -0.144271 0.126107
v -0.126107 -0.144271 0.110872
v -0.124740 -0.141146 0.124740
v 0.111214 0.147689 -0.111214
v 0.126107 0.144271 -0.110872
v 0.110872 0.144271 -0.126107
v 0.124740 0.141146 -0.124740
v -0.111214 0.147689 -0.111214
v -0.110872 0.144271 -0.126107
v -0.126107 0.144271 -0.110872
v -0.124740 0.141146 -0.124740
v -0.111214 0.147689 0.111214
v -0.126107 0.144271 0.110872
v -0.110872 0.144271 0.126107
v -0.124740 0.141146 0.124740
v 0.111214 0.147689 0.111214
v 0.110872 0.144271 0.126107
v 0.126107 0.144271 0.110872
v 0.124740 0.141146 0.124740
v -0.134961 -0.134961 -0.123828
v -0.137451 -0.137451 -0.110645
v -0.137451 -0.137451 0.110645
v -0.134961 -0.134961 0.123828
v -0.134961 -0.123828 0.134961
v -0.137451 -0.110645 0.137451
v -0.137451 0.110645 0.137451
v -0.134961 0.123828 0.134961
v -0.134961 0.134961 0.123828
v -0.137451 0.137451 0.110645
v -0.137451 0.137451 -0.110645
v -0.134961 0.134961 -0.123828
v -0.134961 0.123828 -0.134961
v -0.137451 0.110645 -0.137451
v -0.137451 -0.110645 -0.137451
v -0.134961 -0.123828 -0.134961
v 0.123828 -0.134961 -0.134961
v 0.110645 -0.137451 -0.137451
v -0.110645 -0.137451 -0.137451
v -0.123828 -0.134961 -0.134961
v -0.123828 0.134961 -0.134961
v -0.110645 0.137451 -0.137451
v 0.110645 0.137451 -0.137451
v 0.123828 0.134961 -0.134961
v 0.134961 0.123828 -0.134961
v 0.137451 0.110645 -0.137451
v 0.137451 -0.110645 -0.137451
v 0.134961 -0.123828 -0.134961
v 0.134961 -0.134961 0.123828
v 0.137451 -0.137451 0.110645
v 0.137451 -0.137451 -0.110645
v 0.134961 -0.134961 -0.123828
v 0.134961 0.134961 -0.123828
v 0.137451 0.137451 -0.110645
v 0.137451 0.137451 0.110645
v 0.134961 0.134961 0.123828
v 0.134961 0.123828 0.134961
v 0.137451 0.110645 0.137451
v 0.137451 -0.110645 0.137451
v 0.134961 -0.123828 0.134961
v -0.123828 -0.134961 0.134961
v -0.110645 -0.137451 0.137451
v 0.110645 -0.137451 0.137451
v 0.123828 -0.134961 0.134961
v 0.123828 0.134961 0.134961
v 0.110645 0.137451 0.137451
v -0.110645 0.137451 0.137451
v -0.123828 0.134961 0.134961
v -0.131597 -0.131597 0.131597
v -0.131597 0.131597 0.131597
v -0.131597 -0.131597 -0.131597
v -0.131597 0.131597 -0.131597
v 0.131597 -0.131597 0.131597
v 0.131597 0.131597 0.131597
v 0.131597 -0.131597 -0.131597
v 0.131597 0.131597 -0.131597
vn -0.1263 -0.7014 -0.7014
vn 0.1206 -0.3755 -0.9189
vn 0.1263 -0.7014 -0.7014
vn -0.9868 -0.1145 0.1145
vn -0.8501 -0.3723 0.3723
vn -0.9189 -0.1206 0.3755
vn -0.6551 -0.3764 0.6551
vn -0.7014 -0.1263 0.7014
vn -0.9189 -0.3755 0.1206
vn -0.6551 -0.6551 0.3764
vn -0.5773 -0.5773 0.5773
vn -0.9868 0.1145 0.1145
vn -0.9189 0.3755 -0.1206
vn -0.9868 0.1145 -0.1145
vn -0.1145 -0.9868 -0.1145
vn 0.1145 -0.9868 0.1145
vn -0.1145 -0.9868 0.1145
vn -0.3755 0.9189 0.1206
vn -0.7014 0.7014 -0.1263
vn -0.7014 0.7014 0.1263
vn -0.8501 0.3723 0.3723
vn -0.9189 0.3755 0.1206
vn -0.6551 0.6551 0.3764
vn -0.9189 0.1206 0.3755
vn -0.6551 0.3764 0.6551
vn -0.5773 0.5773 0.5773
vn -0.1145 -0.1145 -0.9868
vn 0.1145 0.1145 -0.9868
vn 0.1145 -0.1145 -0.9868
vn -0.3755 -0.9189 0.1206
vn -0.7014 -0.7014 0.1263
vn -0.9189 -0.3755 -0.1206
vn -0.7014 -0.7014 -0.1263
vn -0.8501 0.3723 -0.3723
vn -0.9189 0.1206 -0.3755
vn -0.6551 0.3764 -0.6551
vn -0.7014 0.1263 -0.7014
vn -0.6551 0.6551 -0.3764
vn -0.5773 0.5773 -0.5773
vn 0.9868 0.1145 -0.1145
vn 0.9189 -0.1206 -0.3755
vn 0.9189 0.1206 -0.3755
vn 0.7014 -0.1263 -0.7014
vn -0.9868 -0.1145 -0.1145
vn -0.8501 -0.3723 -0.3723
vn -0.6551 -0.6551 -0.3764
vn -0.9189 -0.1206 -0.3755
vn -0.6551 -0.3764 -0.6551
vn -0.5773 -0.5773 -0.5773
vn -0.1206 0.9189 0.3755
vn 0.1145 0.9868 0.1145
vn -0.1145 0.9868 0.1145
vn -0.3723 -0.3723 -0.8501
vn -0.3755 -0.1206 -0.9189
vn -0.7014 -0.1263 -0.7014
vn -0.1206 -0.3755 -0.9189
vn -0.3764 -0.6551 -0.6551
vn -0.1145 0.1145 -0.9868
vn -0.3723 0.3723 -0.8501
vn -0.1206 0.3755 -0.9189
vn -0.3764 0.6551 -0.6551
vn -0.1263 0.7014 -0.7014
vn -0.3755 0.1206 -0.9189
vn 0.3755 -0.9189 -0.1206
vn 0.1145 -0.9868 -0.1145
vn 0.3755 0.9189 0.1206
vn 0.7014 0.7014 -0.1263
vn 0.3755 0.9189 -0.1206
vn 0.3723 0.3723 -0.8501
vn 0.3755 0.1206 -0.9189
vn 0.6551 0.3764 -0.6551
vn 0.7014 0.1263 -0.7014
vn 0.1206 0.3755 -0.9189
vn 0.3764 0.6551 -0.6551
vn 0.5773 0.5773 -0.5773
vn -0.3755 0.9189 -0.1206
vn 0.3723 -0.3723 -0.8501
vn 0.3764 -0.6551 -0.6551
vn 0.3755 -0.1206 -0.9189
vn 0.6551 -0.3764 -0.6551
vn 0.5773 -0.5773 -0.5773
vn 0.1206 0.3755 0.9189
vn -0.1263 0.7014 0.7014
vn -0.1206 0.3755 0.9189
vn -0.1145 -0.1145 0.9868
vn 0.1145 0.1145 0.9868
vn -0.1145 0.1145 0.9868
vn 0.9868 -0.1145 -0.1145
vn 0.8501 -0.3723 -0.3723
vn 0.9189 -0.3755 -0.1206
vn 0.6551 -0.6551 -0.3764
vn 0.1145 0.9868 -0.1145
vn -0.1206 -0.3755 0.9189
vn 0.1263 -0.7014 0.7014
vn 0.1206 -0.3755 0.9189
vn 0.8501 0.3723 -0.3723
vn 0.9189 0.3755 -0.1206
vn 0.6551 0.6551 -0.3764
vn -0.7014 0.1263 0.7014
vn 0.9868 0.1145 0.1145
vn 0.8501 0.3723 0.3723
vn 0.9189 0.1206 0.3755
vn 0.6551 0.3764 0.6551
vn 0.7014 0.1263 0.7014
vn 0.9189 0.3755 0.1206
vn 0.6551 0.6551 0.3764
vn 0.5773 0.5773 0.5773
vn -0.1206 -0.9189 -0.3755
vn 0.1206 -0.9189 -0.3755
vn 0.9868 -0.1145 0.1145
vn 0.8501 -0.3723 0.3723
vn 0.9189 -0.3755 0.1206
vn 0.6551 -0.6551 0.3764
vn 0.7014 -0.7014 0.1263
vn 0.9189 -0.1206 0.3755
vn 0.6551 -0.3764 0.6551
vn 0.5773 -0.5773 0.5773
vn 0.1145 -0.1145 0.9868
vn 0.3723 -0.3723 0.8501
vn 0.3755 -0.1206 0.9189
vn 0.7014 -0.1263 0.7014
vn 0.3764 -0.6551 0.6551
vn 0.3723 0.3723 0.8501
vn 0.3764 0.6551 0.6551
vn 0.1263 0.7014 0.7014
vn 0.3755 0.1206 0.9189
vn 0.1206 0.9189 -0.3755
vn -0.1145 0.9868 -0.1145
vn 0.7014 -0.7014 -0.1263
vn -0.3723 0.3723 0.8501
vn -0.3755 0.1206 0.9189
vn -0.3764 0.6551 0.6551
vn 0.3755 -0.9189 0.1206
vn -0.3723 -0.3723 0.8501
vn -0.3764 -0.6551 0.6551
vn -0.1263 -0.7014 0.7014
vn -0.3755 -0.1206 0.9189
vn -0.3723 -0.8501 -0.3723
vn -0.3755 -0.9189 -0.1206
vn 0.3723 -0.8501 -0.3723
vn 0.1206 -0.9189 0.3755
vn -0.1206 -0.9189 0.3755
vn 0.3723 -0.8501 0.3723
vn -0.3723 -0.8501 0.3723
vn -0.1206 0.9189 -0.3755
vn 0.1263 0.7014 -0.7014
vn 0.3723 0.8501 -0.3723
vn -0.3723 0.8501 -0.3723
vn -0.3723 0.8501 0.3723
vn 0.1206 0.9189 0.3755
vn 0.3723 0.8501 0.3723
vn 0.7014 0.7014 0.1263
s 1
f 115//1 31//2 114//3
f 1//4 4//5 3//6
f 3//6 101//7 102//8
f 2//9 100//10 4//5
f 4//5 145//11 101//7
f 5//12 10//13 9//14
f 65//15 73//16 77//17
f 90//18 107//19 106//20
f 5//12 8//21 7//22
f 7//22 105//23 106//20
f 6//24 104//25 8//21
f 8//21 146//26 105//23
f 17//27 25//28 29//29
f 79//30 65//15 77//17
f 99//31 15//32 98//33
f 9//14 12//34 11//35
f 11//35 109//36 110//37
f 10//13 108//38 12//34
f 12//34 148//39 109//36
f 37//40 35//41 38//42
f 123//43 38//42 35//41
f 13//44 16//45 15//32
f 15//32 97//46 98//33
f 14//47 112//48 16//45
f 16//45 147//49 97//46
f 91//50 93//51 89//52
f 14//47 9//14 11//35
f 17//27 20//53 19//54
f 19//54 112//48 111//55
f 18//56 116//57 20//53
f 20//53 147//49 112//48
f 18//56 29//29 31//2
f 21//58 24//59 23//60
f 23//60 117//61 118//62
f 22//63 109//36 24//59
f 24//59 148//39 117//61
f 71//64 73//16 69//65
f 95//66 130//67 82//68
f 25//28 28//69 27//70
f 27//70 121//71 122//72
f 26//73 120//74 28//69
f 28//69 152//75 121//71
f 89//52 87//76 90//18
f 111//55 11//35 110//37
f 29//29 32//77 31//2
f 31//2 113//78 114//3
f 30//79 124//80 32//77
f 32//77 151//81 113//78
f 55//82 143//83 58//84
f 61//85 53//86 57//87
f 33//88 36//89 35//41
f 35//41 124//80 123//43
f 34//90 128//91 36//89
f 36//89 151//81 124//80
f 81//92 95//66 82//68
f 63//93 139//94 50//95
f 37//40 40//96 39//97
f 39//97 129//98 130//67
f 38//42 121//71 40//96
f 40//96 152//75 129//98
f 57//87 55//82 58//84
f 3//6 103//99 6//24
f 41//100 44//101 43//102
f 43//102 133//103 134//104
f 42//105 132//106 44//101
f 44//101 150//107 133//103
f 50//95 61//85 63//93
f 67//108 114//3 70//109
f 45//110 48//111 47//112
f 47//112 125//113 126//114
f 46//115 136//116 48//111
f 48//111 149//117 125//113
f 45//110 43//102 46//115
f 122//72 30//79 27//70
f 49//118 52//119 51//120
f 51//120 136//116 135//121
f 50//95 140//122 52//119
f 52//119 149//117 136//116
f 19//54 110//37 22//63
f 2//9 13//44 15//32
f 53//86 56//123 55//82
f 55//82 141//124 142//125
f 54//126 133//103 56//123
f 56//123 150//107 141//124
f 83//127 85//128 81//92
f 47//112 127//129 34//90
f 57//87 60//130 59//131
f 59//131 104//25 103//99
f 58//84 144//132 60//130
f 60//130 146//26 104//25
f 74//133 127//129 126//114
f 34//90 45//110 47//112
f 61//85 64//134 63//93
f 63//93 137//135 138//136
f 62//137 101//7 64//134
f 64//134 145//11 137//135
f 42//105 37//40 39//97
f 51//120 134//104 54//126
f 9//14 1//4 5//12
f 65//15 68//138 67//108
f 67//108 116//57 115//1
f 66//139 97//46 68//138
f 68//138 147//49 116//57
f 130//67 42//105 39//97
f 59//131 61//85 57//87
f 69//65 72//140 71//64
f 71//64 128//91 127//129
f 70//109 113//78 72//140
f 72//140 151//81 128//91
f 69//65 67//108 70//109
f 75//141 138//136 78//142
f 73//16 76//143 75//141
f 75//141 140//122 139//94
f 74//133 125//113 76//143
f 76//143 149//117 140//122
f 66//139 99//31 98//33
f 19//54 21//58 17//27
f 51//120 53//86 49//118
f 77//17 80//144 79//30
f 79//30 100//10 99//31
f 78//142 137//135 80//144
f 80//144 145//11 100//10
f 21//58 26//73 25//28
f 86//145 119//146 118//62
f 37//40 45//110 33//88
f 81//92 84//147 83//127
f 83//127 120//74 119//146
f 82//68 129//98 84//147
f 84//147 152//75 120//74
f 30//79 25//28 27//70
f 43//102 135//121 46//115
f 81//92 89//52 93//51
f 85//128 88//148 87//76
f 87//76 108//38 107//19
f 86//145 117//61 88//148
f 88//148 148//39 108//38
f 75//141 77//17 73//16
f 7//22 107//19 10//13
f 89//52 92//149 91//50
f 91//50 144//132 143//83
f 90//18 105//23 92//149
f 92//149 146//26 144//132
f 143//83 94//150 91//50
f 119//146 23//60 118//62
f 93//51 96//151 95//66
f 95//66 132//106 131//152
f 94//150 141//124 96//151
f 96//151 150//107 132//106
f 1//4 6//24 5//12
f 62//137 103//99 102//8
f 115//1 18//56 31//2
f 1//4 2//9 4//5
f 3//6 4//5 101//7
f 2//9 99//31 100//10
f 4//5 100//10 145//11
f 5//12 7//22 10//13
f 65//15 69//65 73//16
f 90//18 87//76 107//19
f 5//12 6//24 8//21
f 7//22 8//21 105//23
f 6//24 103//99 104//25
f 8//21 104//25 146//26
f 17//27 21//58 25//28
f 79//30 66//139 65//15
f 99//31 2//9 15//32
f 9//14 10//13 12//34
f 11//35 12//34 109//36
f 10//13 107//19 108//38
f 12//34 108//38 148//39
f 37//40 33//88 35//41
f 123//43 122//72 38//42
f 13//44 14//47 16//45
f 15//32 16//45 97//46
f 14//47 111//55 112//48
f 16//45 112//48 147//49
f 91//50 94//150 93//51
f 14//47 13//44 9//14
f 17//27 18//56 20//53
f 19//54 20//53 112//48
f 18//56 115//1 116//57
f 20//53 116//57 147//49
f 18//56 17//27 29//29
f 21//58 22//63 24//59
f 23//60 24//59 117//61
f 22//63 110//37 109//36
f 24//59 109//36 148//39
f 71//64 74//133 73//16
f 95//66 131//152 130//67
f 25//28 26//73 28//69
f 27//70 28//69 121//71
f 26//73 119//146 120//74
f 28//69 120//74 152//75
f 89//52 85//128 87//76
f 111//55 14//47 11//35
f 29//29 30//79 32//77
f 31//2 32//77 113//78
f 30//79 123//43 124//80
f 32//77 124//80 151//81
f 55//82 142//125 143//83
f 61//85 49//118 53//86
f 33//88 34//90 36//89
f 35//41 36//89 124//80
f 34//90 127//129 128//91
f 36//89 128//91 151//81
f 81//92 93//51 95//66
f 63//93 138//136 139//94
f 37//40 38//42 40//96
f 39//97 40//96 129//98
f 38//42 122//72 121//71
f 40//96 121//71 152//75
f 57//87 53//86 55//82
f 3//6 102//8 103//99
f 41//100 42//105 44//101
f 43//102 44//101 133//103
f 42//105 131//152 132//106
f 44//101 132//106 150//107
f 50//95 49//118 61//85
f 67//108 115//1 114//3
f 45//110 46//115 48//111
f 47//112 48//111 125//113
f 46//115 135//121 136//116
f 48//111 136//116 149//117
f 45//110 41//100 43//102
f 122//72 123//43 30//79
f 49//118 50//95 52//119
f 51//120 52//119 136//116
f 50//95 139//94 140//122
f 52//119 140//122 149//117
f 19//54 111//55 110//37
f 2//9 1//4 13//44
f 53//86 54//126 56//123
f 55//82 56//123 141//124
f 54//126 134//104 133//103
f 56//123 133//103 150//107
f 83//127 86//145 85//128
f 47//112 126//114 127//129
f 57//87 58//84 60//130
f 59//131 60//130 104//25
f 58//84 143//83 144//132
f 60//130 144//132 146//26
f 74//133 71//64 127//129
f 34//90 33//88 45//110
f 61//85 62//137 64//134
f 63//93 64//134 137//135
f 62//137 102//8 101//7
f 64//134 101//7 145//11
f 42//105 41//100 37//40
f 51//120 135//121 134//104
f 9//14 13//44 1//4
f 65//15 66//139 68//138
f 67//108 68//138 116//57
f 66//139 98//33 97//46
f 68//138 97//46 147//49
f 130//67 131//152 42//105
f 59//131 62//137 61//85
f 69//65 70//109 72//140
f 71//64 72//140 128//91
f 70//109 114//3 113//78
f 72//140 113//78 151//81
f 69//65 65//15 67//108
f 75//141 139//94 138//136
f 73//16 74//133 76//143
f 75//141 76//143 140//122
f 74//133 126//114 125//113
f 76//143 125//113 149//117
f 66//139 79//30 99//31
f 19//54 22//63 21//58
f 51//120 54//126 53//86
f 77//17 78//142 80//144
f 79//30 80//144 100//10
f 78//142 138//136 137//135
f 80//144 137//135 145//11
f 21//58 23//60 26//73
f 86//145 83//127 119//146
f 37//40 41//100 45//110
f 81//92 82//68 84//147
f 83//127 84//147 120//74
f 82//68 130//67 129//98
f 84//147 129//98 152//75
f 30//79 29//29 25//28
f 43//102 134//104 135//121
f 81//92 85//128 89//52
f 85//128 86//145 88//148
f 87//76 88//148 108//38
f 86//145 118//62 117//61
f 88//148 117//61 148//39
f 75//141 78//142 77//17
f 7//22 106//20 107//19
f 89//52 90//18 92//149
f 91//50 92//149 144//132
f 90//18 106//20 105//23
f 92//149 105//23 146//26
f 143//83 142//125 94//150
f 119//146 26//73 23//60
f 93//51 94//150 96//151
f 95//66 96//151 132//106
f 94//150 142//125 141//124
f 96//151 141//124 150//107
f 1//4 3//6 6//24
f 62//137 59//131 103//99

51
assets/models/dot.obj Normal file
View File

@@ -0,0 +1,51 @@
# Blender v2.79 (sub 0) OBJ File: 'cube.blend'
# www.blender.org
o dot
v 0.000000 0.044271 0.148510
v -0.011944 0.042630 0.148510
v -0.023003 0.037826 0.148510
v -0.032355 0.030218 0.148510
v -0.039308 0.020368 0.148510
v -0.043345 0.009007 0.148510
v -0.044168 -0.003021 0.148510
v -0.041715 -0.014826 0.148510
v -0.036168 -0.025530 0.148510
v -0.027939 -0.034342 0.148510
v -0.017638 -0.040606 0.148510
v -0.006028 -0.043859 0.148510
v 0.006028 -0.043859 0.148510
v 0.017638 -0.040606 0.148510
v 0.027939 -0.034342 0.148510
v 0.036168 -0.025530 0.148510
v 0.041715 -0.014826 0.148510
v 0.044168 -0.003021 0.148510
v 0.043345 0.009007 0.148510
v 0.039308 0.020368 0.148510
v 0.032355 0.030217 0.148510
v 0.023003 0.037826 0.148510
v 0.011944 0.042630 0.148510
v -0.000000 -0.000000 0.148510
s off
f 1 24 23
f 2 3 24
f 3 4 24
f 4 5 24
f 5 6 24
f 6 7 24
f 7 8 24
f 8 9 24
f 9 10 24
f 10 11 24
f 11 12 24
f 12 13 24
f 13 14 24
f 14 15 24
f 15 16 24
f 16 17 24
f 17 18 24
f 18 19 24
f 19 20 24
f 20 21 24
f 21 22 24
f 23 24 22
f 1 2 24

View File

@@ -6,18 +6,24 @@ var utils = require('../utils');
AFRAME.registerComponent('beat-loader', {
schema: {
challengeId: {type: 'string'},
difficulty: {type: 'string'}
difficulty: {type: 'string'},
beatSpeed: {default: 4.0},
beatAnticipationTime: {default: 2.0}
},
orientations: [180, 0, 270, 90, 225, 135, 315, 45, 0],
horizontalPositions: [-0.60, -0.25, 0.25, 0.60],
verticalPositions: [1.00, 1.35, 1.70],
update: function () {
if (!this.data.challengeId || !this.data.difficulty) { return; }
this.loadBeats(this.data.challengeId, this.data.difficulty);
this.loadBeats();
},
/**
* XHR.
*/
loadBeats: function (id, difficulty) {
loadBeats: function () {
var el = this.el;
var xhr;
@@ -34,12 +40,122 @@ AFRAME.registerComponent('beat-loader', {
},
/**
* TODO: Load the beat data into the game.
* Load the beat data into the game.
*/
handleBeats: function (beatData) {
this.el.sceneEl.emit('beatloaderfinish', beatData, false);
var lessThan = function (a, b) {
return a._time - b._time;
};
this.beatData = beatData;
this.beatData._obstacles.sort(lessThan);
this.beatData._notes.sort(lessThan);
console.log('Finished loading challenge data.');
},
tick: function (time, delta) {
var audioEl = this.el.components.song.audio;
var notes;
var obstacles;
var lastTime = this.lastTime || 0;
var msPerBeat;
var noteTime;
if (!this.data.challengeId || !this.beatData || !audioEl) { return; }
notes = this.beatData._notes;
obstacles = this.beatData._obstacles;
this.bpm = this.beatData._beatsPerMinute;
msPerBeat = 1000 * 60 / this.beatData._beatsPerMinute;
for (i=0; i < notes.length; ++i) {
noteTime = notes[i]._time * msPerBeat;
if (noteTime > lastTime && noteTime <= lastTime + delta) {
notes[i].time = noteTime;
this.generateBeat(notes[i]);
}
}
for (i=0; i < obstacles.length; ++i) {
noteTime = obstacles[i]._time * msPerBeat;
if (noteTime > lastTime && noteTime <= lastTime + delta) {
// this.generateWall(obstacles[i]);
}
}
this.lastTime = lastTime + delta;
// Sync audio with first element.
if (this.audioSync || !this.first) { return; }
if (this.first.el.object3D.position.z < this.el.sceneEl.camera.el.object3D.position.z) { return; }
this.audioSync = true;
this.el.components.song.audio.currentTime = this.first.time;
},
generateBeat: function (noteInfo) {
var color;
var orientation;
var el;
var type = noteInfo._cutDirection === 8 ? 'dot' : 'arrow';
color = noteInfo._type === 0 ? 'red' : 'blue';
if (noteInfo._type === 3) {
type = 'mine';
color = undefined;
}
el = this.requestBeat(type, color);
if (!el) { return; }
el.setAttribute('beat', {
color: color,
type: type,
speed: this.data.beatSpeed});
el.object3D.position.set(
this.horizontalPositions[noteInfo._lineIndex],
this.verticalPositions[noteInfo._lineLayer],
-this.data.beatAnticipationTime * this.data.beatSpeed
);
el.setAttribute('rotation', {x: 0, y: 0, z: this.orientations[noteInfo._cutDirection]});
el.play();
if (this.first) { return; }
this.first = {
el: el,
time: noteInfo._time
};
},
// generateWall: function (wallInfo) {
// var el = this.el.sceneEl.components.pool__wall.requestEntity();
// var speed = this.data.beatSpeed;
// var durationMs;
// if (!el) { return; }
// durationSeconds = 60 * (wallInfo._duration / this.bpm);
// el.setAttribute('wall', {
// speed: speed
// });
// el.object3D.position.set(
// this.horizontalPositions[wallInfo._lineIndex],
// 1.30,
// -(this.data.beatAnticipationTime * speed)
// );
// el.object3D.scale.set(wallInfo._width * 0.30, 2.5, durationSeconds * speed);
// el.play();
// if (this.first) { return; }
// this.first = {
// el: el,
// time: wallInfo._time
// };
// },
requestBeat: function (type, color) {
var beatPoolName = 'pool__beat-' + type;
var pool;
if (color) {beatPoolName += '-' + color; }
pool = this.el.sceneEl.components[beatPoolName];
if (!pool) {
console.warn('Poo ' + beatPoolName + ' unavailable');
return;
}
return pool.requestEntity();
}
});
function updateQueryParam(uri, key, value) {
@@ -51,3 +167,5 @@ function updateQueryParam(uri, key, value) {
return uri + separator + key + '=' + value;
}
}

411
src/components/beat.js Normal file
View File

@@ -0,0 +1,411 @@
AFRAME.registerComponent('beat', {
schema: {
speed: {default: 1.0},
color: {default: 'red', oneOf: ['red', 'blue']},
size: {default: 0.30},
debug: {default: false},
type: {default: 'arrow', oneOf: ['arrow', 'dot', 'mine']}
},
materialColor: {
blue: '#08083E',
red: '#290404'
},
cutColor: {
blue: '#b3dcff',
red: '#ffb3ca'
},
models: {
arrow: "#beat-obj",
dot: "#beat-obj",
mine: "#mine-obj"
},
signModels: {
arrow: "#arrow-obj",
dot: "#dot-obj"
},
init: function () {
var el = this.el;
var color;
var size = this.data.size;
this.beatCollidersConfiguration = [
{position: {x: size / 2, y: 0, z: 0}, size: {width: size / 5.0, height: size, depth: size}},
{position: {x: -size / 2, y: 0, z: 0}, size: {width: size / 5.0, height: size, depth: size}},
{position: {x: 0, y: size / 2, z: 0}, size: {width: size, height: size / 5.0, depth: size}},
{position: {x: 0, y: -size / 2, z: 0}, size: {width: size, height: size / 5.0, depth: size}},
{position: {x: 0, y: 0, z: size / 2}, size: {width: size, height: size, depth: size / 5.0}},
{position: {x: 0, y: 0, z: -size / 2}, size: {width: size, height: size, depth: size / 5.0}}
];
this.boundingBox = new THREE.Box3();
this.saberEls = this.el.sceneEl.querySelectorAll('[saber-controls]');
this.backToPool = false;
this.returnToPoolTimer = 800;
this.initBlock();
this.initColliders();
this.initFragments();
},
update: function () {
this.updateBlock();
this.updateFragments();
},
initBlock: function () {
var el = this.el;
var blockEl = this.blockEl = document.createElement('a-entity');
var signEl = this.signEl = document.createElement('a-entity');
// Small offset to prevent z-fighting when the blocks are far away
signEl.object3D.position.z += 0.02;
blockEl.appendChild(signEl);
el.appendChild(blockEl);
},
updateBlock: function () {
var blockEl = this.blockEl;
var signEl = this.signEl;
blockEl.setAttribute('obj-model', {obj: this.models[this.data.type]});
blockEl.setAttribute('material', {
metalness: 0.6,
roughness: 0.12,
sphericalEnvMap: '#envmapTexture',
color: this.materialColor[this.data.color]
});
// Model is 0.29 size. We make it 1.0 so we can easily scale based on 1m size.
blockEl.object3D.scale.multiplyScalar(3.45).multiplyScalar(this.data.size);
if (this.data.type === 'mine') {
blockEl.addEventListener('model-loaded', (evt) => {
var model = evt.detail.model.children[0];
model.material = this.el.sceneEl.components.stagecolors.mineMaterial;
});
}
signEl.setAttribute('obj-model', {obj: this.signModels[this.data.type]});
signEl.setAttribute('material', {
shader: 'flat',
color: '#88f'
});
},
initColliders: function () {
var beatColliderEl;
var beatCollidersConfiguration = this.beatCollidersConfiguration;
var beatCollidersEls = this.beatCollidersEls = [];
var i;
var size;
for (i = 0; i < 6; i++) {
beatColliderEl = document.createElement('a-entity');
size = beatCollidersConfiguration[i].size;
beatColliderEl.setAttribute('geometry', {
primitive: 'box',
height: size.height,
width: size.width,
depth: size.depth
});
beatColliderEl.setAttribute('position', beatCollidersConfiguration[i].position);
beatColliderEl.setAttribute('visible', false);
beatCollidersEls.push(beatColliderEl);
if (i == 2) { this.correctBeatColliderEl = beatColliderEl; }
this.el.appendChild(beatColliderEl);
if (this.data.debug) {
beatColliderEl.setAttribute('visible', true);
if (i == 2) {
beatColliderEl.setAttribute('material', 'color: yellow');
} else {
beatColliderEl.setAttribute('material', 'color: purple');
}
}
}
},
initFragments: function () {
var partEl;
var cutEl;
var color = this.data.color === 'red' ? '#5b0502' : '#083771';
var size = this.data.size;
var geometry = {primitive: 'box', height: size, width: size, depth: size};
this.cutDirection = new THREE.Vector3();
this.rotationAxis = new THREE.Vector3();
partEl = this.partLeftEl = document.createElement('a-entity');
cutEl = this.cutLeftEl = document.createElement('a-entity');
partEl.appendChild(cutEl);
this.el.appendChild(partEl);
partEl = this.partRightEl = document.createElement('a-entity');
cutEl = this.cutRightEl = document.createElement('a-entity');
partEl.appendChild(cutEl);
this.el.appendChild(partEl);
this.initCuttingClippingPlanes();
},
updateFragments: function () {
var cutLeftEl = this.cutLeftEl;
var cutRightEl = this.cutRightEl;
var partLeftEl = this.partLeftEl;
var partRightEl = this.partRightEl;
partLeftEl.setAttribute('obj-model', 'obj: #beat-obj');
partLeftEl.setAttribute('material', {
metalness: 0.8,
roughness: 0.12,
sphericalEnvMap: '#envmapTexture',
color: this.materialColor[this.data.color],
side: 'double'
});
partLeftEl.setAttribute('visible', false);
cutLeftEl.setAttribute('obj-model', 'obj: #beat-obj');
cutLeftEl.setAttribute('material', {
shader: 'flat',
color: this.data.cutColor,
side: 'double'
});
partRightEl.setAttribute('obj-model', 'obj: #beat-obj');
partRightEl.setAttribute('material', {
metalness: 0.8,
roughness: 0.12,
sphericalEnvMap: '#envmapTexture',
color: this.materialColor[this.data.color],
side: 'double'
});
partRightEl.setAttribute('visible', false);
cutRightEl.setAttribute('obj-model', 'obj: #beat-obj');
cutRightEl.setAttribute('material', {
shader: 'flat',
color: this.data.cutColor,
side: 'double'
});
},
destroyBeat: (function () {
var point1 = new THREE.Vector3();
var point2 = new THREE.Vector3();
var point3 = new THREE.Vector3();
var planeMaterial = new THREE.MeshBasicMaterial({color: 'grey', side: THREE.DoubleSide});
var parallelPlaneMaterial = new THREE.MeshBasicMaterial({color: '#00008b', side: THREE.DoubleSide});
return function (saberEl) {
var i;
var trailPoints = saberEl.components.trail.saberTrajectory;
var direction = this.cutDirection;
point1.copy(trailPoints[0].top);
point2.copy(trailPoints[0].center);
point3.copy(trailPoints[trailPoints.length - 1].top);
direction.copy(point1).sub(point3);
var parallelPlane;
var parallelPlane2;
var planeGeometry;
var planeMesh;
var coplanarPoint;
var focalPoint;
var cutThickness = this.cutThickness = 0.02;
var rightCutPlane = this.rightCutPlane;
var rightBorderOuterPlane = this.rightBorderOuterPlane;
var leftCutPlane = this.leftCutPlane;
var leftBorderOuterPlane = this.leftBorderOuterPlane;
var rightBorderInnerPlane = this.rightBorderInnerPlane;
var leftBorderInnerPlane = this.leftBorderInnerPlane;
this.partLeftEl.object3D.position.set(0, 0, 0);
this.partLeftEl.object3D.rotation.set(0, 0, 0)
this.partLeftEl.object3D.updateMatrixWorld();
this.partRightEl.object3D.position.set(0, 0, 0);
this.partRightEl.object3D.rotation.set(0, 0, 0);
this.partRightEl.object3D.updateMatrixWorld();
this.rightCutPlanePoints = [
this.partRightEl.object3D.worldToLocal(point1.clone()),
this.partRightEl.object3D.worldToLocal(point2.clone()),
this.partRightEl.object3D.worldToLocal(point3.clone()),
];
this.leftCutPlanePoints = [
this.partLeftEl.object3D.worldToLocal(point3.clone()),
this.partLeftEl.object3D.worldToLocal(point2.clone()),
this.partLeftEl.object3D.worldToLocal(point1.clone()),
];
this.generateCutClippingPlanes();
if (this.data.debug) {
coplanarPoint = new THREE.Vector3();
planeGeometry = new THREE.PlaneGeometry(4.0, 4.0, 1.0, 1.0);
rightCutPlane.coplanarPoint(coplanarPoint);
planeGeometry.lookAt(rightCutPlane.normal);
planeGeometry.translate(coplanarPoint.x, coplanarPoint.y, coplanarPoint.z);
planeMesh = new THREE.Mesh(planeGeometry, planeMaterial);
this.el.sceneEl.setObject3D('rightCutPlane', planeMesh);
planeGeometry = new THREE.PlaneGeometry(4.0, 4.0, 1.0, 1.0);
rightBorderOuterPlane.coplanarPoint(coplanarPoint);
planeGeometry.lookAt(rightBorderOuterPlane.normal);
planeGeometry.translate(coplanarPoint.x, coplanarPoint.y, coplanarPoint.z);
parallelPlaneMesh = new THREE.Mesh(planeGeometry, parallelPlaneMaterial);
this.el.sceneEl.setObject3D('planeParallel', parallelPlaneMesh);
}
this.blockEl.object3D.visible = false;
this.partRightEl.getObject3D('mesh').material.clippingPlanes = [rightCutPlane];
this.cutRightEl.getObject3D('mesh').material.clippingPlanes = [rightBorderOuterPlane, rightBorderInnerPlane];
this.partLeftEl.getObject3D('mesh').material.clippingPlanes = [leftCutPlane];
this.cutLeftEl.getObject3D('mesh').material.clippingPlanes = [leftBorderInnerPlane, leftBorderOuterPlane];
for (i = 0; i < 6; i++) {
this.beatCollidersEls[i].setAttribute('visible', false);
}
this.partLeftEl.object3D.visible = true;
this.partRightEl.object3D.visible = true;
this.el.sceneEl.renderer.localClippingEnabled = true;
this.destroyed = true;
this.el.emit('beatdestroyed');
this.rotationAxis = this.rightCutPlanePoints[0].clone().sub(this.rightCutPlanePoints[1]);
this.returnToPoolTimer = 800;
//this.el.sceneEl.components['json-particles__hit'].explode(this.el.object3D.position, rightCutPlane.normal, direction, this.data.color);
}
})(),
pause: function () {
this.el.object3D.visible = false;
this.partLeftEl.object3D.visible = false;
this.partRightEl.object3D.visible = false;
},
play: function () {
this.destroyed = false;
this.el.object3D.visible = true;
this.blockEl.object3D.visible = true;
},
initCuttingClippingPlanes: function () {
this.leftCutPlanePointsWorld = [
new THREE.Vector3(),
new THREE.Vector3(),
new THREE.Vector3()
];
this.rightCutPlanePointsWorld = [
new THREE.Vector3(),
new THREE.Vector3(),
new THREE.Vector3()
];
this.rightCutPlane = new THREE.Plane();
this.rightBorderOuterPlane = new THREE.Plane();
this.rightBorderInnerPlane = new THREE.Plane();
this.leftCutPlane = new THREE.Plane();
this.leftBorderOuterPlane = new THREE.Plane();
this.leftBorderInnerPlane = new THREE.Plane();
},
generateCutClippingPlanes: function () {
var leftCutPlanePointsWorld = this.leftCutPlanePointsWorld;
var rightCutPlanePointsWorld = this.rightCutPlanePointsWorld;
var rightCutPlane = this.rightCutPlane;
var rightBorderOuterPlane = this.rightBorderOuterPlane;
var rightBorderInnerPlane = this.rightBorderInnerPlane;
var leftCutPlane = this.leftCutPlane;
var leftBorderOuterPlane = this.leftBorderOuterPlane;
var leftBorderInnerPlane = this.leftBorderInnerPlane;
var partLeftEl = this.partLeftEl;
var partRightEl = this.partRightEl;
partRightEl.object3D.updateMatrixWorld();
partRightEl.object3D.localToWorld(rightCutPlanePointsWorld[0].copy(this.rightCutPlanePoints[0]));
partRightEl.object3D.localToWorld(rightCutPlanePointsWorld[1].copy(this.rightCutPlanePoints[1]));
partRightEl.object3D.localToWorld(rightCutPlanePointsWorld[2].copy(this.rightCutPlanePoints[2]));
partLeftEl.object3D.updateMatrixWorld();
partLeftEl.object3D.localToWorld(leftCutPlanePointsWorld[0].copy(this.leftCutPlanePoints[0]));
partLeftEl.object3D.localToWorld(leftCutPlanePointsWorld[1].copy(this.leftCutPlanePoints[1]));
partLeftEl.object3D.localToWorld(leftCutPlanePointsWorld[2].copy(this.leftCutPlanePoints[2]));
rightCutPlane.setFromCoplanarPoints(rightCutPlanePointsWorld[0], rightCutPlanePointsWorld[1], rightCutPlanePointsWorld[2]);
rightBorderOuterPlane.set(rightCutPlane.normal, rightCutPlane.constant + this.cutThickness);
leftCutPlane.setFromCoplanarPoints(leftCutPlanePointsWorld[0], leftCutPlanePointsWorld[1], leftCutPlanePointsWorld[2]);
leftBorderOuterPlane.set(leftCutPlane.normal, leftCutPlane.constant + this.cutThickness);
rightBorderInnerPlane.setFromCoplanarPoints(rightCutPlanePointsWorld[2], rightCutPlanePointsWorld[1], rightCutPlanePointsWorld[0]);
leftBorderInnerPlane.setFromCoplanarPoints(leftCutPlanePointsWorld[2], leftCutPlanePointsWorld[1], leftCutPlanePointsWorld[0]);
},
returnToPool: function () {
var poolName;
var type;
if (!this.backToPool) { return; }
type = this.data.type;
poolName = 'pool__beat-' + type;
if (type !== 'mine') { poolName += '-' + this.data.color; }
this.el.sceneEl.components[poolName].returnEntity(this.el);
this.el.pause();
},
tock: (function () {
var rightCutNormal = new THREE.Vector3();
var leftCutNormal = new THREE.Vector3();
var leftRotation = 0;
var rightRotation = 0;
var rotationStep = 2 * Math.PI / 150;
return function (time, timeDelta) {
var i;
var saberEls = this.saberEls;
var boundingBox;
var saberBoundingBox;
var plane;
if (!this.destroyed) {
if (!this.correctBeatColliderEl.getObject3D('mesh')) { return; }
boundingBox = this.boundingBox.setFromObject(this.correctBeatColliderEl.getObject3D('mesh'));
for (i = 0; i < saberEls.length; i++) {
saberBoundingBox = saberEls[i].components['saber-controls'].boundingBox;
if (boundingBox && saberBoundingBox && saberBoundingBox.intersectsBox(boundingBox)) {
this.destroyBeat(saberEls[i]);
break;
}
}
this.el.object3D.position.z += this.data.speed * (timeDelta / 1000);
this.backToPool = this.el.object3D.position.z >= 2;
} else {
rightCutNormal.copy(this.rightCutPlane.normal).multiplyScalar((this.data.speed / 2) * (timeDelta / 500));
this.partRightEl.object3D.position.add(rightCutNormal);
this.partRightEl.object3D.setRotationFromAxisAngle(this.rotationAxis, rightRotation);
rightRotation = rightRotation >= 2 * Math.PI ? 0 : rightRotation + rotationStep;
leftCutNormal.copy(this.leftCutPlane.normal).multiplyScalar((this.data.speed / 2) * (timeDelta / 500));
this.partLeftEl.object3D.position.add(leftCutNormal);
this.partLeftEl.object3D.setRotationFromAxisAngle(this.rotationAxis, leftRotation);
leftRotation = leftRotation >= 2 * Math.PI ? 0 : leftRotation + rotationStep;
this.generateCutClippingPlanes();
this.returnToPoolTimer -= timeDelta;
this.backToPool = this.returnToPoolTimer <= 0;
}
this.returnToPool();
};
})()
});

View File

@@ -18,12 +18,19 @@
effect-bloom="strength: 1"
intro-song
overlay="objects: #menu, #keyboard, #rightHand, #leftHand, [mixin~='cursorMesh']"
pool__beat-arrow-blue="mixin: beat arrow-blue-beat; size: 5; container: #beatContainer"
pool__beat-arrow-red="mixin: beat arrow-red-beat; size: 10; container: #beatContainer"
pool__beat-dot-blue="mixin: beat dot-blue-beat; size: 10; container: #beatContainer"
pool__beat-dot-red="mixin: beat dot-red-beat; size: 10; container: #beatContainer"
proxy-event="event: menuchallengeselect; to: #searchResultsContainer, #menuDifficultiesGroup"
search
stage-colors="blue"
fog="color: #a00; density: 0.035; type: exponential">
fog="color: #a00; density: 0.035; type: exponential" debug>
<a-assets timeout="10000">
<a-asset-item id="arrow-obj" src="assets/models/arrow.obj"></a-asset-item>
<a-asset-item id="backglow-obj" src="assets/models/backglow.obj"></a-asset-item>
<a-asset-item id="beat-obj" src="assets/models/beat.obj"></a-asset-item>
<a-asset-item id="dot-obj" src="assets/models/dot.obj"></a-asset-item>
<a-asset-item id="logofront-obj" src="assets/models/logofront.obj"></a-asset-item>
<a-asset-item id="logoback-obj" src="assets/models/logoback.obj"></a-asset-item>
<a-asset-item id="logofront-u-obj" src="assets/models/logofront-u.obj"></a-asset-item>
@@ -36,6 +43,7 @@
<img id="backglowTexture" src="assets/img/stage/backglow.png">
<img id="cursorMeshImg" src="assets/models/laser/laser.png">
<img id="downIconImg" src="assets/img/downIcon.png">
<img id="envmapTexture" src="assets/img/envMap.png"></img>
<img id="floorImg" src="assets/img/stage/floor.png">
<img id="gridImg" src="assets/img/grid.png">
<img id="playImg" src="assets/img/play.png">
@@ -47,8 +55,15 @@
<a-mixin id="stageLaser" geometry="height: 300; depth: 0.16; width: 0.16" materials="neon"></a-mixin>
<a-mixin id="font" text="font: assets/fonts/Teko-Bold.json; shader: msdf; letterSpacing: 1"></a-mixin>
<a-mixin id="textFont" text="font: assets/fonts/Teko-Bold.json; shader: msdf; letterSpacing: 1"></a-mixin>
<a-mixin id="beat" beat></a-mixin>
<a-mixin id="arrow-blue-beat" beat="color: blue; type: arrow"></a-mixin>
<a-mixin id="arrow-red-beat" beat="color: red; type: arrow"></a-mixin>
<a-mixin id="dot-blue-beat" beat="color: blue; type: dot"></a-mixin>
</a-assets>
<a-entity id="beatContainer"></a-entity>
<a-entity id="cursorLaser" obj-model="obj: #laserObj" visible="false"></a-entity>
<a-entity id="container">