虽然利用threejs来在网页中渲染3d模型不是第一次折腾了,但是还是遇到了各种问题。总结下我所遇到的问题,希望能给正在使用threejs的小伙伴一个帮助。

一、所使用的软件与开发环境

  1. Maya2014、Blender2.77a

  2. threejs-r82

  3. webpack + gulp

二、 动画模型的导入导出

1、格式的选择

threejs支持的动画模型有Collada(.dae)、mmd(用过MikuMikuDance的应该知道) 、fbx、json。

Collada里面包含了你场景中所有数据(camera、scene、light),因为手生所有这次没有采用这种格式。

fbx虽然网页中可以加载fbx,但我常用的是从其它软件中导个fbx给blender用。不过这里值的注意一下,以maya为栗子。

maya导出fbx的时候会有一个文件格式的选项: 二进制(导出给blender选择这种编码)ASCII(导出给threejs直接用选择这种编码)如下图所示:

2、动画的分类

  • 变形动画(threejs中MorphAnimMesh类)

变形动画简单点来说就是通过变形物体来改变物体的样子,复杂的动画用这种方法处理就不合试了,因为改变一下所有的顶点都会随之改变。数据量挺大的。

在blender中的导出json选择如下所示:

  • 骨骼动画(threejs中SkinnedMesh类)

骨骼动画也就是蒙皮动画,通过给物体绑定骨骼来对物体进行操作。

在blender中的导出json时存在以下两种情况:

1、keyframe animation 导出选项以及json代码如下所示:

2、skeletal animation 导出选项以及json代码如下所示:

3、从maya中导出fbx至blender中

  1. 在maya中导出fbx给blender的时候文件格式选择二进制

  2. 做模型绑定的时候对模型的数据进行清零(这点很重要,不然blender导出json的会出现错误情况)、绑定方法的话按照做游戏的绑定方法就可以了。

  3. 软边显示与硬边显示(导出时在maya中选择软边显示)照理说应该是硬边显示才对,瞎猜是blender与maya设置不同吧。在页面中渲染的情况如下所示:

三、 模型渲染到网页中

1、创建场景

var camera,scene,rendererscene = new THREE.Scene();camera = new THREE.PerspectiveCamera(40, 750 / 1200, 0.1, 10000);renderer = new THREE.WebGLRenderer({antialias: true, alpha: false, preserveDrawingBuffer: true});renderer.shadowMap.enabled = true;renderer.autoClear = true;var render = function () {renderer.render(scene, camera);}
var animate = function () {requestAnimationFrame(_that.animate);render();}//一个简单的场景就写好了

2、创建动画模型

这里我导出的是json格式的蒙皮动画所以我采用了threejs中提供的BlendCharacter()方法来创建我的动画模型。具体代码如下所示:

