OBJ是文件,先来解释下OBJ文件。随便找一个OBJ文件,用文本查看:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
# Max2Obj Version 4.0 Mar 10th, 2001
#
# object (null) to come ...
#
v -0.257 0.191 0.423
v -0.115 0.29 -0.068
v -0.237 0 -0.074
v -0.237 0.071 0.646
...
# 82 vertices
vt 0.623 0.227 0
vt 0.615 0.53 0
vt 0.895 0.555 0
vt 0.825 0.246 0
vt 0.647 0.847 0
...
# 39 texture vertices
f 1/1 2/2 3/3
f 3/3 4/4 1/1
f 2/2 5/5 6/6
f 6/6 3/3 2/2
...
# 142 faces

v:是模型的顶点信息 vt:是贴图的UV坐标 f:是定义面的顶点索引和顶点对应的UV坐标索引 清楚了OBJ文件里各种数据所代表的信息,接下来就是如何把数据传递给显卡渲染。 那么我们需要一个解析OBJ文件的类(代码比较简单,注释就省了)

 
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
package com.parser
{
    import flash.utils.ByteArray;
 
  
    public class OBJParser
    {
        private var _lines:Array;
        private const LINE_FEED:String = String.fromCharCode(10);
        private const SPACE:String = String.fromCharCode(32);
        private var _scale:Number;
        public function OBJParser(objfile:ByteArray,scale:Number = 1)
        {
            _scale = scale;
            if(objfile)
            {
                var lineStr:String = parserToStr(objfile);
                _lines = lineStr.split(LINE_FEED);
                var loop:uint = _lines.length;
                for(var i:uint = 0; i < loop; i++)
                {
                    parseLine(_lines[i]);
                }
            }  
        }
 
        private const VERTEX:String = 'v';
        private const UV:String = 'vt';
        private const INDEX_DATA:String = 'f';
        private function parseLine(lineStr:String):void
        {
            var data:Array = lineStr.split(SPACE);
            if(!data.length)return;
            var key:String = data[0];
            var parseData:Array = data.slice(1);
            switch(key)
            {
                case VERTEX:
                    parseVertex(parseData);
                    break;
                case UV:
                    parseUV(parseData);
                    break;
                case INDEX_DATA:
                    parseIndexData(parseData);
                    break;
            }
        }
 
        private var _vertices:Vector.<Number> = new Vector.<Number>();
        private function parseVertex(data:Array):void
        {
            if(data[0] == '' || data[0] == " ")
            {
                data = data.slice(1);
            }
            var loop:uint = data.length;
            for(var i:uint = 0; i < loop; i++)
            {
                var value:Number = Number(data[i]);
                _vertices.push(value*_scale);
            }
        }
 
        private var _uvs:Vector.<Number> = new Vector.<Number>();
        private function parseUV(data:Array):void
        {
            if(data[0] == '' || data[0] == " ")
            {
                data = data.slice(1);
            }
            var loop:uint = 2;
            for(var i:uint = 0; i < loop; i++)
            {
                var value:Number = Number(data[i]);
                _uvs.push(value*_scale);
            }
        }
 
        private const SLASH:String = "/";
        private var _indexData:Vector.<uint> = new Vector.<uint>();
        private var _vertexsData:Vector.<Number> = new Vector.<Number>();
        private var _uvData:Vector.<Number> = new Vector.<Number>();
        private var _faceIndex:uint;
        private function parseIndexData(data:Array):void
        {
            var index:uint = 0;
            while((data[index] == '') || (data[index] == ' '))index++;
            var loop:uint = index+3;
 
            var vertexIndex:int;
            var uvIndex:int;
            var normalIndex:int;
            for(var i:uint = index; i < loop; i++)
            {
                var triplet:String = data[i];
                var subdata:Array = triplet.split(SLASH);
                vertexIndex = int(subdata[0]) - 1;
                uvIndex     = int(subdata[1]) - 1;
 
                if(vertexIndex < 0) vertexIndex = 0;
                if(uvIndex < 0) uvIndex = 0;
 
                index = 3*vertexIndex;
                _vertexsData.push(_vertices[index + 0],
                _vertices[index + 1], _vertices[index + 2]);
 
                index = 2*uvIndex;
                _uvData.push(1-_uvs[index+0],1-_uvs[index+1]);
            }
            _indexData.push(_faceIndex+0,_faceIndex+1,_faceIndex+2);
            _faceIndex += 3;
        }
 
        private function parserToStr(objFileByteArray:ByteArray):String
        {
            return objFileByteArray.readUTFBytes(objFileByteArray.bytesAvailable);
        }
 
        /**
         * 顶点数据
         * @return
         *
         */    
        public function get vertexsData():Vector.<Number>
        {
            return _vertexsData;
        }
 
        /**
         * UV数据
         * @return
         *
         */    
        public function get uvData():Vector.<Number>
        {
            return _uvData;
        }
 
        /**
         * 索引数据
         * @return
         *
         */    
        public function get indexData():Vector.<uint>
        {
            return _indexData;
        }
 
    }
}
 
