首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >光线浇铸渲染-墙的边缘交叉问题

光线浇铸渲染-墙的边缘交叉问题
EN

Stack Overflow用户
提问于 2022-04-22 09:08:55
回答 1查看 147关注 0票数 0

我正在使用光线投射方法(如Wolfenstein3D)实现一个假的3D渲染。我遵循永久的教程(https://permadi.com/1996/05/ray-casting-tutorial-table-of-contents/)

作为第一种观点,它似乎运作良好,但我正在努力解决一个问题,我不知道会发生什么。事实上,墙壁的边缘是互相交叉的,有时光线也没有探测到任何墙壁。

但情况并不总是如此。有时效果很好,这取决于球员的方向。

在用2D渲染场景之后,我可以看到光线确实没有探测到墙壁。但视方向而定,情况并不总是如此。

在上面的截图中,左边这个不工作,但是在右边这个是工作的。

这就是我如何检测墙壁,得到距离和Y轴

代码语言:javascript
复制
float getDistanceOnHorizontalGrid(float rayAngle, float playerPosX, float playerPosY)
{
    float pointInRayY = playerPosY + (100 * sin(DEGREE_TO_RADIAN(rayAngle))); // Arbitrary Point to evaluate whether ray is facing up or down
    float firstIntersectPointY;
    float ya;
    float xa;

    if (pointInRayY <= playerPosY) // ray is facing up
    {
        firstIntersectPointY = floorf(playerPosY / WALL_SIZE) * (WALL_SIZE)-1;
        ya = -WALL_SIZE;
        xa = WALL_SIZE / tan(DEGREE_TO_RADIAN(rayAngle)) * -1;
    }
    else // ray is facing down
    {
        firstIntersectPointY = floorf(playerPosY / WALL_SIZE) * (WALL_SIZE)+WALL_SIZE;
        ya = WALL_SIZE;
        xa = WALL_SIZE / tan(DEGREE_TO_RADIAN(rayAngle));
    }

    float firstIntersectPointX = playerPosX - (playerPosY - firstIntersectPointY) / tan(DEGREE_TO_RADIAN(rayAngle));

    float nextPointX = firstIntersectPointX;
    float nextPointY = firstIntersectPointY;

    for (int i = 0; i < MAP_HEIGHT; i++)
    {
        int toMapX = convertWorldToGridCoordinate(floor(nextPointX));
        int toMapY = convertWorldToGridCoordinate(floor(nextPointY));

        if (!(toMapX >= 0 && toMapX <= MAP_WIDTH - 1 && toMapY >= 0 && toMapY <= MAP_HEIGHT - 1))
        {
            return 0.0f;
        }

        if (map[toMapY][toMapX] == 1)
        {
            return abs(sqrt(((playerPosX - nextPointX) * (playerPosX - nextPointX)) + ((playerPosY - nextPointY) * (playerPosY - nextPointY))));
        }

        nextPointX += xa;
        nextPointY += ya;
    }

    return 0.0f;
}

X轴也是如此

代码语言:javascript
复制
float getDistanceOnverticalGrid(float rayAngle, float playerPosX, float playerPosY)
{
    float pointInRayX = playerPosX + (100 * cos(DEGREE_TO_RADIAN(rayAngle))); // Arbitrary Point to evaluate whether ray is facing left or right
    float firstIntersectX;
    float firstIntersectY;
    float xa;
    float ya;

    if (pointInRayX <= playerPosX) // ray facing left
    {
        firstIntersectX = floorf(playerPosX / WALL_SIZE) * (WALL_SIZE)-1;
        xa = -WALL_SIZE;
        ya = (WALL_SIZE * tan(DEGREE_TO_RADIAN(rayAngle))) * -1;
    }
    else
    {
        firstIntersectX = floorf(playerPosX / WALL_SIZE) * (WALL_SIZE)+WALL_SIZE;
        ya = WALL_SIZE * tan(DEGREE_TO_RADIAN(rayAngle));
        xa = WALL_SIZE;
    }

    firstIntersectY = playerPosY - (playerPosX - firstIntersectX) * tan(DEGREE_TO_RADIAN(rayAngle));

    float nextPointX = firstIntersectX;
    float nextPointY = firstIntersectY;


    for (int i = 0; i < MAP_WIDTH; i++)
    {
        int toMapX = convertWorldToGridCoordinate(floorf(nextPointX));
        int toMapY = convertWorldToGridCoordinate(floorf(nextPointY));

        if (!(toMapX >= 0 && toMapX <= (MAP_WIDTH - 1) && toMapY >= 0 && toMapY <= (MAP_HEIGHT - 1)))
        {
            return 0.0f;
        }

        if (map[toMapY][toMapX] == 1)
        {
            return abs(sqrt(((playerPosX - nextPointX) * (playerPosX - nextPointX)) + ((playerPosY - nextPointY) * (playerPosY - nextPointY))));
        }

        nextPointX += xa;
        nextPointY += ya;
    }

    return 0.0f;
}

我一定做错了什么,但我不知道在哪里。谢谢你的帮助

更新

尽管把数值从1降下来仍然是必要的,但在计算中,所提到的BCT是正确的。在使loog更接近permadi的实现之后,完成以下操作

代码语言:javascript
复制
horizontalGrid = Math.floor(this.fPlayerY/this.TILE_SIZE)*this.TILE_SIZE  + this.TILE_SIZE;

他做到了:

代码语言:javascript
复制
horizontalGrid--;

一开始我以为这和我所做的是一样的,但实际上没有。他后来降低了值的原因是因为这只是为了得到网格坐标。

为了解决我的问题,我从计算中删除了-1,并且只在寻找网格坐标时降低了值。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-04-22 09:49:22

我看了你发送的链接。似乎其中一个if块的价值很差:

这是教程代码:

代码语言:javascript
复制
// Ray is facing down
        if (castArc > this.ANGLE0 && castArc < this.ANGLE180)
        {
            // truncuate then add to get the coordinate of the FIRST grid (horizontal
            // wall) that is in front of the player (this is in pixel unit)
            // ROUNDED DOWN
            horizontalGrid = Math.floor(this.fPlayerY/this.TILE_SIZE)*this.TILE_SIZE  + this.TILE_SIZE;

这是你的代码:

代码语言:javascript
复制
 if (pointInRayY <= playerPosY) // ray is facing up
 {
     firstIntersectPointY = floorf(playerPosY / WALL_SIZE) * (WALL_SIZE)-1;

请注意,您的末尾是-1,而不是this.TILE_SIZE,在您的示例中,应该是WALL_SIZE

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/71966198

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档