2019-03-18 01:27:50 +00:00
// SONIC ROBO BLAST 2
2014-03-15 16:59:03 +00:00
//-----------------------------------------------------------------------------
2019-03-18 01:27:50 +00:00
// Copyright (C) 1993-1996 by id Software, Inc.
2014-03-15 16:59:03 +00:00
// Copyright (C) 1998-2000 by DooM Legacy Team.
2019-03-18 01:27:50 +00:00
// Copyright (C) 1999-2019 by Sonic Team Junior.
2014-03-15 16:59:03 +00:00
//
2019-03-18 01:27:50 +00:00
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
2014-03-15 16:59:03 +00:00
//-----------------------------------------------------------------------------
/// \file
/// \brief MD2 Handling
/// Inspired from md2.c by Mete Ciragan (mete@swissquake.ch)
# ifdef __GNUC__
# include <unistd.h>
# endif
# include <stdio.h>
# include <stdlib.h>
# include <string.h>
# include <math.h>
# include "../doomdef.h"
# include "../doomstat.h"
# ifdef HWRENDER
# include "hw_drv.h"
# include "hw_light.h"
# include "hw_md2.h"
2018-05-13 19:34:08 +00:00
# include "../d_main.h"
2014-03-15 16:59:03 +00:00
# include "../r_bsp.h"
# include "../r_main.h"
# include "../m_misc.h"
# include "../w_wad.h"
# include "../z_zone.h"
# include "../r_things.h"
2018-02-05 02:11:17 +00:00
# include "../r_draw.h"
# include "../p_tick.h"
2018-07-04 23:06:45 +00:00
# include "../k_kart.h" // colortranslations
2018-12-16 01:57:11 +00:00
# include "hw_model.h"
2014-03-15 16:59:03 +00:00
# include "hw_main.h"
2016-07-06 04:09:17 +00:00
# include "../v_video.h"
2014-03-15 16:59:03 +00:00
# ifdef HAVE_PNG
# ifndef _MSC_VER
# ifndef _LARGEFILE64_SOURCE
# define _LARGEFILE64_SOURCE
# endif
# endif
# ifndef _LFS64_LARGEFILE
# define _LFS64_LARGEFILE
# endif
# ifndef _FILE_OFFSET_BITS
# define _FILE_OFFSET_BITS 0
# endif
# include "png.h"
# ifndef PNG_READ_SUPPORTED
# undef HAVE_PNG
# endif
# if PNG_LIBPNG_VER < 100207
//#undef HAVE_PNG
# endif
# endif
2018-05-13 20:04:34 +00:00
# ifndef errno
# include "errno.h"
# endif
2014-03-15 16:59:03 +00:00
md2_t md2_models [ NUMSPRITES ] ;
md2_t md2_playermodels [ MAXSKINS ] ;
/*
* free model
*/
2018-12-19 00:17:33 +00:00
#if 0
2018-12-16 01:57:11 +00:00
static void md2_freeModel ( model_t * model )
2014-03-15 16:59:03 +00:00
{
2018-12-16 01:57:11 +00:00
UnloadModel ( model ) ;
2014-03-15 16:59:03 +00:00
}
2018-12-19 00:17:33 +00:00
# endif
2014-03-15 16:59:03 +00:00
//
// load model
//
// Hurdler: the current path is the Legacy.exe path
2018-12-16 01:57:11 +00:00
static model_t * md2_readModel ( const char * filename )
2014-03-15 16:59:03 +00:00
{
2018-05-13 19:19:36 +00:00
//Filename checking fixed ~Monster Iestyn and Golden
2019-01-11 03:08:37 +00:00
if ( FIL_FileExists ( va ( " %s " PATHSEP " %s " , srb2home , filename ) ) )
return LoadModel ( va ( " %s " PATHSEP " %s " , srb2home , filename ) , PU_STATIC ) ;
else if ( FIL_FileExists ( va ( " %s " PATHSEP " %s " , srb2path , filename ) ) )
return LoadModel ( va ( " %s " PATHSEP " %s " , srb2path , filename ) , PU_STATIC ) ;
return NULL ;
2014-03-15 16:59:03 +00:00
}
2018-12-16 01:57:11 +00:00
static inline void md2_printModelInfo ( model_t * model )
2014-03-15 16:59:03 +00:00
{
#if 0
INT32 i ;
CONS_Debug ( DBG_RENDER , " magic: \t \t \t %c%c%c%c \n " , model - > header . magic > > 24 ,
( model - > header . magic > > 16 ) & 0xff ,
( model - > header . magic > > 8 ) & 0xff ,
model - > header . magic & 0xff ) ;
CONS_Debug ( DBG_RENDER , " version: \t \t %d \n " , model - > header . version ) ;
CONS_Debug ( DBG_RENDER , " skinWidth: \t \t %d \n " , model - > header . skinWidth ) ;
CONS_Debug ( DBG_RENDER , " skinHeight: \t \t %d \n " , model - > header . skinHeight ) ;
CONS_Debug ( DBG_RENDER , " frameSize: \t \t %d \n " , model - > header . frameSize ) ;
CONS_Debug ( DBG_RENDER , " numSkins: \t \t %d \n " , model - > header . numSkins ) ;
CONS_Debug ( DBG_RENDER , " numVertices: \t \t %d \n " , model - > header . numVertices ) ;
CONS_Debug ( DBG_RENDER , " numTexCoords: \t \t %d \n " , model - > header . numTexCoords ) ;
CONS_Debug ( DBG_RENDER , " numTriangles: \t \t %d \n " , model - > header . numTriangles ) ;
CONS_Debug ( DBG_RENDER , " numGlCommands: \t \t %d \n " , model - > header . numGlCommands ) ;
CONS_Debug ( DBG_RENDER , " numFrames: \t \t %d \n " , model - > header . numFrames ) ;
CONS_Debug ( DBG_RENDER , " offsetSkins: \t \t %d \n " , model - > header . offsetSkins ) ;
CONS_Debug ( DBG_RENDER , " offsetTexCoords: \t %d \n " , model - > header . offsetTexCoords ) ;
CONS_Debug ( DBG_RENDER , " offsetTriangles: \t %d \n " , model - > header . offsetTriangles ) ;
CONS_Debug ( DBG_RENDER , " offsetFrames: \t \t %d \n " , model - > header . offsetFrames ) ;
CONS_Debug ( DBG_RENDER , " offsetGlCommands: \t %d \n " , model - > header . offsetGlCommands ) ;
CONS_Debug ( DBG_RENDER , " offsetEnd: \t \t %d \n " , model - > header . offsetEnd ) ;
for ( i = 0 ; i < model - > header . numFrames ; i + + )
CONS_Debug ( DBG_RENDER , " %s " , model - > frames [ i ] . name ) ;
CONS_Debug ( DBG_RENDER , " \n " ) ;
# else
( void ) model ;
# endif
}
# ifdef HAVE_PNG
static void PNG_error ( png_structp PNG , png_const_charp pngtext )
{
CONS_Debug ( DBG_RENDER , " libpng error at %p: %s " , PNG , pngtext ) ;
//I_Error("libpng error at %p: %s", PNG, pngtext);
}
static void PNG_warn ( png_structp PNG , png_const_charp pngtext )
{
CONS_Debug ( DBG_RENDER , " libpng warning at %p: %s " , PNG , pngtext ) ;
}
2019-03-21 21:23:40 +00:00
static GLTextureFormat_t PNG_Load ( const char * filename , int * w , int * h , GLPatch_t * grpatch )
2014-03-15 16:59:03 +00:00
{
png_structp png_ptr ;
png_infop png_info_ptr ;
png_uint_32 width , height ;
int bit_depth , color_type ;
# ifdef PNG_SETJMP_SUPPORTED
# ifdef USE_FAR_KEYWORD
jmp_buf jmpbuf ;
# endif
# endif
2019-01-19 02:28:31 +00:00
volatile png_FILE_p png_FILE ;
2018-05-13 19:19:36 +00:00
//Filename checking fixed ~Monster Iestyn and Golden
2019-04-12 05:35:35 +00:00
char * pngfilename = va ( " %s " PATHSEP " mdls " PATHSEP " %s " , srb2home , filename ) ;
2014-03-15 16:59:03 +00:00
FIL_ForceExtension ( pngfilename , " .png " ) ;
png_FILE = fopen ( pngfilename , " rb " ) ;
if ( ! png_FILE )
{
2019-04-12 05:35:35 +00:00
pngfilename = va ( " %s " PATHSEP " mdls " PATHSEP " %s " , srb2path , filename ) ;
2019-01-09 21:53:59 +00:00
FIL_ForceExtension ( pngfilename , " .png " ) ;
png_FILE = fopen ( pngfilename , " rb " ) ;
2014-03-15 16:59:03 +00:00
//CONS_Debug(DBG_RENDER, "M_SavePNG: Error on opening %s for loading\n", filename);
2019-01-09 21:53:59 +00:00
if ( ! png_FILE )
return 0 ;
2014-03-15 16:59:03 +00:00
}
png_ptr = png_create_read_struct ( PNG_LIBPNG_VER_STRING , NULL ,
PNG_error , PNG_warn ) ;
if ( ! png_ptr )
{
CONS_Debug ( DBG_RENDER , " PNG_Load: Error on initialize libpng \n " ) ;
fclose ( png_FILE ) ;
return 0 ;
}
png_info_ptr = png_create_info_struct ( png_ptr ) ;
if ( ! png_info_ptr )
{
CONS_Debug ( DBG_RENDER , " PNG_Load: Error on allocate for libpng \n " ) ;
png_destroy_read_struct ( & png_ptr , NULL , NULL ) ;
fclose ( png_FILE ) ;
return 0 ;
}
# ifdef USE_FAR_KEYWORD
if ( setjmp ( jmpbuf ) )
# else
if ( setjmp ( png_jmpbuf ( png_ptr ) ) )
# endif
{
//CONS_Debug(DBG_RENDER, "libpng load error on %s\n", filename);
png_destroy_read_struct ( & png_ptr , & png_info_ptr , NULL ) ;
fclose ( png_FILE ) ;
2019-11-08 00:30:29 +00:00
Z_Free ( grpatch - > mipmap - > grInfo . data ) ;
2014-03-15 16:59:03 +00:00
return 0 ;
}
# ifdef USE_FAR_KEYWORD
png_memcpy ( png_jmpbuf ( png_ptr ) , jmpbuf , sizeof jmp_buf ) ;
# endif
png_init_io ( png_ptr , png_FILE ) ;
# ifdef PNG_SET_USER_LIMITS_SUPPORTED
png_set_user_limits ( png_ptr , 2048 , 2048 ) ;
# endif
png_read_info ( png_ptr , png_info_ptr ) ;
png_get_IHDR ( png_ptr , png_info_ptr , & width , & height , & bit_depth , & color_type ,
NULL , NULL , NULL ) ;
if ( bit_depth = = 16 )
png_set_strip_16 ( png_ptr ) ;
if ( color_type = = PNG_COLOR_TYPE_GRAY | | color_type = = PNG_COLOR_TYPE_GRAY_ALPHA )
png_set_gray_to_rgb ( png_ptr ) ;
else if ( color_type = = PNG_COLOR_TYPE_PALETTE )
png_set_palette_to_rgb ( png_ptr ) ;
if ( png_get_valid ( png_ptr , png_info_ptr , PNG_INFO_tRNS ) )
png_set_tRNS_to_alpha ( png_ptr ) ;
else if ( color_type ! = PNG_COLOR_TYPE_RGB_ALPHA & & color_type ! = PNG_COLOR_TYPE_GRAY_ALPHA )
{
# if PNG_LIBPNG_VER < 10207
png_set_filler ( png_ptr , 0xFF , PNG_FILLER_AFTER ) ;
# else
png_set_add_alpha ( png_ptr , 0xFF , PNG_FILLER_AFTER ) ;
# endif
}
png_read_update_info ( png_ptr , png_info_ptr ) ;
{
png_uint_32 i , pitch = png_get_rowbytes ( png_ptr , png_info_ptr ) ;
2019-11-08 00:30:29 +00:00
png_bytep PNG_image = Z_Malloc ( pitch * height , PU_HWRCACHE , & grpatch - > mipmap - > grInfo . data ) ;
2014-03-15 16:59:03 +00:00
png_bytepp row_pointers = png_malloc ( png_ptr , height * sizeof ( png_bytep ) ) ;
for ( i = 0 ; i < height ; i + + )
row_pointers [ i ] = PNG_image + i * pitch ;
png_read_image ( png_ptr , row_pointers ) ;
png_free ( png_ptr , ( png_voidp ) row_pointers ) ;
}
png_destroy_read_struct ( & png_ptr , & png_info_ptr , NULL ) ;
fclose ( png_FILE ) ;
* w = ( int ) width ;
* h = ( int ) height ;
return GR_RGBA ;
}
# endif
typedef struct
{
UINT8 manufacturer ;
UINT8 version ;
UINT8 encoding ;
UINT8 bitsPerPixel ;
INT16 xmin ;
INT16 ymin ;
INT16 xmax ;
INT16 ymax ;
INT16 hDpi ;
INT16 vDpi ;
UINT8 colorMap [ 48 ] ;
UINT8 reserved ;
UINT8 numPlanes ;
INT16 bytesPerLine ;
INT16 paletteInfo ;
INT16 hScreenSize ;
INT16 vScreenSize ;
UINT8 filler [ 54 ] ;
} PcxHeader ;
2019-03-21 21:23:40 +00:00
static GLTextureFormat_t PCX_Load ( const char * filename , int * w , int * h ,
2014-03-15 16:59:03 +00:00
GLPatch_t * grpatch )
{
PcxHeader header ;
# define PALSIZE 768
UINT8 palette [ PALSIZE ] ;
const UINT8 * pal ;
RGBA_t * image ;
size_t pw , ph , size , ptr = 0 ;
INT32 ch , rep ;
FILE * file ;
2018-05-13 19:19:36 +00:00
//Filename checking fixed ~Monster Iestyn and Golden
2019-04-12 05:35:35 +00:00
char * pcxfilename = va ( " %s " PATHSEP " mdls " PATHSEP " %s " , srb2home , filename ) ;
2014-03-15 16:59:03 +00:00
FIL_ForceExtension ( pcxfilename , " .pcx " ) ;
file = fopen ( pcxfilename , " rb " ) ;
if ( ! file )
2019-01-09 21:53:59 +00:00
{
2019-04-12 05:35:35 +00:00
pcxfilename = va ( " %s " PATHSEP " mdls " PATHSEP " %s " , srb2path , filename ) ;
2019-01-09 21:53:59 +00:00
FIL_ForceExtension ( pcxfilename , " .pcx " ) ;
file = fopen ( pcxfilename , " rb " ) ;
if ( ! file )
return 0 ;
}
2014-03-15 16:59:03 +00:00
if ( fread ( & header , sizeof ( PcxHeader ) , 1 , file ) ! = 1 )
{
fclose ( file ) ;
return 0 ;
}
if ( header . bitsPerPixel ! = 8 )
{
fclose ( file ) ;
return 0 ;
}
fseek ( file , - PALSIZE , SEEK_END ) ;
pw = * w = header . xmax - header . xmin + 1 ;
ph = * h = header . ymax - header . ymin + 1 ;
2019-11-08 00:30:29 +00:00
image = Z_Malloc ( pw * ph * 4 , PU_HWRCACHE , & grpatch - > mipmap - > grInfo . data ) ;
2014-03-15 16:59:03 +00:00
if ( fread ( palette , sizeof ( UINT8 ) , PALSIZE , file ) ! = PALSIZE )
{
Z_Free ( image ) ;
fclose ( file ) ;
return 0 ;
}
fseek ( file , sizeof ( PcxHeader ) , SEEK_SET ) ;
size = pw * ph ;
while ( ptr < size )
{
ch = fgetc ( file ) ; //Hurdler: beurk
if ( ch > = 192 )
{
rep = ch - 192 ;
ch = fgetc ( file ) ;
}
else
{
rep = 1 ;
}
while ( rep - - )
{
pal = palette + ch * 3 ;
image [ ptr ] . s . red = * pal + + ;
image [ ptr ] . s . green = * pal + + ;
image [ ptr ] . s . blue = * pal + + ;
image [ ptr ] . s . alpha = 0xFF ;
ptr + + ;
}
}
fclose ( file ) ;
return GR_RGBA ;
}
// -----------------+
// md2_loadTexture : Download a pcx or png texture for MD2 models
// -----------------+
static void md2_loadTexture ( md2_t * model )
{
GLPatch_t * grpatch ;
const char * filename = model - > filename ;
if ( model - > grpatch )
{
grpatch = model - > grpatch ;
2019-11-08 00:30:29 +00:00
Z_Free ( grpatch - > mipmap - > grInfo . data ) ;
2014-03-15 16:59:03 +00:00
}
else
2019-11-08 02:04:53 +00:00
{
2014-03-15 16:59:03 +00:00
grpatch = Z_Calloc ( sizeof * grpatch , PU_HWRPATCHINFO ,
& ( model - > grpatch ) ) ;
2019-11-08 02:04:53 +00:00
grpatch - > mipmap = Z_Calloc ( sizeof ( GLMipmap_t ) , PU_HWRPATCHINFO , NULL ) ;
}
2014-03-15 16:59:03 +00:00
2019-11-08 00:30:29 +00:00
if ( ! grpatch - > mipmap - > downloaded & & ! grpatch - > mipmap - > grInfo . data )
2014-03-15 16:59:03 +00:00
{
int w = 0 , h = 0 ;
# ifdef HAVE_PNG
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > grInfo . format = PNG_Load ( filename , & w , & h , grpatch ) ;
if ( grpatch - > mipmap - > grInfo . format = = 0 )
2014-03-15 16:59:03 +00:00
# endif
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > grInfo . format = PCX_Load ( filename , & w , & h , grpatch ) ;
if ( grpatch - > mipmap - > grInfo . format = = 0 )
2020-04-11 13:16:31 +00:00
{
grpatch - > notfound = true ; // mark it so its not searched for again repeatedly
2014-03-15 16:59:03 +00:00
return ;
2020-04-11 13:16:31 +00:00
}
2014-03-15 16:59:03 +00:00
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > downloaded = 0 ;
grpatch - > mipmap - > flags = 0 ;
2014-03-15 16:59:03 +00:00
grpatch - > width = ( INT16 ) w ;
grpatch - > height = ( INT16 ) h ;
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > width = ( UINT16 ) w ;
grpatch - > mipmap - > height = ( UINT16 ) h ;
2014-03-15 16:59:03 +00:00
// not correct!
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > grInfo . smallLodLog2 = GR_LOD_LOG2_256 ;
grpatch - > mipmap - > grInfo . largeLodLog2 = GR_LOD_LOG2_256 ;
grpatch - > mipmap - > grInfo . aspectRatioLog2 = GR_ASPECT_LOG2_1x1 ;
2014-03-15 16:59:03 +00:00
}
2019-11-08 00:30:29 +00:00
HWD . pfnSetTexture ( grpatch - > mipmap ) ;
2014-03-15 16:59:03 +00:00
HWR_UnlockCachedPatch ( grpatch ) ;
}
2016-07-06 04:09:17 +00:00
// -----------------+
// md2_loadBlendTexture : Download a pcx or png texture for blending MD2 models
// -----------------+
static void md2_loadBlendTexture ( md2_t * model )
{
GLPatch_t * grpatch ;
char * filename = Z_Malloc ( strlen ( model - > filename ) + 7 , PU_STATIC , NULL ) ;
strcpy ( filename , model - > filename ) ;
FIL_ForceExtension ( filename , " _blend.png " ) ;
if ( model - > blendgrpatch )
{
grpatch = model - > blendgrpatch ;
2019-11-08 00:30:29 +00:00
Z_Free ( grpatch - > mipmap - > grInfo . data ) ;
2016-07-06 04:09:17 +00:00
}
else
2019-11-08 02:04:53 +00:00
{
2016-07-06 04:09:17 +00:00
grpatch = Z_Calloc ( sizeof * grpatch , PU_HWRPATCHINFO ,
& ( model - > blendgrpatch ) ) ;
2019-11-08 02:04:53 +00:00
grpatch - > mipmap = Z_Calloc ( sizeof ( GLMipmap_t ) , PU_HWRPATCHINFO , NULL ) ;
}
2016-07-06 04:09:17 +00:00
2019-11-08 00:30:29 +00:00
if ( ! grpatch - > mipmap - > downloaded & & ! grpatch - > mipmap - > grInfo . data )
2016-07-06 04:09:17 +00:00
{
int w = 0 , h = 0 ;
# ifdef HAVE_PNG
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > grInfo . format = PNG_Load ( filename , & w , & h , grpatch ) ;
if ( grpatch - > mipmap - > grInfo . format = = 0 )
2016-07-06 04:09:17 +00:00
# endif
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > grInfo . format = PCX_Load ( filename , & w , & h , grpatch ) ;
if ( grpatch - > mipmap - > grInfo . format = = 0 )
2016-07-06 04:09:17 +00:00
{
2020-04-11 13:16:31 +00:00
grpatch - > notfound = true ; // mark it so its not searched for again repeatedly
2016-07-06 04:09:17 +00:00
Z_Free ( filename ) ;
return ;
}
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > downloaded = 0 ;
grpatch - > mipmap - > flags = 0 ;
2016-07-06 04:09:17 +00:00
grpatch - > width = ( INT16 ) w ;
grpatch - > height = ( INT16 ) h ;
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > width = ( UINT16 ) w ;
grpatch - > mipmap - > height = ( UINT16 ) h ;
2016-07-06 04:09:17 +00:00
// not correct!
2019-11-08 00:30:29 +00:00
grpatch - > mipmap - > grInfo . smallLodLog2 = GR_LOD_LOG2_256 ;
grpatch - > mipmap - > grInfo . largeLodLog2 = GR_LOD_LOG2_256 ;
grpatch - > mipmap - > grInfo . aspectRatioLog2 = GR_ASPECT_LOG2_1x1 ;
2016-07-06 04:09:17 +00:00
}
2019-11-08 00:30:29 +00:00
HWD . pfnSetTexture ( grpatch - > mipmap ) ; // We do need to do this so that it can be cleared and knows to recreate it when necessary
2016-07-06 04:09:17 +00:00
HWR_UnlockCachedPatch ( grpatch ) ;
Z_Free ( filename ) ;
}
2014-04-14 05:14:58 +00:00
// Don't spam the console, or the OS with fopen requests!
static boolean nomd2s = false ;
2014-03-15 16:59:03 +00:00
void HWR_InitMD2 ( void )
{
size_t i ;
INT32 s ;
FILE * f ;
char name [ 18 ] , filename [ 32 ] ;
float scale , offset ;
CONS_Printf ( " InitMD2()... \n " ) ;
for ( s = 0 ; s < MAXSKINS ; s + + )
{
md2_playermodels [ s ] . scale = - 1.0f ;
md2_playermodels [ s ] . model = NULL ;
md2_playermodels [ s ] . grpatch = NULL ;
md2_playermodels [ s ] . skin = - 1 ;
md2_playermodels [ s ] . notfound = true ;
2016-11-03 21:06:23 +00:00
md2_playermodels [ s ] . error = false ;
2014-03-15 16:59:03 +00:00
}
for ( i = 0 ; i < NUMSPRITES ; i + + )
{
md2_models [ i ] . scale = - 1.0f ;
md2_models [ i ] . model = NULL ;
md2_models [ i ] . grpatch = NULL ;
md2_models [ i ] . skin = - 1 ;
md2_models [ i ] . notfound = true ;
2016-11-06 17:50:04 +00:00
md2_models [ i ] . error = false ;
2014-03-15 16:59:03 +00:00
}
2019-04-12 05:35:35 +00:00
// read the mdls.dat file
2018-05-13 19:19:36 +00:00
//Filename checking fixed ~Monster Iestyn and Golden
2019-04-12 05:35:35 +00:00
f = fopen ( va ( " %s " PATHSEP " %s " , srb2home , " mdls.dat " ) , " rt " ) ;
2014-04-14 05:14:58 +00:00
2014-03-15 16:59:03 +00:00
if ( ! f )
{
2019-04-12 05:35:35 +00:00
f = fopen ( va ( " %s " PATHSEP " %s " , srb2path , " mdls.dat " ) , " rt " ) ;
2019-01-09 21:35:51 +00:00
if ( ! f )
{
2019-04-12 05:35:35 +00:00
CONS_Printf ( " %s %s \n " , M_GetText ( " Error while loading mdls.dat: " ) , strerror ( errno ) ) ;
2019-01-09 21:35:51 +00:00
nomd2s = true ;
return ;
}
2014-03-15 16:59:03 +00:00
}
while ( fscanf ( f , " %19s %31s %f %f " , name , filename , & scale , & offset ) = = 4 )
{
2019-01-08 17:57:10 +00:00
/*if (stricmp(name, "PLAY") == 0)
2016-07-06 04:09:17 +00:00
{
2019-04-12 05:35:35 +00:00
CONS_Printf ( " MD2 for sprite PLAY detected in mdls.dat, use a player skin instead! \n " ) ;
2016-07-06 04:09:17 +00:00
continue ;
2019-01-08 17:57:10 +00:00
} */
// 8/1/19: Allow PLAY to load for default MD2.
2016-07-06 04:09:17 +00:00
2014-03-15 16:59:03 +00:00
for ( i = 0 ; i < NUMSPRITES ; i + + )
{
if ( stricmp ( name , sprnames [ i ] ) = = 0 )
{
2016-07-06 04:09:17 +00:00
//if (stricmp(name, "PLAY") == 0)
//continue;
2014-03-15 16:59:03 +00:00
//CONS_Debug(DBG_RENDER, " Found: %s %s %f %f\n", name, filename, scale, offset);
md2_models [ i ] . scale = scale ;
md2_models [ i ] . offset = offset ;
md2_models [ i ] . notfound = false ;
strcpy ( md2_models [ i ] . filename , filename ) ;
2016-07-06 04:09:17 +00:00
goto md2found ;
2014-03-15 16:59:03 +00:00
}
}
for ( s = 0 ; s < MAXSKINS ; s + + )
{
if ( stricmp ( name , skins [ s ] . name ) = = 0 )
{
//CONS_Printf(" Found: %s %s %f %f\n", name, filename, scale, offset);
md2_playermodels [ s ] . skin = s ;
md2_playermodels [ s ] . scale = scale ;
md2_playermodels [ s ] . offset = offset ;
md2_playermodels [ s ] . notfound = false ;
strcpy ( md2_playermodels [ s ] . filename , filename ) ;
2016-07-06 04:09:17 +00:00
goto md2found ;
2014-03-15 16:59:03 +00:00
}
}
2019-06-12 19:36:47 +00:00
// no sprite/player skin name found?!?D
2019-04-12 05:35:35 +00:00
CONS_Printf ( " Unknown sprite/player skin %s detected in mdls.dat \n " , name ) ;
2016-07-06 04:09:17 +00:00
md2found :
// move on to next line...
continue ;
2014-03-15 16:59:03 +00:00
}
fclose ( f ) ;
}
void HWR_AddPlayerMD2 ( int skin ) // For MD2's that were added after startup
{
FILE * f ;
char name [ 18 ] , filename [ 32 ] ;
float scale , offset ;
2014-04-14 05:14:58 +00:00
if ( nomd2s )
return ;
2014-03-15 16:59:03 +00:00
CONS_Printf ( " AddPlayerMD2()... \n " ) ;
2019-04-12 05:35:35 +00:00
// read the mdls.dat file
2018-05-13 19:19:36 +00:00
//Filename checking fixed ~Monster Iestyn and Golden
2019-04-12 05:35:35 +00:00
f = fopen ( va ( " %s " PATHSEP " %s " , srb2home , " mdls.dat " ) , " rt " ) ;
2014-04-14 05:14:58 +00:00
2014-03-15 16:59:03 +00:00
if ( ! f )
{
2019-04-12 05:35:35 +00:00
f = fopen ( va ( " %s " PATHSEP " %s " , srb2path , " mdls.dat " ) , " rt " ) ;
2019-01-09 21:35:51 +00:00
if ( ! f )
{
2019-04-12 05:35:35 +00:00
CONS_Printf ( " %s %s \n " , M_GetText ( " Error while loading mdls.dat: " ) , strerror ( errno ) ) ;
2019-01-09 21:35:51 +00:00
nomd2s = true ;
return ;
}
2014-03-15 16:59:03 +00:00
}
2019-03-18 21:34:20 +00:00
// Check for any MD2s that match the names of sprite names!
2014-03-15 16:59:03 +00:00
while ( fscanf ( f , " %19s %31s %f %f " , name , filename , & scale , & offset ) = = 4 )
{
if ( stricmp ( name , skins [ skin ] . name ) = = 0 )
{
md2_playermodels [ skin ] . skin = skin ;
md2_playermodels [ skin ] . scale = scale ;
md2_playermodels [ skin ] . offset = offset ;
md2_playermodels [ skin ] . notfound = false ;
strcpy ( md2_playermodels [ skin ] . filename , filename ) ;
2016-07-06 04:09:17 +00:00
goto playermd2found ;
2014-03-15 16:59:03 +00:00
}
}
2016-07-06 04:09:17 +00:00
//CONS_Printf("MD2 for player skin %s not found\n", skins[skin].name);
md2_playermodels [ skin ] . notfound = true ;
playermd2found :
2014-03-15 16:59:03 +00:00
fclose ( f ) ;
}
void HWR_AddSpriteMD2 ( size_t spritenum ) // For MD2s that were added after startup
{
FILE * f ;
2019-04-12 05:35:35 +00:00
// name[18] is used to check for names in the mdls.dat file that match with sprites or player skins
2014-03-15 16:59:03 +00:00
// sprite names are always 4 characters long, and names is for player skins can be up to 19 characters long
char name [ 18 ] , filename [ 32 ] ;
float scale , offset ;
2014-04-14 05:14:58 +00:00
if ( nomd2s )
return ;
2014-03-15 16:59:03 +00:00
2016-07-06 04:09:17 +00:00
if ( spritenum = = SPR_PLAY ) // Handled already NEWMD2: Per sprite, per-skin check
return ;
2014-04-14 05:14:58 +00:00
// Read the md2.dat file
2018-05-13 19:19:36 +00:00
//Filename checking fixed ~Monster Iestyn and Golden
2019-04-12 05:35:35 +00:00
f = fopen ( va ( " %s " PATHSEP " %s " , srb2home , " mdls.dat " ) , " rt " ) ;
2014-03-15 16:59:03 +00:00
if ( ! f )
{
2019-04-12 05:35:35 +00:00
f = fopen ( va ( " %s " PATHSEP " %s " , srb2path , " mdls.dat " ) , " rt " ) ;
2019-01-09 21:35:51 +00:00
if ( ! f )
{
2019-04-12 05:35:35 +00:00
CONS_Printf ( " %s %s \n " , M_GetText ( " Error while loading mdls.dat: " ) , strerror ( errno ) ) ;
2019-01-09 21:35:51 +00:00
nomd2s = true ;
return ;
}
2014-03-15 16:59:03 +00:00
}
2018-12-16 01:57:11 +00:00
// Check for any MD2s that match the names of sprite names!
2014-03-15 16:59:03 +00:00
while ( fscanf ( f , " %19s %31s %f %f " , name , filename , & scale , & offset ) = = 4 )
{
2016-07-06 04:09:17 +00:00
if ( stricmp ( name , sprnames [ spritenum ] ) = = 0 )
2014-03-15 16:59:03 +00:00
{
2016-07-06 04:09:17 +00:00
md2_models [ spritenum ] . scale = scale ;
md2_models [ spritenum ] . offset = offset ;
md2_models [ spritenum ] . notfound = false ;
strcpy ( md2_models [ spritenum ] . filename , filename ) ;
goto spritemd2found ;
}
}
//CONS_Printf("MD2 for sprite %s not found\n", sprnames[spritenum]);
md2_models [ spritenum ] . notfound = true ;
spritemd2found :
fclose ( f ) ;
}
2018-09-17 03:28:10 +00:00
// Define for getting accurate color brightness readings according to how the human eye sees them.
// https://en.wikipedia.org/wiki/Relative_luminance
// 0.2126 to red
// 0.7152 to green
// 0.0722 to blue
// (See this same define in k_kart.c!)
# define SETBRIGHTNESS(brightness,r,g,b) \
brightness = ( UINT8 ) ( ( ( 1063 * ( ( UINT16 ) r ) / 5000 ) + ( 3576 * ( ( UINT16 ) g ) / 5000 ) + ( 361 * ( ( UINT16 ) b ) / 5000 ) ) / 3 )
2018-11-26 00:17:34 +00:00
2018-02-05 02:11:17 +00:00
static void HWR_CreateBlendedTexture ( GLPatch_t * gpatch , GLPatch_t * blendgpatch , GLMipmap_t * grmip , INT32 skinnum , skincolors_t color )
2016-07-06 04:09:17 +00:00
{
2018-07-04 23:06:45 +00:00
UINT8 i ;
2016-07-06 04:09:17 +00:00
UINT16 w = gpatch - > width , h = gpatch - > height ;
UINT32 size = w * h ;
RGBA_t * image , * blendimage , * cur , blendcolor ;
if ( grmip - > width = = 0 )
{
grmip - > width = gpatch - > width ;
grmip - > height = gpatch - > height ;
// no wrap around, no chroma key
grmip - > flags = 0 ;
// setup the texture info
grmip - > grInfo . format = GR_RGBA ;
}
Z_Free ( grmip - > grInfo . data ) ;
grmip - > grInfo . data = NULL ;
cur = Z_Malloc ( size * 4 , PU_HWRCACHE , & grmip - > grInfo . data ) ;
memset ( cur , 0x00 , size * 4 ) ;
2019-11-08 00:30:29 +00:00
image = gpatch - > mipmap - > grInfo . data ;
blendimage = blendgpatch - > mipmap - > grInfo . data ;
2016-07-06 04:09:17 +00:00
2018-07-04 23:06:45 +00:00
// Average all of the translation's colors
2016-07-06 04:09:17 +00:00
{
2018-09-17 03:39:18 +00:00
const UINT8 div = 6 ;
const UINT8 start = 4 ;
UINT32 r , g , b ;
2018-07-04 23:06:45 +00:00
2018-09-17 03:39:18 +00:00
blendcolor = V_GetColor ( colortranslations [ color ] [ start ] ) ;
r = ( UINT32 ) ( blendcolor . s . red * blendcolor . s . red ) ;
g = ( UINT32 ) ( blendcolor . s . green * blendcolor . s . green ) ;
b = ( UINT32 ) ( blendcolor . s . blue * blendcolor . s . blue ) ;
2018-07-04 23:06:45 +00:00
2018-09-17 03:39:18 +00:00
for ( i = 1 ; i < div ; i + + )
2018-07-04 23:06:45 +00:00
{
2018-09-17 03:39:18 +00:00
RGBA_t nextcolor = V_GetColor ( colortranslations [ color ] [ start + i ] ) ;
r + = ( UINT32 ) ( nextcolor . s . red * nextcolor . s . red ) ;
g + = ( UINT32 ) ( nextcolor . s . green * nextcolor . s . green ) ;
b + = ( UINT32 ) ( nextcolor . s . blue * nextcolor . s . blue ) ;
2018-07-04 23:06:45 +00:00
}
2018-09-17 03:39:18 +00:00
blendcolor . s . red = ( UINT8 ) ( FixedSqrt ( ( r / div ) < < FRACBITS ) > > FRACBITS ) ;
blendcolor . s . green = ( UINT8 ) ( FixedSqrt ( ( g / div ) < < FRACBITS ) > > FRACBITS ) ;
blendcolor . s . blue = ( UINT8 ) ( FixedSqrt ( ( b / div ) < < FRACBITS ) > > FRACBITS ) ;
2016-07-06 04:09:17 +00:00
}
2018-06-08 04:02:28 +00:00
// rainbow support, could theoretically support boss ones too
if ( skinnum = = TC_RAINBOW )
2016-07-06 04:09:17 +00:00
{
2018-02-05 02:11:17 +00:00
while ( size - - )
2016-07-06 04:09:17 +00:00
{
2018-02-05 02:11:17 +00:00
if ( image - > s . alpha = = 0 & & blendimage - > s . alpha = = 0 )
{
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
cur - > rgba = image - > rgba ;
}
else
{
UINT32 tempcolor ;
UINT16 imagebright , blendbright , finalbright , colorbright ;
2018-09-17 03:28:10 +00:00
SETBRIGHTNESS ( imagebright , image - > s . red , image - > s . green , image - > s . blue ) ;
SETBRIGHTNESS ( blendbright , blendimage - > s . red , blendimage - > s . green , blendimage - > s . blue ) ;
2018-02-05 02:11:17 +00:00
// slightly dumb average between the blend image color and base image colour, usually one or the other will be fully opaque anyway
finalbright = ( imagebright * ( 255 - blendimage - > s . alpha ) ) / 255 + ( blendbright * blendimage - > s . alpha ) / 255 ;
2018-09-17 03:28:10 +00:00
SETBRIGHTNESS ( colorbright , blendcolor . s . red , blendcolor . s . green , blendcolor . s . blue ) ;
2018-02-05 02:11:17 +00:00
tempcolor = ( finalbright * blendcolor . s . red ) / colorbright ;
2018-07-06 23:34:03 +00:00
tempcolor = min ( 255 , tempcolor ) ;
2018-02-05 02:11:17 +00:00
cur - > s . red = ( UINT8 ) tempcolor ;
tempcolor = ( finalbright * blendcolor . s . green ) / colorbright ;
2018-07-06 23:34:03 +00:00
tempcolor = min ( 255 , tempcolor ) ;
2018-02-05 02:11:17 +00:00
cur - > s . green = ( UINT8 ) tempcolor ;
tempcolor = ( finalbright * blendcolor . s . blue ) / colorbright ;
2018-07-06 23:34:03 +00:00
tempcolor = min ( 255 , tempcolor ) ;
2018-02-05 02:11:17 +00:00
cur - > s . blue = ( UINT8 ) tempcolor ;
cur - > s . alpha = image - > s . alpha ;
}
cur + + ; image + + ; blendimage + + ;
2016-07-06 04:09:17 +00:00
}
2018-02-05 02:11:17 +00:00
}
else
{
while ( size - - )
2016-07-06 04:09:17 +00:00
{
2018-02-05 02:11:17 +00:00
if ( blendimage - > s . alpha = = 0 )
{
// Don't bother with blending the pixel if the alpha of the blend pixel is 0
cur - > rgba = image - > rgba ;
}
else
{
INT32 tempcolor ;
INT16 tempmult , tempalpha ;
tempalpha = - ( abs ( blendimage - > s . red - 127 ) - 127 ) * 2 ;
if ( tempalpha > 255 )
tempalpha = 255 ;
else if ( tempalpha < 0 )
tempalpha = 0 ;
tempmult = ( blendimage - > s . red - 127 ) * 2 ;
if ( tempmult > 255 )
tempmult = 255 ;
else if ( tempmult < 0 )
tempmult = 0 ;
tempcolor = ( image - > s . red * ( 255 - blendimage - > s . alpha ) ) / 255 + ( ( tempmult + ( ( tempalpha * blendcolor . s . red ) / 255 ) ) * blendimage - > s . alpha ) / 255 ;
cur - > s . red = ( UINT8 ) tempcolor ;
tempcolor = ( image - > s . green * ( 255 - blendimage - > s . alpha ) ) / 255 + ( ( tempmult + ( ( tempalpha * blendcolor . s . green ) / 255 ) ) * blendimage - > s . alpha ) / 255 ;
cur - > s . green = ( UINT8 ) tempcolor ;
tempcolor = ( image - > s . blue * ( 255 - blendimage - > s . alpha ) ) / 255 + ( ( tempmult + ( ( tempalpha * blendcolor . s . blue ) / 255 ) ) * blendimage - > s . alpha ) / 255 ;
cur - > s . blue = ( UINT8 ) tempcolor ;
cur - > s . alpha = image - > s . alpha ;
}
2016-07-06 04:09:17 +00:00
2018-02-05 02:11:17 +00:00
cur + + ; image + + ; blendimage + + ;
}
2016-07-06 04:09:17 +00:00
}
return ;
}
2018-09-17 03:28:10 +00:00
# undef SETBRIGHTNESS
2018-02-05 02:11:17 +00:00
static void HWR_GetBlendedTexture ( GLPatch_t * gpatch , GLPatch_t * blendgpatch , INT32 skinnum , const UINT8 * colormap , skincolors_t color )
2016-07-06 04:09:17 +00:00
{
// mostly copied from HWR_GetMappedPatch, hence the similarities and comment
GLMipmap_t * grmip , * newmip ;
if ( colormap = = colormaps | | colormap = = NULL )
{
// Don't do any blending
2019-11-08 00:30:29 +00:00
HWD . pfnSetTexture ( gpatch - > mipmap ) ;
2016-07-06 04:09:17 +00:00
return ;
}
// search for the mimmap
// skip the first (no colormap translated)
2019-11-08 00:30:29 +00:00
for ( grmip = gpatch - > mipmap ; grmip - > nextcolormap ; )
2016-07-06 04:09:17 +00:00
{
grmip = grmip - > nextcolormap ;
if ( grmip - > colormap = = colormap )
{
if ( grmip - > downloaded & & grmip - > grInfo . data )
2014-03-15 16:59:03 +00:00
{
2016-07-06 04:09:17 +00:00
HWD . pfnSetTexture ( grmip ) ; // found the colormap, set it to the correct texture
Z_ChangeTag ( grmip - > grInfo . data , PU_HWRCACHE_UNLOCKED ) ;
return ;
2014-03-15 16:59:03 +00:00
}
}
}
2016-07-06 04:09:17 +00:00
// If here, the blended texture has not been created
// So we create it
//BP: WARNING: don't free it manually without clearing the cache of harware renderer
// (it have a liste of mipmap)
// this malloc is cleared in HWR_FreeTextureCache
// (...) unfortunately z_malloc fragment alot the memory :(so malloc is better
newmip = calloc ( 1 , sizeof ( * newmip ) ) ;
if ( newmip = = NULL )
I_Error ( " %s: Out of memory " , " HWR_GetMappedPatch " ) ;
grmip - > nextcolormap = newmip ;
newmip - > colormap = colormap ;
2018-02-05 02:11:17 +00:00
HWR_CreateBlendedTexture ( gpatch , blendgpatch , newmip , skinnum , color ) ;
2016-07-06 04:09:17 +00:00
HWD . pfnSetTexture ( newmip ) ;
2017-02-17 20:03:10 +00:00
Z_ChangeTag ( newmip - > grInfo . data , PU_HWRCACHE_UNLOCKED ) ;
2014-03-15 16:59:03 +00:00
}
// -----------------+
// HWR_DrawMD2 : Draw MD2
2019-03-19 02:03:29 +00:00
// :
2014-03-15 16:59:03 +00:00
// Returns :
// -----------------+
2019-03-18 21:34:20 +00:00
2014-03-15 16:59:03 +00:00
void HWR_DrawMD2 ( gr_vissprite_t * spr )
{
2019-03-18 21:34:20 +00:00
md2_t * md2 ;
2014-03-15 16:59:03 +00:00
char filename [ 64 ] ;
2018-12-19 03:50:00 +00:00
INT32 frame = 0 ;
INT32 nextFrame = - 1 ;
FTransform p ;
2019-03-18 21:34:20 +00:00
FSurfaceInfo Surf ;
2014-03-15 16:59:03 +00:00
2019-04-12 05:35:35 +00:00
if ( ! cv_grmdls . value )
2016-07-06 04:09:17 +00:00
return ;
if ( spr - > precip )
return ;
2014-03-15 16:59:03 +00:00
// MD2 colormap fix
// colormap test
2019-01-21 22:48:57 +00:00
if ( spr - > mobj - > subsector )
2014-03-15 16:59:03 +00:00
{
sector_t * sector = spr - > mobj - > subsector - > sector ;
extracolormap_t * colormap = sector - > extra_colormap ;
2019-03-18 01:27:50 +00:00
UINT8 lightlevel = 255 ;
2014-03-15 16:59:03 +00:00
if ( sector - > numlights )
{
2014-03-19 23:10:37 +00:00
INT32 light ;
2014-03-15 16:59:03 +00:00
2014-03-19 23:10:37 +00:00
light = R_GetPlaneLight ( sector , spr - > mobj - > z + spr - > mobj - > height , false ) ; // Always use the light at the top instead of whatever I was doing before
2014-03-15 16:59:03 +00:00
2014-03-19 23:10:37 +00:00
if ( ! ( spr - > mobj - > frame & FF_FULLBRIGHT ) )
2014-03-24 16:11:25 +00:00
lightlevel = * sector - > lightlist [ light ] . lightlevel ;
2014-03-15 16:59:03 +00:00
2014-03-19 23:10:37 +00:00
if ( sector - > lightlist [ light ] . extra_colormap )
colormap = sector - > lightlist [ light ] . extra_colormap ;
2014-03-15 16:59:03 +00:00
}
else
{
if ( ! ( spr - > mobj - > frame & FF_FULLBRIGHT ) )
2014-03-24 16:11:25 +00:00
lightlevel = sector - > lightlevel ;
2014-03-15 16:59:03 +00:00
if ( sector - > extra_colormap )
colormap = sector - > extra_colormap ;
}
if ( colormap )
2019-03-18 01:27:50 +00:00
HWR_Lighting ( & Surf , lightlevel , colormap - > rgba , colormap - > fadergba ) ;
2014-03-15 16:59:03 +00:00
else
2019-04-07 02:33:34 +00:00
HWR_NoColormapLighting ( & Surf , lightlevel , GL_NORMALFOG , GL_FADEFOG ) ;
2014-03-15 16:59:03 +00:00
}
2019-01-21 22:48:57 +00:00
else
{
2019-06-12 19:36:47 +00:00
Surf . PolyColor . rgba = 0xFFFFFFFF ;
2019-01-21 22:48:57 +00:00
}
2014-03-15 16:59:03 +00:00
2016-07-06 04:09:17 +00:00
// Look at HWR_ProjectSprite for more
2014-03-15 16:59:03 +00:00
{
GLPatch_t * gpatch ;
2018-12-19 03:50:00 +00:00
INT32 durs = spr - > mobj - > state - > tics ;
INT32 tics = spr - > mobj - > tics ;
2018-12-19 05:38:00 +00:00
//mdlframe_t *next = NULL;
2018-12-19 03:50:00 +00:00
const UINT8 flip = ( UINT8 ) ( ( spr - > mobj - > eflags & MFE_VERTICALFLIP ) = = MFE_VERTICALFLIP ) ;
spritedef_t * sprdef ;
spriteframe_t * sprframe ;
float finalscale ;
// Apparently people don't like jump frames like that, so back it goes
//if (tics > durs)
//durs = tics;
2014-04-07 11:37:15 +00:00
2014-03-15 16:59:03 +00:00
if ( spr - > mobj - > flags2 & MF2_SHADOW )
2019-03-18 01:27:50 +00:00
Surf . PolyColor . s . alpha = 0x40 ;
2014-03-15 16:59:03 +00:00
else if ( spr - > mobj - > frame & FF_TRANSMASK )
2014-03-21 18:03:40 +00:00
HWR_TranstableToAlpha ( ( spr - > mobj - > frame & FF_TRANSMASK ) > > FF_TRANSSHIFT , & Surf ) ;
2014-03-15 16:59:03 +00:00
else
2019-03-18 01:27:50 +00:00
Surf . PolyColor . s . alpha = 0xFF ;
2014-03-15 16:59:03 +00:00
// dont forget to enabled the depth test because we can't do this like
// before: polygons models are not sorted
// 1. load model+texture if not already loaded
// 2. draw model with correct position, rotation,...
2019-01-08 17:57:10 +00:00
if ( spr - > mobj - > skin & & spr - > mobj - > sprite = = SPR_PLAY & & ! md2_playermodels [ ( skin_t * ) spr - > mobj - > skin - skins ] . notfound ) // Use the player MD2 list if the mobj has a skin and is using the player sprites
2014-03-15 16:59:03 +00:00
{
md2 = & md2_playermodels [ ( skin_t * ) spr - > mobj - > skin - skins ] ;
md2 - > skin = ( skin_t * ) spr - > mobj - > skin - skins ;
}
2019-01-08 17:57:10 +00:00
else // if we can't find the player md2, use SPR_PLAY's MD2.
2014-03-15 16:59:03 +00:00
md2 = & md2_models [ spr - > mobj - > sprite ] ;
2016-11-03 21:06:23 +00:00
if ( md2 - > error )
return ; // we already failed loading this before :(
2014-03-15 16:59:03 +00:00
if ( ! md2 - > model )
{
2019-04-12 05:35:35 +00:00
CONS_Debug ( DBG_RENDER , " Loading model... (%s, %s) " , sprnames [ spr - > mobj - > sprite ] , md2 - > filename ) ;
sprintf ( filename , " mdls/%s " , md2 - > filename ) ;
2014-03-15 16:59:03 +00:00
md2 - > model = md2_readModel ( filename ) ;
if ( md2 - > model )
{
md2_printModelInfo ( md2 - > model ) ;
2018-12-26 15:58:37 +00:00
HWD . pfnCreateModelVBOs ( md2 - > model ) ;
2014-03-15 16:59:03 +00:00
}
else
{
//CONS_Debug(DBG_RENDER, " FAILED\n");
2016-11-03 21:06:23 +00:00
md2 - > error = true ; // prevent endless fail
2014-03-15 16:59:03 +00:00
return ;
}
}
2018-12-19 03:50:00 +00:00
finalscale = md2 - > scale ;
2014-03-15 16:59:03 +00:00
//Hurdler: arf, I don't like that implementation at all... too much crappy
gpatch = md2 - > grpatch ;
2019-11-08 00:30:29 +00:00
if ( ! gpatch | | ( ( ! gpatch - > mipmap - > grInfo . format | | ! gpatch - > mipmap - > downloaded ) & & ! gpatch - > notfound ) )
2014-03-15 16:59:03 +00:00
md2_loadTexture ( md2 ) ;
2014-03-30 16:45:58 +00:00
gpatch = md2 - > grpatch ; // Load it again, because it isn't being loaded into gpatch after md2_loadtexture...
2019-11-08 00:30:29 +00:00
if ( ( gpatch & & gpatch - > mipmap - > grInfo . format ) // don't load the blend texture if the base texture isn't available
2020-04-11 13:16:31 +00:00
& & ( ! md2 - > blendgrpatch
2019-11-08 00:30:29 +00:00
| | ( ( ! ( ( GLPatch_t * ) md2 - > blendgrpatch ) - > mipmap - > grInfo . format | | ! ( ( GLPatch_t * ) md2 - > blendgrpatch ) - > mipmap - > downloaded )
2020-04-11 13:16:31 +00:00
& & ! ( ( GLPatch_t * ) md2 - > blendgrpatch ) - > notfound ) ) )
2016-07-06 04:09:17 +00:00
md2_loadBlendTexture ( md2 ) ;
2019-11-08 00:30:29 +00:00
if ( gpatch & & gpatch - > mipmap - > grInfo . format ) // else if meant that if a texture couldn't be loaded, it would just end up using something else's texture
2014-03-15 16:59:03 +00:00
{
2016-07-06 04:09:17 +00:00
if ( ( skincolors_t ) spr - > mobj - > color ! = SKINCOLOR_NONE & &
2019-11-08 00:30:29 +00:00
md2 - > blendgrpatch & & ( ( GLPatch_t * ) md2 - > blendgrpatch ) - > mipmap - > grInfo . format
2016-07-06 04:09:17 +00:00
& & gpatch - > width = = ( ( GLPatch_t * ) md2 - > blendgrpatch ) - > width & & gpatch - > height = = ( ( GLPatch_t * ) md2 - > blendgrpatch ) - > height )
{
2019-01-03 00:11:51 +00:00
INT32 skinnum = TC_DEFAULT ;
2018-02-05 02:11:17 +00:00
if ( ( spr - > mobj - > flags & MF_BOSS ) & & ( spr - > mobj - > flags2 & MF2_FRET ) & & ( leveltime & 1 ) ) // Bosses "flash"
{
if ( spr - > mobj - > type = = MT_CYBRAKDEMON )
skinnum = TC_ALLWHITE ;
else if ( spr - > mobj - > type = = MT_METALSONIC_BATTLE )
skinnum = TC_METALSONIC ;
else
skinnum = TC_BOSS ;
}
else if ( spr - > mobj - > color )
{
if ( spr - > mobj - > skin & & spr - > mobj - > sprite = = SPR_PLAY )
{
if ( spr - > mobj - > colorized )
2018-06-08 04:02:28 +00:00
skinnum = TC_RAINBOW ;
2018-02-05 02:11:17 +00:00
else
{
skinnum = ( INT32 ) ( ( skin_t * ) spr - > mobj - > skin - skins ) ;
}
}
else skinnum = TC_DEFAULT ;
}
HWR_GetBlendedTexture ( gpatch , ( GLPatch_t * ) md2 - > blendgrpatch , skinnum , spr - > colormap , ( skincolors_t ) spr - > mobj - > color ) ;
2016-07-06 04:09:17 +00:00
}
else
{
// This is safe, since we know the texture has been downloaded
2019-11-08 00:30:29 +00:00
HWD . pfnSetTexture ( gpatch - > mipmap ) ;
2016-07-06 04:09:17 +00:00
}
2014-03-15 16:59:03 +00:00
}
else
{
// Sprite
gpatch = W_CachePatchNum ( spr - > patchlumpnum , PU_CACHE ) ;
HWR_GetMappedPatch ( gpatch , spr - > colormap ) ;
}
2018-12-19 03:50:00 +00:00
if ( spr - > mobj - > frame & FF_ANIMATE )
{
// set duration and tics to be the correct values for FF_ANIMATE states
durs = spr - > mobj - > state - > var2 ;
tics = spr - > mobj - > anim_duration ;
}
//FIXME: this is not yet correct
frame = ( spr - > mobj - > frame & FF_FRAMEMASK ) % md2 - > model - > meshes [ 0 ] . numFrames ;
2018-12-19 04:44:38 +00:00
2018-12-19 15:33:13 +00:00
# ifdef USE_MODEL_NEXTFRAME
2019-04-12 05:35:35 +00:00
if ( cv_grmdls . value = = 1 & & tics < = durs )
2018-12-19 03:50:00 +00:00
{
// frames are handled differently for states with FF_ANIMATE, so get the next frame differently for the interpolation
if ( spr - > mobj - > frame & FF_ANIMATE )
{
2018-12-19 05:38:00 +00:00
nextFrame = ( spr - > mobj - > frame & FF_FRAMEMASK ) + 1 ;
if ( nextFrame > = spr - > mobj - > state - > var1 )
nextFrame = ( spr - > mobj - > state - > frame & FF_FRAMEMASK ) ;
nextFrame % = md2 - > model - > meshes [ 0 ] . numFrames ;
//next = &md2->model->meshes[0].frames[nextFrame];
2018-12-19 03:50:00 +00:00
}
else
{
2018-12-19 04:44:38 +00:00
if ( spr - > mobj - > state - > nextstate ! = S_NULL & & states [ spr - > mobj - > state - > nextstate ] . sprite ! = SPR_NULL
& & ! ( spr - > mobj - > player & & ( spr - > mobj - > state - > nextstate = = S_PLAY_TAP1 | | spr - > mobj - > state - > nextstate = = S_PLAY_TAP2 ) & & spr - > mobj - > state = = & states [ S_PLAY_STND ] ) )
2018-12-19 03:50:00 +00:00
{
2018-12-19 05:38:00 +00:00
nextFrame = ( states [ spr - > mobj - > state - > nextstate ] . frame & FF_FRAMEMASK ) % md2 - > model - > meshes [ 0 ] . numFrames ;
//next = &md2->model->meshes[0].frames[nextFrame];
2018-12-19 03:50:00 +00:00
}
}
}
2018-12-19 15:33:13 +00:00
# endif
2018-12-19 03:50:00 +00:00
//Hurdler: it seems there is still a small problem with mobj angle
p . x = FIXED_TO_FLOAT ( spr - > mobj - > x ) ;
p . y = FIXED_TO_FLOAT ( spr - > mobj - > y ) + md2 - > offset ;
if ( spr - > mobj - > eflags & MFE_VERTICALFLIP )
p . z = FIXED_TO_FLOAT ( spr - > mobj - > z + spr - > mobj - > height ) ;
else
p . z = FIXED_TO_FLOAT ( spr - > mobj - > z ) ;
if ( spr - > mobj - > skin & & spr - > mobj - > sprite = = SPR_PLAY )
sprdef = & ( ( skin_t * ) spr - > mobj - > skin ) - > spritedef ;
else
sprdef = & sprites [ spr - > mobj - > sprite ] ;
sprframe = & sprdef - > spriteframes [ spr - > mobj - > frame & FF_FRAMEMASK ] ;
if ( sprframe - > rotate )
{
2019-01-08 16:30:04 +00:00
fixed_t anglef ;
2019-01-08 16:22:33 +00:00
if ( spr - > mobj - > player )
anglef = AngleFixed ( spr - > mobj - > player - > frameangle ) ;
else
anglef = AngleFixed ( spr - > mobj - > angle ) ;
2018-12-19 03:50:00 +00:00
p . angley = FIXED_TO_FLOAT ( anglef ) ;
}
else
{
const fixed_t anglef = AngleFixed ( ( R_PointToAngle ( spr - > mobj - > x , spr - > mobj - > y ) ) - ANGLE_180 ) ;
p . angley = FIXED_TO_FLOAT ( anglef ) ;
}
p . anglex = 0.0f ;
2018-12-19 05:17:51 +00:00
# ifdef USE_FTRANSFORM_ANGLEZ
// Slope rotation from Kart
2018-12-19 03:50:00 +00:00
p . anglez = 0.0f ;
if ( spr - > mobj - > standingslope )
{
fixed_t tempz = spr - > mobj - > standingslope - > normal . z ;
fixed_t tempy = spr - > mobj - > standingslope - > normal . y ;
fixed_t tempx = spr - > mobj - > standingslope - > normal . x ;
fixed_t tempangle = AngleFixed ( R_PointToAngle2 ( 0 , 0 , FixedSqrt ( FixedMul ( tempy , tempy ) + FixedMul ( tempz , tempz ) ) , tempx ) ) ;
p . anglez = FIXED_TO_FLOAT ( tempangle ) ;
tempangle = - AngleFixed ( R_PointToAngle2 ( 0 , 0 , tempz , tempy ) ) ;
p . anglex = FIXED_TO_FLOAT ( tempangle ) ;
}
2018-12-19 05:17:51 +00:00
# endif
2018-12-19 03:50:00 +00:00
// SRB2CBTODO: MD2 scaling support
finalscale * = FIXED_TO_FLOAT ( spr - > mobj - > scale ) ;
p . flip = atransform . flip ;
2018-12-19 05:17:51 +00:00
# ifdef USE_FTRANSFORM_MIRROR
p . mirror = atransform . mirror ; // from Kart
# endif
2018-12-19 03:50:00 +00:00
2019-04-07 03:09:53 +00:00
HWD . pfnSetShader ( 4 ) ; // model shader
2019-03-18 21:34:20 +00:00
HWD . pfnDrawModel ( md2 - > model , frame , durs , tics , nextFrame , & p , finalscale , flip , & Surf ) ;
2014-03-15 16:59:03 +00:00
}
}
# endif //HWRENDER