Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/467.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 基于光线跟踪的声反射模拟算法_Javascript - Fatal编程技术网

Javascript 基于光线跟踪的声反射模拟算法

Javascript 基于光线跟踪的声反射模拟算法,javascript,Javascript,我的职业是土木建筑,热爱数学、物理和计算机。对于我的一个项目,我正在设计一个有3面直墙和4面曲墙的房间。声源靠近左墙 +------- | \ | + | | / +------- 有了一些空闲时间,我决定尝试使用JavaScript和CanvasAPI对这个房间的声学进行建模。我的目标是计算房间中的每一点: 将直接从声源发出的声音与墙壁反射的声音(包括弯曲声)相加得到的净声强。这将包括由平方反比定律引起的衰减和墙壁的吸收 混响特性,通过跟踪直接来自声源

我的职业是土木建筑,热爱数学、物理和计算机。对于我的一个项目,我正在设计一个有3面直墙和4面曲墙的房间。声源靠近左墙

+-------
|        \
| +       |
|        /
+-------
有了一些空闲时间,我决定尝试使用JavaScript和CanvasAPI对这个房间的声学进行建模。我的目标是计算房间中的每一点:

  • 将直接从声源发出的声音与墙壁反射的声音(包括弯曲声)相加得到的净声强。这将包括由平方反比定律引起的衰减和墙壁的吸收
  • 混响特性,通过跟踪直接来自声源的路径长度和来自墙壁的反射。如果在主信号到达后约0.05秒,房间中的一个点接收到反射信号,我们可能有回声问题
  • 我假设画布尺寸为800x600像素,房间的真实尺寸为45x44英尺(左墙=44英尺,顶/底墙31英尺,弧形墙半径22英尺),声源距离左墙5英尺。我将每面墙建模为直线或圆方程,并编写了一个函数,告诉我一个点是否在房间内。对于画布中的每个像素,我将其转换为真实世界坐标,计算其与源的距离,并使用平方反比定律计算声音强度。我的结局是:

    但是,不用说,这只捕获来自源的主反弹。它并没有捕捉到任何反射,而这些反射对我来说太难计算了

    我正在寻找一个洞察我如何能做到这一点。我尝试了以下部分:

  • 我没有在房间网格中迭代点,而是尝试从源生成光线。计算直墙的反射很容易。但曲线墙带来了一些挑战。我遇到的最大问题是:如果我从360条射线开始,离光源最近的点每像素有太多的点,但当我们向外移动时,这些点变得非常稀疏,相邻点之间可能有几十个像素。这也意味着,当我反射光线时,它肯定不会落在主反弹创建的点上,我无法简单地将它们相加。即使我插值,结果也不正确,因为一些点会由于主反弹而记录强度,更少的点会由于次/三次反弹而记录强度,而许多点不会记录任何内容。在下图中,我尝试了这种仅使用主反弹的方法
  • 按方向迭代房间网格。对于房间中的每个点,计算光源的直接方向以及光源在每面墙中的反射位置。使用这些距离计算房间中每个采样点的净强度。对于直墙来说,这很容易做到。但对于我来说,曲线墙的数学变得异常复杂,无法解决
  • 假设
    A
    是源,
    O
    是曲线的中心,
    B
    是我们当前测试的房间点,
    X
    是曲线上的点。对于二次反弹,èAXO=èBXO。我们知道
    A
    O
    B
    。如果我们能找到
    X
    ,那么
    BX
    需要向后延伸一段等于
    AX
    的距离,并且源图像将位于那里。问题是查找
    X
    是一个非常困难的问题。即使可以做到这一点,它也只能解释二次反弹。三次反弹将更难计算

    我认为选择2是更好的解决办法。但是我没有足够的数学/计算机技能来独自解决这个问题。此时此刻,我试图解决这个问题不是为了我的项目,而是为了我个人的好奇心。如果你们能解决这个问题并分享你们的解决方案,我将不胜感激。或者,如果你能让我深入了解这个问题,我很乐意进一步研究这个问题

    我缺乏计算插值和光线跟踪方面的专业知识(我认为这是这个问题所需要的)

    谢谢,
    Asim

    So。有了劳拉的指点,以及对矩阵数学和bresenham的线渲染算法的深入研究,我终于能够完成这个爱好项目这里列出了针对类似问题希望遵循此路线的任何人的步骤

  • 抛弃代数方程,代之以矩阵数学。将线改为参数化线
  • 用光线和圆表示墙。行可以表示为
    [xy1]=[x0y01]+t*[dx dy1]
    。圆可以表示为
    (X-C)^2=r^2
  • 从源向外投影光线。对于每条光线,计算其与一面墙的交点,并调整其大小,使其从起点延伸到交点
  • 计算交点时,计算交点处墙的法向量。对于直墙,计算法线很简单(
    [-dy dx 1]
    )。对于圆,法线为
    X-C
  • 使用矩阵围绕法线反射入射光线
  • 根据需要重复此过程以获得尽可能多的反弹
  • 将平面所在的世界坐标系映射到单元坐标系,以将世界划分为单元网格。每个单元格的大小可以是1'-0“x 1'-0”(英尺)。再次使用矩阵在两个坐标系之间进行变换
  • 使用变换矩阵将光线转换为单元坐标系
  • 使用Bresemham的直线算法来确定光线通过哪些单元格。对于每个单元,使用平方反比定律计算该单元的光线强度。将此值添加到单元格网格
  • 最后,使用Canvas API和另一个转换矩阵在单元坐标系之间转换为
                   X
                   +
    
    
                      +B
      +         +
      A         O