Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

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

Open
picacure opened this issue Jul 27, 2017 · 2 comments
Open

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

picacure opened this issue Jul 27, 2017 · 2 comments
Labels

Comments

@picacure
Copy link

使用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 可以提取可渲染性能相关信息

演示示例

传送门

@PeakFish
Copy link

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

@06wj
Copy link
Member

06wj commented Jul 27, 2017

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants