构建 3D 的场景除了创建模型,对模型设置颜色和贴图外,还需要有灯光的效果才能更逼真的反映真实世界的场景。这个例子我觉得既美观又代表性很强,所以拿出来给大家分享一下。

本例地址:http://www.hightopo.com/guide/guide/core/lighting/examples/example_flowing.html

例子动图:

上面场景中主要的知识点包括:3D 灯光以及 3D 模型的流动。

  1. 场景搭建
    整个场景中包括 2D 场景(也就是鹰眼部分)以及 3D 场景:

    dm = new ht.DataModel();
    g3d = new ht.graph3d.Graph3dView(dm);
    g3d.setGridVisible(true);//指定是否显示网格
    g3d.setGridColor('#74AADA');//指定网格线颜色
    g3d.getView().className = 'main';//设置类名
    document.body.appendChild(g3d.getView());//将3d组件添加进body体中
    window.addEventListener('resize', function(e) {
    g3d.invalidate();
    }, false); g2d = new ht.graph.GraphView(dm);
    g2d.setAutoScrollZone(-1);//设置自动滚动区域大小,当鼠标距离拓扑边缘小于这个值时,拓扑自动滚动(调整translateX或translateY)
    g2d.getView().className = 'g2d';
    g2d.setEditable(true);//设置拓扑中的图元是否可编辑
    document.body.appendChild(g2d.getView());
    ht.Default.callLater(g2d.fitContent, g2d, [true, 50, true]);//获取全局下一个id编号 g3d.setHeadlightRange(2000);//灯影响范围,默认为0代表可照射到无穷远处,如果设置了值则光照射效果随物体远离光影而衰减

    所有HT组件最根层都为一个 div 组件,可通过组件的 getView() 函数获得,这里就是利用这种方法将 3D 和 2D 组件添加进 body 体中的。只要 3D 和 2D 共用同一个数据容器,那么数据容器中的图元都是共用的,也就是说只要我们排布好 2D 或者 3D 中的图元,那么剩下的那个组件中图元的排布以及样式都是根据排布好的组件来排布的。

  2. 添加灯光
    场景中出现的灯光,除了会旋转的灯光,还有就是两个静止的红灯和黄灯,当旋转的灯光照向其他地方的时候看得比较清楚:
    redLight = new ht.Light();//灯类
    redLight.p3(0, 0, -175);//实例变量的位置
    redLight.s({
    'light.color': 'red',//灯光颜色
    'light.range': 400//灯影响范围,默认为0代表可照射到无穷远处,如果设置了值则光照射效果随物体远离光影而衰减
    });
    dm.add(redLight);//将实例变量添加进数据容量中 rotateLight = new ht.Light();
    rotateLight.s({
    'light.color': 'green',
    'light.type': 'spot'//默认为point点光灯,可设置为spot聚光灯,以及directional的方向光类型
    });
    dm.add(rotateLight); yellowLight = new ht.Light();
    yellowLight.p3(0, 0, 60);
    yellowLight.s({
    'light.color': 'yellow',
    'light.range': 200
    });
    dm.add(yellowLight);
  3. 场景中模型的构建
    首先是地板的创建,地板是一个圆形的地板,通过设置样式 shape3d 为 cylinder,剩下的只要设置好大小、位置以及样式等等即可:
    floor = new ht.Node();//Node 节点类
    floor.s3(1100, 10, 1100);
    floor.p3(0, -100, -110);
    floor.s({
    'shape3d': 'cylinder',//设置 3D 模型为圆形
    'shape3d.side': 100,//默认值为0,决定3d图形显示为几边型,为0时显示为平滑的曲面效果
    'shape3d.color': 'white',//默认值为#3498DB,3d图形整体颜色
    '3d.selectable': false,//默认值为true,控制图元在Graph3dView上是否可选中
    '2d.visible': false//默认值为true,控制图元在GraphView上是否可见
    });
    dm.add(floor);

    接着添加地板外围的 8 根圆柱:

    for(var i=0; i<8; i++){
    var angle = Math.PI*2*i/8;
    pillar = new ht.Node();
    pillar.s({
    'shape3d': 'cylinder',
    'shape3d.color': 'white',
    'shape': 'circle',//多边形类型图元,为空时显示为图片
    'shape.background': 'gray'//多边形类型图元背景
    });
    pillar.s3(50, 180, 50);
    pillar.p3(Math.cos(angle)*480, 0, -110+Math.sin(angle)*480);
    dm.add(pillar);
    }

    还有就是这些“箭头”作为贴图的模型,各种各样的,这里我就只解析一个,比较靠前的“波动”部分,具体的多边形的描述请参考形状手册

    其中 image 的部分是通过 ht.Default.setImage 函数来创建的名为 arrow 的贴图。

    shape3 = new ht.Shape();//多边形类
    dm.add(shape3);
    shape3.setTall(60);//设置高度
    shape3.setThickness(0);//设置厚度
    shape3.s({//设置样式
    'shape.background': null,
    'shape.border.width': 10,//多边形类型图元边框宽度
    'shape.border.color': 'blue', 'all.visible': false,//六面是否可见
    'front.visible': true,
    'front.blend': 'blue',//前面染色颜色
    'front.reverse.flip': true,//前面的反面是否显示正面的内容
    'front.image': 'arrow',//前面贴图
    'front.uv.scale': [16, 3]//前面贴图的uv缩放,格式为[3,2]
    });
    shape3.setPoints([//设置点数组
    {x: 0, y: 0},
    {x: 25, y: -25},
    {x: 50, y: 0},
    {x: 75, y: 25},
    {x: 100, y: 0},
    {x: 125, y: -25},
    {x: 150, y: 0},
    {x: 175, y: 25},
    {x: 200, y: 0}
    ]);
    shape3.setSegments([//描述点连接样式
    1, // moveTo
    3, // quadraticCurveTo
    3, // quadraticCurveTo
    3, // quadraticCurveTo
    3 // quadraticCurveTo
    ]);
    shape3.p3(-100, 0, 100);
    shape3.setRotationZ(-Math.PI/2);//设置图元在3D拓扑中沿z轴的旋转角度(弧度制)
  4. 设置定时器使各个模型中的图片“流动”以及旋转灯光的旋转
    offset = 0;
    angle = 0;
    setInterval(function(){
    angle += Math.PI/50;
    rotateLight.p3(400*Math.cos(angle), 70, -110+400*Math.sin(angle));//设置旋转灯光的坐标 offset += 0.1;
    uvOffset = [offset, 0];
    shape1.s({
    'front.uv.offset': uvOffset//前面贴图的uv缩放,格式为[3,2]
    });
    shape2.s({
    'front.uv.offset': uvOffset
    });
    shape3.s({
    'front.uv.offset': uvOffset
    });
    shape4.s({
    'front.uv.offset': uvOffset
    });
    shape5.s({
    'shape3d.uv.offset': uvOffset,//决定3d图形整体贴图的uv缩放,格式为[3,2]
    'shape3d.top.uv.offset': uvOffset,//决定3d图形顶面贴图的uv缩放,格式为[3,2]
    'shape3d.bottom.uv.offset': uvOffset//决定3d图形底面贴图的uv缩放,格式为[3,2]
    });
    cylinder.s({
    'shape3d.uv.offset': uvOffset
    });
    torus.s({
    'shape3d.uv.offset': uvOffset
    });
    }, 200);

    整个例子结束,感觉就是“小代码大效果”,代码量少而且简单,效果又非常不错,大家有兴趣可以去官网或者手册中查看其它的例子。

