Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/17.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
Scala 透视投影的非工作实现_Scala_Geometry_Projection_Perspective - Fatal编程技术网

Scala 透视投影的非工作实现

Scala 透视投影的非工作实现,scala,geometry,projection,perspective,Scala,Geometry,Projection,Perspective,我写了一个程序,它接收一些入口点,用三维坐标表示,必须在二维画布上绘制。我使用透视投影、齐次坐标和类似的三角形来实现这一点。然而,我的程序不起作用,我也不知道为什么 我学习了两个教程。我真的理解了我读过的几何定义和性质。然而,我的实现失败了。。。我将一点一点地写这两门课程的参考资料,使你们的阅读更容易理解:) 概述:几何提醒 透视投影是按照这个工作流程完成的(参见这两门课程-我在这篇文章中进一步写下了相关链接(HTML锚): 根据世界坐标系定义要绘制的点;投影矩阵的定义,它是一个变换矩阵,将根据

我写了一个程序,它接收一些入口点,用三维坐标表示,必须在二维画布上绘制。我使用透视投影、齐次坐标和类似的三角形来实现这一点。然而,我的程序不起作用,我也不知道为什么

我学习了两个教程。我真的理解了我读过的几何定义和性质。然而,我的实现失败了。。。我将一点一点地写这两门课程的参考资料,使你们的阅读更容易理解:)