1
 

有了顶点信息,uv信息和面的索引信息接下来就可以把这货渲染出来了。

 
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
package
{
    import com.adobe.utils.AGALMiniAssembler;
    import com.adobe.utils.PerspectiveMatrix3D;
    import com.parser.OBJParser;
 
    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.Vector3D;
    import flash.utils.ByteArray;
 
    [SWF(width='800',height='600',backgroundColor='0x333333',frameRate="60")]
   
    public class GameTest extends Sprite
    {
        [Embed (source = "art/spaceship.obj",
        mimeType = "application/octet-stream")]
        private var objData:Class;
 
        [Embed (source = "art/spaceship_texture.jpg")]
        private var TextureBitmap:Class;
        private var textureData:Bitmap = new TextureBitmap();
 
        private var _stage3D:Stage3D;
        private var _context3D:Context3D;
        private const sw:uint = 700;
        private const sh:uint = 500;
 
        private var _objParser:OBJParser;
        //顶点缓冲 存储顶点信息
        private var _vertexBuffer:VertexBuffer3D;
        //顶点缓冲 存储UV信息
        private var _uvBuffer:VertexBuffer3D;
        //顶点索引
        private var _indexBuffer:IndexBuffer3D;
        private var _texture:Texture;
        private var _textureSize:uint = 512;
        private var _projectionmatrix:PerspectiveMatrix3D;
        private var _viewmatrix:Matrix3D;
        private var _modelmatrix:Matrix3D = new Matrix3D();
        private var _modelViewProjection:Matrix3D = new Matrix3D();
 
        private var _vertexShaderAssembler:AGALMiniAssembler;
        private var _fragmentAssembler:AGALMiniAssembler;
        private var _program:Program3D;
 
        public function GameTest()
        {
            if(this.stage)
            {
                init();
            }else
            {
                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);
            this.stage.scaleMode = StageScaleMode.NO_SCALE;
            this.stage.align = StageAlign.TOP_LEFT;
            initStage3D();
        }
 
        private function initStage3D():void
        {
            _stage3D = this.stage.stage3Ds[0];
            if(_stage3D)
            {
                _stage3D.addEventListener(Event.CONTEXT3D_CREATE,onContext3DCreate);
                _stage3D.requestContext3D();
            }
        }
 
        private function onContext3DCreate(e:Event):void
        {
            _context3D = _stage3D.context3D;
            if(_context3D == null)
            {
                throw new Error("无法创建Context3D");
                return;
            }
 
            _stage3D.x = (this.stage.stageWidth - sw)/2;
            _stage3D.y = (this.stage.stageHeight - sh)/2;
 
            _context3D.configureBackBuffer(sw,sh,1);
            _context3D.clear(205,205,205);
            _context3D.enableErrorChecking = true;
            initData();
            initShader();
            this.stage.addEventListener(Event.ENTER_FRAME,onEnterFrame);
        }
 
        private function initData():void
        {
            var objdata:ByteArray = new objData() as ByteArray;
            _objParser = new OBJParser(objdata);
 
            var vertexCont:uint = _objParser.vertexsData.length/3;
            _vertexBuffer = _context3D.createVertexBuffer(vertexCont,3);
            _vertexBuffer.uploadFromVector(_objParser.vertexsData,0,vertexCont);
 
            var uvCont:uint = _objParser.uvData.length/2;
            _uvBuffer = _context3D.createVertexBuffer(uvCont,2);
            _uvBuffer.uploadFromVector(_objParser.uvData,0,uvCont);
 
            _context3D.setVertexBufferAt(0,_vertexBuffer,0,Context3DVertexBufferFormat.FLOAT_3);
            _context3D.setVertexBufferAt(1,_uvBuffer,0,Context3DVertexBufferFormat.FLOAT_2);
 
            var indexData:Vector.<uint> = _objParser.indexData;
            _indexBuffer = _context3D.createIndexBuffer(indexData.length);
            _indexBuffer.uploadFromVector(indexData,0,indexData.length);
 
            _texture = _context3D.createTexture(_textureSize,_textureSize,Context3DTextureFormat.BGRA,false);
            uploadTextureWithMipmaps(_texture,textureData.bitmapData);
 
            _projectionmatrix = new PerspectiveMatrix3D();
            _projectionmatrix.identity();
            // 45 degrees FOV, 640/480 aspect ratio, 0.1=near, 100=far
            _projectionmatrix.perspectiveFieldOfViewRH(
                45.0, sw / sh, 0.01, 100.0);
 
            _viewmatrix = new Matrix3D();
            // camera Matrix3D
            _viewmatrix.identity();
            // 移动镜头到(0,0,0)
            _viewmatrix.appendTranslation(0,0,0);
        }
 
        private function initShader():void
        {
            _vertexShaderAssembler = new AGALMiniAssembler();
            _vertexShaderAssembler.assemble(Context3DProgramType.VERTEX,
                "m44 op, va0, vc0\n" +
                "mov v0, va0\n" +
                "mov v1, va1\n");
 
            _fragmentAssembler= new AGALMiniAssembler();
            _fragmentAssembler..assemble
                (
                    Context3DProgramType.FRAGMENT, 
                    "tex ft0, v1, fs0 <2d,linear,repeat,miplinear>\n"+
                    "mov oc, ft0\n"
                );
 
            _program = _context3D.createProgram();
            _program.upload(_vertexShaderAssembler.agalcode,_fragmentAssembler.agalcode);
            _context3D.setTextureAt(0,_texture);           
            _context3D.setProgram(_program);
        }
 
        private var _t:Number = 0;
        private function onEnterFrame(e:Event):void
        {
            _context3D.clear(0,0,0,.7);
            _t += 2.0;
            _modelmatrix.identity();
            //旋转模型
            _modelmatrix.appendRotation(_t*1.0, Vector3D.Y_AXIS);
            _modelmatrix.appendRotation(_t*-0.2, Vector3D.X_AXIS);
            _modelmatrix.appendRotation(_t*0.3, Vector3D.Y_AXIS);
            _modelmatrix.appendTranslation(-0.4, 0, -5);
 
            _modelViewProjection.identity();
            _modelViewProjection.append(_modelmatrix);
            _modelViewProjection.append(_viewmatrix);
            _modelViewProjection.append(_projectionmatrix);
 
            _context3D.setProgramConstantsFromMatrix(Context3DProgramType.VERTEX, 0, _modelViewProjection, true );
            //绘制模型
            _context3D.drawTriangles(_indexBuffer, 0, _objParser.indexData.length/3);
            //呈现至屏幕
            _context3D.present();
        }
 
        /**
         * Mipmap
         * @param dest
         * @param src
         *
         */    
        private function uploadTextureWithMipmaps(dest:Texture, src:BitmapData):void
        {
            var ws:int = src.width;
            var hs:int = src.height;
            var level:int = 0;
            var tmp:BitmapData;
            var transform:Matrix = new Matrix();
 
            tmp = new BitmapData(src.width, src.height, true, 0);
 
            while ( ws >= 1 && hs >= 1 )
            {
                tmp.draw(src, transform, null, null, null, true);
                dest.uploadFromBitmapData(tmp, level);
                transform.scale(0.5, 0.5);
                level++;
                ws >>= 1;
                hs >>= 1;
                if (hs && ws)
                {
                    tmp.dispose();
                    tmp = new BitmapData(ws, hs, true, 0x00000000);
                }
            }
            tmp.dispose();
        }
 
    }
}

