일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 |
- IOS
- 스프링부트
- javascript
- 스프링부트 웹 소켓
- JPA
- 오라클
- jenkins
- Xcode
- 리눅스
- 티스토리챌린지
- Spring
- 스프링
- AI
- 아이패드다이어리
- CD
- 데이터베이스
- springboot
- 소켓
- 다이어리
- libasm
- 프로그래밍언어론
- 42seoul
- MySQL
- swift
- sql
- CI
- 오블완
- DBMS
- 인공지능
- 네트워크
- Today
- Total
Hi yoahn 개발블로그
[42Seoul/cub3D] #3 벽과 바닥 raycasting 본문
텍스처 그리기와 동일한 코드에서 바닥과 천장 캐스팅하는 부분을 추가한다.
github.com/l-yohai/cub3d/blob/master/mlx_example/floor_ceiling.md
l-yohai/cub3d
Porting by Lode's Computer Graphics Tutorial - Raycasting to C and Minilibx for 42 Subject Cub3D - l-yohai/cub3d
github.com
void calc(t_game *game)
{
// floor casting
for (int y = 0;y < screenHeight;y++)
{
float rayDirX0 = game->dirX - game->planeX;
float rayDirY0 = game->dirY - game->planeY;
float rayDirX1 = game->dirX + game->planeX;
float rayDirY1 = game->dirY + game->planeY;
// 현재 y 위치와 스크린 높이 중앙 위치를 비교
int p = y - screenHeight / 2;
// camera 수직 위치
float posZ = 0.5 * screenHeight;
float rowDistance = posZ / p;
float floorStepX = rowDistance * (rayDirX1 - rayDirX0) / screenWidth;
float floorStepY = rowDistance * (rayDirY1 - rayDirY0) / screenWidth;
float floorX = game->posX + rowDistance * rayDirX0;
float floorY = game->posY + rowDistance * rayDirY0;
for (int x = 0;x < screenWidth;x++)
{
int cellX = (int)floorX;
int cellY = (int)floorY;
int tx = (int)(texWidth * (floorX - cellX)) & (texWidth - 1);
int ty = (int)(texHeight * (floorY - cellY)) & (texHeight - 1);
floorX += floorStepX;
floorY += floorStepY;
int floorTexture = 3;
int ceilingTexture = 6;
int color;
color = game->texture[floorTexture][texWidth * ty + tx];
color = (color >> 1) & 8355711; // 어둡게 표현
game->buf[y][x] = color;
color = game->texture[ceilingTexture][texWidth * ty + tx];
color = (color >> 1) & 8355711;
game->buf[screenHeight - y - 1][x] = color;
}
}
posZ : 광선 시작점
y = (0 ~ screenHeight/2)
p : y와 스크린 중앙의 차이값
화면을 가로로 반 나눠서 위에는 천장 텍스처를 그리고, 아래에는 바닥 텍스처를 그린다.
y 가 height / 2 여도 같은 결과가 나온다.
이 루프의 결과는 이동과 상관없이 화면을 절반씩 나눠 천장과 바닥을 그리는 것이므로 그려진 화면에서 이동하게 되면 바닥과 천장은 움직이지 않아 플레이어가 움직이는 것이 아니라 벽이 이동하는 것처럼 보이게 된다.
github.com/p-eye/cub3d_texturing/blob/master/3.ceil.md
p-eye/cub3d_texturing
Description of cub3D texturing. Contribute to p-eye/cub3d_texturing development by creating an account on GitHub.
github.com
벽 raycasting 이전에 했던 것과 같다.
for (int x = 0;x < screenWidth;x++)
{
double cameraX = 2 * x / (double)screenWidth - 1;
double rayDirX = game->dirX + game->planeX * cameraX;
double rayDirY = game->dirY + game->planeY * cameraX;
int mapX = (int)game->posX;
int mapY = (int)game->posY;
double sideDistX, sideDistY;
double deltaDistX = fabs(1 / rayDirX);
double deltaDistY = fabs(1 / rayDirY);
double perpWallDist;
int stepX, stepY;
int hit = 0;
int side;
if (rayDirX < 0)
{
stepX = -1;
sideDistX = (game->posX - mapX) * deltaDistX;
}
else
{
stepX = 1;
sideDistX = (mapX + 1.0 - game->posX) * deltaDistX;
}
if (rayDirY < 0)
{
stepY = -1;
sideDistY = (game->posY - mapY) * deltaDistY;
}
else
{
stepY = 1;
sideDistY = (mapY + 1.0 - game->posY) * deltaDistY;
}
while (hit == 0)
{
if (sideDistX < sideDistY)
{
sideDistX += deltaDistX;
mapX += stepX;
side = 0;
}
else
{
sideDistY += deltaDistY;
mapY += stepY;
side = 1;
}
if (worldMap[mapX][mapY] > 0) hit = 1;
}
if (side == 0)
perpWallDist = (mapX - game->posX + (1 - stepX) / 2) / rayDirX;
else
perpWallDist = (mapY - game->posY + (1 - stepY) / 2) / rayDirY;
int lineHeight = (int)(screenHeight / perpWallDist);
int drawStart = -lineHeight / 2 + screenHeight / 2;
if (drawStart < 0)
drawStart = 0;
int drawEnd = lineHeight / 2 + screenHeight / 2;
if (drawEnd >= screenHeight)
drawEnd = screenHeight - 1;
int texNum = worldMap[mapX][mapY] - 1;
double wallX;
if (side == 0)
wallX = game->posY + perpWallDist * rayDirY;
else
wallX = game->posX + perpWallDist * rayDirX;
wallX -= floor(wallX);
int texX = (int)(wallX * (double)texWidth);
if (side == 0 && rayDirX > 0)
texX = texWidth - texX - 1;
if (side == 1 && rayDirY < 0)
texX = texWidth - texX - 1;
// How much to increase the texture coordinate per screen pixel
double step = 1.0 * texHeight / lineHeight;
// starting texture coordinate
double texPos = (drawStart - screenHeight / 2 + lineHeight / 2) * step;
for (int y = drawStart; y < drawEnd;y++)
{
int texY = (int)texPos & (texHeight - 1);
texPos += step;
int color = game->texture[texNum][texWidth * texY + texX];
if (side == 1)
color = (color >> 1) & 8355711;
game->buf[y][x] = color;
}
벽이 그려지는 범위인 drawStart - drawEnd 이외의 범위에 천장과 바닥을 그린다.
// floor casting
double floorXWall, floorYWall;
if (side == 0 && rayDirX > 0)
{
floorXWall = mapX;
floorYWall = mapY + wallX;
}
else if (side == 0 && rayDirX < 0)
{
floorXWall = mapX + 1.0;
floorYWall = mapY + wallX;
}
else if (side == 1 && rayDirY > 0)
{
floorXWall = mapX + wallX;
floorYWall = mapY;
}
else
{
floorXWall = mapX + wallX;
floorYWall = mapY + 1.0;
}
double distWall, distPlayer, currentDist;
distWall = perpWallDist;
distPlayer = 0.0;
if (drawEnd < 0) drawEnd = screenHeight;
for (int y = drawEnd + 1; y < screenHeight; y++)
{
currentDist = screenHeight / (2.0 * y - screenHeight);
double weight = (currentDist - distPlayer) / (distWall - distPlayer);
double currentFloorX = weight * floorXWall + (1.0 - weight) * game->posX;
double currentFloorY = weight * floorYWall + (1.0 - weight) * game->posY;
int floorTexX, floorTexY;
floorTexX = (int)(currentFloorX * texWidth) % texWidth;
floorTexY = (int)(currentFloorY * texHeight) % texHeight;
int checkerBoardPattern = ((int)(currentFloorX) + (int)(currentFloorY)) % 2;
int floorTexture;
if (checkerBoardPattern == 0) floorTexture = 3;
else floorTexture = 4;
game->buf[y][x] = (game->texture[floorTexture][texWidth * floorTexY + floorTexX] >> 1) & 8355711;
game->buf[screenHeight - y][x] = game->texture[6][texWidth * floorTexY + floorTexX];
}
}
}
if side == 0 && rayDirX > 0
벽에 부딪힌 면이 Y축 면이고 광선 방향이 양수이면
바닥의 x 축 값은 현재 mapX 값이고
바닥의 y 축 값은 현재 mapY + wallX
(wallX가 부딪힌 벽에서 정확한 위치값을 나타냄)
if side == 0 && rayDirX < 0
벽에 부딪힌 면이 y축이고 광선의 방향이 음수이면
바닥의 x축 값은 mapX + 1.0
바닥의 y축 값은 mapY + wallX
'42 SEOUL > 배운 것들 정리' 카테고리의 다른 글
SSH Tunneling (0) | 2021.07.27 |
---|---|
[42Seoul] push_swap 풀이 과정 (0) | 2021.05.24 |
[42Seoul/Cub3d] #2 cub3D 벡터를 이용해 화면 그리기 (0) | 2021.03.27 |
[42Seoul/exam] exam02 공부 (0) | 2021.03.18 |
[42Seoul/Cub3d] #1 cub3d 시작하기 (0) | 2021.03.12 |