一般几何里面用相交比较多 简单写个demo测试下WebAssembly 和js的速度,
主要计算的就是射线交线段,主要是测试计算速度 算法不一定对,
rust代码如下,刚开始写rust 可能有点不规范
ray表示射线
另外两个用float32array作为 线的顶点和索引
这里说明下,如果不转换成rust的vec 直接使用float32array.get_index()调用的话,由于要频繁调用js代码会更慢
pub fn insert(ray:js_sys::Float32Array,in_points:js_sys::Float32Array, in_indexes:js_sys::Int32Array)->js_sys::Float32Array
{
let points = in_points.to_vec();
let indexes = in_indexes.to_vec();
let mut results:Vec = vec![];
let o_x = ray.get_index(0);
let o_y = ray.get_index(1);
let o_z = ray.get_index(2);
let d_x = ray.get_index(3);
let d_y = ray.get_index(4);
let d_z = ray.get_index(5);
let size = indexes.len();
let mut index = 0;
while index < size {
let s_i =indexes[index] as usize;
let e_i =indexes[index + 1] as usize;
index = index + 2 as usize;
let s_x = points[s_i * 3];
let s_y = points[s_i * 3 + 1];
let s_z = points[s_i * 3 + 2];
let e_x = points[e_i * 3];
let e_y = points[e_i * 3 + 1];
let e_z = points[e_i * 3 + 2];
let c_length = f32::sqrt((e_x - s_x).powi(2) + (e_y - s_y).powi(2)+(e_z-s_z).powi(2));
let c_d_x = (e_x - s_x) / c_length;
let c_d_y = (e_y - s_y) / c_length;
let c_d_z = (e_z - s_z) / c_length;
let sbv1 = cross(d_x, d_y, d_z, c_d_x, c_d_y, c_d_z);
let sbv2 = cross(c_d_x, c_d_y, c_d_z, d_x, d_y, d_z);
let sb1 = array_dots(sbv2,sbv1);
let sb2 = array_dots(sbv1,sbv2);
if sb1 < 0.00000001 || sb2 < 0.0000001
{
continue;
}
let mut temp_1 = sub(o_x, o_y, o_z, s_x, s_y, s_z);
let mut temp_2 = cross(temp_1[0], temp_1[1],temp_1[2],c_d_x,c_d_y,c_d_z);
let mut temp_3 = cross(temp_2[0], temp_2[1], temp_2[2], d_x, d_y, d_z);
let t1 = array_dots(temp_2, temp_3) /sb1;
temp_1 = sub(o_x, o_y, o_z, s_x, s_y, s_z);
temp_2 = cross(temp_1[0], temp_1[1],temp_1[2],c_d_x,c_d_y,c_d_z);
temp_3 = cross(temp_2[0], temp_2[1], temp_2[2], d_x, d_y, d_z);
let t2 = array_dots(temp_2, temp_3) /sb1;
let array = [o_x + t1 * d_x, o_y + t1 * d_y, o_z + t1 * d_z, s_x + t2 * c_d_x, s_y + t2 * c_d_y, s_z + t2 * c_d_z];
if (array[0] - array[3]).powi(2) + (array[1] - array[4]).powi(2) + (array[2] - array[5]).powi(2) < 1.0
{
results.push(array[0]);
results.push(array[1]);
results.push(array[2]);
results.push(array[3]);
results.push(array[4]);
results.push(array[5]);
}
// let array = js_sys::Float32Array::default();
// array.copy_from(&[o_x + t1 * d_x, o_y + t1 * d_y, o_z + t1 * d_z, s_x + t2 * c_d_x, s_y + t2 * c_d_y, s_z + t2 * c_d_z]);
// return array;
}
let array = js_sys::Float32Array::new_with_length(results.len() as u32);
array.copy_from(&results);
return array;
}
测试float32array转vec的时间,为了避免未使用变量优化 计算下结果
#[wasm_bindgen]
pub fn only_copy(ray:js_sys::Float32Array,in_points:js_sys::Float32Array, in_indexes:js_sys::Int32Array)->f32
{
let points = in_points.to_vec();
let indexes = in_indexes.to_vec();
let o_x = ray.get_index(0);
let o_y = ray.get_index(1);
let o_z = ray.get_index(2);
let d_x = ray.get_index(3);
let d_y = ray.get_index(4);
let d_z = ray.get_index(5);
return points[0] + indexes[1] as f32 + o_x + d_x + d_y + d_z + o_y + o_z;
}
js的代码
let js = (ray:Float32Array,points:Float32Array, indexes:Int32Array)=>{
let origin =new THREE.Vector3(ray[0], ray[1], ray[2]);
let direction =new THREE.Vector3(ray[3], ray[4], ray[3]);
let start = new THREE.Vector3();
let end = new THREE.Vector3();
let sbv1 = new THREE.Vector3();
let lDirection = new THREE.Vector3();
let sbv2 = new THREE.Vector3();
let size = indexes.length;
let index = 0;
while (index < size) {
let s_i =indexes[index] ;
let e_i =indexes[index + 1] ;
index = index + 2 ;
start.set(points[s_i * 3],points[s_i * 3 +1],points[s_i * 3 + 2]);
end.set(points[e_i * 3],points[e_i * 3 +1],points[e_i * 3 + 2]);
lDirection = lDirection.copy(end).sub(start).normalize();
sbv1 =sbv1.copy(lDirection).cross(direction);
sbv2 =sbv2.copy(direction).cross(lDirection);
let sb1 = sbv1.dot(sbv2);
let sb2 = sbv2.dot(sbv1);
if (sb1 < 0.00000001 || sb2 < 0.0000001)
{
continue;
}
let temp_1 = origin.clone().sub(start).cross(lDirection);
let temp_2 = start.clone().sub(origin).cross(direction);
let t1 = temp_1.dot(temp_2) /sb1;
temp_1 = origin.clone().sub(start).cross(lDirection);
temp_2 = start.clone().sub(origin).cross(direction);
let t2= temp_1.dot(temp_2) /sb1;
// let array = js_sys::Float32Array::default();
// array.copy_from(&[o_x + t1 * d_x, o_y + t1 * d_y, o_z + t1 * d_z, s_x + t2 * c_d_x, s_y + t2 * c_d_y, s_z + t2 * c_d_z]);
// return array;
}
return new Float32Array();
}
测试数据 直接用随机数计算出线段
const size = 10000;
let index = [];
for (let i = 0; i < size; i++)
{
array.push(Math.random() * 1000, Math.random() * 1000, Math.random() * 1000);
index.push(i);
if(i != 0 || i!= size-1)
{
index.push(i);
}
}
let p1 = new Float32Array(array);
let indies = new Int32Array(index);
10000结果如下:
rust: 1.133056640625 ms
only_copy: 0.083984375 ms
js: 3.298095703125 ms
100000结果
rust: 3.6298828125 ms
only_copy: 0.214111328125 ms
js: 5.56884765625 ms
1000000结果
rust: 28.794921875 ms
only_copy: 1.44482421875 ms
js: 23.551025390625 ms
数据量多的时候 rust编译出来的WebAssembly 开始慢下来了,推测可能是内存有点施展不开来
10000000时候慢的更多了
rust: 313.79296875 ms
only_copy: 19.958251953125 ms
js: 215.423828125 ms
个人感觉 对于密集型运算使用WebAssembly 会好很多,如果要是js和WebAssembly直接频繁调用还是直接js更块 因为js调用WebAssembly或者WebAssembly叫用js也耗用一定资源