mirror of
https://github.com/id-Software/Wolf3D-iOS.git
synced 2026-03-20 08:59:51 +01:00
Source release of Wolfenstein 3D Classic Platinum for iOS, 1.1
This commit is contained in:
373
wolf3d/code/wolf/wolf_raycast.c
Normal file
373
wolf3d/code/wolf/wolf_raycast.c
Normal file
@@ -0,0 +1,373 @@
|
||||
/*
|
||||
|
||||
Copyright (C) 2004 Michael Liebscher
|
||||
Copyright (C) 2000-2002 by DarkOne the Hacker
|
||||
|
||||
This program is free software; you can redistribute it and/or
|
||||
modify it under the terms of the GNU General Public License
|
||||
as published by the Free Software Foundation; either version 2
|
||||
of the License, or (at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* wolf_raycast.c: Wolfenstein3-D ray-casting.
|
||||
*
|
||||
* Author: Michael Liebscher <johnnycanuck@users.sourceforge.net>
|
||||
* Date: 2004
|
||||
*
|
||||
* Acknowledgement:
|
||||
* This code was derived from NewWolf, and was originally
|
||||
* written by DarkOne the Hacker.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "../wolfiphone.h"
|
||||
|
||||
|
||||
W8 tile_visible[ 64 ][ 64 ]; // can player see this tile?
|
||||
|
||||
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
Function: R_RayCast() -Ray cast viewport.
|
||||
|
||||
Parameters: viewport -[in] Position of camera.
|
||||
lvl -[in] Pointer to valid LevelData_t structure.
|
||||
|
||||
Returns: Nothing.
|
||||
|
||||
Notes: Marks all visible tiles in tile_visible[] array.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
PUBLIC void R_RayCast( placeonplane_t viewport, LevelData_t *lvl )
|
||||
{
|
||||
int n, x, y, angle, vx, vy;
|
||||
r_trace_t trace;
|
||||
|
||||
memset( tile_visible, 0, sizeof( tile_visible ) ); // clear tile visible flags
|
||||
|
||||
// viewport tile coordinates
|
||||
x = viewport.origin[ 0 ];
|
||||
y = viewport.origin[ 1 ];
|
||||
angle = viewport.angle;
|
||||
|
||||
vx = POS2TILE( viewport.origin[ 0 ] );
|
||||
vy = POS2TILE( viewport.origin[ 1 ] );
|
||||
|
||||
trace.tile_vis = tile_visible;
|
||||
trace.flags = TRACE_SIGHT | TRACE_MARK_MAP;
|
||||
|
||||
//
|
||||
// Ray casting
|
||||
//
|
||||
|
||||
// FIXME: control ray count and make angle init
|
||||
for( n = 0 ; n < 640 ; ++n )
|
||||
{
|
||||
trace.x = x;
|
||||
trace.y = y;
|
||||
trace.a = NormalizeAngle( angle + ColumnAngle[ n ] );
|
||||
|
||||
R_Trace( &trace, lvl );
|
||||
}
|
||||
|
||||
//
|
||||
// Rendering
|
||||
//
|
||||
for( x = 0 ; x < 64; ++x )
|
||||
for( y = 0 ; y < 64; ++y )
|
||||
if( tile_visible[ x ][ y ] )
|
||||
{
|
||||
lvl->tileEverVisible[x][y] = 1; // for automap
|
||||
if( lvl->tilemap[ x ][ y ] & DOOR_TILE )
|
||||
{
|
||||
/* door */
|
||||
if( lvl->Doors.DoorMap[ x ][ y ].action != dr_open )
|
||||
{
|
||||
_boolean backside = false;
|
||||
|
||||
if( lvl->Doors.DoorMap[ x ][ y ].vertical )
|
||||
{
|
||||
if( x < vx )
|
||||
backside = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( y < vy )
|
||||
backside = true;
|
||||
}
|
||||
|
||||
R_Draw_Door( x, y, LOWERZCOORD, UPPERZCOORD,
|
||||
lvl->Doors.DoorMap[ x ][ y ].vertical,
|
||||
backside,
|
||||
lvl->Doors.DoorMap[ x ][ y ].texture,
|
||||
Door_Opened( &lvl->Doors, x, y ) );
|
||||
}
|
||||
/* door sides */
|
||||
if( lvl->Doors.DoorMap[ x ][ y ].vertical )
|
||||
{
|
||||
if( y <= vy )
|
||||
R_Draw_Wall( (float)x, (float)(y-1), LOWERZCOORD, UPPERZCOORD, dir4_north, TEX_PLATE );
|
||||
|
||||
if( y >= vy )
|
||||
R_Draw_Wall( (float)x, (float)(y+1), LOWERZCOORD, UPPERZCOORD, dir4_south, TEX_PLATE );
|
||||
|
||||
if( x <= vx && lvl->tilemap[ x - 1 ][ y ] & WALL_TILE )
|
||||
R_Draw_Wall( (float)(x-1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_east, lvl->wall_tex_x[ x - 1 ][ y ] );
|
||||
|
||||
if( x >= vx && lvl->tilemap[ x + 1 ][ y ] & WALL_TILE )
|
||||
R_Draw_Wall( (float)(x+1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_west, lvl->wall_tex_x[ x + 1 ][ y ] );
|
||||
}
|
||||
else
|
||||
{
|
||||
if( x <= vx )
|
||||
R_Draw_Wall((float)(x-1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_east, TEX_PLATE+1);
|
||||
|
||||
if( x >= vx )
|
||||
R_Draw_Wall((float)(x+1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_west, TEX_PLATE+1);
|
||||
|
||||
if( y <= vy && lvl->tilemap[ x ][ y - 1 ] & WALL_TILE )
|
||||
R_Draw_Wall( (float)x, (float)(y-1), LOWERZCOORD, UPPERZCOORD, dir4_north, lvl->wall_tex_y[x][y-1]);
|
||||
|
||||
if( y >= vy && lvl->tilemap[ x ][ y + 1 ] & WALL_TILE )
|
||||
R_Draw_Wall( (float)x, (float)(y+1), LOWERZCOORD, UPPERZCOORD, dir4_south, lvl->wall_tex_y[x][y+1]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Push-Wall */
|
||||
if( (r_world->tilemap[ x ][ y ] & PUSHWALL_TILE) )
|
||||
{
|
||||
float dx, dy;
|
||||
|
||||
dx = PWall.dx * PWall.PWpointsmoved / 128.0f;
|
||||
dy = PWall.dy * PWall.PWpointsmoved / 128.0f;
|
||||
|
||||
if( PWall.x <= vx )
|
||||
R_Draw_Wall( (float)PWall.x + dx, (float)PWall.y + dy, LOWERZCOORD, UPPERZCOORD, dir4_east, PWall.tex_x );
|
||||
|
||||
if( PWall.x >= vx )
|
||||
R_Draw_Wall( (float)PWall.x + dx, (float)PWall.y + dy, LOWERZCOORD, UPPERZCOORD, dir4_west, PWall.tex_x );
|
||||
|
||||
if( PWall.y <= vy )
|
||||
R_Draw_Wall( (float)PWall.x + dx, (float)PWall.y + dy, LOWERZCOORD, UPPERZCOORD, dir4_north, PWall.tex_y );
|
||||
|
||||
if( PWall.y >= vy )
|
||||
R_Draw_Wall( (float)PWall.x + dx, (float)PWall.y + dy, LOWERZCOORD, UPPERZCOORD, dir4_south, PWall.tex_y );
|
||||
|
||||
}
|
||||
/* x-wall */
|
||||
if( x <= vx && r_world->tilemap[ x - 1 ][ y ] & WALL_TILE )
|
||||
R_Draw_Wall( (float)(x-1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_east, r_world->wall_tex_x[x-1][y]);
|
||||
|
||||
if( x >= vx && r_world->tilemap[ x + 1 ][ y ] & WALL_TILE )
|
||||
R_Draw_Wall( (float)(x+1), (float)y, LOWERZCOORD, UPPERZCOORD, dir4_west, r_world->wall_tex_x[x+1][y]);
|
||||
|
||||
/* y-wall */
|
||||
if( y <= vy && r_world->tilemap[ x ][ y - 1 ] & WALL_TILE )
|
||||
R_Draw_Wall( (float)x, (float)(y-1), LOWERZCOORD, UPPERZCOORD, dir4_north, r_world->wall_tex_y[x][y-1]);
|
||||
|
||||
if( y >= vy && r_world->tilemap[ x ][ y + 1 ] & WALL_TILE )
|
||||
R_Draw_Wall( (float)x, (float)(y+1), LOWERZCOORD, UPPERZCOORD, dir4_south, r_world->wall_tex_y[x][y+1]);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// back to full brightness in case the last draw was a dim wall
|
||||
pfglColor3f( 1, 1, 1 );
|
||||
}
|
||||
|
||||
|
||||
int x_tile_step[ 4 ] = { 1, -1, -1, 1 };
|
||||
int y_tile_step[ 4 ] = { 1, 1, -1, -1 };
|
||||
|
||||
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
Function: R_TraceCheck() -Trace ray check.
|
||||
|
||||
Parameters:
|
||||
lvl -[in] Pointer to valid LevelData_t structure.
|
||||
x, y -[in] In tiles.
|
||||
|
||||
Returns: true to stop tracing, false otherwise.
|
||||
|
||||
Notes: Tells ray casting if we hit a wall or door and to stop tracing.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
PRIVATE _boolean R_TraceCheck( LevelData_t *lvl, int x, int y, int frac, int dfrac, _boolean vert, _boolean flip, r_trace_t *trace )
|
||||
{
|
||||
if( lvl->tilemap[ x ][ y ] & WALL_TILE )
|
||||
{
|
||||
if( vert )
|
||||
{
|
||||
trace->x = (x << TILESHIFT) + (flip ? TILEGLOBAL : 0);
|
||||
trace->y = (y << TILESHIFT) + frac;
|
||||
trace->flags |= TRACE_HIT_VERT;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace->x = (x << TILESHIFT) + frac;
|
||||
trace->y = (y << TILESHIFT) + (flip ? TILEGLOBAL : 0);
|
||||
trace->flags &= ~TRACE_HIT_VERT;
|
||||
}
|
||||
|
||||
return true; // wall, stop tracing
|
||||
}
|
||||
|
||||
if( trace->tile_vis )
|
||||
{
|
||||
trace->tile_vis[ x ][ y ] = true; // this tile is visible
|
||||
}
|
||||
|
||||
|
||||
if( lvl->tilemap[ x ][ y ] & DOOR_TILE &&
|
||||
lvl->Doors.DoorMap[ x ][ y ].action != dr_open )
|
||||
{
|
||||
frac += dfrac >> 1;
|
||||
if( POS2TILE( frac ) )
|
||||
return false;
|
||||
|
||||
if( vert )
|
||||
{
|
||||
if( lvl->Doors.DoorMap[ x ][ y ].action != dr_closed &&
|
||||
(frac >> 10) > DOOR_FULLOPEN - Door_Opened( &lvl->Doors, x, y ) )
|
||||
{
|
||||
return false; // opened enough
|
||||
}
|
||||
|
||||
trace->x = TILE2POS( x );
|
||||
trace->y = (y << TILESHIFT) + frac;
|
||||
trace->flags |= TRACE_HIT_VERT;
|
||||
}
|
||||
else
|
||||
{
|
||||
if( lvl->Doors.DoorMap[ x ][ y ].action != dr_closed &&
|
||||
(frac >> 10) < Door_Opened( &lvl->Doors, x, y ) )
|
||||
{
|
||||
return false; // opened enough
|
||||
}
|
||||
|
||||
trace->y = TILE2POS( y );
|
||||
trace->x = (x << TILESHIFT) + frac;
|
||||
trace->flags &= ~TRACE_HIT_VERT;
|
||||
}
|
||||
trace->flags |= TRACE_HIT_DOOR;
|
||||
|
||||
return true; // closed door, stop tracing
|
||||
}
|
||||
|
||||
return false; // no intersection, go on!
|
||||
}
|
||||
|
||||
/*
|
||||
-----------------------------------------------------------------------------
|
||||
Function: R_Trace() -Trace ray.
|
||||
|
||||
Parameters:
|
||||
trace -[in] Pointer to valid r_trace_t structure.
|
||||
lvl -[in] Pointer to valid LevelData_t structure.
|
||||
|
||||
|
||||
Returns: Nothing.
|
||||
|
||||
Notes:
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
*/
|
||||
PUBLIC void R_Trace( r_trace_t *trace, LevelData_t *lvl )
|
||||
{
|
||||
int xtilestep, ytilestep;
|
||||
int xstep, ystep;
|
||||
int xtile, ytile;
|
||||
int xintercept, yintercept;
|
||||
int YmapPos, XmapPos;
|
||||
quadrant q;
|
||||
|
||||
// Setup for ray casting
|
||||
q = GetQuadrant( FINE2RAD( trace->a ) );
|
||||
|
||||
xtilestep = x_tile_step[ q ];
|
||||
ytilestep = y_tile_step[ q ];
|
||||
|
||||
xtile = POS2TILE( trace->x ) + xtilestep;
|
||||
ytile = POS2TILE( trace->y ) + ytilestep;
|
||||
|
||||
xstep = ytilestep * XnextTable[ trace->a ];
|
||||
ystep = xtilestep * YnextTable[ trace->a ];
|
||||
|
||||
xintercept = (int)( ( ((ytilestep == -1 ? ytile+1 : ytile) << TILESHIFT) - trace->y ) / TanTable[ trace->a ]) + trace->x;
|
||||
yintercept = (int)( ( ((xtilestep == -1 ? xtile+1 : xtile) << TILESHIFT) - trace->x ) * TanTable[ trace->a ]) + trace->y;
|
||||
|
||||
YmapPos = yintercept >> TILESHIFT; // toXray
|
||||
XmapPos = xintercept >> TILESHIFT; // toYray
|
||||
|
||||
if( trace->tile_vis )
|
||||
{
|
||||
// this tile is visible
|
||||
trace->tile_vis[ POS2TILE( trace->x ) ][ POS2TILE( trace->y ) ] = true;
|
||||
}
|
||||
|
||||
//
|
||||
// Start of ray-casting
|
||||
//
|
||||
while( 1 )
|
||||
{
|
||||
//
|
||||
// Vertical loop // an anologue for X-Ray
|
||||
//
|
||||
while( ! (ytilestep == -1 && YmapPos <= ytile) && ! (ytilestep == 1 && YmapPos >= ytile) )
|
||||
{
|
||||
if( xtile < 0 || xtile >= 64 || YmapPos < 0 || YmapPos >= 64 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( R_TraceCheck( lvl, xtile, YmapPos, yintercept % TILEGLOBAL, ystep, true, (_boolean)(xtilestep == -1), trace ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// prepare for next step
|
||||
xtile += xtilestep;
|
||||
yintercept += ystep;
|
||||
YmapPos = yintercept >> TILESHIFT;
|
||||
}
|
||||
|
||||
//
|
||||
// Horizontal loop // an anologue for Y-Ray
|
||||
//
|
||||
while( ! (xtilestep == -1 && XmapPos <= xtile) && ! (xtilestep == 1 && XmapPos >= xtile) )
|
||||
{
|
||||
if( ytile < 0 || ytile >= 64 || XmapPos < 0 || XmapPos >= 64 )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if( R_TraceCheck( lvl, XmapPos, ytile, xintercept % TILEGLOBAL, xstep, false, (_boolean)(ytilestep == -1), trace ) )
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// prepare for next step
|
||||
ytile += ytilestep;
|
||||
xintercept += xstep;
|
||||
XmapPos = xintercept >> TILESHIFT;
|
||||
}
|
||||
|
||||
} // end of while( 1 )
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user