概述:几何提醒 透视投影是按照这个工作流程完成的(参见这两门课程-我在这篇文章中进一步写下了相关链接(HTML锚):

  • 根据世界坐标系定义要绘制的点;投影矩阵的定义,它是一个变换矩阵,将根据世界坐标系表示的点“转换”为根据相机坐标系表示的点(注意:该矩阵也可以理解为相机)

  • 这些点与该矩阵的乘积(定义见下文adequat部分):这些点的乘积将导致这些点转换为相机坐标系。注意,点和矩阵用4D表示(齐次坐标的概念)

  • 使用类似的三角形概念在画布上投影(在这一步中仅进行计算)摄像机内表示的点(使用其4D坐标):它们现在以3D表示(计算第三个坐标,但不在画布上实际使用)

  • 最后一步:光栅化,在画布上实际绘制像素(其他计算和显示在此步骤中完成)

  • 首先是问题 嗯,我想画一个立方体,但它没有出现。投影点似乎绘制在相同的坐标上

    而不是我的立方体,只有一个黑色像素是可见的

    斯卡斯蒂(片段) 注意:由于X11未在Scastie上激活,因此我要创建的窗口将不会显示

    条目 也许问题与条目有关?好吧,我给你

    立方体点 参考:我自己

    val world_cube_points : Seq[Seq[Double]] = Seq(
      Seq(0, 40, 0, 1),
      Seq(0, 40, 10, 1),
      Seq(0, 0, 0, 1),
      Seq(0, 0, 10, 1),
      Seq(20, 40, 0, 1),
      Seq(20, 40, 10, 1),
      Seq(20, 0, 0, 1),
      Seq(20, 0, 10, 1)
    )
    
    变换(投影)矩阵 参考号:

    其次,我的程序执行的第一个操作是:一个点与一个矩阵的简单乘积。 参考号:

    然后,使用相似的三角形 参考文献1/2:第1部分。“将点转换为摄影机空间的重要性 “的

    参考文献2/2:

    注意:在此步骤中,条目是根据相机表示的点(即:它们是具有预先定义的矩阵的预先定义的产品的结果)

    最后,在画布上绘制投影点。 参考:第二部分。“从屏幕空间到光栅空间”

    问题:
    我的程序怎么了?我理解了这两个教程所解释的几何概念,我仔细阅读了这两个教程。我很肯定我的产品能用。我认为光栅化或条目(矩阵)可能是错误的…

    您在标准化设备坐标上调用了
    toInt
    (表示有效范围为[0,1]):

    这将使其四舍五入为0或1,以便所有点都位于屏幕的边界上。仅在乘以屏幕分辨率后进行四舍五入:

    (normalized_drawn_point.head * IMAGE_WIDTH).toInt
    

    (从技术上讲,如果屏幕坐标从零开始,它应该是
    *(图像宽度-1)
    ,这是非常常见的。垂直坐标也是如此。)

    啊,谢谢!我可以看到类似立方体的东西,即使它不完美。你知道投影矩阵应该用什么值吗?或者我随机选择它们?@JarsOfJam。投影矩阵的值有特定的含义,所以你不能只是随机选择它们。它是如何构造的,以及它所依赖的摄影机变量。
    /**
      * Matrix in the shape of (use of homogeneous coordinates) :
      * c00 c01 c02 c03
      * c10 c11 c12 c13
      * c20 c21 c22 c23
      *   0   0   0   1
      *
      * @param content the content of the matrix
      */
    class Matrix(val content : Seq[Seq[Double]]) {
    
      /**
        * Computes the product between a point P(x ; y ; z) and the matrix.
        *
        * @param point a point P(x ; y ; z ; 1)
        * @return a new point P'(
        *         x * c00 + y * c10 + z * c20
        *         ;
        *         x * c01 + y * c11 + z * c21
        *         ;
        *         x * c02 + y * c12 + z * c22
        *         ;
        *         1
        *         )
        */
      def product(point : Seq[Double]) : Seq[Double] = {
        (0 to 3).map(
          i => content(i).zip(point).map(couple2 => couple2._1 * couple2._2).sum
        )
      }
    
    }
    
    class Projector {
    
      /**
        * Computes the coordinates of the projection of the point P on the canvas.
        * The canvas is assumed to be 1 unit forward the camera.
        * The computation uses the definition of the similar triangles.
        *
        * @param points the point P we want to project on the canvas. Its coordinates must be expressed in the coordinates
        *          system of the camera before using this function.
        * @return the point P', projection of P.
        */
      def drawPointsOnCanvas(points : Seq[Seq[Double]]) : Seq[Seq[Double]] = {
        points.map(point => {
          point.map(coordinate => {
            coordinate / -point(3)
          }).dropRight(1)
        })
    
      }
    
    }
    
    import java.awt.Graphics
    import javax.swing.JFrame
    
    /**
      * Assumed to be 1 unit forward the camera.
      * Contains the drawn points.
      */
    class Canvas(val drawn_points : Seq[Seq[Double]]) extends JFrame {
    
      val CANVAS_WIDTH = 60
      val CANVAS_HEIGHT = 60
      val IMAGE_WIDTH = 55
      val IMAGE_HEIGHT = 55
    
      def display = {
        setTitle("Perlin")
        setSize(CANVAS_WIDTH, CANVAS_HEIGHT)
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE)
        setVisible(true)
      }
    
      override def paint(graphics : Graphics): Unit = {
        super.paint(graphics)
        drawn_points.foreach(point => {
    
          if(!(Math.abs(point.head) <= CANVAS_WIDTH / 2 || Math.abs(point(1)) <= CANVAS_HEIGHT / 2)) {
            println("WARNING : the point (" + point.head + " ; " + point(1) + ") can't be drawn in this canvas.")
          } else {
            val normalized_drawn_point = Seq((point.head + (CANVAS_WIDTH / 2)) / CANVAS_WIDTH, (point(1) + (CANVAS_HEIGHT / 2)) / CANVAS_HEIGHT)
            graphics.drawRect(normalized_drawn_point.head.toInt * IMAGE_WIDTH, (1 - normalized_drawn_point(1).toInt) * IMAGE_HEIGHT, 1, 1)
          }
        })
      }
    
    }
    
    object Main {
      def main(args : Array[String]) : Unit = {
        val projector = new Projector()
    
        val world_cube_points : Seq[Seq[Double]] = Seq(
          Seq(0, 40, 0, 1),
          Seq(0, 40, 10, 1),
          Seq(0, 0, 0, 1),
          Seq(0, 0, 10, 1),
          Seq(20, 40, 0, 1),
          Seq(20, 40, 10, 1),
          Seq(20, 0, 0, 1),
          Seq(20, 0, 10, 1)
        )
    
        val matrix_world_to_camera : Matrix = new Matrix(Seq(
          Seq(1, 0, 0, 0),
          Seq(0, 1, 0, 0),
          Seq(0, 0, 1, 0),
          Seq(0, 0, -1, 1)
        ))
    
        val points_to_draw_on_canvas = projector.drawPointsOnCanvas(world_cube_points.map(point => {
          matrix_world_to_camera.product(point)
        }))
        new Canvas(points_to_draw_on_canvas).display
    
      }
    }
    
    normalized_drawn_point.head.toInt * IMAGE_WIDTH
                                ----- 
    
    (normalized_drawn_point.head * IMAGE_WIDTH).toInt