article icon indicating copy to clipboard operation
article copied to clipboard

实现38女王节3D打斗场面

Open picacure opened this issue 8 years ago • 2 comments

使用Hilo3d V1.0 Alpha版本渲染38女王节AR 互动打斗场景截图:

55b34711f9982f1ef17fd02639cf600d

好,我们使用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的效果

843f628f94f9b14690b37f558bddfc3d

输入控制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 可以提取可渲染性能相关信息

演示示例

传送门

picacure avatar Jul 27 '17 02:07 picacure

Hilo3d 是实现了 gltf 的 渲染器 ? 支持 2.0 版本不 , 我学习学习。

PeakFish avatar Jul 27 '17 02:07 PeakFish

@PeakFish 是的,同时支持1.0&2.0,2.0目前基本功能都支持了,还差些细节处理,会在8月份全部修好。

06wj avatar Jul 27 '17 09:07 06wj