同时为了开发者和使用者的方便,我在这里提供记分板命名规范。
记分板名称:<函数名>_<参数名>_<下标>
例子:abs_arg_0
函数名即是使用此记分板的函数的名称,参数名代表这个记分板的作用,下标在此参数名不止一个的时候防止冲突。
在此定死参数名类型:arg, out和tmp
※ arg即输入,out为输出,tmp是在计算过程中需要处理到的临时量。
在我们的规范中,输入的arg不会因计算改变。调用者只允许写入arg读取out,tmp不允许外部函数或者调用者操作。
我们的函数放置位置和命名也是有规范的
- 所有函数必须存在于math命名空间内
- math空间下存在函数的子目录,每个子目录内有与目录同名的.mcfunction文件。调用者调用这个文件。如果需要拆分function内容为多个文件的,皆放在相应函数的子目录下。例:math/functions/sqrt/sqrt.mcfunction调用math/functions/sqrt/iteration.mcfunction
- 所需的记分板必须统一创造在math:init.mcfunction中,此function必须被load.json引用,且命名符合上述命名规范
- 如果需要给函数功能分类,创建功能名子文件夹,并在文件夹下创建相应的函数文件夹
- - abs
- - pow
- - sqrt
- - vector:
- - length
- - normalize
复制代码
abs:
- # Abs Start
- scoreboard objectives add abs_arg_0 dummy
- scoreboard objectives add abs_out_0 dummy
- # Abs End
- # Sqrt Start
- scoreboard objectives add sqrt_arg_0 dummy
- # Different
- scoreboard objectives add sqrt_tmp_0 dummy
- # Devide Result
- scoreboard objectives add sqrt_tmp_1 dummy
- scoreboard objectives add sqrt_out_0 dummy
- # Sqrt End
- # Pow Start
- # Base Number
- scoreboard objectives add pow_arg_0 dummy
- # Exponent
- scoreboard objectives add pow_arg_1 dummy
- # Counter
- scoreboard objectives add pow_tmp_0 dummy
- scoreboard objectives add pow_out_0 dummy
- # Pow End
- # Vector Start
- # Normalize Start
- scoreboard objectives add norm_arg_0 dummy
- scoreboard objectives add norm_arg_1 dummy
- scoreboard objectives add norm_arg_2 dummy
- scoreboard objectives add norm_out_0 dummy
- scoreboard objectives add norm_out_1 dummy
- scoreboard objectives add norm_out_2 dummy
- # Normalize End
- # Length Start
- scoreboard objectives add leng_arg_0 dummy
- scoreboard objectives add leng_arg_1 dummy
- scoreboard objectives add leng_arg_2 dummy
- scoreboard objectives add leng_out_0 dummy
- # Length End
- # Vector End
- # Constants Start
- scoreboard objectives add constants dummy
- scoreboard players set minus_one constants -1
- scoreboard players set zero constants 0
- scoreboard players set one constants 1
- scoreboard players set two constants 2
- scoreboard players set three constants 3
- scoreboard players set four constants 4
- scoreboard players set five constants 5
- scoreboard players set six constants 6
- scoreboard players set seven constants 7
- scoreboard players set eight constants 8
- scoreboard players set nine constants 9
- scoreboard players set ten constants 10
- # Precision 10^-4
- scoreboard players set precision constants 10000
- scoreboard players set pi constants 31415
- scoreboard players set e constants 27182
- scoreboard players set sqrt_out_prec constants 100
- scoreboard players set sqrt_diff constants 1
- # Constants End
复制代码
主要负责记分板的创建和设置各种常量……很乱,并且其中一些常量根本没有用到。
- # Absolute x=-x(x<0) || x=x(x>=0)
- scoreboard players operation @s abs_out_0 = @s abs_arg_0
- execute if entity @s[scores={abs_out_0=..-1}] run scoreboard players operation @s abs_out_0 *= minus_one constants
复制代码
当a>=0时,|a|=a,反之|a|=-a
- # Pow
- scoreboard players operation @s pow_tmp_0 = @s pow_arg_1
- scoreboard players operation @s pow_out_0 = @s pow_arg_0
- scoreboard players remove @s pow_tmp_0 1
- execute if score @s pow_tmp_0 >= one constants if score @s pow_arg_1 > one constants run function math:pow/iteration
- execute if score @s pow_arg_1 = zero constants run scoreboard players set @s pow_out_0 1
- execute if score @s pow_arg_1 < zero constants run scoreboard players set @s pow_out_0 0
复制代码
pow/iteration.mcfunction
- scoreboard players operation @s pow_out_0 *= @s pow_arg_0
- scoreboard players remove @s pow_tmp_0 1
- execute if score @s pow_tmp_0 >= one constants run function math:pow/iteration
复制代码
我们在主函数中做第一次处理,随后判断条件进入迭代。在迭代中我们每次都将结果*底数,并且将临时量-1。随后判断条件继续迭代。最后我们回到主函数,对指数为0或指数<0的情况做特殊处理。
- # SquareRoot
- # Newton Iteration f(x1)=(f(x0)+r/f(x0))/2
- # For precision, r=r*10^4, so we get result*100
- scoreboard players operation @s abs_arg_0 = @s sqrt_arg_0
- function math:abs/abs
- scoreboard players operation @s sqrt_out_0 = @s abs_out_0
- scoreboard players operation @s sqrt_out_0 *= precision constants
- scoreboard players operation @s sqrt_tmp_0 = @s sqrt_out_0
- scoreboard players operation @s sqrt_out_0 /= two constants
- scoreboard players operation @s sqrt_tmp_0 -= @s sqrt_out_0
- execute if score @s sqrt_tmp_0 > sqrt_diff constants run function math:sqrt/iteration
- scoreboard players set @s sqrt_tmp_0 0
- scoreboard players set @s sqrt_tmp_1 0
复制代码
sqrt/iteration.mcfunction
- scoreboard players operation @s sqrt_tmp_1 = @s sqrt_arg_0
- scoreboard players operation @s sqrt_tmp_1 *= precision constants
- scoreboard players operation @s sqrt_tmp_1 /= @s sqrt_out_0
- scoreboard players operation @s sqrt_tmp_1 += @s sqrt_out_0
- scoreboard players operation @s sqrt_tmp_1 /= two constants
- scoreboard players operation @s sqrt_tmp_0 = @s sqrt_out_0
- scoreboard players operation @s sqrt_out_0 = @s sqrt_tmp_1
- scoreboard players operation @s sqrt_tmp_0 -= @s sqrt_out_0
- execute if score @s sqrt_tmp_0 > sqrt_diff constants run function math:sqrt/iteration
复制代码
我们对平方根的处理使用了牛顿迭代法(Newton Iteration)。即f(xn+1)=(f(xn)+a/f(xn))/2迭代,直到f(xn-1)-f(xn+1)<规定的精度为止。至于具体推导等,请自行百度。
- scoreboard players set @s sqrt_arg_0 0
- scoreboard players operation @s leng_out_0 = @s leng_arg_0
- scoreboard players operation @s leng_out_0 *= @s leng_out_0
- scoreboard players operation @s sqrt_arg_0 += @s leng_out_0
- scoreboard players operation @s leng_out_0 = @s leng_arg_1
- scoreboard players operation @s leng_out_0 *= @s leng_out_0
- scoreboard players operation @s sqrt_arg_0 += @s leng_out_0
- scoreboard players operation @s leng_out_0 = @s leng_arg_2
- scoreboard players operation @s leng_out_0 *= @s leng_out_0
- scoreboard players operation @s sqrt_arg_0 += @s leng_out_0
- function math:sqrt/sqrt
- scoreboard players operation @s leng_out_0 = @s sqrt_out_0
复制代码
向量长度计算公式为 √x2+y2+z2,并且由于sqrt的结果是*10^2的,所以我们的length算出来自然也是*10^2的
- scoreboard players operation @s leng_arg_0 = @s norm_arg_0
- scoreboard players operation @s leng_arg_1 = @s norm_arg_1
- scoreboard players operation @s leng_arg_2 = @s norm_arg_2
- scoreboard players operation @s norm_out_0 = @s norm_arg_0
- scoreboard players operation @s norm_out_1 = @s norm_arg_1
- scoreboard players operation @s norm_out_2 = @s norm_arg_2
- function math:vector/length/length
- scoreboard players operation @s pow_arg_0 = sqrt_out_prec constants
- scoreboard players set @s pow_arg_1 2
- function math:pow/pow
- scoreboard players operation @s norm_out_0 *= @s pow_out_0
- scoreboard players operation @s norm_out_1 *= @s pow_out_0
- scoreboard players operation @s norm_out_2 *= @s pow_out_0
- scoreboard players operation @s norm_out_0 /= @s leng_out_0
- scoreboard players operation @s norm_out_1 /= @s leng_out_0
- scoreboard players operation @s norm_out_2 /= @s leng_out_0
复制代码
规格化向量的公式为 normalize(u)=(ux/||u||,uy/||u||,uz/||u||)