Stage3D_Game_Programming:渲染3D模型的更多相关文章

  1. WPF 3D模型 3D场景

    1.首先得说明的是这并不是真正的3D,模型被导出为一系列的单个图片,例如一个3D户型图,以某个视角旋转360°,渲染出一系列连续的单个图片文件. 2.在Image.MouseMove事件中添加相应代码 ...

  2. unity3d设置3D模型显示在2D背景之前(多个相机分层显示)(转)

    解决步骤: 1.添加一个摄像机,命名为BackgroundCamera,然后在Layer添加一个background层.并且将plane拖放到改相机节点下. 然后将BackgroundCamera和P ...

  3. Flash Stage3D 在2D UI 界面上显示3D模型问题完美解决

    一直以来很多Stage3D开发者都在为3D模型在2DUI上显示的问题头疼.Stage3D一直是在 Stage2D下面.为了做到3D模型在2DUI上显示通常大家有几种实现方式,下面来说说这几种实现方式吧 ...

  4. three.js实现3D模型展示

    由于项目需要展示3d模型,所以对three做了点研究,分享出来 希望能帮到大家 先看看效果: three.js整体来说 不是很难 只要你静下心来研究研究 很快就会上手的 首先我们在页面上需要创建一个能 ...

  5. 3D模型展示以及体积、表面积计算

    本文原创 如转载请注明出处!!! 本博客地址http://www.cnblogs.com/we-jack 本文原创,如果有同样需求的小伙伴请第一时间联系我 或者在留言区留言 上次为大家提供了3D模型的 ...

  6. Unity在UI界面上显示3D模型/物体,控制模型旋转

    Unity3D物体在UI界面的显示 本文提供全流程,中文翻译. Chinar 坚持将简单的生活方式,带给世人!(拥有更好的阅读体验 -- 高分辨率用户请根据需求调整网页缩放比例) Chinar -- ...

  7. 使用Chrome控制台进行3D模型编辑的尝试

    前言:3D模型编辑的核心是对顶点位置和纹理颜色的编辑,这个研究的目的在于寻找一种通过编程方式直接对模型进行编辑的方法,这种编辑方法和时下流行的通过鼠标点选.拖拽进行编辑的方法之间的关系,和前端编程中“ ...

  8. XNA 中3D模型的显示

    XNA 中3D模型的显示: ModelMeshPart[] meshParts; Model start_model; Matrix[] dq_model_transforms; Matrix vie ...

  9. 分享一个WebGL开发的网站-用JavaScript + WebGL开发3D模型

    这张图每位程序员应该都深有感触. 人民心目中的程序员是这样的:坐在电脑面前噼里啪啦敲着键盘,运键如飞. 现实中程序员是这样的:编码5分钟,调试两小时. 今天我要给大家分享一个用WebGL开发的网站,感 ...

