(1)首先来看一下demo的实际效果:
通过观察上下两张图,我们发现风车的黄色扇叶发生了变化,对,没错,今天的案例就是做一个不断旋转的风车。
(2)接下来,我们来介绍实现该demo涉及到的知识点:
a.风车的组成部分是:黄色扇叶、红色柱子,这两个部分是采用obj建模的方式构建出来(建模知识稍等在介绍),建模的部分由美工完成,我们只需要把建模的文件加载进来尽可以了;
b.由于风车是有独立的两个部分构建的,所以我们还要把这两部分组合在一起,组成一个整体的风车模型。当然有人会说,可以使用sethost()互相绑定就可以,是的,这样做也可以的,但是这样做会产生一个问题:当我想要让扇叶转动时,柱子也会跟着旋转。那么问题来了,我们采用什么方法呢,是的,我们采用:模型组合。
c.最后:采用interval定时器,定时改变扇叶的rotation的属性,这样,扇叶就会出现上述的动画效果了。(当然我们也可以用调度的方式实现。以后会说)
(3)HT知识点拓展:
a.首先,我们来介绍下obj部分的知识内容:
(也可查阅官网obj手册:http://www.hightopo.com/guide/guide/plugin/obj/ht-obj-guide.html)
(3.1)什么是obj格式?
简单说:就是后缀名分别:.obj 和.mtl 资源文件。在新建项目上引入就好了。如图:(该图非本demo的资源图。)
我们更多打交道的是.mtl资源文件(PS:截止到本小白接触学习的时间点为止,所碰到的几个demo里,都有对mtl文件的深入了解。),所以,非常有必要了解一下.mtl文件的一些信息。
***.mtl文件介绍:
该资源文件描述是贴图图片以及颜色等材质信息。聪明的你一定发现了我们刚刚的关于资源文件的截图了,看到有.jpg和.png的两个图片文件了,对,是的,该图片就是被.mtl引用的(所以呢,如果在构建项目的时候,发现模型构建出来了,但是好像样式有些不对,也许就是你没有把图片资源也导入哦)。
好了,具体的介绍,请看官网的截图:
ps:看到图中红色边框框选出来的部分了吗?对,这个东西在接下来的文章里,会告诉你这个的坑。(当然,如果你对obj足够了解的话,请忽略上述ps)。
(3.2)什么是模型组合:
有兴趣的,可以查阅官网(modeling建模手册http://www.hightopo.com/guide/guide/plugin/modeling/ht-modeling-guide.html)
其实呢,在官网已经介绍的很详细,我就不重复了,我就挑项目中实际上需要关注的地方:
第一点:通过ht.Default.setShape3dModel(name, model)函数,可注册自定义3D模型;
第二点:
vs:顶点坐标数组
is:顶点索引数组
(4)接下来是具体代码的实现部分
(4.1)首先引入HT组件文件:
为什么要引入这两个文件,这两个文件的作用是什么?
首先:第一个文件:是核心类库文件,包括:数据模型,数表通用组件,2D拓扑组件,矢量以及3D渲染引擎等核心组件。
第二个文件:导入OBJ格式功能需要引入ht-obj.js的插件扩展包;(在本例中不需要引入。)
接下来,我们来看看一些基础的代码:几乎涉及到 3D的的场景,这些代码都大同小异:
//数据容器(datamodel手册)
dataModel = new ht.DataModel();
//定义3d渲染引擎组件(3d手册)
g3d = new ht.graph3d.Graph3dView(dataModel);
view =g3d.getView();
view.className = 'main';
document.body.appendChild(view);
//监听图元变化,但是又不能在图元立马改变的时候就更新,而是每隔一段时
//间异步刷新
window.addEventListener('resize', function(e) {
g3d.invalidate();
}, false);
//设置海平面
g3d.setGridVisible(true);
//设置可编辑为true
g3d.setEditable(true);
//设置观察视觉
g3d.setEye([-82, 169, 327]);
//决定目标中心点
g3d.setCenter([-8, 48, 8]);
//其实像这些属性,都不用自己来写的,大多数采用默认的就可以用了
getEye()|setEye([x, y, z]),决定眼睛(或Camera)所在位置,默认值为[0, 300, 1000]
getCenter()|setCenter([x, y, z]),决定目标中心点(或Target)所在位置,默认值为[0, 0, 0]
getUp()|setUp([x, y, z]),决定摄像头正上方向,该参数一般较少改动,默认值为[0, 1, 0]
getNear()|setNear(near),决定近端截面位置,默认值为10
getFar()|setFar(far),决定远端截面位置,默认值为10000
(4.2)把描述风扇和扇叶的顶点坐标和顶点索引信息加载进来(由于文件过大,本例只截取部分只说明原理)。
var windmill_base_positions = [0, -0.3600277900695801, 9.063931465148926, 0.34631508588790894, 0.9793881177902222, 8.812317848205566, 0, 0.9793879985809326, 9.063931465148926, 0.34631508588790894];
var windmill_base_indices = [0, 1, 2, 3, 4, 5, 6, 7];
var windmill_blades_positions = [-0.7316640019416809, -0.560940146446228, -0.15819978713989258, -0.4289890229701996, -0.4811832904815674, -0.03272248059511185, -0.42898908257484436];
var windmill_blades_indices = [0, 1, 2, 3, 4, 5, 6, 7];
//注册3d柱子模型:
ht.Default.setShape3dModel('zhuzi', {
vs: windmill_base_positions_new,
is: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
});
//注册3d扇叶模型:
ht.Default.setShape3dModel('fengshan', {
vs: windmill_blades_positions_new,
is: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
});
//组合模型:
ht.Default.setShape3dModel('zuhe', [{
shape3d: 'zhuzi',
color:'red'
}, {
shape3d: 'fengshan',
t3: [0, 175 / 20, 0],
r3: {
func: function(data) {
return [0,0,data.a('angle')];//获取值显示。
}
},
color:'yellow'
}]);
/*这里我们来解释func。由于HT的独特设计,任何属性都可以通过对象方法func,来进行属性值得改变,那么这里又引申出dataModel了,因为不同view是共用一个dataModel的,所以,所有data的属性都可以进行关联。而func实际上是Data对象调用firePropertyChange(property, oldValue, newValue)触发属性变化从而派发属性变化事件,*/
通过以上代码,我们已经将JSON模型对象注册到系统。接下来通过node.setStyle('shape3d', 'zuhe')//设置需要显示为该模型效果的图元属性即可。如下代码:
var node = new ht.Node();
node.s3(10,10,10);
node.s({
'shape3d': 'zuhe',
});
dataModel.add(node);
/*
在nodo设置大小,width,height,tall值一样的,具体原因,我们下一章节在进行详细介绍。
*/
//通过interval改变风扇的angle值,从而从风扇动起来
var angle = -Math.PI / 2;
setInterval(function() {
angle += 0.1;
node.a('angle', angle);
}, 10);