第一人称在 3D 中的用法要参考第一人称在射击游戏中的使用,第一人称射击游戏(FPS)是以第一人称视角为中心围绕枪和其他武器为基础的视频游戏类型;也就是说,玩家通过主角的眼睛来体验动作。自从流派开始以来,先进的3D和伪 3D图形已经对硬件发展提出了挑战,而多人游戏已经不可或缺。
Doom的截图,这个流派的突破游戏之一,展示了第一人称射击游戏的典型视角
现在博物馆或者公司也经常使用到 3D 动画做宣传片等等,3D动画演绎最大的优势,便是在于内容与形式上给人的真实感受。它比平面作品更直观,比 2D 动画更真实,所以更能给观赏者以置身于广告环境当中的感受,大大增强广告的说服力。3D 技术的发展甚至挑战受众的分辨能力,使受众的判断游离于与虚拟和现实之间。
而且 3D特效的应用为创意提供了更加广阔的思维空间,并成为创意执行的可靠保证,并丰富了创意的形式和风格手段。根据广告主题的表现诉求,可以营造出梦幻般的神奇氛围来刺激打动受众,从而起到与受众沟通的目的。
3D动画宣传片将 3D动画、特效镜头、企业视频、照片、未来前景等内容通过后期合成、配音、解说形成一部直观、生动、喜闻乐见的高品位的企业广告宣传片,让社会不同层面的人士对企业产生正面的、积极的、良好的印象,从而建立对企业的好感与信任,并信赖该企业的产品或服务。
现在 3D 发展地如此迅速也要感谢人类对于“现实”的追求,所以学好用好 3D 是未来成功必不可少的一部分。
本文例子的思路是进入一个机房参观,打开门的动作是再生动不过了, 再加上适当地转弯,基本上完全模拟了人在机房中参观的效果。还有一个好处就是,如果要演示给领导看而又不用操作,这种炫酷的效果领导一定会很满意!
http://www.hightopo.com/demo/room-walkthrough/index.html
界面上的“reset”和“start”两个按钮是直接加在 body 体中的 button,并在这两个按钮上添加点击事件:
<div></div><div></div>
整个场景由 HT 封装的 3D 组件搭建形成的,构造这么大的场景是需要一定量的代码的,为了简化,我把场景单独拿出来,并用 HT 封装的 ht.JSONSerializer 类将场景序列化为 json,代码中只引入了生成后的 json 文件,为了让大家更明确,我这边做个示例,假设已经搭建好 3D 场景了:
dm = new ht.DataModel();g3d = new ht.graph3d.Graph3dView(dm);//.......构建好场景dm.serialize();//可以填入number参数,作为空格缩进值
既然我们已经搭建好环境,转成了 json 文件,代码中不好控制,这种情况下我们会将 DataModel 数据模型再反序列化,这个函数的功能就是将 json 格式转成对象,并将反序列化的对象传入到 DataModel 数据模型中,详情请参考HT for Web 序列化手册:
var g3d = window.g3d = new ht.graph3d.Graph3dView(), dataModel = g3d.dm(), view = g3d.getView(), path = null;g3d.setMovableFunc(function(data) { return false;}); g3d.setVisibleFunc(function(data) { if (data.getName() === "path") { return false; } return true;}); g3d.setEye([523, 5600, 8165]);g3d.setFar(60000);dataModel.deserialize(json);
我们目前需要操作场景中的“门”、以及我们将要走的路线“path”,遍历 DataModel 数据模型,获取这两个数据:
for (var i = 0; i < dataModel.size(); i++) { var data = dataModel.getDatas().get(i); if (data.getName() === "门") {//json中设置的名称 window.door = data; } if (data.getName() === "path") { path = data; } if (window.door && path) {//获取到door 和 path 的data之后就跳出循环 break; }}
这个例子中简单来说就只有四个动作,“重置”回到原点、“开始动作”、“向前移动”,“停止”。点击“开始”按钮,在“开始动作”中我们只做了一个动作,“开门”动作,动作结束之后调用“forward”函数向前移动:
function startAnim() { if (window.isAnimationRunning) { return; } reset(); window.isAnimationRunning = true;//动画是否正在进行 ht.Default.startAnim({ frames: 30, // 动画帧数,默认采用`ht.Default.animFrames`。 interval: 20, // 动画帧间隔,默认采用`ht.Default.animInterval`。 finishFunc: function() {// 动画结束后调用的函数。 forward(); }, action: function(t){ // action函数必须提供,实现动画过程中的属性变化。 door.setRotationY(-120 * Math.PI / 180 * t); } }); }
这边的“reset”函数就是“重置”回到原点的功能,我们通过这个函数将所有变化过的都恢复初始的位置,包括“门”的位置:
function reset() { if (window.isAnimationRunning) { return; } g3d.setCenter([0,0,0]); g3d.setEye([523, 5600, 8165]); window.forwardIndex = 0; door.setRotationY(0);}
要“移动”,肯定需要走路的“路径”,也就是我们刚刚获取到的“path”,通过window.points = path.getPoints()._as; 获取“path”中的所有元素,初始化window.forwardIndex = 0; 通过控制“path”中前后两点来设置 3D 场景中的 Eye 和 Center,这样就能营造一个我们是第一人的效果:
var point1 = points[forwardIndex], point2 = points[forwardIndex + 1];var distanceX = (point2.x - point1.x), distanceY = (point2.y - point1.y), distance = Math.sqrt(distanceX * distanceX + distanceY * distanceY)-200;//两点之间的距离通过三角形勾股定理计算 怕碰墙所以-200g3d.setEye([point1.x, 1600, point1.y]);//眼睛g3d.setCenter([point2.x, 1600, point2.y]);//我
HT 中 3D 组件有一个 walk(step, anim, firstPersonMode)方法,该函数同时改变eye和center的位置,也就是eye和center在两点建立的矢量方向上同时移动相同的偏移量。step为偏移的矢量长度值。firstPersonMode参数为空时则默认采用Graph3dView#isFirstPersonMode()当前值, 如果为第一人称模式调用walk操作,该函数会考虑Graph3dView#getBoundaries()边界限制。
g3d.walk(distance, { frames: 50, interval: 30, easing: function(t) {return t; }, finishFunc: function() { forwardIndex += 1; if (points.length - 2 > forwardIndex) {//points.length = 5 g3d.setCenter([point2.x, 1600, point2.y]);//把结束点变成起始点 g3d.rotate(Math.PI / 2, 0, { frames: 30, interval: 30, easing: function(t) {return t;}, finishFunc:function() { forward();} }); } else { var lastPoint = points[points.length - 1];//json 中path的points 的最后一个点 g3d.setCenter([lastPoint.x, 1400, lastPoint.y]); g3d.rotate(-Math.PI / 2, 0, { frames: 30, interval: 30, finishFunc: function() { window.isAnimationRunning = false; } }); } }});
不管“path”的点有多少个,这个判断语句还是能运作,只在最后一个点是跳出 finishFunc 动画结束后调用的函数,并将 window.isAnimationRunning 值设为 false 停止 startAnim 函数。如果不是最后一个点,用户“旋转”之后,回调 forward 函数。至此,全部代码解释完毕,很短的代码量,却做出了这么大的工程!
总结
以上所述是小编给大家介绍的基于HTML5的WebGL经典3D虚拟机房漫游动画,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对网站的支持!
虚拟漫游,html5,webgl
《魔兽世界》大逃杀!60人新游玩模式《强袭风暴》3月21日上线
暴雪近日发布了《魔兽世界》10.2.6 更新内容,新游玩模式《强袭风暴》即将于3月21 日在亚服上线,届时玩家将前往阿拉希高地展开一场 60 人大逃杀对战。
艾泽拉斯的冒险者已经征服了艾泽拉斯的大地及遥远的彼岸。他们在对抗世界上最致命的敌人时展现出过人的手腕,并且成功阻止终结宇宙等级的威胁。当他们在为即将于《魔兽世界》资料片《地心之战》中来袭的萨拉塔斯势力做战斗准备时,他们还需要在熟悉的阿拉希高地面对一个全新的敌人──那就是彼此。在《巨龙崛起》10.2.6 更新的《强袭风暴》中,玩家将会进入一个全新的海盗主题大逃杀式限时活动,其中包含极高的风险和史诗级的奖励。
《强袭风暴》不是普通的战场,作为一个独立于主游戏之外的活动,玩家可以用大逃杀的风格来体验《魔兽世界》,不分职业、不分装备(除了你在赛局中捡到的),光是技巧和战略的强弱之分就能决定出谁才是能坚持到最后的赢家。本次活动将会开放单人和双人模式,玩家在加入海盗主题的预赛大厅区域前,可以从强袭风暴角色画面新增好友。游玩游戏将可以累计名望轨迹,《巨龙崛起》和《魔兽世界:巫妖王之怒 经典版》的玩家都可以获得奖励。
更新日志
- 小骆驼-《草原狼2(蓝光CD)》[原抓WAV+CUE]
- 群星《欢迎来到我身边 电影原声专辑》[320K/MP3][105.02MB]
- 群星《欢迎来到我身边 电影原声专辑》[FLAC/分轨][480.9MB]
- 雷婷《梦里蓝天HQⅡ》 2023头版限量编号低速原抓[WAV+CUE][463M]
- 群星《2024好听新歌42》AI调整音效【WAV分轨】
- 王思雨-《思念陪着鸿雁飞》WAV
- 王思雨《喜马拉雅HQ》头版限量编号[WAV+CUE]
- 李健《无时无刻》[WAV+CUE][590M]
- 陈奕迅《酝酿》[WAV分轨][502M]
- 卓依婷《化蝶》2CD[WAV+CUE][1.1G]
- 群星《吉他王(黑胶CD)》[WAV+CUE]
- 齐秦《穿乐(穿越)》[WAV+CUE]
- 发烧珍品《数位CD音响测试-动向效果(九)》【WAV+CUE】
- 邝美云《邝美云精装歌集》[DSF][1.6G]
- 吕方《爱一回伤一回》[WAV+CUE][454M]