基于 HTML5 WebGL 的 3D 场景中的灯光效果的更多相关文章

  1. 基于 HTML5 WebGL 的 3D 风机 Web 组态工业互联网应用

    基于 HTML5 WebGL 的 3D 风机 Web 组态工业互联网应用 前言 在目前大数据时代背景之下,数据可视化的需求也变得越来越庞大,在数据可视化的背景之下,通过智能机器间的链接并最终将人机链接 ...

  2. 基于 HTML5 + WebGL 的 3D 可视化挖掘机

    前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...

  3. 基于 HTML5 + WebGL 实现 3D 可视化地铁系统

    前言 工业互联网,物联网,可视化等名词在我们现在信息化的大背景下已经是耳熟能详,日常生活的交通,出行,吃穿等可能都可以用信息化的方式来为我们表达,在传统的可视化监控领域,一般都是基于 Web SCAD ...

  4. 基于 HTML5 + WebGL 实现 3D 挖掘机系统

    前言 在工业互联网以及物联网的影响下,人们对于机械的管理,机械的可视化,机械的操作可视化提出了更高的要求.如何在一个系统中完整的显示机械的运行情况,机械的运行轨迹,或者机械的机械动作显得尤为的重要,因 ...

  5. 基于 HTML5 WebGL 构建 3D 智能数字化城市全景

    前言 自 2011 年我国城镇化率首次突破 50% 以来,<新型城镇化发展规划>将智慧城市列为我国城市发展的三大目标之一,并提出到 2020 年,建成一批特色鲜明的智慧城市.截至现今,全国 ...

  6. 基于 HTML5 WebGL 的 3D 智慧隧道漫游巡检

    前言 这次为大家展示的是通过 HT for Web 灵活的图型化编辑工具打造的智慧隧道监控系统.通过 HTML5 技术实现了桌面和移动端的跨平台性,同时现实了可视化运维. 这次主要跟大家分享里面的漫游 ...

  7. 基于 HTML5 WebGL 的 3D 仓储管理系统

    仓储管理系统(WMS)是一个实时的计算机软件系统,它能够按照运作的业务规则和运算法则,对信息.资源.行为.存货和分销运作进行更完美地管理,使其最大化满足有效产出和精确性的要求.从财务软件.进销存软件C ...

  8. 基于 HTML5 WebGL 的 3D 机房

    前言 用 WebGL 渲染的 3D 机房现在也不是什么新鲜事儿了,这篇文章的主要目的是说明一下,3D 机房中的 eye 和 center 的问题,刚好在项目中用上了,好生思考了一番,最终觉得这个例子最 ...

  9. 基于 HTML5 + WebGL 的3D无人机 展示

    前言 近年来,无人机的发展越发迅速,既可民用于航拍,又可军用于侦察,涉及行业广泛,也被称为“会飞的照相机”.但作为军事使用,无人机的各项性能要求更加严格.重要.本系统则是通过 Hightopo 的   ...

