使用molehill构建一个旋转的方形

使用MoleHill 来构建一个选择的方形,不借助任何现成的第三方引擎.
直接上代码
代码中的注释已经非常的详尽了.

提前做一个绘制方向顶点定义的解释

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
        private function initData() : void
        {
            //定义每个多边形用到的顶点
            //一个方形是由2个三角形构成的
            meshIndexData = Vector.<uint>
                ([
                    0,1,2,      0,2,3,
                ]);
           
            // 源数据需要用到4个顶点
            // xyz坐标, texture 坐标系 UV, 归一化 xyz
            meshVertexData = Vector.<Number>
                ([
                    //X, Y, Z,  U,  V,  nX,  nY,  nZ
                    -1, -1, 1,  0,  0,  0,  0,  1,
                     1, -1, 1,  1,  0,  0,  0,  1,
                     1, 1,  1,  1,  1,  0,  0,  1,
                    -1, 1,  1,  0,  1,  0,  0,  1
                ]);
        }

meshIndexData 的作用是顶点索引,即告诉渲染程序,当前顶点的数据要从 顶点数据集中的第几个索引中去取.
meshIndexData 的长度6,在渲染网格的时候将其长度/2 来告诉程序每个网格要到3个顶点.
meshVertexData 就是顶点数据 长度为4, 每8个为1组,因此渲染网格的时候将其长度/8
meshVertexData 中的xyz 构成的是一个坐标系中的方形的4个坐标点 UV用来定义该点唯一坐标系的中哪一个区域, 其中0表示负半轴,1表示正半轴
nx,ny,nz表示归一化后的xyz坐标

后面是完整代码和demo

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
package
{
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;
   
    import flash.display.Bitmap;
    import flash.display.BitmapData;
    import flash.display.Sprite;
    import flash.display.Stage3D;
    import flash.display.StageAlign;
    import flash.display.StageScaleMode;
    import flash.display3D.Context3D;
    import flash.display3D.Context3DProgramType;
    import flash.display3D.Context3DTextureFormat;
    import flash.display3D.Context3DVertexBufferFormat;
    import flash.display3D.IndexBuffer3D;
    import flash.display3D.Program3D;
    import flash.display3D.VertexBuffer3D;
    import flash.display3D.textures.Texture;
    import flash.events.Event;
    import flash.geom.Matrix;
    import flash.geom.Matrix3D;
    import flash.geom.PerspectiveProjection;
    import flash.geom.Vector3D;
   
    [SWF(width="640",height="480",frameRate="60",backgroundColor="#FFFFFF")]
    public class MoleHill extends Sprite
    {
        private const swfWidth : int = 640;
        private const swfHeight : int = 480;
        private const textureSize : int = 512;
       
        //屏幕上的3D图形窗口
        private var context3D : Context3D;
        //编译shader来渲染网格
        private var shaderProgram : Program3D;
        //上传顶点给网格使用
        private var vertexBuffer : VertexBuffer3D;
        //上传网格的顶点索引
        private var indexBuffer : IndexBuffer3D;
        //定义3D网格模型
        private var meshVertexData : Vector.<Number>;
        // 定义哪些索引的数据给顶点使用
        private var meshIndexData : Vector.<uint>;
       
        //影响网格坐标和摄像机角度的矩阵
        private var projectMatrix : PerspectiveMatrix3D = new PerspectiveMatrix3D();
        private var modelMatrix : Matrix3D = new Matrix3D();
        private var viewMatrix : Matrix3D = new Matrix3D();
        private var modelViewProjection : Matrix3D = new Matrix3D();
       
        //简单的帧率计算
        private var t : Number = 0;
       
        [Embed (source ="texture.jpg")]
        private var myTextureBitmap : Class;
       
        private var myTextureData : Bitmap = new myTextureBitmap();
        //Molehill 材质需要用到 myTextureData
        private var myTexture : Texture;
       
        public function MoleHill()
        {
            stage ? init() : addEventListener(Event.ADDED_TO_STAGE, init);
        }
       
        private function init(e:Event = null) : void
        {
            if(hasEventListener(Event.ADDED_TO_STAGE))
                removeEventListener(Event.ADDED_TO_STAGE,init);
           
            stage.scaleMode = StageScaleMode.NO_SCALE;
            stage.align = StageAlign.TOP_LEFT;
           
            stage.stage3Ds[0].addEventListener(Event.CONTEXT3D_CREATE, onContext3DCreate);
            stage.stage3Ds[0].requestContext3D();
        }
       
        private function enterFrame(e:Event) : void
        {
            //清除场景之前渲染的内容
            context3D.clear(0,0,0);
            context3D.setProgram(shaderProgram);
           
            //创建一系列变换矩阵
            modelMatrix.identity();
            modelMatrix.appendRotation(t*0.7, Vector3D.Y_AXIS);
            modelMatrix.appendRotation(t*0.6, Vector3D.X_AXIS);
            modelMatrix.appendRotation(t*1.0, Vector3D.Y_AXIS);
            modelMatrix.appendTranslation(0.0,0.0,0.0);
            modelMatrix.appendRotation(90.0,Vector3D.X_AXIS);
           
            //下一帧多选择2倍
            t += 2.0;
           
            //清除矩阵 然后附加角度
            modelViewProjection.identity();
            modelViewProjection.append(modelMatrix);
            modelViewProjection.append(viewMatrix);
            modelViewProjection.append(projectMatrix);
           
            //传递矩阵数据到渲染程序
            context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX,0,modelViewProjection,true);
           
            //将当前矩阵数据联合到渲染程序
            //位置
            context3D.setVertexBufferAt(0,vertexBuffer,0, Context3DVertexBufferFormat.FLOAT_3);
            //材质坐标
            context3D.setVertexBufferAt(1,vertexBuffer,3,Context3DVertexBufferFormat.FLOAT_3);
           
            //选择要使用的材质
            context3D.setTextureAt(0,myTexture);
           
            //绘制三角形
            context3D.drawTriangles(indexBuffer,0,meshIndexData.length/3);
           
            //对准/翻转 刷新
            context3D.present();
           
        }
       
        private function onContext3DCreate(e:Event) : void
        {
            //保证这货不会先运行
            removeEventListener(Event.ENTER_FRAME, enterFrame);
           
            //获得当前环境
            var t : Stage3D = e.target as Stage3D;
            context3D = t.context3D;
           
            if(!context3D) return;
           
            //禁用错误信息可以提高性能
            //当时这些错误有时是很有帮助的
            context3D.enableErrorChecking = true;
           
            initData();
           
            //3D背投尺寸
            context3D.configureBackBuffer(swfWidth,swfHeight,0,true);
           
            //一个简单的顶点渲染3D变换
            var vertexShaderAssembler : AGALMiniAssembler = new AGALMiniAssembler();
            vertexShaderAssembler.assemble
                (
                    //模式
                    Context3DProgramType.VERTEX,
                    //存入一个4x4矩阵, vc0 * va0
                    "m44 op, va0, vc0n" +
                    //告诉材质根据xyz坐标渲染 将 va0 复制到 v0
                    "mov v0, va0n" +
                    //告诉材质根据UV渲染
                    "mov v1, va1n"
                );
           
            //一个简单的材质渲染,将把顶点当作颜色
            var fragmentShaderAssemlber : AGALMiniAssembler = new AGALMiniAssembler();
            fragmentShaderAssemlber.assemble
                (
                    //模式
                    Context3DProgramType.FRAGMENT,
                    //从材质 fs0 上抓去材质颜色,使用 UV 坐标系来存储到 v1
                    "tex ft0, v1, fs0 <2d,repeat,miplinear>n" +
                    //输出存储后的颜色
                    "mov oc, ft0n"
                );
           
            //合并渲染到程序中,然后我们可以把它上传到GPU
            shaderProgram = context3D.createProgram();
            shaderProgram.upload(vertexShaderAssembler.agalcode, fragmentShaderAssemlber.agalcode);
           
           
            //上传网格索引
            indexBuffer = context3D.createIndexBuffer(meshIndexData.length);
            indexBuffer.uploadFromVector(meshIndexData,0,meshIndexData.length);
           
            //上传网格顶点数据
            //片段数据为 x,y,z,u,v,nx,ny,nz
            //每个顶点使用8位元素
            vertexBuffer = context3D.createVertexBuffer(meshVertexData.length/8,8);
            vertexBuffer.uploadFromVector(meshVertexData,0,meshVertexData.length/8);
           
            //生成编码
            myTexture = context3D.createTexture(textureSize,textureSize,Context3DTextureFormat.BGRA,false);
            var ws : int = myTextureData.bitmapData.width;
            var hs : int = myTextureData.bitmapData.height;
            var level : int = 0;
            var temp : BitmapData;
            var tansform : Matrix = new Matrix();
            temp = new BitmapData(ws,hs,true,0);
            while(ws >= 1 && hs >= 1){
                temp.draw(myTextureData.bitmapData,tansform,null,null,null,true);
                myTexture.uploadFromBitmapData(temp,level);
                tansform.scale(0.5,0.5);
                level ++;
                ws >>= 1;
                hs >>= 1;
                if( hs && ws) {
                    temp.dispose();
                    temp = new BitmapData(ws,hs,true,0);
                }
            }
            temp.dispose();
           
            //为我们的3D场景创建一个投影矩阵
            projectMatrix.identity();
            //视野大小为45度,640/480 视界比例, 最近面 0.1, 最远面100
            projectMatrix.perspectiveFieldOfViewRH(45.0,swfWidth / swfHeight, 0.1, 100.0);
           
            //创建一个矩阵来定义摄像机位置
            viewMatrix.identity();
            viewMatrix.appendTranslation(0,0,-4);
           
            //开始动画
            addEventListener(Event.ENTER_FRAME, enterFrame);
        }
       
        private function initData() : void
        {
            //定义每个多边形用到的顶点
            //一个方形是由2个三角形构成的
            meshIndexData = Vector.<uint>
                ([
                    0,1,2,      0,2,3,
                ]);
           
            // 源数据需要用到4个顶点
            // xyz坐标, texture 坐标系 UV, 归一化 xyz
            meshVertexData = Vector.<Number>
                ([
                    //X, Y, Z,  U,  V,  nX,  nY,  nZ
                    -1, -1, 1,  0,  0,  0,  0,  1,
                     1, -1, 1,  1,  0,  0,  0,  1,
                     1, 1,  1,  1,  1,  0,  0,  1,
                    -1, 1,  1,  0,  1,  0,  0,  1
                ]);
        }
       
    }
}

发表评论

电子邮件地址不会被公开。 必填项已用*标注

This site uses Akismet to reduce spam. Learn how your comment data is processed.