您的位置:首页 > Web前端 > JavaScript

three.js自学之旅(5)—— 辅助对象的使用、扩展一个新的基础方法调整对象参数

2018-01-17 15:04 986 查看
本来想说这一章节研究一下各种模型的,但我觉得应该将这个辅助工具单独拿出来玩一下,后面遇到难以理解的都可以开辅助,包括之前的一些可以开辅助的(估计写这个插件的人考虑到了美帝人民普遍数学比较差,空间想象能力不够用)

聚光灯和阴影那一章由于数据计算比较复杂,我正好又是个数学文盲,所以很多东西推荐大家自己体验一下。上一章说到在研究聚光光源的时候遇到一些弃用的方法,如:

light.shadowCameraVisible = true;//开启聚光灯源的辅助,新版本被弃用

本来想开个辅助的,结果上网查了一下弃用了(bi~),今天打开的时候由于F12一直开着,竟然发现控制台输出一句话
THREE.Light: .shadowCameraVisible has been removed. Use new THREE.CameraHelper( light.shadow.camera ) instead.

以前我对于这种黄不溜秋的字是一个标点符号都不看的,因为我英语也不咋地,这次我竟然发现能看懂,就勉为其难的看了一眼,又勉为其难的去官方文档查了一下,后来发现,他(MD)竟然把这么好用的辅助工具写在那么后面!!!

既然找到了,就把辅助开起来,顺便写一个通用的方法,通过改变参数的数值,来具体观察参数对于对象的影响。

//开一下辅助
var spotLightHelper = new THREE.SpotLightHelper( light );
scene.add( spotLightHelper );




瞬间清晰起来了!

接下来扩展一个基础方法,并将它写到辅助工具对象里去,以后会将之前的(如相机旋转,滚轮控制视角),或者以后想到的各种辅助工具都放到这个辅助工具对象中去。先看代码,你可以先复制粘贴,再看后面对这个方法的详解。

//通用方法调整参数
var  assistantTool = {
modifyParameters:function(obj,parArr){
for(var i = 0;i<parArr.length;i++) {
var index = i;
var now = obj[parArr[index].par];
$("body").append("<span class='wz'>"+parArr[index].par+":</span></span><button index='"+i+"' class='buttonadd'>+</button><span class='sz'>"+ now +"</span></span><button index='"+i+"' class='buttonsubduction'>-</button>");
$(".buttonadd").eq(i).bind("click",function(ev){
ev .stopPropagation();
var _index = $(this).attr("index");
if(obj[parArr[_index].par] < parArr[_index].max){
obj[parArr[_index].par] = floatObj.add($(".sz").eq(_index).html(),parArr[_index].every);
}
$(".sz").eq(_index).html(obj[parArr[_index].par]);
})
$(".buttonsubduction").eq(i).bind("click",function(ev){
ev .stopPropagation();
var _index = $(this).attr("index");
if(obj[parArr[_index].par] > parArr[_index].min){
obj[parArr[_index].par] = floatObj.subtract($(".sz").eq(_index).html(),parArr[_index].every);
}
$(".sz").eq(_index).html(obj[parArr[_index].par]);
})
$(".buttonsubduction").eq(i).css("top",50*i);
$(".buttonadd").eq(i).css("top",50*i);
$(".wz").eq(i).css("top",50*i);
$(".sz").eq(i).css("top",50*i);
}
}
}
//调用调整参数的方法,并填写必要的参数
assistantTool.modifyParameters(light,[
{
par:"intensity",
max:2,
min:0,
every:0.1
}, {
par:"distance",
max:400,
min:10,
every:10
},{
par:"angle",
max:Math.PI/2,
min:Math.PI/12,
every:0.1
},{
par:"penumbra",
max:1,
min:0,
every:0.1
},{
par:"decay",
max:4,
min:-1,
every:0.1
}
]);

先看一下最终的效果,注意右上角增加的一些辅助工具(忽略新增的黄色线)



方法的具体实现原理可以不必探究,还有不完善的地方会在后续的版本中改进(如定位问题),先说明一下要调用这个方法的一些参数说明
assistantTool.modifyParameters(obj,parArr)

第一个参数,只需要将你想改变的对象传进去即可,如light、cube等等,第二个参数是一个json数组,包括四个要填的参数,

{

par:你需要改变的对象的某个属性名称,

max:可以设置的最大值,

min:可以设置的最小值,

every:每次要增加/减少的数值

},

注意!这些参数都是必填的,因为比较懒,没有给他设置默认值。

