目录

  • 一. 模型的制作

    • 1.1 生成字体模型
    • 1.2 多表面贴图
  • 二. 镜头及动画
  • 三. 大作业总结

示例代码托管在:http://www.github.com/dashnowords/blogs

博客园地址:《大史住在大前端》原创博文目录

华为云社区地址:【你要的前端打怪升级指南】

有了上一篇基础知识的储备,本节就来制作一下简易版的MARVEL的片头动画。【点击观看动画效果】

一. 模型的制作

1.1 生成字体模型

字体模型的生成使用到了THREE.TextGeometry,它需要先加载字体文件,然后在回调函数中生成字体模型,相当于在THREE.ShapeGeometry实例上绘制平面图形,然后再拉伸成为THREE.ExtrudeGeometry拉伸体。基本代码如下:

var loader = new THREE.FontLoader();
loader.load( 'fonts/helvetiker_regular.typeface.json', function ( font ) {var geometry = new THREE.TextGeometry( 'MARVEL',{font: font,size: 80,//平面形状大小height: 5,//拉伸高度curveSegments: 12,//默认使用的三角面片数,越多则表面越平滑bevelEnabled: true,//是否使用倒角bevelThickness: 10,bevelSize: 8,bevelOffset: 0,bevelSegments: 5} );
} );

本例中为了在不同的字母表面使用不同的videoTexture来进行贴图,所以将6个字母分成3组进行生成,所以在生成过程中需要动态调整几何体的空间位置,避免最后生成的模型都挤在一起。调整的方法如下:

//geometry指字体模型实例
geometry.computeBoundingBox();//计算过一次以后,包围盒属性就会添加到geometry.boundingBox上,然后就可以以此为依据进行调整
cube.position.x = - (font.boundingBox.max.x - font.boundingBox.min.x)/2 + tempPos;
cube.position.y = - (font.boundingBox.max.y - font.boundingBox.min.y)/2;
cube.position.z = - (font.boundingBox.max.z - font.boundingBox.min.z)/2; 

调整的思路就是,通过将x,y,z三个方向都偏移包围盒自身尺寸的一半,从而达到将定位参考点移动到立方体的几何中心的目的,tempPos记录上一个几何体总宽度,作为下一个几何体横向(x方向)的偏移参考,这样就可以保证几何体横向错开。设置好参数后,就可以生成MARVEL生成的字体模型线框图(下图在材料中开启了wireframe线框模式):

1.2 多表面贴图

从上面的线框图可以看到,字体模型虽然很容易生成,但是使用了超过100个三角面,再用上一节中的手动贴图修复的方法显然是行不通的,所以此处需要想办法通过程序来自动贴图。

首先,每一个面都有一个normal属性,它是一个归一化的向量,表明了这个面在空间中的指向,也就是面的法向量。比如上面例子中,字母的正面表面的法向量就是从屏幕内垂直指向屏幕外,也就是+z方向,所以这个面的法向量实例vector3中的z分量一定是正值。从动画进行的角度看,我们需要使用到的表面是模型的正面,左面和下面。左面实际上就是法向量中x分量为负数的面,下面就是y坐标为负数的面,通过法向量的特征,我们就可以挑选出从特定角度观察几何体时看到的效果,例如遍历几何体的表面,把所有法向量中z为正数的面挑出来,实际上就相当于在z轴正方向往负方向看时看到的图形,也就是平面的MARVEL这几个字母。

在不规则表面贴图,就像把电影投影到一个不规则表面进行放映,比如将投影仪的幕布折叠成某个形状,画面依旧会以二维投影的形式展现在幕布上。举个栗子,比如现在要给MA这两个字母的下表面贴图(都是凹进去的),需要选出的面的法向量特征满足y < 0,然后求出包围盒大小后,对应关系如下:

所以贴图时,需要将素材的y方向(0-1之间的某个数字)坐标按比例映射到包围盒z方向,将素材x方向坐标按比例映射到包围盒x方向,如上图所示。有了映射关系,就可以让程序遍历表面并自动进行贴图处理,上图的贴图效果最终会是类似下面的样子:

A的字体模型内部有一个封闭空间,其中也有法向量z值小于0的面,它们也会按照同样的坐标转换标准被贴图。示例demo中的自动贴图相关代码如下:

//重新计算uv贴图部分
function rebuildUV(geo) {if(!geo.isGeometry) return;const max = geo.boundingBox.max;const min = geo.boundingBox.min;const offset = new THREE.Vector3(0 - min.x,0 - min.y, 0 - min.z);const range = new THREE.Vector3(max.x  -  min.x,max.y - min.y, max.z - min.z);const faces = geo.faces;geo.faceVertexUvs [0] = []; for(let i = 0; i< faces.length; i++){const v1 = geo.vertices [faces [i] .a],v2 = geo.vertices [faces [i] .b],v3 = geo.vertices [faces [i] .c]; //faces[i].normal中为归一化的向量,可以表明面的指向if(faces[i].normal.z > 0){//z > 0 的面面向屏幕正面,与使用者相对。geo.faceVertexUvs[0].push([new THREE.Vector2((v1.x+offset.x)/range.x,(v1.y+offset.y)/range.y),new THREE.Vector2((v2.x+offset.x)/range.x,(v2.y+offset.y)/range.y),new THREE.Vector2((v3.x+offset.x)/range.x,(v3.y+offset.y)/range.y)]);}else if (faces[i].normal.y < 0){// y < 0 的面为模型下面geo.faceVertexUvs[0].push([new THREE.Vector2((v1.x+offset.x)/range.x,(v1.z+offset.z)/range.z),new THREE.Vector2((v2.x+offset.x)/range.x,(v2.z+offset.z)/range.z),new THREE.Vector2((v3.x+offset.x)/range.x,(v3.z+offset.z)/range.z),]) } else{//没有用到的表面默认为不贴图geo.faceVertexUvs[0].push([new THREE.Vector2(0,0),new THREE.Vector2(0,0),new THREE.Vector2(0,0)]);}}geo.uvsNeedUpdate = true;
}

二. 镜头及动画

变角度观察立体模型时,透视相机的效果会更逼真一些,本例中使用正交相机进行开发。关于这两种相机的使用,直观的区别是:

使用透视相机就好比使用者在调节一个真实摄像机的参数来改变出现在镜头中的画面的效果,可以说是一种间接确定拍摄范围,且它的视场是一个锥形区域;而正交相机相当于是直接设定拍摄范围的长宽高,至于镜头该在哪不需要关心,它的视场是一个矩形盒子,更像是一种平面投影,也不会有透视造成的变形效果。

正交相机的构造函数如下:

OrthographicCamera( left : Number, right : Number, top : Number, bottom : Number, near : Number, far : Number )
left — Camera frustum left plane.
right — Camera frustum right plane.
top — Camera frustum top plane.
bottom — Camera frustum bottom plane.
near — Camera frustum near plane.
far — Camera frustum far plane.

通过传入左右上下远近6个参数来确定一个矩形盒子作为舞台区域,在舞台内的就可以显示,不在舞台内的就不显示,比如下面示例中如果绕y轴转动字体模型,就会有一部分超出所设定的舞台区域:

[](https://img2018.cnblogs.com/blog/1354575/201907/1354575-20190723204434735-254014144.png

)

由于正交相机的舞台是一个矩形盒子,所以无论远近,投影在前后表面的图形都是一样的(透视相机则不同,和真实效果更类似,离得越远,看到的物体越小),所以调节正交相机position.z通常是达不到预期效果的,只能更新相机参数的上下左右坐标值改变投影面的大小,也就是正交相机舞台的正投影面区域,来模拟z方向位置的变化造成的视觉效果变化。正交相机的参数修改后需要显示调用一下camera.updateProjectionMatrix( )来让其生效。

本例中镜头变化相关代码如下(远近效果通过调节相机实现,角度翻转通过操作字体模型组实现):

//模拟相机移动轨迹
function mockCameraTrack() {//1.初始轨迹调整相机参数,将镜头拉远if (camera.right < windowWidth) {   //镜头位置camera.left -= step;camera.right += step;camera.top += step;camera.bottom -= step;}//2.到达预设时间时开始反转if (group.rotation.x < 0){if(windowWidth - camera.right < 200){step = 3;rotationStep = 0.6;}group.position.x += 0.2 * step;group.rotation.x += rotationStep * Math.PI / 180;group.rotation.z -= (rotationStep * 5 / 9) * Math.PI / 180;}//更新相机投影坐标camera.updateProjectionMatrix();
}

三. 大作业总结

通过大作业的练习,熟悉了很多three.js的特性,希望感兴趣的读者也可以自行练习,比如把整个片头动画都做出来什么的。

转载于:https://www.cnblogs.com/dashnowords/p/11234360.html

【带着canvas去流浪(13)】用Three.js制作简易的MARVEL片头动画(下)相关推荐

  1. 【带着canvas去流浪(13)】用Three.js制作简易的MARVEL片头动画(下)#华为云·寻找黑马程序员#

    [摘要] three.js实现的Web 3D字体模型动画 示例代码托管在:http://www.github.com/dashnowords/blogs 有了上一篇基础知识的储备,本节就来制作一下简易 ...

  2. 【带着canvas去流浪(12)】用Three.js制作简易的MARVEL片头动画(上)

    我的github主页:https://github.com/dashnowords 我的新书上架啦,3天即登京东计算机编程语言类排行榜Top1!!!精选30+JavaScript库,从使用方式,设计原 ...

  3. 【带着canvas去流浪(12)】用Three.js制作简易的MARVEL片头动画(上) #华为云·寻找黑马程序员#

    [摘要] 用three.js实现简易的漫威片头动画 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 大作业说明 通读完上一篇博文中提及的教程,觉得 ...

  4. 带着canvas去流浪系列之二 绘制折线图

    [摘要] 用canvasAPI实现echarts简易图表 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI绘制 ...

  5. 带着canvas去流浪系列之六 绘制雷达图

    [摘要] 用canvas原生API实现百度Echarts基本图表. 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvas ...

  6. 【带着canvas去流浪(6)】绘制雷达图

    目录 一. 任务说明 二. 重点提示 三. 示例代码 示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端>原创博文 ...

  7. echarts 雷达图_【带着canvas去流浪】绘制雷达图

    使用原生canvasAPI绘制雷达图.(截图以及数据来自于百度Echarts官方示例库[查看示例链接]). 二. 重点提示 雷达图绘制的看起来并不复杂,无非就是一些路径点的连线,其中的难点都在于一些细 ...

  8. 【带着canvas去流浪(10)】文字烟花

    目录 一. 文字烟花 二. 动画原理 2.1 像素操作 2.2 烟花生成算法 2.3 计时器 示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址 ...

  9. 【带着canvas去流浪(15)】threejs fundamentals翻译系列1-scene graph

    示例代码托管在:http://www.github.com/dashnowords/blogs 博客园地址:<大史住在大前端>原创博文目录 华为云社区地址:[你要的前端打怪升级指南] 目录 ...

  10. 带着canvas去流浪系列之五 绘制K线图

    [摘要] 用canvas原生API实现百度Echarts 示例代码托管在:http://www.github.com/dashnowords/blogs 一. 任务说明 使用原生canvasAPI绘制 ...

最新文章

  1. android状态栏半透明灰色,Android7.0沉浸式状态栏蒙灰问题完美解决
  2. ABAP OO的八大理由
  3. 推荐一个博客,或许给技术流的自己一些启示
  4. 西南大学网络教育学院计算机答案,西南大学网络与继续教育学院课程《数字信号处理》2018年春季大作业机考 答案.doc...
  5. python分词_Python 结巴分词实现关键词抽取分析
  6. Log4j2进阶使用(按大小时间备份日志)
  7. 【Tensorflow深度学习】Tensorflow2.0GPU版极简安装
  8. 需求分析与系统设计读书笔记之五
  9. 开篇-.net与.net framework和C#的关系与区别,历史沿革
  10. 高等数学(同济大学)
  11. 记录:ubuntu安装zlog及使用
  12. 开关电源(DC/DC)和线性电源(LDO低压差线性稳压器)的区别
  13. 2048游戏回顾三:自定义Dialog和ProgressBar
  14. 使用C#开发Excel插件
  15. 名词性从句的时态规则
  16. 不习惯的 Vue3 起步六 の Echarts绘制下钻地图
  17. java象棋打谱系统
  18. 华为“天才少年”的200万年薪里,藏着人力资源管理的下一个10年
  19. C语言中所有,C语言所有关键字.doc
  20. 全球顶尖公司的烧脑面试题

热门文章

  1. Python的Cython在Windows环境下的部署安装
  2. oc 画一个圆弧_弯管半圆弧滑块抽芯结构拆解,3个核心要点
  3. c++ 多线程_python要点-多线程
  4. ubuntu apt 卸载 golang
  5. 安徽省计算机一级PDF,安徽省计算机一级考试试题 .pdf
  6. C++中Lambda函数(匿名函数)
  7. Java 序列化漏洞多到修不完
  8. Spring Boot @PropertySource 加载配置文件、@ImportResource 导入Spring 配置文件
  9. Java SE 随机数生成器 Random
  10. 后台java规范参数_详解Java后端优雅验证参数合法性