var createSkinningAnimate = function (model) {var blendMesh = new THREE.BlendCharacter();blendMesh.modelId = model.id;blendMesh.load( model.modelSrc, function(){blendMesh.name = model.modelName;blendMesh.scale.set(model.scaleX, model.scaleY, model.scaleZ);blendMesh.position.set(model.x, model.y, model.z);blendMesh.frustumCulled = false;blendMesh.material.transparent =  true;//blendMesh.material.opacity = 0;if(model.shadow) {blendMesh.castShadow = true;  //表示这个物体是可以产生阴影的}if(model.receive) {blendMesh.receiveShadow = true;  //表示这个物体是可以接受(显示)阴影的}if(model.side) {blendMesh.material.side = THREE.DoubleSide;  //解决单双面显示问题}blendMesh.visible = false;for(var i = 0, len = model.action.length; i < len; i++) {blendMesh.applyWeight( model.action[i].name, model.action[i].weight);};blendModelGroup.add(blendMesh);loadModelProgress();});}

创建这个模型的时候我遇到了两个问题:

  • 模型出现渲染的时候单双面问题吗,具体表现如下所示。

解决方法:

//设置material的sideblendMesh.material.side = THREE.DoubleSide;  //解决单双面显示问题
  • 当镜头拉近的时候模型从视野中消失,具体表现如下所示

解决方法:

//设置这个属性为false时这个bug就好了。blendMesh.frustumCulled = false;

frustumCulled 这个属性是至今干嘛用的我不太清楚,求告知。

3、灯光渲染

场景中利用了两个灯光全局灯(AmbientLight)与聚光灯(SpotLight)代码如下:

_that.ambientLight = new THREE.AmbientLight( 0xffffff);scene.add(_that.ambientLight);var spotLight = new THREE.SpotLight(0xffffff);_that.spotLight = spotLight;spotLight.angle = 0.74;
spotLight.position.set(0, 60, -1);
spotLight.castShadow = true;
spotLight.penumbra = 0.7;
spotLight.intensity = 2;
spotLight.distance = 200;
spotLight.shadow.camera.near = 50;
spotLight.shadow.camera.far = 200;
spotLight.shadow.camera.fov = 35;
spotLight.shadow.mapSize.height = 1024;
spotLight.shadow.mapSize.width = 1024;spotLight.name = 'spotLight';scene.add(spotLight);spotLight.target.position.set(-15,0,0);//scene.add(new THREE.SpotLightHelper( spotLight ));scene.add(spotLight.target);

灯光的调试主要靠guiLightHelper,这两个东西调试起来非常方便省了不少时间。调试前与调试后如图所示:

5、调试技巧

  • gui

  • helper

  • topView

helper:threejs的相机、灯光都提供了Helper这个方法,在页面中渲染添加一个参考线。

topView: 意思就是在页面中渲染一个顶视图,如果需要做相机的移动这个方法比较靠谱可以清楚的看见相机是这么运动的。然后发现问题的所在。渲染如下图所示:

实现代码:

var testW = 750,testH = 1200;var views = {left: 0.5,bottom: 0,width: 0.5,height: 0.5,eye: [0, 0, 50],direction: [-1, 0, 0]
};var orthoCam = new THREE.OrthographicCamera(testW / -2, testW / 2, testH / 2, testH / -2, -500, 10000);
view.orthoCam = orthoCam;update () {var left   = Math.floor( testW  * 0.0 );var bottom = Math.floor( testH * 0 );var width  = Math.floor( testW  * 1.0 );var height = Math.floor( testH * 1.0 );renderer.setViewport( left, bottom, width, height );renderer.setScissor( left, bottom, width, height );renderer.setScissorTest ( true );camera.updateProjectionMatrix();cameraHelper.update();cameraHelper.visible = false;renderer.render(scene, camera);cameraHelper.visible = true;var view = views;orthoCam = view.orthoCam;orthoCam.left = testW / - 2;orthoCam.right = testW / 2;orthoCam.top = testH / 2;orthoCam.bottom = testH / - 2;orthoCam.position.x = view.eye[ 0 ];orthoCam.position.y = view.eye[ 1 ];orthoCam.position.z = view.eye[ 2 ];orthoCam.rotation.x = view.direction[ 0 ] * Math.PI * 0.5;orthoCam.rotation.y = view.direction[ 1 ] * Math.PI * 0.5;orthoCam.rotation.z = view.direction[ 2 ] * Math.PI * 0.5;orthoCam.updateProjectionMatrix();var left1   = Math.floor( testW  * view.left );var bottom1 = Math.floor( testH * view.bottom );var width1  = Math.floor( testW  * view.width );var height1 = Math.floor( testH * view.height );renderer.setViewport( left1, bottom1, width1, height1 );renderer.setScissor( left1, bottom1, width1, height1 );renderer.setScissorTest ( true );renderer.shadowMap.enabled = true;renderer.render( scene, orthoCam );
}

核心创建一个正交相机OrthographicCamera

6、兼容判断

因为不是所有手机都支持webgl所以需要做一下兼容性的判断。

  • 在ios8虽然支持webgl但是时间跟踪clock不支持,但在不报错。查看源码的情况下估计是var newTime = ( performance || Date ).now()没有得到正确的值。因为时间关系没有过多的深入,所以页面在ios8直接跳转至2d版本。

-getExtension('WEBGL_depth_texture')经过测试在一些安卓上返回为null,所以没有用这个去做区分。

兼容代码如下所示:

var canvas = document.createElement("canvas");
var gl =  canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
if( gl ){var OES_TextureExtension = gl.getExtension('OES_texture_half_float');var EXT_TextureExtension = gl.getExtension( 'EXT_texture_filter_anisotropic' );
}if(gl && OES_TextureExtension && EXT_TextureExtension&& !(isIos && version < 9)) {//..3d code}else {//..2d code};

TODO:

虽然这个项目上线了,但是还有很多东西需要去细化完善- -!!。

  1. 更好的完成相机的移动

  2. 人物的动画拆分

  3. 整个场景动画优化

之前用threejs做的一个小项目点击这里查看

最后附上体验地址:

转载于:https://www.cnblogs.com/pursues/p/6231891.html

从Maya中把模型搬运至网页的过程相关推荐

  1. maya骨骼显示_干货 | 如何删除maya中绑定好的骨骼,只留下一个干净的模型

    哈喽大家好 我是曼特君 五分钟小课堂又要开课辣 快搬个小板凳准备好 今天交大家maya中删除骨骼绑定的方法 想把导入maya中带骨骼和绑定的模型 除了模型以外的部分 全部删除掉 变成一个干净的模型文件 ...

  2. 【3D游戏建模全流程教学】在Maya中制作小岛模型

    本文为大家展示使用Maya创建一个小岛的过程,希望大家喜欢. 1 模型参考 将Quixel岩石转过来,用它制成漂浮的岩石,从Maya中的Feel Good Inc.建造浮岛. 我在这里没有做太多的参考 ...

  3. 如何在Maya中修改已经绑定后的模型的法线

    前言:最近想把尼尔机械纪元的2B导入到UE中看看效果,可不知道是不是我解包的过程有问题,2B模型的裙子部分的发现有问题,而且裙子的模型还被拆分为了3个部分,直接软边是不管用的,而且已经绑定的模型就算修 ...

  4. 从maya中 导入物体 到Uniyt3D 规范 整理

    从maya中导入物体到Uniyt3D 我想,很多小白跟我一样,从maya或者3dmax中导入到u3d的物体不知道怎么用.我也是新手,共同分享一下今上午的经验. 我想大部分人看到我这个东西之前,已经看多 ...

  5. Cesium中gltf模型的坐标系

    Cesium中使用gltf格式的模型,而gltf格式的模型的坐标系在加载到Cesium中后,Cesium会自动变换坐标系. 本文简要阐述gltf模型的坐标系加载前后的变化. gltf模型 可以使用各种 ...

  6. Web前端,CSS中盒子模型的组成,了解掌握盒子模型的边框、内边距、外边距

    前言 持续总结输出中,今天分享的是Web前端,CSS中盒子模型的组成,了解掌握盒子模型的边框.内边距.外边距 1.盒子模型的介绍 盒子的概念 页面中的每一个标签,都可看做是一个 "盒子&qu ...

  7. 从Poser中输出模型与向3ds Max导入模型

    Poser与其他3D软件,如3ds Max.Maya.LightWave等可以进行数据交换,这也是在制作模型成品时不可缺少的重要步骤,Poser既可以将其他3D软件制作的模型作为道具导入Poser,也 ...

  8. 在Maya中快速建模的几种技巧!新手都看呆了,你还不会?

    在Maya中其实有多种方法可以完成所有工作,而且作为初学者,几乎不可能立即学习每个工具.很容易陷入例行工作,以为自己在高效地做某事,其实不然.在Maya中使用以下五种工具,如果使用正确,它们可以极大地 ...

  9. 在Quake4中创建模型

    原文地址 https://www.iddevnet.com/quake4/ArtReference_CreatingModels 在Quake4中创建模型 本文件将尝试解释Raven Software ...

最新文章

  1. CCNA10月27日战报
  2. 关于pycharm右键只能选择run Unit不能直接run的解决方法
  3. 什么是梯度爆炸/梯度消失?
  4. flash java 通信,Flash到JavaScript的通信实例
  5. python函数介绍
  6. react native在static中使用this方法
  7. MyBatis学习笔记(一):MAVEN的下载,安装与环境配置和在IDEA中配置maven
  8. 小米路由器4a刷第三方固件_小米路由器4A的断网问题初探
  9. 深入.NET编程 第十一章 影院售票系统
  10. webStorm汉化
  11. 学习电商项目的经验总结(三)
  12. stm32开发环境搭建及应用
  13. 阿兹卡塔防 Azgard Defense 详细攻略
  14. 【系统运维-raid5】HW5885V3下挂4块2T硬盘如何做RAID5
  15. Mac电脑程序无响应怎么办?mac强制关闭软件的6种方法
  16. 审稿审什么你真的弄清楚了吗
  17. 那些年我在兄弟连学的PHP
  18. 高中关于人工智能方面的课题_人工智能的课题有什么研究方向
  19. 吴恩达离职百度 | 一别两宽,各奔前程
  20. 1、暴力破解与实用性原则

热门文章

  1. c语言中数组作为参数传参
  2. java 导出本地xml文件_java导出xml文件
  3. 用AI 来一键体验“返老还童”的快乐!马化腾、李彦宏、杨幂都能还原的那种 |儿童节福利...
  4. oracle的switch+case语句吗,2.7 switch 语句中的 case 范围
  5. 光滑曲线_极简微积分——函数的曲线的描绘
  6. AccessKey泄露利用
  7. 大家都在努力,你凭什么不努力
  8. 微信小程序支持分享到朋友圈了
  9. 高清碑文《怀仁集王羲之书圣教序》
  10. 传奇服务器怎么设置状态是开区还是合区,传奇私服开区合区教程全解