本文源代码地址:http://download.csdn.net/detail/jamesplur/9797919

实现任务:能够在前端网页中嵌入3D机房模型并实现基本的交互


3D基本原理

为了实现3D图像的动态展示有三个要点:

  1. 建立三维场景

    三维场景包括三维模型、光源、相机三个部分构成。

    从最简单的情形来说,三维模型由网格(mesh)和材质(material)组成。网格则一般由若干个图元(一般是空间中的三角形)拼接而成。网格表面还要考虑本身的纹理和对光源的反射情况。所以3D模型的数据主要是顶点信息和网格表面材质信息。

    光源就是在空间中人为添加光照信息,例如方向,强度,光色等。没有光源,渲染出来的3D场景将一片漆黑。

    相机相当于场景的一个观察点。相机在建立时就要确定,视角,远平面,近平面,纵横比四个参数。根据这些参数可以确定一个可视区域。3D模型必须在可视区域(view frustum)内。否则将不会被屏幕捕捉。

  1. 将场景以2D的形式显示

    要想将场景以2D的形式显示出来,实际就是将空间中的点映射为平面的像素值。这个过程需要考虑两个关系:

    模型和相机之间的关系:这个变换关系由两个矩阵控制,其中一个矩阵表示了相机所在位置和方向,另一个矩阵控制了从3D到2D的投影参数。模型和相机的关系决定空间中的某一点是否会被渲染。

    光源和材质的关系: 光源和材质的关系决定这一点的像素值会是多少。着色器将会结合该点的材质(包括对光的反射率)和光照强度,判断该点的颜色。

  2. 当3D数据发生改变时,可以近乎无延迟的对2D图像更新渲染

    上述复杂的映射过程,实际是交给着色器来完成的,着色器往往是一种基于gpu的程序(所谓硬件加速)。保证了渲染的低延迟。

浏览器对3D的支持

WEBGL标准的实现,使利用浏览器进行3D绘图成为可能
这里引用wiki百科的一段介绍

WebGL (Web Graphics Library) is a JavaScript API for rendering 3D graphics within any compatible web browser without the use of plug-ins.[2] WebGL is integrated completely into all the web standards of the browser allowing GPU accelerated usage of physics and image processing and effects as part of the web page canvas. WebGL elements can be mixed with other HTML elements and composited with other parts of the page or page background.[3] WebGL programs consist of control code written in JavaScript and shader code that is written in OpenGL Shading Language (GLSL), a language similar to C or C++, and is executed on a computer’s graphics processing unit (GPU). WebGL is designed and maintained by the non-profit Khronos Group.[4]

总结一下要点:

  • 部分浏览器支持(火狐、谷歌),不需要插件
  • OPENGL的web版,提供了js接口,可将3d场景直接绘制到页面元素中(canvas元素)
  • 提供了硬件加速手段,也就是之前所提的着色器,这段着色器由GLSL语言所编写,可以操控显卡使网页的显示更加流畅

实际上利用WEBGL接口进行开发是非常非常吃力的,具体有多吃力可以参考附件代码。
可以看到编写一个旋转的正方体就用了三百行代码。这是开发所不允许的。

VIZI开发引擎简介

提高开发效率有两个要点:

  • 选用一个合适的3D开发引擎:
    由于目前3D开发还没有一个功能全面的的而且被广泛兼容的(兼容这一点更加重要)框架,所以很多公司都给出了自己的解决方案,大多都是收费的。在免费的框架中,three.js是其中最为出色的,它合理的封装了WEBGL的主要部件,使得初学者学习3D开发变成了可能。tween.js则是three.js有力的补充,利用tween.js可以实现一些简单的补间动画。

  • 利用模型软件进行建模:
    用js进行建模可真的是想多了。最合理的方式是利用3Dmaxs或者maya进行建模和一些复杂动画的编辑。再导出到合适的格式中去。这些格式包括obj,dae等。其中dae是功能最为强大的通用场景格式文件,包含了相机、光源、几何体、材质、动画等信息。three.js中提供了这些文件的解析器,将会把这些文件解析为json格式,再进一步转化为three.scene对象。

    这里注意:
    WebGL默认情况下不允许使用本机上的纹理、模型文件的。若想加载外部模型和纹理文件,
    由于同源策略的安全限制从文件系统加载文件会因为安全异常而失败。不过有两个办法可以解决:
    降低浏览器的安全级别
    在本机上建立一个服务器,把外部文件放到该服务器作为网络文件访问
    

所谓开发引擎,便是将接口进行高度的封装抽象,以实现快速的开发。

Vizi是由美国tony parisi编写的3d开发引擎,该引擎基于three.js和tween.js,可以快速实现3d开发所需的基本功能。之后给出实例也是基于tony parisi所编写的例程。

这里简要介绍下VIZI的类所完成的工作:

Viewer类:

在实例化viewer时,会将viewer的容器(一个块状dom元素)传递给它作为显示3d内容的画布。

viewerrun()方法会初始化渲染器(一个封装了webgl着色器的类)并开启循环。

viewerreplacescene()方法会将读取到的场景数据加载到画布中,如果场景数据没有相机和光源的话,该函数还会创建默认的光源和相机。

Object类:

vizi中模型存储的基本数据类型

loader类:

loaderloadscene()方法会根据加载文件的类型自动选择three.js的加载器

picker类:

picker对象可以添加到模型对象的属性中去,并可由addEventListener()方法添加交互事件,如鼠标经过,鼠标点击等

Component类:

component对象可以添加到模型对象的属性中去,并通过tween.js为对象添加简单的补间动画

附录程序使用文档

这里利用vizi引擎,开发了3D机房的一个演示界面

3d机房的模型文件是由maya导出的dae文件,导出插件为opencollada(不知道为什么,3dsmax导出的dae文件是不能用的)

该程序将vizi的一些类都封装起来,提供了所需要的一些接口函数和回调函数。下面是程序详细解释:

1. 文件结构

  • 3d 是模型测试页面
  • Src中存放3d机房的源文件3d.js
  • Libs中存放相关库文件
  • Images中存放图片
  • Css中存放样式表

2. 建立机房

首先建立一个容器:

    <div id="container"></div>

然后实例化threedroom类,并将container元素作为参数传递。其余的参数为可能用到的回调函数

var container = document.getElementById("container");threedroom = new ThreeDroom({ container : container,loadCallback : onLoadComplete,loadProgressCallback : onLoadProgress,mouseOverCallback : onMouseOver,mouseOutCallback : onMouseOut,mouseUpCallback : onMouseUp,});threedroom.go();

threedroom.go()函数实例化了viewer类,加载了场景文件,并开始了渲染循环

ThreeDroom.prototype.go = function() {this.viewer = new Vizi.Viewer({ container : this.container, showGrid : true});this.loadURL(ThreeDroom.URL);this.viewer.run();
}

其中loadURL为加载模型的函数,同时也为添加了两个监听事件,当加载完成之后会调用onLoadComplete()这个函数(onLoadProgress负责显示加载的进度)

ThreeDroom.prototype.loadURL = function(url) {var that = this;var loader = new Vizi.Loader;loader.addEventListener("loaded", function(data) { that.onLoadComplete(data, loadStartTime); }); loader.addEventListener("progress", function(progress) { that.onLoadProgress(progress); }); var loadStartTime = Date.now();loader.loadScene(url);
}

3. 添加鼠标交互

onLoadComplete()除了将场景数据交给viewer之外,还为场景中的对象添加了交互事件:

ThreeDroom.prototype.onLoadComplete = function(data, loadStartTime)
{var that = this;ThreeDroom.Scene = data.scene;this.viewer.replaceScene(data);ThreeDroom.Scene.map(/^bottom_Mesh(.*)/,function(o){console.log("found node!");var highlight=new Vizi.HighlightBehavior({highlightColor:0x88eeff});o.addComponent(highlight);var picker = new Vizi.Picker;picker.addEventListener("mouseover", function (event) {that.onMouseOver("over", event);if(!that.warningstatus){highlight.on();}});picker.addEventListener("mouseout", function (event) {that.onMouseOut("out", event);if(!that.warningstatus){highlight.off();}});picker.addEventListener("mouseup", function (event) {that.onMouseUp("up", event);});o.addComponent(picker);});

首先,添加场景数据之后,所有的3d对象数据都存储在ThreeDroom.Scene中。

map()是一个遍历函数,它会找到对象名称符合正则表达式的对象,并添加鼠标的交互事件。

 ThreeDroom.Scene.map(/这里添加正则表达式/,function(这里添加响应事件))

鼠标交互事件会触发对应的响应函数,这个响应函数定义在3d.js里:

ThreeDroom.prototype.onMouseOver = function(what, event) {if (this.mouseOverCallback)this.mouseOverCallback(what, event);}ThreeDroom.prototype.onMouseOut = function(what, event) {if (this.mouseOutCallback)this.mouseOutCallback(what, event);
}ThreeDroom.prototype.onMouseUp = function(what, event) {if (this.mouseUpCallback)this.mouseUpCallback(what, event);
}

该函数的作用是回调用主页面的处理函数,应在此添加事件
其中可通过what参数来区分是由那个元素触发了事件,event是jquery所定义的事件标记

function onMouseOver(what, event) {console.log("Mouse over");alert("在这里填充响应事件!");
}function onMouseOut(what, event) {console.log("Mouse out");alert("在这里填充响应事件!");}
function onMouseUp(what, event) {console.log("Mouse up");alert("在这里填充响应事件!");
}

总结来说,要为添加鼠标交互事件,首先要在onloadcomplete函数中,为指定的3d对象添加picker

然后在页面中的回调函数中利用what参数分辨是哪个元素产生的事件

4. 添加报警动画

警报动画的接口函数为warningon与warningoff,参数为target。也就是所需要添加警报动画的对象的名称的正则表达式,warningon代表开启警报,warningoff代表关闭警报。需要注意只有有材质的子对象才可以添加报警动画。组对象是不能添加的。

function warningon() {threedroom.warningon(/^bottom_Mesh(.*)/);
}function warningoff() {threedroom.warningoff(/^bottom_Mesh(.*)/);
}

3D机房前端学习笔记相关推荐

  1. 前端学习笔记之CSS3基础语法与盒模型(二)

    前端学习笔记之 CSS3基础语法与盒模型 CSS3简介 CSS(cascading style sheet,层叠式样式表)是用来给HTML标签添加样式的语言 CSS3是CSS的最新版本,增加了大量的样 ...

  2. 2017-2-15从0开始前端学习笔记(HTML)-图片-表格-表单

    2017-2-15从0开始前端学习笔记-图片-表格-表单 标签 图片 图片<img src="#" alt="文本说明 不能加载图片时显示" title= ...

  3. 前端学习笔记:Bootstrap框架入门

    前端学习笔记:Bootstrap框架入门 一.Bootstrap概述 1.基本信息 ​Bootstrap,来自 Twitter,是目前很受欢迎的前端框架.Bootstrap 是基于 HTML.CSS. ...

  4. 【前端学习笔记】JavaScript + jQuery + Vue.js + Element-UI

    前端学习笔记 JavaScript jQuery Vue.js Element-UI Java 后端部分的笔记:Java 后端笔记 JavaScript 基础语法(数据类型.字符串.数组.对象.Map ...

  5. 前端学习笔记(this)

    前端学习笔记(this) 在函数中调用 在函数中直接调用 函数作为对象的方法进行调用 不在函数中调用 es6的箭头函数 在函数中调用 在函数中直接调用 1 严格模式和非严格模式中this 严格模式下t ...

  6. 前端学习笔记(js基础知识)

    前端学习笔记(js基础知识) JavaScript 输出 JavaScript 数据类型 常见的HTML事件 DOM 冒泡与捕获 流程控制语句 for..in 计时器 let,var,const的区别 ...

  7. 前端学习笔记:省市区三级联动

    前端学习笔记:省市区三级联动 一.数据库 sql表是自关联的表. 表名:province_city_district 字段: id:区域自身的id pid:区域的父级id name:区域自身的名字 二 ...

  8. 前端学习笔记36-水平方向的布局

    前端学习笔记36-水平方向的布局 上一节中的margin-right是没用的,为什么呢? 子元素的七个水平布局设置: margin-left border-left padding-left widt ...

  9. web前端学习笔记(最新)

    web前端学习笔记 大家好,我是链表哥,新的学期,新的学习,我会为您展示我的学习进程. 一:什么是WEB前端? 所谓的Web前端指的是用户所能接触到的,并服务于用户的前沿端口,经我们程序员编辑修饰后展 ...

最新文章

  1. jQuery 图片剪裁插件初探之 Jcrop
  2. MySQL-事务管理(基础)
  3. Eclipse上安装GIT插件EGit及使用
  4. BAT解密:互联网技术发展之路(5)- 开发层技术剖析
  5. 在线音乐用户寄望用爱发电,资本不愿无米之炊
  6. python数据类型怎么定义_零基础如何学好Python 之int 数字整型类型 定义int()范围大小转换...
  7. 金士顿固态硬盘计算机如何识别,金士顿SV300 SF2281固态硬盘SSD不认盘开卡修复教程...
  8. 我想成为计算机专业第一,我对计算机专业学生的忠告。
  9. 软件缺陷分析—软件测试之犯罪心理学
  10. Win 7 SSDP 组播 引发 局域网 QQ掉线 分析
  11. dht11 java_树莓派使用DHT11温湿度传感器
  12. Ceph 网络模块(1) - 网络模块基本结构
  13. oracle imp加快速度,加快IMP速度
  14. linux内核Ethernet以太网卡驱动收发数据过程
  15. 崩坏3服务器修改水晶数量,崩坏3半年不氪金能攒多少水晶 半积年攒水晶数量详情...
  16. 华为 网络 链路捆绑
  17. Android Studio配置优化最全详解
  18. 电脑屏幕亮度能否自动调节
  19. 光伏电站远程监控应用方案
  20. 新网的虚拟主机连接mysql_虚拟主机怎么导入数据库

热门文章

  1. Oracle 一种简单粗暴的办法解析XML文件的例子
  2. 中国农垦周先标谋定品牌-万祥军:对话农民丰收节交易会
  3. 树莓派入门(MacBook本)
  4. c语言595驱动数码管,74hc595驱动4位数码管程序解析 - 74hc595驱动4位数码管电路连接图及程序解析...
  5. 经典linux c程序,经典 c 程序 100 例
  6. Vue Dhtmlxgantt甘特图/横道图 baselines 含(计划、实际时间对比)树形实例实现及部分扩展
  7. 格林函数一阶常微分方程方法介绍
  8. 计算机主机箱内的主要硬件有,电脑的基本硬件包括哪些
  9. 前端——IndexedDB
  10. 小心被钓鱼!移动物联卡怎么购买才安全!