随机推荐

  1. jquery 动态创建的元素,绑定事件无效之解决方法

    今天遇到一个问题,动态创建的元素,绑定事件无效,如下: js 代码如下: var OaddX = $('.detright div.duibi div.duibox ul li span'); // ...

  2. Docker 使用教程

    概括  Docker与传统虚拟机的区别 与传统虚拟机的区别  Docker的安装 的安装  Docker daemon , client , containerd  镜像与容器操作  容器运 ...

  3. 魔术常量(Magic constants)

    魔术常量(Magic constants) PHP中的常量大部分都是不变的,但是有8个常量会随着他们所在代码位置的变化而变化,这8个常量被称为魔术常量. __LINE__,文件中的当前行号 __FIL ...

  4. Shell 初步学习

    Shell 概述 Shell:Linux命令解释器 脚本执行方式 chmod 755 脚本名:赋权限(调用必须显示的使用绝对路径或相对路径) bash 脚本名:通过Bash调用执行脚本 命令别名 al ...

  5. 组件嵌套时报:Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.

    在组件嵌套的过程中,报了一个错误: 这里报错的原因是:vue的组件(模板)只能有一个根节点,即.vue文件中的<template>标签下只能有一个子元素. 因此,建议大家在写.vue组件的 ...

  6. 【Keras】从两个实际任务掌握图像分类

    我们一般用深度学习做图片分类的入门教材都是MNIST或者CIFAR-10,因为数据都是别人准备好的,有的甚至是一个函数就把所有数据都load进来了,所以跑起来都很简单,但是跑完了,好像自己还没掌握图片 ...

  7. PHP递归解决兔子问题,面试必备

    接到面试通知辗转反侧,一直在默念明天改如何介绍自己的项目经验等.早早的起床,洗漱,把自己的总结的问题自问自答了一些.匆匆吃了早饭,挤进让人面目狰狞的地铁,此时什么都不顾,只盼着赶紧下地铁.终于提前半小 ...

  8. Python爬虫学习之使用beautifulsoup爬取招聘网站信息

    菜鸟一只,也是在尝试并学习和摸索爬虫相关知识. 1.首先分析要爬取页面结构.可以看到一列搜索的结果,现在需要得到每一个链接,然后才能爬取对应页面. 关键代码思路如下: html = getHtml(& ...

  9. 网络基础之 OSI七层模型

    OSI七层模型模型图如下: 前三层(应用层,表示层,会话层)=>给用户提供服务. 后四层(传输层,网络层,数据链路层,物理层)=>数据传递提供服务. 其中 数据链路层中MAC地址负责局域网 ...

  10. Winform开发中如何将数据库字段绑定到ComboBox控件

    最近开始自己动手写一个财务分析软件,由于自己也是刚学.Net不久,所以自己写的的时候遇到了很多问题,希望通过博客把一些印象深刻的问题记录下来. Winform开发中如何将数据库字段绑定到ComboBo ...