mirror of
https://github.com/ZDoom/qzdoom.git
synced 2025-03-15 23:40:52 +00:00
Merge branch 'master' of https://github.com/coelckers/gzdoom
This commit is contained in:
commit
9f70db98fd
481 changed files with 6616 additions and 9356 deletions
|
@ -14,7 +14,7 @@ environment:
|
|||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
|
||||
- GENERATOR: "Visual Studio 14 2015 Win64"
|
||||
CONFIGURATION: Release
|
||||
TOOLSET: v140_xp
|
||||
TOOLSET: v140
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
|
||||
- GENERATOR: "Visual Studio 15 2017"
|
||||
CONFIGURATION: Release
|
||||
|
@ -22,11 +22,11 @@ environment:
|
|||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
|
||||
- GENERATOR: "Visual Studio 15 2017 Win64"
|
||||
CONFIGURATION: Release
|
||||
TOOLSET: v141_xp
|
||||
TOOLSET: v141
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2017"
|
||||
- GENERATOR: "Visual Studio 14 2015 Win64"
|
||||
CONFIGURATION: Debug
|
||||
TOOLSET: v140
|
||||
TOOLSET: v140_xp
|
||||
APPVEYOR_BUILD_WORKER_IMAGE: "Visual Studio 2015"
|
||||
|
||||
build_script:
|
||||
|
|
|
@ -11,7 +11,12 @@ git:
|
|||
matrix:
|
||||
include:
|
||||
- os: osx
|
||||
osx_image: xcode9.2
|
||||
osx_image: xcode8
|
||||
env:
|
||||
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Debug -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7"
|
||||
|
||||
- os: osx
|
||||
osx_image: xcode9.3
|
||||
env:
|
||||
- CMAKE_OPTIONS="-DCMAKE_BUILD_TYPE=Release -DCMAKE_OSX_DEPLOYMENT_TARGET=10.7"
|
||||
|
||||
|
|
|
@ -14,8 +14,19 @@ function(enable_precompiled_headers PRECOMPILED_HEADER SOURCE_VARIABLE_NAME)
|
|||
get_filename_component(pch_basename ${PRECOMPILED_HEADER} NAME_WE)
|
||||
set(pch_abs ${CMAKE_CURRENT_SOURCE_DIR}/${PRECOMPILED_HEADER})
|
||||
set(pch_unity ${CMAKE_CURRENT_BINARY_DIR}/${pch_basename}.cpp)
|
||||
FILE(WRITE ${pch_unity} "// Precompiled header unity generated by CMake\n")
|
||||
FILE(APPEND ${pch_unity} "#include <${pch_abs}>\n")
|
||||
set(pch_content "// Precompiled header unity generated by CMake\n#include <${pch_abs}>\n")
|
||||
# Read .cpp if exists
|
||||
if(EXISTS ${pch_unity})
|
||||
file(READ ${pch_unity} pch_content_prev)
|
||||
endif()
|
||||
# Compare existing .cpp content with the actual one
|
||||
if (pch_content_prev AND pch_content STREQUAL pch_content_prev)
|
||||
unset(pch_content)
|
||||
endif()
|
||||
# Write .cpp if it's out-of-date
|
||||
if (pch_content)
|
||||
FILE(WRITE ${pch_unity} "${pch_content}")
|
||||
endif()
|
||||
set_source_files_properties(${pch_unity} PROPERTIES COMPILE_FLAGS "/Yc\"${pch_abs}\"")
|
||||
|
||||
# Update properties of source files to use the precompiled header.
|
||||
|
|
|
@ -62,21 +62,6 @@ if( WIN32 )
|
|||
set( DX_dinput8_LIBRARY dinput8 )
|
||||
else()
|
||||
|
||||
find_path( D3D_INCLUDE_DIR d3d9.h
|
||||
PATHS ENV DXSDK_DIR
|
||||
PATH_SUFFIXES Include )
|
||||
if( NOT D3D_INCLUDE_DIR )
|
||||
# Modern versions of the Windows SDK include d3d9.h. Unfortunately,
|
||||
# CMake cannot find this file via find_path, so we check for it using
|
||||
# CHECK_INCLUDE_FILE.
|
||||
CHECK_INCLUDE_FILE( d3d9.h D3D9_H_FOUND )
|
||||
if ( NOT D3D9_H_FOUND )
|
||||
message( SEND_ERROR "Could not find DirectX 9 header files" )
|
||||
endif()
|
||||
else()
|
||||
include_directories( ${D3D_INCLUDE_DIR} )
|
||||
endif()
|
||||
|
||||
find_path( XINPUT_INCLUDE_DIR xinput.h
|
||||
PATHS ENV DXSDK_DIR
|
||||
PATH_SUFFIXES Include )
|
||||
|
@ -652,19 +637,7 @@ add_definitions(-DADLMIDI_DISABLE_MUS_SUPPORT -DADLMIDI_DISABLE_XMI_SUPPORT -DAD
|
|||
|
||||
# Project files should be aware of the header files. We can GLOB these since
|
||||
# there's generally a new cpp for every header so this file will get changed
|
||||
if( WIN32 )
|
||||
set( EXTRA_HEADER_DIRS win32/*.h )
|
||||
elseif( APPLE )
|
||||
if( OSX_COCOA_BACKEND )
|
||||
set( EXTRA_HEADER_DIRS posix/*.h posix/cocoa/*.h )
|
||||
else()
|
||||
set( EXTRA_HEADER_DIRS posix/*.h posix/sdl/*.h )
|
||||
endif()
|
||||
else()
|
||||
set( EXTRA_HEADER_DIRS posix/*.h posix/sdl/*.h )
|
||||
endif()
|
||||
file( GLOB HEADER_FILES
|
||||
${EXTRA_HEADER_DIRS}
|
||||
fragglescript/*.h
|
||||
g_shared/*.h
|
||||
g_statusbar/*.h
|
||||
|
@ -678,6 +651,7 @@ file( GLOB HEADER_FILES
|
|||
posix/*.h
|
||||
posix/cocoa/*.h
|
||||
posix/sdl/*.h
|
||||
win32/*.h
|
||||
r_data/*.h
|
||||
r_data/models/*.h
|
||||
rapidjson/*.h
|
||||
|
@ -713,8 +687,12 @@ file( GLOB HEADER_FILES
|
|||
polyrenderer/math/*.h
|
||||
polyrenderer/drawers/*.h
|
||||
polyrenderer/scene/*.h
|
||||
hwrenderer/data/*.h
|
||||
hwrenderer/dynlights/*.h
|
||||
hwrenderer/scene/*.h
|
||||
hwrenderer/textures/*.h
|
||||
hwrenderer/utilities/*.h
|
||||
gl/*.h
|
||||
gl/api/*.h
|
||||
gl/data/*.h
|
||||
gl/dynlights/*.h
|
||||
gl/models/*.h
|
||||
|
@ -817,7 +795,7 @@ set( NOT_COMPILED_SOURCE_FILES
|
|||
)
|
||||
|
||||
# This is disabled for now because I cannot find a way to give the .pch file a different name.
|
||||
# Visual C++ 2015 seems hell-bent of only allowing one .pch file with the same name as the executable.
|
||||
# Visual C++ 2015 seems hell-bent on only allowing one .pch file with the same name as the executable.
|
||||
#enable_precompiled_headers( g_pch2.h FASTMATH_PCH_SOURCES )
|
||||
|
||||
# Enable fast math for some sources
|
||||
|
@ -831,7 +809,6 @@ set( FASTMATH_SOURCES
|
|||
sound/sndfile_decoder.cpp
|
||||
sound/timiditypp/fft4g.cpp
|
||||
sound/timiditypp/reverb.cpp
|
||||
gl/utility/gl_clock.cpp
|
||||
textures/hires/hqnx/init.cpp
|
||||
textures/hires/hqnx/hq2x.cpp
|
||||
textures/hires/hqnx/hq3x.cpp
|
||||
|
@ -839,26 +816,28 @@ set( FASTMATH_SOURCES
|
|||
textures/hires/xbr/xbrz.cpp
|
||||
textures/hires/xbr/xbrz_old.cpp
|
||||
gl/scene/gl_bsp.cpp
|
||||
gl/scene/gl_fakeflat.cpp
|
||||
gl/scene/gl_clipper.cpp
|
||||
gl/scene/gl_decal.cpp
|
||||
gl/scene/gl_drawinfo.cpp
|
||||
gl/scene/gl_flats.cpp
|
||||
gl/scene/gl_walls.cpp
|
||||
gl/scene/gl_sprite.cpp
|
||||
gl/scene/gl_skydome.cpp
|
||||
gl/scene/gl_renderhacks.cpp
|
||||
gl/scene/gl_weapon.cpp
|
||||
gl/scene/gl_scene.cpp
|
||||
gl/scene/gl_swscene.cpp
|
||||
gl/scene/gl_sky.cpp
|
||||
gl/scene/gl_portal.cpp
|
||||
gl/scene/gl_walls_draw.cpp
|
||||
gl/scene/gl_vertex.cpp
|
||||
gl/scene/gl_spritelight.cpp
|
||||
gl/dynlights/gl_dynlight1.cpp
|
||||
gl_load/gl_load.c
|
||||
gl/models/gl_models.cpp
|
||||
hwrenderer/dynlights/hw_dynlightdata.cpp
|
||||
hwrenderer/scene/hw_fakeflat.cpp
|
||||
hwrenderer/scene/hw_decal.cpp
|
||||
hwrenderer/scene/hw_drawlist.cpp
|
||||
hwrenderer/scene/hw_clipper.cpp
|
||||
hwrenderer/scene/hw_flats.cpp
|
||||
hwrenderer/scene/hw_renderhacks.cpp
|
||||
hwrenderer/scene/hw_sky.cpp
|
||||
hwrenderer/scene/hw_sprites.cpp
|
||||
hwrenderer/scene/hw_spritelight.cpp
|
||||
hwrenderer/scene/hw_walls.cpp
|
||||
hwrenderer/scene/hw_walls_vertex.cpp
|
||||
r_data/models/models.cpp
|
||||
r_data/matrix.cpp
|
||||
sound/adlmidi/adldata.cpp
|
||||
|
@ -933,7 +912,6 @@ set (PCH_SOURCES
|
|||
i_time.cpp
|
||||
info.cpp
|
||||
keysections.cpp
|
||||
lumpconfigfile.cpp
|
||||
m_alloc.cpp
|
||||
m_argv.cpp
|
||||
m_bbox.cpp
|
||||
|
@ -1045,6 +1023,7 @@ set (PCH_SOURCES
|
|||
gl/data/gl_vertexbuffer.cpp
|
||||
gl/dynlights/gl_lightbuffer.cpp
|
||||
gl/dynlights/gl_shadowmap.cpp
|
||||
gl/models/gl_models.cpp
|
||||
gl/renderer/gl_quaddrawer.cpp
|
||||
gl/renderer/gl_renderer.cpp
|
||||
gl/renderer/gl_renderstate.cpp
|
||||
|
@ -1076,14 +1055,18 @@ set (PCH_SOURCES
|
|||
gl/system/gl_interface.cpp
|
||||
gl/system/gl_framebuffer.cpp
|
||||
gl/system/gl_debug.cpp
|
||||
gl/system/gl_menu.cpp
|
||||
gl/system/gl_wipe.cpp
|
||||
gl/textures/gl_hwtexture.cpp
|
||||
gl/textures/gl_texture.cpp
|
||||
gl/textures/gl_material.cpp
|
||||
gl/textures/gl_samplers.cpp
|
||||
hwrenderer/data/flatvertices.cpp
|
||||
hwrenderer/dynlights/hw_aabbtree.cpp
|
||||
hwrenderer/dynlights/hw_shadowmap.cpp
|
||||
hwrenderer/scene/hw_skydome.cpp
|
||||
hwrenderer/textures/hw_material.cpp
|
||||
hwrenderer/textures/hw_precache.cpp
|
||||
hwrenderer/utility/hw_clock.cpp
|
||||
hwrenderer/utility/hw_cvars.cpp
|
||||
hwrenderer/utility/hw_lighting.cpp
|
||||
|
||||
menu/joystickmenu.cpp
|
||||
menu/loadsavemenu.cpp
|
||||
|
@ -1242,8 +1225,6 @@ set (PCH_SOURCES
|
|||
sound/wildmidi/wildmidi_lib.cpp
|
||||
sound/wildmidi/wm_error.cpp
|
||||
events.cpp
|
||||
GuillotineBinPack.cpp
|
||||
SkylineBinPack.cpp
|
||||
)
|
||||
|
||||
enable_precompiled_headers( g_pch.h PCH_SOURCES )
|
||||
|
@ -1284,9 +1265,6 @@ set_source_files_properties( ${FASTMATH_SOURCES} PROPERTIES COMPILE_FLAGS ${ZD_F
|
|||
set_source_files_properties( xlat/parse_xlat.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/xlat_parser.c" )
|
||||
set_source_files_properties( sc_man.cpp PROPERTIES OBJECT_DEPENDS "${CMAKE_CURRENT_BINARY_DIR}/sc_man_scanner.h" )
|
||||
set_source_files_properties( ${NOT_COMPILED_SOURCE_FILES} PROPERTIES HEADER_FILE_ONLY TRUE )
|
||||
if ( WIN32 )
|
||||
set_source_files_properties( win32/fb_d3d9.cpp win32/fb_d3d9_wipe.cpp PROPERTIES COMPILE_FLAGS ${ZD_FASTMATH_FLAG} )
|
||||
endif()
|
||||
|
||||
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "SunOS")
|
||||
|
|
|
@ -1,643 +0,0 @@
|
|||
/** @file GuillotineBinPack.cpp
|
||||
@author Jukka Jylänki
|
||||
|
||||
@brief Implements different bin packer algorithms that use the GUILLOTINE data structure.
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <limits.h>
|
||||
#include "templates.h"
|
||||
#include "GuillotineBinPack.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
GuillotineBinPack::GuillotineBinPack()
|
||||
:binWidth(0),
|
||||
binHeight(0)
|
||||
{
|
||||
}
|
||||
|
||||
GuillotineBinPack::GuillotineBinPack(int width, int height)
|
||||
{
|
||||
Init(width, height);
|
||||
}
|
||||
|
||||
void GuillotineBinPack::Init(int width, int height)
|
||||
{
|
||||
binWidth = width;
|
||||
binHeight = height;
|
||||
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Clear();
|
||||
#endif
|
||||
|
||||
// Clear any memory of previously packed rectangles.
|
||||
usedRectangles.Clear();
|
||||
|
||||
// We start with a single big free rectangle that spans the whole bin.
|
||||
Rect n;
|
||||
n.x = 0;
|
||||
n.y = 0;
|
||||
n.width = width;
|
||||
n.height = height;
|
||||
|
||||
freeRectangles.Clear();
|
||||
freeRectangles.Push(n);
|
||||
}
|
||||
|
||||
void GuillotineBinPack::Insert(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
|
||||
FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
dst.Clear();
|
||||
|
||||
// Remember variables about the best packing choice we have made so far during the iteration process.
|
||||
int bestFreeRect = 0;
|
||||
int bestRect = 0;
|
||||
bool bestFlipped = false;
|
||||
|
||||
// Pack rectangles one at a time until we have cleared the rects array of all rectangles.
|
||||
// rects will get destroyed in the process.
|
||||
while(rects.Size() > 0)
|
||||
{
|
||||
// Stores the penalty score of the best rectangle placement - bigger=worse, smaller=better.
|
||||
int bestScore = INT_MAX;
|
||||
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
{
|
||||
for(unsigned j = 0; j < rects.Size(); ++j)
|
||||
{
|
||||
// If this rectangle is a perfect match, we pick it instantly.
|
||||
if (rects[j].width == freeRectangles[i].width && rects[j].height == freeRectangles[i].height)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = false;
|
||||
bestScore = INT_MIN;
|
||||
i = freeRectangles.Size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||
break;
|
||||
}
|
||||
// If flipping this rectangle is a perfect match, pick that then.
|
||||
else if (rects[j].height == freeRectangles[i].width && rects[j].width == freeRectangles[i].height)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = true;
|
||||
bestScore = INT_MIN;
|
||||
i = freeRectangles.Size(); // Force a jump out of the outer loop as well - we got an instant fit.
|
||||
break;
|
||||
}
|
||||
// Try if we can fit the rectangle upright.
|
||||
else if (rects[j].width <= freeRectangles[i].width && rects[j].height <= freeRectangles[i].height)
|
||||
{
|
||||
int score = ScoreByHeuristic(rects[j].width, rects[j].height, freeRectangles[i], rectChoice);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = false;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
// If not, then perhaps flipping sideways will make it fit?
|
||||
else if (rects[j].height <= freeRectangles[i].width && rects[j].width <= freeRectangles[i].height)
|
||||
{
|
||||
int score = ScoreByHeuristic(rects[j].height, rects[j].width, freeRectangles[i], rectChoice);
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestFreeRect = i;
|
||||
bestRect = j;
|
||||
bestFlipped = true;
|
||||
bestScore = score;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// If we didn't manage to find any rectangle to pack, abort.
|
||||
if (bestScore == INT_MAX)
|
||||
return;
|
||||
|
||||
// Otherwise, we're good to go and do the actual packing.
|
||||
Rect newNode;
|
||||
newNode.x = freeRectangles[bestFreeRect].x;
|
||||
newNode.y = freeRectangles[bestFreeRect].y;
|
||||
newNode.width = rects[bestRect].width;
|
||||
newNode.height = rects[bestRect].height;
|
||||
|
||||
if (bestFlipped)
|
||||
std::swap(newNode.width, newNode.height);
|
||||
|
||||
// Remove the free space we lost in the bin.
|
||||
SplitFreeRectByHeuristic(freeRectangles[bestFreeRect], newNode, splitMethod);
|
||||
freeRectangles.Delete(bestFreeRect);
|
||||
|
||||
// Remove the rectangle we just packed from the input list.
|
||||
rects.Delete(bestRect);
|
||||
|
||||
// Perform a Rectangle Merge step if desired.
|
||||
if (merge)
|
||||
MergeFreeList();
|
||||
|
||||
// Remember the new used rectangle.
|
||||
usedRectangles.Push(newNode);
|
||||
|
||||
// Check that we're really producing correct packings here.
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Add(newNode) == true);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
/// @return True if r fits inside freeRect (possibly rotated).
|
||||
bool Fits(const RectSize &r, const Rect &freeRect)
|
||||
{
|
||||
return (r.width <= freeRect.width && r.height <= freeRect.height) ||
|
||||
(r.height <= freeRect.width && r.width <= freeRect.height);
|
||||
}
|
||||
|
||||
/// @return True if r fits perfectly inside freeRect, i.e. the leftover area is 0.
|
||||
bool FitsPerfectly(const RectSize &r, const Rect &freeRect)
|
||||
{
|
||||
return (r.width == freeRect.width && r.height == freeRect.height) ||
|
||||
(r.height == freeRect.width && r.width == freeRect.height);
|
||||
}
|
||||
|
||||
/*
|
||||
// A helper function for GUILLOTINE-MAXFITTING. Counts how many rectangles fit into the given rectangle
|
||||
// after it has been split.
|
||||
void CountNumFitting(const Rect &freeRect, int width, int height, const TArray<RectSize> &rects,
|
||||
int usedRectIndex, bool splitHorizontal, int &score1, int &score2)
|
||||
{
|
||||
const int w = freeRect.width - width;
|
||||
const int h = freeRect.height - height;
|
||||
|
||||
Rect bottom;
|
||||
bottom.x = freeRect.x;
|
||||
bottom.y = freeRect.y + height;
|
||||
bottom.height = h;
|
||||
|
||||
Rect right;
|
||||
right.x = freeRect.x + width;
|
||||
right.y = freeRect.y;
|
||||
right.width = w;
|
||||
|
||||
if (splitHorizontal)
|
||||
{
|
||||
bottom.width = freeRect.width;
|
||||
right.height = height;
|
||||
}
|
||||
else // Split vertically
|
||||
{
|
||||
bottom.width = width;
|
||||
right.height = freeRect.height;
|
||||
}
|
||||
|
||||
int fitBottom = 0;
|
||||
int fitRight = 0;
|
||||
for(size_t i = 0; i < rects.size(); ++i)
|
||||
if (i != usedRectIndex)
|
||||
{
|
||||
if (FitsPerfectly(rects[i], bottom))
|
||||
fitBottom |= 0x10000000;
|
||||
if (FitsPerfectly(rects[i], right))
|
||||
fitRight |= 0x10000000;
|
||||
|
||||
if (Fits(rects[i], bottom))
|
||||
++fitBottom;
|
||||
if (Fits(rects[i], right))
|
||||
++fitRight;
|
||||
}
|
||||
|
||||
score1 = min(fitBottom, fitRight);
|
||||
score2 = max(fitBottom, fitRight);
|
||||
}
|
||||
*/
|
||||
/*
|
||||
// Implements GUILLOTINE-MAXFITTING, an experimental heuristic that's really cool but didn't quite work in practice.
|
||||
void GuillotineBinPack::InsertMaxFitting(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
|
||||
FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
dst.clear();
|
||||
int bestRect = 0;
|
||||
bool bestFlipped = false;
|
||||
bool bestSplitHorizontal = false;
|
||||
|
||||
// Pick rectangles one at a time and pack the one that leaves the most choices still open.
|
||||
while(rects.size() > 0 && freeRectangles.size() > 0)
|
||||
{
|
||||
int bestScore1 = -1;
|
||||
int bestScore2 = -1;
|
||||
|
||||
///\todo Different sort predicates.
|
||||
clb::sort::QuickSort(&freeRectangles[0], freeRectangles.size(), CompareRectShortSide);
|
||||
|
||||
Rect &freeRect = freeRectangles[0];
|
||||
|
||||
for(size_t j = 0; j < rects.size(); ++j)
|
||||
{
|
||||
int score1;
|
||||
int score2;
|
||||
|
||||
if (rects[j].width == freeRect.width && rects[j].height == freeRect.height)
|
||||
{
|
||||
bestRect = j;
|
||||
bestFlipped = false;
|
||||
bestScore1 = bestScore2 = std::numeric_limits<int>::max();
|
||||
break;
|
||||
}
|
||||
else if (rects[j].width <= freeRect.width && rects[j].height <= freeRect.height)
|
||||
{
|
||||
CountNumFitting(freeRect, rects[j].width, rects[j].height, rects, j, false, score1, score2);
|
||||
|
||||
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
|
||||
{
|
||||
bestRect = j;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestFlipped = false;
|
||||
bestSplitHorizontal = false;
|
||||
}
|
||||
|
||||
CountNumFitting(freeRect, rects[j].width, rects[j].height, rects, j, true, score1, score2);
|
||||
|
||||
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
|
||||
{
|
||||
bestRect = j;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestFlipped = false;
|
||||
bestSplitHorizontal = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (rects[j].height == freeRect.width && rects[j].width == freeRect.height)
|
||||
{
|
||||
bestRect = j;
|
||||
bestFlipped = true;
|
||||
bestScore1 = bestScore2 = std::numeric_limits<int>::max();
|
||||
break;
|
||||
}
|
||||
else if (rects[j].height <= freeRect.width && rects[j].width <= freeRect.height)
|
||||
{
|
||||
CountNumFitting(freeRect, rects[j].height, rects[j].width, rects, j, false, score1, score2);
|
||||
|
||||
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
|
||||
{
|
||||
bestRect = j;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestFlipped = true;
|
||||
bestSplitHorizontal = false;
|
||||
}
|
||||
|
||||
CountNumFitting(freeRect, rects[j].height, rects[j].width, rects, j, true, score1, score2);
|
||||
|
||||
if (score1 > bestScore1 || (score1 == bestScore1 && score2 > bestScore2))
|
||||
{
|
||||
bestRect = j;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestFlipped = true;
|
||||
bestSplitHorizontal = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestScore1 >= 0)
|
||||
{
|
||||
Rect newNode;
|
||||
newNode.x = freeRect.x;
|
||||
newNode.y = freeRect.y;
|
||||
newNode.width = rects[bestRect].width;
|
||||
newNode.height = rects[bestRect].height;
|
||||
if (bestFlipped)
|
||||
std::swap(newNode.width, newNode.height);
|
||||
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
SplitFreeRectAlongAxis(freeRect, newNode, bestSplitHorizontal);
|
||||
|
||||
rects.erase(rects.begin() + bestRect);
|
||||
|
||||
if (merge)
|
||||
MergeFreeList();
|
||||
|
||||
usedRectangles.push_back(newNode);
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Add(newNode);
|
||||
#endif
|
||||
}
|
||||
|
||||
freeRectangles.erase(freeRectangles.begin());
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
Rect GuillotineBinPack::Insert(int width, int height, bool merge, FreeRectChoiceHeuristic rectChoice,
|
||||
GuillotineSplitHeuristic splitMethod)
|
||||
{
|
||||
// Find where to put the new rectangle.
|
||||
int freeNodeIndex = 0;
|
||||
Rect newRect = FindPositionForNewNode(width, height, rectChoice, &freeNodeIndex);
|
||||
|
||||
// Abort if we didn't have enough space in the bin.
|
||||
if (newRect.height == 0)
|
||||
return newRect;
|
||||
|
||||
// Remove the space that was just consumed by the new rectangle.
|
||||
SplitFreeRectByHeuristic(freeRectangles[freeNodeIndex], newRect, splitMethod);
|
||||
freeRectangles.Delete(freeNodeIndex);
|
||||
|
||||
// Perform a Rectangle Merge step if desired.
|
||||
if (merge)
|
||||
MergeFreeList();
|
||||
|
||||
// Remember the new used rectangle.
|
||||
usedRectangles.Push(newRect);
|
||||
|
||||
// Check that we're really producing correct packings here.
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Add(newRect) == true);
|
||||
#endif
|
||||
return newRect;
|
||||
}
|
||||
|
||||
/// Computes the ratio of used surface area to the total bin area.
|
||||
float GuillotineBinPack::Occupancy() const
|
||||
{
|
||||
///\todo The occupancy rate could be cached/tracked incrementally instead
|
||||
/// of looping through the list of packed rectangles here.
|
||||
unsigned long usedSurfaceArea = 0;
|
||||
for(unsigned i = 0; i < usedRectangles.Size(); ++i)
|
||||
usedSurfaceArea += usedRectangles[i].width * usedRectangles[i].height;
|
||||
|
||||
return (float)usedSurfaceArea / (binWidth * binHeight);
|
||||
}
|
||||
|
||||
/// Returns the heuristic score value for placing a rectangle of size width*height into freeRect. Does not try to rotate.
|
||||
int GuillotineBinPack::ScoreByHeuristic(int width, int height, const Rect &freeRect, FreeRectChoiceHeuristic rectChoice)
|
||||
{
|
||||
switch(rectChoice)
|
||||
{
|
||||
case RectBestAreaFit: return ScoreBestAreaFit(width, height, freeRect);
|
||||
case RectBestShortSideFit: return ScoreBestShortSideFit(width, height, freeRect);
|
||||
case RectBestLongSideFit: return ScoreBestLongSideFit(width, height, freeRect);
|
||||
case RectWorstAreaFit: return ScoreWorstAreaFit(width, height, freeRect);
|
||||
case RectWorstShortSideFit: return ScoreWorstShortSideFit(width, height, freeRect);
|
||||
case RectWorstLongSideFit: return ScoreWorstLongSideFit(width, height, freeRect);
|
||||
default: assert(false); return INT_MAX;
|
||||
}
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreBestAreaFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
return freeRect.width * freeRect.height - width * height;
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreBestShortSideFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
int leftoverHoriz = abs(freeRect.width - width);
|
||||
int leftoverVert = abs(freeRect.height - height);
|
||||
int leftover = MIN(leftoverHoriz, leftoverVert);
|
||||
return leftover;
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreBestLongSideFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
int leftoverHoriz = abs(freeRect.width - width);
|
||||
int leftoverVert = abs(freeRect.height - height);
|
||||
int leftover = MAX(leftoverHoriz, leftoverVert);
|
||||
return leftover;
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreWorstAreaFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
return -ScoreBestAreaFit(width, height, freeRect);
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreWorstShortSideFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
return -ScoreBestShortSideFit(width, height, freeRect);
|
||||
}
|
||||
|
||||
int GuillotineBinPack::ScoreWorstLongSideFit(int width, int height, const Rect &freeRect)
|
||||
{
|
||||
return -ScoreBestLongSideFit(width, height, freeRect);
|
||||
}
|
||||
|
||||
Rect GuillotineBinPack::FindPositionForNewNode(int width, int height, FreeRectChoiceHeuristic rectChoice, int *nodeIndex)
|
||||
{
|
||||
Rect bestNode;
|
||||
memset(&bestNode, 0, sizeof(Rect));
|
||||
|
||||
int bestScore = INT_MAX;
|
||||
|
||||
/// Try each free rectangle to find the best one for placement.
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
{
|
||||
// If this is a perfect fit upright, choose it immediately.
|
||||
if (width == freeRectangles[i].width && height == freeRectangles[i].height)
|
||||
{
|
||||
bestNode.x = freeRectangles[i].x;
|
||||
bestNode.y = freeRectangles[i].y;
|
||||
bestNode.width = width;
|
||||
bestNode.height = height;
|
||||
bestScore = INT_MIN;
|
||||
*nodeIndex = i;
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
// If this is a perfect fit sideways, choose it.
|
||||
/* else if (height == freeRectangles[i].width && width == freeRectangles[i].height)
|
||||
{
|
||||
bestNode.x = freeRectangles[i].x;
|
||||
bestNode.y = freeRectangles[i].y;
|
||||
bestNode.width = height;
|
||||
bestNode.height = width;
|
||||
bestScore = INT_MIN;
|
||||
*nodeIndex = i;
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
break;
|
||||
}
|
||||
*/ // Does the rectangle fit upright?
|
||||
else if (width <= freeRectangles[i].width && height <= freeRectangles[i].height)
|
||||
{
|
||||
int score = ScoreByHeuristic(width, height, freeRectangles[i], rectChoice);
|
||||
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestNode.x = freeRectangles[i].x;
|
||||
bestNode.y = freeRectangles[i].y;
|
||||
bestNode.width = width;
|
||||
bestNode.height = height;
|
||||
bestScore = score;
|
||||
*nodeIndex = i;
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
// Does the rectangle fit sideways?
|
||||
/* else if (height <= freeRectangles[i].width && width <= freeRectangles[i].height)
|
||||
{
|
||||
int score = ScoreByHeuristic(height, width, freeRectangles[i], rectChoice);
|
||||
|
||||
if (score < bestScore)
|
||||
{
|
||||
bestNode.x = freeRectangles[i].x;
|
||||
bestNode.y = freeRectangles[i].y;
|
||||
bestNode.width = height;
|
||||
bestNode.height = width;
|
||||
bestScore = score;
|
||||
*nodeIndex = i;
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
}
|
||||
}
|
||||
*/ }
|
||||
return bestNode;
|
||||
}
|
||||
|
||||
void GuillotineBinPack::SplitFreeRectByHeuristic(const Rect &freeRect, const Rect &placedRect, GuillotineSplitHeuristic method)
|
||||
{
|
||||
// Compute the lengths of the leftover area.
|
||||
const int w = freeRect.width - placedRect.width;
|
||||
const int h = freeRect.height - placedRect.height;
|
||||
|
||||
// Placing placedRect into freeRect results in an L-shaped free area, which must be split into
|
||||
// two disjoint rectangles. This can be achieved with by splitting the L-shape using a single line.
|
||||
// We have two choices: horizontal or vertical.
|
||||
|
||||
// Use the given heuristic to decide which choice to make.
|
||||
|
||||
bool splitHorizontal;
|
||||
switch(method)
|
||||
{
|
||||
case SplitShorterLeftoverAxis:
|
||||
// Split along the shorter leftover axis.
|
||||
splitHorizontal = (w <= h);
|
||||
break;
|
||||
case SplitLongerLeftoverAxis:
|
||||
// Split along the longer leftover axis.
|
||||
splitHorizontal = (w > h);
|
||||
break;
|
||||
case SplitMinimizeArea:
|
||||
// Maximize the larger area == minimize the smaller area.
|
||||
// Tries to make the single bigger rectangle.
|
||||
splitHorizontal = (placedRect.width * h > w * placedRect.height);
|
||||
break;
|
||||
case SplitMaximizeArea:
|
||||
// Maximize the smaller area == minimize the larger area.
|
||||
// Tries to make the rectangles more even-sized.
|
||||
splitHorizontal = (placedRect.width * h <= w * placedRect.height);
|
||||
break;
|
||||
case SplitShorterAxis:
|
||||
// Split along the shorter total axis.
|
||||
splitHorizontal = (freeRect.width <= freeRect.height);
|
||||
break;
|
||||
case SplitLongerAxis:
|
||||
// Split along the longer total axis.
|
||||
splitHorizontal = (freeRect.width > freeRect.height);
|
||||
break;
|
||||
default:
|
||||
splitHorizontal = true;
|
||||
assert(false);
|
||||
}
|
||||
|
||||
// Perform the actual split.
|
||||
SplitFreeRectAlongAxis(freeRect, placedRect, splitHorizontal);
|
||||
}
|
||||
|
||||
/// This function will add the two generated rectangles into the freeRectangles array. The caller is expected to
|
||||
/// remove the original rectangle from the freeRectangles array after that.
|
||||
void GuillotineBinPack::SplitFreeRectAlongAxis(const Rect &freeRect, const Rect &placedRect, bool splitHorizontal)
|
||||
{
|
||||
// Form the two new rectangles.
|
||||
Rect bottom;
|
||||
bottom.x = freeRect.x;
|
||||
bottom.y = freeRect.y + placedRect.height;
|
||||
bottom.height = freeRect.height - placedRect.height;
|
||||
|
||||
Rect right;
|
||||
right.x = freeRect.x + placedRect.width;
|
||||
right.y = freeRect.y;
|
||||
right.width = freeRect.width - placedRect.width;
|
||||
|
||||
if (splitHorizontal)
|
||||
{
|
||||
bottom.width = freeRect.width;
|
||||
right.height = placedRect.height;
|
||||
}
|
||||
else // Split vertically
|
||||
{
|
||||
bottom.width = placedRect.width;
|
||||
right.height = freeRect.height;
|
||||
}
|
||||
|
||||
// Add the new rectangles into the free rectangle pool if they weren't degenerate.
|
||||
if (bottom.width > 0 && bottom.height > 0)
|
||||
freeRectangles.Push(bottom);
|
||||
if (right.width > 0 && right.height > 0)
|
||||
freeRectangles.Push(right);
|
||||
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(bottom));
|
||||
assert(disjointRects.Disjoint(right));
|
||||
#endif
|
||||
}
|
||||
|
||||
void GuillotineBinPack::MergeFreeList()
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
DisjointRectCollection test;
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
assert(test.Add(freeRectangles[i]) == true);
|
||||
#endif
|
||||
|
||||
// Do a Theta(n^2) loop to see if any pair of free rectangles could me merged into one.
|
||||
// Note that we miss any opportunities to merge three rectangles into one. (should call this function again to detect that)
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
for(unsigned j = i+1; j < freeRectangles.Size(); ++j)
|
||||
{
|
||||
if (freeRectangles[i].width == freeRectangles[j].width && freeRectangles[i].x == freeRectangles[j].x)
|
||||
{
|
||||
if (freeRectangles[i].y == freeRectangles[j].y + freeRectangles[j].height)
|
||||
{
|
||||
freeRectangles[i].y -= freeRectangles[j].height;
|
||||
freeRectangles[i].height += freeRectangles[j].height;
|
||||
freeRectangles.Delete(j);
|
||||
--j;
|
||||
}
|
||||
else if (freeRectangles[i].y + freeRectangles[i].height == freeRectangles[j].y)
|
||||
{
|
||||
freeRectangles[i].height += freeRectangles[j].height;
|
||||
freeRectangles.Delete(j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
else if (freeRectangles[i].height == freeRectangles[j].height && freeRectangles[i].y == freeRectangles[j].y)
|
||||
{
|
||||
if (freeRectangles[i].x == freeRectangles[j].x + freeRectangles[j].width)
|
||||
{
|
||||
freeRectangles[i].x -= freeRectangles[j].width;
|
||||
freeRectangles[i].width += freeRectangles[j].width;
|
||||
freeRectangles.Delete(j);
|
||||
--j;
|
||||
}
|
||||
else if (freeRectangles[i].x + freeRectangles[i].width == freeRectangles[j].x)
|
||||
{
|
||||
freeRectangles[i].width += freeRectangles[j].width;
|
||||
freeRectangles.Delete(j);
|
||||
--j;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#ifdef _DEBUG
|
||||
test.Clear();
|
||||
for(unsigned i = 0; i < freeRectangles.Size(); ++i)
|
||||
assert(test.Add(freeRectangles[i]) == true);
|
||||
#endif
|
||||
}
|
|
@ -1,135 +0,0 @@
|
|||
/** @file GuillotineBinPack.h
|
||||
@author Jukka Jylänki
|
||||
|
||||
@brief Implements different bin packer algorithms that use the GUILLOTINE data structure.
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
|
||||
#include "Rect.h"
|
||||
|
||||
/** GuillotineBinPack implements different variants of bin packer algorithms that use the GUILLOTINE data structure
|
||||
to keep track of the free space of the bin where rectangles may be placed. */
|
||||
class GuillotineBinPack
|
||||
{
|
||||
public:
|
||||
/// The initial bin size will be (0,0). Call Init to set the bin size.
|
||||
GuillotineBinPack();
|
||||
|
||||
/// Initializes a new bin of the given size.
|
||||
GuillotineBinPack(int width, int height);
|
||||
|
||||
/// (Re)initializes the packer to an empty bin of width x height units. Call whenever
|
||||
/// you need to restart with a new bin.
|
||||
void Init(int width, int height);
|
||||
|
||||
/// Specifies the different choice heuristics that can be used when deciding which of the free subrectangles
|
||||
/// to place the to-be-packed rectangle into.
|
||||
enum FreeRectChoiceHeuristic
|
||||
{
|
||||
RectBestAreaFit, ///< -BAF
|
||||
RectBestShortSideFit, ///< -BSSF
|
||||
RectBestLongSideFit, ///< -BLSF
|
||||
RectWorstAreaFit, ///< -WAF
|
||||
RectWorstShortSideFit, ///< -WSSF
|
||||
RectWorstLongSideFit ///< -WLSF
|
||||
};
|
||||
|
||||
/// Specifies the different choice heuristics that can be used when the packer needs to decide whether to
|
||||
/// subdivide the remaining free space in horizontal or vertical direction.
|
||||
enum GuillotineSplitHeuristic
|
||||
{
|
||||
SplitShorterLeftoverAxis, ///< -SLAS
|
||||
SplitLongerLeftoverAxis, ///< -LLAS
|
||||
SplitMinimizeArea, ///< -MINAS, Try to make a single big rectangle at the expense of making the other small.
|
||||
SplitMaximizeArea, ///< -MAXAS, Try to make both remaining rectangles as even-sized as possible.
|
||||
SplitShorterAxis, ///< -SAS
|
||||
SplitLongerAxis ///< -LAS
|
||||
};
|
||||
|
||||
/// Inserts a single rectangle into the bin. The packer might rotate the rectangle, in which case the returned
|
||||
/// struct will have the width and height values swapped.
|
||||
/// @param merge If true, performs free Rectangle Merge procedure after packing the new rectangle. This procedure
|
||||
/// tries to defragment the list of disjoint free rectangles to improve packing performance, but also takes up
|
||||
/// some extra time.
|
||||
/// @param rectChoice The free rectangle choice heuristic rule to use.
|
||||
/// @param splitMethod The free rectangle split heuristic rule to use.
|
||||
Rect Insert(int width, int height, bool merge, FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
|
||||
|
||||
/// Inserts a list of rectangles into the bin.
|
||||
/// @param rects The list of rectangles to add. This list will be destroyed in the packing process.
|
||||
/// @param dst The outputted list of rectangles. Note that the indices will not correspond to the input indices.
|
||||
/// @param merge If true, performs Rectangle Merge operations during the packing process.
|
||||
/// @param rectChoice The free rectangle choice heuristic rule to use.
|
||||
/// @param splitMethod The free rectangle split heuristic rule to use.
|
||||
void Insert(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
|
||||
FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
|
||||
|
||||
// Implements GUILLOTINE-MAXFITTING, an experimental heuristic that's really cool but didn't quite work in practice.
|
||||
// void InsertMaxFitting(TArray<RectSize> &rects, TArray<Rect> &dst, bool merge,
|
||||
// FreeRectChoiceHeuristic rectChoice, GuillotineSplitHeuristic splitMethod);
|
||||
|
||||
/// Computes the ratio of used/total surface area. 0.00 means no space is yet used, 1.00 means the whole bin is used.
|
||||
float Occupancy() const;
|
||||
|
||||
/// Returns the internal list of disjoint rectangles that track the free area of the bin. You may alter this vector
|
||||
/// any way desired, as long as the end result still is a list of disjoint rectangles.
|
||||
TArray<Rect> &GetFreeRectangles() { return freeRectangles; }
|
||||
|
||||
/// Returns the list of packed rectangles. You may alter this vector at will, for example, you can move a Rect from
|
||||
/// this list to the Free Rectangles list to free up space on-the-fly, but notice that this causes fragmentation.
|
||||
TArray<Rect> &GetUsedRectangles() { return usedRectangles; }
|
||||
|
||||
/// Performs a Rectangle Merge operation. This procedure looks for adjacent free rectangles and merges them if they
|
||||
/// can be represented with a single rectangle. Takes up Theta(|freeRectangles|^2) time.
|
||||
void MergeFreeList();
|
||||
|
||||
#ifdef _DEBUG
|
||||
void DelDisjoint(const Rect &r) { disjointRects.Del(r); }
|
||||
#endif
|
||||
|
||||
private:
|
||||
int binWidth;
|
||||
int binHeight;
|
||||
|
||||
/// Stores a list of all the rectangles that we have packed so far. This is used only to compute the Occupancy ratio,
|
||||
/// so if you want to have the packer consume less memory, this can be removed.
|
||||
TArray<Rect> usedRectangles;
|
||||
|
||||
/// Stores a list of rectangles that represents the free area of the bin. This rectangles in this list are disjoint.
|
||||
TArray<Rect> freeRectangles;
|
||||
|
||||
#ifdef _DEBUG
|
||||
/// Used to track that the packer produces proper packings.
|
||||
DisjointRectCollection disjointRects;
|
||||
#endif
|
||||
|
||||
/// Goes through the list of free rectangles and finds the best one to place a rectangle of given size into.
|
||||
/// Running time is Theta(|freeRectangles|).
|
||||
/// @param nodeIndex [out] The index of the free rectangle in the freeRectangles array into which the new
|
||||
/// rect was placed.
|
||||
/// @return A Rect structure that represents the placement of the new rect into the best free rectangle.
|
||||
Rect FindPositionForNewNode(int width, int height, FreeRectChoiceHeuristic rectChoice, int *nodeIndex);
|
||||
|
||||
static int ScoreByHeuristic(int width, int height, const Rect &freeRect, FreeRectChoiceHeuristic rectChoice);
|
||||
// The following functions compute (penalty) score values if a rect of the given size was placed into the
|
||||
// given free rectangle. In these score values, smaller is better.
|
||||
|
||||
static int ScoreBestAreaFit(int width, int height, const Rect &freeRect);
|
||||
static int ScoreBestShortSideFit(int width, int height, const Rect &freeRect);
|
||||
static int ScoreBestLongSideFit(int width, int height, const Rect &freeRect);
|
||||
|
||||
static int ScoreWorstAreaFit(int width, int height, const Rect &freeRect);
|
||||
static int ScoreWorstShortSideFit(int width, int height, const Rect &freeRect);
|
||||
static int ScoreWorstLongSideFit(int width, int height, const Rect &freeRect);
|
||||
|
||||
/// Splits the given L-shaped free rectangle into two new free rectangles after placedRect has been placed into it.
|
||||
/// Determines the split axis by using the given heuristic.
|
||||
void SplitFreeRectByHeuristic(const Rect &freeRect, const Rect &placedRect, GuillotineSplitHeuristic method);
|
||||
|
||||
/// Splits the given L-shaped free rectangle into two new free rectangles along the given fixed split axis.
|
||||
void SplitFreeRectAlongAxis(const Rect &freeRect, const Rect &placedRect, bool splitHorizontal);
|
||||
};
|
94
src/Rect.h
94
src/Rect.h
|
@ -1,94 +0,0 @@
|
|||
/** @file Rect.h
|
||||
@author Jukka Jylänki
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <vector>
|
||||
|
||||
struct RectSize
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
struct Rect
|
||||
{
|
||||
int x;
|
||||
int y;
|
||||
int width;
|
||||
int height;
|
||||
};
|
||||
|
||||
/// Performs a lexicographic compare on (rect short side, rect long side).
|
||||
/// @return -1 if the smaller side of a is shorter than the smaller side of b, 1 if the other way around.
|
||||
/// If they are equal, the larger side length is used as a tie-breaker.
|
||||
/// If the rectangles are of same size, returns 0.
|
||||
int CompareRectShortSide(const Rect &a, const Rect &b);
|
||||
|
||||
/// Performs a lexicographic compare on (x, y, width, height).
|
||||
int NodeSortCmp(const Rect &a, const Rect &b);
|
||||
|
||||
/// Returns true if a is contained in b.
|
||||
bool IsContainedIn(const Rect &a, const Rect &b);
|
||||
|
||||
#ifdef _DEBUG
|
||||
class DisjointRectCollection
|
||||
{
|
||||
public:
|
||||
TArray<Rect> rects;
|
||||
|
||||
bool Add(const Rect &r)
|
||||
{
|
||||
// Degenerate rectangles are ignored.
|
||||
if (r.width == 0 || r.height == 0)
|
||||
return true;
|
||||
|
||||
if (!Disjoint(r))
|
||||
return false;
|
||||
rects.Push(r);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Del(const Rect &r)
|
||||
{
|
||||
for(unsigned i = 0; i < rects.Size(); ++i)
|
||||
{
|
||||
if(r.x == rects[i].x && r.y == rects[i].y && r.width == rects[i].width && r.height == rects[i].height)
|
||||
{
|
||||
rects.Delete(i);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
rects.Clear();
|
||||
}
|
||||
|
||||
bool Disjoint(const Rect &r) const
|
||||
{
|
||||
// Degenerate rectangles are ignored.
|
||||
if (r.width == 0 || r.height == 0)
|
||||
return true;
|
||||
|
||||
for(unsigned i = 0; i < rects.Size(); ++i)
|
||||
if (!Disjoint(rects[i], r))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool Disjoint(const Rect &a, const Rect &b)
|
||||
{
|
||||
if (a.x + a.width <= b.x ||
|
||||
b.x + b.width <= a.x ||
|
||||
a.y + a.height <= b.y ||
|
||||
b.y + b.height <= a.y)
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
};
|
||||
#endif
|
|
@ -1,412 +0,0 @@
|
|||
/** @file SkylineBinPack.cpp
|
||||
@author Jukka Jylänki
|
||||
|
||||
@brief Implements different bin packer algorithms that use the SKYLINE data structure.
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
|
||||
#include <cassert>
|
||||
#include <limits.h>
|
||||
#include "templates.h"
|
||||
|
||||
#include "SkylineBinPack.h"
|
||||
|
||||
using namespace std;
|
||||
|
||||
SkylineBinPack::SkylineBinPack()
|
||||
:binWidth(0),
|
||||
binHeight(0)
|
||||
{
|
||||
}
|
||||
|
||||
SkylineBinPack::SkylineBinPack(int width, int height, bool useWasteMap)
|
||||
{
|
||||
Init(width, height, useWasteMap);
|
||||
}
|
||||
|
||||
void SkylineBinPack::Init(int width, int height, bool useWasteMap_)
|
||||
{
|
||||
binWidth = width;
|
||||
binHeight = height;
|
||||
|
||||
useWasteMap = useWasteMap_;
|
||||
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Clear();
|
||||
#endif
|
||||
|
||||
usedSurfaceArea = 0;
|
||||
skyLine.Clear();
|
||||
SkylineNode node;
|
||||
node.x = 0;
|
||||
node.y = 0;
|
||||
node.width = binWidth;
|
||||
skyLine.Push(node);
|
||||
|
||||
if (useWasteMap)
|
||||
{
|
||||
wasteMap.Init(width, height);
|
||||
wasteMap.GetFreeRectangles().Clear();
|
||||
}
|
||||
}
|
||||
|
||||
void SkylineBinPack::Insert(TArray<RectSize> &rects, TArray<Rect> &dst)
|
||||
{
|
||||
dst.Clear();
|
||||
|
||||
while(rects.Size() > 0)
|
||||
{
|
||||
Rect bestNode;
|
||||
int bestScore1 = INT_MAX;
|
||||
int bestScore2 = INT_MAX;
|
||||
int bestSkylineIndex = -1;
|
||||
int bestRectIndex = -1;
|
||||
for(unsigned i = 0; i < rects.Size(); ++i)
|
||||
{
|
||||
Rect newNode;
|
||||
int score1;
|
||||
int score2;
|
||||
int index;
|
||||
newNode = FindPositionForNewNodeMinWaste(rects[i].width, rects[i].height, score2, score1, index);
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
#endif
|
||||
if (newNode.height != 0)
|
||||
{
|
||||
if (score1 < bestScore1 || (score1 == bestScore1 && score2 < bestScore2))
|
||||
{
|
||||
bestNode = newNode;
|
||||
bestScore1 = score1;
|
||||
bestScore2 = score2;
|
||||
bestSkylineIndex = index;
|
||||
bestRectIndex = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (bestRectIndex == -1)
|
||||
return;
|
||||
|
||||
// Perform the actual packing.
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(bestNode));
|
||||
disjointRects.Add(bestNode);
|
||||
#endif
|
||||
AddSkylineLevel(bestSkylineIndex, bestNode);
|
||||
usedSurfaceArea += rects[bestRectIndex].width * rects[bestRectIndex].height;
|
||||
rects.Delete(bestRectIndex);
|
||||
dst.Push(bestNode);
|
||||
}
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::Insert(int width, int height)
|
||||
{
|
||||
// First try to pack this rectangle into the waste map, if it fits.
|
||||
Rect node = wasteMap.Insert(width, height, true, GuillotineBinPack::RectBestShortSideFit,
|
||||
GuillotineBinPack::SplitMaximizeArea);
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(node));
|
||||
#endif
|
||||
|
||||
if (node.height != 0)
|
||||
{
|
||||
Rect newNode;
|
||||
newNode.x = node.x;
|
||||
newNode.y = node.y;
|
||||
newNode.width = node.width;
|
||||
newNode.height = node.height;
|
||||
usedSurfaceArea += width * height;
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
disjointRects.Add(newNode);
|
||||
#endif
|
||||
return newNode;
|
||||
}
|
||||
|
||||
return InsertBottomLeft(width, height);
|
||||
}
|
||||
|
||||
bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y) const
|
||||
{
|
||||
int x = skyLine[skylineNodeIndex].x;
|
||||
if (x + width > binWidth)
|
||||
return false;
|
||||
int widthLeft = width;
|
||||
int i = skylineNodeIndex;
|
||||
y = skyLine[skylineNodeIndex].y;
|
||||
while(widthLeft > 0)
|
||||
{
|
||||
y = MAX(y, skyLine[i].y);
|
||||
if (y + height > binHeight)
|
||||
return false;
|
||||
widthLeft -= skyLine[i].width;
|
||||
++i;
|
||||
assert(i < (int)skyLine.Size() || widthLeft <= 0);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
int SkylineBinPack::ComputeWastedArea(int skylineNodeIndex, int width, int height, int y) const
|
||||
{
|
||||
int wastedArea = 0;
|
||||
const int rectLeft = skyLine[skylineNodeIndex].x;
|
||||
const int rectRight = rectLeft + width;
|
||||
for(; skylineNodeIndex < (int)skyLine.Size() && skyLine[skylineNodeIndex].x < rectRight; ++skylineNodeIndex)
|
||||
{
|
||||
if (skyLine[skylineNodeIndex].x >= rectRight || skyLine[skylineNodeIndex].x + skyLine[skylineNodeIndex].width <= rectLeft)
|
||||
break;
|
||||
|
||||
int leftSide = skyLine[skylineNodeIndex].x;
|
||||
int rightSide = MIN(rectRight, leftSide + skyLine[skylineNodeIndex].width);
|
||||
assert(y >= skyLine[skylineNodeIndex].y);
|
||||
wastedArea += (rightSide - leftSide) * (y - skyLine[skylineNodeIndex].y);
|
||||
}
|
||||
return wastedArea;
|
||||
}
|
||||
|
||||
bool SkylineBinPack::RectangleFits(int skylineNodeIndex, int width, int height, int &y, int &wastedArea) const
|
||||
{
|
||||
bool fits = RectangleFits(skylineNodeIndex, width, height, y);
|
||||
if (fits)
|
||||
wastedArea = ComputeWastedArea(skylineNodeIndex, width, height, y);
|
||||
|
||||
return fits;
|
||||
}
|
||||
|
||||
void SkylineBinPack::AddWasteMapArea(int skylineNodeIndex, int width, int height, int y)
|
||||
{
|
||||
int wastedArea = 0;
|
||||
const int rectLeft = skyLine[skylineNodeIndex].x;
|
||||
const int rectRight = rectLeft + width;
|
||||
for(; skylineNodeIndex < (int)skyLine.Size() && skyLine[skylineNodeIndex].x < rectRight; ++skylineNodeIndex)
|
||||
{
|
||||
if (skyLine[skylineNodeIndex].x >= rectRight || skyLine[skylineNodeIndex].x + skyLine[skylineNodeIndex].width <= rectLeft)
|
||||
break;
|
||||
|
||||
int leftSide = skyLine[skylineNodeIndex].x;
|
||||
int rightSide = MIN(rectRight, leftSide + skyLine[skylineNodeIndex].width);
|
||||
assert(y >= skyLine[skylineNodeIndex].y);
|
||||
|
||||
Rect waste;
|
||||
waste.x = leftSide;
|
||||
waste.y = skyLine[skylineNodeIndex].y;
|
||||
waste.width = rightSide - leftSide;
|
||||
waste.height = y - skyLine[skylineNodeIndex].y;
|
||||
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(waste));
|
||||
#endif
|
||||
wasteMap.GetFreeRectangles().Push(waste);
|
||||
}
|
||||
}
|
||||
|
||||
void SkylineBinPack::AddWaste(const Rect &waste)
|
||||
{
|
||||
wasteMap.GetFreeRectangles().Push(waste);
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Del(waste);
|
||||
wasteMap.DelDisjoint(waste);
|
||||
#endif
|
||||
}
|
||||
|
||||
void SkylineBinPack::AddSkylineLevel(int skylineNodeIndex, const Rect &rect)
|
||||
{
|
||||
// First track all wasted areas and mark them into the waste map if we're using one.
|
||||
if (useWasteMap)
|
||||
AddWasteMapArea(skylineNodeIndex, rect.width, rect.height, rect.y);
|
||||
|
||||
SkylineNode newNode;
|
||||
newNode.x = rect.x;
|
||||
newNode.y = rect.y + rect.height;
|
||||
newNode.width = rect.width;
|
||||
skyLine.Insert(skylineNodeIndex, newNode);
|
||||
|
||||
assert(newNode.x + newNode.width <= binWidth);
|
||||
assert(newNode.y <= binHeight);
|
||||
|
||||
for(unsigned i = skylineNodeIndex+1; i < skyLine.Size(); ++i)
|
||||
{
|
||||
assert(skyLine[i-1].x <= skyLine[i].x);
|
||||
|
||||
if (skyLine[i].x < skyLine[i-1].x + skyLine[i-1].width)
|
||||
{
|
||||
int shrink = skyLine[i-1].x + skyLine[i-1].width - skyLine[i].x;
|
||||
|
||||
skyLine[i].x += shrink;
|
||||
skyLine[i].width -= shrink;
|
||||
|
||||
if (skyLine[i].width <= 0)
|
||||
{
|
||||
skyLine.Delete(i);
|
||||
--i;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
else
|
||||
break;
|
||||
}
|
||||
MergeSkylines();
|
||||
}
|
||||
|
||||
void SkylineBinPack::MergeSkylines()
|
||||
{
|
||||
for(unsigned i = 0; i < skyLine.Size()-1; ++i)
|
||||
if (skyLine[i].y == skyLine[i+1].y)
|
||||
{
|
||||
skyLine[i].width += skyLine[i+1].width;
|
||||
skyLine.Delete(i+1);
|
||||
--i;
|
||||
}
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::InsertBottomLeft(int width, int height)
|
||||
{
|
||||
int bestHeight;
|
||||
int bestWidth;
|
||||
int bestIndex;
|
||||
Rect newNode = FindPositionForNewNodeBottomLeft(width, height, bestHeight, bestWidth, bestIndex);
|
||||
|
||||
if (bestIndex != -1)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
#endif
|
||||
// Perform the actual packing.
|
||||
AddSkylineLevel(bestIndex, newNode);
|
||||
|
||||
usedSurfaceArea += width * height;
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Add(newNode);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
memset(&newNode, 0, sizeof(Rect));
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const
|
||||
{
|
||||
bestHeight = INT_MAX;
|
||||
bestIndex = -1;
|
||||
// Used to break ties if there are nodes at the same level. Then pick the narrowest one.
|
||||
bestWidth = INT_MAX;
|
||||
Rect newNode = { 0, 0, 0, 0 };
|
||||
for(unsigned i = 0; i < skyLine.Size(); ++i)
|
||||
{
|
||||
int y;
|
||||
if (RectangleFits(i, width, height, y))
|
||||
{
|
||||
if (y + height < bestHeight || (y + height == bestHeight && skyLine[i].width < bestWidth))
|
||||
{
|
||||
bestHeight = y + height;
|
||||
bestIndex = i;
|
||||
bestWidth = skyLine[i].width;
|
||||
newNode.x = skyLine[i].x;
|
||||
newNode.y = y;
|
||||
newNode.width = width;
|
||||
newNode.height = height;
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* if (RectangleFits(i, height, width, y))
|
||||
{
|
||||
if (y + width < bestHeight || (y + width == bestHeight && skyLine[i].width < bestWidth))
|
||||
{
|
||||
bestHeight = y + width;
|
||||
bestIndex = i;
|
||||
bestWidth = skyLine[i].width;
|
||||
newNode.x = skyLine[i].x;
|
||||
newNode.y = y;
|
||||
newNode.width = height;
|
||||
newNode.height = width;
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
}
|
||||
}
|
||||
*/ }
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::InsertMinWaste(int width, int height)
|
||||
{
|
||||
int bestHeight;
|
||||
int bestWastedArea;
|
||||
int bestIndex;
|
||||
Rect newNode = FindPositionForNewNodeMinWaste(width, height, bestHeight, bestWastedArea, bestIndex);
|
||||
|
||||
if (bestIndex != -1)
|
||||
{
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
#endif
|
||||
// Perform the actual packing.
|
||||
AddSkylineLevel(bestIndex, newNode);
|
||||
|
||||
usedSurfaceArea += width * height;
|
||||
#ifdef _DEBUG
|
||||
disjointRects.Add(newNode);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
memset(&newNode, 0, sizeof(newNode));
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
Rect SkylineBinPack::FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const
|
||||
{
|
||||
bestHeight = INT_MAX;
|
||||
bestWastedArea = INT_MAX;
|
||||
bestIndex = -1;
|
||||
Rect newNode;
|
||||
memset(&newNode, 0, sizeof(newNode));
|
||||
for(unsigned i = 0; i < skyLine.Size(); ++i)
|
||||
{
|
||||
int y;
|
||||
int wastedArea;
|
||||
|
||||
if (RectangleFits(i, width, height, y, wastedArea))
|
||||
{
|
||||
if (wastedArea < bestWastedArea || (wastedArea == bestWastedArea && y + height < bestHeight))
|
||||
{
|
||||
bestHeight = y + height;
|
||||
bestWastedArea = wastedArea;
|
||||
bestIndex = i;
|
||||
newNode.x = skyLine[i].x;
|
||||
newNode.y = y;
|
||||
newNode.width = width;
|
||||
newNode.height = height;
|
||||
#ifdef _DEBUG
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
#endif
|
||||
}
|
||||
}
|
||||
/* if (RectangleFits(i, height, width, y, wastedArea))
|
||||
{
|
||||
if (wastedArea < bestWastedArea || (wastedArea == bestWastedArea && y + width < bestHeight))
|
||||
{
|
||||
bestHeight = y + width;
|
||||
bestWastedArea = wastedArea;
|
||||
bestIndex = i;
|
||||
newNode.x = skyLine[i].x;
|
||||
newNode.y = y;
|
||||
newNode.width = height;
|
||||
newNode.height = width;
|
||||
assert(disjointRects.Disjoint(newNode));
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
return newNode;
|
||||
}
|
||||
|
||||
/// Computes the ratio of used surface area.
|
||||
float SkylineBinPack::Occupancy() const
|
||||
{
|
||||
return (float)usedSurfaceArea / (binWidth * binHeight);
|
||||
}
|
|
@ -1,91 +0,0 @@
|
|||
/** @file SkylineBinPack.h
|
||||
@author Jukka Jylänki
|
||||
|
||||
@brief Implements different bin packer algorithms that use the SKYLINE data structure.
|
||||
|
||||
This work is released to Public Domain, do whatever you want with it.
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include "tarray.h"
|
||||
|
||||
#include "Rect.h"
|
||||
#include "GuillotineBinPack.h"
|
||||
|
||||
/** Implements bin packing algorithms that use the SKYLINE data structure to store the bin contents. Uses
|
||||
GuillotineBinPack as the waste map. */
|
||||
class SkylineBinPack
|
||||
{
|
||||
public:
|
||||
/// Instantiates a bin of size (0,0). Call Init to create a new bin.
|
||||
SkylineBinPack();
|
||||
|
||||
/// Instantiates a bin of the given size.
|
||||
SkylineBinPack(int binWidth, int binHeight, bool useWasteMap);
|
||||
|
||||
/// (Re)initializes the packer to an empty bin of width x height units. Call whenever
|
||||
/// you need to restart with a new bin.
|
||||
void Init(int binWidth, int binHeight, bool useWasteMap);
|
||||
|
||||
/// Inserts the given list of rectangles in an offline/batch mode, possibly rotated.
|
||||
/// @param rects The list of rectangles to insert. This vector will be destroyed in the process.
|
||||
/// @param dst [out] This list will contain the packed rectangles. The indices will not correspond to that of rects.
|
||||
/// @param method The rectangle placement rule to use when packing.
|
||||
void Insert(TArray<RectSize> &rects, TArray<Rect> &dst);
|
||||
|
||||
/// Inserts a single rectangle into the bin, possibly rotated.
|
||||
Rect Insert(int width, int height);
|
||||
|
||||
/// Adds a rectangle to the waste list. It must have been previously returned by
|
||||
/// Insert or the results are undefined.
|
||||
void AddWaste(const Rect &rect);
|
||||
|
||||
/// Computes the ratio of used surface area to the total bin area.
|
||||
float Occupancy() const;
|
||||
|
||||
private:
|
||||
int binWidth;
|
||||
int binHeight;
|
||||
|
||||
#ifdef _DEBUG
|
||||
DisjointRectCollection disjointRects;
|
||||
#endif
|
||||
|
||||
/// Represents a single level (a horizontal line) of the skyline/horizon/envelope.
|
||||
struct SkylineNode
|
||||
{
|
||||
/// The starting x-coordinate (leftmost).
|
||||
int x;
|
||||
|
||||
/// The y-coordinate of the skyline level line.
|
||||
int y;
|
||||
|
||||
/// The line width. The ending coordinate (inclusive) will be x+width-1.
|
||||
int width;
|
||||
};
|
||||
|
||||
TArray<SkylineNode> skyLine;
|
||||
|
||||
unsigned long usedSurfaceArea;
|
||||
|
||||
/// If true, we use the GuillotineBinPack structure to recover wasted areas into a waste map.
|
||||
bool useWasteMap;
|
||||
GuillotineBinPack wasteMap;
|
||||
|
||||
Rect InsertBottomLeft(int width, int height);
|
||||
Rect InsertMinWaste(int width, int height);
|
||||
|
||||
Rect FindPositionForNewNodeBottomLeft(int width, int height, int &bestHeight, int &bestWidth, int &bestIndex) const;
|
||||
Rect FindPositionForNewNodeMinWaste(int width, int height, int &bestHeight, int &bestWastedArea, int &bestIndex) const;
|
||||
|
||||
bool RectangleFits(int skylineNodeIndex, int width, int height, int &y) const;
|
||||
bool RectangleFits(int skylineNodeIndex, int width, int height, int &y, int &wastedArea) const;
|
||||
int ComputeWastedArea(int skylineNodeIndex, int width, int height, int y) const;
|
||||
|
||||
void AddWasteMapArea(int skylineNodeIndex, int width, int height, int y);
|
||||
|
||||
void AddSkylineLevel(int skylineNodeIndex, const Rect &rect);
|
||||
|
||||
/// Merges all skyline nodes that are at the same level.
|
||||
void MergeSkylines();
|
||||
};
|
|
@ -34,7 +34,6 @@
|
|||
#include "actorptrselect.h"
|
||||
#include "actor.h"
|
||||
#include "d_player.h"
|
||||
#include "p_pspr.h"
|
||||
#include "p_local.h"
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -30,14 +30,11 @@
|
|||
#include "doomdef.h"
|
||||
#include "templates.h"
|
||||
#include "g_level.h"
|
||||
#include "doomdef.h"
|
||||
#include "st_stuff.h"
|
||||
#include "p_local.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "w_wad.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "statnums.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "d_event.h"
|
||||
#include "gi.h"
|
||||
#include "p_setup.h"
|
||||
|
@ -50,19 +47,10 @@
|
|||
#include "p_blockmap.h"
|
||||
|
||||
#include "m_cheat.h"
|
||||
#include "i_system.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "colormatcher.h"
|
||||
#include "d_netinf.h"
|
||||
|
||||
// Needs access to LFB.
|
||||
#include "v_video.h"
|
||||
#include "v_palette.h"
|
||||
|
||||
#include "v_text.h"
|
||||
|
||||
// State.
|
||||
#include "doomstat.h"
|
||||
#include "r_state.h"
|
||||
#include "r_utility.h"
|
||||
|
||||
|
@ -72,7 +60,6 @@
|
|||
#include "am_map.h"
|
||||
#include "po_man.h"
|
||||
#include "a_keys.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "actorinlines.h"
|
||||
|
||||
|
|
|
@ -40,7 +40,6 @@
|
|||
#include "c_cvars.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "b_bot.h"
|
||||
#include "m_argv.h"
|
||||
#include "doomstat.h"
|
||||
#include "p_local.h"
|
||||
#include "cmdlib.h"
|
||||
|
|
|
@ -48,12 +48,6 @@
|
|||
#include "p_maputl.h"
|
||||
#include "b_bot.h"
|
||||
#include "g_game.h"
|
||||
#include "m_random.h"
|
||||
#include "r_sky.h"
|
||||
#include "st_stuff.h"
|
||||
#include "stats.h"
|
||||
#include "i_system.h"
|
||||
#include "s_sound.h"
|
||||
#include "d_event.h"
|
||||
#include "d_player.h"
|
||||
#include "p_spec.h"
|
||||
|
|
|
@ -81,20 +81,15 @@ Everything that is changed is marked (maybe commented) with "Added by MC"
|
|||
#include "p_local.h"
|
||||
#include "b_bot.h"
|
||||
#include "g_game.h"
|
||||
#include "m_random.h"
|
||||
#include "doomstat.h"
|
||||
#include "cmdlib.h"
|
||||
#include "sc_man.h"
|
||||
#include "stats.h"
|
||||
#include "m_misc.h"
|
||||
#include "sbar.h"
|
||||
#include "p_acs.h"
|
||||
#include "teaminfo.h"
|
||||
#include "i_system.h"
|
||||
#include "d_net.h"
|
||||
#include "d_netinf.h"
|
||||
#include "d_player.h"
|
||||
#include "doomerrors.h"
|
||||
#include "events.h"
|
||||
#include "vm.h"
|
||||
|
||||
|
|
|
@ -44,11 +44,7 @@
|
|||
#include "p_local.h"
|
||||
#include "b_bot.h"
|
||||
#include "g_game.h"
|
||||
#include "d_protocol.h"
|
||||
#include "m_random.h"
|
||||
#include "i_system.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "gi.h"
|
||||
#include "a_keys.h"
|
||||
#include "d_event.h"
|
||||
#include "p_enemy.h"
|
||||
|
@ -56,7 +52,6 @@
|
|||
#include "p_spec.h"
|
||||
#include "p_checkposition.h"
|
||||
#include "actorinlines.h"
|
||||
#include "math/cmath.h"
|
||||
|
||||
static FRandom pr_botopendoor ("BotOpenDoor");
|
||||
static FRandom pr_bottrywalk ("BotTryWalk");
|
||||
|
|
|
@ -47,14 +47,9 @@
|
|||
#include "p_local.h"
|
||||
#include "b_bot.h"
|
||||
#include "g_game.h"
|
||||
#include "m_random.h"
|
||||
#include "stats.h"
|
||||
#include "a_pickups.h"
|
||||
#include "statnums.h"
|
||||
#include "d_net.h"
|
||||
#include "d_event.h"
|
||||
#include "d_player.h"
|
||||
#include "vectors.h"
|
||||
#include "actorinlines.h"
|
||||
|
||||
static FRandom pr_botmove ("BotMove");
|
||||
|
|
|
@ -44,11 +44,7 @@
|
|||
|
||||
#include "actor.h"
|
||||
#include "gstrings.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
#include "d_player.h"
|
||||
#include "g_level.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
|
|
@ -34,14 +34,11 @@
|
|||
|
||||
#include "doomtype.h"
|
||||
#include "doomdef.h"
|
||||
#include "cmdlib.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "c_bind.h"
|
||||
#include "g_level.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "gi.h"
|
||||
#include "configfile.h"
|
||||
#include "i_system.h"
|
||||
#include "d_event.h"
|
||||
#include "w_wad.h"
|
||||
#include "templates.h"
|
||||
|
@ -49,9 +46,6 @@
|
|||
#include "vm.h"
|
||||
#include "i_time.h"
|
||||
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
const char *KeyNames[NUM_KEYS] =
|
||||
{
|
||||
// This array is dependant on the particular keyboard input
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <direct.h>
|
||||
|
@ -56,11 +55,9 @@
|
|||
#include "g_game.h"
|
||||
#include "g_level.h"
|
||||
#include "w_wad.h"
|
||||
#include "g_level.h"
|
||||
#include "gi.h"
|
||||
#include "r_defs.h"
|
||||
#include "d_player.h"
|
||||
#include "templates.h"
|
||||
#include "p_local.h"
|
||||
#include "r_sky.h"
|
||||
#include "p_setup.h"
|
||||
|
@ -68,9 +65,7 @@
|
|||
#include "d_net.h"
|
||||
#include "v_text.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "v_video.h"
|
||||
#include "r_utility.h"
|
||||
#include "r_data/r_interpolate.h"
|
||||
#include "c_functions.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
|
|
|
@ -34,10 +34,6 @@
|
|||
|
||||
#include "templates.h"
|
||||
#include "p_setup.h"
|
||||
#include <stdarg.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "version.h"
|
||||
#include "g_game.h"
|
||||
|
@ -49,27 +45,22 @@
|
|||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "g_input.h"
|
||||
#include "m_swap.h"
|
||||
#include "v_palette.h"
|
||||
#include "v_video.h"
|
||||
#include "v_text.h"
|
||||
#include "w_wad.h"
|
||||
#include "sbar.h"
|
||||
#include "s_sound.h"
|
||||
#include "s_sndseq.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_gui.h"
|
||||
#include "v_video.h"
|
||||
#include "cmdlib.h"
|
||||
#include "d_net.h"
|
||||
#include "g_level.h"
|
||||
#include "d_event.h"
|
||||
#include "d_player.h"
|
||||
#include "gstrings.h"
|
||||
#include "c_consolebuffer.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
#include "i_time.h"
|
||||
|
||||
FString FStringFormat(VM_ARGS); // extern from thingdef_data.cpp
|
||||
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "cmdlib.h"
|
||||
|
@ -42,18 +41,12 @@
|
|||
#include "c_dispatch.h"
|
||||
|
||||
#include "doomstat.h"
|
||||
#include "c_cvars.h"
|
||||
#include "d_player.h"
|
||||
|
||||
#include "d_netinf.h"
|
||||
|
||||
#include "i_system.h"
|
||||
#include "v_palette.h"
|
||||
#include "v_video.h"
|
||||
#include "colormatcher.h"
|
||||
#include "menu/menu.h"
|
||||
#include "vm.h"
|
||||
#include "v_text.h"
|
||||
|
||||
struct FLatchedValue
|
||||
{
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "templates.h"
|
||||
#include "doomtype.h"
|
||||
|
@ -49,7 +48,6 @@
|
|||
#include "doomstat.h"
|
||||
#include "d_player.h"
|
||||
#include "configfile.h"
|
||||
#include "m_crc32.h"
|
||||
#include "v_text.h"
|
||||
#include "d_net.h"
|
||||
#include "d_main.h"
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
|
|
|
@ -39,7 +39,6 @@
|
|||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "colormatcher.h"
|
||||
|
|
|
@ -41,20 +41,17 @@
|
|||
|
||||
#include "compatibility.h"
|
||||
#include "sc_man.h"
|
||||
#include "cmdlib.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomdata.h"
|
||||
#include "doomstat.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "gi.h"
|
||||
#include "g_level.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "p_tags.h"
|
||||
#include "r_state.h"
|
||||
#include "w_wad.h"
|
||||
#include "textures.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
#include "actor.h"
|
||||
|
||||
// MACROS ------------------------------------------------------------------
|
||||
|
||||
|
@ -74,28 +71,6 @@ enum
|
|||
SLOT_BCOMPAT
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
CP_END,
|
||||
CP_CLEARFLAGS,
|
||||
CP_SETFLAGS,
|
||||
CP_SETSPECIAL,
|
||||
CP_CLEARSPECIAL,
|
||||
CP_SETACTIVATION,
|
||||
CP_SETSECTOROFFSET,
|
||||
CP_SETSECTORSPECIAL,
|
||||
CP_SETWALLYSCALE,
|
||||
CP_SETWALLTEXTURE,
|
||||
CP_SETTHINGZ,
|
||||
CP_SETTAG,
|
||||
CP_SETTHINGFLAGS,
|
||||
CP_SETVERTEX,
|
||||
CP_SETTHINGSKILLS,
|
||||
CP_SETSECTORTEXTURE,
|
||||
CP_SETSECTORLIGHT,
|
||||
CP_SETLINESECTORREF,
|
||||
};
|
||||
|
||||
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
|
||||
|
||||
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
|
||||
|
@ -397,6 +372,22 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingSkills)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingXY)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_INT(thing);
|
||||
PARAM_FLOAT(x);
|
||||
PARAM_FLOAT(y);
|
||||
|
||||
if ((unsigned)thing < MapThingsConverted.Size())
|
||||
{
|
||||
auto& pos = MapThingsConverted[thing].pos;
|
||||
pos.X = x;
|
||||
pos.Y = y;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetThingZ)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
|
@ -459,6 +450,13 @@ DEFINE_ACTION_FUNCTION(DLevelCompatibility, SetLineSectorRef)
|
|||
return 0;
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DLevelCompatibility, GetDefaultActor)
|
||||
{
|
||||
PARAM_PROLOGUE;
|
||||
PARAM_NAME(actorclass);
|
||||
ACTION_RETURN_OBJECT(GetDefaultByName(actorclass));
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
|
|
|
@ -26,20 +26,15 @@
|
|||
#include "doomdef.h"
|
||||
#include "m_swap.h"
|
||||
#include "hu_stuff.h"
|
||||
#include "w_wad.h"
|
||||
#include "s_sound.h"
|
||||
#include "doomstat.h"
|
||||
#include "st_stuff.h"
|
||||
#include "c_console.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "c_cvars.h"
|
||||
#include "d_player.h"
|
||||
#include "v_text.h"
|
||||
#include "v_video.h"
|
||||
#include "gi.h"
|
||||
#include "d_gui.h"
|
||||
#include "g_input.h"
|
||||
#include "templates.h"
|
||||
#include "d_net.h"
|
||||
#include "d_event.h"
|
||||
#include "sbar.h"
|
||||
|
|
|
@ -48,30 +48,19 @@
|
|||
#include "doomstat.h"
|
||||
#include "info.h"
|
||||
#include "d_dehacked.h"
|
||||
#include "s_sound.h"
|
||||
#include "g_level.h"
|
||||
#include "cmdlib.h"
|
||||
#include "gstrings.h"
|
||||
#include "m_alloc.h"
|
||||
#include "m_misc.h"
|
||||
#include "w_wad.h"
|
||||
#include "d_player.h"
|
||||
#include "r_state.h"
|
||||
#include "gi.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "decallib.h"
|
||||
#include "v_palette.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "vectors.h"
|
||||
#include "dobject.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "sc_man.h"
|
||||
#include "i_system.h"
|
||||
#include "doomerrors.h"
|
||||
#include "p_effect.h"
|
||||
#include "serializer.h"
|
||||
#include "thingdef.h"
|
||||
#include "info.h"
|
||||
#include "v_text.h"
|
||||
#include "backend/vmbuilder.h"
|
||||
#include "types.h"
|
||||
|
|
|
@ -38,11 +38,8 @@
|
|||
#include "doomstat.h"
|
||||
#include "i_system.h"
|
||||
#include "w_wad.h"
|
||||
#include "w_zip.h"
|
||||
#include "v_palette.h"
|
||||
#include "m_argv.h"
|
||||
#include "m_misc.h"
|
||||
#include "c_cvars.h"
|
||||
#include "sc_man.h"
|
||||
#include "v_video.h"
|
||||
#include "gameconfigfile.h"
|
||||
|
@ -197,6 +194,12 @@ void FIWadManager::ParseIWadInfo(const char *fn, const char *data, int datasize,
|
|||
iwad->StartupType = FStartupInfo::StrifeStartup;
|
||||
else iwad->StartupType = FStartupInfo::DefaultStartup;
|
||||
}
|
||||
else if (sc.Compare("StartupSong"))
|
||||
{
|
||||
sc.MustGetStringName("=");
|
||||
sc.MustGetString();
|
||||
iwad->Song = sc.String;
|
||||
}
|
||||
else
|
||||
{
|
||||
sc.ScriptError("Unknown keyword '%s'", sc.String);
|
||||
|
@ -769,6 +772,7 @@ const FIWADInfo *FIWadManager::FindIWAD(TArray<FString> &wadfiles, const char *i
|
|||
DoomStartupInfo.FgColor = iwad_info->FgColor;
|
||||
}
|
||||
if (DoomStartupInfo.Type == 0) DoomStartupInfo.Type = iwad_info->StartupType;
|
||||
if (DoomStartupInfo.Song.IsEmpty()) DoomStartupInfo.Song = iwad_info->Song;
|
||||
I_SetIWADInfo();
|
||||
return iwad_info;
|
||||
}
|
||||
|
|
|
@ -38,16 +38,13 @@
|
|||
#ifdef HAVE_FPU_CONTROL
|
||||
#include <fpu_control.h>
|
||||
#endif
|
||||
#include <float.h>
|
||||
|
||||
#if defined(__unix__) || defined(__APPLE__)
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include "doomerrors.h"
|
||||
|
||||
|
@ -67,7 +64,6 @@
|
|||
#include "menu/menu.h"
|
||||
#include "c_console.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "i_system.h"
|
||||
#include "i_sound.h"
|
||||
#include "i_video.h"
|
||||
#include "g_game.h"
|
||||
|
@ -81,40 +77,29 @@
|
|||
#include "d_main.h"
|
||||
#include "d_dehacked.h"
|
||||
#include "cmdlib.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_swap.h"
|
||||
#include "v_text.h"
|
||||
#include "gi.h"
|
||||
#include "b_bot.h" //Added by MC:
|
||||
#include "stats.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "sbar.h"
|
||||
#include "decallib.h"
|
||||
#include "version.h"
|
||||
#include "v_text.h"
|
||||
#include "st_start.h"
|
||||
#include "templates.h"
|
||||
#include "teaminfo.h"
|
||||
#include "hardware.h"
|
||||
#include "sbarinfo.h"
|
||||
#include "d_net.h"
|
||||
#include "g_level.h"
|
||||
#include "d_event.h"
|
||||
#include "d_netinf.h"
|
||||
#include "v_palette.h"
|
||||
#include "m_cheat.h"
|
||||
#include "compatibility.h"
|
||||
#include "m_joy.h"
|
||||
#include "sc_man.h"
|
||||
#include "po_man.h"
|
||||
#include "resourcefiles/resourcefile.h"
|
||||
#include "r_renderer.h"
|
||||
#include "p_local.h"
|
||||
#include "autosegs.h"
|
||||
#include "fragglescript/t_fs.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "events.h"
|
||||
#include "r_utility.h"
|
||||
#include "vm.h"
|
||||
#include "types.h"
|
||||
#include "r_data/r_vanillatrans.h"
|
||||
|
|
|
@ -101,6 +101,7 @@ struct FIWADInfo
|
|||
FString Required; // Requires another IWAD
|
||||
uint32_t FgColor = 0; // Foreground color for title banner
|
||||
uint32_t BkColor = 0xc0c0c0; // Background color for title banner
|
||||
FString Song;
|
||||
EGameType gametype = GAME_Doom; // which game are we playing?
|
||||
int StartupType = FStartupInfo::DefaultStartup; // alternate startup type
|
||||
FString MapInfo; // Base mapinfo to load
|
||||
|
|
|
@ -30,18 +30,13 @@
|
|||
|
||||
#include "version.h"
|
||||
#include "menu/menu.h"
|
||||
#include "m_random.h"
|
||||
#include "i_system.h"
|
||||
#include "i_video.h"
|
||||
#include "i_net.h"
|
||||
#include "g_game.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "c_console.h"
|
||||
#include "d_netinf.h"
|
||||
#include "d_net.h"
|
||||
#include "cmdlib.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_cheat.h"
|
||||
#include "p_local.h"
|
||||
#include "c_dispatch.h"
|
||||
|
@ -49,19 +44,15 @@
|
|||
#include "gi.h"
|
||||
#include "m_misc.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "d_gui.h"
|
||||
#include "templates.h"
|
||||
#include "p_acs.h"
|
||||
#include "p_trace.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "st_start.h"
|
||||
#include "teaminfo.h"
|
||||
#include "p_conversation.h"
|
||||
#include "g_level.h"
|
||||
#include "d_event.h"
|
||||
#include "m_argv.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "v_video.h"
|
||||
#include "p_spec.h"
|
||||
#include "hardware.h"
|
||||
#include "r_utility.h"
|
||||
|
|
|
@ -35,26 +35,17 @@
|
|||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_netinf.h"
|
||||
#include "d_net.h"
|
||||
#include "d_protocol.h"
|
||||
#include "d_player.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "v_palette.h"
|
||||
#include "v_video.h"
|
||||
#include "i_system.h"
|
||||
#include "r_state.h"
|
||||
#include "sbar.h"
|
||||
#include "gi.h"
|
||||
#include "m_random.h"
|
||||
#include "teaminfo.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "templates.h"
|
||||
#include "cmdlib.h"
|
||||
#include "serializer.h"
|
||||
#include "vm.h"
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "i_system.h"
|
||||
#include "d_protocol.h"
|
||||
#include "d_net.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
#include "cmdlib.h"
|
||||
#include "serializer.h"
|
||||
|
@ -408,7 +407,6 @@ int SkipTicCmd (uint8_t **stream, int count)
|
|||
return skip;
|
||||
}
|
||||
|
||||
#include <assert.h>
|
||||
extern short consistancy[MAXPLAYERS][BACKUPTICS];
|
||||
void ReadTicCmd (uint8_t **stream, int player, int tic)
|
||||
{
|
||||
|
|
|
@ -36,17 +36,13 @@
|
|||
#include "sc_man.h"
|
||||
#include "w_wad.h"
|
||||
#include "v_video.h"
|
||||
#include "v_palette.h"
|
||||
#include "cmdlib.h"
|
||||
#include "m_random.h"
|
||||
#include "weightedlist.h"
|
||||
#include "statnums.h"
|
||||
#include "templates.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "gi.h"
|
||||
#include "g_level.h"
|
||||
#include "colormatcher.h"
|
||||
#include "b_bot.h"
|
||||
#include "serializer.h"
|
||||
#include "g_levellocals.h"
|
||||
|
|
|
@ -33,19 +33,13 @@
|
|||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "cmdlib.h"
|
||||
#include "actor.h"
|
||||
#include "dobject.h"
|
||||
#include "doomstat.h" // Ideally, DObjects can be used independant of Doom.
|
||||
#include "d_player.h" // See p_user.cpp to find out why this doesn't work.
|
||||
#include "g_game.h" // Needed for bodyque.
|
||||
#include "c_dispatch.h"
|
||||
#include "i_system.h"
|
||||
#include "r_state.h"
|
||||
#include "stats.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "dsectoreffect.h"
|
||||
#include "serializer.h"
|
||||
#include "vm.h"
|
||||
|
|
|
@ -63,16 +63,11 @@
|
|||
#include "g_game.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "sbar.h"
|
||||
#include "stats.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "s_sndseq.h"
|
||||
#include "r_data/r_interpolate.h"
|
||||
#include "doomstat.h"
|
||||
#include "m_argv.h"
|
||||
#include "po_man.h"
|
||||
#include "autosegs.h"
|
||||
#include "v_video.h"
|
||||
#include "textures/textures.h"
|
||||
#include "r_utility.h"
|
||||
#include "menu/menu.h"
|
||||
#include "intermission/intermission.h"
|
||||
|
|
|
@ -35,19 +35,15 @@
|
|||
|
||||
// HEADER FILES ------------------------------------------------------------
|
||||
|
||||
#include <float.h>
|
||||
#include <limits>
|
||||
|
||||
#include "dobject.h"
|
||||
#include "i_system.h"
|
||||
#include "serializer.h"
|
||||
#include "actor.h"
|
||||
#include "templates.h"
|
||||
#include "autosegs.h"
|
||||
#include "v_text.h"
|
||||
#include "a_pickups.h"
|
||||
#include "d_player.h"
|
||||
#include "doomerrors.h"
|
||||
#include "fragglescript/t_fs.h"
|
||||
#include "a_keys.h"
|
||||
#include "vm.h"
|
||||
|
|
|
@ -28,10 +28,8 @@
|
|||
|
||||
#include "stringtable.h"
|
||||
#include "doomstat.h"
|
||||
#include "c_cvars.h"
|
||||
#include "i_system.h"
|
||||
#include "g_level.h"
|
||||
#include "p_local.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
int SaveVersion;
|
||||
|
|
|
@ -283,6 +283,17 @@ enum ESSType
|
|||
|
||||
const double M_PI = 3.14159265358979323846; // matches value in gcc v2 math.h
|
||||
|
||||
inline float DEG2RAD(float deg)
|
||||
{
|
||||
return deg * float(M_PI / 180.0);
|
||||
}
|
||||
|
||||
inline float RAD2DEG(float deg)
|
||||
{
|
||||
return deg * float(180. / M_PI);
|
||||
}
|
||||
|
||||
|
||||
template <typename T, size_t N>
|
||||
char ( &_ArraySizeHelper( T (&array)[N] ))[N];
|
||||
|
||||
|
|
|
@ -26,12 +26,10 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "dsectoreffect.h"
|
||||
#include "gi.h"
|
||||
#include "p_local.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "p_3dmidtex.h"
|
||||
#include "r_data/r_interpolate.h"
|
||||
#include "statnums.h"
|
||||
#include "serializer.h"
|
||||
#include "doomstat.h"
|
||||
#include "vm.h"
|
||||
|
|
|
@ -35,9 +35,6 @@
|
|||
#include "dthinker.h"
|
||||
#include "stats.h"
|
||||
#include "p_local.h"
|
||||
#include "statnums.h"
|
||||
#include "i_system.h"
|
||||
#include "doomerrors.h"
|
||||
#include "serializer.h"
|
||||
#include "d_player.h"
|
||||
#include "vm.h"
|
||||
|
|
|
@ -36,7 +36,6 @@
|
|||
|
||||
#include "w_wad.h"
|
||||
#include "m_argv.h"
|
||||
#include "zstring.h"
|
||||
#include "sc_man.h"
|
||||
#include "g_level.h"
|
||||
#include "doomdata.h"
|
||||
|
@ -46,9 +45,7 @@
|
|||
#include "p_setup.h"
|
||||
#include "p_tags.h"
|
||||
#include "p_terrain.h"
|
||||
#include "v_palette.h"
|
||||
#include "p_acs.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
|
||||
|
|
|
@ -35,7 +35,6 @@
|
|||
#include "r_utility.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "gi.h"
|
||||
#include "v_text.h"
|
||||
#include "actor.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "d_net.h"
|
||||
|
|
|
@ -23,14 +23,10 @@
|
|||
//
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "i_video.h"
|
||||
#include "v_video.h"
|
||||
#include "m_random.h"
|
||||
#include "doomdef.h"
|
||||
#include "f_wipe.h"
|
||||
#include "c_cvars.h"
|
||||
#include "templates.h"
|
||||
#include "v_palette.h"
|
||||
|
||||
int wipe_CalcBurn (uint8_t *burnarray, int width, int height, int density)
|
||||
{
|
||||
|
|
|
@ -34,9 +34,7 @@
|
|||
*/
|
||||
|
||||
#include "files.h"
|
||||
#include "i_system.h"
|
||||
#include "templates.h"
|
||||
#include "m_misc.h"
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -27,7 +27,6 @@
|
|||
|
||||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include "p_local.h"
|
||||
#include "doomdef.h"
|
||||
#include "doomstat.h"
|
||||
|
|
|
@ -37,26 +37,15 @@
|
|||
#include "templates.h"
|
||||
#include "p_local.h"
|
||||
#include "t_script.h"
|
||||
#include "s_sound.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "m_random.h"
|
||||
#include "c_console.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "d_player.h"
|
||||
#include "w_wad.h"
|
||||
#include "gi.h"
|
||||
#include "zstring.h"
|
||||
#include "i_system.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
#include "v_palette.h"
|
||||
#include "v_font.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "serializer.h"
|
||||
#include "p_setup.h"
|
||||
#include "p_spec.h"
|
||||
#include "r_utility.h"
|
||||
#include "math/cmath.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "actorinlines.h"
|
||||
|
||||
|
|
|
@ -25,14 +25,11 @@
|
|||
|
||||
|
||||
#include "w_wad.h"
|
||||
#include "tarray.h"
|
||||
#include "g_level.h"
|
||||
#include "sc_man.h"
|
||||
#include "s_sound.h"
|
||||
#include "r_sky.h"
|
||||
#include "t_script.h"
|
||||
#include "cmdlib.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "gi.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "xlat/xlat.h"
|
||||
|
|
|
@ -33,10 +33,7 @@
|
|||
/* includes ************************/
|
||||
#include <stdarg.h>
|
||||
#include "t_script.h"
|
||||
#include "s_sound.h"
|
||||
#include "v_text.h"
|
||||
#include "c_cvars.h"
|
||||
#include "i_system.h"
|
||||
|
||||
|
||||
CVAR(Bool, script_debug, false, 0)
|
||||
|
|
|
@ -41,7 +41,6 @@
|
|||
/* includes ************************/
|
||||
|
||||
#include "t_script.h"
|
||||
#include "i_system.h"
|
||||
#include "w_wad.h"
|
||||
#include "serializer.h"
|
||||
|
||||
|
|
|
@ -33,14 +33,10 @@
|
|||
//
|
||||
|
||||
#include "t_script.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "a_keys.h"
|
||||
#include "d_player.h"
|
||||
#include "p_spec.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "i_system.h"
|
||||
#include "doomerrors.h"
|
||||
#include "doomstat.h"
|
||||
#include "serializer.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
|
|
|
@ -36,13 +36,8 @@
|
|||
#include "info.h"
|
||||
#include "actor.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "m_fixed.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "templates.h"
|
||||
#include "cmdlib.h"
|
||||
#include "g_level.h"
|
||||
#include "v_text.h"
|
||||
#include "i_system.h"
|
||||
|
||||
|
||||
const char *SpecialMapthingNames[] = {
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stddef.h>
|
||||
#include <time.h>
|
||||
#include <memory>
|
||||
#ifdef __APPLE__
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
@ -43,9 +42,7 @@
|
|||
#include "m_argv.h"
|
||||
#include "m_misc.h"
|
||||
#include "menu/menu.h"
|
||||
#include "m_random.h"
|
||||
#include "m_crc32.h"
|
||||
#include "i_system.h"
|
||||
#include "p_saveg.h"
|
||||
#include "p_tick.h"
|
||||
#include "d_main.h"
|
||||
|
@ -54,24 +51,16 @@
|
|||
#include "st_stuff.h"
|
||||
#include "am_map.h"
|
||||
#include "c_console.h"
|
||||
#include "c_cvars.h"
|
||||
#include "c_bind.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "v_video.h"
|
||||
#include "w_wad.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "gstrings.h"
|
||||
#include "r_sky.h"
|
||||
#include "g_game.h"
|
||||
#include "g_level.h"
|
||||
#include "b_bot.h" //Added by MC:
|
||||
#include "sbar.h"
|
||||
#include "m_swap.h"
|
||||
#include "m_png.h"
|
||||
#include "gi.h"
|
||||
#include "a_keys.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "cmdlib.h"
|
||||
#include "d_net.h"
|
||||
#include "d_event.h"
|
||||
|
@ -82,18 +71,12 @@
|
|||
#include "r_utility.h"
|
||||
#include "a_morph.h"
|
||||
#include "p_spec.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "serializer.h"
|
||||
#include "w_zip.h"
|
||||
#include "resourcefiles/resourcefile.h"
|
||||
#include "vm.h"
|
||||
|
||||
#include <zlib.h>
|
||||
|
||||
#include "g_hub.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "events.h"
|
||||
#include "d_main.h"
|
||||
|
||||
|
||||
static FRandom pr_dmspawn ("DMSpawn");
|
||||
|
|
|
@ -35,11 +35,8 @@
|
|||
|
||||
#include "doomstat.h"
|
||||
#include "g_hub.h"
|
||||
#include "tarray.h"
|
||||
#include "g_level.h"
|
||||
#include "g_game.h"
|
||||
#include "gi.h"
|
||||
#include "files.h"
|
||||
#include "m_png.h"
|
||||
#include "gstrings.h"
|
||||
#include "wi_stuff.h"
|
||||
|
|
|
@ -37,11 +37,7 @@
|
|||
#include "gstrings.h"
|
||||
#include "d_player.h"
|
||||
#include "c_console.h"
|
||||
#include "s_sound.h"
|
||||
#include "sc_man.h"
|
||||
#include "v_palette.h"
|
||||
#include "w_wad.h"
|
||||
#include "doomstat.h"
|
||||
#include "v_font.h"
|
||||
#include "vm.h"
|
||||
|
||||
|
|
|
@ -36,28 +36,21 @@
|
|||
#include <assert.h>
|
||||
|
||||
#include "info.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "s_sound.h"
|
||||
#include "gi.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "sbar.h"
|
||||
#include "statnums.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "gstrings.h"
|
||||
#include "templates.h"
|
||||
#include "a_morph.h"
|
||||
#include "a_specialspot.h"
|
||||
#include "g_level.h"
|
||||
#include "g_game.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_player.h"
|
||||
#include "p_spec.h"
|
||||
#include "serializer.h"
|
||||
#include "vm.h"
|
||||
#include "c_functions.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
|
||||
EXTERN_CVAR(Bool, sv_unlimited_pickup)
|
||||
|
||||
|
|
|
@ -38,18 +38,11 @@
|
|||
#include "a_pickups.h"
|
||||
#include "gi.h"
|
||||
#include "d_player.h"
|
||||
#include "s_sound.h"
|
||||
#include "i_system.h"
|
||||
#include "r_state.h"
|
||||
#include "p_pspr.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "m_misc.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "cmdlib.h"
|
||||
#include "templates.h"
|
||||
#include "sbar.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
#include "d_net.h"
|
||||
#include "serializer.h"
|
||||
#include "vm.h"
|
||||
|
|
|
@ -52,7 +52,6 @@
|
|||
#include "r_sky.h"
|
||||
#include "c_console.h"
|
||||
#include "intermission/intermission.h"
|
||||
#include "gstrings.h"
|
||||
#include "v_video.h"
|
||||
#include "st_stuff.h"
|
||||
#include "hu_stuff.h"
|
||||
|
@ -62,31 +61,22 @@
|
|||
#include "v_text.h"
|
||||
#include "s_sndseq.h"
|
||||
#include "b_bot.h"
|
||||
#include "sc_man.h"
|
||||
#include "sbar.h"
|
||||
#include "a_lightning.h"
|
||||
#include "m_png.h"
|
||||
#include "m_random.h"
|
||||
#include "version.h"
|
||||
#include "statnums.h"
|
||||
#include "sbarinfo.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "r_data/r_interpolate.h"
|
||||
#include "cmdlib.h"
|
||||
#include "d_net.h"
|
||||
#include "d_netinf.h"
|
||||
#include "v_palette.h"
|
||||
#include "menu/menu.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "r_renderer.h"
|
||||
#include "r_utility.h"
|
||||
#include "p_spec.h"
|
||||
#include "serializer.h"
|
||||
#include "vm.h"
|
||||
#include "events.h"
|
||||
#include "dobjgc.h"
|
||||
#include "i_music.h"
|
||||
|
||||
#include "gi.h"
|
||||
|
@ -94,11 +84,8 @@
|
|||
#include "g_hub.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "actorinlines.h"
|
||||
#include "vm.h"
|
||||
#include "i_time.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
void STAT_StartNewGame(const char *lev);
|
||||
void STAT_ChangeLevel(const char *newl);
|
||||
|
||||
|
|
|
@ -36,21 +36,17 @@
|
|||
#include <assert.h>
|
||||
#include "templates.h"
|
||||
#include "g_level.h"
|
||||
#include "sc_man.h"
|
||||
#include "w_wad.h"
|
||||
#include "cmdlib.h"
|
||||
#include "v_video.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "p_setup.h"
|
||||
#include "i_system.h"
|
||||
#include "gi.h"
|
||||
#include "gstrings.h"
|
||||
#include "p_acs.h"
|
||||
#include "doomstat.h"
|
||||
#include "d_player.h"
|
||||
#include "autosegs.h"
|
||||
#include "version.h"
|
||||
#include "v_text.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "events.h"
|
||||
|
||||
|
|
|
@ -24,16 +24,11 @@
|
|||
#include "actor.h"
|
||||
#include "p_conversation.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "d_player.h"
|
||||
#include "p_local.h"
|
||||
#include "p_terrain.h"
|
||||
#include "p_enemy.h"
|
||||
#include "statnums.h"
|
||||
#include "templates.h"
|
||||
#include "serializer.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "vm.h"
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
|
|
@ -36,17 +36,12 @@
|
|||
#include "a_sharedglobal.h"
|
||||
#include "r_defs.h"
|
||||
#include "p_local.h"
|
||||
#include "v_video.h"
|
||||
#include "p_trace.h"
|
||||
#include "decallib.h"
|
||||
#include "statnums.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "d_net.h"
|
||||
#include "colormatcher.h"
|
||||
#include "v_palette.h"
|
||||
#include "serializer.h"
|
||||
#include "doomdata.h"
|
||||
#include "r_state.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
static double DecalWidth, DecalLeft, DecalRight;
|
||||
|
|
|
@ -55,26 +55,14 @@
|
|||
**
|
||||
*/
|
||||
|
||||
#include "templates.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "g_level.h"
|
||||
#include "thingdef.h"
|
||||
#include "i_system.h"
|
||||
#include "templates.h"
|
||||
#include "doomdata.h"
|
||||
#include "r_utility.h"
|
||||
#include "p_local.h"
|
||||
#include "portal.h"
|
||||
#include "doomstat.h"
|
||||
#include "serializer.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "a_dynlight.h"
|
||||
#include "actorinlines.h"
|
||||
#include "c_cvars.h"
|
||||
#include "gl/system//gl_interface.h"
|
||||
#include "vm.h"
|
||||
|
||||
|
||||
CUSTOM_CVAR (Bool, gl_lights, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG | CVAR_NOINITCALL)
|
||||
|
@ -179,6 +167,7 @@ void ADynamicLight::BeginPlay()
|
|||
|
||||
specialf1 = DAngle(double(SpawnAngle)).Normalized360().Degrees;
|
||||
visibletoplayer = true;
|
||||
mShadowmapIndex = 1024;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
EXTERN_CVAR(Bool, gl_lights)
|
||||
EXTERN_CVAR(Bool, gl_attachedlights)
|
||||
|
||||
struct side_t;
|
||||
struct seg_t;
|
||||
|
||||
class ADynamicLight;
|
||||
class FSerializer;
|
||||
|
||||
|
@ -227,7 +230,9 @@ public:
|
|||
bool shadowmapped;
|
||||
int bufferindex;
|
||||
LightFlags lightflags;
|
||||
DAngle SpotInnerAngle = 10.0;
|
||||
DAngle SpotOuterAngle = 25.0;
|
||||
DAngle SpotInnerAngle;
|
||||
DAngle SpotOuterAngle;
|
||||
|
||||
int mShadowmapIndex;
|
||||
|
||||
};
|
||||
|
|
|
@ -33,7 +33,6 @@
|
|||
*/
|
||||
|
||||
#include "a_sharedglobal.h"
|
||||
#include "g_level.h"
|
||||
#include "d_player.h"
|
||||
#include "serializer.h"
|
||||
#include "g_levellocals.h"
|
||||
|
|
|
@ -25,7 +25,6 @@
|
|||
#include "a_lightning.h"
|
||||
#include "doomstat.h"
|
||||
#include "p_lnspec.h"
|
||||
#include "statnums.h"
|
||||
#include "m_random.h"
|
||||
#include "templates.h"
|
||||
#include "s_sound.h"
|
||||
|
|
|
@ -23,23 +23,18 @@
|
|||
|
||||
#include "info.h"
|
||||
#include "a_pickups.h"
|
||||
#include "gstrings.h"
|
||||
#include "p_local.h"
|
||||
#include "gi.h"
|
||||
#include "s_sound.h"
|
||||
#include "m_random.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "sbar.h"
|
||||
#include "a_morph.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
#include "serializer.h"
|
||||
#include "p_enemy.h"
|
||||
#include "d_player.h"
|
||||
#include "r_data/sprites.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
#include "vm.h"
|
||||
|
||||
static FRandom pr_morphmonst ("MorphMonster");
|
||||
|
||||
|
|
|
@ -27,11 +27,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "p_local.h"
|
||||
#include "actor.h"
|
||||
#include "m_bbox.h"
|
||||
#include "m_random.h"
|
||||
#include "s_sound.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "statnums.h"
|
||||
#include "serializer.h"
|
||||
#include "d_player.h"
|
||||
#include "r_utility.h"
|
||||
|
|
|
@ -33,10 +33,7 @@
|
|||
**
|
||||
*/
|
||||
#include "a_specialspot.h"
|
||||
#include "m_random.h"
|
||||
#include "p_local.h"
|
||||
#include "statnums.h"
|
||||
#include "i_system.h"
|
||||
#include "doomstat.h"
|
||||
#include "serializer.h"
|
||||
#include "a_pickups.h"
|
||||
|
|
|
@ -38,7 +38,6 @@
|
|||
#include "c_cvars.h"
|
||||
#include "v_video.h"
|
||||
#include "cmdlib.h"
|
||||
#include "doomstat.h"
|
||||
#include "serializer.h"
|
||||
#include "vm.h"
|
||||
|
||||
|
|
|
@ -40,12 +40,10 @@
|
|||
#include "doomdef.h"
|
||||
#include "v_video.h"
|
||||
#include "gi.h"
|
||||
#include "c_cvars.h"
|
||||
#include "w_wad.h"
|
||||
#include "a_keys.h"
|
||||
#include "sbar.h"
|
||||
#include "sc_man.h"
|
||||
#include "templates.h"
|
||||
#include "p_local.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
|
|
|
@ -36,12 +36,9 @@
|
|||
#include <ctype.h>
|
||||
#include "doomstat.h"
|
||||
#include "d_player.h"
|
||||
#include "g_level.h"
|
||||
#include "g_game.h"
|
||||
#include "gi.h"
|
||||
#include "templates.h"
|
||||
#include "v_font.h"
|
||||
#include "m_fixed.h"
|
||||
#include "gstrings.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
|
|
|
@ -36,10 +36,7 @@
|
|||
#include "r_defs.h"
|
||||
#include "m_random.h"
|
||||
#include "d_player.h"
|
||||
#include "d_event.h"
|
||||
#include "sbar.h"
|
||||
#include "sbarinfo.h"
|
||||
#include "templates.h"
|
||||
#include "r_utility.h"
|
||||
#include "actorinlines.h"
|
||||
|
||||
|
|
|
@ -38,24 +38,13 @@
|
|||
#include "v_font.h"
|
||||
#include "v_video.h"
|
||||
#include "sbar.h"
|
||||
#include "r_defs.h"
|
||||
#include "w_wad.h"
|
||||
#include "m_random.h"
|
||||
#include "d_player.h"
|
||||
#include "st_stuff.h"
|
||||
#include "m_swap.h"
|
||||
#include "a_keys.h"
|
||||
#include "templates.h"
|
||||
#include "i_system.h"
|
||||
#include "sbar.h"
|
||||
#include "sbarinfo.h"
|
||||
#include "gi.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "g_level.h"
|
||||
#include "v_palette.h"
|
||||
#include "p_acs.h"
|
||||
#include "gstrings.h"
|
||||
#include "cmdlib.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
|
||||
|
|
|
@ -41,25 +41,19 @@
|
|||
#include "c_dispatch.h"
|
||||
#include "c_console.h"
|
||||
#include "v_video.h"
|
||||
#include "m_swap.h"
|
||||
#include "w_wad.h"
|
||||
#include "v_text.h"
|
||||
#include "s_sound.h"
|
||||
#include "gi.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
#include "d_net.h"
|
||||
#include "colormatcher.h"
|
||||
#include "v_palette.h"
|
||||
#include "d_player.h"
|
||||
#include "serializer.h"
|
||||
#include "gstrings.h"
|
||||
#include "r_utility.h"
|
||||
#include "cmdlib.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "vm.h"
|
||||
#include "p_acs.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "sbarinfo.h"
|
||||
#include "events.h"
|
||||
|
||||
|
@ -658,7 +652,6 @@ void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer
|
|||
{
|
||||
DHUDMessageBase *old = NULL;
|
||||
DHUDMessageBase **prev;
|
||||
DObject *container = this;
|
||||
|
||||
old = (id == 0 || id == 0xFFFFFFFF) ? NULL : DetachMessage (id);
|
||||
if (old != NULL)
|
||||
|
@ -679,14 +672,13 @@ void DBaseStatusBar::AttachMessage (DHUDMessageBase *msg, uint32_t id, int layer
|
|||
// it gets drawn back to front.)
|
||||
while (*prev != NULL && (*prev)->SBarID > id)
|
||||
{
|
||||
container = *prev;
|
||||
prev = &(*prev)->Next;
|
||||
}
|
||||
|
||||
msg->Next = *prev;
|
||||
msg->SBarID = id;
|
||||
*prev = msg;
|
||||
GC::WriteBarrier(container, msg);
|
||||
GC::WriteBarrier(msg);
|
||||
}
|
||||
|
||||
DEFINE_ACTION_FUNCTION(DBaseStatusBar, AttachMessage)
|
||||
|
|
|
@ -33,18 +33,15 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <time.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <CoreServices/CoreServices.h>
|
||||
#endif
|
||||
|
||||
#include "doomdef.h"
|
||||
#include "gameconfigfile.h"
|
||||
#include "c_cvars.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "c_bind.h"
|
||||
#include "gstrings.h"
|
||||
#include "m_argv.h"
|
||||
#include "cmdlib.h"
|
||||
#include "version.h"
|
||||
|
@ -52,7 +49,6 @@
|
|||
#include "v_font.h"
|
||||
#include "a_pickups.h"
|
||||
#include "doomstat.h"
|
||||
#include "i_system.h"
|
||||
#include "gi.h"
|
||||
#include "d_main.h"
|
||||
|
||||
|
|
|
@ -35,11 +35,8 @@
|
|||
#include <stdlib.h>
|
||||
#include "info.h"
|
||||
#include "gi.h"
|
||||
#include "m_fixed.h"
|
||||
#include "v_palette.h"
|
||||
#include "sc_man.h"
|
||||
#include "w_wad.h"
|
||||
#include "i_system.h"
|
||||
#include "v_video.h"
|
||||
#include "g_level.h"
|
||||
#include "vm.h"
|
||||
|
|
|
@ -30,21 +30,15 @@
|
|||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "menu/menu.h"
|
||||
#include "tarray.h"
|
||||
#include "doomtype.h"
|
||||
#include "m_argv.h"
|
||||
#include "zstring.h"
|
||||
#include "i_system.h"
|
||||
#include "v_text.h"
|
||||
#include "r_utility.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "actorinlines.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "gl/dynlights/gl_dynlight.h"
|
||||
#include "hwrenderer/dynlights/hw_dynlightdata.h"
|
||||
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_lightdata.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
|
@ -438,7 +432,7 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, FVector3 & nearP
|
|||
|
||||
if (radius <= 0.f) return false;
|
||||
if (dist > radius) return false;
|
||||
if (checkside && gl_lights_checkside && p.PointOnSide(lpos.X, lpos.Z, lpos.Y))
|
||||
if (checkside && p.PointOnSide(lpos.X, lpos.Z, lpos.Y))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -489,8 +483,8 @@ bool gl_SetupLight(int group, Plane & p, ADynamicLight * light, FVector3 & nearP
|
|||
|
||||
bool gl_SetupLightTexture()
|
||||
{
|
||||
if (!GLRenderer->glLight.isValid()) return false;
|
||||
FMaterial * pat = FMaterial::ValidateTexture(GLRenderer->glLight, false, false);
|
||||
if (!TexMan.glLight.isValid()) return false;
|
||||
FMaterial * pat = FMaterial::ValidateTexture(TexMan.glLight, false, false);
|
||||
gl_RenderState.SetMaterial(pat, CLAMP_XY_NOMIP, 0, -1, false);
|
||||
return true;
|
||||
}
|
||||
|
@ -501,7 +495,7 @@ bool gl_SetupLightTexture()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
static bool gl_CheckFog(FColormap *cm, int lightlevel)
|
||||
static bool CheckFog(FColormap *cm, int lightlevel)
|
||||
{
|
||||
bool frontfog;
|
||||
|
||||
|
@ -555,11 +549,13 @@ bool FDrawInfo::PutWallCompat(GLWall *wall, int passflag)
|
|||
if (wall->sub->lighthead == nullptr) return false;
|
||||
}
|
||||
|
||||
bool foggy = gl_CheckFog(&wall->Colormap, wall->lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
|
||||
bool foggy = CheckFog(&wall->Colormap, wall->lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
|
||||
bool masked = passflag == 2 && wall->gltexture->isMasked();
|
||||
|
||||
int list = list_indices[masked][foggy];
|
||||
dldrawlists[list].AddWall(wall);
|
||||
auto newwall = dldrawlists[list].NewWall();
|
||||
*newwall = *wall;
|
||||
if (!masked) newwall->ProcessDecals(this);
|
||||
return true;
|
||||
|
||||
}
|
||||
|
@ -570,20 +566,21 @@ bool FDrawInfo::PutWallCompat(GLWall *wall, int passflag)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
bool GLFlat::PutFlatCompat(bool fog)
|
||||
bool FDrawInfo::PutFlatCompat(GLFlat *flat, bool fog)
|
||||
{
|
||||
// are lights possible?
|
||||
if (mDrawer->FixedColormap != CM_DEFAULT || !gl_lights || !gltexture || renderstyle != STYLE_Translucent || alpha < 1.f - FLT_EPSILON || sector->lighthead == NULL) return false;
|
||||
if (FixedColormap != CM_DEFAULT || !gl_lights || !flat->gltexture || flat->renderstyle != STYLE_Translucent || flat->alpha < 1.f - FLT_EPSILON || flat->sector->lighthead == NULL) return false;
|
||||
|
||||
static int list_indices[2][2] =
|
||||
{ { GLLDL_FLATS_PLAIN, GLLDL_FLATS_FOG },{ GLLDL_FLATS_MASKED, GLLDL_FLATS_FOGMASKED } };
|
||||
|
||||
bool masked = gltexture->isMasked() && ((renderflags&SSRF_RENDER3DPLANES) || stack);
|
||||
bool foggy = gl_CheckFog(&Colormap, lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
|
||||
bool masked = flat->gltexture->isMasked() && ((flat->renderflags&SSRF_RENDER3DPLANES) || flat->stack);
|
||||
bool foggy = CheckFog(&flat->Colormap, flat->lightlevel) || (level.flags&LEVEL_HASFADETABLE) || gl_lights_additive;
|
||||
|
||||
|
||||
int list = list_indices[masked][foggy];
|
||||
gl_drawinfo->dldrawlists[list].AddFlat(this);
|
||||
auto newflat = gl_drawinfo->dldrawlists[list].NewFlat();
|
||||
*newflat = *flat;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -594,11 +591,17 @@ bool GLFlat::PutFlatCompat(bool fog)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void GLWall::RenderFogBoundaryCompat()
|
||||
void FDrawInfo::RenderFogBoundaryCompat(GLWall *wall)
|
||||
{
|
||||
// without shaders some approximation is needed. This won't look as good
|
||||
// as the shader version but it's an acceptable compromise.
|
||||
float fogdensity = gl_GetFogDensity(lightlevel, Colormap.FadeColor, Colormap.FogDensity);
|
||||
auto &Colormap = wall->Colormap;
|
||||
auto &glseg = wall->glseg;
|
||||
auto tcs = wall->tcs;
|
||||
auto ztop = wall->ztop;
|
||||
auto zbottom = wall->zbottom;
|
||||
|
||||
float fogdensity = hw_GetFogDensity(wall->lightlevel, Colormap.FadeColor, Colormap.FogDensity);
|
||||
|
||||
float dist1 = Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, glseg.x1, glseg.y1);
|
||||
float dist2 = Dist2(r_viewpoint.Pos.X, r_viewpoint.Pos.Y, glseg.x2, glseg.y2);
|
||||
|
@ -618,14 +621,14 @@ void GLWall::RenderFogBoundaryCompat()
|
|||
glDepthFunc(GL_LEQUAL);
|
||||
glColor4f(fc[0], fc[1], fc[2], fogd1);
|
||||
glBegin(GL_TRIANGLE_FAN);
|
||||
glTexCoord2f(tcs[LOLFT].u, tcs[LOLFT].v);
|
||||
glTexCoord2f(tcs[GLWall::LOLFT].u, tcs[GLWall::LOLFT].v);
|
||||
glVertex3f(glseg.x1, zbottom[0], glseg.y1);
|
||||
glTexCoord2f(tcs[UPLFT].u, tcs[UPLFT].v);
|
||||
glTexCoord2f(tcs[GLWall::UPLFT].u, tcs[GLWall::UPLFT].v);
|
||||
glVertex3f(glseg.x1, ztop[0], glseg.y1);
|
||||
glColor4f(fc[0], fc[1], fc[2], fogd2);
|
||||
glTexCoord2f(tcs[UPRGT].u, tcs[UPRGT].v);
|
||||
glTexCoord2f(tcs[GLWall::UPRGT].u, tcs[GLWall::UPRGT].v);
|
||||
glVertex3f(glseg.x2, ztop[1], glseg.y2);
|
||||
glTexCoord2f(tcs[LORGT].u, tcs[LORGT].v);
|
||||
glTexCoord2f(tcs[GLWall::LORGT].u, tcs[GLWall::LORGT].v);
|
||||
glVertex3f(glseg.x2, zbottom[1], glseg.y2);
|
||||
glEnd();
|
||||
glDepthFunc(GL_LESS);
|
||||
|
@ -642,7 +645,7 @@ void GLWall::RenderFogBoundaryCompat()
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
|
||||
void FDrawInfo::DrawSubsectorLights(GLFlat *flat, subsector_t * sub, int pass)
|
||||
{
|
||||
Plane p;
|
||||
FVector3 nearPt, up, right, t1;
|
||||
|
@ -663,14 +666,14 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
|
|||
|
||||
// we must do the side check here because gl_SetupLight needs the correct plane orientation
|
||||
// which we don't have for Legacy-style 3D-floors
|
||||
double planeh = plane.plane.ZatPoint(light);
|
||||
if (gl_lights_checkside && ((planeh<light->Z() && ceiling) || (planeh>light->Z() && !ceiling)))
|
||||
double planeh = flat->plane.plane.ZatPoint(light);
|
||||
if (((planeh<light->Z() && flat->ceiling) || (planeh>light->Z() && !flat->ceiling)))
|
||||
{
|
||||
node = node->nextLight;
|
||||
continue;
|
||||
}
|
||||
|
||||
p.Set(plane.plane.Normal(), plane.plane.fD());
|
||||
p.Set(flat->plane.plane.Normal(), flat->plane.plane.fD());
|
||||
if (!gl_SetupLight(sub->sector->PortalGroup, p, light, nearPt, up, right, scale, false, pass != GLPASS_LIGHTTEX))
|
||||
{
|
||||
node = node->nextLight;
|
||||
|
@ -683,7 +686,7 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
|
|||
{
|
||||
vertex_t *vt = sub->firstline[k].v1;
|
||||
ptr->x = vt->fX();
|
||||
ptr->z = plane.plane.ZatPoint(vt) + dz;
|
||||
ptr->z = flat->plane.plane.ZatPoint(vt) + flat->dz;
|
||||
ptr->y = vt->fY();
|
||||
t1 = { ptr->x, ptr->z, ptr->y };
|
||||
FVector3 nearToVert = t1 - nearPt;
|
||||
|
@ -703,29 +706,29 @@ void GLFlat::DrawSubsectorLights(subsector_t * sub, int pass)
|
|||
//
|
||||
//==========================================================================
|
||||
|
||||
void GLFlat::DrawLightsCompat(int pass)
|
||||
void FDrawInfo::DrawLightsCompat(GLFlat *flat, int pass)
|
||||
{
|
||||
gl_RenderState.Apply();
|
||||
// Draw the subsectors belonging to this sector
|
||||
for (int i = 0; i<sector->subsectorcount; i++)
|
||||
for (int i = 0; i<flat->sector->subsectorcount; i++)
|
||||
{
|
||||
subsector_t * sub = sector->subsectors[i];
|
||||
if (gl_drawinfo->ss_renderflags[sub->Index()] & renderflags)
|
||||
subsector_t * sub = flat->sector->subsectors[i];
|
||||
if (gl_drawinfo->ss_renderflags[sub->Index()] & flat->renderflags)
|
||||
{
|
||||
DrawSubsectorLights(sub, pass);
|
||||
DrawSubsectorLights(flat, sub, pass);
|
||||
}
|
||||
}
|
||||
|
||||
// Draw the subsectors assigned to it due to missing textures
|
||||
if (!(renderflags&SSRF_RENDER3DPLANES))
|
||||
if (!(flat->renderflags&SSRF_RENDER3DPLANES))
|
||||
{
|
||||
gl_subsectorrendernode * node = (renderflags&SSRF_RENDERFLOOR) ?
|
||||
gl_drawinfo->GetOtherFloorPlanes(sector->sectornum) :
|
||||
gl_drawinfo->GetOtherCeilingPlanes(sector->sectornum);
|
||||
gl_subsectorrendernode * node = (flat->renderflags&SSRF_RENDERFLOOR) ?
|
||||
gl_drawinfo->GetOtherFloorPlanes(flat->sector->sectornum) :
|
||||
gl_drawinfo->GetOtherCeilingPlanes(flat->sector->sectornum);
|
||||
|
||||
while (node)
|
||||
{
|
||||
DrawSubsectorLights(node->sub, pass);
|
||||
DrawSubsectorLights(flat, node->sub, pass);
|
||||
node = node->next;
|
||||
}
|
||||
}
|
||||
|
@ -737,22 +740,27 @@ void GLFlat::DrawLightsCompat(int pass)
|
|||
// Sets up the texture coordinates for one light to be rendered
|
||||
//
|
||||
//==========================================================================
|
||||
bool GLWall::PrepareLight(ADynamicLight * light, int pass)
|
||||
static bool PrepareLight(GLWall *wall, ADynamicLight * light, int pass)
|
||||
{
|
||||
auto &glseg = wall->glseg;
|
||||
auto tcs = wall->tcs;
|
||||
auto ztop = wall->ztop;
|
||||
auto zbottom = wall->zbottom;
|
||||
|
||||
float vtx[] = { glseg.x1,zbottom[0],glseg.y1, glseg.x1,ztop[0],glseg.y1, glseg.x2,ztop[1],glseg.y2, glseg.x2,zbottom[1],glseg.y2 };
|
||||
Plane p;
|
||||
FVector3 nearPt, up, right;
|
||||
float scale;
|
||||
|
||||
auto normal = glseg.Normal();
|
||||
p.Set(normal, -normal.X * glseg.x1 - normal.Y * glseg.y1);
|
||||
p.Set(normal, -normal.X * glseg.x1 - normal.Z * glseg.y1);
|
||||
|
||||
if (!p.ValidNormal())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!gl_SetupLight(seg->frontsector->PortalGroup, p, light, nearPt, up, right, scale, true, pass != GLPASS_LIGHTTEX))
|
||||
if (!gl_SetupLight(wall->seg->frontsector->PortalGroup, p, light, nearPt, up, right, scale, true, pass != GLPASS_LIGHTTEX))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -782,27 +790,27 @@ bool GLWall::PrepareLight(ADynamicLight * light, int pass)
|
|||
}
|
||||
|
||||
|
||||
void GLWall::RenderLightsCompat(int pass)
|
||||
void FDrawInfo::RenderLightsCompat(GLWall *wall, int pass)
|
||||
{
|
||||
FLightNode * node;
|
||||
|
||||
// black fog is diminishing light and should affect lights less than the rest!
|
||||
if (pass == GLPASS_LIGHTTEX) mDrawer->SetFog((255 + lightlevel) >> 1, 0, NULL, false);
|
||||
else mDrawer->SetFog(lightlevel, 0, &Colormap, true);
|
||||
if (pass == GLPASS_LIGHTTEX) mDrawer->SetFog((255 + wall->lightlevel) >> 1, 0, NULL, false);
|
||||
else mDrawer->SetFog(wall->lightlevel, 0, &wall->Colormap, true);
|
||||
|
||||
if (seg->sidedef == NULL)
|
||||
if (wall->seg->sidedef == NULL)
|
||||
{
|
||||
return;
|
||||
}
|
||||
else if (!(seg->sidedef->Flags & WALLF_POLYOBJ))
|
||||
else if (!(wall->seg->sidedef->Flags & WALLF_POLYOBJ))
|
||||
{
|
||||
// Iterate through all dynamic lights which touch this wall and render them
|
||||
node = seg->sidedef->lighthead;
|
||||
node = wall->seg->sidedef->lighthead;
|
||||
}
|
||||
else if (sub)
|
||||
else if (wall->sub)
|
||||
{
|
||||
// To avoid constant rechecking for polyobjects use the subsector's lightlist instead
|
||||
node = sub->lighthead;
|
||||
node = wall->sub->lighthead;
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -810,7 +818,7 @@ void GLWall::RenderLightsCompat(int pass)
|
|||
}
|
||||
|
||||
texcoord save[4];
|
||||
memcpy(save, tcs, sizeof(tcs));
|
||||
memcpy(save, wall->tcs, sizeof(wall->tcs));
|
||||
while (node)
|
||||
{
|
||||
ADynamicLight * light = node->lightsource;
|
||||
|
@ -822,15 +830,15 @@ void GLWall::RenderLightsCompat(int pass)
|
|||
node = node->nextLight;
|
||||
continue;
|
||||
}
|
||||
if (PrepareLight(light, pass))
|
||||
if (PrepareLight(wall, light, pass))
|
||||
{
|
||||
vertcount = 0;
|
||||
RenderWall(RWF_TEXTURED);
|
||||
wall->vertcount = 0;
|
||||
RenderWall(wall, GLWall::RWF_TEXTURED);
|
||||
}
|
||||
node = node->nextLight;
|
||||
}
|
||||
memcpy(tcs, save, sizeof(tcs));
|
||||
vertcount = 0;
|
||||
memcpy(wall->tcs, save, sizeof(wall->tcs));
|
||||
wall->vertcount = 0;
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
|
@ -849,8 +857,8 @@ void GLSceneDrawer::RenderMultipassStuff()
|
|||
gl_RenderState.EnableTexture(false);
|
||||
gl_RenderState.EnableBrightmap(false);
|
||||
gl_RenderState.Apply();
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_PLAIN);
|
||||
|
||||
// Part 2: masked geometry. This is set up so that only pixels with alpha>0.5 will show
|
||||
// This creates a blank surface that only fills the nontransparent parts of the texture
|
||||
|
@ -858,18 +866,18 @@ void GLSceneDrawer::RenderMultipassStuff()
|
|||
gl_RenderState.SetTextureMode(TM_MASK);
|
||||
gl_RenderState.EnableBrightmap(true);
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_PLAIN);
|
||||
|
||||
// Part 3: The base of fogged surfaces, including the texture
|
||||
gl_RenderState.EnableBrightmap(false);
|
||||
gl_RenderState.SetTextureMode(TM_MODULATE);
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, 0);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(gl_drawinfo, GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(gl_drawinfo, GLPASS_PLAIN);
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_threshold);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(gl_drawinfo, GLPASS_PLAIN);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(gl_drawinfo, GLPASS_PLAIN);
|
||||
|
||||
// second pass: draw lights
|
||||
glDepthMask(false);
|
||||
|
@ -880,10 +888,10 @@ void GLSceneDrawer::RenderMultipassStuff()
|
|||
gl_RenderState.BlendFunc(GL_ONE, GL_ONE);
|
||||
glDepthFunc(GL_EQUAL);
|
||||
if (level.lightmode == 8) gl_RenderState.SetSoftLightLevel(255);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_LIGHTTEX);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_LIGHTTEX);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_LIGHTTEX);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_LIGHTTEX);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX);
|
||||
gl_RenderState.BlendEquation(GL_FUNC_ADD);
|
||||
}
|
||||
else gl_lights = false;
|
||||
|
@ -895,11 +903,11 @@ void GLSceneDrawer::RenderMultipassStuff()
|
|||
gl_RenderState.EnableFog(false);
|
||||
gl_RenderState.AlphaFunc(GL_GEQUAL, 0);
|
||||
glDepthFunc(GL_LEQUAL);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_TEXONLY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_TEXONLY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_TEXONLY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_TEXONLY);
|
||||
gl_RenderState.AlphaFunc(GL_GREATER, gl_mask_threshold);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_TEXONLY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_TEXONLY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_TEXONLY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_TEXONLY);
|
||||
|
||||
// fourth pass: additive lights
|
||||
gl_RenderState.EnableFog(true);
|
||||
|
@ -907,14 +915,14 @@ void GLSceneDrawer::RenderMultipassStuff()
|
|||
glDepthFunc(GL_EQUAL);
|
||||
if (gl_SetupLightTexture())
|
||||
{
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(GLPASS_LIGHTTEX_ADDITIVE);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(GLPASS_LIGHTTEX_ADDITIVE);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(GLPASS_LIGHTTEX_ADDITIVE);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(GLPASS_LIGHTTEX_FOGGY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(GLPASS_LIGHTTEX_FOGGY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(GLPASS_LIGHTTEX_FOGGY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(GLPASS_LIGHTTEX_FOGGY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_PLAIN].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_MASKED].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_PLAIN].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_MASKED].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_ADDITIVE);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOG].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_WALLS_FOGMASKED].DrawWalls(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOG].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
|
||||
gl_drawinfo->dldrawlists[GLLDL_FLATS_FOGMASKED].DrawFlats(gl_drawinfo, GLPASS_LIGHTTEX_FOGGY);
|
||||
}
|
||||
else gl_lights = false;
|
||||
|
||||
|
@ -1001,4 +1009,4 @@ int LegacyDesaturation(F2DDrawer::RenderCommand &cmd)
|
|||
auto &tbl = DesaturatedTranslationTable[cmd.mTranslation];
|
||||
tbl.tables[desat] = newremap;
|
||||
return newremap->GetUniqueIndex();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,14 +30,10 @@
|
|||
#include "gl/system/gl_system.h"
|
||||
#include "tarray.h"
|
||||
#include "doomtype.h"
|
||||
#include "zstring.h"
|
||||
#include "i_system.h"
|
||||
#include "r_utility.h"
|
||||
#include "w_wad.h"
|
||||
#include "gl/dynlights/gl_dynlight.h"
|
||||
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
|
||||
|
||||
class LegacyShader
|
||||
|
|
|
@ -29,9 +29,6 @@
|
|||
#include "doomtype.h"
|
||||
#include "p_local.h"
|
||||
#include "r_state.h"
|
||||
#include "m_argv.h"
|
||||
#include "c_cvars.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
|
@ -160,13 +157,9 @@ FFlatVertexBuffer::FFlatVertexBuffer(int width, int height)
|
|||
mIndex = mCurIndex = 0;
|
||||
mNumReserved = NUM_RESERVED;
|
||||
|
||||
if (gl.buffermethod == BM_DEFERRED)
|
||||
{
|
||||
Map();
|
||||
memcpy(map, &vbo_shadowdata[0], mNumReserved * sizeof(FFlatVertex));
|
||||
Unmap();
|
||||
}
|
||||
|
||||
Map();
|
||||
memcpy(map, &vbo_shadowdata[0], mNumReserved * sizeof(FFlatVertex));
|
||||
Unmap();
|
||||
}
|
||||
|
||||
FFlatVertexBuffer::~FFlatVertexBuffer()
|
||||
|
|
|
@ -23,11 +23,15 @@
|
|||
#ifndef __VERTEXBUFFER_H
|
||||
#define __VERTEXBUFFER_H
|
||||
|
||||
#include <atomic>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include "tarray.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
#include "hwrenderer/utility/hw_clock.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "r_data/models/models.h"
|
||||
#include "hwrenderer/data/flatvertices.h"
|
||||
#include "hwrenderer/scene/hw_skydome.h"
|
||||
|
||||
struct vertex_t;
|
||||
struct secplane_t;
|
||||
|
@ -93,7 +97,8 @@ class FFlatVertexBuffer : public FVertexBuffer, public FFlatVertexGenerator
|
|||
{
|
||||
FFlatVertex *map;
|
||||
unsigned int mIndex;
|
||||
unsigned int mCurIndex;
|
||||
std::atomic<unsigned int> mCurIndex;
|
||||
std::mutex mBufferMutex;
|
||||
unsigned int mNumReserved;
|
||||
|
||||
|
||||
|
@ -125,12 +130,22 @@ public:
|
|||
{
|
||||
return &map[mCurIndex];
|
||||
}
|
||||
FFlatVertex *Alloc(int num, int *poffset)
|
||||
|
||||
template<class T>
|
||||
FFlatVertex *Alloc(int num, T *poffset)
|
||||
{
|
||||
again:
|
||||
FFlatVertex *p = GetBuffer();
|
||||
*poffset = mCurIndex;
|
||||
mCurIndex += num;
|
||||
if (mCurIndex >= BUFFER_SIZE_TO_USE) mCurIndex = mIndex;
|
||||
auto index = mCurIndex.fetch_add(num);
|
||||
*poffset = static_cast<T>(index);
|
||||
if (index + num >= BUFFER_SIZE_TO_USE)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(mBufferMutex);
|
||||
if (mCurIndex >= BUFFER_SIZE_TO_USE) // retest condition, in case another thread got here first
|
||||
mCurIndex = mIndex;
|
||||
|
||||
if (index >= BUFFER_SIZE_TO_USE) goto again;
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
|
@ -182,73 +197,15 @@ public:
|
|||
};
|
||||
|
||||
|
||||
struct FSkyVertex
|
||||
class FSkyVertexBuffer : public FVertexBuffer, public FSkyDomeCreator
|
||||
{
|
||||
float x, y, z, u, v;
|
||||
PalEntry color;
|
||||
|
||||
void Set(float xx, float zz, float yy, float uu=0, float vv=0, PalEntry col=0xffffffff)
|
||||
{
|
||||
x = xx;
|
||||
z = zz;
|
||||
y = yy;
|
||||
u = uu;
|
||||
v = vv;
|
||||
color = col;
|
||||
}
|
||||
|
||||
void SetXYZ(float xx, float yy, float zz, float uu = 0, float vv = 0, PalEntry col = 0xffffffff)
|
||||
{
|
||||
x = xx;
|
||||
y = yy;
|
||||
z = zz;
|
||||
u = uu;
|
||||
v = vv;
|
||||
color = col;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FSkyVertexBuffer : public FVertexBuffer
|
||||
{
|
||||
public:
|
||||
static const int SKYHEMI_UPPER = 1;
|
||||
static const int SKYHEMI_LOWER = 2;
|
||||
|
||||
enum
|
||||
{
|
||||
SKYMODE_MAINLAYER = 0,
|
||||
SKYMODE_SECONDLAYER = 1,
|
||||
SKYMODE_FOGLAYER = 2
|
||||
};
|
||||
|
||||
private:
|
||||
TArray<FSkyVertex> mVertices;
|
||||
TArray<unsigned int> mPrimStart;
|
||||
|
||||
int mRows, mColumns;
|
||||
|
||||
// indices for sky cubemap faces
|
||||
int mFaceStart[7];
|
||||
int mSideStart;
|
||||
|
||||
void SkyVertex(int r, int c, bool yflip);
|
||||
void CreateSkyHemisphere(int hemi);
|
||||
void CreateDome();
|
||||
void RenderRow(int prim, int row);
|
||||
|
||||
public:
|
||||
|
||||
FSkyVertexBuffer();
|
||||
virtual ~FSkyVertexBuffer();
|
||||
void RenderDome(FMaterial *tex, int mode);
|
||||
void BindVBO();
|
||||
int FaceStart(int i)
|
||||
{
|
||||
if (i >= 0 && i < 7) return mFaceStart[i];
|
||||
else return mSideStart;
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
class FModelVertexBuffer : public FVertexBuffer, public IModelVertexBuffer
|
||||
|
|
|
@ -28,9 +28,8 @@
|
|||
#include "gl/system/gl_system.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "gl/dynlights/gl_dynlight.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/utility//gl_clock.h"
|
||||
#include "hwrenderer/utility/hw_clock.h"
|
||||
#include "hwrenderer/dynlights/hw_dynlightdata.h"
|
||||
|
||||
static const int INITIAL_BUFFER_SIZE = 160000; // This means 80000 lights per frame and 160000*16 bytes == 2.56 MB.
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
#define __GL_LIGHTBUFFER_H
|
||||
|
||||
#include "tarray.h"
|
||||
struct FDynLightData;
|
||||
#include "hwrenderer/dynlights/hw_dynlightdata.h"
|
||||
|
||||
class FLightBuffer
|
||||
{
|
||||
|
@ -35,5 +35,9 @@ public:
|
|||
int GetIndex(int i) const { return mIndices[i]; }
|
||||
};
|
||||
|
||||
int gl_SetDynModelLight(AActor *self, int dynlightindex);
|
||||
|
||||
extern thread_local FDynLightData lightdata;
|
||||
|
||||
#endif
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
// 1D dynamic shadow maps
|
||||
// 1D dynamic shadow maps (OpenGL dependent part)
|
||||
// Copyright(C) 2017 Magnus Norddahl
|
||||
// All rights reserved.
|
||||
//
|
||||
|
@ -23,80 +23,15 @@
|
|||
#include "gl/system/gl_system.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/dynlights/gl_shadowmap.h"
|
||||
#include "gl/dynlights/gl_dynlight.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_debug.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_postprocessstate.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include "gl/shaders/gl_shadowmapshader.h"
|
||||
#include "r_state.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "hwrenderer/dynlights/hw_dynlightdata.h"
|
||||
#include "stats.h"
|
||||
|
||||
/*
|
||||
The 1D shadow maps are stored in a 1024x1024 texture as float depth values (R32F).
|
||||
|
||||
Each line in the texture is assigned to a single light. For example, to grab depth values for light 20
|
||||
the fragment shader (main.fp) needs to sample from row 20. That is, the V texture coordinate needs
|
||||
to be 20.5/1024.
|
||||
|
||||
mLightToShadowmap is a hash map storing which line each ADynamicLight is assigned to. The public
|
||||
ShadowMapIndex function allows the main rendering to find the index and upload that along with the
|
||||
normal light data. From there, the main.fp shader can sample from the shadow map texture, which
|
||||
is currently always bound to texture unit 16.
|
||||
|
||||
The texel row for each light is split into four parts. One for each direction, like a cube texture,
|
||||
but then only in 2D where this reduces itself to a square. When main.fp samples from the shadow map
|
||||
it first decides in which direction the fragment is (relative to the light), like cubemap sampling does
|
||||
for 3D, but once again just for the 2D case.
|
||||
|
||||
Texels 0-255 is Y positive, 256-511 is X positive, 512-767 is Y negative and 768-1023 is X negative.
|
||||
|
||||
Generating the shadow map itself is done by FShadowMap::Update(). The shadow map texture's FBO is
|
||||
bound and then a screen quad is drawn to make a fragment shader cover all texels. For each fragment
|
||||
it shoots a ray and collects the distance to what it hit.
|
||||
|
||||
The shadowmap.fp shader knows which light and texel it is processing by mapping gl_FragCoord.y back
|
||||
to the light index, and it knows which direction to ray trace by looking at gl_FragCoord.x. For
|
||||
example, if gl_FragCoord.y is 20.5, then it knows its processing light 20, and if gl_FragCoord.x is
|
||||
127.5, then it knows we are shooting straight ahead for the Y positive direction.
|
||||
|
||||
Ray testing is done by uploading two GPU storage buffers - one holding AABB tree nodes, and one with
|
||||
the line segments at the leaf nodes of the tree. The fragment shader then performs a test same way
|
||||
as on the CPU, except everything uses indexes as pointers are not allowed in GLSL.
|
||||
*/
|
||||
|
||||
namespace
|
||||
{
|
||||
cycle_t UpdateCycles;
|
||||
int LightsProcessed;
|
||||
int LightsShadowmapped;
|
||||
}
|
||||
|
||||
ADD_STAT(shadowmap)
|
||||
{
|
||||
FString out;
|
||||
out.Format("upload=%04.2f ms lights=%d shadowmapped=%d", UpdateCycles.TimeMS(), LightsProcessed, LightsShadowmapped);
|
||||
return out;
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int, gl_shadowmap_quality, 512, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
{
|
||||
switch (self)
|
||||
{
|
||||
case 128:
|
||||
case 256:
|
||||
case 512:
|
||||
case 1024:
|
||||
break;
|
||||
default:
|
||||
self = 128;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void FShadowMap::Update()
|
||||
{
|
||||
UpdateCycles.Reset();
|
||||
|
@ -139,63 +74,10 @@ void FShadowMap::Update()
|
|||
UpdateCycles.Unclock();
|
||||
}
|
||||
|
||||
bool FShadowMap::ShadowTest(ADynamicLight *light, const DVector3 &pos)
|
||||
{
|
||||
if (light->shadowmapped && light->radius > 0.0 && IsEnabled() && mAABBTree)
|
||||
return mAABBTree->RayTest(light->Pos(), pos) >= 1.0f;
|
||||
else
|
||||
return true;
|
||||
}
|
||||
|
||||
bool FShadowMap::IsEnabled() const
|
||||
{
|
||||
return gl_light_shadowmap && !!(gl.flags & RFL_SHADER_STORAGE_BUFFER);
|
||||
}
|
||||
|
||||
int FShadowMap::ShadowMapIndex(ADynamicLight *light)
|
||||
{
|
||||
if (IsEnabled())
|
||||
{
|
||||
auto val = mLightToShadowmap.CheckKey(light);
|
||||
if (val != nullptr) return *val;
|
||||
}
|
||||
return 1024;
|
||||
}
|
||||
|
||||
void FShadowMap::UploadLights()
|
||||
{
|
||||
if (mLights.Size() != 1024 * 4) mLights.Resize(1024 * 4);
|
||||
int lightindex = 0;
|
||||
mLightToShadowmap.Clear(mLightToShadowmap.CountUsed() * 2); // To do: allow clearing a TMap while building up a reserve
|
||||
|
||||
// Todo: this should go through the blockmap in a spiral pattern around the player so that closer lights are preferred.
|
||||
TThinkerIterator<ADynamicLight> it(STAT_DLIGHT);
|
||||
while (auto light = it.Next())
|
||||
{
|
||||
LightsProcessed++;
|
||||
if (light->shadowmapped)
|
||||
{
|
||||
LightsShadowmapped++;
|
||||
|
||||
mLightToShadowmap[light] = lightindex >> 2;
|
||||
|
||||
mLights[lightindex] = light->X();
|
||||
mLights[lightindex+1] = light->Y();
|
||||
mLights[lightindex+2] = light->Z();
|
||||
mLights[lightindex+3] = light->GetRadius();
|
||||
lightindex += 4;
|
||||
|
||||
if (lightindex == 1024*4) // Only 1024 lights for now
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
for (; lightindex < 1024 * 4; lightindex++)
|
||||
{
|
||||
mLights[lightindex] = 0;
|
||||
}
|
||||
|
||||
CollectLights();
|
||||
|
||||
if (mLightList == 0)
|
||||
glGenBuffers(1, (GLuint*)&mLightList);
|
||||
|
||||
|
@ -208,28 +90,21 @@ void FShadowMap::UploadLights()
|
|||
|
||||
void FShadowMap::UploadAABBTree()
|
||||
{
|
||||
// Just comparing the level info is not enough. If two MAPINFO-less levels get played after each other,
|
||||
// they can both refer to the same default level info.
|
||||
if (level.info != mLastLevel && (level.nodes.Size() != mLastNumNodes || level.segs.Size() != mLastNumSegs))
|
||||
Clear();
|
||||
if (!ValidateAABBTree())
|
||||
{
|
||||
int oldBinding = 0;
|
||||
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &oldBinding);
|
||||
|
||||
if (mAABBTree)
|
||||
return;
|
||||
glGenBuffers(1, (GLuint*)&mNodesBuffer);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mNodesBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(hwrenderer::AABBTreeNode) * mAABBTree->nodes.Size(), &mAABBTree->nodes[0], GL_STATIC_DRAW);
|
||||
|
||||
mAABBTree.reset(new hwrenderer::LevelAABBTree());
|
||||
glGenBuffers(1, (GLuint*)&mLinesBuffer);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mLinesBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(hwrenderer::AABBTreeLine) * mAABBTree->lines.Size(), &mAABBTree->lines[0], GL_STATIC_DRAW);
|
||||
|
||||
int oldBinding = 0;
|
||||
glGetIntegerv(GL_SHADER_STORAGE_BUFFER_BINDING, &oldBinding);
|
||||
|
||||
glGenBuffers(1, (GLuint*)&mNodesBuffer);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mNodesBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(hwrenderer::AABBTreeNode) * mAABBTree->nodes.Size(), &mAABBTree->nodes[0], GL_STATIC_DRAW);
|
||||
|
||||
glGenBuffers(1, (GLuint*)&mLinesBuffer);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, mLinesBuffer);
|
||||
glBufferData(GL_SHADER_STORAGE_BUFFER, sizeof(hwrenderer::AABBTreeLine) * mAABBTree->lines.Size(), &mAABBTree->lines[0], GL_STATIC_DRAW);
|
||||
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
|
||||
glBindBuffer(GL_SHADER_STORAGE_BUFFER, oldBinding);
|
||||
}
|
||||
}
|
||||
|
||||
void FShadowMap::Clear()
|
||||
|
@ -251,10 +126,4 @@ void FShadowMap::Clear()
|
|||
glDeleteBuffers(1, (GLuint*)&mLinesBuffer);
|
||||
mLinesBuffer = 0;
|
||||
}
|
||||
|
||||
mAABBTree.reset();
|
||||
|
||||
mLastLevel = level.info;
|
||||
mLastNumNodes = level.nodes.Size();
|
||||
mLastNumSegs = level.segs.Size();
|
||||
}
|
||||
|
|
|
@ -1,33 +1,18 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include "hwrenderer/dynlights/hw_aabbtree.h"
|
||||
#include "tarray.h"
|
||||
#include <memory>
|
||||
#include "hwrenderer/dynlights/hw_shadowmap.h"
|
||||
|
||||
class ADynamicLight;
|
||||
struct level_info_t;
|
||||
|
||||
class FShadowMap
|
||||
class FShadowMap : public IShadowMap
|
||||
{
|
||||
public:
|
||||
FShadowMap() { }
|
||||
~FShadowMap() { Clear(); }
|
||||
|
||||
// Release resources
|
||||
void Clear();
|
||||
void Clear() override;
|
||||
|
||||
// Update shadow map texture
|
||||
void Update();
|
||||
|
||||
// Return the assigned shadow map index for a given light
|
||||
int ShadowMapIndex(ADynamicLight *light);
|
||||
|
||||
// Test if a world position is in shadow relative to the specified light and returns false if it is
|
||||
bool ShadowTest(ADynamicLight *light, const DVector3 &pos);
|
||||
|
||||
// Returns true if gl_light_shadowmap is enabled and supported by the hardware
|
||||
bool IsEnabled() const;
|
||||
void Update() override;
|
||||
|
||||
private:
|
||||
// Upload the AABB-tree to the GPU
|
||||
|
@ -39,24 +24,7 @@ private:
|
|||
// OpenGL storage buffer with the list of lights in the shadow map texture
|
||||
int mLightList = 0;
|
||||
|
||||
// Working buffer for creating the list of lights. Stored here to avoid allocating memory each frame
|
||||
TArray<float> mLights;
|
||||
|
||||
// The assigned shadow map index for each light
|
||||
TMap<ADynamicLight*, int> mLightToShadowmap;
|
||||
|
||||
// OpenGL storage buffers for the AABB tree
|
||||
int mNodesBuffer = 0;
|
||||
int mLinesBuffer = 0;
|
||||
|
||||
// Used to detect when a level change requires the AABB tree to be regenerated
|
||||
level_info_t *mLastLevel = nullptr;
|
||||
unsigned mLastNumNodes = 0;
|
||||
unsigned mLastNumSegs = 0;
|
||||
|
||||
// AABB-tree of the level, used for ray tests
|
||||
std::unique_ptr<hwrenderer::LevelAABBTree> mAABBTree;
|
||||
|
||||
FShadowMap(const FShadowMap &) = delete;
|
||||
FShadowMap &operator=(FShadowMap &) = delete;
|
||||
};
|
||||
|
|
|
@ -28,27 +28,20 @@
|
|||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "w_wad.h"
|
||||
#include "cmdlib.h"
|
||||
#include "sc_man.h"
|
||||
#include "m_crc32.h"
|
||||
#include "c_console.h"
|
||||
#include "g_game.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
#include "r_state.h"
|
||||
#include "d_player.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "r_utility.h"
|
||||
#include "i_time.h"
|
||||
//#include "resources/voxels.h"
|
||||
//#include "gl/gl_intern.h"
|
||||
#include "hwrenderer/textures/hw_material.h"
|
||||
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
|
||||
|
|
|
@ -1,30 +0,0 @@
|
|||
#ifndef __GL_COLORMAP
|
||||
#define __GL_COLORMAP
|
||||
|
||||
#include "doomtype.h"
|
||||
#include "v_palette.h"
|
||||
#include "r_data/colormaps.h"
|
||||
|
||||
struct lightlist_t;
|
||||
|
||||
enum EColorManipulation
|
||||
{
|
||||
CM_SPECIAL2D = -3, // the special colormaps get passed as color pair from the 2D drawer so they need a different value here.
|
||||
CM_PLAIN2D = -2, // regular 2D drawing.
|
||||
CM_INVALID=-1,
|
||||
CM_DEFAULT=0, // untranslated
|
||||
CM_FIRSTSPECIALCOLORMAP, // first special fixed colormap
|
||||
CM_FIRSTSPECIALCOLORMAPFORCED= 0x08000000, // first special fixed colormap, application forced (for 2D overlays)
|
||||
|
||||
CM_FOGLAYER = 0x10000000, // Sprite shaped fog layer
|
||||
|
||||
// These are not to be passed to the texture manager
|
||||
CM_LITE = 0x20000000, // special values to handle these items without excessive hacking
|
||||
CM_TORCH= 0x20000010, // These are not real color manipulations
|
||||
};
|
||||
|
||||
#define CM_MAXCOLORMAP int(CM_FIRSTSPECIALCOLORMAP + SpecialColormaps.Size())
|
||||
#define CM_MAXCOLORMAPFORCED int(CM_FIRSTSPECIALCOLORMAPFORCED + SpecialColormaps.Size())
|
||||
|
||||
|
||||
#endif
|
|
@ -27,73 +27,13 @@
|
|||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "gl/renderer/gl_colormap.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "gl/renderer/gl_lightdata.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "c_dispatch.h"
|
||||
#include "p_local.h"
|
||||
#include "g_level.h"
|
||||
#include "r_sky.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
// externally settable lighting properties
|
||||
static float distfogtable[2][256]; // light to fog conversion table for black fog
|
||||
|
||||
CVAR(Int, gl_weaponlight, 8, CVAR_ARCHIVE);
|
||||
CUSTOM_CVAR(Bool, gl_enhanced_nightvision, true, CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||
{
|
||||
// The fixed colormap state needs to be reset because if this happens when
|
||||
// a shader is set to CM_LITE or CM_TORCH it won't register the change in behavior caused by this CVAR.
|
||||
if (GLRenderer != nullptr && GLRenderer->mShaderManager != nullptr)
|
||||
{
|
||||
GLRenderer->mShaderManager->ResetFixedColormap();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Sets up the fog tables
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
CUSTOM_CVAR (Int, gl_distfog, 70, CVAR_ARCHIVE | CVAR_GLOBALCONFIG)
|
||||
{
|
||||
for (int i=0;i<256;i++)
|
||||
{
|
||||
|
||||
if (i<164)
|
||||
{
|
||||
distfogtable[0][i]= (gl_distfog>>1) + (gl_distfog)*(164-i)/164;
|
||||
}
|
||||
else if (i<230)
|
||||
{
|
||||
distfogtable[0][i]= (gl_distfog>>1) - (gl_distfog>>1)*(i-164)/(230-164);
|
||||
}
|
||||
else distfogtable[0][i]=0;
|
||||
|
||||
if (i<128)
|
||||
{
|
||||
distfogtable[1][i]= 6.f + (gl_distfog>>1) + (gl_distfog)*(128-i)/48;
|
||||
}
|
||||
else if (i<216)
|
||||
{
|
||||
distfogtable[1][i]= (216.f-i) / ((216.f-128.f)) * gl_distfog / 10;
|
||||
}
|
||||
else distfogtable[1][i]=0;
|
||||
}
|
||||
}
|
||||
|
||||
CUSTOM_CVAR(Int,gl_fogmode,1,CVAR_ARCHIVE|CVAR_NOINITCALL)
|
||||
{
|
||||
if (self>2) self=2;
|
||||
if (self<0) self=0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
@ -149,79 +89,6 @@ void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblend
|
|||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Get current light level
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
int gl_CalcLightLevel(int lightlevel, int rellight, bool weapon)
|
||||
{
|
||||
int light;
|
||||
|
||||
if (lightlevel == 0) return 0;
|
||||
|
||||
if ((level.lightmode & 2) && lightlevel < 192 && !weapon)
|
||||
{
|
||||
if (lightlevel > 100)
|
||||
{
|
||||
light = xs_CRoundToInt(192.f - (192 - lightlevel)* 1.87f);
|
||||
if (light + rellight < 20)
|
||||
{
|
||||
light = 20 + (light + rellight - 20) / 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
light += rellight;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
light = (lightlevel + rellight) / 5;
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
light=lightlevel+rellight;
|
||||
}
|
||||
|
||||
return clamp(light, 0, 255);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Get current light color
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
static PalEntry gl_CalcLightColor(int light, PalEntry pe, int blendfactor)
|
||||
{
|
||||
int r,g,b;
|
||||
|
||||
if (level.lightmode == 8)
|
||||
{
|
||||
return pe;
|
||||
}
|
||||
else if (blendfactor == 0)
|
||||
{
|
||||
r = pe.r * light / 255;
|
||||
g = pe.g * light / 255;
|
||||
b = pe.b * light / 255;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is what Legacy does with colored light in 3D volumes. No, it doesn't really make sense...
|
||||
// It also doesn't translate well to software style lighting.
|
||||
int mixlight = light * (255 - blendfactor);
|
||||
|
||||
r = (mixlight + pe.r * blendfactor) / 255;
|
||||
g = (mixlight + pe.g * blendfactor) / 255;
|
||||
b = (mixlight + pe.b * blendfactor) / 255;
|
||||
}
|
||||
return PalEntry(255, uint8_t(r), uint8_t(g), uint8_t(b));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// set current light color
|
||||
|
@ -236,144 +103,13 @@ void gl_SetColor(int sectorlightlevel, int rellight, bool fullbright, const FCol
|
|||
}
|
||||
else
|
||||
{
|
||||
int hwlightlevel = gl_CalcLightLevel(sectorlightlevel, rellight, weapon);
|
||||
PalEntry pe = gl_CalcLightColor(hwlightlevel, cm.LightColor, cm.BlendFactor);
|
||||
int hwlightlevel = hw_CalcLightLevel(sectorlightlevel, rellight, weapon);
|
||||
PalEntry pe = hw_CalcLightColor(hwlightlevel, cm.LightColor, cm.BlendFactor);
|
||||
gl_RenderState.SetColorAlpha(pe, alpha, cm.Desaturation);
|
||||
gl_RenderState.SetSoftLightLevel(gl_ClampLight(sectorlightlevel + rellight));
|
||||
gl_RenderState.SetSoftLightLevel(hw_ClampLight(sectorlightlevel + rellight));
|
||||
}
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// calculates the current fog density
|
||||
//
|
||||
// Rules for fog:
|
||||
//
|
||||
// 1. If bit 4 of gl_lightmode is set always use the level's fog density.
|
||||
// This is what Legacy's GL render does.
|
||||
// 2. black fog means no fog and always uses the distfogtable based on the level's fog density setting
|
||||
// 3. If outside fog is defined and the current fog color is the same as the outside fog
|
||||
// the engine always uses the outside fog density to make the fog uniform across the level.
|
||||
// If the outside fog's density is undefined it uses the level's fog density and if that is
|
||||
// not defined it uses a default of 70.
|
||||
// 4. If a global fog density is specified it is being used for all fog on the level
|
||||
// 5. If none of the above apply fog density is based on the light level as for the software renderer.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity)
|
||||
{
|
||||
float density;
|
||||
|
||||
if (level.lightmode & 4)
|
||||
{
|
||||
// uses approximations of Legacy's default settings.
|
||||
density = level.fogdensity ? level.fogdensity : 18;
|
||||
}
|
||||
else if (sectorfogdensity != 0)
|
||||
{
|
||||
// case 1: Sector has an explicit fog density set.
|
||||
density = sectorfogdensity;
|
||||
}
|
||||
else if ((fogcolor.d & 0xffffff) == 0)
|
||||
{
|
||||
// case 2: black fog
|
||||
if (level.lightmode != 8 && !(level.flags3 & LEVEL3_NOLIGHTFADE))
|
||||
{
|
||||
density = distfogtable[level.lightmode != 0][gl_ClampLight(lightlevel)];
|
||||
}
|
||||
else
|
||||
{
|
||||
density = 0;
|
||||
}
|
||||
}
|
||||
else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff))
|
||||
{
|
||||
// case 3. outsidefogdensity has already been set as needed
|
||||
density = level.outsidefogdensity;
|
||||
}
|
||||
else if (level.fogdensity != 0)
|
||||
{
|
||||
// case 4: level has fog density set
|
||||
density = level.fogdensity;
|
||||
}
|
||||
else if (lightlevel < 248)
|
||||
{
|
||||
// case 5: use light level
|
||||
density = clamp<int>(255 - lightlevel, 30, 255);
|
||||
}
|
||||
else
|
||||
{
|
||||
density = 0.f;
|
||||
}
|
||||
return density;
|
||||
}
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Check if the current linedef is a candidate for a fog boundary
|
||||
//
|
||||
// Requirements for a fog boundary:
|
||||
// - front sector has no fog
|
||||
// - back sector has fog
|
||||
// - at least one of both does not have a sky ceiling.
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
bool gl_CheckFog(sector_t *frontsector, sector_t *backsector)
|
||||
{
|
||||
if (frontsector == backsector) return false; // there can't be a boundary if both sides are in the same sector.
|
||||
|
||||
// Check for fog boundaries. This needs a few more checks for the sectors
|
||||
|
||||
PalEntry fogcolor = frontsector->Colormap.FadeColor;
|
||||
|
||||
if ((fogcolor.d & 0xffffff) == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (fogcolor.a != 0)
|
||||
{
|
||||
}
|
||||
else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff))
|
||||
{
|
||||
}
|
||||
else if (level.fogdensity!=0 || (level.lightmode & 4))
|
||||
{
|
||||
// case 3: level has fog density set
|
||||
}
|
||||
else
|
||||
{
|
||||
// case 4: use light level
|
||||
if (frontsector->lightlevel >= 248) return false;
|
||||
}
|
||||
|
||||
fogcolor = backsector->Colormap.FadeColor;
|
||||
|
||||
if ((fogcolor.d & 0xffffff) == 0)
|
||||
{
|
||||
}
|
||||
else if (level.outsidefogdensity != 0 && APART(level.info->outsidefog) != 0xff && (fogcolor.d & 0xffffff) == (level.info->outsidefog & 0xffffff))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
else if (level.fogdensity!=0 || (level.lightmode & 4))
|
||||
{
|
||||
// case 3: level has fog density set
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// case 4: use light level
|
||||
if (backsector->lightlevel < 248) return false;
|
||||
}
|
||||
|
||||
// in all other cases this might create more problems than it solves.
|
||||
return ((frontsector->GetTexture(sector_t::ceiling)!=skyflatnum ||
|
||||
backsector->GetTexture(sector_t::ceiling)!=skyflatnum));
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Lighting stuff
|
||||
|
@ -427,7 +163,7 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c
|
|||
else if (cmap != NULL && !fullbright)
|
||||
{
|
||||
fogcolor = cmap->FadeColor;
|
||||
fogdensity = gl_GetFogDensity(lightlevel, fogcolor, cmap->FogDensity);
|
||||
fogdensity = hw_GetFogDensity(lightlevel, fogcolor, cmap->FogDensity);
|
||||
fogcolor.a=0;
|
||||
}
|
||||
else
|
||||
|
@ -450,7 +186,7 @@ void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *c
|
|||
{
|
||||
if (level.lightmode == 2 && fogcolor == 0)
|
||||
{
|
||||
float light = gl_CalcLightLevel(lightlevel, rellight, false);
|
||||
float light = hw_CalcLightLevel(lightlevel, rellight, false);
|
||||
gl_SetShaderLight(light, lightlevel);
|
||||
}
|
||||
else
|
||||
|
|
|
@ -4,35 +4,15 @@
|
|||
#include "v_palette.h"
|
||||
#include "p_3dfloors.h"
|
||||
#include "r_data/renderstyle.h"
|
||||
#include "gl/renderer/gl_colormap.h"
|
||||
|
||||
inline int gl_ClampLight(int lightlevel)
|
||||
{
|
||||
return clamp(lightlevel, 0, 255);
|
||||
}
|
||||
#include "hwrenderer/utility/hw_lighting.h"
|
||||
#include "r_data/colormaps.h"
|
||||
|
||||
void gl_GetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending,
|
||||
int *tm, int *sb, int *db, int *be);
|
||||
|
||||
int gl_CalcLightLevel(int lightlevel, int rellight, bool weapon);
|
||||
void gl_SetColor(int light, int rellight, bool fullbright, const FColormap &cm, float alpha, bool weapon=false);
|
||||
|
||||
float gl_GetFogDensity(int lightlevel, PalEntry fogcolor, int sectorfogdensity);
|
||||
struct sector_t;
|
||||
bool gl_CheckFog(sector_t *frontsector, sector_t *backsector);
|
||||
|
||||
void gl_SetFog(int lightlevel, int rellight, bool fullbright, const FColormap *cm, bool isadditive);
|
||||
|
||||
inline bool gl_isBlack(PalEntry color)
|
||||
{
|
||||
return color.r + color.g + color.b == 0;
|
||||
}
|
||||
|
||||
inline bool gl_isWhite(PalEntry color)
|
||||
{
|
||||
return color.r + color.g + color.b == 3*0xff;
|
||||
}
|
||||
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -28,23 +28,10 @@
|
|||
#include "gl/system/gl_system.h"
|
||||
#include "gi.h"
|
||||
#include "m_png.h"
|
||||
#include "m_random.h"
|
||||
#include "st_stuff.h"
|
||||
#include "dobject.h"
|
||||
#include "doomstat.h"
|
||||
#include "g_level.h"
|
||||
#include "r_data/r_interpolate.h"
|
||||
#include "r_utility.h"
|
||||
#include "d_player.h"
|
||||
#include "p_effect.h"
|
||||
#include "sbar.h"
|
||||
#include "po_man.h"
|
||||
#include "r_utility.h"
|
||||
#include "p_local.h"
|
||||
#include "colormatcher.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_framebuffer.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "gl/system/gl_debug.h"
|
||||
#include "gl/renderer/gl_lightdata.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
|
@ -60,9 +47,9 @@
|
|||
#include "gl/shaders/gl_lensshader.h"
|
||||
#include "gl/shaders/gl_fxaashader.h"
|
||||
#include "gl/shaders/gl_presentshader.h"
|
||||
#include "gl/shaders/gl_postprocessshader.h"
|
||||
#include "gl/shaders/gl_postprocessshaderinstance.h"
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
#include "gl/textures/gl_hwtexture.h"
|
||||
#include "r_videoscale.h"
|
||||
|
||||
//==========================================================================
|
||||
|
@ -614,7 +601,8 @@ void FGLRenderer::CreateTonemapPalette()
|
|||
{
|
||||
for (int b = 0; b < 64; b++)
|
||||
{
|
||||
PalEntry color = GPalette.BaseColors[(uint8_t)PTM_BestColor((uint32_t *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4), 0, 256)];
|
||||
PalEntry color = GPalette.BaseColors[(uint8_t)PTM_BestColor((uint32_t *)GPalette.BaseColors, (r << 2) | (r >> 4), (g << 2) | (g >> 4), (b << 2) | (b >> 4),
|
||||
gl_paltonemap_reverselookup, gl_paltonemap_powtable, 0, 256)];
|
||||
int index = ((r * 64 + g) * 64 + b) * 4;
|
||||
lut[index] = color.b;
|
||||
lut[index + 1] = color.g;
|
||||
|
@ -927,41 +915,3 @@ void FGLRenderer::ClearBorders()
|
|||
glDisable(GL_SCISSOR_TEST);
|
||||
}
|
||||
|
||||
|
||||
// [SP] Re-implemented BestColor for more precision rather than speed. This function is only ever called once until the game palette is changed.
|
||||
|
||||
int FGLRenderer::PTM_BestColor (const uint32_t *pal_in, int r, int g, int b, int first, int num)
|
||||
{
|
||||
const PalEntry *pal = (const PalEntry *)pal_in;
|
||||
static double powtable[256];
|
||||
static bool firstTime = true;
|
||||
static float trackpowtable = 0.;
|
||||
|
||||
double fbestdist = DBL_MAX, fdist;
|
||||
int bestcolor = 0;
|
||||
|
||||
if (firstTime || trackpowtable != gl_paltonemap_powtable)
|
||||
{
|
||||
trackpowtable = gl_paltonemap_powtable;
|
||||
firstTime = false;
|
||||
for (int x = 0; x < 256; x++) powtable[x] = pow((double)x/255, (double)gl_paltonemap_powtable);
|
||||
}
|
||||
|
||||
for (int color = first; color < num; color++)
|
||||
{
|
||||
double x = powtable[abs(r-pal[color].r)];
|
||||
double y = powtable[abs(g-pal[color].g)];
|
||||
double z = powtable[abs(b-pal[color].b)];
|
||||
fdist = x + y + z;
|
||||
if (color == first || ((gl_paltonemap_reverselookup)?(fdist <= fbestdist):(fdist < fbestdist)))
|
||||
{
|
||||
if (fdist == 0 && !gl_paltonemap_reverselookup)
|
||||
return color;
|
||||
|
||||
fbestdist = fdist;
|
||||
bestcolor = color;
|
||||
}
|
||||
}
|
||||
return bestcolor;
|
||||
}
|
||||
|
||||
|
|
|
@ -29,9 +29,6 @@
|
|||
#include "gl/system/gl_system.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_postprocessstate.h"
|
||||
|
||||
//-----------------------------------------------------------------------------
|
||||
|
|
|
@ -23,9 +23,7 @@
|
|||
#include "gl/system/gl_system.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/renderer/gl_quaddrawer.h"
|
||||
#include "r_data/matrix.h"
|
||||
|
||||
/*
|
||||
** For handling of dynamically created quads when no persistently mapped
|
||||
|
|
|
@ -26,18 +26,12 @@
|
|||
*/
|
||||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "m_swap.h"
|
||||
#include "v_video.h"
|
||||
#include "vectors.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_framebuffer.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "gl/system/gl_debug.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include "w_wad.h"
|
||||
#include "i_system.h"
|
||||
#include "doomerrors.h"
|
||||
#include <random>
|
||||
|
||||
CVAR(Int, gl_multisample, 1, CVAR_ARCHIVE|CVAR_GLOBALCONFIG);
|
||||
|
|
|
@ -27,13 +27,9 @@
|
|||
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "files.h"
|
||||
#include "m_swap.h"
|
||||
#include "v_video.h"
|
||||
#include "r_data/r_translate.h"
|
||||
#include "m_png.h"
|
||||
#include "m_crc32.h"
|
||||
#include "w_wad.h"
|
||||
#include "vectors.h"
|
||||
#include "doomstat.h"
|
||||
#include "i_time.h"
|
||||
#include "p_effect.h"
|
||||
|
@ -42,7 +38,7 @@
|
|||
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/system/gl_framebuffer.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "gl/system/gl_debug.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_lightdata.h"
|
||||
|
@ -52,8 +48,6 @@
|
|||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/scene/gl_swscene.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/shaders/gl_ambientshader.h"
|
||||
#include "gl/shaders/gl_bloomshader.h"
|
||||
#include "gl/shaders/gl_blurshader.h"
|
||||
|
@ -64,13 +58,9 @@
|
|||
#include "gl/shaders/gl_presentshader.h"
|
||||
#include "gl/shaders/gl_present3dRowshader.h"
|
||||
#include "gl/shaders/gl_shadowmapshader.h"
|
||||
#include "gl/shaders/gl_postprocessshader.h"
|
||||
#include "gl/shaders/gl_postprocessshaderinstance.h"
|
||||
#include "gl/stereo3d/gl_stereo3d.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "gl/textures/gl_samplers.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
#include "gl/models/gl_models.h"
|
||||
#include "gl/dynlights/gl_lightbuffer.h"
|
||||
#include "r_videoscale.h"
|
||||
|
||||
|
@ -105,7 +95,6 @@ FGLRenderer::FGLRenderer(OpenGLFrameBuffer *fb)
|
|||
mViewVector = FVector2(0,0);
|
||||
mVBO = nullptr;
|
||||
mSkyVBO = nullptr;
|
||||
gl_spriteindex = 0;
|
||||
mShaderManager = nullptr;
|
||||
mLights = nullptr;
|
||||
mTonemapPalette = nullptr;
|
||||
|
@ -168,8 +157,6 @@ void FGLRenderer::Initialize(int width, int height)
|
|||
legacyShaders = new LegacyShaderContainer;
|
||||
}
|
||||
|
||||
GetSpecialTextures();
|
||||
|
||||
// needed for the core profile, because someone decided it was a good idea to remove the default VAO.
|
||||
if (!gl.legacyMode)
|
||||
{
|
||||
|
@ -240,16 +227,6 @@ FGLRenderer::~FGLRenderer()
|
|||
delete mFXAALumaShader;
|
||||
}
|
||||
|
||||
|
||||
void FGLRenderer::GetSpecialTextures()
|
||||
{
|
||||
if (gl.legacyMode) glLight = TexMan.CheckForTexture("glstuff/gllight.png", ETextureType::MiscPatch);
|
||||
glPart2 = TexMan.CheckForTexture("glstuff/glpart2.png", ETextureType::MiscPatch);
|
||||
glPart = TexMan.CheckForTexture("glstuff/glpart.png", ETextureType::MiscPatch);
|
||||
mirrorTexture = TexMan.CheckForTexture("glstuff/mirror.png", ETextureType::MiscPatch);
|
||||
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Calculates the viewport values needed for 2D and 3D operations
|
||||
|
|
|
@ -9,6 +9,10 @@
|
|||
#include "gl/dynlights/gl_shadowmap.h"
|
||||
#include <functional>
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
struct particle_t;
|
||||
class FCanvasTexture;
|
||||
class FFlatVertexBuffer;
|
||||
|
@ -47,27 +51,6 @@ class FCustomPostProcessShaders;
|
|||
class GLSceneDrawer;
|
||||
class SWSceneDrawer;
|
||||
|
||||
inline float DEG2RAD(float deg)
|
||||
{
|
||||
return deg * float(M_PI / 180.0);
|
||||
}
|
||||
|
||||
inline float RAD2DEG(float deg)
|
||||
{
|
||||
return deg * float(180. / M_PI);
|
||||
}
|
||||
|
||||
enum SectorRenderFlags
|
||||
{
|
||||
// This is used to avoid creating too many drawinfos
|
||||
SSRF_RENDERFLOOR = 1,
|
||||
SSRF_RENDERCEILING = 2,
|
||||
SSRF_RENDER3DPLANES = 4,
|
||||
SSRF_RENDERALL = 7,
|
||||
SSRF_PROCESSED = 8,
|
||||
SSRF_SEEN = 16,
|
||||
};
|
||||
|
||||
struct GL_IRECT
|
||||
{
|
||||
int left,top;
|
||||
|
@ -126,7 +109,6 @@ public:
|
|||
AActor *mViewActor;
|
||||
FShaderManager *mShaderManager;
|
||||
FSamplerManager *mSamplerManager;
|
||||
int gl_spriteindex;
|
||||
unsigned int mFBID;
|
||||
unsigned int mVAOID;
|
||||
int mOldFBID;
|
||||
|
@ -157,13 +139,6 @@ public:
|
|||
|
||||
FShadowMap mShadowMap;
|
||||
|
||||
FTextureID glLight;
|
||||
FTextureID glPart2;
|
||||
FTextureID glPart;
|
||||
FTextureID mirrorTexture;
|
||||
|
||||
float mSky1Pos, mSky2Pos;
|
||||
|
||||
FRotator mAngles;
|
||||
FVector2 mViewVector;
|
||||
|
||||
|
@ -213,7 +188,6 @@ public:
|
|||
void CopyToBackbuffer(const GL_IRECT *bounds, bool applyGamma);
|
||||
void DrawPresentTexture(const GL_IRECT &box, bool applyGamma);
|
||||
void Flush();
|
||||
void GetSpecialTextures();
|
||||
void Draw2D(F2DDrawer *data);
|
||||
void RenderTextureView(FCanvasTexture *tex, AActor *Viewpoint, double FOV);
|
||||
void WriteSavePic(player_t *player, FileWriter *file, int width, int height);
|
||||
|
@ -228,24 +202,11 @@ public:
|
|||
double originx, double originy, double scalex, double scaley,
|
||||
DAngle rotation, const FColormap &colormap, PalEntry flatcolor, int lightlevel, int bottomclip);
|
||||
|
||||
int PTM_BestColor (const uint32_t *pal_in, int r, int g, int b, int first, int num);
|
||||
|
||||
static float GetZNear() { return 5.f; }
|
||||
static float GetZFar() { return 65536.f; }
|
||||
};
|
||||
|
||||
enum area_t
|
||||
{
|
||||
area_normal,
|
||||
area_below,
|
||||
area_above,
|
||||
area_default
|
||||
};
|
||||
|
||||
|
||||
// Global functions. Make them members of GLRenderer later?
|
||||
bool gl_CheckClip(side_t * sidedef, sector_t * frontsector, sector_t * backsector);
|
||||
sector_t * gl_FakeFlat(sector_t * sec, sector_t * dest, area_t in_area, bool back);
|
||||
#include "hwrenderer/scene/hw_fakeflat.h"
|
||||
|
||||
struct TexFilter_s
|
||||
{
|
||||
|
@ -257,4 +218,4 @@ struct TexFilter_s
|
|||
|
||||
extern FGLRenderer *GLRenderer;
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
@ -27,17 +27,15 @@
|
|||
|
||||
#include "templates.h"
|
||||
#include "doomstat.h"
|
||||
#include "r_data/colormaps.h"
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "hwrenderer/utility/hw_cvars.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/renderer/gl_colormap.h"
|
||||
#include "gl/dynlights//gl_lightbuffer.h"
|
||||
#include "gl/renderer/gl_renderbuffers.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
void gl_SetTextureMode(int type);
|
||||
|
||||
|
@ -69,7 +67,6 @@ void FRenderState::Reset()
|
|||
currentColorMask[0] = currentColorMask[1] = currentColorMask[2] = currentColorMask[3] = true;
|
||||
mFogColor.d = -1;
|
||||
mTextureMode = -1;
|
||||
mLightIndex = -1;
|
||||
mDesaturation = 0;
|
||||
mSrcBlend = GL_SRC_ALPHA;
|
||||
mDstBlend = GL_ONE_MINUS_SRC_ALPHA;
|
||||
|
@ -176,7 +173,7 @@ bool FRenderState::ApplyShader()
|
|||
activeShader->muClipHeightDirection.Set(mClipHeightDirection);
|
||||
activeShader->muTimer.Set((double)(screen->FrameTime - firstFrame) * (double)mShaderTimer / 1000.);
|
||||
activeShader->muAlphaThreshold.Set(mAlphaThreshold);
|
||||
activeShader->muLightIndex.Set(mLightIndex); // will always be -1 for now
|
||||
activeShader->muLightIndex.Set(-1);
|
||||
activeShader->muClipSplit.Set(mClipSplit);
|
||||
activeShader->muViewHeight.Set(viewheight);
|
||||
activeShader->muSpecularMaterial.Set(mGlossiness, mSpecularLevel);
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
#include <string.h>
|
||||
#include "gl/system/gl_interface.h"
|
||||
#include "r_data/matrix.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "hwrenderer/scene//hw_drawstructs.h"
|
||||
#include "hwrenderer/textures/hw_material.h"
|
||||
#include "c_cvars.h"
|
||||
#include "r_defs.h"
|
||||
#include "r_data/r_translate.h"
|
||||
|
@ -34,6 +35,7 @@
|
|||
|
||||
class FVertexBuffer;
|
||||
class FShader;
|
||||
struct GLSectorPlane;
|
||||
extern TArray<VSMatrix> gl_MatrixStack;
|
||||
|
||||
EXTERN_CVAR(Bool, gl_direct_state_change)
|
||||
|
@ -82,7 +84,6 @@ class FRenderState
|
|||
bool mBrightmapEnabled;
|
||||
bool mColorMask[4];
|
||||
bool currentColorMask[4];
|
||||
int mLightIndex;
|
||||
int mSpecialEffect;
|
||||
int mTextureMode;
|
||||
int mDesaturation;
|
||||
|
@ -327,11 +328,6 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void SetLightIndex(int n)
|
||||
{
|
||||
mLightIndex = n;
|
||||
}
|
||||
|
||||
void EnableBrightmap(bool on)
|
||||
{
|
||||
mBrightmapEnabled = on;
|
||||
|
@ -536,6 +532,15 @@ public:
|
|||
// Backwards compatibility crap follows
|
||||
void ApplyFixedFunction();
|
||||
void DrawColormapOverlay();
|
||||
|
||||
void SetPlaneTextureRotation(GLSectorPlane *plane, FMaterial *texture)
|
||||
{
|
||||
if (hw_SetPlaneTextureRotation(plane, texture, mTextureMatrix))
|
||||
{
|
||||
EnableTextureMatrix(true);
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
extern FRenderState gl_RenderState;
|
||||
|
|
|
@ -29,18 +29,12 @@
|
|||
#include "p_local.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "g_levellocals.h"
|
||||
#include "r_sky.h"
|
||||
#include "p_effect.h"
|
||||
#include "po_man.h"
|
||||
#include "doomdata.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/scene/gl_portal.h"
|
||||
#include "gl/scene/gl_wall.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
|
||||
EXTERN_CVAR(Bool, gl_render_segs)
|
||||
|
||||
|
@ -91,7 +85,7 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
|
|||
if (portalclip)
|
||||
{
|
||||
int clipres = GLRenderer->mClipPortal->ClipSeg(seg);
|
||||
if (clipres == GLPortal::PClip_InFront) return;
|
||||
if (clipres == PClip_InFront) return;
|
||||
}
|
||||
|
||||
angle_t startAngle = clipper.GetClipAngle(seg->v2);
|
||||
|
@ -146,11 +140,11 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
|
|||
else
|
||||
{
|
||||
// clipping checks are only needed when the backsector is not the same as the front sector
|
||||
CheckViewArea(seg->v1, seg->v2, seg->frontsector, seg->backsector);
|
||||
in_area = hw_CheckViewArea(in_area, seg->v1, seg->v2, seg->frontsector, seg->backsector);
|
||||
|
||||
backsector = gl_FakeFlat(seg->backsector, &bs, in_area, true);
|
||||
backsector = hw_FakeFlat(seg->backsector, &bs, in_area, true);
|
||||
|
||||
if (gl_CheckClip(seg->sidedef, currentsector, backsector))
|
||||
if (hw_CheckClip(seg->sidedef, currentsector, backsector))
|
||||
{
|
||||
clipper.SafeAddClipRange(startAngle, endAngle);
|
||||
}
|
||||
|
@ -172,9 +166,9 @@ void GLSceneDrawer::AddLine (seg_t *seg, bool portalclip)
|
|||
{
|
||||
SetupWall.Clock();
|
||||
|
||||
GLWall wall(this);
|
||||
GLWall wall;
|
||||
wall.sub = currentsubsector;
|
||||
wall.Process(seg, currentsector, backsector);
|
||||
wall.Process(gl_drawinfo, seg, currentsector, backsector);
|
||||
rendered_lines++;
|
||||
|
||||
SetupWall.Unclock();
|
||||
|
@ -369,9 +363,12 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
|
|||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
GLSprite sprite(this);
|
||||
sprite.Process(thing, sector, false);
|
||||
// If this thing is in a map section that's not in view it can't possibly be visible
|
||||
if (CurrentMapSections[thing->subsector->mapsection])
|
||||
{
|
||||
GLSprite sprite;
|
||||
sprite.Process(gl_drawinfo, thing, sector, in_area, false);
|
||||
}
|
||||
}
|
||||
|
||||
for (msecnode_t *node = sec->sectorportal_thinglist; node; node = node->m_snext)
|
||||
|
@ -388,8 +385,8 @@ void GLSceneDrawer::RenderThings(subsector_t * sub, sector_t * sector)
|
|||
}
|
||||
}
|
||||
|
||||
GLSprite sprite(this);
|
||||
sprite.Process(thing, sector, true);
|
||||
GLSprite sprite;
|
||||
sprite.Process(gl_drawinfo, thing, sector, gl_drawinfo->mDrawer->in_area, true);
|
||||
}
|
||||
SetupSprite.Unclock();
|
||||
}
|
||||
|
@ -434,12 +431,12 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
|
|||
}
|
||||
if (clipper.IsBlocked()) return; // if we are inside a stacked sector portal which hasn't unclipped anything yet.
|
||||
|
||||
fakesector=gl_FakeFlat(sector, &fake, in_area, false);
|
||||
fakesector=hw_FakeFlat(sector, &fake, in_area, false);
|
||||
|
||||
if (GLRenderer->mClipPortal)
|
||||
{
|
||||
int clipres = GLRenderer->mClipPortal->ClipSubsector(sub);
|
||||
if (clipres == GLPortal::PClip_InFront)
|
||||
if (clipres == PClip_InFront)
|
||||
{
|
||||
line_t *line = GLRenderer->mClipPortal->ClipLine();
|
||||
// The subsector is out of range, but we still have to check lines that lie directly on the boundary and may expose their upper or lower parts.
|
||||
|
@ -461,8 +458,14 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
|
|||
|
||||
for (i = ParticlesInSubsec[sub->Index()]; i != NO_PARTICLE; i = Particles[i].snext)
|
||||
{
|
||||
GLSprite sprite(this);
|
||||
sprite.ProcessParticle(&Particles[i], fakesector);
|
||||
if (GLRenderer->mClipPortal)
|
||||
{
|
||||
int clipres = GLRenderer->mClipPortal->ClipPoint(Particles[i].Pos);
|
||||
if (clipres == PClip_InFront) continue;
|
||||
}
|
||||
|
||||
GLSprite sprite;
|
||||
sprite.ProcessParticle(gl_drawinfo, &Particles[i], fakesector);
|
||||
}
|
||||
SetupSprite.Unclock();
|
||||
}
|
||||
|
@ -501,7 +504,7 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
|
|||
sector = sub->render_sector;
|
||||
// the planes of this subsector are faked to belong to another sector
|
||||
// This means we need the heightsec parts and light info of the render sector, not the actual one.
|
||||
fakesector = gl_FakeFlat(sector, &fake, in_area, false);
|
||||
fakesector = hw_FakeFlat(sector, &fake, in_area, false);
|
||||
}
|
||||
|
||||
uint8_t &srf = gl_drawinfo->sectorrenderflags[sub->render_sector->sectornum];
|
||||
|
@ -510,8 +513,8 @@ void GLSceneDrawer::DoSubsector(subsector_t * sub)
|
|||
srf |= SSRF_PROCESSED;
|
||||
|
||||
SetupFlat.Clock();
|
||||
GLFlat flat(this);
|
||||
flat.ProcessSector(fakesector);
|
||||
GLFlat flat;
|
||||
flat.ProcessSector(gl_drawinfo, fakesector);
|
||||
SetupFlat.Unclock();
|
||||
}
|
||||
// mark subsector as processed - but mark for rendering only if it has an actual area.
|
||||
|
|
|
@ -1,398 +0,0 @@
|
|||
//
|
||||
//---------------------------------------------------------------------------
|
||||
//
|
||||
// Copyright(C) 2003-2016 Christoph Oelckers
|
||||
// All rights reserved.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Lesser General Public License as published by
|
||||
// the Free Software Foundation, either version 3 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 Lesser General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Lesser General Public License
|
||||
// along with this program. If not, see http://www.gnu.org/licenses/
|
||||
//
|
||||
//--------------------------------------------------------------------------
|
||||
//
|
||||
/*
|
||||
** gl_decal.cpp
|
||||
** OpenGL decal rendering code
|
||||
**
|
||||
*/
|
||||
|
||||
#include "doomdata.h"
|
||||
#include "gl/system/gl_system.h"
|
||||
#include "a_sharedglobal.h"
|
||||
#include "r_utility.h"
|
||||
#include "g_levellocals.h"
|
||||
|
||||
#include "gl/system/gl_cvars.h"
|
||||
#include "gl/data/gl_vertexbuffer.h"
|
||||
#include "gl/renderer/gl_renderer.h"
|
||||
#include "gl/renderer/gl_lightdata.h"
|
||||
#include "gl/renderer/gl_renderstate.h"
|
||||
#include "gl/scene/gl_drawinfo.h"
|
||||
#include "gl/scene/gl_scenedrawer.h"
|
||||
#include "gl/shaders/gl_shader.h"
|
||||
#include "gl/textures/gl_material.h"
|
||||
#include "gl/utility/gl_clock.h"
|
||||
#include "gl/renderer/gl_quaddrawer.h"
|
||||
|
||||
struct DecalVertex
|
||||
{
|
||||
float x,y,z;
|
||||
float u,v;
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void GLWall::DrawDecal(DBaseDecal *decal)
|
||||
{
|
||||
line_t * line=seg->linedef;
|
||||
side_t * side=seg->sidedef;
|
||||
int i;
|
||||
float zpos;
|
||||
int light;
|
||||
int rel;
|
||||
float a;
|
||||
bool flipx, flipy;
|
||||
DecalVertex dv[4];
|
||||
FTextureID decalTile;
|
||||
|
||||
|
||||
if (decal->RenderFlags & RF_INVISIBLE) return;
|
||||
if (type==RENDERWALL_FFBLOCK && gltexture->isMasked()) return; // No decals on 3D floors with transparent textures.
|
||||
|
||||
//if (decal->sprite != 0xffff)
|
||||
{
|
||||
decalTile = decal->PicNum;
|
||||
flipx = !!(decal->RenderFlags & RF_XFLIP);
|
||||
flipy = !!(decal->RenderFlags & RF_YFLIP);
|
||||
}
|
||||
/*
|
||||
else
|
||||
{
|
||||
decalTile = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].lump[0];
|
||||
flipx = SpriteFrames[sprites[decal->sprite].spriteframes + decal->frame].flip & 1;
|
||||
}
|
||||
*/
|
||||
|
||||
FTexture *texture = TexMan[decalTile];
|
||||
if (texture == NULL) return;
|
||||
|
||||
FMaterial *tex;
|
||||
|
||||
|
||||
tex = FMaterial::ValidateTexture(texture, true);
|
||||
|
||||
|
||||
// the sectors are only used for their texture origin coordinates
|
||||
// so we don't need the fake sectors for deep water etc.
|
||||
// As this is a completely split wall fragment no further splits are
|
||||
// necessary for the decal.
|
||||
sector_t *frontsector;
|
||||
|
||||
// for 3d-floor segments use the model sector as reference
|
||||
if ((decal->RenderFlags&RF_CLIPMASK)==RF_CLIPMID) frontsector=decal->Sector;
|
||||
else frontsector=seg->frontsector;
|
||||
|
||||
switch (decal->RenderFlags & RF_RELMASK)
|
||||
{
|
||||
default:
|
||||
// No valid decal can have this type. If one is encountered anyway
|
||||
// it is in some way invalid so skip it.
|
||||
return;
|
||||
//zpos = decal->z;
|
||||
//break;
|
||||
|
||||
case RF_RELUPPER:
|
||||
if (type!=RENDERWALL_TOP) return;
|
||||
if (line->flags & ML_DONTPEGTOP)
|
||||
{
|
||||
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
|
||||
}
|
||||
else
|
||||
{
|
||||
zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::ceiling);
|
||||
}
|
||||
break;
|
||||
case RF_RELLOWER:
|
||||
if (type!=RENDERWALL_BOTTOM) return;
|
||||
if (line->flags & ML_DONTPEGBOTTOM)
|
||||
{
|
||||
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
|
||||
}
|
||||
else
|
||||
{
|
||||
zpos = decal->Z + seg->backsector->GetPlaneTexZ(sector_t::floor);
|
||||
}
|
||||
break;
|
||||
case RF_RELMID:
|
||||
if (type==RENDERWALL_TOP || type==RENDERWALL_BOTTOM) return;
|
||||
if (line->flags & ML_DONTPEGBOTTOM)
|
||||
{
|
||||
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::floor);
|
||||
}
|
||||
else
|
||||
{
|
||||
zpos = decal->Z + frontsector->GetPlaneTexZ(sector_t::ceiling);
|
||||
}
|
||||
}
|
||||
|
||||
if (decal->RenderFlags & RF_FULLBRIGHT)
|
||||
{
|
||||
light = 255;
|
||||
rel = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
light = lightlevel;
|
||||
rel = rellight + getExtraLight();
|
||||
}
|
||||
|
||||
FColormap p = Colormap;
|
||||
|
||||
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING)
|
||||
{
|
||||
p.Decolorize();
|
||||
}
|
||||
|
||||
|
||||
|
||||
a = decal->Alpha;
|
||||
|
||||
// now clip the decal to the actual polygon
|
||||
float decalwidth = tex->TextureWidth() * decal->ScaleX;
|
||||
float decalheight= tex->TextureHeight() * decal->ScaleY;
|
||||
float decallefto = tex->GetLeftOffset() * decal->ScaleX;
|
||||
float decaltopo = tex->GetTopOffset() * decal->ScaleY;
|
||||
|
||||
|
||||
float leftedge = glseg.fracleft * side->TexelLength;
|
||||
float linelength = glseg.fracright * side->TexelLength - leftedge;
|
||||
|
||||
// texel index of the decal's left edge
|
||||
float decalpixpos = (float)side->TexelLength * decal->LeftDistance - (flipx? decalwidth-decallefto : decallefto) - leftedge;
|
||||
|
||||
float left,right;
|
||||
float lefttex,righttex;
|
||||
|
||||
// decal is off the left edge
|
||||
if (decalpixpos < 0)
|
||||
{
|
||||
left = 0;
|
||||
lefttex = -decalpixpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
left = decalpixpos;
|
||||
lefttex = 0;
|
||||
}
|
||||
|
||||
// decal is off the right edge
|
||||
if (decalpixpos + decalwidth > linelength)
|
||||
{
|
||||
right = linelength;
|
||||
righttex = right - decalpixpos;
|
||||
}
|
||||
else
|
||||
{
|
||||
right = decalpixpos + decalwidth;
|
||||
righttex = decalwidth;
|
||||
}
|
||||
if (right<=left) return; // nothing to draw
|
||||
|
||||
// one texture unit on the wall as vector
|
||||
float vx=(glseg.x2-glseg.x1)/linelength;
|
||||
float vy=(glseg.y2-glseg.y1)/linelength;
|
||||
|
||||
dv[1].x=dv[0].x=glseg.x1+vx*left;
|
||||
dv[1].y=dv[0].y=glseg.y1+vy*left;
|
||||
|
||||
dv[3].x=dv[2].x=glseg.x1+vx*right;
|
||||
dv[3].y=dv[2].y=glseg.y1+vy*right;
|
||||
|
||||
zpos+= (flipy? decalheight-decaltopo : decaltopo);
|
||||
|
||||
dv[1].z=dv[2].z = zpos;
|
||||
dv[0].z=dv[3].z = dv[1].z - decalheight;
|
||||
dv[1].v=dv[2].v = tex->GetVT();
|
||||
|
||||
dv[1].u=dv[0].u = tex->GetU(lefttex / decal->ScaleX);
|
||||
dv[3].u=dv[2].u = tex->GetU(righttex / decal->ScaleX);
|
||||
dv[0].v=dv[3].v = tex->GetVB();
|
||||
|
||||
|
||||
// now clip to the top plane
|
||||
float vzt=(ztop[1]-ztop[0])/linelength;
|
||||
float topleft=this->ztop[0]+vzt*left;
|
||||
float topright=this->ztop[0]+vzt*right;
|
||||
|
||||
// completely below the wall
|
||||
if (topleft<dv[0].z && topright<dv[3].z)
|
||||
return;
|
||||
|
||||
if (topleft<dv[1].z || topright<dv[2].z)
|
||||
{
|
||||
// decal has to be clipped at the top
|
||||
// let texture clamping handle all extreme cases
|
||||
dv[1].v=(dv[1].z-topleft)/(dv[1].z-dv[0].z)*dv[0].v;
|
||||
dv[2].v=(dv[2].z-topright)/(dv[2].z-dv[3].z)*dv[3].v;
|
||||
dv[1].z=topleft;
|
||||
dv[2].z=topright;
|
||||
}
|
||||
|
||||
// now clip to the bottom plane
|
||||
float vzb=(zbottom[1]-zbottom[0])/linelength;
|
||||
float bottomleft=this->zbottom[0]+vzb*left;
|
||||
float bottomright=this->zbottom[0]+vzb*right;
|
||||
|
||||
// completely above the wall
|
||||
if (bottomleft>dv[1].z && bottomright>dv[2].z)
|
||||
return;
|
||||
|
||||
if (bottomleft>dv[0].z || bottomright>dv[3].z)
|
||||
{
|
||||
// decal has to be clipped at the bottom
|
||||
// let texture clamping handle all extreme cases
|
||||
dv[0].v=(dv[1].z-bottomleft)/(dv[1].z-dv[0].z)*(dv[0].v-dv[1].v) + dv[1].v;
|
||||
dv[3].v=(dv[2].z-bottomright)/(dv[2].z-dv[3].z)*(dv[3].v-dv[2].v) + dv[2].v;
|
||||
dv[0].z=bottomleft;
|
||||
dv[3].z=bottomright;
|
||||
}
|
||||
|
||||
|
||||
if (flipx)
|
||||
{
|
||||
float ur = tex->GetUR();
|
||||
for(i=0;i<4;i++) dv[i].u=ur-dv[i].u;
|
||||
}
|
||||
if (flipy)
|
||||
{
|
||||
float vb = tex->GetVB();
|
||||
for(i=0;i<4;i++) dv[i].v=vb-dv[i].v;
|
||||
}
|
||||
|
||||
// calculate dynamic light effect.
|
||||
if (gl_lights && GLRenderer->mLightCount && !mDrawer->FixedColormap && gl_light_sprites)
|
||||
{
|
||||
// Note: This should be replaced with proper shader based lighting.
|
||||
double x, y;
|
||||
decal->GetXY(seg->sidedef, x, y);
|
||||
gl_SetDynSpriteLight(nullptr, x, y, zpos - decalheight * 0.5f, sub);
|
||||
}
|
||||
|
||||
// alpha color only has an effect when using an alpha texture.
|
||||
if (decal->RenderStyle.Flags & STYLEF_RedIsAlpha)
|
||||
{
|
||||
gl_RenderState.SetObjectColor(decal->AlphaColor|0xff000000);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
gl_SetRenderStyle(decal->RenderStyle, false, false);
|
||||
gl_RenderState.SetMaterial(tex, CLAMP_XY, decal->Translation, 0, !!(decal->RenderStyle.Flags & STYLEF_RedIsAlpha));
|
||||
|
||||
|
||||
// If srcalpha is one it looks better with a higher alpha threshold
|
||||
if (decal->RenderStyle.SrcAlpha == STYLEALPHA_One) gl_RenderState.AlphaFunc(GL_GEQUAL, gl_mask_sprite_threshold);
|
||||
else gl_RenderState.AlphaFunc(GL_GREATER, 0.f);
|
||||
|
||||
|
||||
mDrawer->SetColor(light, rel, p, a);
|
||||
// for additively drawn decals we must temporarily set the fog color to black.
|
||||
PalEntry fc = gl_RenderState.GetFogColor();
|
||||
if (decal->RenderStyle.BlendOp == STYLEOP_Add && decal->RenderStyle.DestAlpha == STYLEALPHA_One)
|
||||
{
|
||||
gl_RenderState.SetFog(0,-1);
|
||||
}
|
||||
|
||||
gl_RenderState.SetNormal(glseg.Normal());
|
||||
|
||||
FQuadDrawer qd;
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
qd.Set(i, dv[i].x, dv[i].z, dv[i].y, dv[i].u, dv[i].v);
|
||||
}
|
||||
|
||||
if (lightlist == NULL)
|
||||
{
|
||||
gl_RenderState.Apply();
|
||||
qd.Render(GL_TRIANGLE_FAN);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned k = 0; k < lightlist->Size(); k++)
|
||||
{
|
||||
secplane_t &lowplane = k == (*lightlist).Size() - 1 ? bottomplane : (*lightlist)[k + 1].plane;
|
||||
|
||||
float low1 = lowplane.ZatPoint(dv[1].x, dv[1].y);
|
||||
float low2 = lowplane.ZatPoint(dv[2].x, dv[2].y);
|
||||
|
||||
if (low1 < dv[1].z || low2 < dv[2].z)
|
||||
{
|
||||
int thisll = (*lightlist)[k].caster != NULL ? gl_ClampLight(*(*lightlist)[k].p_lightlevel) : lightlevel;
|
||||
FColormap thiscm;
|
||||
thiscm.FadeColor = Colormap.FadeColor;
|
||||
thiscm.CopyFrom3DLight(&(*lightlist)[k]);
|
||||
mDrawer->SetColor(thisll, rel, thiscm, a);
|
||||
if (level.flags3 & LEVEL3_NOCOLOREDSPRITELIGHTING) thiscm.Decolorize();
|
||||
mDrawer->SetFog(thisll, rel, &thiscm, RenderStyle == STYLE_Add);
|
||||
gl_RenderState.SetSplitPlanes((*lightlist)[k].plane, lowplane);
|
||||
|
||||
gl_RenderState.Apply();
|
||||
qd.Render(GL_TRIANGLE_FAN);
|
||||
}
|
||||
if (low1 <= dv[0].z && low2 <= dv[3].z) break;
|
||||
}
|
||||
}
|
||||
|
||||
rendered_decals++;
|
||||
gl_RenderState.SetTextureMode(TM_MODULATE);
|
||||
gl_RenderState.SetObjectColor(0xffffffff);
|
||||
gl_RenderState.SetFog(fc,-1);
|
||||
gl_RenderState.SetDynLight(0,0,0);
|
||||
}
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
//
|
||||
//
|
||||
//==========================================================================
|
||||
void GLWall::DoDrawDecals()
|
||||
{
|
||||
if (seg->sidedef && seg->sidedef->AttachedDecals)
|
||||
{
|
||||
if (lightlist != NULL)
|
||||
{
|
||||
gl_RenderState.EnableSplit(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
mDrawer->SetFog(lightlevel, rellight + getExtraLight(), &Colormap, false);
|
||||
}
|
||||
|
||||
DBaseDecal *decal = seg->sidedef->AttachedDecals;
|
||||
while (decal)
|
||||
{
|
||||
DrawDecal(decal);
|
||||
decal = decal->WallNext;
|
||||
}
|
||||
|
||||
if (lightlist != NULL)
|
||||
{
|
||||
gl_RenderState.EnableSplit(false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load diff
|
@ -1,14 +1,13 @@
|
|||
#ifndef __GL_DRAWINFO_H
|
||||
#define __GL_DRAWINFO_H
|
||||
|
||||
#include "gl/scene/gl_wall.h"
|
||||
#include "hwrenderer/scene/hw_drawlist.h"
|
||||
|
||||
enum GLDrawItemType
|
||||
{
|
||||
GLDIT_WALL,
|
||||
GLDIT_FLAT,
|
||||
GLDIT_SPRITE,
|
||||
};
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable:4244)
|
||||
#endif
|
||||
|
||||
class GLSceneDrawer;
|
||||
|
||||
enum DrawListType
|
||||
{
|
||||
|
@ -18,10 +17,10 @@ enum DrawListType
|
|||
GLDL_MASKEDFLATS,
|
||||
GLDL_MASKEDWALLSOFS,
|
||||
GLDL_MODELS,
|
||||
|
||||
|
||||
GLDL_TRANSLUCENT,
|
||||
GLDL_TRANSLUCENTBORDER,
|
||||
|
||||
|
||||
GLDL_TYPES,
|
||||
};
|
||||
|
||||
|
@ -31,16 +30,16 @@ enum DLDrawListType
|
|||
// These are organized so that the various multipass rendering modes have to be set as few times as possible
|
||||
GLLDL_WALLS_PLAIN, // dynamic lights on normal walls
|
||||
GLLDL_WALLS_MASKED, // dynamic lights on masked midtextures
|
||||
|
||||
|
||||
GLLDL_FLATS_PLAIN, // dynamic lights on normal flats
|
||||
GLLDL_FLATS_MASKED, // dynamic lights on masked flats
|
||||
|
||||
|
||||
GLLDL_WALLS_FOG, // lights on fogged walls
|
||||
GLLDL_WALLS_FOGMASKED, // lights on fogged masked midtextures
|
||||
|
||||
|
||||
GLLDL_FLATS_FOG, // lights on fogged walls
|
||||
GLLDL_FLATS_FOGMASKED, // lights on fogged masked midtextures
|
||||
|
||||
|
||||
GLLDL_TYPES,
|
||||
};
|
||||
|
||||
|
@ -52,7 +51,7 @@ enum Drawpasses
|
|||
GLPASS_PLAIN, // Main pass without dynamic lights
|
||||
GLPASS_DECALS, // Draws a decal
|
||||
GLPASS_TRANSLUCENT, // Draws translucent objects
|
||||
|
||||
|
||||
// these are only used with texture based dynamic lights
|
||||
GLPASS_BASE, // untextured base for dynamic lights
|
||||
GLPASS_BASE_MASKED, // same but with active texture
|
||||
|
@ -60,226 +59,86 @@ enum Drawpasses
|
|||
GLPASS_TEXONLY, // finishing texture pass
|
||||
GLPASS_LIGHTTEX_ADDITIVE, // lighttexture pass (additive)
|
||||
GLPASS_LIGHTTEX_FOGGY, // lighttexture pass on foggy surfaces (forces all lights to be additive)
|
||||
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// Intermediate struct to link one draw item into a draw list
|
||||
//
|
||||
// unfortunately this struct must not contain pointers because
|
||||
// the arrays may be reallocated!
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
struct GLDrawItem
|
||||
{
|
||||
GLDrawItemType rendertype;
|
||||
int index;
|
||||
|
||||
GLDrawItem(GLDrawItemType _rendertype,int _index) : rendertype(_rendertype),index(_index) {}
|
||||
};
|
||||
|
||||
struct SortNode
|
||||
{
|
||||
int itemindex;
|
||||
SortNode * parent;
|
||||
SortNode * next; // unsorted successor
|
||||
SortNode * left; // left side of this node
|
||||
SortNode * equal; // equal to this node
|
||||
SortNode * right; // right side of this node
|
||||
|
||||
|
||||
void UnlinkFromChain();
|
||||
void Link(SortNode * hook);
|
||||
void AddToEqual(SortNode * newnode);
|
||||
void AddToLeft (SortNode * newnode);
|
||||
void AddToRight(SortNode * newnode);
|
||||
};
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// One draw list. This contains all info for one type of rendering data
|
||||
//
|
||||
//==========================================================================
|
||||
|
||||
struct GLDrawList
|
||||
{
|
||||
//private:
|
||||
TArray<GLWall> walls;
|
||||
TArray<GLFlat> flats;
|
||||
TArray<GLSprite> sprites;
|
||||
TArray<GLDrawItem> drawitems;
|
||||
int SortNodeStart;
|
||||
SortNode * sorted;
|
||||
|
||||
public:
|
||||
GLDrawList()
|
||||
{
|
||||
next=NULL;
|
||||
SortNodeStart=-1;
|
||||
sorted=NULL;
|
||||
}
|
||||
|
||||
~GLDrawList()
|
||||
{
|
||||
Reset();
|
||||
}
|
||||
|
||||
unsigned int Size()
|
||||
{
|
||||
return drawitems.Size();
|
||||
}
|
||||
|
||||
void AddWall(GLWall * wall);
|
||||
void AddFlat(GLFlat * flat);
|
||||
void AddSprite(GLSprite * sprite);
|
||||
void Reset();
|
||||
void SortWalls();
|
||||
void SortFlats();
|
||||
|
||||
|
||||
void MakeSortList();
|
||||
SortNode * FindSortPlane(SortNode * head);
|
||||
SortNode * FindSortWall(SortNode * head);
|
||||
void SortPlaneIntoPlane(SortNode * head,SortNode * sort);
|
||||
void SortWallIntoPlane(SortNode * head,SortNode * sort);
|
||||
void SortSpriteIntoPlane(SortNode * head,SortNode * sort);
|
||||
void SortWallIntoWall(SortNode * head,SortNode * sort);
|
||||
void SortSpriteIntoWall(SortNode * head,SortNode * sort);
|
||||
int CompareSprites(SortNode * a,SortNode * b);
|
||||
SortNode * SortSpriteList(SortNode * head);
|
||||
SortNode * DoSort(SortNode * head);
|
||||
|
||||
void DoDraw(int pass, int index, bool trans);
|
||||
void DoDrawSorted(SortNode * node);
|
||||
void DrawSorted();
|
||||
void Draw(int pass, bool trans = false);
|
||||
void DrawWalls(int pass);
|
||||
void DrawFlats(int pass);
|
||||
void DrawDecals();
|
||||
|
||||
GLDrawList * next;
|
||||
} ;
|
||||
|
||||
|
||||
//==========================================================================
|
||||
//
|
||||
// these are used to link faked planes due to missing textures to a sector
|
||||
//
|
||||
//==========================================================================
|
||||
struct gl_subsectorrendernode
|
||||
{
|
||||
gl_subsectorrendernode * next;
|
||||
subsector_t * sub;
|
||||
};
|
||||
|
||||
|
||||
struct FDrawInfo
|
||||
struct FDrawInfo : public HWDrawInfo
|
||||
{
|
||||
struct wallseg
|
||||
{
|
||||
float x1, y1, z1, x2, y2, z2;
|
||||
};
|
||||
|
||||
bool temporary;
|
||||
|
||||
|
||||
|
||||
struct MissingTextureInfo
|
||||
{
|
||||
seg_t * seg;
|
||||
subsector_t * sub;
|
||||
float Planez;
|
||||
float Planezfront;
|
||||
};
|
||||
|
||||
struct MissingSegInfo
|
||||
{
|
||||
seg_t * seg;
|
||||
int MTI_Index; // tells us which MissingTextureInfo represents this seg.
|
||||
};
|
||||
|
||||
struct SubsectorHackInfo
|
||||
{
|
||||
subsector_t * sub;
|
||||
uint8_t flags;
|
||||
};
|
||||
|
||||
GLSceneDrawer *mDrawer;
|
||||
|
||||
TArray<uint8_t> sectorrenderflags;
|
||||
TArray<uint8_t> ss_renderflags;
|
||||
TArray<uint8_t> no_renderflags;
|
||||
|
||||
TArray<MissingTextureInfo> MissingUpperTextures;
|
||||
TArray<MissingTextureInfo> MissingLowerTextures;
|
||||
|
||||
TArray<MissingSegInfo> MissingUpperSegs;
|
||||
TArray<MissingSegInfo> MissingLowerSegs;
|
||||
|
||||
TArray<SubsectorHackInfo> SubsectorHacks;
|
||||
|
||||
TArray<gl_subsectorrendernode*> otherfloorplanes;
|
||||
TArray<gl_subsectorrendernode*> otherceilingplanes;
|
||||
|
||||
TArray<sector_t *> CeilingStacks;
|
||||
TArray<sector_t *> FloorStacks;
|
||||
|
||||
TArray<subsector_t *> HandledSubsectors;
|
||||
|
||||
|
||||
FDrawInfo * next;
|
||||
GLDrawList drawlists[GLDL_TYPES];
|
||||
GLDrawList *dldrawlists = NULL; // only gets allocated when needed.
|
||||
|
||||
HWDrawList drawlists[GLDL_TYPES];
|
||||
TArray<GLDecal *> decals[2]; // the second slot is for mirrors which get rendered in a separate pass.
|
||||
HWDrawList *dldrawlists = NULL; // only gets allocated when needed.
|
||||
|
||||
FDrawInfo();
|
||||
~FDrawInfo();
|
||||
void ClearBuffers();
|
||||
|
||||
void AddWall(GLWall *wall) override;
|
||||
void AddMirrorSurface(GLWall *w) override;
|
||||
GLDecal *AddDecal(bool onmirror) override;
|
||||
void AddPortal(GLWall *w, int portaltype) override;
|
||||
void AddFlat(GLFlat *flat, bool fog) override;
|
||||
void AddSprite(GLSprite *sprite, bool translucent) override;
|
||||
|
||||
void AddWall(GLWall *wall);
|
||||
bool PutWallCompat(GLWall *wall, int passflag); // Legacy GL only.
|
||||
std::pair<FFlatVertex *, unsigned int> AllocVertices(unsigned int count) override;
|
||||
|
||||
bool DoOneSectorUpper(subsector_t * subsec, float planez);
|
||||
bool DoOneSectorLower(subsector_t * subsec, float planez);
|
||||
bool DoFakeBridge(subsector_t * subsec, float planez);
|
||||
bool DoFakeCeilingBridge(subsector_t * subsec, float planez);
|
||||
// Legacy GL only.
|
||||
bool PutWallCompat(GLWall *wall, int passflag);
|
||||
bool PutFlatCompat(GLFlat *flat, bool fog);
|
||||
void RenderFogBoundaryCompat(GLWall *wall);
|
||||
void RenderLightsCompat(GLWall *wall, int pass);
|
||||
void DrawSubsectorLights(GLFlat *flat, subsector_t * sub, int pass);
|
||||
void DrawLightsCompat(GLFlat *flat, int pass);
|
||||
|
||||
bool CheckAnchorFloor(subsector_t * sub);
|
||||
bool CollectSubsectorsFloor(subsector_t * sub, sector_t * anchor);
|
||||
bool CheckAnchorCeiling(subsector_t * sub);
|
||||
bool CollectSubsectorsCeiling(subsector_t * sub, sector_t * anchor);
|
||||
void CollectSectorStacksCeiling(subsector_t * sub, sector_t * anchor);
|
||||
void CollectSectorStacksFloor(subsector_t * sub, sector_t * anchor);
|
||||
|
||||
void AddUpperMissingTexture(side_t * side, subsector_t *sub, float backheight);
|
||||
void AddLowerMissingTexture(side_t * side, subsector_t *sub, float backheight);
|
||||
void HandleMissingTextures();
|
||||
void DrawUnhandledMissingTextures();
|
||||
void AddHackedSubsector(subsector_t * sub);
|
||||
void HandleHackedSubsectors();
|
||||
void AddFloorStack(sector_t * sec);
|
||||
void AddCeilingStack(sector_t * sec);
|
||||
void ProcessSectorStacks();
|
||||
|
||||
void AddOtherFloorPlane(int sector, gl_subsectorrendernode * node);
|
||||
void AddOtherCeilingPlane(int sector, gl_subsectorrendernode * node);
|
||||
void DrawDecal(GLDecal *gldecal);
|
||||
void DrawDecals();
|
||||
void DrawDecalsForMirror(GLWall *wall);
|
||||
|
||||
void StartScene();
|
||||
void SetupFloodStencil(wallseg * ws);
|
||||
void ClearFloodStencil(wallseg * ws);
|
||||
void DrawFloodedPlane(wallseg * ws, float planez, sector_t * sec, bool ceiling);
|
||||
void FloodUpperGap(seg_t * seg);
|
||||
void FloodLowerGap(seg_t * seg);
|
||||
void FloodUpperGap(seg_t * seg) override;
|
||||
void FloodLowerGap(seg_t * seg) override;
|
||||
|
||||
// Wall drawer
|
||||
void RenderWall(GLWall *wall, int textured);
|
||||
void RenderFogBoundary(GLWall *wall);
|
||||
void RenderMirrorSurface(GLWall *wall);
|
||||
void RenderTranslucentWall(GLWall *wall);
|
||||
void RenderTexturedWall(GLWall *wall, int rflags);
|
||||
void DrawWall(GLWall *wall, int pass) override;
|
||||
|
||||
// Flat drawer
|
||||
void DrawFlat(GLFlat *flat, int pass, bool trans) override; // trans only has meaning for GLPASS_LIGHTSONLY
|
||||
void DrawSkyboxSector(GLFlat *flat, int pass, bool processlights);
|
||||
void DrawSubsectors(GLFlat *flat, int pass, bool processlights, bool istrans);
|
||||
void ProcessLights(GLFlat *flat, bool istrans);
|
||||
void DrawSubsector(GLFlat *flat, subsector_t * sub);
|
||||
void SetupSubsectorLights(GLFlat *flat, int pass, subsector_t * sub, int *dli);
|
||||
|
||||
// Sprite drawer
|
||||
void DrawSprite(GLSprite *sprite, int pass);
|
||||
|
||||
void DoDrawSorted(HWDrawList *dl, SortNode * head);
|
||||
void DrawSorted(int listindex);
|
||||
|
||||
// These two may be moved to the API independent part of the renderer later.
|
||||
void ProcessLowerMinisegs(TArray<seg_t *> &lowersegs) override;
|
||||
void AddSubsectorToPortal(FSectorPortalGroup *portal, subsector_t *sub) override;
|
||||
int ClipPoint(const DVector3 &pos) override;
|
||||
|
||||
static void StartDrawInfo(GLSceneDrawer *drawer);
|
||||
static void EndDrawInfo();
|
||||
|
||||
|
||||
gl_subsectorrendernode * GetOtherFloorPlanes(unsigned int sector)
|
||||
{
|
||||
if (sector<otherfloorplanes.Size()) return otherfloorplanes[sector];
|
||||
else return NULL;
|
||||
}
|
||||
|
||||
|
||||
gl_subsectorrendernode * GetOtherCeilingPlanes(unsigned int sector)
|
||||
{
|
||||
if (sector<otherceilingplanes.Size()) return otherceilingplanes[sector];
|
||||
|
@ -290,9 +149,9 @@ struct FDrawInfo
|
|||
class FDrawInfoList
|
||||
{
|
||||
TDeletingArray<FDrawInfo *> mList;
|
||||
|
||||
|
||||
public:
|
||||
|
||||
|
||||
FDrawInfo *GetNew();
|
||||
void Release(FDrawInfo *);
|
||||
};
|
||||
|
@ -300,7 +159,6 @@ public:
|
|||
|
||||
extern FDrawInfo * gl_drawinfo;
|
||||
|
||||
void gl_SetPlaneTextureRotation(const GLSectorPlane * secplane, FMaterial * gltexture);
|
||||
void gl_SetRenderStyle(FRenderStyle style, bool drawopaque, bool allowcolorblending);
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue