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

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

提前做一个绘制方向顶点定义的解释
[cc lang=”actionscript3″ nowrap=”false”]
private function initData() : void
{
//定义每个多边形用到的顶点
//一个方形是由2个三角形构成的
meshIndexData = Vector.
([
0,1,2, 0,2,3,
]);

// 源数据需要用到4个顶点
// xyz坐标, texture 坐标系 UV, 归一化 xyz
meshVertexData = Vector.
([
//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
]);
}
[/cc]

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

后面是完整代码和demo

[cc lang=”actionscript3″ nowrap=”false”]
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.;
// 定义哪些索引的数据给顶点使用
private var meshIndexData : Vector.;

//影响网格坐标和摄像机角度的矩阵
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,
//存入一个4×4矩阵, 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.
([
0,1,2, 0,2,3,
]);

// 源数据需要用到4个顶点
// xyz坐标, texture 坐标系 UV, 归一化 xyz
meshVertexData = Vector.
([
//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
]);
}

}
}
[/cc]

发表评论

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