如何使用光线投射绘制伪3d效果?

huwehgph  于 2021-06-30  发布在  Java
关注(0)|答案(0)|浏览(232)

我正在用java做一个小的光线投射项目,需要一些帮助。我已经为头顶光线投射算法编写了代码,所以效果很好。然而,在伪3d环境中绘制它却不是很好。

private ArrayList<Line2D.Double> calcRays(ArrayList<Wall> walls, int resolution, int maxDist) {

ArrayList<Line2D.Double> rays = new ArrayList<>();
int mx = cameraX;//this.getMouse().getMouseX();
int my = cameraY;//this.getMouse().getMouseY();

// If we exceed the right-boundary, just bail out.
if (mx > this.getGameWidth() / 2) {
  return rays;
}

for (int r = 0; r < resolution; r++) {
  // Compute the angle of this ray, normalized to our field of view.
  double rayAngle = ThetaUtils.normalize(r, 0, resolution, angle, angle + fov);

  // Compute the coordinates of the end of this ray.
  int ex = (int) (mx + maxDist * Math.cos(Math.toRadians(rayAngle)));
  int ey = (int) (my + maxDist * Math.sin(Math.toRadians(rayAngle)));

  // Build the ray, and declare variables for finding the MINIMUM ray.
  Line2D.Double ray = new Line2D.Double(mx, my, ex, ey);
  Point2D.Double minRay = null;
  Color minColor = null;
  double minDist = Integer.MAX_VALUE;

  // For each wall, find the wall that is the closest intersected
  // if one exists.
  for (Wall wall : walls) {
    if (wall.getLine().intersectsLine(ray)) {
      Point2D.Double rayEnd = wall.intersection(ray);
      double dist = rayEnd.distance(mx, my);
      if (dist <= minDist) {
        minDist = dist;
        minRay = rayEnd;
        minColor = wall.getColor();
      }
    }
  }

  // If we found a nearest collision, assign it to be the end-point of the ray.
  if (minRay != null) {
    ray.x2 = minRay.x;
    ray.y2 = minRay.y;
  }

  // If the ray extends beyond the separator, set that as the end-point.
  ray.x2 = ThetaUtils.clamp((int) ray.x2, 0, this.getGameWidth() / 2);
  rays.add(ray);

  // Now... draw the rectangle in pseudo-3D.
  // Fix the fish-eye effect first.
  double ca = ThetaUtils.clamp((int) (this.angle + fov / 2 - rayAngle), 0, 360);
  minDist = minDist * Math.cos(Math.toRadians(ca));

  // X coordinate.
  int rx = (int) ThetaUtils.normalize(r, 0, resolution, this.getGameWidth() / 2, this.getGameWidth());

  // Wall height calculation.
  final double H_OFFSET = 25.0;
  final int MAX_WALL_HEIGHT = this.getGameHeight() / 2;
  double wallHeight = ThetaUtils.clamp((int) (this.getGameHeight() * H_OFFSET / minDist), 0, MAX_WALL_HEIGHT);

  // Y coordinate.
  double lineO = this.getGameHeight() / 2.0 - wallHeight / 2.0;
  ThetaGraphics.GFXContext.setColor(minColor);
  ThetaGraphics.GFXContext.drawLine(rx, (int) lineO, rx, (int) (wallHeight + lineO));
}

return rays;

}
我发布的是我在投射光线和绘制3d环境方面的尝试。我将x坐标标准化为width()/2和width之间,因为我保留了一半屏幕用于自顶向下的光线视图,另一半用于此三维透视。作为参考,我的视野设置为70。
我试着到处找教程来解释代码,但没有一个能达到我所需要的程度。代码现在可以工作了,但看起来不太对劲。我觉得我的数字好像不对劲了。有人能帮忙吗?
gif格式:https://giphy.com/gifs/ojj2hgdrqlffem17yu

暂无答案!

目前还没有任何答案,快来回答吧!

相关问题