最后,需要说明很重要的一点,在使用辅助工具的时候,当你配合着我写的函数去改变比如说light的某些值得时候,辅助对象本身也会发生变化,但是,你如果没有刷新这个对象的话,他就一直傻傻的保持在第一帧的状态,所以,一定要在渲染函数里面加上一句话

shadowCameraHelper.update();
spotLightHelper.update();
//辅助对象.update()

有兴趣的同学可以去玩一下官网的一些辅助对象,说实话,中文文档的并不全,比如我开的
new THREE.CameraHelper( light.shadow.camera );

他就没有(说明)。

所以学英语没坏处(此处应有一波雅思托福广告)。尽量看英文文档吧,实在看不懂对照着看。

下一章开始玩模型

补一下css

canvas{
width: 100%;
height:100%;
position: absolute;
left:0;
}
.buttonadd{
z-index:100;
width: 40px;
height:40px;
position: absolute;
right:0;
}
.buttonsubduction{
z-index:100;
width: 40px;
height:40px;
position: absolute;
right:101px;
}
.wz{
z-index:100;
position: absolute;
right:142px;
line-height: 40px;
}
.sz{
z-index:100;
position: absolute;
right:41px;
line-height: 40px;
text-align: center;
width: 60px;
}

再补一个小姿势,js对于浮点型数的计算支持很差!!连小学生水平都米有,不信你让他算1.9-0.1竟然=1.799999998,具体原因是跟计算机计算小数的时候会转化成二进制,而很多小数转换成二进制的时候精度出了问题,所以上网找了个通用的解决这个问题,上代码。

var floatObj = function() {

/*
* 判断obj是否为一个整数
*/
function isInteger(obj) {
return Math.floor(obj) === obj
}

/*
* 将一个浮点数转成整数,返回整数和倍数。如 3.14 > 314,倍数是 100
* @pa
4000
ram floatNum {number} 小数
* @return {object}
* {times:100, num: 314}
*/
function toInteger(floatNum) {
var ret = {times: 1, num: 0}
if (isInteger(floatNum)) {
ret.num = floatNum
return ret
}
var strfi = floatNum + ''
var dotPos = strfi.indexOf('.')
var len = strfi.substr(dotPos+1).length
var times = Math.pow(10, len)
var intNum = parseInt(floatNum * times + 0.5, 10)
ret.times = times
ret.num = intNum
return ret
}

/*
* 核心方法,实现加减乘除运算,确保不丢失精度
* 思路:把小数放大为整数(乘),进行算术运算,再缩小为小数(除)
*
* @param a {number} 运算数1
* @param b {number} 运算数2
* @param digits {number} 精度,保留的小数点数,比如 2, 即保留为两位小数
* @param op {string} 运算类型,有加减乘除(add/subtract/multiply/divide)
*
*/
function operation(a, b, digits, op) {
var o1 = toInteger(a)
var o2 = toInteger(b)
var n1 = o1.num
var n2 = o2.num
var t1 = o1.times
var t2 = o2.times
var max = t1 > t2 ? t1 : t2
var result = null
switch (op) {
case 'add':
if (t1 === t2) { // 两个小数位数相同
result = n1 + n2
} else if (t1 > t2) { // o1 小数位 大于 o2
result = n1 + n2 * (t1 / t2)
} else { // o1 小数位 小于 o2
result = n1 * (t2 / t1) + n2
}
return result / max
case 'subtract':
if (t1 === t2) {
result = n1 - n2
} else if (t1 > t2) {
result = n1 - n2 * (t1 / t2)
} else {
result = n1 * (t2 / t1) - n2
}
return result / max
case 'multiply':
result = (n1 * n2) / (t1 * t2)
return result
case 'divide':
result = (n1 / n2) * (t2 / t1)
return result
}
}

// 加减乘除的四个接口
function add(a, b, digits) {
return operation(a, b, digits, 'add')
}
function subtract(a, b, digits) {
return operation(a, b, digits, 'subtract')
}
function multiply(a, b, digits) {
return operation(a, b, digits, 'multiply')
}
function divide(a, b, digits) {
return operation(a, b, digits, 'divide')
}

// exports
return {
add: add,
subtract: subtract,
multiply: multiply,
divide: divide
}
}();
//toFixed的修复如下

// toFixed 修复
function toFixed(num, s) {
var times = Math.pow(10, s)
var des = num * times + 0.5
des = parseInt(des, 10) / times
return des + ''
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