一群会跟着声音跳舞的3D格子!
近来在学习Flash的3D技术,现在我看过的就PV3D 与Away3D这两个开源框架,感觉还不错,好像Away3D的效果好点,但效率不如PV3D,PV3D算是亻为(不会用五笔打这个字-_-,我机子里又没拼音输入,将就下吧!)3D,不管这么多了,做个东西练练手,先看效果:
[url=http://www.jiangzone.com.cn/jiang/3dmusic/soundtest.swf]这里看看效果![/url]
这个程序很简单到没无简单了,就只是用了PV3D框架中的Cube的3D对象,一口气生成64个放在数组里待用,之后用Flash里的声音类加载并播放声音,之后在ENTER_FRAME事件里检测当前声音的频谱,之后根据频谱的高低来调整Cube格子的高低,在Flash里获取的声音频谱有512个Float数据,代表512级频谱,而前256级为LeftChangle,后256级为RightChangle,由于如果生成256个3D对象的话,对CPU来说是个考验,所以就折中间隔抽取64个频段来显示,由于懒于写代码了,就只写了LeftChangle的频谱。
以下是代码:
1
//
************导入需要用到的类
2 import flash.display.Sprite;
3 import org.papervision3d.scenes.Scene3D;
4 import org.papervision3d.cameras.FreeCamera3D;
5 import org.papervision3d.objects.Cube;
6 import org.papervision3d.materials.MaterialsList;
7 import org.papervision3d.materials.WireframeMaterial;
8 import org.papervision3d.materials.ColorMaterial;
9 import org.papervision3d.cameras.Camera3D;
10 import org.papervision3d.objects.Plane;
11
12 // ************定义需要用到的对象
13 var cont:Sprite;
14 var scene:Scene3D;
15 var camera:FreeCamera3D;
16 var ml:MaterialsList;
17 var material:ColorMaterial;
18 var cubeArr:Array;
19
20 // ***********设置放置3D东东的容器
21 cont = new Sprite();
22 cont.x = 150 ;
23 cont.y = 120 ;
24 this .addChild(cont);
25
26 // ******设置一个3D场景,并设置好Camera的位置与角度
27 scene = new Scene3D(cont);
28 camera = new FreeCamera3D();
29 camera.z = 1200 ;
30 camera.x = 100 ;
31 camera.y = 700 ;
32 camera.rotationX = - 30 ;
33 camera.rotationY = 180 ;
34 camera.focus = 100 ;
35 camera.zoom = 10 ;
36
37 // ***********定义一个存放所有格子的数组
38 cubeArr = new Array();
39
40 // 定义一个颜色材质与材质列表,用于应用于格子的6个面的贴图
41 material = new ColorMaterial( 0x096288 );
42 ml = new MaterialsList();
43 ml.addMaterial(material, " front " );
44 ml.addMaterial(material, " back " );
45 ml.addMaterial(material, " top " );
46 ml.addMaterial(material, " bottom " );
47 ml.addMaterial(material, " left " );
48 ml.addMaterial(material, " right " );
49
50 var i: int = 0 ;
51 var j: int = 0 ;
52
53 // 生成64个小格子并排列好位置
54 for (;i < 64 ;i ++ ){
55 ml.addMaterial( new ColorMaterial( 0xB9DFCF ), " top " );
56 var c:Cube = new Cube(ml, 20 , 20 , 20 );
57 c.x = (i % 8 ) * ( 20 + 5 );
58 c.z = (j % 8 ) * ( 20 + 5 );
59 (i % 8 == 0 ) ? j ++ :j = j;
60 cubeArr[i] = c;
61 scene.addChild(c);
62 }
63
64 // 创建一个面板,设置好位置放在小格子队列的下面(地板)
65 var plane:Plane = new Plane( new WireframeMaterial( 0xaaaaaa ), 300 , 300 , 7 , 7 );
66 plane.rotationX = - 90 ;
67 plane.y = - 50 ;
68 plane.x = 70 ;
69 plane.z = 60 ;
70 scene.addChild(plane);
71
72 // 以上是3D部分,以下是声音部分
73 // 建立一个字节数组用于存放获取到的频谱信息
74 var bArr:ByteArray = new ByteArray();
75 // 读取声音文件并播放
76 var req:URLRequest = new URLRequest( " a.mp3 " );
77 var sound:Sound = new Sound(req);
78 sound.play();
79
80 // 添加一个事件侦听器
81 this .addEventListener(Event.ENTER_FRAME,onEnter);
82
83 function onEnter(e:Event): void {
84 // 获取当前声音频谱,将数据存放在bArr里面。
85 // true为频谱模式,0为采样率代号
86 SoundMixer.computeSpectrum(bArr, true , 0 );
87 i = 0 ;
88 // 读取前256个数据,即Left声道的频谱
89 for (;i < 256 ;i ++ ){
90 var temp:Number = bArr.readFloat();
91 // 间隔4个数据中获取一个显示
92 if (i % 4 == 0 ){
93 // 从数组中获取相应的格子
94 var c:Cube = cubeArr[i / 4 ] as Cube;
95 // 设置格子在三维坐标中的高。
96 // 由于频谱数据是0-1,所以将其放大100倍
97 c.y = temp * 100 ;
98 }
99 }
100 // 镜头旋转移动
101 camera.moveLeft( 12 );
102 camera.rotationY += 0.6 ;
103 scene.renderCamera(camera);
104 }
2 import flash.display.Sprite;
3 import org.papervision3d.scenes.Scene3D;
4 import org.papervision3d.cameras.FreeCamera3D;
5 import org.papervision3d.objects.Cube;
6 import org.papervision3d.materials.MaterialsList;
7 import org.papervision3d.materials.WireframeMaterial;
8 import org.papervision3d.materials.ColorMaterial;
9 import org.papervision3d.cameras.Camera3D;
10 import org.papervision3d.objects.Plane;
11
12 // ************定义需要用到的对象
13 var cont:Sprite;
14 var scene:Scene3D;
15 var camera:FreeCamera3D;
16 var ml:MaterialsList;
17 var material:ColorMaterial;
18 var cubeArr:Array;
19
20 // ***********设置放置3D东东的容器
21 cont = new Sprite();
22 cont.x = 150 ;
23 cont.y = 120 ;
24 this .addChild(cont);
25
26 // ******设置一个3D场景,并设置好Camera的位置与角度
27 scene = new Scene3D(cont);
28 camera = new FreeCamera3D();
29 camera.z = 1200 ;
30 camera.x = 100 ;
31 camera.y = 700 ;
32 camera.rotationX = - 30 ;
33 camera.rotationY = 180 ;
34 camera.focus = 100 ;
35 camera.zoom = 10 ;
36
37 // ***********定义一个存放所有格子的数组
38 cubeArr = new Array();
39
40 // 定义一个颜色材质与材质列表,用于应用于格子的6个面的贴图
41 material = new ColorMaterial( 0x096288 );
42 ml = new MaterialsList();
43 ml.addMaterial(material, " front " );
44 ml.addMaterial(material, " back " );
45 ml.addMaterial(material, " top " );
46 ml.addMaterial(material, " bottom " );
47 ml.addMaterial(material, " left " );
48 ml.addMaterial(material, " right " );
49
50 var i: int = 0 ;
51 var j: int = 0 ;
52
53 // 生成64个小格子并排列好位置
54 for (;i < 64 ;i ++ ){
55 ml.addMaterial( new ColorMaterial( 0xB9DFCF ), " top " );
56 var c:Cube = new Cube(ml, 20 , 20 , 20 );
57 c.x = (i % 8 ) * ( 20 + 5 );
58 c.z = (j % 8 ) * ( 20 + 5 );
59 (i % 8 == 0 ) ? j ++ :j = j;
60 cubeArr[i] = c;
61 scene.addChild(c);
62 }
63
64 // 创建一个面板,设置好位置放在小格子队列的下面(地板)
65 var plane:Plane = new Plane( new WireframeMaterial( 0xaaaaaa ), 300 , 300 , 7 , 7 );
66 plane.rotationX = - 90 ;
67 plane.y = - 50 ;
68 plane.x = 70 ;
69 plane.z = 60 ;
70 scene.addChild(plane);
71
72 // 以上是3D部分,以下是声音部分
73 // 建立一个字节数组用于存放获取到的频谱信息
74 var bArr:ByteArray = new ByteArray();
75 // 读取声音文件并播放
76 var req:URLRequest = new URLRequest( " a.mp3 " );
77 var sound:Sound = new Sound(req);
78 sound.play();
79
80 // 添加一个事件侦听器
81 this .addEventListener(Event.ENTER_FRAME,onEnter);
82
83 function onEnter(e:Event): void {
84 // 获取当前声音频谱,将数据存放在bArr里面。
85 // true为频谱模式,0为采样率代号
86 SoundMixer.computeSpectrum(bArr, true , 0 );
87 i = 0 ;
88 // 读取前256个数据,即Left声道的频谱
89 for (;i < 256 ;i ++ ){
90 var temp:Number = bArr.readFloat();
91 // 间隔4个数据中获取一个显示
92 if (i % 4 == 0 ){
93 // 从数组中获取相应的格子
94 var c:Cube = cubeArr[i / 4 ] as Cube;
95 // 设置格子在三维坐标中的高。
96 // 由于频谱数据是0-1,所以将其放大100倍
97 c.y = temp * 100 ;
98 }
99 }
100 // 镜头旋转移动
101 camera.moveLeft( 12 );
102 camera.rotationY += 0.6 ;
103 scene.renderCamera(camera);
104 }