article
article copied to clipboard
实现38女王节3D打斗场面
使用Hilo3d V1.0 Alpha版本渲染38女王节AR 互动打斗场景截图:

好,我们使用Hilo 3d实现以上效果:
创建一个透视相机
var camera = new Hilo3d.PerspectiveCamera({
aspect: innerWidth / innerHeight,
far: 1000,
near:0.1,
fov:75,
y:4,
z:3
});
- aspect: 选取设备的像素宽高比
- far: 平截头体的远视口,z轴方向
- near: 平截头体的近视口,z轴方向
- fov,透视开角大小,关于fov移步这里
- y,z:摄像机的y z位置,x y z默认为0
创建一个舞台stage
var dpr = window.devicePixelRatio;
var stage = new Hilo3d.Stage({
container: document.getElementById('container'),
camera: camera,
width: innerWidth * dpr,
height: innerHeight * dpr
});
if(dpr > 1){
stage.canvas.style.width = innerWidth + "px";
stage.canvas.style.height = innerHeight + "px";
}
- container: 指定绑定的Dom结点,Hilo3d会创建一个Canvas对象
- camera: 即上面创建的摄像机
- width: 设备像素宽度,本例取的window.innerWidth * window.devicePixelRatio
- height: 设备像素高度,本例取的window.innerHeight * window.devicePixelRatio
为了避免锯齿现象,我们把Canvas画布的对象真实宽高置为window.devicePixelRatio倍,同时将画布的css的宽高置为当前窗口大小。
避免锯齿的方法除了上面的方式,修改着色器也是方法之一,以后再做阐述。
设置计时器
var ticker = new Hilo3d.Ticker(60);
ticker.addTick(stage);
ticker.addTick(Hilo3d.Tween);
ticker.addTick(Hilo3d.Animation);
ticker.start();
- Hilo3d.Ticker(60): 指定FPS参数数值大小
- addTick(Hilo3d.Tween): 开场需要对一些模型做缓动,需要将缓动
Hilo3d.Tween手动加入到Ticker循环中 - addTick(stage): stage中所有的子对象都会被逐结点查找,并在逐时间片内完成update和render过程
- addTick(Hilo3d.Animation): 如果glTF模型中包含动画,需要添加
Hilo3d.Animation对象,Hilo3d会协助完成动画相关的解析和渲染 - ticker.start(): start一旦调用,渲染和3维元素数据更新便开启了
准备3D素材资源
借助海螺码头素材转化能力,我们将3D设计师提供给我们的3d素材转换成Hilo3d指定渲染格式(glTF)
var res = [{
"id": "soldier",
"src": "//cx.alicdn.com/tmx/1cf44ad84cc97b8a24e411d7caed0719.gltf"
},{
"id": "ground",
"src": "//cx.alicdn.com/tmx/429cd105280881c86312f1f7aabd908e.gltf"
}, {
"id": "player0",
"src": "//cx.alicdn.com/tmx/076728f9a1d45e926fe70f7efe625bf5.gltf"
},{
"id": "player1",
"src": "//cx.alicdn.com/tmx/0551344875278d5619b175f02d3075d1.gltf"
}
];
- 从海螺码头获取3D素材资源列表,3个角色,一个地面场景
var loadQueue = new Hilo3d.LoadQueue();
loadQueue.add(res).on('complete', function(){
res.forEach(function(r){
var node = loadQueue.getContent(r.id).node;
node.getChildByName('RootNode').setScale(0.01);
res[r.id] = node;
});
init();
}).start();
-
Hilo3d.LoadQueue: Hilo3d下载队列,
Hilo3d.LoadQueue采用链式调用,开放load,error,complete事件监听 -
loadQueue.getContent:获取对应Id资源
-
loadQueue.getContent(r.id).node:
Hilo3d.LoadQueue会自动根据资源类型路由到Hilo3d.GLTFLoader, GLTFLoader会调用Hilo3d.GLTFParser解析glTF模型并返回以下属性字段:
.node(Hilo3d.Node)
.meshes(Hilod.Mesh 或者 Hilo3d.SkinedMesh)
.cameras(Hilo3d.PerspectiveCamera)
.textures(Hilo3d.Texture)
.materials(Hilo3d.BasicMaterial)
- node.getChildByName('RootNode'): Node提供查找子节点相关方法,以结点名称查找
另外,还可以按照nodeId 方式查找节点node.getChildById("XX")
或是按照className 查找 node.getChildrenByClassName("XX"),className为Hilo3d的实体类型分类,如Node的className为"Node", Mesh的className为"Mesh", Geometry的className为"Geometry"
设置场景
设置根节点
_root = new Hilo3d.Node({
y:0.1,
onUpdate:function(){
this.rotationY += 0.3;
}
}).addTo(stage);
- 一般我们会在主场景下,设置一个根节点,方便对整个场景操作
设置玩家角色
player0 = res.player0;
player0.x = -3;
player0.rotationY = 90;;
player0.setScale(playerScale);
_root.addChild(player0);
- 从loadQueue获取的资源列表选取我们要设置的角色对象
- 将角色对象添加到根节点中
player0.anim.addClip('run', 0, 20/30);
player0.anim.addClip('attack', 20/30, 45/30);
player0.anim.stop();
- 本例中设计师将一套动画资源放在一起,我们需要根据时间片选取对应动画数据
- player0.anim 为
Hilo3d.Animation对象,包含和动画相关的API,如果模型文件中不包含动画,此属性为null - player0.anim.addClip('run', 0, 20/30): 为player0指定一段自定义为“run”的动画片段,动画的时间片为[0, 20/30],时长为2/3秒
- player0.anim.addClip('attack', 20/30, 45/30):为player0指定一段自定义为“attack”的动画片段,动画的时间片为[20/30, 45/30],时长为0.83秒
- player0.anim.stop(): Hilo3d默认启动动画播放,不需要自动执行动画时需要暂停
缓动角色对象
soldier.setPosition(pos[0], 5, pos[2]);
soldier.rotationY = index > 3?-90:90;
soldier.setScale(soldierScale);
soldier.visible = false;
- 设置角色对象的soldier 位置,大小和朝向
Hilo3d.Tween.to(soldier, {
y:0
}, {
onStart:function(){
soldier.visible = true;
},
delay:250,
duration:500
});
- Hilo3d.Tween: 沿用Hilo2d的缓动Tween
- 将soldier的y方向位置置为0,耗时0.5秒,延迟 0.25秒执行
soldiers.push(soldier);
_root.addChild(soldier);
soldier.anim.addClip('run', 0, 20/30);
soldier.anim.addClip('attack', 20/30, 45/30);
soldier.anim.stop();
- 设置soldier的角色动画,禁止自动播放
设置相机朝向
camera.lookAt(ground);
- camera.lookAt: lookAt继承自
Hilo3d.Node, 确定摄像机的朝向为某个场景内物体,另外对场景内的物体使用lookAt 可以实现Billboard的效果

输入控制OrbitControls
var orbitControls = new OrbitControls(stage);
- 将手机屏幕等虚拟成一个近似球形平面,支持双手指缩放
- 接受参数
Hilo3d.Stage
渲染Gizmos
渲染期间想了解模型的fps,面数,drawcall次数,系统内存占用等性能信息(PC Only),可直接创建Stats对象
var stats = new Stats(ticker, stage.renderer.renderInfo);
- Stats以插件形式提供,对应目录 example/
- 从
renderer.renderInfo可以提取可渲染性能相关信息
演示示例
Hilo3d 是实现了 gltf 的 渲染器 ? 支持 2.0 版本不 , 我学习学习。
@PeakFish 是的,同时支持1.0&2.0,2.0目前基本功能都支持了,还差些细节处理,会在8月份全部修好。