随机推荐

  1. Ubuntu 12.04下解决Rhythmbox Music Player乱码问题

    1.打开终端输入如下信息: $ sudo gedit ~/.profile 2.在打开的文档末尾加上如下两句: export GST_ID3_TAG_ENCODING=GBK:UTF-8:GB1803 ...

  2. ccui.ScrollView 扩展

    大多数游戏都有背包这个东西. 道具列表通常用 ScrollView 来实现. 这个ScrollView内部有一个Layout, 滑动都是由移动这个Layout来实现. 道具摆放通常从上往下, 从左到右 ...

  3. poj 1273.PIG (最大流)

    网络流 关键是建图,思路在代码里 /* 最大流SAP 邻接表 思路:基本源于FF方法,给每个顶点设定层次标号,和允许弧. 优化: 1.当前弧优化(重要). 1.每找到以条增广路回退到断点(常数优化). ...

  4. mongo db安装和php,python插件安装

    安装mongodb 1.下载,解压mongodb(下载解压目录为/opt) 在/opt目录下执行命令 wget fastdl.mongodb.org/linux/mongodb-linux-x86_6 ...

  5. Extjs 4学习2

    主要学习采自:http://www.ishowshao.com/blog/2012/06/19/extjs-4-getting-started/ 用的sdk为extjs4.2.1 根据其中的提示装了一 ...

  6. Js冒泡事件和捕获事件

    js中冒泡事件和捕获事件: 冒泡事件:冒泡事件是从里向外,即是从被绑定元素开始一直向外到达页面的所有祖先元素都会被触发,这 一过程被称为事件冒泡.这个事件从原始元素开始一直冒泡到DOM树的最上层 捕获 ...

  7. Android 内核基本知识

    Android基本知识 Android基本知识.... 1 1. 各版本系统特性.... 1 2. View绘制流程.... 2 3. 动画体系.... 2 4. 事件分发机制.... 3 输入消息获 ...

  8. python自动开发之第十八天

    一.JS正则 test - 判断字符串是否符合规定的正则 rep = /\d+/; rep.test("asdfoiklfasdf89asdfasdf") # true rep = ...

  9. python模块之hashlib加密

    40.加密模块:hashlib      1.           >>> import hashlib >>> ret1 = hashlib.md5()     ...

  10. Python新手学习基础之初识python——与众不同2

    看完了Python的缩进,现在来看看Python的标识符.引号和注释. 标识符 关于Python的标识符,其实不是与众不同,只是有一定的规则. 标识符是编程时使用的名字.在Python中,标识符有几点 ...